From cda6f9fd324035b14322cb2102b0b8a9973f2b98 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Mon, 9 Feb 2009 17:18:53 +0000 Subject: [PATCH] initial import - uclibc 0.9.30 --- COPYING.LIB | 504 + COPYING.LIB.boilerplate | 1 + Changelog | 791 + DEDICATION.mjn3 | 22 + INSTALL | 80 + MAINTAINERS | 150 + Makefile | 14 + Makefile.help | 45 + Makefile.in | 510 + Makerules | 428 + README | 73 + Rules.mak | 647 + TODO | 179 + docs/Glibc_vs_uClibc_Differences.txt | 215 + docs/PORTING | 138 + docs/man/ldconfig.8 | 73 + docs/man/ldd.1 | 17 + docs/threads.txt | 56 + docs/uClibc_vs_SuSv3.txt | 105 + extra/Configs/Config.alpha | 19 + extra/Configs/Config.arm | 136 + extra/Configs/Config.avr32 | 31 + extra/Configs/Config.bfin | 18 + extra/Configs/Config.cris | 37 + extra/Configs/Config.e1 | 23 + extra/Configs/Config.frv | 18 + extra/Configs/Config.h8300 | 31 + extra/Configs/Config.hppa | 20 + extra/Configs/Config.i386 | 102 + extra/Configs/Config.i960 | 19 + extra/Configs/Config.ia64 | 18 + extra/Configs/Config.in | 2070 +++ extra/Configs/Config.in.arch | 209 + extra/Configs/Config.m68k | 13 + extra/Configs/Config.microblaze | 21 + extra/Configs/Config.mips | 77 + extra/Configs/Config.nios | 23 + extra/Configs/Config.nios2 | 22 + extra/Configs/Config.powerpc | 38 + extra/Configs/Config.sh | 55 + extra/Configs/Config.sh64 | 35 + extra/Configs/Config.sparc | 41 + extra/Configs/Config.v850 | 22 + extra/Configs/Config.vax | 24 + extra/Configs/Config.x86_64 | 17 + extra/Configs/Config.xtensa | 12 + extra/Configs/defconfigs/alpha | 1 + extra/Configs/defconfigs/arm | 1 + extra/Configs/defconfigs/avr32 | 1 + extra/Configs/defconfigs/bfin | 1 + extra/Configs/defconfigs/cris | 1 + extra/Configs/defconfigs/e1 | 1 + extra/Configs/defconfigs/frv | 1 + extra/Configs/defconfigs/h8300 | 1 + extra/Configs/defconfigs/hppa | 1 + extra/Configs/defconfigs/i386 | 1 + extra/Configs/defconfigs/i960 | 1 + extra/Configs/defconfigs/ia64 | 1 + extra/Configs/defconfigs/m68k | 1 + extra/Configs/defconfigs/microblaze | 1 + extra/Configs/defconfigs/mips | 1 + extra/Configs/defconfigs/nios | 1 + extra/Configs/defconfigs/nios2 | 1 + extra/Configs/defconfigs/powerpc | 1 + extra/Configs/defconfigs/sh | 1 + extra/Configs/defconfigs/sh64 | 1 + extra/Configs/defconfigs/sparc | 1 + extra/Configs/defconfigs/v850 | 1 + extra/Configs/defconfigs/vax | 1 + extra/Configs/defconfigs/x86_64 | 1 + extra/Makefile | 13 + extra/Makefile.in | 9 + extra/config/.gitignore | 19 + extra/config/Makefile | 45 + extra/config/Makefile.kconfig | 285 + extra/config/POTFILES.in | 12 + extra/config/README.uClibc | 19 + extra/config/check.sh | 14 + extra/config/conf.c | 602 + extra/config/confdata.c | 882 ++ extra/config/expr.c | 1106 ++ extra/config/expr.h | 202 + extra/config/gconf.c | 1632 ++ extra/config/gconf.glade | 648 + extra/config/images.c | 326 + extra/config/kconfig-language.txt | 379 + extra/config/kconfig-to-uclibc.patch.gz | Bin 0 -> 5816 bytes extra/config/kconfig_load.c | 35 + extra/config/kxgettext.c | 229 + extra/config/lex.zconf.c_shipped | 2413 +++ extra/config/lkc.h | 168 + extra/config/lkc_proto.h | 45 + extra/config/lxdialog/.gitignore | 4 + extra/config/lxdialog/BIG.FAT.WARNING | 4 + extra/config/lxdialog/check-lxdialog.sh | 82 + extra/config/lxdialog/checklist.c | 325 + extra/config/lxdialog/dialog.h | 230 + extra/config/lxdialog/inputbox.c | 238 + extra/config/lxdialog/menubox.c | 434 + extra/config/lxdialog/textbox.c | 391 + extra/config/lxdialog/util.c | 655 + extra/config/lxdialog/yesno.c | 114 + extra/config/mconf.c | 930 ++ extra/config/menu.c | 453 + extra/config/qconf.cc | 1759 +++ extra/config/qconf.h | 334 + extra/config/symbol.c | 973 ++ extra/config/util.c | 133 + extra/config/zconf.gperf | 44 + extra/config/zconf.hash.c_shipped | 237 + extra/config/zconf.l | 356 + extra/config/zconf.tab.c_shipped | 2490 +++ extra/config/zconf.y | 706 + extra/libstrip/libstrip | 72 + extra/locale/LOCALES | 346 + extra/locale/Makefile | 13 + extra/locale/Makefile.in | 217 + extra/locale/README | 71 + extra/locale/charmaps/ARMSCII-8.pairs | 254 + extra/locale/charmaps/ASCII.pairs | 128 + extra/locale/charmaps/CP1251.pairs | 255 + extra/locale/charmaps/CP1255.pairs | 233 + extra/locale/charmaps/GEORGIAN-PS.pairs | 256 + extra/locale/charmaps/ISO-8859-1.pairs | 256 + extra/locale/charmaps/ISO-8859-10.pairs | 256 + extra/locale/charmaps/ISO-8859-13.pairs | 256 + extra/locale/charmaps/ISO-8859-14.pairs | 256 + extra/locale/charmaps/ISO-8859-15.pairs | 256 + extra/locale/charmaps/ISO-8859-16.pairs | 256 + extra/locale/charmaps/ISO-8859-2.pairs | 256 + extra/locale/charmaps/ISO-8859-3.pairs | 249 + extra/locale/charmaps/ISO-8859-4.pairs | 256 + extra/locale/charmaps/ISO-8859-5.pairs | 256 + extra/locale/charmaps/ISO-8859-6.pairs | 211 + extra/locale/charmaps/ISO-8859-7.pairs | 250 + extra/locale/charmaps/ISO-8859-8.pairs | 220 + extra/locale/charmaps/ISO-8859-9.pairs | 256 + extra/locale/charmaps/KOI8-R.pairs | 256 + extra/locale/charmaps/KOI8-T.pairs | 237 + extra/locale/charmaps/KOI8-U.pairs | 256 + extra/locale/charmaps/TIS-620.pairs | 215 + extra/locale/collation/af_ZA | 1 + extra/locale/collation/am_ET | 26 + extra/locale/collation/ar_AE | 4 + extra/locale/collation/ar_BH | 4 + extra/locale/collation/ar_DZ | 4 + extra/locale/collation/ar_EG | 4 + extra/locale/collation/ar_IN | 3 + extra/locale/collation/ar_IQ | 4 + extra/locale/collation/ar_JO | 4 + extra/locale/collation/ar_KW | 4 + extra/locale/collation/ar_LB | 4 + extra/locale/collation/ar_LY | 4 + extra/locale/collation/ar_MA | 4 + extra/locale/collation/ar_OM | 4 + extra/locale/collation/ar_QA | 4 + extra/locale/collation/ar_SA | 220 + extra/locale/collation/ar_SD | 4 + extra/locale/collation/ar_SY | 4 + extra/locale/collation/ar_TN | 4 + extra/locale/collation/ar_YE | 4 + extra/locale/collation/az_AZ | 137 + extra/locale/collation/be_BY | 15 + extra/locale/collation/bg_BG | 106 + extra/locale/collation/bn_BD | 2 + extra/locale/collation/bn_IN | 4 + extra/locale/collation/br_FR | 40 + extra/locale/collation/bs_BA | 91 + extra/locale/collation/ca_ES | 2061 +++ extra/locale/collation/comm | 1872 +++ extra/locale/collation/cs_CZ | 2162 +++ extra/locale/collation/cy_GB | 136 + extra/locale/collation/da_DK | 2075 +++ extra/locale/collation/de_AT | 2 + extra/locale/collation/de_BE | 1 + extra/locale/collation/de_CH | 1 + extra/locale/collation/de_DE | 4 + extra/locale/collation/de_LU | 1 + extra/locale/collation/el_GR | 1 + extra/locale/collation/en_AU | 1 + extra/locale/collation/en_BW | 1 + extra/locale/collation/en_CA | 2061 +++ extra/locale/collation/en_DK | 1 + extra/locale/collation/en_GB | 2 + extra/locale/collation/en_HK | 1 + extra/locale/collation/en_IE | 1 + extra/locale/collation/en_IN | 4 + extra/locale/collation/en_NZ | 1 + extra/locale/collation/en_PH | 4 + extra/locale/collation/en_SG | 4 + extra/locale/collation/en_US | 4 + extra/locale/collation/en_ZA | 1 + extra/locale/collation/en_ZW | 1 + extra/locale/collation/eo_EO | 49 + extra/locale/collation/es_AR | 1 + extra/locale/collation/es_BO | 1 + extra/locale/collation/es_CL | 1 + extra/locale/collation/es_CO | 1 + extra/locale/collation/es_CR | 1 + extra/locale/collation/es_DO | 1 + extra/locale/collation/es_EC | 1 + extra/locale/collation/es_ES | 2061 +++ extra/locale/collation/es_GT | 1 + extra/locale/collation/es_HN | 1 + extra/locale/collation/es_MX | 1 + extra/locale/collation/es_NI | 1 + extra/locale/collation/es_PA | 1 + extra/locale/collation/es_PE | 1 + extra/locale/collation/es_PR | 1 + extra/locale/collation/es_PY | 1 + extra/locale/collation/es_SV | 1 + extra/locale/collation/es_US | 2077 +++ extra/locale/collation/es_UY | 1 + extra/locale/collation/es_VE | 1 + extra/locale/collation/et_EE | 2061 +++ extra/locale/collation/eu_ES | 1 + extra/locale/collation/fa_IR | 185 + extra/locale/collation/fi_FI | 2062 +++ extra/locale/collation/fo_FO | 1 + extra/locale/collation/fr_BE | 1 + extra/locale/collation/fr_CA | 1 + extra/locale/collation/fr_CH | 1 + extra/locale/collation/fr_FR | 2 + extra/locale/collation/fr_LU | 1 + extra/locale/collation/ga_IE | 1 + extra/locale/collation/gd_GB | 1 + extra/locale/collation/gl_ES | 1 + extra/locale/collation/gv_GB | 1 + extra/locale/collation/he_IL | 1 + extra/locale/collation/hi_IN | 4 + extra/locale/collation/hr_HR | 2085 +++ extra/locale/collation/hu_HU | 357 + extra/locale/collation/hy_AM | 91 + extra/locale/collation/id_ID | 1 + extra/locale/collation/is_IS | 2104 +++ extra/locale/collation/iso14651_t1 | 1495 ++ extra/locale/collation/it_CH | 1 + extra/locale/collation/it_IT | 1 + extra/locale/collation/iw_IL | 1 + extra/locale/collation/ja_JP | 13188 ++++++++++++++++ extra/locale/collation/ka_GE | 1 + extra/locale/collation/kl_GL | 1 + extra/locale/collation/ko_KR | 6010 +++++++ extra/locale/collation/kw_GB | 1 + extra/locale/collation/lt_LT | 2061 +++ extra/locale/collation/lv_LV | 2061 +++ extra/locale/collation/mi_NZ | 44 + extra/locale/collation/mk_MK | 1 + extra/locale/collation/mr_IN | 4 + extra/locale/collation/ms_MY | 4 + extra/locale/collation/mt_MT | 80 + extra/locale/collation/nl_BE | 1 + extra/locale/collation/nl_NL | 1 + extra/locale/collation/nn_NO | 4 + extra/locale/collation/no_NO | 2070 +++ extra/locale/collation/oc_FR | 1 + extra/locale/collation/pl_PL | 2061 +++ extra/locale/collation/pt_BR | 1 + extra/locale/collation/pt_PT | 1 + extra/locale/collation/ro_RO | 54 + extra/locale/collation/ru_RU | 15 + extra/locale/collation/ru_UA | 15 + extra/locale/collation/se_NO | 149 + extra/locale/collation/sk_SK | 1 + extra/locale/collation/sl_SI | 2061 +++ extra/locale/collation/sq_AL | 4 + extra/locale/collation/sr_YU | 90 + extra/locale/collation/sv_FI | 1 + extra/locale/collation/sv_SE | 51 + extra/locale/collation/ta_IN | 4 + extra/locale/collation/te_IN | 4 + extra/locale/collation/tg_TJ | 63 + extra/locale/collation/th_TH | 746 + extra/locale/collation/ti_ER | 1 + extra/locale/collation/ti_ET | 1 + extra/locale/collation/tl_PH | 30 + extra/locale/collation/tr_TR | 2061 +++ extra/locale/collation/tt_RU | 162 + extra/locale/collation/uk_UA | 15 + extra/locale/collation/ur_PK | 1 + extra/locale/collation/uz_UZ | 28 + extra/locale/collation/vi_VN | 4 + extra/locale/collation/wa_BE | 1 + extra/locale/collation/yi_US | 43 + extra/locale/collation/zh_CN | 1 + extra/locale/collation/zh_HK | 4 + extra/locale/collation/zh_SG | 4 + extra/locale/collation/zh_TW | 1 + extra/locale/gen_collate.c | 3997 +++++ extra/locale/gen_ldc.c | 298 + extra/locale/gen_locale.c | 1337 ++ extra/locale/gen_mmap.c | 237 + extra/locale/gen_wc8bit.c | 715 + extra/locale/gen_wctype.c | 892 ++ extra/locale/lmmtolso.c | 72 + extra/locale/locale_mmap.h | 93 + extra/locale/programs/categories.def | 357 + extra/locale/programs/locale.c | 462 + extra/locale/tst_nl_langinfo.c | 296 + extra/scripts/Makefile.arch.lvl3 | 13 + extra/scripts/Makefile.arch.lvl4 | 13 + extra/scripts/Makefile.libs.lvl0 | 13 + extra/scripts/Makefile.libs.lvl1 | 13 + extra/scripts/Makefile.libs.lvl2 | 13 + extra/scripts/Makefile.objs.lvl2 | 13 + extra/scripts/Makefile.objs.lvl3 | 13 + extra/scripts/Makefile.objs.lvl4 | 13 + extra/scripts/Makefile.utils.lvl1 | 13 + extra/scripts/conf-header.sh | 27 + extra/scripts/create_makefiles.sh | 71 + extra/scripts/defs.awk | 27 + extra/scripts/format.lds | 3 + extra/scripts/gen_bits_syscall_h.sh | 46 + extra/scripts/getent | 43 + extra/scripts/install_headers.sh | 58 + extra/scripts/install_kernel_headers.sh | 74 + extra/scripts/randconfig.sh | 34 + extra/scripts/relative_path.sh | 44 + extra/scripts/relinfo.pl | 78 + extra/scripts/unifdef.c | 1005 ++ include/_lfs_64.h | 29 + include/a.out.h | 5 + include/alloca.h | 43 + include/ar.h | 48 + include/arpa/ftp.h | 105 + include/arpa/inet.h | 108 + include/arpa/nameser.h | 557 + include/arpa/nameser_compat.h | 183 + include/arpa/telnet.h | 316 + include/arpa/tftp.h | 76 + include/assert.h | 78 + include/atomic.h | 261 + include/byteswap.h | 40 + include/complex.h | 107 + include/cpio.h | 74 + include/crypt.h | 42 + include/ctype.h | 383 + include/dirent.h | 293 + include/dlfcn.h | 201 + include/elf.h | 3040 ++++ include/endian.h | 58 + include/err.h | 58 + include/errno.h | 77 + include/error.h | 52 + include/fcntl.h | 228 + include/features.h | 425 + include/fenv.h | 136 + include/fnmatch.h | 72 + include/ftw.h | 178 + include/getopt.h | 4 + include/glob.h | 208 + include/gnu-versions.h | 53 + include/grp.h | 210 + include/iconv.h | 60 + include/ieee754.h | 199 + include/ifaddrs.h | 74 + include/inttypes.h | 328 + include/langinfo.h | 623 + include/lastlog.h | 4 + include/libc-internal.h | 100 + include/libc-symbols.h | 726 + include/libgen.h | 40 + include/libintl.h | 133 + include/limits.h | 153 + include/link.h | 240 + include/locale.h | 227 + include/malloc.h | 198 + include/math.h | 468 + include/memory.h | 34 + include/mntent.h | 98 + include/mqueue.h | 94 + include/net/ethernet.h | 76 + include/net/if.h | 205 + include/net/if_arp.h | 176 + include/net/if_packet.h | 37 + include/net/if_ppp.h | 169 + include/net/if_shaper.h | 59 + include/net/if_slip.h | 25 + include/net/ppp-comp.h | 1 + include/net/ppp_defs.h | 10 + include/net/route.h | 145 + include/netax25/ax25.h | 171 + include/netdb.h | 663 + include/neteconet/ec.h | 52 + include/netinet/ether.h | 57 + include/netinet/icmp6.h | 346 + include/netinet/if_ether.h | 105 + include/netinet/if_fddi.h | 37 + include/netinet/if_tr.h | 111 + include/netinet/igmp.h | 126 + include/netinet/in.h | 556 + include/netinet/in_systm.h | 41 + include/netinet/ip.h | 249 + include/netinet/ip6.h | 189 + include/netinet/ip_icmp.h | 283 + include/netinet/protocols.h | 62 + include/netinet/tcp.h | 246 + include/netinet/udp.h | 79 + include/netipx/ipx.h | 113 + include/netpacket/packet.h | 64 + include/nl_types.h | 59 + include/obstack.h | 509 + include/paths.h | 80 + include/poll.h | 1 + include/printf.h | 237 + include/protocols/routed.h | 101 + include/protocols/rwhod.h | 67 + include/protocols/talkd.h | 113 + include/protocols/timed.h | 97 + include/pty.h | 44 + include/pwd.h | 186 + include/regex.h | 565 + include/regexp.h | 222 + include/resolv.h | 395 + include/rpc/auth.h | 224 + include/rpc/auth_des.h | 112 + include/rpc/auth_unix.h | 90 + include/rpc/clnt.h | 421 + include/rpc/des_crypt.h | 97 + include/rpc/key_prot.h | 346 + include/rpc/netdb.h | 74 + include/rpc/pmap_clnt.h | 98 + include/rpc/pmap_prot.h | 108 + include/rpc/pmap_rmt.h | 68 + include/rpc/rpc.h | 113 + include/rpc/rpc_des.h | 72 + include/rpc/rpc_msg.h | 202 + include/rpc/svc.h | 316 + include/rpc/svc_auth.h | 54 + include/rpc/types.h | 108 + include/rpc/xdr.h | 385 + include/sched.h | 86 + include/scsi/scsi.h | 226 + include/scsi/scsi_ioctl.h | 34 + include/scsi/sg.h | 275 + include/search.h | 175 + include/setjmp.h | 104 + include/sgtty.h | 41 + include/shadow.h | 149 + include/signal.h | 402 + include/stdint.h | 332 + include/stdio.h | 877 + include/stdio_ext.h | 87 + include/stdlib.h | 872 + include/string.h | 485 + include/strings.h | 101 + include/sys/bitypes.h | 3 + include/sys/cdefs.h | 358 + include/sys/dir.h | 28 + include/sys/errno.h | 1 + include/sys/fcntl.h | 1 + include/sys/file.h | 56 + include/sys/fsuid.h | 36 + include/sys/ioctl.h | 46 + include/sys/ipc.h | 58 + include/sys/kd.h | 35 + include/sys/kdaemon.h | 33 + include/sys/klog.h | 34 + include/sys/mman.h | 175 + include/sys/mount.h | 119 + include/sys/msg.h | 81 + include/sys/mtio.h | 277 + include/sys/param.h | 72 + include/sys/personality.h | 73 + include/sys/poll.h | 76 + include/sys/queue.h | 618 + include/sys/quota.h | 158 + include/sys/reboot.h | 49 + include/sys/resource.h | 103 + include/sys/select.h | 130 + include/sys/sem.h | 69 + include/sys/sendfile.h | 52 + include/sys/shm.h | 64 + include/sys/signal.h | 1 + include/sys/signalfd.h | 86 + include/sys/socket.h | 236 + include/sys/socketvar.h | 3 + include/sys/soundcard.h | 1 + include/sys/stat.h | 366 + include/sys/statfs.h | 70 + include/sys/statvfs.h | 91 + include/sys/swap.h | 43 + include/sys/syscall.h | 37 + include/sys/sysctl.h | 72 + include/sys/sysinfo.h | 67 + include/sys/syslog.h | 212 + include/sys/sysmacros.h | 69 + include/sys/termios.h | 4 + include/sys/time.h | 192 + include/sys/timeb.h | 46 + include/sys/times.h | 53 + include/sys/timex.h | 129 + include/sys/ttydefaults.h | 100 + include/sys/types.h | 275 + include/sys/uio.h | 54 + include/sys/un.h | 47 + include/sys/unistd.h | 1 + include/sys/ustat.h | 38 + include/sys/utsname.h | 74 + include/sys/vfs.h | 4 + include/sys/vt.h | 1 + include/sys/wait.h | 186 + include/sys/xattr.h | 104 + include/syscall.h | 1 + include/sysexits.h | 114 + include/syslog.h | 1 + include/tar.h | 108 + include/termio.h | 6 + include/termios.h | 110 + include/tgmath.h | 430 + include/time.h | 445 + include/ttyent.h | 65 + include/ucontext.h | 32 + include/ulimit.h | 48 + include/unistd.h | 1125 ++ include/ustat.h | 1 + include/utime.h | 52 + include/utmp.h | 97 + include/values.h | 71 + include/wait.h | 1 + include/wchar.h | 752 + include/wctype.h | 330 + include/wordexp.h | 71 + include/xlocale.h | 62 + ldso/COPYRIGHT | 49 + ldso/Makefile | 13 + ldso/Makefile.in | 9 + ldso/README | 841 + ldso/include/dl-defs.h | 254 + ldso/include/dl-elf.h | 199 + ldso/include/dl-hash.h | 155 + ldso/include/dl-string.h | 365 + ldso/include/dl-syscall.h | 203 + ldso/include/dlfcn.h | 28 + ldso/include/ldso.h | 124 + ldso/include/unsecvars.h | 32 + ldso/ldso/Makefile | 13 + ldso/ldso/Makefile.in | 61 + ldso/ldso/arm/dl-debug.h | 44 + ldso/ldso/arm/dl-startup.h | 194 + ldso/ldso/arm/dl-syscalls.h | 42 + ldso/ldso/arm/dl-sysdep.h | 146 + ldso/ldso/arm/elfinterp.c | 333 + ldso/ldso/arm/resolve.S | 169 + ldso/ldso/avr32/dl-debug.h | 45 + ldso/ldso/avr32/dl-startup.h | 112 + ldso/ldso/avr32/dl-syscalls.h | 6 + ldso/ldso/avr32/dl-sysdep.h | 105 + ldso/ldso/avr32/elfinterp.c | 193 + ldso/ldso/avr32/resolve.S | 28 + ldso/ldso/bfin/dl-debug.h | 54 + ldso/ldso/bfin/dl-inlines.h | 574 + ldso/ldso/bfin/dl-startup.h | 145 + ldso/ldso/bfin/dl-syscalls.h | 208 + ldso/ldso/bfin/dl-sysdep.h | 229 + ldso/ldso/bfin/elfinterp.c | 350 + ldso/ldso/bfin/resolve.S | 77 + ldso/ldso/cris/dl-debug.h | 42 + ldso/ldso/cris/dl-startup.h | 81 + ldso/ldso/cris/dl-syscalls.h | 6 + ldso/ldso/cris/dl-sysdep.h | 111 + ldso/ldso/cris/elfinterp.c | 294 + ldso/ldso/cris/resolve.S | 89 + ldso/ldso/dl-array.c | 84 + ldso/ldso/dl-debug.c | 106 + ldso/ldso/dl-elf.c | 956 ++ ldso/ldso/dl-hash.c | 367 + ldso/ldso/dl-startup.c | 325 + ldso/ldso/frv/dl-debug.h | 29 + ldso/ldso/frv/dl-inlines.h | 456 + ldso/ldso/frv/dl-startup.h | 133 + ldso/ldso/frv/dl-syscalls.h | 175 + ldso/ldso/frv/dl-sysdep.h | 191 + ldso/ldso/frv/elfinterp.c | 355 + ldso/ldso/frv/resolve.S | 57 + ldso/ldso/i386/dl-debug.h | 36 + ldso/ldso/i386/dl-startup.h | 65 + ldso/ldso/i386/dl-syscalls.h | 6 + ldso/ldso/i386/dl-sysdep.h | 80 + ldso/ldso/i386/elfinterp.c | 294 + ldso/ldso/i386/resolve.S | 51 + ldso/ldso/ldso.c | 947 ++ ldso/ldso/m68k/dl-debug.h | 42 + ldso/ldso/m68k/dl-startup.h | 86 + ldso/ldso/m68k/dl-syscalls.h | 6 + ldso/ldso/m68k/dl-sysdep.h | 74 + ldso/ldso/m68k/elfinterp.c | 326 + ldso/ldso/m68k/resolve.S | 28 + ldso/ldso/mips/README | 52 + ldso/ldso/mips/dl-debug.h | 45 + ldso/ldso/mips/dl-startup.h | 190 + ldso/ldso/mips/dl-syscalls.h | 6 + ldso/ldso/mips/dl-sysdep.h | 220 + ldso/ldso/mips/elfinterp.c | 237 + ldso/ldso/mips/resolve.S | 114 + ldso/ldso/powerpc/dl-debug.h | 44 + ldso/ldso/powerpc/dl-startup.h | 89 + ldso/ldso/powerpc/dl-syscalls.h | 6 + ldso/ldso/powerpc/dl-sysdep.h | 187 + ldso/ldso/powerpc/elfinterp.c | 430 + ldso/ldso/powerpc/resolve.S | 57 + ldso/ldso/sh/dl-debug.h | 41 + ldso/ldso/sh/dl-startup.h | 68 + ldso/ldso/sh/dl-syscalls.h | 14 + ldso/ldso/sh/dl-sysdep.h | 174 + ldso/ldso/sh/elfinterp.c | 285 + ldso/ldso/sh/resolve.S | 98 + ldso/ldso/sh64/dl-debug.h | 79 + ldso/ldso/sh64/dl-startup.h | 117 + ldso/ldso/sh64/dl-syscalls.h | 25 + ldso/ldso/sh64/dl-sysdep.h | 169 + ldso/ldso/sh64/elfinterp.c | 346 + ldso/ldso/sh64/resolve.S | 95 + ldso/ldso/sparc/dl-debug.h | 40 + ldso/ldso/sparc/dl-startup.h | 78 + ldso/ldso/sparc/dl-syscalls.h | 6 + ldso/ldso/sparc/dl-sysdep.h | 171 + ldso/ldso/sparc/elfinterp.c | 372 + ldso/ldso/sparc/resolve.S | 22 + ldso/ldso/x86_64/dl-debug.h | 39 + ldso/ldso/x86_64/dl-startup.h | 64 + ldso/ldso/x86_64/dl-syscalls.h | 6 + ldso/ldso/x86_64/dl-sysdep.h | 113 + ldso/ldso/x86_64/elfinterp.c | 321 + ldso/ldso/x86_64/resolve.S | 62 + ldso/ldso/xtensa/dl-debug.h | 61 + ldso/ldso/xtensa/dl-startup.h | 106 + ldso/ldso/xtensa/dl-syscalls.h | 7 + ldso/ldso/xtensa/dl-sysdep.h | 132 + ldso/ldso/xtensa/elfinterp.c | 285 + ldso/ldso/xtensa/resolve.S | 57 + ldso/libdl/Makefile | 13 + ldso/libdl/Makefile.in | 57 + ldso/libdl/libdl.c | 806 + ldso/man/Makefile | 22 + ldso/man/dlopen.3 | 218 + ldso/man/ld.so.8 | 113 + ldso/man/ld.so.texi | 411 + ldso/man/ldconfig.8 | 189 + ldso/man/ldd.1 | 59 + libc/Makefile | 13 + libc/Makefile.in | 100 + libc/inet/.indent.pro | 33 + libc/inet/Makefile | 13 + libc/inet/Makefile.in | 67 + libc/inet/accept.c | 8 + libc/inet/addr.c | 223 + libc/inet/bind.c | 8 + libc/inet/closenameservers.c | 8 + libc/inet/connect.c | 8 + libc/inet/decodea.c | 8 + libc/inet/decoded.c | 8 + libc/inet/decodeh.c | 8 + libc/inet/decodep.c | 8 + libc/inet/decodeq.c | 8 + libc/inet/dnslookup.c | 8 + libc/inet/encodea.c | 8 + libc/inet/encoded.c | 8 + libc/inet/encodeh.c | 8 + libc/inet/encodep.c | 8 + libc/inet/encodeq.c | 8 + libc/inet/ether_addr.c | 104 + libc/inet/ethers.c | 122 + libc/inet/formquery.c | 8 + libc/inet/gai_strerror.c | 61 + libc/inet/get_hosts_byaddr_r.c | 8 + libc/inet/get_hosts_byname_r.c | 8 + libc/inet/getaddrinfo.c | 893 ++ libc/inet/gethostbyaddr.c | 8 + libc/inet/gethostbyaddr_r.c | 8 + libc/inet/gethostbyname.c | 8 + libc/inet/gethostbyname2.c | 8 + libc/inet/gethostbyname2_r.c | 8 + libc/inet/gethostbyname_r.c | 8 + libc/inet/gethostent.c | 8 + libc/inet/getnameinfo.c | 8 + libc/inet/getnetbyad.c | 40 + libc/inet/getnetbynm.c | 49 + libc/inet/getnetent.c | 148 + libc/inet/getpeername.c | 8 + libc/inet/getproto.c | 279 + libc/inet/getservice.c | 285 + libc/inet/getsockname.c | 8 + libc/inet/getsockopt.c | 8 + libc/inet/herror.c | 68 + libc/inet/hostid.c | 104 + libc/inet/if_index.c | 346 + libc/inet/ifaddrs.c | 865 + libc/inet/in6_addr.c | 33 + libc/inet/inet_addr.c | 8 + libc/inet/inet_aton.c | 8 + libc/inet/inet_lnaof.c | 8 + libc/inet/inet_makeaddr.c | 8 + libc/inet/inet_net.c | 106 + libc/inet/inet_netof.c | 8 + libc/inet/inet_ntoa.c | 8 + libc/inet/lengthd.c | 8 + libc/inet/lengthq.c | 8 + libc/inet/listen.c | 8 + libc/inet/netlinkaccess.h | 69 + libc/inet/ns_name.c | 8 + libc/inet/ntohl.c | 60 + libc/inet/ntop.c | 409 + libc/inet/opennameservers.c | 8 + libc/inet/opensock.c | 43 + libc/inet/read_etc_hosts_r.c | 8 + libc/inet/recv.c | 8 + libc/inet/recvfrom.c | 8 + libc/inet/recvmsg.c | 8 + libc/inet/res_comp.c | 8 + libc/inet/res_init.c | 8 + libc/inet/res_query.c | 8 + libc/inet/resolv.c | 2840 ++++ libc/inet/resolveaddress.c | 8 + libc/inet/resolvename.c | 8 + libc/inet/rpc/.indent.pro | 33 + libc/inet/rpc/Makefile | 13 + libc/inet/rpc/Makefile.in | 45 + libc/inet/rpc/auth_none.c | 140 + libc/inet/rpc/auth_unix.c | 355 + libc/inet/rpc/authunix_prot.c | 73 + libc/inet/rpc/bindresvport.c | 94 + libc/inet/rpc/clnt_generic.c | 189 + libc/inet/rpc/clnt_perror.c | 448 + libc/inet/rpc/clnt_raw.c | 261 + libc/inet/rpc/clnt_simple.c | 170 + libc/inet/rpc/clnt_tcp.c | 566 + libc/inet/rpc/clnt_udp.c | 631 + libc/inet/rpc/clnt_unix.c | 634 + libc/inet/rpc/create_xid.c | 62 + libc/inet/rpc/errqueue.h | 46 + libc/inet/rpc/get_myaddress.c | 114 + libc/inet/rpc/getrpcent.c | 362 + libc/inet/rpc/getrpcport.c | 81 + libc/inet/rpc/pm_getmaps.c | 89 + libc/inet/rpc/pm_getport.c | 102 + libc/inet/rpc/pmap_clnt.c | 187 + libc/inet/rpc/pmap_prot.c | 60 + libc/inet/rpc/pmap_prot2.c | 123 + libc/inet/rpc/pmap_rmt.c | 440 + libc/inet/rpc/rcmd.c | 782 + libc/inet/rpc/rexec.c | 212 + libc/inet/rpc/rpc_cmsg.c | 215 + libc/inet/rpc/rpc_commondata.c | 47 + libc/inet/rpc/rpc_dtablesize.c | 58 + libc/inet/rpc/rpc_private.h | 56 + libc/inet/rpc/rpc_prot.c | 296 + libc/inet/rpc/rpc_thread.c | 169 + libc/inet/rpc/rtime.c | 161 + libc/inet/rpc/ruserpass.c | 347 + libc/inet/rpc/sa_len.c | 63 + libc/inet/rpc/svc.c | 526 + libc/inet/rpc/svc_auth.c | 125 + libc/inet/rpc/svc_authux.c | 163 + libc/inet/rpc/svc_raw.c | 171 + libc/inet/rpc/svc_run.c | 95 + libc/inet/rpc/svc_simple.c | 209 + libc/inet/rpc/svc_tcp.c | 452 + libc/inet/rpc/svc_udp.c | 636 + libc/inet/rpc/svc_unix.c | 563 + libc/inet/rpc/xdr.c | 767 + libc/inet/rpc/xdr_array.c | 180 + libc/inet/rpc/xdr_float.c | 310 + libc/inet/rpc/xdr_intXX_t.c | 203 + libc/inet/rpc/xdr_mem.c | 241 + libc/inet/rpc/xdr_rec.c | 675 + libc/inet/rpc/xdr_reference.c | 156 + libc/inet/rpc/xdr_stdio.c | 200 + libc/inet/send.c | 8 + libc/inet/sendmsg.c | 8 + libc/inet/sendto.c | 8 + libc/inet/setsockopt.c | 8 + libc/inet/shutdown.c | 8 + libc/inet/socket.c | 8 + libc/inet/socketcalls.c | 393 + libc/inet/socketpair.c | 8 + libc/misc/Makefile | 13 + libc/misc/Makefile.in | 33 + libc/misc/assert/.indent.pro | 33 + libc/misc/assert/Makefile | 13 + libc/misc/assert/Makefile.in | 21 + libc/misc/assert/__assert.c | 71 + libc/misc/ctype/.indent.pro | 33 + libc/misc/ctype/Makefile | 13 + libc/misc/ctype/Makefile.in | 38 + libc/misc/ctype/__C_ctype_b.c | 8 + libc/misc/ctype/__C_ctype_tolower.c | 8 + libc/misc/ctype/__C_ctype_toupper.c | 8 + libc/misc/ctype/__ctype_assert.c | 8 + libc/misc/ctype/__ctype_b_loc.c | 8 + libc/misc/ctype/__ctype_tolower_loc.c | 8 + libc/misc/ctype/__ctype_toupper_loc.c | 8 + libc/misc/ctype/ctype.c | 1119 ++ libc/misc/ctype/isalnum.c | 8 + libc/misc/ctype/isalnum_l.c | 9 + libc/misc/ctype/isalpha.c | 8 + libc/misc/ctype/isalpha_l.c | 9 + libc/misc/ctype/isascii.c | 8 + libc/misc/ctype/isascii_l.c | 9 + libc/misc/ctype/isblank.c | 8 + libc/misc/ctype/isblank_l.c | 9 + libc/misc/ctype/iscntrl.c | 8 + libc/misc/ctype/iscntrl_l.c | 9 + libc/misc/ctype/isctype.c | 8 + libc/misc/ctype/isdigit.c | 8 + libc/misc/ctype/isdigit_l.c | 9 + libc/misc/ctype/isgraph.c | 8 + libc/misc/ctype/isgraph_l.c | 9 + libc/misc/ctype/islower.c | 8 + libc/misc/ctype/islower_l.c | 9 + libc/misc/ctype/isprint.c | 8 + libc/misc/ctype/isprint_l.c | 9 + libc/misc/ctype/ispunct.c | 8 + libc/misc/ctype/ispunct_l.c | 9 + libc/misc/ctype/isspace.c | 8 + libc/misc/ctype/isspace_l.c | 9 + libc/misc/ctype/isupper.c | 8 + libc/misc/ctype/isupper_l.c | 9 + libc/misc/ctype/isxdigit.c | 8 + libc/misc/ctype/isxdigit_l.c | 9 + libc/misc/ctype/toascii.c | 8 + libc/misc/ctype/toascii_l.c | 9 + libc/misc/ctype/tolower.c | 8 + libc/misc/ctype/tolower_l.c | 9 + libc/misc/ctype/toupper.c | 8 + libc/misc/ctype/toupper_l.c | 9 + libc/misc/dirent/Makefile | 13 + libc/misc/dirent/Makefile.in | 26 + libc/misc/dirent/alphasort.c | 18 + libc/misc/dirent/alphasort64.c | 19 + libc/misc/dirent/closedir.c | 38 + libc/misc/dirent/dirfd.c | 22 + libc/misc/dirent/dirstream.h | 74 + libc/misc/dirent/opendir.c | 83 + libc/misc/dirent/readdir.c | 57 + libc/misc/dirent/readdir64.c | 57 + libc/misc/dirent/readdir64_r.c | 68 + libc/misc/dirent/readdir_r.c | 66 + libc/misc/dirent/rewinddir.c | 25 + libc/misc/dirent/scandir.c | 100 + libc/misc/dirent/scandir64.c | 117 + libc/misc/dirent/seekdir.c | 24 + libc/misc/dirent/telldir.c | 22 + libc/misc/error/Makefile | 13 + libc/misc/error/Makefile.in | 27 + libc/misc/error/err.c | 129 + libc/misc/error/error.c | 115 + libc/misc/file/Makefile | 13 + libc/misc/file/Makefile.in | 24 + libc/misc/file/lockf.c | 79 + libc/misc/file/lockf64.c | 98 + libc/misc/fnmatch/.indent.pro | 33 + libc/misc/fnmatch/Makefile | 13 + libc/misc/fnmatch/Makefile.in | 25 + libc/misc/fnmatch/fnmatch.c | 476 + libc/misc/fnmatch/fnmatch_loop.c | 1205 ++ libc/misc/fnmatch/fnmatch_old.c | 222 + libc/misc/ftw/Makefile | 13 + libc/misc/ftw/Makefile.in | 24 + libc/misc/ftw/ftw.c | 826 + libc/misc/ftw/ftw64.c | 32 + libc/misc/glob/.indent.pro | 33 + libc/misc/glob/Makefile | 13 + libc/misc/glob/Makefile.in | 31 + libc/misc/glob/glob-susv3.c | 322 + libc/misc/glob/glob.c | 1093 ++ libc/misc/glob/glob64-susv3.c | 20 + libc/misc/glob/glob64.c | 15 + libc/misc/gnu/Makefile | 13 + libc/misc/gnu/Makefile.in | 21 + libc/misc/gnu/obstack.c | 456 + libc/misc/internals/Makefile | 13 + libc/misc/internals/Makefile.in | 39 + libc/misc/internals/__errno_location.c | 17 + libc/misc/internals/__h_errno_location.c | 14 + libc/misc/internals/__uClibc_main.c | 425 + libc/misc/internals/errno.c | 15 + libc/misc/internals/internal_errno.h | 18 + libc/misc/internals/shared_flat_add_library.c | 46 + libc/misc/internals/shared_flat_initfini.c | 53 + libc/misc/internals/shared_flat_lib.h | 35 + libc/misc/internals/tempname.c | 263 + libc/misc/internals/tempname.h | 20 + libc/misc/locale/Makefile | 13 + libc/misc/locale/Makefile.in | 28 + libc/misc/locale/__curlocale.c | 9 + libc/misc/locale/__locale_mbrtowc_l.c | 8 + libc/misc/locale/_locale_init.c | 8 + libc/misc/locale/duplocale.c | 9 + libc/misc/locale/freelocale.c | 9 + libc/misc/locale/locale.c | 1498 ++ libc/misc/locale/localeconv.c | 8 + libc/misc/locale/newlocale.c | 8 + libc/misc/locale/nl_langinfo.c | 8 + libc/misc/locale/nl_langinfo_l.c | 9 + libc/misc/locale/setlocale.c | 8 + libc/misc/locale/uselocale.c | 9 + libc/misc/mntent/.indent.pro | 33 + libc/misc/mntent/Makefile | 13 + libc/misc/mntent/Makefile.in | 21 + libc/misc/mntent/mntent.c | 124 + libc/misc/pthread/Makefile | 13 + libc/misc/pthread/Makefile.in | 17 + libc/misc/pthread/unlock.c | 27 + libc/misc/pthread/weaks.c | 44 + libc/misc/regex/.indent.pro | 33 + libc/misc/regex/Makefile | 13 + libc/misc/regex/Makefile.in | 25 + libc/misc/regex/_regex.h | 45 + libc/misc/regex/regcomp.c | 3808 +++++ libc/misc/regex/regex.c | 152 + libc/misc/regex/regex_internal.c | 1646 ++ libc/misc/regex/regex_internal.h | 761 + libc/misc/regex/regex_old.c | 8361 ++++++++++ libc/misc/regex/regexec.c | 4337 +++++ libc/misc/search/Makefile | 13 + libc/misc/search/Makefile.in | 33 + libc/misc/search/_hsearch_r.c | 231 + libc/misc/search/_lsearch.c | 51 + libc/misc/search/_tsearch.c | 223 + libc/misc/search/hcreate_r.c | 8 + libc/misc/search/hdestroy_r.c | 8 + libc/misc/search/hsearch.c | 55 + libc/misc/search/hsearch_r.c | 8 + libc/misc/search/insque.c | 8 + libc/misc/search/insremque.c | 54 + libc/misc/search/lfind.c | 8 + libc/misc/search/lsearch.c | 8 + libc/misc/search/remque.c | 8 + libc/misc/search/tdelete.c | 8 + libc/misc/search/tdestroy.c | 8 + libc/misc/search/tfind.c | 8 + libc/misc/search/tsearch.c | 8 + libc/misc/search/twalk.c | 8 + libc/misc/statfs/Makefile | 13 + libc/misc/statfs/Makefile.in | 29 + libc/misc/statfs/fstatfs64.c | 53 + libc/misc/statfs/fstatvfs.c | 68 + libc/misc/statfs/fstatvfs64.c | 80 + libc/misc/statfs/internal_statvfs.c | 111 + libc/misc/statfs/statfs64.c | 52 + libc/misc/statfs/statvfs.c | 57 + libc/misc/statfs/statvfs64.c | 80 + libc/misc/syslog/Makefile | 13 + libc/misc/syslog/Makefile.in | 23 + libc/misc/syslog/syslog.c | 360 + libc/misc/sysvipc/.indent.pro | 33 + libc/misc/sysvipc/Makefile | 13 + libc/misc/sysvipc/Makefile.in | 30 + libc/misc/sysvipc/__syscall_ipc.c | 17 + libc/misc/sysvipc/ftok.c | 37 + libc/misc/sysvipc/ipc.h | 35 + libc/misc/sysvipc/msgctl.c | 8 + libc/misc/sysvipc/msgget.c | 8 + libc/misc/sysvipc/msgq.c | 73 + libc/misc/sysvipc/msgrcv.c | 8 + libc/misc/sysvipc/msgsnd.c | 8 + libc/misc/sysvipc/sem.c | 105 + libc/misc/sysvipc/semctl.c | 8 + libc/misc/sysvipc/semget.c | 8 + libc/misc/sysvipc/semop.c | 8 + libc/misc/sysvipc/semtimedop.c | 8 + libc/misc/sysvipc/shm.c | 96 + libc/misc/sysvipc/shmat.c | 8 + libc/misc/sysvipc/shmctl.c | 8 + libc/misc/sysvipc/shmdt.c | 8 + libc/misc/sysvipc/shmget.c | 8 + libc/misc/time/.indent.pro | 33 + libc/misc/time/Makefile | 13 + libc/misc/time/Makefile.in | 41 + libc/misc/time/__time_tm.c | 8 + libc/misc/time/_time_localtime_tzi.c | 8 + libc/misc/time/_time_mktime.c | 8 + libc/misc/time/_time_mktime_tzi.c | 8 + libc/misc/time/_time_t2tm.c | 8 + libc/misc/time/adjtime.c | 59 + libc/misc/time/asctime.c | 8 + libc/misc/time/asctime_r.c | 8 + libc/misc/time/clock.c | 8 + libc/misc/time/ctime.c | 8 + libc/misc/time/ctime_r.c | 8 + libc/misc/time/difftime.c | 8 + libc/misc/time/dysize.c | 8 + libc/misc/time/ftime.c | 37 + libc/misc/time/gmtime.c | 8 + libc/misc/time/gmtime_r.c | 8 + libc/misc/time/localtime.c | 8 + libc/misc/time/localtime_r.c | 8 + libc/misc/time/mktime.c | 8 + libc/misc/time/strftime.c | 8 + libc/misc/time/strftime_l.c | 9 + libc/misc/time/strptime.c | 8 + libc/misc/time/strptime_l.c | 9 + libc/misc/time/time.c | 2454 +++ libc/misc/time/timegm.c | 8 + libc/misc/time/tzset.c | 8 + libc/misc/time/wcsftime.c | 8 + libc/misc/time/wcsftime_l.c | 9 + libc/misc/ttyent/Makefile | 13 + libc/misc/ttyent/Makefile.in | 21 + libc/misc/ttyent/getttyent.c | 228 + libc/misc/utmp/Makefile | 13 + libc/misc/utmp/Makefile.in | 21 + libc/misc/utmp/utent.c | 210 + libc/misc/utmp/wtent.c | 58 + libc/misc/wchar/Makefile | 13 + libc/misc/wchar/Makefile.in | 39 + libc/misc/wchar/_wchar_utf8sntowcs.c | 8 + libc/misc/wchar/_wchar_wcsntoutf8s.c | 8 + libc/misc/wchar/btowc.c | 8 + libc/misc/wchar/iconv.c | 8 + libc/misc/wchar/mbrlen.c | 8 + libc/misc/wchar/mbrtowc.c | 8 + libc/misc/wchar/mbsinit.c | 8 + libc/misc/wchar/mbsnrtowcs.c | 8 + libc/misc/wchar/mbsrtowcs.c | 8 + libc/misc/wchar/wchar.c | 1737 ++ libc/misc/wchar/wcrtomb.c | 8 + libc/misc/wchar/wcsnrtombs.c | 8 + libc/misc/wchar/wcsrtombs.c | 8 + libc/misc/wchar/wcswidth.c | 8 + libc/misc/wchar/wctob.c | 8 + libc/misc/wchar/wcwidth.c | 8 + libc/misc/wctype/Makefile | 13 + libc/misc/wctype/Makefile.in | 34 + libc/misc/wctype/_wctype.c | 947 ++ libc/misc/wctype/iswalnum.c | 8 + libc/misc/wctype/iswalnum_l.c | 9 + libc/misc/wctype/iswalpha.c | 8 + libc/misc/wctype/iswalpha_l.c | 9 + libc/misc/wctype/iswblank.c | 8 + libc/misc/wctype/iswblank_l.c | 9 + libc/misc/wctype/iswcntrl.c | 8 + libc/misc/wctype/iswcntrl_l.c | 9 + libc/misc/wctype/iswctype.c | 8 + libc/misc/wctype/iswctype_l.c | 9 + libc/misc/wctype/iswdigit.c | 8 + libc/misc/wctype/iswdigit_l.c | 9 + libc/misc/wctype/iswgraph.c | 8 + libc/misc/wctype/iswgraph_l.c | 9 + libc/misc/wctype/iswlower.c | 8 + libc/misc/wctype/iswlower_l.c | 9 + libc/misc/wctype/iswprint.c | 8 + libc/misc/wctype/iswprint_l.c | 9 + libc/misc/wctype/iswpunct.c | 8 + libc/misc/wctype/iswpunct_l.c | 9 + libc/misc/wctype/iswspace.c | 8 + libc/misc/wctype/iswspace_l.c | 9 + libc/misc/wctype/iswupper.c | 8 + libc/misc/wctype/iswupper_l.c | 9 + libc/misc/wctype/iswxdigit.c | 8 + libc/misc/wctype/iswxdigit_l.c | 9 + libc/misc/wctype/towctrans.c | 8 + libc/misc/wctype/towctrans_l.c | 9 + libc/misc/wctype/towlower.c | 8 + libc/misc/wctype/towlower_l.c | 9 + libc/misc/wctype/towupper.c | 8 + libc/misc/wctype/towupper_l.c | 9 + libc/misc/wctype/wctrans.c | 8 + libc/misc/wctype/wctrans_l.c | 9 + libc/misc/wctype/wctype.c | 8 + libc/misc/wctype/wctype_l.c | 9 + libc/misc/wordexp/Makefile | 13 + libc/misc/wordexp/Makefile.in | 21 + libc/misc/wordexp/wordexp.c | 2275 +++ libc/pwd_grp/.indent.pro | 33 + libc/pwd_grp/Makefile | 13 + libc/pwd_grp/Makefile.in | 31 + libc/pwd_grp/__getgrouplist_internal.c | 8 + libc/pwd_grp/__parsegrent.c | 8 + libc/pwd_grp/__parsepwent.c | 8 + libc/pwd_grp/__parsespent.c | 8 + libc/pwd_grp/__pgsreader.c | 8 + libc/pwd_grp/fgetgrent.c | 8 + libc/pwd_grp/fgetgrent_r.c | 8 + libc/pwd_grp/fgetpwent.c | 8 + libc/pwd_grp/fgetpwent_r.c | 8 + libc/pwd_grp/fgetspent.c | 8 + libc/pwd_grp/fgetspent_r.c | 8 + libc/pwd_grp/getgrent.c | 8 + libc/pwd_grp/getgrent_r.c | 12 + libc/pwd_grp/getgrgid.c | 8 + libc/pwd_grp/getgrgid_r.c | 8 + libc/pwd_grp/getgrnam.c | 8 + libc/pwd_grp/getgrnam_r.c | 8 + libc/pwd_grp/getgrouplist.c | 8 + libc/pwd_grp/getpw.c | 12 + libc/pwd_grp/getpwent.c | 8 + libc/pwd_grp/getpwent_r.c | 8 + libc/pwd_grp/getpwnam.c | 8 + libc/pwd_grp/getpwnam_r.c | 8 + libc/pwd_grp/getpwuid.c | 8 + libc/pwd_grp/getpwuid_r.c | 8 + libc/pwd_grp/getspent.c | 8 + libc/pwd_grp/getspent_r.c | 8 + libc/pwd_grp/getspnam.c | 8 + libc/pwd_grp/getspnam_r.c | 8 + libc/pwd_grp/initgroups.c | 8 + libc/pwd_grp/lckpwdf.c | 195 + libc/pwd_grp/putgrent.c | 12 + libc/pwd_grp/putpwent.c | 8 + libc/pwd_grp/putspent.c | 8 + libc/pwd_grp/pwd_grp.c | 1228 ++ libc/pwd_grp/pwd_grp_internal.c | 103 + libc/pwd_grp/sgetspent.c | 8 + libc/pwd_grp/sgetspent_r.c | 8 + libc/signal/Makefile | 13 + libc/signal/Makefile.in | 34 + libc/signal/allocrtsig.c | 66 + libc/signal/killpg.c | 37 + libc/signal/raise.c | 21 + libc/signal/sigaction.c | 115 + libc/signal/sigaddset.c | 34 + libc/signal/sigandset.c | 34 + libc/signal/sigblock.c | 41 + libc/signal/sigdelset.c | 33 + libc/signal/sigempty.c | 39 + libc/signal/sigfillset.c | 49 + libc/signal/siggetmask.c | 32 + libc/signal/sighold.c | 42 + libc/signal/sigignore.c | 39 + libc/signal/sigintr.c | 59 + libc/signal/sigisempty.c | 34 + libc/signal/sigismem.c | 31 + libc/signal/sigjmp.c | 37 + libc/signal/signal.c | 57 + libc/signal/sigorset.c | 34 + libc/signal/sigpause.c | 65 + libc/signal/sigrelse.c | 42 + libc/signal/sigset-cvt-mask.h | 44 + libc/signal/sigset.c | 81 + libc/signal/sigsetmask.c | 43 + libc/signal/sigsetops.c | 11 + libc/signal/sigsetops.h | 33 + libc/signal/sigwait.c | 101 + libc/signal/sysv_signal.c | 59 + libc/stdio/.indent.pro | 33 + libc/stdio/Makefile | 13 + libc/stdio/Makefile.in | 107 + libc/stdio/_READ.c | 69 + libc/stdio/_WRITE.c | 102 + libc/stdio/__fbufsize.c | 20 + libc/stdio/__flbf.c | 20 + libc/stdio/__fpending.c | 35 + libc/stdio/__fpurge.c | 34 + libc/stdio/__freadable.c | 20 + libc/stdio/__freading.c | 20 + libc/stdio/__fsetlocking.c | 48 + libc/stdio/__fwritable.c | 20 + libc/stdio/__fwriting.c | 20 + libc/stdio/__psfs_do_numeric.c | 9 + libc/stdio/__psfs_parse_spec.c | 9 + libc/stdio/__scan_cookie.c | 9 + libc/stdio/_adjust_pos.c | 68 + libc/stdio/_cs_funcs.c | 76 + libc/stdio/_flushlbf.c | 20 + libc/stdio/_fopen.c | 223 + libc/stdio/_fpmaxtostr.c | 766 + libc/stdio/_fwrite.c | 82 + libc/stdio/_load_inttype.c | 67 + libc/stdio/_ppfs_init.c | 9 + libc/stdio/_ppfs_parsespec.c | 9 + libc/stdio/_ppfs_prepargs.c | 9 + libc/stdio/_ppfs_setargs.c | 9 + libc/stdio/_rfill.c | 45 + libc/stdio/_scanf.c | 2260 +++ libc/stdio/_stdio.c | 445 + libc/stdio/_stdio.h | 456 + libc/stdio/_store_inttype.c | 58 + libc/stdio/_trans2r.c | 79 + libc/stdio/_trans2w.c | 95 + libc/stdio/_uintmaxtostr.c | 153 + libc/stdio/_vfprintf.c | 1983 +++ libc/stdio/_vfprintf_internal.c | 9 + libc/stdio/_vfwprintf_internal.c | 9 + libc/stdio/_wcommit.c | 31 + libc/stdio/_wfwrite.c | 75 + libc/stdio/asprintf.c | 36 + libc/stdio/clearerr.c | 40 + libc/stdio/clearerr_unlocked.c | 9 + libc/stdio/ctermid.c | 28 + libc/stdio/dprintf.c | 27 + libc/stdio/fclose.c | 106 + libc/stdio/fcloseall.c | 71 + libc/stdio/fdopen.c | 21 + libc/stdio/feof.c | 43 + libc/stdio/feof_unlocked.c | 9 + libc/stdio/ferror.c | 43 + libc/stdio/ferror_unlocked.c | 9 + libc/stdio/fflush.c | 214 + libc/stdio/fflush_unlocked.c | 9 + libc/stdio/fgetc.c | 117 + libc/stdio/fgetc_unlocked.c | 9 + libc/stdio/fgetpos.c | 40 + libc/stdio/fgetpos64.c | 14 + libc/stdio/fgets.c | 91 + libc/stdio/fgets_unlocked.c | 14 + libc/stdio/fgetwc.c | 142 + libc/stdio/fgetwc_unlocked.c | 9 + libc/stdio/fgetws.c | 62 + libc/stdio/fgetws_unlocked.c | 9 + libc/stdio/fileno.c | 51 + libc/stdio/fileno_unlocked.c | 9 + libc/stdio/flockfile.c | 16 + libc/stdio/fmemopen.c | 183 + libc/stdio/fopen.c | 22 + libc/stdio/fopen64.c | 14 + libc/stdio/fopencookie.c | 67 + libc/stdio/fprintf.c | 25 + libc/stdio/fputc.c | 115 + libc/stdio/fputc_unlocked.c | 9 + libc/stdio/fputs.c | 55 + libc/stdio/fputs_unlocked.c | 14 + libc/stdio/fputwc.c | 44 + libc/stdio/fputwc_unlocked.c | 9 + libc/stdio/fputws.c | 49 + libc/stdio/fputws_unlocked.c | 9 + libc/stdio/fread.c | 117 + libc/stdio/fread_unlocked.c | 9 + libc/stdio/freopen.c | 76 + libc/stdio/freopen64.c | 13 + libc/stdio/fscanf.c | 9 + libc/stdio/fseeko.c | 86 + libc/stdio/fseeko64.c | 13 + libc/stdio/fsetpos.c | 39 + libc/stdio/fsetpos64.c | 14 + libc/stdio/ftello.c | 62 + libc/stdio/ftello64.c | 13 + libc/stdio/ftrylockfile.c | 19 + libc/stdio/funlockfile.c | 15 + libc/stdio/fwide.c | 32 + libc/stdio/fwprintf.c | 24 + libc/stdio/fwrite.c | 65 + libc/stdio/fwrite_unlocked.c | 9 + libc/stdio/fwscanf.c | 9 + libc/stdio/getchar.c | 47 + libc/stdio/getchar_unlocked.c | 9 + libc/stdio/getdelim.c | 84 + libc/stdio/getline.c | 23 + libc/stdio/gets.c | 40 + libc/stdio/getw.c | 20 + libc/stdio/getwchar.c | 32 + libc/stdio/getwchar_unlocked.c | 9 + libc/stdio/old_vfprintf.c | 717 + libc/stdio/open_memstream.c | 170 + libc/stdio/parse_printf_format.c | 9 + libc/stdio/perror.c | 41 + libc/stdio/popen.c | 196 + libc/stdio/printf.c | 25 + libc/stdio/putchar.c | 44 + libc/stdio/putchar_unlocked.c | 9 + libc/stdio/puts.c | 36 + libc/stdio/putw.c | 30 + libc/stdio/putwchar.c | 34 + libc/stdio/putwchar_unlocked.c | 9 + libc/stdio/register_printf_function.c | 9 + libc/stdio/remove.c | 34 + libc/stdio/rewind.c | 24 + libc/stdio/scanf.c | 9 + libc/stdio/setbuf.c | 17 + libc/stdio/setbuffer.c | 26 + libc/stdio/setlinebuf.c | 25 + libc/stdio/setvbuf.c | 108 + libc/stdio/snprintf.c | 31 + libc/stdio/sprintf.c | 31 + libc/stdio/sscanf.c | 9 + libc/stdio/swprintf.c | 31 + libc/stdio/swscanf.c | 9 + libc/stdio/tempnam.c | 45 + libc/stdio/tmpfile.c | 55 + libc/stdio/tmpnam.c | 55 + libc/stdio/tmpnam_r.c | 35 + libc/stdio/ungetc.c | 79 + libc/stdio/ungetwc.c | 50 + libc/stdio/vasprintf.c | 91 + libc/stdio/vdprintf.c | 79 + libc/stdio/vfprintf.c | 9 + libc/stdio/vfscanf.c | 9 + libc/stdio/vfwprintf.c | 9 + libc/stdio/vfwscanf.c | 9 + libc/stdio/vprintf.c | 16 + libc/stdio/vscanf.c | 9 + libc/stdio/vsnprintf.c | 221 + libc/stdio/vsprintf.c | 23 + libc/stdio/vsscanf.c | 9 + libc/stdio/vswprintf.c | 71 + libc/stdio/vswscanf.c | 9 + libc/stdio/vwprintf.c | 17 + libc/stdio/vwscanf.c | 9 + libc/stdio/wprintf.c | 25 + libc/stdio/wscanf.c | 9 + libc/stdlib/.indent.pro | 33 + libc/stdlib/Makefile | 13 + libc/stdlib/Makefile.in | 99 + libc/stdlib/__cxa_atexit.c | 8 + libc/stdlib/__cxa_finalize.c | 8 + libc/stdlib/__exit_handler.c | 8 + libc/stdlib/__fp_range_check.c | 8 + libc/stdlib/__strtofpmax.c | 8 + libc/stdlib/__strtofpmax_l.c | 9 + libc/stdlib/__uc_malloc.c | 48 + libc/stdlib/__wcstofpmax.c | 8 + libc/stdlib/__wcstofpmax_l.c | 9 + libc/stdlib/_atexit.c | 339 + libc/stdlib/_stdlib_mb_cur_max.c | 7 + libc/stdlib/_stdlib_strto_l.c | 7 + libc/stdlib/_stdlib_strto_l_l.c | 8 + libc/stdlib/_stdlib_strto_ll.c | 7 + libc/stdlib/_stdlib_strto_ll_l.c | 8 + libc/stdlib/_stdlib_wcsto_l.c | 7 + libc/stdlib/_stdlib_wcsto_l_l.c | 8 + libc/stdlib/_stdlib_wcsto_ll.c | 7 + libc/stdlib/_stdlib_wcsto_ll_l.c | 8 + libc/stdlib/_strtod.c | 620 + libc/stdlib/a64l.c | 64 + libc/stdlib/abort.c | 120 + libc/stdlib/abs.c | 7 + libc/stdlib/arc4random.c | 210 + libc/stdlib/atexit.c | 8 + libc/stdlib/atof.c | 7 + libc/stdlib/atoi.c | 7 + libc/stdlib/atol.c | 7 + libc/stdlib/atoll.c | 7 + libc/stdlib/bsd_getpt.c | 78 + libc/stdlib/bsearch.c | 7 + libc/stdlib/div.c | 17 + libc/stdlib/drand48-iter.c | 59 + libc/stdlib/drand48.c | 34 + libc/stdlib/drand48_r.c | 29 + libc/stdlib/erand48.c | 34 + libc/stdlib/erand48_r.c | 49 + libc/stdlib/exit.c | 8 + libc/stdlib/gcvt.c | 13 + libc/stdlib/getenv.c | 33 + libc/stdlib/getpt.c | 135 + libc/stdlib/grantpt.c | 77 + libc/stdlib/jrand48.c | 34 + libc/stdlib/jrand48_r.c | 37 + libc/stdlib/l64a.c | 56 + libc/stdlib/labs.c | 7 + libc/stdlib/ldiv.c | 61 + libc/stdlib/llabs.c | 7 + libc/stdlib/lldiv.c | 61 + libc/stdlib/lrand48.c | 34 + libc/stdlib/lrand48_r.c | 33 + libc/stdlib/malloc-simple/Makefile | 13 + libc/stdlib/malloc-simple/Makefile.in | 22 + libc/stdlib/malloc-simple/alloc.c | 190 + libc/stdlib/malloc-simple/calloc.c | 8 + libc/stdlib/malloc-simple/free.c | 8 + libc/stdlib/malloc-simple/malloc.c | 8 + libc/stdlib/malloc-simple/memalign.c | 8 + libc/stdlib/malloc-simple/realloc.c | 8 + libc/stdlib/malloc-standard/Makefile | 13 + libc/stdlib/malloc-standard/Makefile.in | 23 + libc/stdlib/malloc-standard/calloc.c | 94 + libc/stdlib/malloc-standard/free.c | 411 + libc/stdlib/malloc-standard/mallinfo.c | 126 + libc/stdlib/malloc-standard/malloc.c | 1167 ++ libc/stdlib/malloc-standard/malloc.h | 966 ++ libc/stdlib/malloc-standard/mallopt.c | 64 + libc/stdlib/malloc-standard/memalign.c | 130 + libc/stdlib/malloc-standard/realloc.c | 242 + libc/stdlib/malloc/Makefile | 13 + libc/stdlib/malloc/Makefile.in | 37 + libc/stdlib/malloc/calloc.c | 43 + libc/stdlib/malloc/free.c | 274 + libc/stdlib/malloc/heap.h | 230 + libc/stdlib/malloc/heap_alloc.c | 51 + libc/stdlib/malloc/heap_alloc_at.c | 47 + libc/stdlib/malloc/heap_debug.c | 147 + libc/stdlib/malloc/heap_free.c | 89 + libc/stdlib/malloc/malloc.c | 234 + libc/stdlib/malloc/malloc.h | 230 + libc/stdlib/malloc/malloc_debug.c | 91 + libc/stdlib/malloc/memalign.c | 95 + libc/stdlib/malloc/realloc.c | 98 + libc/stdlib/mblen.c | 7 + libc/stdlib/mbstowcs.c | 7 + libc/stdlib/mbtowc.c | 7 + libc/stdlib/mkdtemp.c | 37 + libc/stdlib/mkstemp.c | 30 + libc/stdlib/mkstemp64.c | 30 + libc/stdlib/mktemp.c | 35 + libc/stdlib/mrand48.c | 34 + libc/stdlib/mrand48_r.c | 31 + libc/stdlib/nrand48.c | 34 + libc/stdlib/nrand48_r.c | 40 + libc/stdlib/old_atexit.c | 8 + libc/stdlib/on_exit.c | 8 + libc/stdlib/posix_memalign.c | 42 + libc/stdlib/ptsname.c | 200 + libc/stdlib/pty-private.h | 42 + libc/stdlib/qsort.c | 7 + libc/stdlib/rand.c | 16 + libc/stdlib/rand_r.c | 48 + libc/stdlib/random.c | 257 + libc/stdlib/random_r.c | 365 + libc/stdlib/realpath.c | 172 + libc/stdlib/seed48.c | 32 + libc/stdlib/seed48_r.c | 42 + libc/stdlib/setenv.c | 206 + libc/stdlib/srand48.c | 30 + libc/stdlib/srand48_r.c | 40 + libc/stdlib/stdlib.c | 1177 ++ libc/stdlib/strtod.c | 8 + libc/stdlib/strtod_l.c | 9 + libc/stdlib/strtof.c | 8 + libc/stdlib/strtof_l.c | 9 + libc/stdlib/strtol.c | 7 + libc/stdlib/strtol_l.c | 8 + libc/stdlib/strtold.c | 8 + libc/stdlib/strtold_l.c | 9 + libc/stdlib/strtoll.c | 7 + libc/stdlib/strtoll_l.c | 8 + libc/stdlib/strtoul.c | 7 + libc/stdlib/strtoul_l.c | 8 + libc/stdlib/strtoull.c | 7 + libc/stdlib/strtoull_l.c | 8 + libc/stdlib/system.c | 70 + libc/stdlib/unix_grantpt.c | 215 + libc/stdlib/unlockpt.c | 50 + libc/stdlib/valloc.c | 37 + libc/stdlib/wcstod.c | 8 + libc/stdlib/wcstod_l.c | 9 + libc/stdlib/wcstof.c | 8 + libc/stdlib/wcstof_l.c | 9 + libc/stdlib/wcstol.c | 7 + libc/stdlib/wcstol_l.c | 8 + libc/stdlib/wcstold.c | 8 + libc/stdlib/wcstold_l.c | 9 + libc/stdlib/wcstoll.c | 7 + libc/stdlib/wcstoll_l.c | 8 + libc/stdlib/wcstombs.c | 7 + libc/stdlib/wcstoul.c | 7 + libc/stdlib/wcstoul_l.c | 8 + libc/stdlib/wcstoull.c | 7 + libc/stdlib/wcstoull_l.c | 8 + libc/stdlib/wctomb.c | 7 + libc/string/.indent.pro | 33 + libc/string/Makefile | 13 + libc/string/Makefile.in | 139 + libc/string/__glibc_strerror_r.c | 20 + libc/string/__xpg_basename.c | 36 + libc/string/__xpg_strerror_r.c | 279 + libc/string/_collate.c | 686 + libc/string/_string.h | 32 + libc/string/_string_syserrmsgs.c | 147 + libc/string/_string_syssigmsgs.c | 51 + libc/string/_syserrmsg.h | 37 + libc/string/arm/Makefile | 13 + libc/string/arm/_memcpy.S | 746 + libc/string/arm/bcopy.S | 72 + libc/string/arm/bzero.S | 68 + libc/string/arm/memcmp.S | 96 + libc/string/arm/memcpy.S | 61 + libc/string/arm/memmove.S | 61 + libc/string/arm/memset.S | 144 + libc/string/arm/strcmp.S | 78 + libc/string/arm/strlen.S | 111 + libc/string/avr32/Makefile | 26 + libc/string/avr32/bcopy.S | 26 + libc/string/avr32/bzero.S | 24 + libc/string/avr32/memcmp.S | 61 + libc/string/avr32/memcpy.S | 111 + libc/string/avr32/memmove.S | 116 + libc/string/avr32/memset.S | 65 + libc/string/avr32/strcmp.S | 91 + libc/string/avr32/strlen.S | 62 + libc/string/basename.c | 29 + libc/string/bcopy.c | 56 + libc/string/bfin/Makefile | 13 + libc/string/bfin/memchr.S | 55 + libc/string/bfin/memcmp.S | 104 + libc/string/bfin/memcpy.S | 77 + libc/string/bfin/memmove.S | 100 + libc/string/bfin/memset.S | 90 + libc/string/bfin/strcmp.S | 122 + libc/string/bzero.c | 34 + libc/string/cris/memcopy.h | 62 + libc/string/cris/memcpy.c | 243 + libc/string/cris/memmove.c | 101 + libc/string/cris/memset.c | 263 + libc/string/cris/strcpy.c | 51 + libc/string/cris/strncpy.c | 61 + libc/string/dirname.c | 44 + libc/string/ffs.c | 55 + libc/string/frv/Makefile | 13 + libc/string/frv/memcpy.S | 127 + libc/string/frv/memset.S | 158 + libc/string/generic/Makefile | 13 + libc/string/generic/_memcpy_fwd.c | 185 + libc/string/generic/bp-checks.h | 129 + libc/string/generic/memchr.c | 177 + libc/string/generic/memcmp.c | 329 + libc/string/generic/memcopy.h | 150 + libc/string/generic/memcpy.c | 62 + libc/string/generic/memmem.c | 54 + libc/string/generic/memmove.c | 291 + libc/string/generic/mempcpy.c | 20 + libc/string/generic/memrchr.c | 178 + libc/string/generic/memset.c | 86 + libc/string/generic/pagecopy.h | 75 + libc/string/generic/rawmemchr.c | 164 + libc/string/generic/strcat.c | 48 + libc/string/generic/strchr.c | 187 + libc/string/generic/strchrnul.c | 169 + libc/string/generic/strcmp.c | 50 + libc/string/generic/strcpy.c | 47 + libc/string/generic/strcspn.c | 38 + libc/string/generic/strlen.c | 152 + libc/string/generic/strncat.c | 77 + libc/string/generic/strncmp.c | 68 + libc/string/generic/strncpy.c | 82 + libc/string/generic/strnlen.c | 164 + libc/string/generic/strrchr.c | 48 + libc/string/generic/strsep.c | 71 + libc/string/generic/strspn.c | 43 + libc/string/generic/strstr.c | 114 + libc/string/generic/strtok_r.c | 72 + libc/string/i386/Makefile | 13 + libc/string/i386/memchr.c | 51 + libc/string/i386/memcpy.c | 53 + libc/string/i386/memmove.c | 59 + libc/string/i386/memset.c | 47 + libc/string/i386/strcat.c | 51 + libc/string/i386/strchr.c | 56 + libc/string/i386/strcmp.c | 61 + libc/string/i386/strcpy.c | 48 + libc/string/i386/strlen.c | 48 + libc/string/i386/strncat.c | 61 + libc/string/i386/strncmp.c | 58 + libc/string/i386/strncpy.c | 56 + libc/string/i386/strnlen.c | 56 + libc/string/i386/strrchr.c | 54 + libc/string/ia64/Makefile | 13 + libc/string/ia64/bcopy.S | 14 + libc/string/ia64/bzero.S | 320 + libc/string/ia64/memccpy.S | 213 + libc/string/ia64/memchr.S | 133 + libc/string/ia64/memcmp.S | 166 + libc/string/ia64/memcpy.S | 436 + libc/string/ia64/memmove.S | 251 + libc/string/ia64/memset.S | 400 + libc/string/ia64/softpipe.h | 29 + libc/string/ia64/strchr.S | 113 + libc/string/ia64/strcmp.S | 59 + libc/string/ia64/strcpy.S | 145 + libc/string/ia64/strlen.S | 98 + libc/string/ia64/strncmp.S | 62 + libc/string/ia64/strncpy.S | 232 + libc/string/ia64/sysdep.h | 168 + libc/string/memccpy.c | 21 + libc/string/memchr.c | 40 + libc/string/memcmp.c | 44 + libc/string/memcpy.c | 36 + libc/string/memmem.c | 42 + libc/string/memmove.c | 58 + libc/string/mempcpy.c | 40 + libc/string/memrchr.c | 38 + libc/string/memset.c | 38 + libc/string/mips/Makefile | 13 + libc/string/mips/memcpy.S | 257 + libc/string/mips/memset.S | 159 + libc/string/mips/sysdep.h | 45 + libc/string/powerpc/Makefile | 13 + libc/string/powerpc/memcpy.c | 82 + libc/string/powerpc/memmove.c | 78 + libc/string/powerpc/memset.c | 83 + libc/string/psignal.c | 32 + libc/string/rawmemchr.c | 21 + libc/string/sh/sh4/memcpy.S | 808 + libc/string/sh64/Makefile | 13 + libc/string/sh64/memcpy.S | 205 + libc/string/sh64/memset.S | 97 + libc/string/sh64/strcpy.S | 102 + libc/string/sh64/strlen.S | 63 + libc/string/sparc/Makefile | 13 + libc/string/sparc/_glibc_inc.h | 27 + libc/string/sparc/bcopy.c | 1 + libc/string/sparc/bzero.c | 1 + libc/string/sparc/memchr.S | 13 + libc/string/sparc/memcpy.S | 19 + libc/string/sparc/memmove.c | 1 + libc/string/sparc/memset.S | 13 + libc/string/sparc/sparc32/memchr.S | 144 + libc/string/sparc/sparc32/memcpy.S | 973 ++ libc/string/sparc/sparc32/memset.S | 157 + libc/string/sparc/sparc32/sparcv9b/memchr.S | 4 + libc/string/sparc/sparc32/sparcv9b/memcpy.S | 4 + libc/string/sparc/sparc32/sparcv9b/memset.S | 4 + libc/string/sparc/sparc32/sparcv9b/stpcpy.S | 4 + libc/string/sparc/sparc32/sparcv9b/strcat.S | 4 + libc/string/sparc/sparc32/sparcv9b/strchr.S | 4 + libc/string/sparc/sparc32/sparcv9b/strcmp.S | 4 + libc/string/sparc/sparc32/sparcv9b/strcpy.S | 4 + libc/string/sparc/sparc32/sparcv9b/strlen.S | 4 + libc/string/sparc/sparc32/stpcpy.S | 161 + libc/string/sparc/sparc32/strcat.S | 348 + libc/string/sparc/sparc32/strchr.S | 287 + libc/string/sparc/sparc32/strcmp.S | 256 + libc/string/sparc/sparc32/strcpy.S | 273 + libc/string/sparc/sparc32/strlen.S | 102 + libc/string/sparc/sparc64/memchr.S | 261 + libc/string/sparc/sparc64/memcpy.S | 923 ++ libc/string/sparc/sparc64/memset.S | 317 + libc/string/sparc/sparc64/sparcv9b/memcpy.S | 612 + libc/string/sparc/sparc64/stpcpy.S | 271 + libc/string/sparc/sparc64/strcat.S | 339 + libc/string/sparc/sparc64/strchr.S | 486 + libc/string/sparc/sparc64/strcmp.S | 279 + libc/string/sparc/sparc64/strcpy.S | 245 + libc/string/sparc/sparc64/strlen.S | 173 + libc/string/sparc/stpcpy.S | 13 + libc/string/sparc/strcat.S | 13 + libc/string/sparc/strchr.S | 13 + libc/string/sparc/strcmp.S | 18 + libc/string/sparc/strcpy.S | 13 + libc/string/sparc/strlen.S | 13 + libc/string/sparc/strrchr.c | 1 + libc/string/stpcpy.c | 32 + libc/string/stpncpy.c | 42 + libc/string/strcasecmp.c | 78 + libc/string/strcasecmp_l.c | 8 + libc/string/strcasestr.c | 57 + libc/string/strcat.c | 28 + libc/string/strchr.c | 32 + libc/string/strchrnul.c | 27 + libc/string/strcmp.c | 46 + libc/string/strcpy.c | 32 + libc/string/strcspn.c | 33 + libc/string/strdup.c | 37 + libc/string/strerror.c | 23 + libc/string/strlcat.c | 47 + libc/string/strlcpy.c | 63 + libc/string/strlen.c | 26 + libc/string/strncasecmp.c | 81 + libc/string/strncasecmp_l.c | 8 + libc/string/strncat.c | 39 + libc/string/strncmp.c | 42 + libc/string/strncpy.c | 39 + libc/string/strndup.c | 28 + libc/string/strnlen.c | 40 + libc/string/strpbrk.c | 30 + libc/string/strrchr.c | 35 + libc/string/strsep.c | 37 + libc/string/strsignal.c | 147 + libc/string/strspn.c | 31 + libc/string/strstr.c | 44 + libc/string/strtok.c | 25 + libc/string/strtok_r.c | 60 + libc/string/strxfrm.c | 9 + libc/string/strxfrm_l.c | 10 + libc/string/sys_errlist.c | 171 + libc/string/sys_siglist.c | 57 + libc/string/wcpcpy.c | 8 + libc/string/wcpncpy.c | 8 + libc/string/wcscasecmp.c | 8 + libc/string/wcscasecmp_l.c | 9 + libc/string/wcscat.c | 8 + libc/string/wcschr.c | 8 + libc/string/wcschrnul.c | 8 + libc/string/wcscmp.c | 8 + libc/string/wcscpy.c | 8 + libc/string/wcscspn.c | 8 + libc/string/wcsdup.c | 8 + libc/string/wcslcpy.c | 8 + libc/string/wcslen.c | 8 + libc/string/wcsncasecmp.c | 8 + libc/string/wcsncasecmp_l.c | 9 + libc/string/wcsncat.c | 8 + libc/string/wcsncmp.c | 8 + libc/string/wcsncpy.c | 8 + libc/string/wcsnlen.c | 8 + libc/string/wcspbrk.c | 8 + libc/string/wcsrchr.c | 8 + libc/string/wcsspn.c | 8 + libc/string/wcsstr.c | 8 + libc/string/wcstok.c | 8 + libc/string/wcsxfrm.c | 9 + libc/string/wcsxfrm_l.c | 10 + libc/string/wmemchr.c | 8 + libc/string/wmemcmp.c | 8 + libc/string/wmemcpy.c | 8 + libc/string/wmemmove.c | 8 + libc/string/wmempcpy.c | 8 + libc/string/wmemset.c | 8 + libc/string/x86_64/Makefile | 13 + libc/string/x86_64/_glibc_inc.h | 21 + libc/string/x86_64/bzero.S | 5 + libc/string/x86_64/memcpy.S | 98 + libc/string/x86_64/mempcpy.S | 3 + libc/string/x86_64/memset.S | 147 + libc/string/x86_64/stpcpy.S | 4 + libc/string/x86_64/strcat.S | 268 + libc/string/x86_64/strchr.S | 295 + libc/string/x86_64/strcmp.S | 47 + libc/string/x86_64/strcpy.S | 162 + libc/string/x86_64/strcspn.S | 137 + libc/string/x86_64/strlen.S | 144 + libc/string/x86_64/strpbrk.S | 3 + libc/string/x86_64/strspn.S | 124 + libc/string/xtensa/Makefile | 13 + libc/string/xtensa/memcpy.S | 297 + libc/string/xtensa/memset.S | 165 + libc/string/xtensa/strcmp.S | 314 + libc/string/xtensa/strcpy.S | 150 + libc/string/xtensa/strlen.S | 104 + libc/string/xtensa/strncpy.S | 241 + libc/sysdeps/Makefile | 13 + libc/sysdeps/Makefile.in | 8 + libc/sysdeps/README | 6 + libc/sysdeps/linux/Makefile | 13 + libc/sysdeps/linux/Makefile.commonarch | 42 + libc/sysdeps/linux/Makefile.in | 10 + libc/sysdeps/linux/README | 7 + libc/sysdeps/linux/alpha/Makefile | 13 + libc/sysdeps/linux/alpha/Makefile.arch | 15 + libc/sysdeps/linux/alpha/__longjmp.S | 57 + libc/sysdeps/linux/alpha/__syscall_error.c | 16 + .../linux/alpha/__syscall_rt_sigaction.S | 81 + libc/sysdeps/linux/alpha/bits/atomic.h | 369 + libc/sysdeps/linux/alpha/bits/dirent.h | 55 + libc/sysdeps/linux/alpha/bits/elfclass.h | 14 + libc/sysdeps/linux/alpha/bits/endian.h | 7 + libc/sysdeps/linux/alpha/bits/fcntl.h | 233 + libc/sysdeps/linux/alpha/bits/fenv.h | 123 + libc/sysdeps/linux/alpha/bits/ioctls.h | 37 + libc/sysdeps/linux/alpha/bits/ipc.h | 55 + .../linux/alpha/bits/kernel_sigaction.h | 23 + libc/sysdeps/linux/alpha/bits/kernel_stat.h | 52 + libc/sysdeps/linux/alpha/bits/kernel_types.h | 41 + libc/sysdeps/linux/alpha/bits/mathdef.h | 80 + libc/sysdeps/linux/alpha/bits/mathinline.h | 183 + libc/sysdeps/linux/alpha/bits/mman.h | 118 + libc/sysdeps/linux/alpha/bits/msq.h | 74 + libc/sysdeps/linux/alpha/bits/netdb.h | 35 + libc/sysdeps/linux/alpha/bits/resource.h | 225 + libc/sysdeps/linux/alpha/bits/sem.h | 85 + libc/sysdeps/linux/alpha/bits/setjmp.h | 87 + libc/sysdeps/linux/alpha/bits/shm.h | 101 + libc/sysdeps/linux/alpha/bits/sigaction.h | 74 + .../sysdeps/linux/alpha/bits/sigcontextinfo.h | 25 + libc/sysdeps/linux/alpha/bits/siginfo.h | 303 + libc/sysdeps/linux/alpha/bits/signum.h | 82 + libc/sysdeps/linux/alpha/bits/sigstack.h | 55 + libc/sysdeps/linux/alpha/bits/stackinfo.h | 28 + libc/sysdeps/linux/alpha/bits/stat.h | 151 + libc/sysdeps/linux/alpha/bits/statfs.h | 67 + libc/sysdeps/linux/alpha/bits/statvfs.h | 96 + libc/sysdeps/linux/alpha/bits/syscalls.h | 192 + libc/sysdeps/linux/alpha/bits/termios.h | 226 + libc/sysdeps/linux/alpha/bits/typesizes.h | 66 + .../linux/alpha/bits/uClibc_arch_features.h | 38 + .../sysdeps/linux/alpha/bits/uClibc_clk_tck.h | 8 + libc/sysdeps/linux/alpha/bits/uClibc_page.h | 28 + libc/sysdeps/linux/alpha/bits/wordsize.h | 30 + libc/sysdeps/linux/alpha/brk.S | 82 + libc/sysdeps/linux/alpha/bsd-_setjmp.S | 1 + libc/sysdeps/linux/alpha/bsd-setjmp.S | 1 + libc/sysdeps/linux/alpha/clone.S | 95 + libc/sysdeps/linux/alpha/crt1.S | 97 + libc/sysdeps/linux/alpha/crti.S | 43 + libc/sysdeps/linux/alpha/crtn.S | 30 + libc/sysdeps/linux/alpha/divl.S | 6 + libc/sysdeps/linux/alpha/divq.S | 6 + libc/sysdeps/linux/alpha/divrem.h | 198 + libc/sysdeps/linux/alpha/fpu_control.h | 108 + libc/sysdeps/linux/alpha/pipe.S | 48 + libc/sysdeps/linux/alpha/reml.S | 6 + libc/sysdeps/linux/alpha/remq.S | 6 + libc/sysdeps/linux/alpha/setjmp.S | 91 + libc/sysdeps/linux/alpha/sigprocmask.c | 61 + libc/sysdeps/linux/alpha/sys/acct.h | 66 + libc/sysdeps/linux/alpha/sys/io.h | 95 + libc/sysdeps/linux/alpha/sys/procfs.h | 115 + libc/sysdeps/linux/alpha/sys/regdef.h | 47 + libc/sysdeps/linux/alpha/sys/ucontext.h | 61 + libc/sysdeps/linux/alpha/sys/user.h | 50 + libc/sysdeps/linux/alpha/syscall.S | 71 + libc/sysdeps/linux/arm/Makefile | 13 + libc/sysdeps/linux/arm/Makefile.arch | 35 + libc/sysdeps/linux/arm/__longjmp.S | 114 + libc/sysdeps/linux/arm/__syscall_error.c | 18 + libc/sysdeps/linux/arm/aeabi_assert.c | 30 + libc/sysdeps/linux/arm/aeabi_atexit.c | 31 + libc/sysdeps/linux/arm/aeabi_errno_addr.c | 25 + libc/sysdeps/linux/arm/aeabi_lcsts.c | 84 + libc/sysdeps/linux/arm/aeabi_localeconv.c | 27 + libc/sysdeps/linux/arm/aeabi_math.c | 42 + libc/sysdeps/linux/arm/aeabi_mb_cur_max.c | 35 + libc/sysdeps/linux/arm/aeabi_memclr.c | 33 + libc/sysdeps/linux/arm/aeabi_memcpy.c | 34 + libc/sysdeps/linux/arm/aeabi_memmove.c | 34 + libc/sysdeps/linux/arm/aeabi_memset.c | 33 + libc/sysdeps/linux/arm/aeabi_sighandlers.S | 52 + libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c | 43 + libc/sysdeps/linux/arm/bits/arm_asm.h | 28 + libc/sysdeps/linux/arm/bits/armsigctx.h | 73 + libc/sysdeps/linux/arm/bits/endian.h | 19 + libc/sysdeps/linux/arm/bits/fcntl.h | 240 + libc/sysdeps/linux/arm/bits/fenv.h | 99 + libc/sysdeps/linux/arm/bits/huge_val.h | 72 + libc/sysdeps/linux/arm/bits/kernel_stat.h | 76 + libc/sysdeps/linux/arm/bits/kernel_types.h | 44 + libc/sysdeps/linux/arm/bits/mathdef.h | 36 + libc/sysdeps/linux/arm/bits/mman.h | 103 + libc/sysdeps/linux/arm/bits/setjmp.h | 52 + libc/sysdeps/linux/arm/bits/shm.h | 103 + libc/sysdeps/linux/arm/bits/sigcontextinfo.h | 51 + libc/sysdeps/linux/arm/bits/stackinfo.h | 28 + libc/sysdeps/linux/arm/bits/syscalls.h | 203 + .../linux/arm/bits/uClibc_arch_features.h | 42 + libc/sysdeps/linux/arm/bits/wordsize.h | 19 + libc/sysdeps/linux/arm/brk.c | 42 + libc/sysdeps/linux/arm/bsd-_setjmp.S | 61 + libc/sysdeps/linux/arm/bsd-setjmp.S | 61 + libc/sysdeps/linux/arm/clone.S | 125 + libc/sysdeps/linux/arm/crt1.S | 254 + libc/sysdeps/linux/arm/crti.S | 87 + libc/sysdeps/linux/arm/crtn.S | 35 + libc/sysdeps/linux/arm/find_exidx.c | 80 + libc/sysdeps/linux/arm/fpu_control.h | 203 + libc/sysdeps/linux/arm/ioperm.c | 258 + libc/sysdeps/linux/arm/iopl.c | 37 + libc/sysdeps/linux/arm/mmap.c | 74 + libc/sysdeps/linux/arm/mmap64.S | 142 + libc/sysdeps/linux/arm/posix_fadvise.c | 36 + libc/sysdeps/linux/arm/posix_fadvise64.c | 46 + libc/sysdeps/linux/arm/setjmp.S | 101 + libc/sysdeps/linux/arm/sigaction.c | 126 + libc/sysdeps/linux/arm/sigrestorer.S | 89 + libc/sysdeps/linux/arm/sys/elf.h | 26 + libc/sysdeps/linux/arm/sys/io.h | 48 + libc/sysdeps/linux/arm/sys/procfs.h | 123 + libc/sysdeps/linux/arm/sys/ucontext.h | 97 + libc/sysdeps/linux/arm/sys/user.h | 72 + libc/sysdeps/linux/arm/syscall-eabi.S | 73 + libc/sysdeps/linux/arm/syscall.c | 53 + libc/sysdeps/linux/arm/vfork.S | 95 + libc/sysdeps/linux/avr32/Makefile | 25 + libc/sysdeps/linux/avr32/Makefile.arch | 13 + libc/sysdeps/linux/avr32/__longjmp.S | 21 + libc/sysdeps/linux/avr32/bits/atomic.h | 120 + libc/sysdeps/linux/avr32/bits/byteswap.h | 70 + libc/sysdeps/linux/avr32/bits/endian.h | 7 + libc/sysdeps/linux/avr32/bits/fcntl.h | 214 + libc/sysdeps/linux/avr32/bits/kernel_stat.h | 67 + libc/sysdeps/linux/avr32/bits/kernel_types.h | 55 + libc/sysdeps/linux/avr32/bits/mman.h | 103 + libc/sysdeps/linux/avr32/bits/setjmp.h | 30 + libc/sysdeps/linux/avr32/bits/stackinfo.h | 28 + libc/sysdeps/linux/avr32/bits/syscalls.h | 143 + .../linux/avr32/bits/uClibc_arch_features.h | 42 + libc/sysdeps/linux/avr32/bits/wordsize.h | 1 + libc/sysdeps/linux/avr32/brk.c | 31 + libc/sysdeps/linux/avr32/bsd-_setjmp.S | 16 + libc/sysdeps/linux/avr32/bsd-setjmp.S | 16 + libc/sysdeps/linux/avr32/clone.c | 42 + libc/sysdeps/linux/avr32/crt1.S | 97 + libc/sysdeps/linux/avr32/crti.S | 26 + libc/sysdeps/linux/avr32/crtn.S | 14 + libc/sysdeps/linux/avr32/mmap.c | 33 + libc/sysdeps/linux/avr32/setjmp.S | 29 + libc/sysdeps/linux/avr32/sigaction.c | 61 + libc/sysdeps/linux/avr32/sigrestorer.S | 15 + libc/sysdeps/linux/avr32/sys/elf.h | 26 + libc/sysdeps/linux/avr32/sys/procfs.h | 123 + libc/sysdeps/linux/avr32/sys/ucontext.h | 90 + libc/sysdeps/linux/avr32/sys/user.h | 46 + libc/sysdeps/linux/avr32/syscall.S | 71 + libc/sysdeps/linux/avr32/vfork.S | 58 + libc/sysdeps/linux/bfin/Makefile | 13 + libc/sysdeps/linux/bfin/Makefile.arch | 15 + libc/sysdeps/linux/bfin/__longjmp.S | 107 + libc/sysdeps/linux/bfin/bfin_l1layout.h | 17 + libc/sysdeps/linux/bfin/bfin_sram.h | 30 + libc/sysdeps/linux/bfin/bits/byteswap.h | 94 + libc/sysdeps/linux/bfin/bits/elf-fdpic.h | 115 + libc/sysdeps/linux/bfin/bits/endian.h | 7 + libc/sysdeps/linux/bfin/bits/fcntl.h | 237 + libc/sysdeps/linux/bfin/bits/huge_val.h | 56 + libc/sysdeps/linux/bfin/bits/kernel_stat.h | 59 + libc/sysdeps/linux/bfin/bits/kernel_types.h | 44 + libc/sysdeps/linux/bfin/bits/mman.h | 96 + libc/sysdeps/linux/bfin/bits/setjmp.h | 57 + libc/sysdeps/linux/bfin/bits/sigcontextinfo.h | 26 + libc/sysdeps/linux/bfin/bits/stackinfo.h | 28 + libc/sysdeps/linux/bfin/bits/syscalls.h | 138 + libc/sysdeps/linux/bfin/bits/typesizes.h | 66 + .../linux/bfin/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/bfin/bits/wordsize.h | 19 + libc/sysdeps/linux/bfin/brk.c | 36 + libc/sysdeps/linux/bfin/bsd-_setjmp.S | 97 + libc/sysdeps/linux/bfin/bsdsetjmp.c | 103 + libc/sysdeps/linux/bfin/clone.c | 59 + libc/sysdeps/linux/bfin/crt1.S | 167 + libc/sysdeps/linux/bfin/crti.S | 62 + libc/sysdeps/linux/bfin/crtn.S | 53 + libc/sysdeps/linux/bfin/crtreloc.c | 145 + libc/sysdeps/linux/bfin/dma-memcpy.c | 6 + libc/sysdeps/linux/bfin/setjmp.S | 96 + libc/sysdeps/linux/bfin/sram-alloc.c | 6 + libc/sysdeps/linux/bfin/sram-free.c | 6 + libc/sysdeps/linux/bfin/sys/elf.h | 26 + libc/sysdeps/linux/bfin/sys/io.h | 48 + libc/sysdeps/linux/bfin/sys/procfs.h | 125 + libc/sysdeps/linux/bfin/sys/reg.h | 133 + libc/sysdeps/linux/bfin/sys/ucontext.h | 152 + libc/sysdeps/linux/bfin/syscall.c | 57 + libc/sysdeps/linux/bfin/sysdep.h | 20 + libc/sysdeps/linux/bfin/vfork.S | 20 + libc/sysdeps/linux/common/.indent.pro | 33 + libc/sysdeps/linux/common/Makefile | 13 + libc/sysdeps/linux/common/Makefile.in | 102 + libc/sysdeps/linux/common/__rt_sigtimedwait.c | 54 + libc/sysdeps/linux/common/__socketcall.c | 15 + libc/sysdeps/linux/common/__syscall_fcntl.c | 59 + libc/sysdeps/linux/common/__syscall_fcntl64.c | 36 + .../linux/common/__syscall_rt_sigaction.c | 20 + .../linux/common/__syscall_sigaction.c | 19 + libc/sysdeps/linux/common/_exit.c | 30 + libc/sysdeps/linux/common/access.c | 12 + libc/sysdeps/linux/common/acct.c | 14 + libc/sysdeps/linux/common/adjtimex.c | 19 + libc/sysdeps/linux/common/alarm.c | 42 + libc/sysdeps/linux/common/arch_prctl.c | 15 + libc/sysdeps/linux/common/bdflush.c | 21 + libc/sysdeps/linux/common/bits/atomic.h | 43 + libc/sysdeps/linux/common/bits/byteswap.h | 87 + libc/sysdeps/linux/common/bits/cmathcalls.h | 181 + libc/sysdeps/linux/common/bits/confname.h | 606 + libc/sysdeps/linux/common/bits/dirent.h | 53 + libc/sysdeps/linux/common/bits/dlfcn.h | 67 + libc/sysdeps/linux/common/bits/elfclass.h | 14 + libc/sysdeps/linux/common/bits/endian.h | 18 + libc/sysdeps/linux/common/bits/environments.h | 78 + libc/sysdeps/linux/common/bits/errno.h | 59 + libc/sysdeps/linux/common/bits/fcntl.h | 3 + libc/sysdeps/linux/common/bits/fenv.h | 56 + libc/sysdeps/linux/common/bits/fenvinline.h | 8 + libc/sysdeps/linux/common/bits/getopt.h | 181 + libc/sysdeps/linux/common/bits/huge_val.h | 55 + libc/sysdeps/linux/common/bits/huge_valf.h | 53 + libc/sysdeps/linux/common/bits/huge_vall.h | 29 + libc/sysdeps/linux/common/bits/in.h | 170 + libc/sysdeps/linux/common/bits/inf.h | 30 + libc/sysdeps/linux/common/bits/initspin.h | 28 + libc/sysdeps/linux/common/bits/ioctl-types.h | 78 + libc/sysdeps/linux/common/bits/ioctls.h | 109 + libc/sysdeps/linux/common/bits/ipc.h | 56 + .../linux/common/bits/kernel_sigaction.h | 68 + libc/sysdeps/linux/common/bits/kernel_stat.h | 2 + libc/sysdeps/linux/common/bits/kernel_types.h | 20 + libc/sysdeps/linux/common/bits/local_lim.h | 87 + libc/sysdeps/linux/common/bits/locale.h | 46 + libc/sysdeps/linux/common/bits/mathcalls.h | 444 + libc/sysdeps/linux/common/bits/mathdef.h | 37 + libc/sysdeps/linux/common/bits/mathinline.h | 12 + libc/sysdeps/linux/common/bits/mman.h | 97 + libc/sysdeps/linux/common/bits/mqueue.h | 32 + libc/sysdeps/linux/common/bits/msq.h | 77 + libc/sysdeps/linux/common/bits/nan.h | 53 + libc/sysdeps/linux/common/bits/netdb.h | 33 + libc/sysdeps/linux/common/bits/poll.h | 50 + libc/sysdeps/linux/common/bits/posix1_lim.h | 169 + libc/sysdeps/linux/common/bits/posix2_lim.h | 91 + libc/sysdeps/linux/common/bits/posix_opt.h | 180 + libc/sysdeps/linux/common/bits/resource.h | 225 + libc/sysdeps/linux/common/bits/sched.h | 132 + libc/sysdeps/linux/common/bits/select.h | 35 + libc/sysdeps/linux/common/bits/sem.h | 87 + libc/sysdeps/linux/common/bits/setjmp.h | 2 + libc/sysdeps/linux/common/bits/shm.h | 103 + libc/sysdeps/linux/common/bits/sigaction.h | 77 + libc/sysdeps/linux/common/bits/sigcontext.h | 29 + .../linux/common/bits/sigcontextinfo.h | 27 + libc/sysdeps/linux/common/bits/siginfo.h | 313 + libc/sysdeps/linux/common/bits/signum.h | 80 + libc/sysdeps/linux/common/bits/sigset.h | 125 + libc/sysdeps/linux/common/bits/sigstack.h | 55 + libc/sysdeps/linux/common/bits/sigthread.h | 38 + libc/sysdeps/linux/common/bits/sockaddr.h | 40 + libc/sysdeps/linux/common/bits/socket.h | 333 + libc/sysdeps/linux/common/bits/stab.def | 234 + libc/sysdeps/linux/common/bits/stackinfo.h | 34 + libc/sysdeps/linux/common/bits/stat.h | 165 + libc/sysdeps/linux/common/bits/statfs.h | 67 + libc/sysdeps/linux/common/bits/statvfs.h | 107 + libc/sysdeps/linux/common/bits/stdio.h | 23 + libc/sysdeps/linux/common/bits/stdio_lim.h | 41 + libc/sysdeps/linux/common/bits/syscalls.h | 8 + libc/sysdeps/linux/common/bits/termios.h | 219 + libc/sysdeps/linux/common/bits/time.h | 79 + libc/sysdeps/linux/common/bits/types.h | 209 + libc/sysdeps/linux/common/bits/typesizes.h | 66 + .../linux/common/bits/uClibc_arch_features.h | 44 + .../linux/common/bits/uClibc_clk_tck.h | 8 + libc/sysdeps/linux/common/bits/uClibc_ctype.h | 279 + libc/sysdeps/linux/common/bits/uClibc_errno.h | 43 + libc/sysdeps/linux/common/bits/uClibc_fpmax.h | 122 + .../linux/common/bits/uClibc_local_lim.h | 33 + .../sysdeps/linux/common/bits/uClibc_locale.h | 380 + libc/sysdeps/linux/common/bits/uClibc_mutex.h | 88 + libc/sysdeps/linux/common/bits/uClibc_page.h | 29 + .../linux/common/bits/uClibc_pthread.h | 50 + libc/sysdeps/linux/common/bits/uClibc_stdio.h | 517 + .../linux/common/bits/uClibc_touplow.h | 55 + .../linux/common/bits/uClibc_uintmaxtostr.h | 116 + .../sysdeps/linux/common/bits/uClibc_uwchar.h | 57 + .../linux/common/bits/uClibc_va_copy.h | 40 + libc/sysdeps/linux/common/bits/uio.h | 50 + libc/sysdeps/linux/common/bits/ustat.h | 31 + libc/sysdeps/linux/common/bits/utmp.h | 125 + libc/sysdeps/linux/common/bits/utmpx.h | 103 + libc/sysdeps/linux/common/bits/utsname.h | 29 + libc/sysdeps/linux/common/bits/waitflags.h | 38 + libc/sysdeps/linux/common/bits/waitstatus.h | 106 + libc/sysdeps/linux/common/bits/wchar.h | 26 + libc/sysdeps/linux/common/bits/wordsize.h | 6 + libc/sysdeps/linux/common/bits/xopen_lim.h | 150 + libc/sysdeps/linux/common/capget.c | 20 + libc/sysdeps/linux/common/capset.c | 20 + libc/sysdeps/linux/common/chdir.c | 23 + libc/sysdeps/linux/common/chmod.c | 22 + libc/sysdeps/linux/common/chown.c | 41 + libc/sysdeps/linux/common/chroot.c | 23 + libc/sysdeps/linux/common/clock_getres.c | 44 + libc/sysdeps/linux/common/clock_gettime.c | 40 + libc/sysdeps/linux/common/clock_settime.c | 42 + libc/sysdeps/linux/common/close.c | 18 + libc/sysdeps/linux/common/cmsg_nxthdr.c | 43 + libc/sysdeps/linux/common/creat64.c | 35 + libc/sysdeps/linux/common/create_module.c | 59 + libc/sysdeps/linux/common/delete_module.c | 19 + libc/sysdeps/linux/common/dl-osinfo.h | 69 + libc/sysdeps/linux/common/dup.c | 11 + libc/sysdeps/linux/common/dup2.c | 16 + libc/sysdeps/linux/common/epoll.c | 50 + libc/sysdeps/linux/common/execve.c | 18 + libc/sysdeps/linux/common/fchdir.c | 16 + libc/sysdeps/linux/common/fchmod.c | 20 + libc/sysdeps/linux/common/fchown.c | 38 + libc/sysdeps/linux/common/fdatasync.c | 17 + libc/sysdeps/linux/common/flock.c | 19 + libc/sysdeps/linux/common/fork.c | 36 + libc/sysdeps/linux/common/fpu_control.h | 41 + libc/sysdeps/linux/common/fstat.c | 44 + libc/sysdeps/linux/common/fstat64.c | 35 + libc/sysdeps/linux/common/fstatfs.c | 35 + libc/sysdeps/linux/common/fsync.c | 16 + libc/sysdeps/linux/common/ftruncate.c | 16 + libc/sysdeps/linux/common/ftruncate64.c | 85 + libc/sysdeps/linux/common/get_kernel_syms.c | 22 + libc/sysdeps/linux/common/getcwd.c | 208 + libc/sysdeps/linux/common/getdents.c | 166 + libc/sysdeps/linux/common/getdents64.c | 105 + libc/sysdeps/linux/common/getdirname.c | 67 + libc/sysdeps/linux/common/getdomainname.c | 57 + libc/sysdeps/linux/common/getdtablesize.c | 32 + libc/sysdeps/linux/common/getegid.c | 35 + libc/sysdeps/linux/common/geteuid.c | 36 + libc/sysdeps/linux/common/getgid.c | 24 + libc/sysdeps/linux/common/getgroups.c | 62 + libc/sysdeps/linux/common/gethostname.c | 37 + libc/sysdeps/linux/common/getitimer.c | 12 + libc/sysdeps/linux/common/getpagesize.c | 48 + libc/sysdeps/linux/common/getpgid.c | 22 + libc/sysdeps/linux/common/getpgrp.c | 16 + libc/sysdeps/linux/common/getpid.c | 21 + libc/sysdeps/linux/common/getppid.c | 20 + libc/sysdeps/linux/common/getpriority.c | 31 + libc/sysdeps/linux/common/getresgid.c | 38 + libc/sysdeps/linux/common/getresuid.c | 38 + libc/sysdeps/linux/common/getrlimit.c | 68 + libc/sysdeps/linux/common/getrlimit64.c | 51 + libc/sysdeps/linux/common/getrusage.c | 13 + libc/sysdeps/linux/common/getsid.c | 24 + libc/sysdeps/linux/common/gettimeofday.c | 19 + libc/sysdeps/linux/common/getuid.c | 24 + libc/sysdeps/linux/common/hp-timing.h | 83 + libc/sysdeps/linux/common/init_module.c | 25 + libc/sysdeps/linux/common/inotify.c | 24 + libc/sysdeps/linux/common/ioctl.c | 31 + libc/sysdeps/linux/common/ioperm.c | 15 + libc/sysdeps/linux/common/iopl.c | 15 + libc/sysdeps/linux/common/kill.c | 22 + libc/sysdeps/linux/common/klogctl.c | 18 + libc/sysdeps/linux/common/lchown.c | 38 + libc/sysdeps/linux/common/link.c | 12 + libc/sysdeps/linux/common/llseek.c | 43 + libc/sysdeps/linux/common/longjmp.c | 51 + libc/sysdeps/linux/common/lseek.c | 31 + libc/sysdeps/linux/common/lstat.c | 45 + libc/sysdeps/linux/common/lstat64.c | 36 + libc/sysdeps/linux/common/madvise.c | 14 + libc/sysdeps/linux/common/mincore.c | 15 + libc/sysdeps/linux/common/mkdir.c | 23 + libc/sysdeps/linux/common/mkfifo.c | 31 + libc/sysdeps/linux/common/mknod.c | 28 + libc/sysdeps/linux/common/mlock.c | 14 + libc/sysdeps/linux/common/mlockall.c | 14 + libc/sysdeps/linux/common/mmap.c | 73 + libc/sysdeps/linux/common/mmap64.c | 73 + libc/sysdeps/linux/common/modify_ldt.c | 15 + libc/sysdeps/linux/common/mount.c | 14 + libc/sysdeps/linux/common/mprotect.c | 15 + libc/sysdeps/linux/common/mremap.c | 26 + libc/sysdeps/linux/common/msync.c | 22 + libc/sysdeps/linux/common/munlock.c | 14 + libc/sysdeps/linux/common/munlockall.c | 16 + libc/sysdeps/linux/common/munmap.c | 17 + libc/sysdeps/linux/common/nanosleep.c | 22 + libc/sysdeps/linux/common/nice.c | 77 + libc/sysdeps/linux/common/noophooks.c | 29 + libc/sysdeps/linux/common/ntp_gettime.c | 34 + libc/sysdeps/linux/common/open.c | 48 + libc/sysdeps/linux/common/open64.c | 43 + libc/sysdeps/linux/common/pause.c | 28 + libc/sysdeps/linux/common/personality.c | 12 + libc/sysdeps/linux/common/pipe.c | 16 + libc/sysdeps/linux/common/pivot_root.c | 21 + libc/sysdeps/linux/common/poll.c | 234 + libc/sysdeps/linux/common/posix_fadvise.c | 62 + libc/sysdeps/linux/common/posix_fadvise64.c | 105 + libc/sysdeps/linux/common/ppoll.c | 50 + libc/sysdeps/linux/common/prctl.c | 17 + libc/sysdeps/linux/common/pread_write.c | 191 + libc/sysdeps/linux/common/pselect.c | 69 + libc/sysdeps/linux/common/ptrace.c | 43 + libc/sysdeps/linux/common/query_module.c | 23 + libc/sysdeps/linux/common/quotactl.c | 16 + libc/sysdeps/linux/common/read.c | 18 + libc/sysdeps/linux/common/readahead.c | 58 + libc/sysdeps/linux/common/readlink.c | 15 + libc/sysdeps/linux/common/readv.c | 18 + libc/sysdeps/linux/common/reboot.c | 17 + libc/sysdeps/linux/common/remap_file_pages.c | 16 + libc/sysdeps/linux/common/rename.c | 24 + libc/sysdeps/linux/common/rmdir.c | 16 + libc/sysdeps/linux/common/sbrk.c | 36 + .../linux/common/sched_get_priority_max.c | 12 + .../linux/common/sched_get_priority_min.c | 12 + libc/sysdeps/linux/common/sched_getaffinity.c | 54 + libc/sysdeps/linux/common/sched_getparam.c | 21 + .../sysdeps/linux/common/sched_getscheduler.c | 20 + .../linux/common/sched_rr_get_interval.c | 21 + libc/sysdeps/linux/common/sched_setaffinity.c | 92 + libc/sysdeps/linux/common/sched_setparam.c | 21 + .../sysdeps/linux/common/sched_setscheduler.c | 21 + libc/sysdeps/linux/common/sched_yield.c | 12 + libc/sysdeps/linux/common/select.c | 47 + libc/sysdeps/linux/common/sendfile.c | 29 + libc/sysdeps/linux/common/sendfile64.c | 24 + libc/sysdeps/linux/common/setdomainname.c | 14 + libc/sysdeps/linux/common/setegid.c | 38 + libc/sysdeps/linux/common/seteuid.c | 46 + libc/sysdeps/linux/common/setfsgid.c | 35 + libc/sysdeps/linux/common/setfsuid.c | 35 + libc/sysdeps/linux/common/setgid.c | 35 + libc/sysdeps/linux/common/setgroups.c | 66 + libc/sysdeps/linux/common/sethostname.c | 14 + libc/sysdeps/linux/common/setitimer.c | 17 + libc/sysdeps/linux/common/setpgid.c | 26 + libc/sysdeps/linux/common/setpgrp.c | 15 + libc/sysdeps/linux/common/setpriority.c | 16 + libc/sysdeps/linux/common/setregid.c | 41 + libc/sysdeps/linux/common/setresgid.c | 43 + libc/sysdeps/linux/common/setresuid.c | 43 + libc/sysdeps/linux/common/setreuid.c | 41 + libc/sysdeps/linux/common/setrlimit.c | 70 + libc/sysdeps/linux/common/setrlimit64.c | 49 + libc/sysdeps/linux/common/setsid.c | 16 + libc/sysdeps/linux/common/settimeofday.c | 20 + libc/sysdeps/linux/common/setuid.c | 35 + libc/sysdeps/linux/common/sigaltstack.c | 17 + libc/sysdeps/linux/common/signalfd.c | 41 + libc/sysdeps/linux/common/sigpending.c | 27 + libc/sysdeps/linux/common/sigprocmask.c | 73 + libc/sysdeps/linux/common/sigqueue.c | 55 + libc/sysdeps/linux/common/sigsuspend.c | 38 + libc/sysdeps/linux/common/splice.c | 28 + libc/sysdeps/linux/common/ssp-local.c | 35 + libc/sysdeps/linux/common/ssp.c | 130 + libc/sysdeps/linux/common/stat.c | 46 + libc/sysdeps/linux/common/stat64.c | 35 + libc/sysdeps/linux/common/statfs.c | 25 + libc/sysdeps/linux/common/stime.c | 33 + libc/sysdeps/linux/common/swapoff.c | 17 + libc/sysdeps/linux/common/swapon.c | 17 + libc/sysdeps/linux/common/symlink.c | 14 + libc/sysdeps/linux/common/sync.c | 25 + libc/sysdeps/linux/common/sync_file_range.c | 33 + libc/sysdeps/linux/common/sys/acct.h | 77 + libc/sysdeps/linux/common/sys/epoll.h | 110 + libc/sysdeps/linux/common/sys/inotify.h | 92 + libc/sysdeps/linux/common/sys/prctl.h | 32 + libc/sysdeps/linux/common/sys/ptrace.h | 129 + libc/sysdeps/linux/common/sys/user.h | 1 + libc/sysdeps/linux/common/syscalls.h | 24 + libc/sysdeps/linux/common/sysctl.c | 44 + libc/sysdeps/linux/common/sysfs.c | 17 + libc/sysdeps/linux/common/sysinfo.c | 12 + libc/sysdeps/linux/common/tee.c | 16 + libc/sysdeps/linux/common/time.c | 37 + libc/sysdeps/linux/common/times.c | 16 + libc/sysdeps/linux/common/truncate.c | 16 + libc/sysdeps/linux/common/truncate64.c | 82 + libc/sysdeps/linux/common/ulimit.c | 59 + libc/sysdeps/linux/common/umask.c | 19 + libc/sysdeps/linux/common/umount.c | 41 + libc/sysdeps/linux/common/umount2.c | 23 + libc/sysdeps/linux/common/uname.c | 16 + libc/sysdeps/linux/common/unlink.c | 16 + libc/sysdeps/linux/common/uselib.c | 18 + libc/sysdeps/linux/common/ustat.c | 25 + libc/sysdeps/linux/common/utime.c | 37 + libc/sysdeps/linux/common/utimes.c | 38 + libc/sysdeps/linux/common/vfork.c | 27 + libc/sysdeps/linux/common/vhangup.c | 14 + libc/sysdeps/linux/common/vmsplice.c | 28 + libc/sysdeps/linux/common/wait.c | 23 + libc/sysdeps/linux/common/wait3.c | 25 + libc/sysdeps/linux/common/wait4.c | 26 + libc/sysdeps/linux/common/waitid.c | 51 + libc/sysdeps/linux/common/waitpid.c | 22 + libc/sysdeps/linux/common/write.c | 23 + libc/sysdeps/linux/common/writev.c | 18 + libc/sysdeps/linux/common/xattr.c | 164 + libc/sysdeps/linux/common/xstatconv.c | 83 + libc/sysdeps/linux/common/xstatconv.h | 32 + libc/sysdeps/linux/cris/Makefile | 13 + libc/sysdeps/linux/cris/Makefile.arch | 15 + libc/sysdeps/linux/cris/__init_brk.c | 32 + libc/sysdeps/linux/cris/__longjmp.S | 62 + libc/sysdeps/linux/cris/bits/byteswap.h | 83 + libc/sysdeps/linux/cris/bits/endian.h | 7 + libc/sysdeps/linux/cris/bits/fcntl.h | 238 + libc/sysdeps/linux/cris/bits/kernel_stat.h | 84 + libc/sysdeps/linux/cris/bits/kernel_types.h | 46 + libc/sysdeps/linux/cris/bits/mman.h | 98 + libc/sysdeps/linux/cris/bits/setjmp.h | 66 + libc/sysdeps/linux/cris/bits/stackinfo.h | 28 + libc/sysdeps/linux/cris/bits/syscalls.h | 159 + libc/sysdeps/linux/cris/bits/termios.h | 215 + .../linux/cris/bits/uClibc_arch_features.h | 42 + libc/sysdeps/linux/cris/bits/uClibc_page.h | 34 + libc/sysdeps/linux/cris/bits/wordsize.h | 19 + libc/sysdeps/linux/cris/brk.c | 38 + libc/sysdeps/linux/cris/clone.S | 96 + libc/sysdeps/linux/cris/crt1.S | 56 + libc/sysdeps/linux/cris/crti.S | 37 + libc/sysdeps/linux/cris/crtn.S | 23 + libc/sysdeps/linux/cris/fork.c | 19 + libc/sysdeps/linux/cris/libc.map | 3 + libc/sysdeps/linux/cris/sbrk.c | 42 + libc/sysdeps/linux/cris/setjmp.S | 84 + libc/sysdeps/linux/cris/sys/procfs.h | 115 + libc/sysdeps/linux/cris/sys/ucontext.h | 95 + libc/sysdeps/linux/cris/syscall.S | 61 + libc/sysdeps/linux/cris/sysdep.S | 80 + libc/sysdeps/linux/cris/sysdep.h | 149 + libc/sysdeps/linux/e1/Makefile | 56 + libc/sysdeps/linux/e1/bits/endian.h | 7 + libc/sysdeps/linux/e1/bits/fcntl.h | 234 + libc/sysdeps/linux/e1/bits/fenv.h | 88 + libc/sysdeps/linux/e1/bits/fenvinline.h | 298 + libc/sysdeps/linux/e1/bits/kernel_stat.h | 60 + libc/sysdeps/linux/e1/bits/kernel_types.h | 46 + libc/sysdeps/linux/e1/bits/mman.h | 76 + libc/sysdeps/linux/e1/bits/proto.h | 5 + libc/sysdeps/linux/e1/bits/setjmp.h | 22 + libc/sysdeps/linux/e1/bits/syscalls.h | 17 + .../linux/e1/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/e1/bits/unistd.h | 464 + libc/sysdeps/linux/e1/bits/wordsize.h | 22 + libc/sysdeps/linux/e1/crt0.S | 17 + libc/sysdeps/linux/e1/crt1.c | 48 + libc/sysdeps/linux/e1/longjmp.c | 77 + libc/sysdeps/linux/e1/setjmp.c | 56 + libc/sysdeps/linux/e1/sys/procfs.h | 31 + libc/sysdeps/linux/e1/sys/reg.h | 25 + libc/sysdeps/linux/e1/sys/ucontext.h | 109 + libc/sysdeps/linux/e1/syscalls.c | 11 + libc/sysdeps/linux/e1/vfork.c | 15 + libc/sysdeps/linux/frv/Makefile | 58 + libc/sysdeps/linux/frv/__init_brk.c | 26 + libc/sysdeps/linux/frv/__longjmp.S | 83 + libc/sysdeps/linux/frv/bits/elf-fdpic.h | 115 + libc/sysdeps/linux/frv/bits/endian.h | 7 + libc/sysdeps/linux/frv/bits/fcntl.h | 216 + libc/sysdeps/linux/frv/bits/kernel_stat.h | 88 + libc/sysdeps/linux/frv/bits/kernel_types.h | 43 + libc/sysdeps/linux/frv/bits/mman.h | 76 + libc/sysdeps/linux/frv/bits/setjmp.h | 58 + libc/sysdeps/linux/frv/bits/stackinfo.h | 28 + libc/sysdeps/linux/frv/bits/stat.h | 154 + libc/sysdeps/linux/frv/bits/syscalls.h | 139 + .../linux/frv/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/frv/bits/uClibc_page.h | 32 + libc/sysdeps/linux/frv/bits/wordsize.h | 19 + libc/sysdeps/linux/frv/brk.c | 28 + libc/sysdeps/linux/frv/clone.S | 83 + libc/sysdeps/linux/frv/crt0.S | 125 + libc/sysdeps/linux/frv/crti.S | 50 + libc/sysdeps/linux/frv/crtn.S | 44 + libc/sysdeps/linux/frv/crtreloc.c | 120 + libc/sysdeps/linux/frv/dl-iterate-phdr.c | 42 + libc/sysdeps/linux/frv/fstat.c | 18 + libc/sysdeps/linux/frv/fstat64.c | 20 + libc/sysdeps/linux/frv/lstat.c | 18 + libc/sysdeps/linux/frv/lstat64.c | 20 + libc/sysdeps/linux/frv/mmap.c | 51 + libc/sysdeps/linux/frv/sbrk.c | 26 + libc/sysdeps/linux/frv/setjmp.S | 90 + libc/sysdeps/linux/frv/stat.c | 18 + libc/sysdeps/linux/frv/stat64.c | 20 + libc/sysdeps/linux/frv/sys/procfs.h | 125 + libc/sysdeps/linux/frv/sys/ptrace.h | 139 + libc/sysdeps/linux/frv/sys/ucontext.h | 451 + libc/sysdeps/linux/frv/syscall.c | 41 + libc/sysdeps/linux/frv/sysdep.c | 27 + libc/sysdeps/linux/frv/vfork.S | 47 + libc/sysdeps/linux/frv/xstatconv.c | 1 + libc/sysdeps/linux/h8300/Makefile | 65 + libc/sysdeps/linux/h8300/__longjmp.S | 22 + libc/sysdeps/linux/h8300/bits/byteswap.h | 67 + libc/sysdeps/linux/h8300/bits/endian.h | 7 + libc/sysdeps/linux/h8300/bits/fcntl.h | 234 + libc/sysdeps/linux/h8300/bits/kernel_stat.h | 61 + libc/sysdeps/linux/h8300/bits/kernel_types.h | 44 + libc/sysdeps/linux/h8300/bits/mman.h | 76 + libc/sysdeps/linux/h8300/bits/setjmp.h | 32 + .../sysdeps/linux/h8300/bits/sigcontextinfo.h | 26 + libc/sysdeps/linux/h8300/bits/stackinfo.h | 28 + libc/sysdeps/linux/h8300/bits/syscalls.h | 151 + .../linux/h8300/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/h8300/bits/wordsize.h | 1 + libc/sysdeps/linux/h8300/brk.c | 38 + libc/sysdeps/linux/h8300/bsd-_setjmp.S | 27 + libc/sysdeps/linux/h8300/bsd-setjmp.S | 30 + libc/sysdeps/linux/h8300/clone.S | 68 + libc/sysdeps/linux/h8300/crt0.S | 70 + libc/sysdeps/linux/h8300/crti.S | 30 + libc/sysdeps/linux/h8300/crtn.S | 30 + libc/sysdeps/linux/h8300/float.h | 96 + libc/sysdeps/linux/h8300/ptrace.c | 36 + libc/sysdeps/linux/h8300/setjmp.S | 23 + libc/sysdeps/linux/h8300/sys/procfs.h | 126 + libc/sysdeps/linux/h8300/sys/ucontext.h | 75 + libc/sysdeps/linux/h8300/vfork.S | 41 + libc/sysdeps/linux/hppa/Makefile | 13 + libc/sysdeps/linux/hppa/Makefile.arch | 13 + libc/sysdeps/linux/hppa/__longjmp.S | 74 + libc/sysdeps/linux/hppa/__syscall_error.c | 18 + libc/sysdeps/linux/hppa/add_n.s | 58 + libc/sysdeps/linux/hppa/bits/endian.h | 7 + libc/sysdeps/linux/hppa/bits/fcntl.h | 228 + libc/sysdeps/linux/hppa/bits/fenv.h | 78 + libc/sysdeps/linux/hppa/bits/ipc.h | 63 + .../linux/hppa/bits/kernel_sigaction.h | 26 + libc/sysdeps/linux/hppa/bits/kernel_stat.h | 72 + libc/sysdeps/linux/hppa/bits/kernel_types.h | 61 + libc/sysdeps/linux/hppa/bits/mman.h | 92 + libc/sysdeps/linux/hppa/bits/setjmp.h | 45 + libc/sysdeps/linux/hppa/bits/sigaction.h | 75 + libc/sysdeps/linux/hppa/bits/signum.h | 82 + libc/sysdeps/linux/hppa/bits/stackinfo.h | 28 + libc/sysdeps/linux/hppa/bits/syscalls.h | 155 + .../linux/hppa/bits/uClibc_arch_features.h | 41 + libc/sysdeps/linux/hppa/bits/wordsize.h | 7 + libc/sysdeps/linux/hppa/brk.c | 43 + libc/sysdeps/linux/hppa/bsd-_setjmp.S | 36 + libc/sysdeps/linux/hppa/bsd-setjmp.S | 36 + libc/sysdeps/linux/hppa/clone.S | 135 + libc/sysdeps/linux/hppa/crt1.S | 126 + libc/sysdeps/linux/hppa/crti.S | 24 + libc/sysdeps/linux/hppa/crtn.S | 34 + libc/sysdeps/linux/hppa/lshift.s | 66 + libc/sysdeps/linux/hppa/mmap.c | 20 + libc/sysdeps/linux/hppa/rshift.s | 63 + libc/sysdeps/linux/hppa/setjmp.S | 63 + libc/sysdeps/linux/hppa/sub_n.s | 59 + libc/sysdeps/linux/hppa/sys/procfs.h | 113 + libc/sysdeps/linux/hppa/sys/ucontext.h | 67 + libc/sysdeps/linux/hppa/syscall.c | 65 + libc/sysdeps/linux/hppa/udiv_qrnnd.s | 286 + libc/sysdeps/linux/i386/Makefile | 13 + libc/sysdeps/linux/i386/Makefile.arch | 14 + libc/sysdeps/linux/i386/__longjmp.S | 42 + libc/sysdeps/linux/i386/__syscall_error.c | 36 + libc/sysdeps/linux/i386/bits/atomic.h | 369 + libc/sysdeps/linux/i386/bits/byteswap.h | 133 + libc/sysdeps/linux/i386/bits/endian.h | 7 + libc/sysdeps/linux/i386/bits/fcntl.h | 241 + libc/sysdeps/linux/i386/bits/fenv.h | 90 + libc/sysdeps/linux/i386/bits/kernel_stat.h | 60 + libc/sysdeps/linux/i386/bits/kernel_types.h | 48 + libc/sysdeps/linux/i386/bits/mathdef.h | 46 + libc/sysdeps/linux/i386/bits/mathinline.h | 755 + libc/sysdeps/linux/i386/bits/mman.h | 103 + libc/sysdeps/linux/i386/bits/select.h | 72 + libc/sysdeps/linux/i386/bits/setjmp.h | 46 + libc/sysdeps/linux/i386/bits/sigcontextinfo.h | 51 + libc/sysdeps/linux/i386/bits/stackinfo.h | 28 + libc/sysdeps/linux/i386/bits/syscalls.h | 211 + .../linux/i386/bits/uClibc_arch_features.h | 46 + libc/sysdeps/linux/i386/bits/wchar.h | 26 + libc/sysdeps/linux/i386/bits/wordsize.h | 25 + libc/sysdeps/linux/i386/brk.c | 49 + libc/sysdeps/linux/i386/bsd-_setjmp.S | 46 + libc/sysdeps/linux/i386/bsd-setjmp.S | 60 + libc/sysdeps/linux/i386/clone.S | 123 + libc/sysdeps/linux/i386/crt1.S | 140 + libc/sysdeps/linux/i386/crti.S | 31 + libc/sysdeps/linux/i386/crtn.S | 29 + libc/sysdeps/linux/i386/fpu_control.h | 104 + libc/sysdeps/linux/i386/mmap.S | 51 + libc/sysdeps/linux/i386/mmap64.S | 93 + libc/sysdeps/linux/i386/posix_fadvise64.S | 100 + libc/sysdeps/linux/i386/setjmp.S | 58 + libc/sysdeps/linux/i386/sigaction.c | 172 + libc/sysdeps/linux/i386/sync_file_range.S | 67 + libc/sysdeps/linux/i386/sys/debugreg.h | 91 + libc/sysdeps/linux/i386/sys/elf.h | 26 + libc/sysdeps/linux/i386/sys/io.h | 183 + libc/sysdeps/linux/i386/sys/perm.h | 36 + libc/sysdeps/linux/i386/sys/procfs.h | 131 + libc/sysdeps/linux/i386/sys/reg.h | 43 + libc/sysdeps/linux/i386/sys/ucontext.h | 129 + libc/sysdeps/linux/i386/sys/user.h | 101 + libc/sysdeps/linux/i386/sys/vm86.h | 34 + libc/sysdeps/linux/i386/syscall.S | 50 + libc/sysdeps/linux/i386/vfork.S | 31 + libc/sysdeps/linux/i960/AUTHORS | 4 + libc/sysdeps/linux/i960/Makefile | 55 + libc/sysdeps/linux/i960/README | 71 + libc/sysdeps/linux/i960/bits/endian.h | 15 + libc/sysdeps/linux/i960/bits/fcntl.h | 234 + libc/sysdeps/linux/i960/bits/mman.h | 94 + libc/sysdeps/linux/i960/bits/setjmp.h | 38 + libc/sysdeps/linux/i960/bits/syscalls.h | 15 + .../linux/i960/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/i960/bits/wordsize.h | 19 + libc/sysdeps/linux/i960/clone.S | 62 + libc/sysdeps/linux/i960/crt0.S | 58 + libc/sysdeps/linux/i960/mmap.S | 52 + libc/sysdeps/linux/i960/setjmp.S | 124 + .../specs.uclinux.gcc-2.95.i960-intel-coff | 64 + libc/sysdeps/linux/i960/sys/procfs.h | 126 + libc/sysdeps/linux/i960/sys/ucontext.h | 76 + libc/sysdeps/linux/i960/vfork.S | 33 + libc/sysdeps/linux/ia64/Makefile | 15 + libc/sysdeps/linux/ia64/Makefile.arch | 14 + libc/sysdeps/linux/ia64/__longjmp.S | 162 + libc/sysdeps/linux/ia64/__syscall_error.c | 19 + libc/sysdeps/linux/ia64/bits/atomic.h | 119 + libc/sysdeps/linux/ia64/bits/byteswap.h | 110 + libc/sysdeps/linux/ia64/bits/endian.h | 7 + libc/sysdeps/linux/ia64/bits/fcntl.h | 235 + libc/sysdeps/linux/ia64/bits/fenv.h | 87 + libc/sysdeps/linux/ia64/bits/ipc.h | 54 + libc/sysdeps/linux/ia64/bits/kernel_stat.h | 61 + libc/sysdeps/linux/ia64/bits/kernel_types.h | 56 + libc/sysdeps/linux/ia64/bits/mathdef.h | 37 + libc/sysdeps/linux/ia64/bits/mathinline.h | 54 + libc/sysdeps/linux/ia64/bits/mman.h | 104 + libc/sysdeps/linux/ia64/bits/msq.h | 69 + libc/sysdeps/linux/ia64/bits/sem.h | 87 + libc/sysdeps/linux/ia64/bits/setjmp.h | 40 + libc/sysdeps/linux/ia64/bits/shm.h | 94 + libc/sysdeps/linux/ia64/bits/sigaction.h | 73 + libc/sysdeps/linux/ia64/bits/sigcontext.h | 79 + libc/sysdeps/linux/ia64/bits/siginfo.h | 339 + libc/sysdeps/linux/ia64/bits/sigstack.h | 63 + libc/sysdeps/linux/ia64/bits/stackinfo.h | 29 + libc/sysdeps/linux/ia64/bits/stat.h | 140 + libc/sysdeps/linux/ia64/bits/syscalls.h | 192 + .../linux/ia64/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/ia64/bits/wordsize.h | 19 + libc/sysdeps/linux/ia64/brk.S | 52 + libc/sysdeps/linux/ia64/bsd-_setjmp.S | 1 + libc/sysdeps/linux/ia64/bsd-setjmp.S | 1 + libc/sysdeps/linux/ia64/clone2.S | 107 + libc/sysdeps/linux/ia64/crt1.S | 129 + libc/sysdeps/linux/ia64/crti.S | 36 + libc/sysdeps/linux/ia64/crtn.S | 33 + libc/sysdeps/linux/ia64/fork.S | 42 + libc/sysdeps/linux/ia64/pipe.S | 37 + libc/sysdeps/linux/ia64/setjmp.S | 189 + libc/sysdeps/linux/ia64/sys/io.h | 68 + libc/sysdeps/linux/ia64/sys/procfs.h | 130 + libc/sysdeps/linux/ia64/sys/ptrace.h | 135 + libc/sysdeps/linux/ia64/sys/ucontext.h | 66 + libc/sysdeps/linux/ia64/sys/user.h | 54 + libc/sysdeps/linux/ia64/syscall.S | 30 + libc/sysdeps/linux/ia64/sysdep.h | 168 + libc/sysdeps/linux/ia64/vfork.S | 44 + libc/sysdeps/linux/m68k/Makefile | 13 + libc/sysdeps/linux/m68k/Makefile.arch | 12 + libc/sysdeps/linux/m68k/README.m68k | 54 + libc/sysdeps/linux/m68k/__longjmp.S | 26 + libc/sysdeps/linux/m68k/__syscall_error.c | 19 + libc/sysdeps/linux/m68k/bits/byteswap.h | 67 + libc/sysdeps/linux/m68k/bits/endian.h | 7 + libc/sysdeps/linux/m68k/bits/fcntl.h | 237 + libc/sysdeps/linux/m68k/bits/fenv.h | 79 + libc/sysdeps/linux/m68k/bits/kernel_stat.h | 62 + libc/sysdeps/linux/m68k/bits/kernel_types.h | 44 + libc/sysdeps/linux/m68k/bits/mathdef.h | 38 + libc/sysdeps/linux/m68k/bits/mathinline.h | 445 + libc/sysdeps/linux/m68k/bits/mman.h | 102 + libc/sysdeps/linux/m68k/bits/poll.h | 43 + libc/sysdeps/linux/m68k/bits/setjmp.h | 68 + libc/sysdeps/linux/m68k/bits/sigcontextinfo.h | 26 + libc/sysdeps/linux/m68k/bits/stackinfo.h | 28 + libc/sysdeps/linux/m68k/bits/stat.h | 164 + libc/sysdeps/linux/m68k/bits/syscalls.h | 199 + .../linux/m68k/bits/uClibc_arch_features.h | 45 + libc/sysdeps/linux/m68k/bits/uClibc_page.h | 41 + libc/sysdeps/linux/m68k/bits/wordsize.h | 19 + libc/sysdeps/linux/m68k/brk.c | 38 + libc/sysdeps/linux/m68k/bsd-_setjmp.S | 24 + libc/sysdeps/linux/m68k/bsd-setjmp.S | 23 + libc/sysdeps/linux/m68k/clone.S | 69 + libc/sysdeps/linux/m68k/crt1.S | 152 + libc/sysdeps/linux/m68k/crti.S | 17 + libc/sysdeps/linux/m68k/crtn.S | 11 + libc/sysdeps/linux/m68k/float.h | 96 + libc/sysdeps/linux/m68k/fpu_control.h | 103 + libc/sysdeps/linux/m68k/m68k_pic.S | 64 + libc/sysdeps/linux/m68k/setjmp.S | 23 + libc/sysdeps/linux/m68k/sys/procfs.h | 126 + libc/sysdeps/linux/m68k/sys/reg.h | 89 + libc/sysdeps/linux/m68k/sys/ucontext.h | 109 + libc/sysdeps/linux/m68k/sys/user.h | 90 + libc/sysdeps/linux/m68k/syscall.c | 47 + libc/sysdeps/linux/m68k/vfork.S | 45 + libc/sysdeps/linux/microblaze/Makefile | 67 + libc/sysdeps/linux/microblaze/__longjmp.S | 45 + libc/sysdeps/linux/microblaze/bits/byteswap.h | 41 + libc/sysdeps/linux/microblaze/bits/endian.h | 20 + libc/sysdeps/linux/microblaze/bits/fcntl.h | 234 + .../linux/microblaze/bits/kernel_stat.h | 66 + .../linux/microblaze/bits/kernel_types.h | 55 + libc/sysdeps/linux/microblaze/bits/mman.h | 99 + libc/sysdeps/linux/microblaze/bits/poll.h | 43 + libc/sysdeps/linux/microblaze/bits/select.h | 58 + libc/sysdeps/linux/microblaze/bits/setjmp.h | 43 + libc/sysdeps/linux/microblaze/bits/syscalls.h | 15 + .../microblaze/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/microblaze/bits/wordsize.h | 19 + libc/sysdeps/linux/microblaze/clinkage.h | 15 + libc/sysdeps/linux/microblaze/clone.c | 52 + libc/sysdeps/linux/microblaze/crt0.S | 56 + libc/sysdeps/linux/microblaze/mmap.c | 17 + libc/sysdeps/linux/microblaze/setjmp.S | 53 + libc/sysdeps/linux/microblaze/sys/ptrace.h | 94 + libc/sysdeps/linux/microblaze/sys/ucontext.h | 41 + libc/sysdeps/linux/microblaze/syscall.c | 51 + libc/sysdeps/linux/microblaze/vfork.S | 44 + libc/sysdeps/linux/mips/Makefile | 13 + libc/sysdeps/linux/mips/Makefile.arch | 18 + libc/sysdeps/linux/mips/__longjmp.c | 128 + libc/sysdeps/linux/mips/__syscall_error.c | 18 + libc/sysdeps/linux/mips/_test_and_set.c | 30 + libc/sysdeps/linux/mips/bits/atomic.h | 303 + libc/sysdeps/linux/mips/bits/dirent.h | 61 + libc/sysdeps/linux/mips/bits/dlfcn.h | 66 + libc/sysdeps/linux/mips/bits/endian.h | 16 + libc/sysdeps/linux/mips/bits/fcntl.h | 261 + libc/sysdeps/linux/mips/bits/fenv.h | 77 + libc/sysdeps/linux/mips/bits/ioctl-types.h | 76 + libc/sysdeps/linux/mips/bits/ipc.h | 55 + .../linux/mips/bits/kernel_sigaction.h | 48 + libc/sysdeps/linux/mips/bits/kernel_stat.h | 112 + libc/sysdeps/linux/mips/bits/kernel_types.h | 79 + libc/sysdeps/linux/mips/bits/mathdef.h | 46 + libc/sysdeps/linux/mips/bits/mman.h | 106 + libc/sysdeps/linux/mips/bits/msq.h | 93 + libc/sysdeps/linux/mips/bits/poll.h | 50 + libc/sysdeps/linux/mips/bits/resource.h | 233 + libc/sysdeps/linux/mips/bits/sem.h | 85 + libc/sysdeps/linux/mips/bits/setjmp.h | 72 + libc/sysdeps/linux/mips/bits/shm.h | 94 + libc/sysdeps/linux/mips/bits/sigaction.h | 89 + libc/sysdeps/linux/mips/bits/sigcontext.h | 84 + libc/sysdeps/linux/mips/bits/sigcontextinfo.h | 43 + libc/sysdeps/linux/mips/bits/siginfo.h | 311 + libc/sysdeps/linux/mips/bits/signum.h | 79 + libc/sysdeps/linux/mips/bits/sigstack.h | 55 + libc/sysdeps/linux/mips/bits/socket.h | 334 + libc/sysdeps/linux/mips/bits/stackinfo.h | 28 + libc/sysdeps/linux/mips/bits/stat.h | 203 + libc/sysdeps/linux/mips/bits/statfs.h | 72 + libc/sysdeps/linux/mips/bits/syscalls.h | 393 + libc/sysdeps/linux/mips/bits/termios.h | 217 + .../linux/mips/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/mips/bits/uClibc_page.h | 35 + libc/sysdeps/linux/mips/bits/wordsize.h | 19 + libc/sysdeps/linux/mips/brk.c | 52 + libc/sysdeps/linux/mips/bsd-_setjmp.S | 56 + libc/sysdeps/linux/mips/bsd-setjmp.S | 56 + libc/sysdeps/linux/mips/cacheflush.c | 30 + libc/sysdeps/linux/mips/clone.S | 127 + libc/sysdeps/linux/mips/crt1.S | 148 + libc/sysdeps/linux/mips/crti.S | 158 + libc/sysdeps/linux/mips/crtn.S | 145 + libc/sysdeps/linux/mips/fpu_control.h | 100 + libc/sysdeps/linux/mips/mmap.c | 27 + libc/sysdeps/linux/mips/pipe.S | 45 + libc/sysdeps/linux/mips/posix_fadvise.c | 39 + libc/sysdeps/linux/mips/posix_fadvise64.c | 43 + libc/sysdeps/linux/mips/pread_write.c | 115 + libc/sysdeps/linux/mips/readahead.c | 41 + libc/sysdeps/linux/mips/setjmp.S | 61 + libc/sysdeps/linux/mips/setjmp_aux.c | 108 + libc/sysdeps/linux/mips/sgidefs.h | 73 + libc/sysdeps/linux/mips/sigaction.c | 158 + libc/sysdeps/linux/mips/sys/asm.h | 473 + libc/sysdeps/linux/mips/sys/cachectl.h | 42 + libc/sysdeps/linux/mips/sys/fpregdef.h | 61 + libc/sysdeps/linux/mips/sys/procfs.h | 112 + libc/sysdeps/linux/mips/sys/regdef.h | 80 + libc/sysdeps/linux/mips/sys/sysmips.h | 44 + libc/sysdeps/linux/mips/sys/tas.h | 67 + libc/sysdeps/linux/mips/sys/ucontext.h | 117 + libc/sysdeps/linux/mips/sys/user.h | 217 + libc/sysdeps/linux/mips/syscall.S | 80 + libc/sysdeps/linux/mips/sysmips.c | 7 + libc/sysdeps/linux/nios/Makefile | 13 + libc/sysdeps/linux/nios/Makefile.arch | 14 + libc/sysdeps/linux/nios/NM_Macros.S | 473 + libc/sysdeps/linux/nios/NR_Math1.S | 63 + libc/sysdeps/linux/nios/__longjmp.S | 103 + libc/sysdeps/linux/nios/bits/endian.h | 8 + libc/sysdeps/linux/nios/bits/fcntl.h | 237 + libc/sysdeps/linux/nios/bits/kernel_types.h | 43 + libc/sysdeps/linux/nios/bits/mathdef.h | 36 + libc/sysdeps/linux/nios/bits/mman.h | 76 + libc/sysdeps/linux/nios/bits/setjmp.h | 76 + libc/sysdeps/linux/nios/bits/sigcontextinfo.h | 27 + libc/sysdeps/linux/nios/bits/stackinfo.h | 28 + libc/sysdeps/linux/nios/bits/stat.h | 134 + libc/sysdeps/linux/nios/bits/syscalls.h | 13 + .../linux/nios/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/nios/bits/wordsize.h | 19 + libc/sysdeps/linux/nios/brk.c | 45 + libc/sysdeps/linux/nios/bsd-_setjmp.S | 1 + libc/sysdeps/linux/nios/bsd-setjmp.S | 1 + libc/sysdeps/linux/nios/clone.S | 88 + libc/sysdeps/linux/nios/crt1.S | 59 + libc/sysdeps/linux/nios/crtbegin.c | 37 + libc/sysdeps/linux/nios/crtend.c | 44 + libc/sysdeps/linux/nios/fpu_control.h | 99 + libc/sysdeps/linux/nios/setjmp.S | 102 + libc/sysdeps/linux/nios/sys/procfs.h | 123 + libc/sysdeps/linux/nios/sys/ucontext.h | 104 + libc/sysdeps/linux/nios/vfork.S | 54 + libc/sysdeps/linux/nios2/Makefile | 13 + libc/sysdeps/linux/nios2/Makefile.arch | 14 + libc/sysdeps/linux/nios2/__longjmp.S | 50 + libc/sysdeps/linux/nios2/bits/endian.h | 7 + libc/sysdeps/linux/nios2/bits/fcntl.h | 237 + libc/sysdeps/linux/nios2/bits/kernel_stat.h | 60 + libc/sysdeps/linux/nios2/bits/kernel_types.h | 44 + libc/sysdeps/linux/nios2/bits/mathdef.h | 36 + libc/sysdeps/linux/nios2/bits/mman.h | 85 + libc/sysdeps/linux/nios2/bits/setjmp.h | 72 + .../sysdeps/linux/nios2/bits/sigcontextinfo.h | 26 + libc/sysdeps/linux/nios2/bits/stackinfo.h | 28 + libc/sysdeps/linux/nios2/bits/stat.h | 134 + libc/sysdeps/linux/nios2/bits/syscalls.h | 295 + .../linux/nios2/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/nios2/bits/uClibc_page.h | 29 + libc/sysdeps/linux/nios2/bits/wordsize.h | 19 + libc/sysdeps/linux/nios2/brk.c | 46 + libc/sysdeps/linux/nios2/bsd-_setjmp.S | 45 + libc/sysdeps/linux/nios2/bsd-setjmp.S | 52 + libc/sysdeps/linux/nios2/clone.S | 70 + libc/sysdeps/linux/nios2/clone.c | 50 + libc/sysdeps/linux/nios2/crt1.S | 73 + libc/sysdeps/linux/nios2/crti.S | 22 + libc/sysdeps/linux/nios2/crtn.S | 14 + libc/sysdeps/linux/nios2/fpu_control.h | 99 + libc/sysdeps/linux/nios2/setjmp.S | 51 + libc/sysdeps/linux/nios2/sys/procfs.h | 123 + libc/sysdeps/linux/nios2/sys/ucontext.h | 104 + libc/sysdeps/linux/nios2/syscall.c | 47 + libc/sysdeps/linux/nios2/vfork.S | 56 + libc/sysdeps/linux/powerpc/Makefile | 13 + libc/sysdeps/linux/powerpc/Makefile.arch | 18 + libc/sysdeps/linux/powerpc/README.bits | 14 + libc/sysdeps/linux/powerpc/__longjmp.S | 94 + libc/sysdeps/linux/powerpc/__syscall_error.c | 18 + libc/sysdeps/linux/powerpc/__uClibc_syscall.S | 12 + libc/sysdeps/linux/powerpc/bits/atomic.h | 607 + libc/sysdeps/linux/powerpc/bits/endian.h | 37 + libc/sysdeps/linux/powerpc/bits/fcntl.h | 241 + libc/sysdeps/linux/powerpc/bits/fenv.h | 168 + libc/sysdeps/linux/powerpc/bits/fenvinline.h | 64 + libc/sysdeps/linux/powerpc/bits/ioctl-types.h | 5 + libc/sysdeps/linux/powerpc/bits/ipc.h | 62 + libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 59 + .../sysdeps/linux/powerpc/bits/kernel_types.h | 72 + libc/sysdeps/linux/powerpc/bits/mathdef.h | 75 + libc/sysdeps/linux/powerpc/bits/mathinline.h | 185 + libc/sysdeps/linux/powerpc/bits/mman.h | 104 + libc/sysdeps/linux/powerpc/bits/msq.h | 83 + libc/sysdeps/linux/powerpc/bits/sem.h | 92 + libc/sysdeps/linux/powerpc/bits/setjmp.h | 80 + libc/sysdeps/linux/powerpc/bits/shm.h | 113 + .../linux/powerpc/bits/sigcontextinfo.h | 27 + libc/sysdeps/linux/powerpc/bits/stackinfo.h | 28 + libc/sysdeps/linux/powerpc/bits/stat.h | 267 + libc/sysdeps/linux/powerpc/bits/syscalls.h | 322 + libc/sysdeps/linux/powerpc/bits/sysdep.h | 301 + libc/sysdeps/linux/powerpc/bits/termios.h | 319 + .../linux/powerpc/bits/uClibc_arch_features.h | 42 + libc/sysdeps/linux/powerpc/bits/wordsize.h | 19 + libc/sysdeps/linux/powerpc/brk.S | 80 + libc/sysdeps/linux/powerpc/bsd-_setjmp.S | 35 + libc/sysdeps/linux/powerpc/bsd-setjmp.S | 38 + libc/sysdeps/linux/powerpc/clone.S | 98 + libc/sysdeps/linux/powerpc/crt1.S | 107 + libc/sysdeps/linux/powerpc/crti.S | 24 + libc/sysdeps/linux/powerpc/crtn.S | 23 + libc/sysdeps/linux/powerpc/fenv.h | 136 + libc/sysdeps/linux/powerpc/fpu_control.h | 94 + libc/sysdeps/linux/powerpc/ioctl.c | 74 + libc/sysdeps/linux/powerpc/ppc_asm.h | 137 + libc/sysdeps/linux/powerpc/pread_write.c | 183 + libc/sysdeps/linux/powerpc/setjmp.S | 92 + libc/sysdeps/linux/powerpc/sys/procfs.h | 140 + libc/sysdeps/linux/powerpc/sys/ptrace.h | 99 + libc/sysdeps/linux/powerpc/sys/ucontext.h | 177 + libc/sysdeps/linux/powerpc/sys/user.h | 40 + libc/sysdeps/linux/powerpc/syscall.S | 38 + libc/sysdeps/linux/powerpc/vfork.S | 29 + libc/sysdeps/linux/sh/Makefile | 13 + libc/sysdeps/linux/sh/Makefile.arch | 14 + libc/sysdeps/linux/sh/___fpscr_values.S | 34 + libc/sysdeps/linux/sh/__init_brk.c | 26 + libc/sysdeps/linux/sh/__longjmp.S | 65 + libc/sysdeps/linux/sh/bits/atomic.h | 419 + libc/sysdeps/linux/sh/bits/endian.h | 13 + libc/sysdeps/linux/sh/bits/fcntl.h | 241 + libc/sysdeps/linux/sh/bits/fenv.h | 72 + libc/sysdeps/linux/sh/bits/huge_val.h | 56 + libc/sysdeps/linux/sh/bits/kernel_stat.h | 89 + libc/sysdeps/linux/sh/bits/kernel_types.h | 44 + libc/sysdeps/linux/sh/bits/mathdef.h | 63 + libc/sysdeps/linux/sh/bits/mman.h | 103 + libc/sysdeps/linux/sh/bits/setjmp.h | 56 + libc/sysdeps/linux/sh/bits/shm.h | 109 + libc/sysdeps/linux/sh/bits/sigcontextinfo.h | 27 + libc/sysdeps/linux/sh/bits/stackinfo.h | 28 + libc/sysdeps/linux/sh/bits/syscalls.h | 291 + .../linux/sh/bits/uClibc_arch_features.h | 45 + libc/sysdeps/linux/sh/bits/wordsize.h | 19 + libc/sysdeps/linux/sh/brk.c | 28 + libc/sysdeps/linux/sh/clone.S | 125 + libc/sysdeps/linux/sh/crt1.S | 97 + libc/sysdeps/linux/sh/crti.S | 32 + libc/sysdeps/linux/sh/crtn.S | 36 + libc/sysdeps/linux/sh/fpu_control.h | 60 + libc/sysdeps/linux/sh/mmap.c | 35 + libc/sysdeps/linux/sh/pipe.c | 40 + libc/sysdeps/linux/sh/pread_write.c | 83 + libc/sysdeps/linux/sh/sbrk.c | 26 + libc/sysdeps/linux/sh/setjmp.S | 102 + libc/sysdeps/linux/sh/sys/io.h | 48 + libc/sysdeps/linux/sh/sys/procfs.h | 126 + libc/sysdeps/linux/sh/sys/ucontext.h | 121 + libc/sysdeps/linux/sh/sys/user.h | 78 + libc/sysdeps/linux/sh/syscall.c | 27 + libc/sysdeps/linux/sh/syscall_error.S | 37 + libc/sysdeps/linux/sh/vfork.S | 114 + libc/sysdeps/linux/sh64/Makefile | 15 + libc/sysdeps/linux/sh64/Makefile.arch | 12 + libc/sysdeps/linux/sh64/__init_brk.c | 26 + libc/sysdeps/linux/sh64/__longjmp.S | 141 + libc/sysdeps/linux/sh64/bits/endian.h | 20 + libc/sysdeps/linux/sh64/bits/fcntl.h | 216 + libc/sysdeps/linux/sh64/bits/kernel_stat.h | 67 + libc/sysdeps/linux/sh64/bits/kernel_types.h | 56 + libc/sysdeps/linux/sh64/bits/mman.h | 97 + libc/sysdeps/linux/sh64/bits/setjmp.h | 50 + libc/sysdeps/linux/sh64/bits/shm.h | 103 + libc/sysdeps/linux/sh64/bits/stackinfo.h | 28 + libc/sysdeps/linux/sh64/bits/syscalls.h | 126 + .../linux/sh64/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/sh64/bits/wordsize.h | 12 + libc/sysdeps/linux/sh64/brk.c | 28 + libc/sysdeps/linux/sh64/crt1.S | 83 + libc/sysdeps/linux/sh64/crti.S | 42 + libc/sysdeps/linux/sh64/crtn.S | 33 + libc/sysdeps/linux/sh64/sbrk.c | 26 + libc/sysdeps/linux/sh64/setjmp.S | 140 + libc/sysdeps/linux/sh64/sys/procfs.h | 126 + libc/sysdeps/linux/sh64/sys/ucontext.h | 205 + libc/sysdeps/linux/sh64/syscall.c | 24 + libc/sysdeps/linux/sparc/Makefile | 13 + libc/sysdeps/linux/sparc/Makefile.arch | 14 + libc/sysdeps/linux/sparc/__longjmp.S | 89 + libc/sysdeps/linux/sparc/__syscall_error.c | 18 + libc/sysdeps/linux/sparc/_math_inc.h | 32 + libc/sysdeps/linux/sparc/bits/endian.h | 12 + libc/sysdeps/linux/sparc/bits/fcntl.h | 260 + libc/sysdeps/linux/sparc/bits/fenv.h | 85 + libc/sysdeps/linux/sparc/bits/ioctls.h | 37 + libc/sysdeps/linux/sparc/bits/ipc.h | 62 + libc/sysdeps/linux/sparc/bits/kernel_stat.h | 60 + libc/sysdeps/linux/sparc/bits/kernel_types.h | 76 + libc/sysdeps/linux/sparc/bits/mathdef.h | 69 + libc/sysdeps/linux/sparc/bits/mathinline.h | 292 + libc/sysdeps/linux/sparc/bits/mman.h | 106 + libc/sysdeps/linux/sparc/bits/msq.h | 84 + libc/sysdeps/linux/sparc/bits/poll.h | 50 + libc/sysdeps/linux/sparc/bits/resource.h | 241 + libc/sysdeps/linux/sparc/bits/sem.h | 92 + libc/sysdeps/linux/sparc/bits/setjmp.h | 84 + libc/sysdeps/linux/sparc/bits/shm.h | 111 + libc/sysdeps/linux/sparc/bits/sigaction.h | 76 + libc/sysdeps/linux/sparc/bits/sigcontext.h | 78 + .../sysdeps/linux/sparc/bits/sigcontextinfo.h | 29 + libc/sysdeps/linux/sparc/bits/siginfo.h | 318 + libc/sysdeps/linux/sparc/bits/signum.h | 84 + libc/sysdeps/linux/sparc/bits/sigstack.h | 55 + libc/sysdeps/linux/sparc/bits/stackinfo.h | 28 + libc/sysdeps/linux/sparc/bits/stat.h | 165 + libc/sysdeps/linux/sparc/bits/statvfs.h | 106 + libc/sysdeps/linux/sparc/bits/syscalls.h | 155 + libc/sysdeps/linux/sparc/bits/termios.h | 233 + libc/sysdeps/linux/sparc/bits/typesizes.h | 66 + .../linux/sparc/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/sparc/bits/wordsize.h | 20 + libc/sysdeps/linux/sparc/brk.c | 50 + libc/sysdeps/linux/sparc/bsd-_setjmp.S | 1 + libc/sysdeps/linux/sparc/bsd-setjmp.S | 1 + libc/sysdeps/linux/sparc/clone.S | 66 + libc/sysdeps/linux/sparc/crt1.S | 134 + libc/sysdeps/linux/sparc/crti.S | 23 + libc/sysdeps/linux/sparc/crtn.S | 19 + libc/sysdeps/linux/sparc/fork.S | 49 + libc/sysdeps/linux/sparc/fpu_control.h | 75 + libc/sysdeps/linux/sparc/qp_ops.c | 46 + libc/sysdeps/linux/sparc/rem.S | 9 + libc/sysdeps/linux/sparc/sdiv.S | 9 + libc/sysdeps/linux/sparc/setjmp.S | 70 + libc/sysdeps/linux/sparc/sparcv7/rem.S | 360 + libc/sysdeps/linux/sparc/sparcv7/sdiv.S | 360 + libc/sysdeps/linux/sparc/sparcv7/udiv.S | 343 + libc/sysdeps/linux/sparc/sparcv7/umul.S | 153 + libc/sysdeps/linux/sparc/sparcv7/urem.S | 343 + libc/sysdeps/linux/sparc/sparcv8/rem.S | 19 + libc/sysdeps/linux/sparc/sparcv8/sdiv.S | 18 + libc/sysdeps/linux/sparc/sparcv8/udiv.S | 13 + libc/sysdeps/linux/sparc/sparcv8/umul.S | 11 + libc/sysdeps/linux/sparc/sparcv8/urem.S | 16 + libc/sysdeps/linux/sparc/sparcv9/rem.S | 20 + libc/sysdeps/linux/sparc/sparcv9/sdiv.S | 18 + libc/sysdeps/linux/sparc/sparcv9/udiv.S | 15 + libc/sysdeps/linux/sparc/sparcv9/umul.S | 15 + libc/sysdeps/linux/sparc/sparcv9/urem.S | 17 + libc/sysdeps/linux/sparc/sys/procfs.h | 211 + libc/sysdeps/linux/sparc/sys/ptrace.h | 183 + libc/sysdeps/linux/sparc/sys/ucontext.h | 270 + libc/sysdeps/linux/sparc/sys/user.h | 85 + libc/sysdeps/linux/sparc/syscall.S | 50 + libc/sysdeps/linux/sparc/udiv.S | 9 + libc/sysdeps/linux/sparc/umul.S | 9 + libc/sysdeps/linux/sparc/urem.S | 9 + libc/sysdeps/linux/sparc/vfork.S | 55 + libc/sysdeps/linux/v850/Makefile | 64 + libc/sysdeps/linux/v850/__longjmp.S | 41 + libc/sysdeps/linux/v850/bits/byteswap.h | 63 + libc/sysdeps/linux/v850/bits/endian.h | 18 + libc/sysdeps/linux/v850/bits/fcntl.h | 234 + libc/sysdeps/linux/v850/bits/kernel_stat.h | 66 + libc/sysdeps/linux/v850/bits/kernel_types.h | 53 + libc/sysdeps/linux/v850/bits/mman.h | 99 + libc/sysdeps/linux/v850/bits/poll.h | 43 + libc/sysdeps/linux/v850/bits/select.h | 64 + libc/sysdeps/linux/v850/bits/setjmp.h | 42 + libc/sysdeps/linux/v850/bits/sigcontextinfo.h | 17 + libc/sysdeps/linux/v850/bits/stackinfo.h | 23 + libc/sysdeps/linux/v850/bits/syscalls.h | 15 + .../linux/v850/bits/uClibc_arch_features.h | 39 + libc/sysdeps/linux/v850/bits/wordsize.h | 19 + libc/sysdeps/linux/v850/clinkage.h | 14 + libc/sysdeps/linux/v850/clone.c | 50 + libc/sysdeps/linux/v850/crt0.S | 57 + libc/sysdeps/linux/v850/crti.S | 27 + libc/sysdeps/linux/v850/crtn.S | 24 + libc/sysdeps/linux/v850/mmap.c | 17 + libc/sysdeps/linux/v850/setjmp.S | 48 + libc/sysdeps/linux/v850/sys/procfs.h | 136 + libc/sysdeps/linux/v850/sys/ptrace.h | 98 + libc/sysdeps/linux/v850/sys/ucontext.h | 41 + libc/sysdeps/linux/v850/syscall.c | 43 + libc/sysdeps/linux/v850/vfork.S | 42 + libc/sysdeps/linux/vax/Makefile | 15 + libc/sysdeps/linux/vax/Makefile.arch | 12 + libc/sysdeps/linux/vax/__longjmp.S | 47 + libc/sysdeps/linux/vax/_setjmp.S | 53 + libc/sysdeps/linux/vax/bits/byteswap.h | 64 + libc/sysdeps/linux/vax/bits/endian.h | 9 + libc/sysdeps/linux/vax/bits/fcntl.h | 214 + libc/sysdeps/linux/vax/bits/ipc.h | 50 + libc/sysdeps/linux/vax/bits/kernel_stat.h | 60 + libc/sysdeps/linux/vax/bits/kernel_types.h | 45 + libc/sysdeps/linux/vax/bits/machine-gmon.h | 41 + libc/sysdeps/linux/vax/bits/mman.h | 94 + libc/sysdeps/linux/vax/bits/sem.h | 87 + libc/sysdeps/linux/vax/bits/setjmp.h | 37 + libc/sysdeps/linux/vax/bits/shm.h | 88 + libc/sysdeps/linux/vax/bits/sigcontext.h | 29 + libc/sysdeps/linux/vax/bits/stackinfo.h | 7 + libc/sysdeps/linux/vax/bits/statfs.h | 61 + libc/sysdeps/linux/vax/bits/syscalls.h | 258 + .../linux/vax/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/vax/bits/wordsize.h | 19 + libc/sysdeps/linux/vax/brk.c | 54 + libc/sysdeps/linux/vax/clone.S | 85 + libc/sysdeps/linux/vax/crt1.S | 73 + libc/sysdeps/linux/vax/crti.S | 21 + libc/sysdeps/linux/vax/crtn.S | 21 + libc/sysdeps/linux/vax/mmap.c | 11 + libc/sysdeps/linux/vax/setjmp.S | 39 + libc/sysdeps/linux/vax/sys/procfs.h | 123 + libc/sysdeps/linux/vax/sys/ucontext.h | 80 + libc/sysdeps/linux/x86_64/Makefile | 13 + libc/sysdeps/linux/x86_64/Makefile.arch | 13 + libc/sysdeps/linux/x86_64/__longjmp.S | 46 + libc/sysdeps/linux/x86_64/__syscall_error.c | 21 + libc/sysdeps/linux/x86_64/bits/atomic.h | 324 + libc/sysdeps/linux/x86_64/bits/byteswap.h | 133 + libc/sysdeps/linux/x86_64/bits/endian.h | 7 + libc/sysdeps/linux/x86_64/bits/environments.h | 87 + libc/sysdeps/linux/x86_64/bits/fcntl.h | 255 + libc/sysdeps/linux/x86_64/bits/fenv.h | 97 + libc/sysdeps/linux/x86_64/bits/kernel_stat.h | 54 + libc/sysdeps/linux/x86_64/bits/kernel_types.h | 44 + libc/sysdeps/linux/x86_64/bits/mathdef.h | 48 + libc/sysdeps/linux/x86_64/bits/mathinline.h | 53 + libc/sysdeps/linux/x86_64/bits/mman.h | 104 + libc/sysdeps/linux/x86_64/bits/msq.h | 83 + libc/sysdeps/linux/x86_64/bits/sem.h | 87 + libc/sysdeps/linux/x86_64/bits/setjmp.h | 78 + libc/sysdeps/linux/x86_64/bits/shm.h | 110 + libc/sysdeps/linux/x86_64/bits/sigcontext.h | 159 + .../linux/x86_64/bits/sigcontextinfo.h | 26 + libc/sysdeps/linux/x86_64/bits/stackinfo.h | 28 + libc/sysdeps/linux/x86_64/bits/stat.h | 203 + libc/sysdeps/linux/x86_64/bits/syscalls.h | 213 + .../linux/x86_64/bits/uClibc_arch_features.h | 38 + libc/sysdeps/linux/x86_64/bits/wordsize.h | 8 + libc/sysdeps/linux/x86_64/brk.c | 46 + libc/sysdeps/linux/x86_64/bsd-_setjmp.S | 29 + libc/sysdeps/linux/x86_64/bsd-setjmp.S | 29 + libc/sysdeps/linux/x86_64/clone.S | 114 + libc/sysdeps/linux/x86_64/crt1.S | 140 + libc/sysdeps/linux/x86_64/crti.S | 16 + libc/sysdeps/linux/x86_64/crtn.S | 18 + libc/sysdeps/linux/x86_64/fpu_control.h | 103 + libc/sysdeps/linux/x86_64/mmap.c | 20 + libc/sysdeps/linux/x86_64/setjmp.S | 45 + libc/sysdeps/linux/x86_64/sigaction.c | 150 + libc/sysdeps/linux/x86_64/sys/debugreg.h | 88 + libc/sysdeps/linux/x86_64/sys/epoll.h | 110 + libc/sysdeps/linux/x86_64/sys/io.h | 181 + libc/sysdeps/linux/x86_64/sys/perm.h | 36 + libc/sysdeps/linux/x86_64/sys/procfs.h | 143 + libc/sysdeps/linux/x86_64/sys/reg.h | 79 + libc/sysdeps/linux/x86_64/sys/ucontext.h | 248 + libc/sysdeps/linux/x86_64/sys/user.h | 176 + libc/sysdeps/linux/x86_64/syscall.S | 42 + libc/sysdeps/linux/x86_64/vfork.S | 58 + libc/sysdeps/linux/xtensa/Makefile | 13 + libc/sysdeps/linux/xtensa/Makefile.arch | 14 + libc/sysdeps/linux/xtensa/__longjmp.S | 126 + libc/sysdeps/linux/xtensa/__syscall_error.c | 18 + libc/sysdeps/linux/xtensa/bits/endian.h | 10 + libc/sysdeps/linux/xtensa/bits/fcntl.h | 238 + libc/sysdeps/linux/xtensa/bits/ipc.h | 54 + libc/sysdeps/linux/xtensa/bits/kernel_stat.h | 57 + libc/sysdeps/linux/xtensa/bits/kernel_types.h | 48 + libc/sysdeps/linux/xtensa/bits/mathdef.h | 43 + libc/sysdeps/linux/xtensa/bits/mman.h | 104 + libc/sysdeps/linux/xtensa/bits/msq.h | 88 + libc/sysdeps/linux/xtensa/bits/setjmp.h | 46 + libc/sysdeps/linux/xtensa/bits/shm.h | 115 + .../linux/xtensa/bits/sigcontextinfo.h | 33 + libc/sysdeps/linux/xtensa/bits/stackinfo.h | 28 + libc/sysdeps/linux/xtensa/bits/stat.h | 153 + libc/sysdeps/linux/xtensa/bits/syscalls.h | 140 + .../linux/xtensa/bits/uClibc_arch_features.h | 41 + libc/sysdeps/linux/xtensa/bits/uClibc_page.h | 31 + libc/sysdeps/linux/xtensa/bits/wordsize.h | 19 + .../sysdeps/linux/xtensa/bits/xtensa-config.h | 53 + libc/sysdeps/linux/xtensa/brk.c | 43 + libc/sysdeps/linux/xtensa/bsd-_setjmp.S | 1 + libc/sysdeps/linux/xtensa/bsd-setjmp.S | 1 + libc/sysdeps/linux/xtensa/clone.S | 103 + libc/sysdeps/linux/xtensa/crt1.S | 119 + libc/sysdeps/linux/xtensa/crti.S | 16 + libc/sysdeps/linux/xtensa/crtn.S | 8 + libc/sysdeps/linux/xtensa/fork.c | 25 + libc/sysdeps/linux/xtensa/mmap.S | 57 + libc/sysdeps/linux/xtensa/posix_fadvise.c | 29 + libc/sysdeps/linux/xtensa/posix_fadvise64.c | 39 + libc/sysdeps/linux/xtensa/pread_write.c | 193 + libc/sysdeps/linux/xtensa/setjmp.S | 131 + libc/sysdeps/linux/xtensa/sigaction.c | 59 + libc/sysdeps/linux/xtensa/sigrestorer.S | 19 + libc/sysdeps/linux/xtensa/sys/procfs.h | 121 + libc/sysdeps/linux/xtensa/sys/ptrace.h | 156 + libc/sysdeps/linux/xtensa/sys/ucontext.h | 49 + libc/sysdeps/linux/xtensa/syscall.S | 42 + libc/sysdeps/linux/xtensa/sysdep.h | 160 + libc/sysdeps/linux/xtensa/vfork.S | 170 + libc/sysdeps/linux/xtensa/windowspill.S | 96 + libc/termios/.indent.pro | 33 + libc/termios/Makefile | 13 + libc/termios/Makefile.in | 19 + libc/termios/cfmakeraw.c | 33 + libc/termios/cfsetspeed.c | 179 + libc/termios/isatty.c | 32 + libc/termios/kernel_termios.h | 139 + libc/termios/speed.c | 97 + libc/termios/tcdrain.c | 31 + libc/termios/tcflow.c | 30 + libc/termios/tcflush.c | 31 + libc/termios/tcgetattr.c | 82 + libc/termios/tcgetpgrp.c | 36 + libc/termios/tcgetsid.c | 66 + libc/termios/tcsendbrk.c | 48 + libc/termios/tcsetattr.c | 121 + libc/termios/tcsetpgrp.c | 30 + libc/termios/ttyname.c | 136 + libc/unistd/.indent.pro | 33 + libc/unistd/Makefile | 13 + libc/unistd/Makefile.in | 48 + libc/unistd/__exec_alloc.c | 8 + libc/unistd/confstr.c | 62 + libc/unistd/daemon.c | 92 + libc/unistd/exec.c | 344 + libc/unistd/execl.c | 8 + libc/unistd/execle.c | 8 + libc/unistd/execlp.c | 8 + libc/unistd/execv.c | 8 + libc/unistd/execvp.c | 8 + libc/unistd/fpathconf.c | 258 + libc/unistd/getlogin.c | 49 + libc/unistd/getopt-susv3.c | 126 + libc/unistd/getopt.c | 1203 ++ libc/unistd/getopt_int.h | 134 + libc/unistd/getopt_long-simple.c | 58 + libc/unistd/getpass.c | 120 + libc/unistd/getsubopt-susv3.c | 33 + libc/unistd/getsubopt.c | 75 + libc/unistd/pathconf.c | 202 + libc/unistd/sleep.c | 172 + libc/unistd/swab.c | 23 + libc/unistd/sysconf.c | 896 ++ libc/unistd/ualarm.c | 26 + libc/unistd/usershell.c | 146 + libc/unistd/usleep.c | 35 + libcrypt/Makefile | 13 + libcrypt/Makefile.in | 68 + libcrypt/crypt.c | 21 + libcrypt/crypt_stub.c | 30 + libcrypt/des.c | 755 + libcrypt/libcrypt.h | 20 + libcrypt/md5.c | 634 + libintl/Makefile | 13 + libintl/Makefile.in | 74 + libintl/intl.c | 154 + libm/Makefile | 13 + libm/Makefile.in | 207 + libm/README | 16 + libm/carg.c | 29 + libm/e_acos.c | 111 + libm/e_acosh.c | 70 + libm/e_asin.c | 122 + libm/e_atan2.c | 131 + libm/e_atanh.c | 75 + libm/e_cosh.c | 94 + libm/e_exp.c | 172 + libm/e_fmod.c | 140 + libm/e_gamma.c | 34 + libm/e_gamma_r.c | 33 + libm/e_hypot.c | 128 + libm/e_j0.c | 488 + libm/e_j1.c | 487 + libm/e_jn.c | 282 + libm/e_lgamma.c | 34 + libm/e_lgamma_r.c | 316 + libm/e_log.c | 147 + libm/e_log10.c | 98 + libm/e_log2.c | 130 + libm/e_pow.c | 309 + libm/e_rem_pio2.c | 184 + libm/e_remainder.c | 81 + libm/e_scalb.c | 56 + libm/e_sinh.c | 87 + libm/e_sqrt.c | 453 + libm/float_wrappers.c | 534 + libm/i386/Makefile.arch | 24 + libm/i386/fclrexcpt.c | 61 + libm/i386/fedisblxcpt.c | 55 + libm/i386/feenablxcpt.c | 55 + libm/i386/fegetenv.c | 34 + libm/i386/fegetexcept.c | 32 + libm/i386/fegetround.c | 31 + libm/i386/feholdexcpt.c | 59 + libm/i386/fesetenv.c | 80 + libm/i386/fesetround.c | 52 + libm/i386/feupdateenv.c | 56 + libm/i386/fgetexcptflg.c | 35 + libm/i386/fraiseexcpt.c | 118 + libm/i386/fsetexcptflg.c | 62 + libm/i386/ftestexcept.c | 40 + libm/k_cos.c | 96 + libm/k_rem_pio2.c | 321 + libm/k_sin.c | 79 + libm/k_standard.c | 786 + libm/k_tan.c | 133 + libm/ldouble_wrappers.c | 523 + libm/math_private.h | 199 + libm/nan.c | 60 + libm/powerpc/classic/Makefile.arch | 18 + libm/powerpc/e500/Makefile.arch | 9 + libm/powerpc/e500/README.txt | 8 + libm/powerpc/e500/fpu/Makefile.arch | 19 + libm/powerpc/e500/fpu/fclrexcpt.c | 39 + libm/powerpc/e500/fpu/fe_nomask.c | 32 + libm/powerpc/e500/fpu/fedisblxcpt.c | 60 + libm/powerpc/e500/fpu/feenablxcpt.c | 60 + libm/powerpc/e500/fpu/fegetenv.c | 38 + libm/powerpc/e500/fpu/fegetexcept.c | 31 + libm/powerpc/e500/fpu/fegetround.c | 31 + libm/powerpc/e500/fpu/feholdexcpt.c | 45 + libm/powerpc/e500/fpu/fenv_const.c | 27 + libm/powerpc/e500/fpu/fenv_libc.h | 77 + libm/powerpc/e500/fpu/fesetenv.c | 38 + libm/powerpc/e500/fpu/fesetround.c | 37 + libm/powerpc/e500/fpu/feupdateenv.c | 49 + libm/powerpc/e500/fpu/fgetexcptflg.c | 39 + libm/powerpc/e500/fpu/fraiseexcpt.c | 29 + libm/powerpc/e500/fpu/fsetexcptflg.c | 46 + libm/powerpc/e500/fpu/ftestexcept.c | 32 + libm/powerpc/e500/spe-raise.c | 67 + libm/s_asinh.c | 67 + libm/s_atan.c | 141 + libm/s_cbrt.c | 94 + libm/s_ceil.c | 81 + libm/s_copysign.c | 39 + libm/s_cos.c | 83 + libm/s_erf.c | 317 + libm/s_expm1.c | 230 + libm/s_fabs.c | 36 + libm/s_fdim.c | 24 + libm/s_finite.c | 29 + libm/s_finitef.c | 32 + libm/s_floor.c | 82 + libm/s_fma.c | 30 + libm/s_fmax.c | 25 + libm/s_fmin.c | 25 + libm/s_fpclassify.c | 43 + libm/s_fpclassifyf.c | 42 + libm/s_frexp.c | 60 + libm/s_ilogb.c | 52 + libm/s_isinf.c | 26 + libm/s_isinff.c | 26 + libm/s_isnan.c | 37 + libm/s_isnanf.c | 34 + libm/s_ldexp.c | 34 + libm/s_lib_version.c | 39 + libm/s_llrint.c | 88 + libm/s_llround.c | 75 + libm/s_log1p.c | 175 + libm/s_logb.c | 44 + libm/s_lrint.c | 93 + libm/s_lround.c | 75 + libm/s_matherr.c | 34 + libm/s_modf.c | 84 + libm/s_nearbyint.c | 24 + libm/s_nextafter.c | 80 + libm/s_remquo.c | 37 + libm/s_rint.c | 87 + libm/s_round.c | 92 + libm/s_scalbln.c | 62 + libm/s_scalbn.c | 69 + libm/s_signbit.c | 33 + libm/s_signbitf.c | 34 + libm/s_signgam.c | 5 + libm/s_significand.c | 36 + libm/s_sin.c | 83 + libm/s_tan.c | 77 + libm/s_tanh.c | 88 + libm/s_trunc.c | 57 + libm/w_acos.c | 43 + libm/w_acosh.c | 43 + libm/w_asin.c | 45 + libm/w_atan2.c | 42 + libm/w_atanh.c | 47 + libm/w_cabs.c | 16 + libm/w_cosh.c | 43 + libm/w_drem.c | 15 + libm/w_exp.c | 54 + libm/w_exp2.c | 26 + libm/w_fmod.c | 43 + libm/w_gamma.c | 49 + libm/w_gamma_r.c | 49 + libm/w_hypot.c | 43 + libm/w_j0.c | 71 + libm/w_j1.c | 72 + libm/w_jn.c | 94 + libm/w_lgamma.c | 49 + libm/w_lgamma_r.c | 46 + libm/w_log.c | 43 + libm/w_log10.c | 46 + libm/w_log2.c | 14 + libm/w_pow.c | 61 + libm/w_remainder.c | 43 + libm/w_scalb.c | 61 + libm/w_sinh.c | 43 + libm/w_sqrt.c | 43 + libm/w_tgamma.c | 47 + libnsl/Makefile | 13 + libnsl/Makefile.in | 50 + libnsl/nsl.c | 17 + libpthread/Makefile | 13 + libpthread/Makefile.in | 11 + libpthread/linuxthreads.old/Makefile | 13 + libpthread/linuxthreads.old/Makefile.in | 123 + libpthread/linuxthreads.old/attr.c | 238 + libpthread/linuxthreads.old/cancel.c | 221 + libpthread/linuxthreads.old/condvar.c | 314 + libpthread/linuxthreads.old/debug.h | 40 + libpthread/linuxthreads.old/errno.c | 37 + libpthread/linuxthreads.old/events.c | 37 + libpthread/linuxthreads.old/forward.c | 168 + libpthread/linuxthreads.old/internals.h | 532 + libpthread/linuxthreads.old/join.c | 231 + .../linuxthreads.old/libc_pthread_init.c | 52 + libpthread/linuxthreads.old/linuxthreads.texi | 1627 ++ libpthread/linuxthreads.old/locale.c | 57 + libpthread/linuxthreads.old/lockfile.c | 43 + libpthread/linuxthreads.old/manager.c | 928 ++ libpthread/linuxthreads.old/mutex.c | 362 + libpthread/linuxthreads.old/oldsemaphore.c | 241 + libpthread/linuxthreads.old/pt-machine.c | 22 + libpthread/linuxthreads.old/ptfork.c | 174 + libpthread/linuxthreads.old/pthread.c | 1166 ++ libpthread/linuxthreads.old/ptlongjmp.c | 71 + libpthread/linuxthreads.old/queue.h | 60 + libpthread/linuxthreads.old/restart.h | 50 + libpthread/linuxthreads.old/rwlock.c | 486 + libpthread/linuxthreads.old/semaphore.c | 313 + libpthread/linuxthreads.old/semaphore.h | 94 + libpthread/linuxthreads.old/signals.c | 251 + libpthread/linuxthreads.old/specific.c | 198 + libpthread/linuxthreads.old/spinlock.c | 723 + libpthread/linuxthreads.old/spinlock.h | 218 + .../sysdeps/alpha/pt-machine.h | 127 + .../linuxthreads.old/sysdeps/arm/pt-machine.h | 69 + .../sysdeps/avr32/pt-machine.h | 73 + .../sysdeps/bfin/pt-machine.h | 76 + .../sysdeps/cris/pt-machine.h | 70 + .../linuxthreads.old/sysdeps/frv/pt-machine.h | 70 + .../sysdeps/h8300/pt-machine.h | 58 + .../sysdeps/i386/pt-machine.h | 147 + .../linuxthreads.old/sysdeps/i386/tls.h | 185 + .../linuxthreads.old/sysdeps/i386/useldt.h | 307 + .../sysdeps/ia64/pt-machine.h | 135 + .../linuxthreads.old/sysdeps/ia64/tls.h | 139 + .../sysdeps/m68k/pt-machine.h | 75 + .../sysdeps/mips/pt-machine.h | 106 + .../sysdeps/nios/pt-machine.h | 68 + .../sysdeps/nios2/pt-machine.h | 58 + .../sysdeps/powerpc/pt-machine.h | 102 + .../sysdeps/pthread/bits/libc-lock.h | 416 + .../sysdeps/pthread/bits/libc-tsd.h | 73 + .../sysdeps/pthread/bits/pthreadtypes.h | 142 + .../sysdeps/pthread/pthread-functions.h | 98 + .../sysdeps/pthread/pthread.h | 695 + .../linuxthreads.old/sysdeps/pthread/tls.h | 81 + .../linuxthreads.old/sysdeps/sh/pt-machine.h | 82 + libpthread/linuxthreads.old/sysdeps/sh/tls.h | 117 + .../sysdeps/sh64/Makefile.arch | 30 + .../sysdeps/sh64/pt-machine.c | 47 + .../sysdeps/sh64/pt-machine.h | 39 + .../sysdeps/sparc/pt-machine.h | 8 + .../sysdeps/sparc/sparc32/pt-machine.h | 83 + .../sysdeps/sparc/sparc64/pt-machine.h | 105 + .../sysdeps/v850/pt-machine.h | 52 + .../sysdeps/x86_64/pt-machine.h | 85 + .../linuxthreads.old/sysdeps/x86_64/tls.h | 134 + .../sysdeps/xtensa/pt-machine.h | 48 + libpthread/linuxthreads.old/wrapsyscall.c | 228 + libpthread/linuxthreads.old_db/Banner | 1 + libpthread/linuxthreads.old_db/Makefile | 13 + libpthread/linuxthreads.old_db/Makefile.in | 76 + libpthread/linuxthreads.old_db/Versions | 24 + libpthread/linuxthreads.old_db/proc_service.h | 70 + libpthread/linuxthreads.old_db/td_init.c | 33 + libpthread/linuxthreads.old_db/td_log.c | 32 + .../linuxthreads.old_db/td_symbol_list.c | 61 + .../linuxthreads.old_db/td_ta_clear_event.c | 53 + libpthread/linuxthreads.old_db/td_ta_delete.c | 58 + .../linuxthreads.old_db/td_ta_enable_stats.c | 35 + .../linuxthreads.old_db/td_ta_event_addr.c | 73 + .../linuxthreads.old_db/td_ta_event_getmsg.c | 128 + .../linuxthreads.old_db/td_ta_get_nthreads.c | 42 + libpthread/linuxthreads.old_db/td_ta_get_ph.c | 36 + .../linuxthreads.old_db/td_ta_get_stats.c | 35 + .../linuxthreads.old_db/td_ta_map_id2thr.c | 78 + .../linuxthreads.old_db/td_ta_map_lwp2thr.c | 90 + libpthread/linuxthreads.old_db/td_ta_new.c | 149 + .../linuxthreads.old_db/td_ta_reset_stats.c | 35 + .../linuxthreads.old_db/td_ta_set_event.c | 53 + .../td_ta_setconcurrency.c | 35 + .../linuxthreads.old_db/td_ta_thr_iter.c | 173 + .../linuxthreads.old_db/td_ta_tsd_iter.c | 55 + .../linuxthreads.old_db/td_thr_clear_event.c | 62 + .../linuxthreads.old_db/td_thr_dbresume.c | 30 + .../linuxthreads.old_db/td_thr_dbsuspend.c | 30 + .../linuxthreads.old_db/td_thr_event_enable.c | 57 + .../linuxthreads.old_db/td_thr_event_getmsg.c | 65 + .../linuxthreads.old_db/td_thr_get_info.c | 83 + .../linuxthreads.old_db/td_thr_getfpregs.c | 58 + .../linuxthreads.old_db/td_thr_getgregs.c | 58 + .../linuxthreads.old_db/td_thr_getxregs.c | 30 + .../linuxthreads.old_db/td_thr_getxregsize.c | 30 + .../linuxthreads.old_db/td_thr_set_event.c | 62 + .../linuxthreads.old_db/td_thr_setfpregs.c | 47 + .../linuxthreads.old_db/td_thr_setgregs.c | 47 + .../linuxthreads.old_db/td_thr_setprio.c | 30 + .../td_thr_setsigpending.c | 31 + .../linuxthreads.old_db/td_thr_setxregs.c | 30 + .../linuxthreads.old_db/td_thr_sigsetmask.c | 30 + .../linuxthreads.old_db/td_thr_tls_get_addr.c | 69 + libpthread/linuxthreads.old_db/td_thr_tsd.c | 81 + .../linuxthreads.old_db/td_thr_validate.c | 69 + libpthread/linuxthreads.old_db/thread_db.h | 459 + libpthread/linuxthreads.old_db/thread_dbP.h | 110 + libpthread/linuxthreads/.cvsignore | 3 + libpthread/linuxthreads/Makefile | 13 + libpthread/linuxthreads/Makefile.in | 136 + libpthread/linuxthreads/alloca_cutoff.c | 36 + libpthread/linuxthreads/attr.c | 469 + libpthread/linuxthreads/barrier.c | 128 + libpthread/linuxthreads/cancel.c | 238 + libpthread/linuxthreads/condvar.c | 304 + libpthread/linuxthreads/descr.h | 270 + libpthread/linuxthreads/errno.c | 48 + libpthread/linuxthreads/events.c | 37 + libpthread/linuxthreads/forward.c | 146 + libpthread/linuxthreads/internals.h | 556 + libpthread/linuxthreads/join.c | 220 + libpthread/linuxthreads/libc-cancellation.c | 64 + libpthread/linuxthreads/libc_pthread_init.c | 55 + libpthread/linuxthreads/lockfile.c | 52 + libpthread/linuxthreads/manager.c | 1121 ++ libpthread/linuxthreads/mutex.c | 357 + libpthread/linuxthreads/pt-machine.c | 25 + libpthread/linuxthreads/ptcleanup.c | 74 + libpthread/linuxthreads/ptclock_gettime.c | 69 + libpthread/linuxthreads/ptclock_settime.c | 55 + libpthread/linuxthreads/ptfork.c | 94 + libpthread/linuxthreads/pthandles.c | 5 + libpthread/linuxthreads/pthread.c | 1382 ++ libpthread/linuxthreads/pthread_atfork.c | 63 + libpthread/linuxthreads/pthread_setegid.c | 28 + libpthread/linuxthreads/pthread_seteuid.c | 28 + libpthread/linuxthreads/pthread_setgid.c | 28 + libpthread/linuxthreads/pthread_setregid.c | 28 + libpthread/linuxthreads/pthread_setresgid.c | 28 + libpthread/linuxthreads/pthread_setresuid.c | 28 + libpthread/linuxthreads/pthread_setreuid.c | 28 + libpthread/linuxthreads/pthread_setuid.c | 28 + libpthread/linuxthreads/queue.h | 61 + libpthread/linuxthreads/restart.h | 49 + libpthread/linuxthreads/rwlock.c | 658 + libpthread/linuxthreads/semaphore.c | 298 + libpthread/linuxthreads/semaphore.h | 94 + libpthread/linuxthreads/sighandler.c | 71 + libpthread/linuxthreads/signals.c | 215 + libpthread/linuxthreads/specific.c | 241 + libpthread/linuxthreads/spinlock.c | 720 + libpthread/linuxthreads/spinlock.h | 218 + .../sysdeps/alpha/elf/pt-initfini.c | 90 + .../linuxthreads/sysdeps/alpha/pspinlock.c | 110 + .../linuxthreads/sysdeps/alpha/pt-machine.h | 127 + libpthread/linuxthreads/sysdeps/alpha/tls.h | 134 + .../linuxthreads/sysdeps/arm/pspinlock.c | 82 + .../linuxthreads/sysdeps/arm/pt-machine.h | 54 + libpthread/linuxthreads/sysdeps/arm/tls.h | 172 + .../linuxthreads/sysdeps/avr32/pt-machine.h | 73 + .../linuxthreads/sysdeps/cris/pspinlock.c | 72 + .../linuxthreads/sysdeps/cris/pt-machine.h | 57 + .../linuxthreads/sysdeps/hppa/pspinlock.c | 81 + .../linuxthreads/sysdeps/hppa/pt-machine.h | 60 + .../sysdeps/i386/i686/pt-machine.h | 79 + .../linuxthreads/sysdeps/i386/pspinlock.c | 103 + .../linuxthreads/sysdeps/i386/pt-machine.h | 118 + .../linuxthreads/sysdeps/i386/tcb-offsets.sym | 7 + libpthread/linuxthreads/sysdeps/i386/tls.h | 229 + libpthread/linuxthreads/sysdeps/i386/useldt.h | 314 + .../linuxthreads/sysdeps/ia64/pspinlock.c | 79 + .../linuxthreads/sysdeps/ia64/pt-machine.h | 131 + .../linuxthreads/sysdeps/ia64/tcb-offsets.sym | 9 + libpthread/linuxthreads/sysdeps/ia64/tls.h | 145 + .../linuxthreads/sysdeps/m68k/pspinlock.c | 82 + .../linuxthreads/sysdeps/m68k/pt-machine.h | 68 + .../linuxthreads/sysdeps/mips/pspinlock.c | 96 + .../linuxthreads/sysdeps/mips/pt-machine.h | 89 + libpthread/linuxthreads/sysdeps/mips/tls.h | 170 + .../sysdeps/powerpc/powerpc32/pspinlock.c | 70 + .../sysdeps/powerpc/powerpc32/pt-machine.h | 120 + .../sysdeps/powerpc/powerpc64/pspinlock.c | 70 + .../sysdeps/powerpc/powerpc64/pt-machine.h | 185 + .../linuxthreads/sysdeps/powerpc/pspinlock.c | 8 + .../linuxthreads/sysdeps/powerpc/pt-machine.h | 8 + .../sysdeps/powerpc/tcb-offsets.sym | 19 + libpthread/linuxthreads/sysdeps/powerpc/tls.h | 165 + .../linuxthreads/sysdeps/pthread/.cvsignore | 2 + .../sysdeps/pthread/bits/initspin.h | 28 + .../sysdeps/pthread/bits/libc-lock.h | 409 + .../sysdeps/pthread/bits/libc-tsd.h | 59 + .../sysdeps/pthread/bits/pthreadtypes.h | 152 + .../sysdeps/pthread/bits/typesizes.h | 66 + .../linuxthreads/sysdeps/pthread/errno-loc.c | 45 + .../linuxthreads/sysdeps/pthread/flockfile.c | 33 + .../sysdeps/pthread/ftrylockfile.c | 33 + .../sysdeps/pthread/funlockfile.c | 33 + .../sysdeps/pthread/getcpuclockid.c | 117 + .../linuxthreads/sysdeps/pthread/herrno-loc.c | 43 + .../sysdeps/pthread/kernel-features.h | 80 + .../linuxthreads/sysdeps/pthread/list.h | 114 + .../sysdeps/pthread/malloc-machine.h | 67 + .../linuxthreads/sysdeps/pthread/not-cancel.h | 62 + .../sysdeps/pthread/posix-timer.h | 204 + .../sysdeps/pthread/pt-initfini.c | 124 + .../sysdeps/pthread/pthread-functions.h | 98 + .../linuxthreads/sysdeps/pthread/pthread.h | 678 + .../linuxthreads/sysdeps/pthread/ptlongjmp.c | 39 + .../linuxthreads/sysdeps/pthread/res-state.c | 47 + .../linuxthreads/sysdeps/pthread/semaphore.h | 1 + .../linuxthreads/sysdeps/pthread/sigaction.c | 55 + .../sysdeps/pthread/tcb-offsets.h | 1 + .../sysdeps/pthread/timer_create.c | 170 + .../sysdeps/pthread/timer_delete.c | 70 + .../sysdeps/pthread/timer_getoverr.c | 45 + .../sysdeps/pthread/timer_gettime.c | 77 + .../sysdeps/pthread/timer_routines.c | 573 + .../sysdeps/pthread/timer_settime.c | 137 + .../linuxthreads/sysdeps/pthread/tst-timer.c | 114 + .../sysdeps/pthread/uClibc-glue.h | 47 + .../linuxthreads/sysdeps/s390/pspinlock.c | 91 + .../sysdeps/s390/s390-32/pt-machine.h | 120 + .../sysdeps/s390/s390-64/pt-machine.h | 125 + .../linuxthreads/sysdeps/s390/tcb-offsets.sym | 4 + libpthread/linuxthreads/sysdeps/s390/tls.h | 145 + .../linuxthreads/sysdeps/sh/pspinlock.c | 80 + .../linuxthreads/sysdeps/sh/pt-machine.h | 82 + .../linuxthreads/sysdeps/sh/tcb-offsets.sym | 10 + libpthread/linuxthreads/sysdeps/sh/tls.h | 159 + .../linuxthreads/sysdeps/sparc/pspinlock.c | 14 + .../linuxthreads/sysdeps/sparc/pt-machine.h | 8 + .../sysdeps/sparc/sparc32/pspinlock.c | 88 + .../sysdeps/sparc/sparc32/pt-machine.h | 83 + .../sysdeps/sparc/sparc32/sparcv9/pspinlock.c | 94 + .../sysdeps/sparc/sparc64/pspinlock.c | 93 + .../sysdeps/sparc/sparc64/pt-machine.h | 105 + .../sysdeps/sparc/tcb-offsets.sym | 4 + libpthread/linuxthreads/sysdeps/sparc/tls.h | 115 + .../sysdeps/unix/sysv/linux/.cvsignore | 2 + .../sysdeps/unix/sysv/linux/allocalim.h | 26 + .../sysdeps/unix/sysv/linux/allocrtsig.c | 87 + .../unix/sysv/linux/alpha/aio_cancel.c | 33 + .../unix/sysv/linux/alpha/bits/local_lim.h | 92 + .../unix/sysv/linux/alpha/bits/typesizes.h | 66 + .../unix/sysv/linux/alpha/pt-sigsuspend.S | 28 + .../unix/sysv/linux/alpha/sysdep-cancel.h | 146 + .../sysdeps/unix/sysv/linux/alpha/vfork.S | 70 + .../sysdeps/unix/sysv/linux/execve.c | 73 + .../sysdeps/unix/sysv/linux/fork.c | 30 + .../sysdeps/unix/sysv/linux/fork.h | 58 + .../sysdeps/unix/sysv/linux/hppa/aio_cancel.c | 33 + .../unix/sysv/linux/hppa/bits/initspin.h | 27 + .../unix/sysv/linux/hppa/malloc-machine.h | 73 + .../unix/sysv/linux/hppa/pt-initfini.c | 109 + .../unix/sysv/linux/hppa/sysdep-cancel.h | 189 + .../unix/sysv/linux/i386/sysdep-cancel.h | 187 + .../sysdeps/unix/sysv/linux/i386/vfork.S | 95 + .../unix/sysv/linux/ia64/bits/local_lim.h | 92 + .../sysdeps/unix/sysv/linux/ia64/fork.h | 25 + .../unix/sysv/linux/ia64/pt-initfini.c | 142 + .../unix/sysv/linux/ia64/pt-sigsuspend.c | 33 + .../unix/sysv/linux/ia64/sysdep-cancel.h | 144 + .../sysdeps/unix/sysv/linux/ia64/vfork.S | 54 + .../sysdeps/unix/sysv/linux/jmp-unwind.c | 34 + .../unix/sysv/linux/m68k/sysdep-cancel.h | 129 + .../sysdeps/unix/sysv/linux/m68k/vfork.S | 84 + .../sysv/linux/mips/mips64/sysdep-cancel.h | 144 + .../unix/sysv/linux/mips/sysdep-cancel.h | 143 + .../sysdeps/unix/sysv/linux/mips/vfork.S | 104 + .../sysdeps/unix/sysv/linux/mq_notify.c | 287 + .../linux/powerpc/powerpc32/sysdep-cancel.h | 159 + .../unix/sysv/linux/powerpc/powerpc32/vfork.S | 86 + .../linux/powerpc/powerpc64/sysdep-cancel.h | 127 + .../unix/sysv/linux/powerpc/powerpc64/vfork.S | 91 + .../unix/sysv/linux/powerpc/ptlongjmp.c | 70 + .../sysdeps/unix/sysv/linux/pt-sigsuspend.c | 33 + .../sysdeps/unix/sysv/linux/raise.c | 43 + .../sysdeps/unix/sysv/linux/register-atfork.c | 87 + .../unix/sysv/linux/s390/bits/typesizes.h | 72 + .../sysv/linux/s390/s390-32/pt-initfini.c | 154 + .../sysv/linux/s390/s390-32/sysdep-cancel.h | 137 + .../unix/sysv/linux/s390/s390-32/vfork.S | 69 + .../sysv/linux/s390/s390-64/pt-initfini.c | 137 + .../sysv/linux/s390/s390-64/pt-sigsuspend.c | 1 + .../sysv/linux/s390/s390-64/sysdep-cancel.h | 116 + .../unix/sysv/linux/s390/s390-64/vfork.S | 54 + .../sysdeps/unix/sysv/linux/sh/pt-initfini.c | 143 + .../sysdeps/unix/sysv/linux/sh/smp.h | 24 + .../unix/sysv/linux/sh/sysdep-cancel.h | 227 + .../sysdeps/unix/sysv/linux/sh/vfork.S | 78 + .../sysdeps/unix/sysv/linux/sigwait.c | 88 + .../sysdeps/unix/sysv/linux/smp.h | 48 + .../unix/sysv/linux/sparc/aio_cancel.c | 33 + .../unix/sysv/linux/sparc/bits/local_lim.h | 92 + .../unix/sysv/linux/sparc/bits/typesizes.h | 66 + .../sysdeps/unix/sysv/linux/sparc/fork.h | 34 + .../sysv/linux/sparc/sparc32/sysdep-cancel.h | 102 + .../unix/sysv/linux/sparc/sparc32/vfork.S | 65 + .../sysv/linux/sparc/sparc64/pt-sigsuspend.c | 1 + .../sysv/linux/sparc/sparc64/sysdep-cancel.h | 101 + .../unix/sysv/linux/sparc/sparc64/vfork.S | 64 + .../unix/sysv/linux/unregister-atfork.c | 49 + .../unix/sysv/linux/x86_64/pt-sigsuspend.c | 1 + .../unix/sysv/linux/x86_64/sysdep-cancel.h | 132 + .../sysdeps/unix/sysv/linux/x86_64/vfork.S | 62 + .../linuxthreads/sysdeps/x86_64/pspinlock.c | 97 + .../linuxthreads/sysdeps/x86_64/pt-machine.h | 224 + .../sysdeps/x86_64/tcb-offsets.sym | 4 + libpthread/linuxthreads/sysdeps/x86_64/tls.h | 134 + libpthread/linuxthreads_db/.cvsignore | 5 + libpthread/linuxthreads_db/Banner | 1 + libpthread/linuxthreads_db/ChangeLog | 467 + libpthread/linuxthreads_db/Makefile | 13 + libpthread/linuxthreads_db/Makefile.in | 76 + libpthread/linuxthreads_db/Makefile.old | 57 + libpthread/linuxthreads_db/Versions | 24 + libpthread/linuxthreads_db/proc_service.h | 70 + libpthread/linuxthreads_db/shlib-versions | 2 + libpthread/linuxthreads_db/td_init.c | 34 + libpthread/linuxthreads_db/td_log.c | 32 + libpthread/linuxthreads_db/td_symbol_list.c | 61 + .../linuxthreads_db/td_ta_clear_event.c | 53 + libpthread/linuxthreads_db/td_ta_delete.c | 58 + .../linuxthreads_db/td_ta_enable_stats.c | 35 + libpthread/linuxthreads_db/td_ta_event_addr.c | 73 + .../linuxthreads_db/td_ta_event_getmsg.c | 129 + .../linuxthreads_db/td_ta_get_nthreads.c | 42 + libpthread/linuxthreads_db/td_ta_get_ph.c | 36 + libpthread/linuxthreads_db/td_ta_get_stats.c | 35 + libpthread/linuxthreads_db/td_ta_map_id2thr.c | 79 + .../linuxthreads_db/td_ta_map_lwp2thr.c | 91 + libpthread/linuxthreads_db/td_ta_new.c | 149 + .../linuxthreads_db/td_ta_reset_stats.c | 35 + libpthread/linuxthreads_db/td_ta_set_event.c | 53 + .../linuxthreads_db/td_ta_setconcurrency.c | 35 + libpthread/linuxthreads_db/td_ta_thr_iter.c | 176 + libpthread/linuxthreads_db/td_ta_tsd_iter.c | 56 + .../linuxthreads_db/td_thr_clear_event.c | 62 + libpthread/linuxthreads_db/td_thr_dbresume.c | 30 + libpthread/linuxthreads_db/td_thr_dbsuspend.c | 30 + .../linuxthreads_db/td_thr_event_enable.c | 57 + .../linuxthreads_db/td_thr_event_getmsg.c | 65 + libpthread/linuxthreads_db/td_thr_get_info.c | 83 + libpthread/linuxthreads_db/td_thr_getfpregs.c | 58 + libpthread/linuxthreads_db/td_thr_getgregs.c | 58 + libpthread/linuxthreads_db/td_thr_getxregs.c | 30 + .../linuxthreads_db/td_thr_getxregsize.c | 30 + libpthread/linuxthreads_db/td_thr_set_event.c | 62 + libpthread/linuxthreads_db/td_thr_setfpregs.c | 47 + libpthread/linuxthreads_db/td_thr_setgregs.c | 47 + libpthread/linuxthreads_db/td_thr_setprio.c | 30 + .../linuxthreads_db/td_thr_setsigpending.c | 31 + libpthread/linuxthreads_db/td_thr_setxregs.c | 30 + .../linuxthreads_db/td_thr_sigsetmask.c | 30 + .../linuxthreads_db/td_thr_tls_get_addr.c | 45 + libpthread/linuxthreads_db/td_thr_tlsbase.c | 71 + libpthread/linuxthreads_db/td_thr_tsd.c | 82 + libpthread/linuxthreads_db/td_thr_validate.c | 70 + libpthread/linuxthreads_db/thread_db.h | 459 + libpthread/linuxthreads_db/thread_dbP.h | 108 + libresolv/Makefile | 13 + libresolv/Makefile.in | 50 + libresolv/resolv.c | 18 + librt/Makefile | 13 + librt/Makefile.in | 53 + librt/kernel-posix-timers.h | 36 + librt/mq_close.c | 22 + librt/mq_getsetattr.c | 36 + librt/mq_notify.c | 28 + librt/mq_open.c | 52 + librt/mq_receive.c | 51 + librt/mq_send.c | 51 + librt/mq_unlink.c | 39 + librt/timer_create.c | 71 + librt/timer_delete.c | 33 + librt/timer_getoverr.c | 26 + librt/timer_gettime.c | 27 + librt/timer_settime.c | 28 + libutil/Makefile | 13 + libutil/Makefile.in | 66 + libutil/forkpty.c | 55 + libutil/login.c | 25 + libutil/login_tty.c | 71 + libutil/logout.c | 79 + libutil/logwtmp.c | 56 + libutil/openpty.c | 157 + test/Makefile | 71 + test/README | 68 + test/Rules.mak | 161 + test/Test.mak | 117 + test/args/Makefile | 11 + test/args/arg_test.c | 40 + test/args/arg_test.out.good | 13 + test/args/arg_test_glibc.out.good | 13 + test/assert/Makefile | 7 + test/assert/assert.c | 47 + test/build/Makefile | 4 + test/build/check_config_options.sh | 21 + test/crypt/Makefile | 8 + test/crypt/crypt.c | 113 + test/crypt/crypt.input | 171 + test/crypt/crypt.out.good | 172 + test/crypt/md5c-test.c | 19 + test/ctype/Makefile | 6 + test/ctype/ctype.c | 248 + test/dlopen/Makefile | 40 + test/dlopen/dladdr.c | 25 + test/dlopen/dlafk.c | 36 + test/dlopen/dlstatic.c | 43 + test/dlopen/dltest.c | 41 + test/dlopen/dltest2.c | 1 + test/dlopen/dlundef.c | 29 + test/dlopen/libafk-temp.c | 1 + test/dlopen/libafk.c | 1 + test/dlopen/libstatic.c | 15 + test/dlopen/libtest.c | 13 + test/dlopen/libtest1.c | 40 + test/dlopen/libtest2.c | 38 + test/dlopen/libtest3.c | 1 + test/dlopen/libundef.c | 1 + test/dlopen/test1.c | 33 + test/dlopen/test2.c | 39 + test/dlopen/test3.c | 13 + test/inet/Makefile | 4 + test/inet/bug-if1.c | 54 + test/inet/gethost_r-align.c | 50 + test/inet/if_nameindex.c | 61 + test/inet/tst-aton.c | 80 + test/inet/tst-ethers-line.c | 54 + test/inet/tst-ethers.c | 33 + test/inet/tst-network.c | 105 + test/inet/tst-ntoa.c | 36 + test/locale-mbwc/Makefile | 29 + test/locale-mbwc/dat_isw-funcs.h | 37 + test/locale-mbwc/dat_iswalnum.c | 196 + test/locale-mbwc/dat_iswalpha.c | 169 + test/locale-mbwc/dat_iswcntrl.c | 125 + test/locale-mbwc/dat_iswctype.c | 667 + test/locale-mbwc/dat_iswdigit.c | 125 + test/locale-mbwc/dat_iswgraph.c | 167 + test/locale-mbwc/dat_iswlower.c | 96 + test/locale-mbwc/dat_iswprint.c | 170 + test/locale-mbwc/dat_iswpunct.c | 155 + test/locale-mbwc/dat_iswspace.c | 129 + test/locale-mbwc/dat_iswupper.c | 94 + test/locale-mbwc/dat_iswxdigit.c | 125 + test/locale-mbwc/dat_mblen.c | 137 + test/locale-mbwc/dat_mbrlen.c | 222 + test/locale-mbwc/dat_mbrtowc.c | 140 + test/locale-mbwc/dat_mbsrtowcs.c | 180 + test/locale-mbwc/dat_mbstowcs.c | 190 + test/locale-mbwc/dat_mbtowc.c | 444 + test/locale-mbwc/dat_strcoll.c | 209 + test/locale-mbwc/dat_strfmon.c | 268 + test/locale-mbwc/dat_strxfrm.c | 147 + test/locale-mbwc/dat_swscanf.c | 185 + test/locale-mbwc/dat_tow-funcs.h | 24 + test/locale-mbwc/dat_towctrans.c | 97 + test/locale-mbwc/dat_towlower.c | 47 + test/locale-mbwc/dat_towupper.c | 47 + test/locale-mbwc/dat_wcrtomb.c | 122 + test/locale-mbwc/dat_wcscat.c | 116 + test/locale-mbwc/dat_wcschr.c | 94 + test/locale-mbwc/dat_wcscmp.c | 137 + test/locale-mbwc/dat_wcscoll.c | 210 + test/locale-mbwc/dat_wcscpy.c | 44 + test/locale-mbwc/dat_wcscspn.c | 164 + test/locale-mbwc/dat_wcslen.c | 62 + test/locale-mbwc/dat_wcsncat.c | 158 + test/locale-mbwc/dat_wcsncmp.c | 144 + test/locale-mbwc/dat_wcsncpy.c | 119 + test/locale-mbwc/dat_wcspbrk.c | 176 + test/locale-mbwc/dat_wcsrtombs.c | 272 + test/locale-mbwc/dat_wcsspn.c | 179 + test/locale-mbwc/dat_wcsstr.c | 175 + test/locale-mbwc/dat_wcstod.c | 78 + test/locale-mbwc/dat_wcstok.c | 138 + test/locale-mbwc/dat_wcstombs.c | 271 + test/locale-mbwc/dat_wcswidth.c | 263 + test/locale-mbwc/dat_wcsxfrm.c | 102 + test/locale-mbwc/dat_wctob.c | 61 + test/locale-mbwc/dat_wctomb.c | 168 + test/locale-mbwc/dat_wctrans.c | 99 + test/locale-mbwc/dat_wctype.c | 189 + test/locale-mbwc/dat_wcwidth.c | 149 + test/locale-mbwc/tgn_funcdef.h | 160 + test/locale-mbwc/tgn_locdef.h | 32 + test/locale-mbwc/tsp_common.c | 64 + test/locale-mbwc/tst_funcs.h | 272 + test/locale-mbwc/tst_iswalnum.c | 10 + test/locale-mbwc/tst_iswalpha.c | 10 + test/locale-mbwc/tst_iswcntrl.c | 10 + test/locale-mbwc/tst_iswctype.c | 53 + test/locale-mbwc/tst_iswdigit.c | 11 + test/locale-mbwc/tst_iswgraph.c | 10 + test/locale-mbwc/tst_iswlower.c | 10 + test/locale-mbwc/tst_iswprint.c | 10 + test/locale-mbwc/tst_iswpunct.c | 10 + test/locale-mbwc/tst_iswspace.c | 10 + test/locale-mbwc/tst_iswupper.c | 10 + test/locale-mbwc/tst_iswxdigit.c | 10 + test/locale-mbwc/tst_mblen.c | 85 + test/locale-mbwc/tst_mbrlen.c | 82 + test/locale-mbwc/tst_mbrtowc.c | 103 + test/locale-mbwc/tst_mbsrtowcs.c | 109 + test/locale-mbwc/tst_mbstowcs.c | 98 + test/locale-mbwc/tst_mbtowc.c | 130 + test/locale-mbwc/tst_strcoll.c | 87 + test/locale-mbwc/tst_strfmon.c | 74 + test/locale-mbwc/tst_strxfrm.c | 136 + test/locale-mbwc/tst_swscanf.c | 137 + test/locale-mbwc/tst_towctrans.c | 82 + test/locale-mbwc/tst_towlower.c | 11 + test/locale-mbwc/tst_towupper.c | 10 + test/locale-mbwc/tst_types.h | 729 + test/locale-mbwc/tst_wcrtomb.c | 79 + test/locale-mbwc/tst_wcscat.c | 78 + test/locale-mbwc/tst_wcschr.c | 70 + test/locale-mbwc/tst_wcscmp.c | 40 + test/locale-mbwc/tst_wcscoll.c | 76 + test/locale-mbwc/tst_wcscpy.c | 85 + test/locale-mbwc/tst_wcscspn.c | 38 + test/locale-mbwc/tst_wcslen.c | 31 + test/locale-mbwc/tst_wcsncat.c | 75 + test/locale-mbwc/tst_wcsncmp.c | 40 + test/locale-mbwc/tst_wcsncpy.c | 93 + test/locale-mbwc/tst_wcspbrk.c | 80 + test/locale-mbwc/tst_wcsrtombs.c | 127 + test/locale-mbwc/tst_wcsspn.c | 38 + test/locale-mbwc/tst_wcsstr.c | 86 + test/locale-mbwc/tst_wcstod.c | 69 + test/locale-mbwc/tst_wcstok.c | 96 + test/locale-mbwc/tst_wcstombs.c | 115 + test/locale-mbwc/tst_wcswidth.c | 39 + test/locale-mbwc/tst_wcsxfrm.c | 122 + test/locale-mbwc/tst_wctob.c | 37 + test/locale-mbwc/tst_wctomb.c | 99 + test/locale-mbwc/tst_wctrans.c | 52 + test/locale-mbwc/tst_wctype.c | 48 + test/locale-mbwc/tst_wcwidth.c | 38 + test/locale/Makefile | 31 + test/locale/bug-iconv-trans.c | 68 + test/locale/bug-usesetlocale.c | 38 + test/locale/collate-test.c | 133 + test/locale/dump-ctype.c | 164 + test/locale/gen-unicode-ctype.c | 785 + test/locale/show-ucs-data.c | 62 + test/locale/tst-C-locale.c | 498 + test/locale/tst-ctype-de_DE.ISO-8859-1.in | 56 + test/locale/tst-ctype.c | 447 + test/locale/tst-digits.c | 249 + test/locale/tst-fmon.c | 68 + test/locale/tst-langinfo.c | 284 + test/locale/tst-langinfo.input | 303 + test/locale/tst-leaks.c | 18 + test/locale/tst-mbswcs1.c | 63 + test/locale/tst-mbswcs2.c | 65 + test/locale/tst-mbswcs3.c | 76 + test/locale/tst-mbswcs4.c | 63 + test/locale/tst-mbswcs5.c | 75 + test/locale/tst-mbswcs6.c | 74 + test/locale/tst-numeric.c | 74 + test/locale/tst-rpmatch.c | 37 + test/locale/tst-setlocale.c | 25 + test/locale/tst-sscanf.c | 56 + test/locale/tst-strfmon1.c | 42 + test/locale/tst-trans.c | 71 + test/locale/tst-wctype.c | 144 + test/locale/tst-xlocale1.c | 75 + test/locale/tst-xlocale2.c | 64 + test/locale/tst_nl_langinfo.c | 296 + test/locale/xfrm-test.c | 144 + test/malloc/Makefile | 6 + test/malloc/malloc-standard-alignment.c | 42 + test/malloc/malloc.c | 81 + test/malloc/mallocbug.c | 67 + test/malloc/realloc-can-shrink.c | 17 + test/malloc/realloc0.c | 13 + test/malloc/testmalloc.c | 101 + test/malloc/time_malloc.c | 62 + test/malloc/tst-calloc.c | 126 + test/malloc/tst-malloc.c | 73 + test/malloc/tst-mallocfork.c | 51 + test/malloc/tst-mcheck.c | 96 + test/malloc/tst-obstack.c | 64 + test/malloc/tst-valloc.c | 23 + test/math/Makefile | 26 + test/math/basic-test.c | 123 + test/math/fenv.h | 3 + test/math/gen-libm-test.pl | 738 + test/math/libm-test.inc | 5102 ++++++ test/math/rint.c | 11 + test/math/test-double.c | 34 + test/math/test-float.c | 34 + test/math/test-fpucw.c | 43 + test/math/test-idouble.c | 35 + test/math/test-ifloat.c | 35 + test/math/test-ildoubl.c | 35 + test/math/test-ldouble.c | 34 + test/math/tst-definitions.c | 47 + test/misc/Makefile | 14 + test/misc/bug-glob1.c | 94 + test/misc/bug-glob2.c | 302 + test/misc/bug-readdir1.c | 37 + test/misc/dirent.c | 39 + test/misc/dirent64.c | 1 + test/misc/fdopen.c | 52 + test/misc/opendir-tst1.c | 95 + test/misc/outb.c | 9 + test/misc/popen.c | 47 + test/misc/seek.c | 82 + test/misc/sem.c | 45 + test/misc/stdarg.c | 23 + test/misc/tst-fnmatch.c | 444 + test/misc/tst-fnmatch.input | 755 + test/misc/tst-gnuglob.c | 447 + test/misc/tst-scandir.c | 23 + test/misc/tst-seekdir.c | 79 + test/misc/tst-utmp.c | 404 + test/mmap/Makefile | 4 + test/mmap/mmap.c | 73 + test/mmap/mmap2.c | 41 + test/mmap/mmap64.c | 29 + test/pthread/Makefile | 8 + test/pthread/cancellation-points.c | 280 + test/pthread/ex1.c | 35 + test/pthread/ex2.c | 113 + test/pthread/ex3.c | 152 + test/pthread/ex4.c | 107 + test/pthread/ex5.c | 102 + test/pthread/ex6.c | 41 + test/pthread/ex7.c | 103 + test/pthread/tst-too-many-cleanups.c | 104 + test/pwd_grp/.indent.pro | 33 + test/pwd_grp/Makefile | 10 + test/pwd_grp/getgroups.c | 99 + test/pwd_grp/grcat.c | 32 + test/pwd_grp/pwcat.c | 26 + test/pwd_grp/test_grp.c | 87 + test/pwd_grp/test_pwd.c | 74 + test/regex/.regex.ChangeLog.14 | 2176 +++ test/regex/LICENSE | 72 + test/regex/Makefile | 17 + test/regex/basic.dat | 216 + test/regex/categorize.dat | 62 + test/regex/forcedassoc.dat | 30 + test/regex/interpretation.dat | 93 + test/regex/leftassoc.dat | 16 + test/regex/nullsubexpr.dat | 73 + test/regex/repetition.dat | 79 + test/regex/rightassoc.dat | 16 + test/regex/testregex.c | 2119 +++ test/regex/testregexc.c | 1 + test/regex/testregexf.c | 1 + test/regex/testregexi.c | 1 + test/regex/testregexl.c | 1 + test/regex/testregexn.c | 1 + test/regex/testregexp.c | 1 + test/regex/testregexr.c | 1 + test/regex/tst-regex2.c | 244 + test/regex/tst-regexloc.c | 49 + test/rpc/Makefile | 12 + test/rpc/getrpcent.c | 18 + test/rpc/getrpcent_r.c | 24 + test/setjmp/Makefile | 4 + test/setjmp/bug269-setjmp.c | 107 + test/setjmp/jmpbug.c | 51 + test/setjmp/sigjmpbug.c | 51 + test/setjmp/tst-setjmp.c | 119 + test/setjmp/tst-vfork-longjmp.c | 108 + test/signal/.indent.pro | 33 + test/signal/Makefile | 8 + test/signal/sigchld.c | 68 + test/signal/signal.c | 95 + test/signal/tst-raise.c | 63 + test/signal/tst-signal.c | 44 + test/signal/tst-sigset.c | 45 + test/signal/tst-sigsimple.c | 57 + test/silly/Makefile | 7 + test/silly/hello.c | 8 + test/silly/tiny.c | 6 + test/stat/Makefile | 12 + test/stat/memcmp-stat.c | 107 + test/stat/stat.c | 71 + test/stat/stat64.c | 1 + test/stdio/64bit.c | 12 + test/stdio/Makefile | 6 + test/stdio/fclose-loop.c | 21 + test/stdlib/Makefile | 9 + test/stdlib/ptytest.c | 20 + test/stdlib/qsort.c | 45 + test/stdlib/test-canon.c | 251 + test/stdlib/testatexit.c | 81 + test/stdlib/teston_exit.c | 82 + test/stdlib/teststrtol.c | 109 + test/string/Makefile | 6 + test/string/bug-strcoll1.c | 24 + test/string/bug-strncat1.c | 31 + test/string/bug-strpbrk1.c | 19 + test/string/bug-strspn1.c | 19 + test/string/stratcliff.c | 349 + test/string/test-ffs.c | 66 + test/string/testcopy.c | 108 + test/string/tester.c | 1647 ++ test/string/tst-bswap.c | 74 + test/string/tst-inlcall.c | 83 + test/string/tst-strlen.c | 45 + test/string/tst-strtok.c | 23 + test/string/tst-strxfrm.c | 80 + test/termios/Makefile | 4 + test/termios/termios.c | 25 + test/test-skeleton.c | 394 + test/testsuite.h | 100 + test/time/Makefile | 13 + test/time/bug-asctime.c | 40 + test/time/bug-asctime_r.c | 37 + test/time/clocktest.c | 36 + test/time/test_time.c | 116 + test/time/time.c | 76 + test/time/tst-ftime_l.c | 136 + test/time/tst-mktime.c | 70 + test/time/tst-mktime2.c | 141 + test/time/tst-mktime3.c | 50 + test/time/tst-posixtz.c | 88 + test/time/tst-strftime.c | 111 + test/time/tst-strptime.c | 193 + test/time/tst-strptime2.c | 59 + test/time/tst-timezone.c | 170 + test/time/tst_wcsftime.c | 39 + test/unistd/Makefile | 13 + test/unistd/clone.c | 101 + test/unistd/clone_cruft.h | 24 + test/unistd/errno.c | 29 + test/unistd/exec-null.c | 13 + test/unistd/fork.c | 91 + test/unistd/getcwd.c | 39 + test/unistd/getopt.c | 69 + test/unistd/getopt_long.c | 93 + test/unistd/tst-preadwrite.c | 105 + test/unistd/tst-preadwrite64.c | 24 + test/unistd/tstgetopt.c | 76 + test/unistd/vfork.c | 53 + utils/Makefile | 13 + utils/Makefile.in | 103 + utils/bswap.h | 61 + utils/chroot_realpath.c | 165 + utils/ldconfig.c | 1010 ++ utils/ldd.c | 836 + utils/readelf.c | 363 + utils/readsoname2.c | 143 + 3992 files changed, 478729 insertions(+) create mode 100644 COPYING.LIB create mode 100644 COPYING.LIB.boilerplate create mode 100644 Changelog create mode 100644 DEDICATION.mjn3 create mode 100644 INSTALL create mode 100644 MAINTAINERS create mode 100644 Makefile create mode 100644 Makefile.help create mode 100644 Makefile.in create mode 100644 Makerules create mode 100644 README create mode 100644 Rules.mak create mode 100644 TODO create mode 100644 docs/Glibc_vs_uClibc_Differences.txt create mode 100644 docs/PORTING create mode 100644 docs/man/ldconfig.8 create mode 100644 docs/man/ldd.1 create mode 100644 docs/threads.txt create mode 100644 docs/uClibc_vs_SuSv3.txt create mode 100644 extra/Configs/Config.alpha create mode 100644 extra/Configs/Config.arm create mode 100644 extra/Configs/Config.avr32 create mode 100644 extra/Configs/Config.bfin create mode 100644 extra/Configs/Config.cris create mode 100644 extra/Configs/Config.e1 create mode 100644 extra/Configs/Config.frv create mode 100644 extra/Configs/Config.h8300 create mode 100644 extra/Configs/Config.hppa create mode 100644 extra/Configs/Config.i386 create mode 100644 extra/Configs/Config.i960 create mode 100644 extra/Configs/Config.ia64 create mode 100644 extra/Configs/Config.in create mode 100644 extra/Configs/Config.in.arch create mode 100644 extra/Configs/Config.m68k create mode 100644 extra/Configs/Config.microblaze create mode 100644 extra/Configs/Config.mips create mode 100644 extra/Configs/Config.nios create mode 100644 extra/Configs/Config.nios2 create mode 100644 extra/Configs/Config.powerpc create mode 100644 extra/Configs/Config.sh create mode 100644 extra/Configs/Config.sh64 create mode 100644 extra/Configs/Config.sparc create mode 100644 extra/Configs/Config.v850 create mode 100644 extra/Configs/Config.vax create mode 100644 extra/Configs/Config.x86_64 create mode 100644 extra/Configs/Config.xtensa create mode 100644 extra/Configs/defconfigs/alpha create mode 100644 extra/Configs/defconfigs/arm create mode 100644 extra/Configs/defconfigs/avr32 create mode 100644 extra/Configs/defconfigs/bfin create mode 100644 extra/Configs/defconfigs/cris create mode 100644 extra/Configs/defconfigs/e1 create mode 100644 extra/Configs/defconfigs/frv create mode 100644 extra/Configs/defconfigs/h8300 create mode 100644 extra/Configs/defconfigs/hppa create mode 100644 extra/Configs/defconfigs/i386 create mode 100644 extra/Configs/defconfigs/i960 create mode 100644 extra/Configs/defconfigs/ia64 create mode 100644 extra/Configs/defconfigs/m68k create mode 100644 extra/Configs/defconfigs/microblaze create mode 100644 extra/Configs/defconfigs/mips create mode 100644 extra/Configs/defconfigs/nios create mode 100644 extra/Configs/defconfigs/nios2 create mode 100644 extra/Configs/defconfigs/powerpc create mode 100644 extra/Configs/defconfigs/sh create mode 100644 extra/Configs/defconfigs/sh64 create mode 100644 extra/Configs/defconfigs/sparc create mode 100644 extra/Configs/defconfigs/v850 create mode 100644 extra/Configs/defconfigs/vax create mode 100644 extra/Configs/defconfigs/x86_64 create mode 100644 extra/Makefile create mode 100644 extra/Makefile.in create mode 100644 extra/config/.gitignore create mode 100644 extra/config/Makefile create mode 100644 extra/config/Makefile.kconfig create mode 100644 extra/config/POTFILES.in create mode 100644 extra/config/README.uClibc create mode 100755 extra/config/check.sh create mode 100644 extra/config/conf.c create mode 100644 extra/config/confdata.c create mode 100644 extra/config/expr.c create mode 100644 extra/config/expr.h create mode 100644 extra/config/gconf.c create mode 100644 extra/config/gconf.glade create mode 100644 extra/config/images.c create mode 100644 extra/config/kconfig-language.txt create mode 100644 extra/config/kconfig-to-uclibc.patch.gz create mode 100644 extra/config/kconfig_load.c create mode 100644 extra/config/kxgettext.c create mode 100644 extra/config/lex.zconf.c_shipped create mode 100644 extra/config/lkc.h create mode 100644 extra/config/lkc_proto.h create mode 100644 extra/config/lxdialog/.gitignore create mode 100644 extra/config/lxdialog/BIG.FAT.WARNING create mode 100755 extra/config/lxdialog/check-lxdialog.sh create mode 100644 extra/config/lxdialog/checklist.c create mode 100644 extra/config/lxdialog/dialog.h create mode 100644 extra/config/lxdialog/inputbox.c create mode 100644 extra/config/lxdialog/menubox.c create mode 100644 extra/config/lxdialog/textbox.c create mode 100644 extra/config/lxdialog/util.c create mode 100644 extra/config/lxdialog/yesno.c create mode 100644 extra/config/mconf.c create mode 100644 extra/config/menu.c create mode 100644 extra/config/qconf.cc create mode 100644 extra/config/qconf.h create mode 100644 extra/config/symbol.c create mode 100644 extra/config/util.c create mode 100644 extra/config/zconf.gperf create mode 100644 extra/config/zconf.hash.c_shipped create mode 100644 extra/config/zconf.l create mode 100644 extra/config/zconf.tab.c_shipped create mode 100644 extra/config/zconf.y create mode 100755 extra/libstrip/libstrip create mode 100644 extra/locale/LOCALES create mode 100644 extra/locale/Makefile create mode 100644 extra/locale/Makefile.in create mode 100644 extra/locale/README create mode 100644 extra/locale/charmaps/ARMSCII-8.pairs create mode 100644 extra/locale/charmaps/ASCII.pairs create mode 100644 extra/locale/charmaps/CP1251.pairs create mode 100644 extra/locale/charmaps/CP1255.pairs create mode 100644 extra/locale/charmaps/GEORGIAN-PS.pairs create mode 100644 extra/locale/charmaps/ISO-8859-1.pairs create mode 100644 extra/locale/charmaps/ISO-8859-10.pairs create mode 100644 extra/locale/charmaps/ISO-8859-13.pairs create mode 100644 extra/locale/charmaps/ISO-8859-14.pairs create mode 100644 extra/locale/charmaps/ISO-8859-15.pairs create mode 100644 extra/locale/charmaps/ISO-8859-16.pairs create mode 100644 extra/locale/charmaps/ISO-8859-2.pairs create mode 100644 extra/locale/charmaps/ISO-8859-3.pairs create mode 100644 extra/locale/charmaps/ISO-8859-4.pairs create mode 100644 extra/locale/charmaps/ISO-8859-5.pairs create mode 100644 extra/locale/charmaps/ISO-8859-6.pairs create mode 100644 extra/locale/charmaps/ISO-8859-7.pairs create mode 100644 extra/locale/charmaps/ISO-8859-8.pairs create mode 100644 extra/locale/charmaps/ISO-8859-9.pairs create mode 100644 extra/locale/charmaps/KOI8-R.pairs create mode 100644 extra/locale/charmaps/KOI8-T.pairs create mode 100644 extra/locale/charmaps/KOI8-U.pairs create mode 100644 extra/locale/charmaps/TIS-620.pairs create mode 100644 extra/locale/collation/af_ZA create mode 100644 extra/locale/collation/am_ET create mode 100644 extra/locale/collation/ar_AE create mode 100644 extra/locale/collation/ar_BH create mode 100644 extra/locale/collation/ar_DZ create mode 100644 extra/locale/collation/ar_EG create mode 100644 extra/locale/collation/ar_IN create mode 100644 extra/locale/collation/ar_IQ create mode 100644 extra/locale/collation/ar_JO create mode 100644 extra/locale/collation/ar_KW create mode 100644 extra/locale/collation/ar_LB create mode 100644 extra/locale/collation/ar_LY create mode 100644 extra/locale/collation/ar_MA create mode 100644 extra/locale/collation/ar_OM create mode 100644 extra/locale/collation/ar_QA create mode 100644 extra/locale/collation/ar_SA create mode 100644 extra/locale/collation/ar_SD create mode 100644 extra/locale/collation/ar_SY create mode 100644 extra/locale/collation/ar_TN create mode 100644 extra/locale/collation/ar_YE create mode 100644 extra/locale/collation/az_AZ create mode 100644 extra/locale/collation/be_BY create mode 100644 extra/locale/collation/bg_BG create mode 100644 extra/locale/collation/bn_BD create mode 100644 extra/locale/collation/bn_IN create mode 100644 extra/locale/collation/br_FR create mode 100644 extra/locale/collation/bs_BA create mode 100644 extra/locale/collation/ca_ES create mode 100644 extra/locale/collation/comm create mode 100644 extra/locale/collation/cs_CZ create mode 100644 extra/locale/collation/cy_GB create mode 100644 extra/locale/collation/da_DK create mode 100644 extra/locale/collation/de_AT create mode 100644 extra/locale/collation/de_BE create mode 100644 extra/locale/collation/de_CH create mode 100644 extra/locale/collation/de_DE create mode 100644 extra/locale/collation/de_LU create mode 100644 extra/locale/collation/el_GR create mode 100644 extra/locale/collation/en_AU create mode 100644 extra/locale/collation/en_BW create mode 100644 extra/locale/collation/en_CA create mode 100644 extra/locale/collation/en_DK create mode 100644 extra/locale/collation/en_GB create mode 100644 extra/locale/collation/en_HK create mode 100644 extra/locale/collation/en_IE create mode 100644 extra/locale/collation/en_IN create mode 100644 extra/locale/collation/en_NZ create mode 100644 extra/locale/collation/en_PH create mode 100644 extra/locale/collation/en_SG create mode 100644 extra/locale/collation/en_US create mode 100644 extra/locale/collation/en_ZA create mode 100644 extra/locale/collation/en_ZW create mode 100644 extra/locale/collation/eo_EO create mode 100644 extra/locale/collation/es_AR create mode 100644 extra/locale/collation/es_BO create mode 100644 extra/locale/collation/es_CL create mode 100644 extra/locale/collation/es_CO create mode 100644 extra/locale/collation/es_CR create mode 100644 extra/locale/collation/es_DO create mode 100644 extra/locale/collation/es_EC create mode 100644 extra/locale/collation/es_ES create mode 100644 extra/locale/collation/es_GT create mode 100644 extra/locale/collation/es_HN create mode 100644 extra/locale/collation/es_MX create mode 100644 extra/locale/collation/es_NI create mode 100644 extra/locale/collation/es_PA create mode 100644 extra/locale/collation/es_PE create mode 100644 extra/locale/collation/es_PR create mode 100644 extra/locale/collation/es_PY create mode 100644 extra/locale/collation/es_SV create mode 100644 extra/locale/collation/es_US create mode 100644 extra/locale/collation/es_UY create mode 100644 extra/locale/collation/es_VE create mode 100644 extra/locale/collation/et_EE create mode 100644 extra/locale/collation/eu_ES create mode 100644 extra/locale/collation/fa_IR create mode 100644 extra/locale/collation/fi_FI create mode 100644 extra/locale/collation/fo_FO create mode 100644 extra/locale/collation/fr_BE create mode 100644 extra/locale/collation/fr_CA create mode 100644 extra/locale/collation/fr_CH create mode 100644 extra/locale/collation/fr_FR create mode 100644 extra/locale/collation/fr_LU create mode 100644 extra/locale/collation/ga_IE create mode 100644 extra/locale/collation/gd_GB create mode 100644 extra/locale/collation/gl_ES create mode 100644 extra/locale/collation/gv_GB create mode 100644 extra/locale/collation/he_IL create mode 100644 extra/locale/collation/hi_IN create mode 100644 extra/locale/collation/hr_HR create mode 100644 extra/locale/collation/hu_HU create mode 100644 extra/locale/collation/hy_AM create mode 100644 extra/locale/collation/id_ID create mode 100644 extra/locale/collation/is_IS create mode 100644 extra/locale/collation/iso14651_t1 create mode 100644 extra/locale/collation/it_CH create mode 100644 extra/locale/collation/it_IT create mode 100644 extra/locale/collation/iw_IL create mode 100644 extra/locale/collation/ja_JP create mode 100644 extra/locale/collation/ka_GE create mode 100644 extra/locale/collation/kl_GL create mode 100644 extra/locale/collation/ko_KR create mode 100644 extra/locale/collation/kw_GB create mode 100644 extra/locale/collation/lt_LT create mode 100644 extra/locale/collation/lv_LV create mode 100644 extra/locale/collation/mi_NZ create mode 100644 extra/locale/collation/mk_MK create mode 100644 extra/locale/collation/mr_IN create mode 100644 extra/locale/collation/ms_MY create mode 100644 extra/locale/collation/mt_MT create mode 100644 extra/locale/collation/nl_BE create mode 100644 extra/locale/collation/nl_NL create mode 100644 extra/locale/collation/nn_NO create mode 100644 extra/locale/collation/no_NO create mode 100644 extra/locale/collation/oc_FR create mode 100644 extra/locale/collation/pl_PL create mode 100644 extra/locale/collation/pt_BR create mode 100644 extra/locale/collation/pt_PT create mode 100644 extra/locale/collation/ro_RO create mode 100644 extra/locale/collation/ru_RU create mode 100644 extra/locale/collation/ru_UA create mode 100644 extra/locale/collation/se_NO create mode 100644 extra/locale/collation/sk_SK create mode 100644 extra/locale/collation/sl_SI create mode 100644 extra/locale/collation/sq_AL create mode 100644 extra/locale/collation/sr_YU create mode 100644 extra/locale/collation/sv_FI create mode 100644 extra/locale/collation/sv_SE create mode 100644 extra/locale/collation/ta_IN create mode 100644 extra/locale/collation/te_IN create mode 100644 extra/locale/collation/tg_TJ create mode 100644 extra/locale/collation/th_TH create mode 100644 extra/locale/collation/ti_ER create mode 100644 extra/locale/collation/ti_ET create mode 100644 extra/locale/collation/tl_PH create mode 100644 extra/locale/collation/tr_TR create mode 100644 extra/locale/collation/tt_RU create mode 100644 extra/locale/collation/uk_UA create mode 100644 extra/locale/collation/ur_PK create mode 100644 extra/locale/collation/uz_UZ create mode 100644 extra/locale/collation/vi_VN create mode 100644 extra/locale/collation/wa_BE create mode 100644 extra/locale/collation/yi_US create mode 100644 extra/locale/collation/zh_CN create mode 100644 extra/locale/collation/zh_HK create mode 100644 extra/locale/collation/zh_SG create mode 100644 extra/locale/collation/zh_TW create mode 100644 extra/locale/gen_collate.c create mode 100644 extra/locale/gen_ldc.c create mode 100644 extra/locale/gen_locale.c create mode 100644 extra/locale/gen_mmap.c create mode 100644 extra/locale/gen_wc8bit.c create mode 100644 extra/locale/gen_wctype.c create mode 100644 extra/locale/lmmtolso.c create mode 100644 extra/locale/locale_mmap.h create mode 100644 extra/locale/programs/categories.def create mode 100644 extra/locale/programs/locale.c create mode 100644 extra/locale/tst_nl_langinfo.c create mode 100644 extra/scripts/Makefile.arch.lvl3 create mode 100644 extra/scripts/Makefile.arch.lvl4 create mode 100644 extra/scripts/Makefile.libs.lvl0 create mode 100644 extra/scripts/Makefile.libs.lvl1 create mode 100644 extra/scripts/Makefile.libs.lvl2 create mode 100644 extra/scripts/Makefile.objs.lvl2 create mode 100644 extra/scripts/Makefile.objs.lvl3 create mode 100644 extra/scripts/Makefile.objs.lvl4 create mode 100644 extra/scripts/Makefile.utils.lvl1 create mode 100755 extra/scripts/conf-header.sh create mode 100755 extra/scripts/create_makefiles.sh create mode 100644 extra/scripts/defs.awk create mode 100644 extra/scripts/format.lds create mode 100755 extra/scripts/gen_bits_syscall_h.sh create mode 100755 extra/scripts/getent create mode 100755 extra/scripts/install_headers.sh create mode 100755 extra/scripts/install_kernel_headers.sh create mode 100755 extra/scripts/randconfig.sh create mode 100755 extra/scripts/relative_path.sh create mode 100755 extra/scripts/relinfo.pl create mode 100644 extra/scripts/unifdef.c create mode 100644 include/_lfs_64.h create mode 100644 include/a.out.h create mode 100644 include/alloca.h create mode 100644 include/ar.h create mode 100644 include/arpa/ftp.h create mode 100644 include/arpa/inet.h create mode 100644 include/arpa/nameser.h create mode 100644 include/arpa/nameser_compat.h create mode 100644 include/arpa/telnet.h create mode 100644 include/arpa/tftp.h create mode 100644 include/assert.h create mode 100644 include/atomic.h create mode 100644 include/byteswap.h create mode 100644 include/complex.h create mode 100644 include/cpio.h create mode 100644 include/crypt.h create mode 100644 include/ctype.h create mode 100644 include/dirent.h create mode 100644 include/dlfcn.h create mode 100644 include/elf.h create mode 100644 include/endian.h create mode 100644 include/err.h create mode 100644 include/errno.h create mode 100644 include/error.h create mode 100644 include/fcntl.h create mode 100644 include/features.h create mode 100644 include/fenv.h create mode 100644 include/fnmatch.h create mode 100644 include/ftw.h create mode 100644 include/getopt.h create mode 100644 include/glob.h create mode 100644 include/gnu-versions.h create mode 100644 include/grp.h create mode 100644 include/iconv.h create mode 100644 include/ieee754.h create mode 100644 include/ifaddrs.h create mode 100644 include/inttypes.h create mode 100644 include/langinfo.h create mode 100644 include/lastlog.h create mode 100644 include/libc-internal.h create mode 100644 include/libc-symbols.h create mode 100644 include/libgen.h create mode 100644 include/libintl.h create mode 100644 include/limits.h create mode 100644 include/link.h create mode 100644 include/locale.h create mode 100644 include/malloc.h create mode 100644 include/math.h create mode 100644 include/memory.h create mode 100644 include/mntent.h create mode 100644 include/mqueue.h create mode 100644 include/net/ethernet.h create mode 100644 include/net/if.h create mode 100644 include/net/if_arp.h create mode 100644 include/net/if_packet.h create mode 100644 include/net/if_ppp.h create mode 100644 include/net/if_shaper.h create mode 100644 include/net/if_slip.h create mode 100644 include/net/ppp-comp.h create mode 100644 include/net/ppp_defs.h create mode 100644 include/net/route.h create mode 100644 include/netax25/ax25.h create mode 100644 include/netdb.h create mode 100644 include/neteconet/ec.h create mode 100644 include/netinet/ether.h create mode 100644 include/netinet/icmp6.h create mode 100644 include/netinet/if_ether.h create mode 100644 include/netinet/if_fddi.h create mode 100644 include/netinet/if_tr.h create mode 100644 include/netinet/igmp.h create mode 100644 include/netinet/in.h create mode 100644 include/netinet/in_systm.h create mode 100644 include/netinet/ip.h create mode 100644 include/netinet/ip6.h create mode 100644 include/netinet/ip_icmp.h create mode 100644 include/netinet/protocols.h create mode 100644 include/netinet/tcp.h create mode 100644 include/netinet/udp.h create mode 100644 include/netipx/ipx.h create mode 100644 include/netpacket/packet.h create mode 100644 include/nl_types.h create mode 100644 include/obstack.h create mode 100644 include/paths.h create mode 100644 include/poll.h create mode 100644 include/printf.h create mode 100644 include/protocols/routed.h create mode 100644 include/protocols/rwhod.h create mode 100644 include/protocols/talkd.h create mode 100644 include/protocols/timed.h create mode 100644 include/pty.h create mode 100644 include/pwd.h create mode 100644 include/regex.h create mode 100644 include/regexp.h create mode 100644 include/resolv.h create mode 100644 include/rpc/auth.h create mode 100644 include/rpc/auth_des.h create mode 100644 include/rpc/auth_unix.h create mode 100644 include/rpc/clnt.h create mode 100644 include/rpc/des_crypt.h create mode 100644 include/rpc/key_prot.h create mode 100644 include/rpc/netdb.h create mode 100644 include/rpc/pmap_clnt.h create mode 100644 include/rpc/pmap_prot.h create mode 100644 include/rpc/pmap_rmt.h create mode 100644 include/rpc/rpc.h create mode 100644 include/rpc/rpc_des.h create mode 100644 include/rpc/rpc_msg.h create mode 100644 include/rpc/svc.h create mode 100644 include/rpc/svc_auth.h create mode 100644 include/rpc/types.h create mode 100644 include/rpc/xdr.h create mode 100644 include/sched.h create mode 100644 include/scsi/scsi.h create mode 100644 include/scsi/scsi_ioctl.h create mode 100644 include/scsi/sg.h create mode 100644 include/search.h create mode 100644 include/setjmp.h create mode 100644 include/sgtty.h create mode 100644 include/shadow.h create mode 100644 include/signal.h create mode 100644 include/stdint.h create mode 100644 include/stdio.h create mode 100644 include/stdio_ext.h create mode 100644 include/stdlib.h create mode 100644 include/string.h create mode 100644 include/strings.h create mode 100644 include/sys/bitypes.h create mode 100644 include/sys/cdefs.h create mode 100644 include/sys/dir.h create mode 100644 include/sys/errno.h create mode 100644 include/sys/fcntl.h create mode 100644 include/sys/file.h create mode 100644 include/sys/fsuid.h create mode 100644 include/sys/ioctl.h create mode 100644 include/sys/ipc.h create mode 100644 include/sys/kd.h create mode 100644 include/sys/kdaemon.h create mode 100644 include/sys/klog.h create mode 100644 include/sys/mman.h create mode 100644 include/sys/mount.h create mode 100644 include/sys/msg.h create mode 100644 include/sys/mtio.h create mode 100644 include/sys/param.h create mode 100644 include/sys/personality.h create mode 100644 include/sys/poll.h create mode 100644 include/sys/queue.h create mode 100644 include/sys/quota.h create mode 100644 include/sys/reboot.h create mode 100644 include/sys/resource.h create mode 100644 include/sys/select.h create mode 100644 include/sys/sem.h create mode 100644 include/sys/sendfile.h create mode 100644 include/sys/shm.h create mode 100644 include/sys/signal.h create mode 100644 include/sys/signalfd.h create mode 100644 include/sys/socket.h create mode 100644 include/sys/socketvar.h create mode 100644 include/sys/soundcard.h create mode 100644 include/sys/stat.h create mode 100644 include/sys/statfs.h create mode 100644 include/sys/statvfs.h create mode 100644 include/sys/swap.h create mode 100644 include/sys/syscall.h create mode 100644 include/sys/sysctl.h create mode 100644 include/sys/sysinfo.h create mode 100644 include/sys/syslog.h create mode 100644 include/sys/sysmacros.h create mode 100644 include/sys/termios.h create mode 100644 include/sys/time.h create mode 100644 include/sys/timeb.h create mode 100644 include/sys/times.h create mode 100644 include/sys/timex.h create mode 100644 include/sys/ttydefaults.h create mode 100644 include/sys/types.h create mode 100644 include/sys/uio.h create mode 100644 include/sys/un.h create mode 100644 include/sys/unistd.h create mode 100644 include/sys/ustat.h create mode 100644 include/sys/utsname.h create mode 100644 include/sys/vfs.h create mode 100644 include/sys/vt.h create mode 100644 include/sys/wait.h create mode 100644 include/sys/xattr.h create mode 100644 include/syscall.h create mode 100644 include/sysexits.h create mode 100644 include/syslog.h create mode 100644 include/tar.h create mode 100644 include/termio.h create mode 100644 include/termios.h create mode 100644 include/tgmath.h create mode 100644 include/time.h create mode 100644 include/ttyent.h create mode 100644 include/ucontext.h create mode 100644 include/ulimit.h create mode 100644 include/unistd.h create mode 100644 include/ustat.h create mode 100644 include/utime.h create mode 100644 include/utmp.h create mode 100644 include/values.h create mode 100644 include/wait.h create mode 100644 include/wchar.h create mode 100644 include/wctype.h create mode 100644 include/wordexp.h create mode 100644 include/xlocale.h create mode 100644 ldso/COPYRIGHT create mode 100644 ldso/Makefile create mode 100644 ldso/Makefile.in create mode 100644 ldso/README create mode 100644 ldso/include/dl-defs.h create mode 100644 ldso/include/dl-elf.h create mode 100644 ldso/include/dl-hash.h create mode 100644 ldso/include/dl-string.h create mode 100644 ldso/include/dl-syscall.h create mode 100644 ldso/include/dlfcn.h create mode 100644 ldso/include/ldso.h create mode 100644 ldso/include/unsecvars.h create mode 100644 ldso/ldso/Makefile create mode 100644 ldso/ldso/Makefile.in create mode 100644 ldso/ldso/arm/dl-debug.h create mode 100644 ldso/ldso/arm/dl-startup.h create mode 100644 ldso/ldso/arm/dl-syscalls.h create mode 100644 ldso/ldso/arm/dl-sysdep.h create mode 100644 ldso/ldso/arm/elfinterp.c create mode 100644 ldso/ldso/arm/resolve.S create mode 100644 ldso/ldso/avr32/dl-debug.h create mode 100644 ldso/ldso/avr32/dl-startup.h create mode 100644 ldso/ldso/avr32/dl-syscalls.h create mode 100644 ldso/ldso/avr32/dl-sysdep.h create mode 100644 ldso/ldso/avr32/elfinterp.c create mode 100644 ldso/ldso/avr32/resolve.S create mode 100644 ldso/ldso/bfin/dl-debug.h create mode 100644 ldso/ldso/bfin/dl-inlines.h create mode 100644 ldso/ldso/bfin/dl-startup.h create mode 100644 ldso/ldso/bfin/dl-syscalls.h create mode 100644 ldso/ldso/bfin/dl-sysdep.h create mode 100644 ldso/ldso/bfin/elfinterp.c create mode 100644 ldso/ldso/bfin/resolve.S create mode 100644 ldso/ldso/cris/dl-debug.h create mode 100644 ldso/ldso/cris/dl-startup.h create mode 100644 ldso/ldso/cris/dl-syscalls.h create mode 100644 ldso/ldso/cris/dl-sysdep.h create mode 100644 ldso/ldso/cris/elfinterp.c create mode 100644 ldso/ldso/cris/resolve.S create mode 100644 ldso/ldso/dl-array.c create mode 100644 ldso/ldso/dl-debug.c create mode 100644 ldso/ldso/dl-elf.c create mode 100644 ldso/ldso/dl-hash.c create mode 100644 ldso/ldso/dl-startup.c create mode 100644 ldso/ldso/frv/dl-debug.h create mode 100644 ldso/ldso/frv/dl-inlines.h create mode 100644 ldso/ldso/frv/dl-startup.h create mode 100644 ldso/ldso/frv/dl-syscalls.h create mode 100644 ldso/ldso/frv/dl-sysdep.h create mode 100644 ldso/ldso/frv/elfinterp.c create mode 100644 ldso/ldso/frv/resolve.S create mode 100644 ldso/ldso/i386/dl-debug.h create mode 100644 ldso/ldso/i386/dl-startup.h create mode 100644 ldso/ldso/i386/dl-syscalls.h create mode 100644 ldso/ldso/i386/dl-sysdep.h create mode 100644 ldso/ldso/i386/elfinterp.c create mode 100644 ldso/ldso/i386/resolve.S create mode 100644 ldso/ldso/ldso.c create mode 100644 ldso/ldso/m68k/dl-debug.h create mode 100644 ldso/ldso/m68k/dl-startup.h create mode 100644 ldso/ldso/m68k/dl-syscalls.h create mode 100644 ldso/ldso/m68k/dl-sysdep.h create mode 100644 ldso/ldso/m68k/elfinterp.c create mode 100644 ldso/ldso/m68k/resolve.S create mode 100644 ldso/ldso/mips/README create mode 100644 ldso/ldso/mips/dl-debug.h create mode 100644 ldso/ldso/mips/dl-startup.h create mode 100644 ldso/ldso/mips/dl-syscalls.h create mode 100644 ldso/ldso/mips/dl-sysdep.h create mode 100644 ldso/ldso/mips/elfinterp.c create mode 100644 ldso/ldso/mips/resolve.S create mode 100644 ldso/ldso/powerpc/dl-debug.h create mode 100644 ldso/ldso/powerpc/dl-startup.h create mode 100644 ldso/ldso/powerpc/dl-syscalls.h create mode 100644 ldso/ldso/powerpc/dl-sysdep.h create mode 100644 ldso/ldso/powerpc/elfinterp.c create mode 100644 ldso/ldso/powerpc/resolve.S create mode 100644 ldso/ldso/sh/dl-debug.h create mode 100644 ldso/ldso/sh/dl-startup.h create mode 100644 ldso/ldso/sh/dl-syscalls.h create mode 100644 ldso/ldso/sh/dl-sysdep.h create mode 100644 ldso/ldso/sh/elfinterp.c create mode 100644 ldso/ldso/sh/resolve.S create mode 100644 ldso/ldso/sh64/dl-debug.h create mode 100644 ldso/ldso/sh64/dl-startup.h create mode 100644 ldso/ldso/sh64/dl-syscalls.h create mode 100644 ldso/ldso/sh64/dl-sysdep.h create mode 100644 ldso/ldso/sh64/elfinterp.c create mode 100644 ldso/ldso/sh64/resolve.S create mode 100644 ldso/ldso/sparc/dl-debug.h create mode 100644 ldso/ldso/sparc/dl-startup.h create mode 100644 ldso/ldso/sparc/dl-syscalls.h create mode 100644 ldso/ldso/sparc/dl-sysdep.h create mode 100644 ldso/ldso/sparc/elfinterp.c create mode 100644 ldso/ldso/sparc/resolve.S create mode 100644 ldso/ldso/x86_64/dl-debug.h create mode 100644 ldso/ldso/x86_64/dl-startup.h create mode 100644 ldso/ldso/x86_64/dl-syscalls.h create mode 100644 ldso/ldso/x86_64/dl-sysdep.h create mode 100644 ldso/ldso/x86_64/elfinterp.c create mode 100644 ldso/ldso/x86_64/resolve.S create mode 100644 ldso/ldso/xtensa/dl-debug.h create mode 100644 ldso/ldso/xtensa/dl-startup.h create mode 100644 ldso/ldso/xtensa/dl-syscalls.h create mode 100644 ldso/ldso/xtensa/dl-sysdep.h create mode 100644 ldso/ldso/xtensa/elfinterp.c create mode 100644 ldso/ldso/xtensa/resolve.S create mode 100644 ldso/libdl/Makefile create mode 100644 ldso/libdl/Makefile.in create mode 100644 ldso/libdl/libdl.c create mode 100644 ldso/man/Makefile create mode 100644 ldso/man/dlopen.3 create mode 100644 ldso/man/ld.so.8 create mode 100644 ldso/man/ld.so.texi create mode 100644 ldso/man/ldconfig.8 create mode 100644 ldso/man/ldd.1 create mode 100644 libc/Makefile create mode 100644 libc/Makefile.in create mode 100644 libc/inet/.indent.pro create mode 100644 libc/inet/Makefile create mode 100644 libc/inet/Makefile.in create mode 100644 libc/inet/accept.c create mode 100644 libc/inet/addr.c create mode 100644 libc/inet/bind.c create mode 100644 libc/inet/closenameservers.c create mode 100644 libc/inet/connect.c create mode 100644 libc/inet/decodea.c create mode 100644 libc/inet/decoded.c create mode 100644 libc/inet/decodeh.c create mode 100644 libc/inet/decodep.c create mode 100644 libc/inet/decodeq.c create mode 100644 libc/inet/dnslookup.c create mode 100644 libc/inet/encodea.c create mode 100644 libc/inet/encoded.c create mode 100644 libc/inet/encodeh.c create mode 100644 libc/inet/encodep.c create mode 100644 libc/inet/encodeq.c create mode 100644 libc/inet/ether_addr.c create mode 100644 libc/inet/ethers.c create mode 100644 libc/inet/formquery.c create mode 100644 libc/inet/gai_strerror.c create mode 100644 libc/inet/get_hosts_byaddr_r.c create mode 100644 libc/inet/get_hosts_byname_r.c create mode 100644 libc/inet/getaddrinfo.c create mode 100644 libc/inet/gethostbyaddr.c create mode 100644 libc/inet/gethostbyaddr_r.c create mode 100644 libc/inet/gethostbyname.c create mode 100644 libc/inet/gethostbyname2.c create mode 100644 libc/inet/gethostbyname2_r.c create mode 100644 libc/inet/gethostbyname_r.c create mode 100644 libc/inet/gethostent.c create mode 100644 libc/inet/getnameinfo.c create mode 100644 libc/inet/getnetbyad.c create mode 100644 libc/inet/getnetbynm.c create mode 100644 libc/inet/getnetent.c create mode 100644 libc/inet/getpeername.c create mode 100644 libc/inet/getproto.c create mode 100644 libc/inet/getservice.c create mode 100644 libc/inet/getsockname.c create mode 100644 libc/inet/getsockopt.c create mode 100644 libc/inet/herror.c create mode 100644 libc/inet/hostid.c create mode 100644 libc/inet/if_index.c create mode 100644 libc/inet/ifaddrs.c create mode 100644 libc/inet/in6_addr.c create mode 100644 libc/inet/inet_addr.c create mode 100644 libc/inet/inet_aton.c create mode 100644 libc/inet/inet_lnaof.c create mode 100644 libc/inet/inet_makeaddr.c create mode 100644 libc/inet/inet_net.c create mode 100644 libc/inet/inet_netof.c create mode 100644 libc/inet/inet_ntoa.c create mode 100644 libc/inet/lengthd.c create mode 100644 libc/inet/lengthq.c create mode 100644 libc/inet/listen.c create mode 100644 libc/inet/netlinkaccess.h create mode 100644 libc/inet/ns_name.c create mode 100644 libc/inet/ntohl.c create mode 100644 libc/inet/ntop.c create mode 100644 libc/inet/opennameservers.c create mode 100644 libc/inet/opensock.c create mode 100644 libc/inet/read_etc_hosts_r.c create mode 100644 libc/inet/recv.c create mode 100644 libc/inet/recvfrom.c create mode 100644 libc/inet/recvmsg.c create mode 100644 libc/inet/res_comp.c create mode 100644 libc/inet/res_init.c create mode 100644 libc/inet/res_query.c create mode 100644 libc/inet/resolv.c create mode 100644 libc/inet/resolveaddress.c create mode 100644 libc/inet/resolvename.c create mode 100644 libc/inet/rpc/.indent.pro create mode 100644 libc/inet/rpc/Makefile create mode 100644 libc/inet/rpc/Makefile.in create mode 100644 libc/inet/rpc/auth_none.c create mode 100644 libc/inet/rpc/auth_unix.c create mode 100644 libc/inet/rpc/authunix_prot.c create mode 100644 libc/inet/rpc/bindresvport.c create mode 100644 libc/inet/rpc/clnt_generic.c create mode 100644 libc/inet/rpc/clnt_perror.c create mode 100644 libc/inet/rpc/clnt_raw.c create mode 100644 libc/inet/rpc/clnt_simple.c create mode 100644 libc/inet/rpc/clnt_tcp.c create mode 100644 libc/inet/rpc/clnt_udp.c create mode 100644 libc/inet/rpc/clnt_unix.c create mode 100644 libc/inet/rpc/create_xid.c create mode 100644 libc/inet/rpc/errqueue.h create mode 100644 libc/inet/rpc/get_myaddress.c create mode 100644 libc/inet/rpc/getrpcent.c create mode 100644 libc/inet/rpc/getrpcport.c create mode 100644 libc/inet/rpc/pm_getmaps.c create mode 100644 libc/inet/rpc/pm_getport.c create mode 100644 libc/inet/rpc/pmap_clnt.c create mode 100644 libc/inet/rpc/pmap_prot.c create mode 100644 libc/inet/rpc/pmap_prot2.c create mode 100644 libc/inet/rpc/pmap_rmt.c create mode 100644 libc/inet/rpc/rcmd.c create mode 100644 libc/inet/rpc/rexec.c create mode 100644 libc/inet/rpc/rpc_cmsg.c create mode 100644 libc/inet/rpc/rpc_commondata.c create mode 100644 libc/inet/rpc/rpc_dtablesize.c create mode 100644 libc/inet/rpc/rpc_private.h create mode 100644 libc/inet/rpc/rpc_prot.c create mode 100644 libc/inet/rpc/rpc_thread.c create mode 100644 libc/inet/rpc/rtime.c create mode 100644 libc/inet/rpc/ruserpass.c create mode 100644 libc/inet/rpc/sa_len.c create mode 100644 libc/inet/rpc/svc.c create mode 100644 libc/inet/rpc/svc_auth.c create mode 100644 libc/inet/rpc/svc_authux.c create mode 100644 libc/inet/rpc/svc_raw.c create mode 100644 libc/inet/rpc/svc_run.c create mode 100644 libc/inet/rpc/svc_simple.c create mode 100644 libc/inet/rpc/svc_tcp.c create mode 100644 libc/inet/rpc/svc_udp.c create mode 100644 libc/inet/rpc/svc_unix.c create mode 100644 libc/inet/rpc/xdr.c create mode 100644 libc/inet/rpc/xdr_array.c create mode 100644 libc/inet/rpc/xdr_float.c create mode 100644 libc/inet/rpc/xdr_intXX_t.c create mode 100644 libc/inet/rpc/xdr_mem.c create mode 100644 libc/inet/rpc/xdr_rec.c create mode 100644 libc/inet/rpc/xdr_reference.c create mode 100644 libc/inet/rpc/xdr_stdio.c create mode 100644 libc/inet/send.c create mode 100644 libc/inet/sendmsg.c create mode 100644 libc/inet/sendto.c create mode 100644 libc/inet/setsockopt.c create mode 100644 libc/inet/shutdown.c create mode 100644 libc/inet/socket.c create mode 100644 libc/inet/socketcalls.c create mode 100644 libc/inet/socketpair.c create mode 100644 libc/misc/Makefile create mode 100644 libc/misc/Makefile.in create mode 100644 libc/misc/assert/.indent.pro create mode 100644 libc/misc/assert/Makefile create mode 100644 libc/misc/assert/Makefile.in create mode 100644 libc/misc/assert/__assert.c create mode 100644 libc/misc/ctype/.indent.pro create mode 100644 libc/misc/ctype/Makefile create mode 100644 libc/misc/ctype/Makefile.in create mode 100644 libc/misc/ctype/__C_ctype_b.c create mode 100644 libc/misc/ctype/__C_ctype_tolower.c create mode 100644 libc/misc/ctype/__C_ctype_toupper.c create mode 100644 libc/misc/ctype/__ctype_assert.c create mode 100644 libc/misc/ctype/__ctype_b_loc.c create mode 100644 libc/misc/ctype/__ctype_tolower_loc.c create mode 100644 libc/misc/ctype/__ctype_toupper_loc.c create mode 100644 libc/misc/ctype/ctype.c create mode 100644 libc/misc/ctype/isalnum.c create mode 100644 libc/misc/ctype/isalnum_l.c create mode 100644 libc/misc/ctype/isalpha.c create mode 100644 libc/misc/ctype/isalpha_l.c create mode 100644 libc/misc/ctype/isascii.c create mode 100644 libc/misc/ctype/isascii_l.c create mode 100644 libc/misc/ctype/isblank.c create mode 100644 libc/misc/ctype/isblank_l.c create mode 100644 libc/misc/ctype/iscntrl.c create mode 100644 libc/misc/ctype/iscntrl_l.c create mode 100644 libc/misc/ctype/isctype.c create mode 100644 libc/misc/ctype/isdigit.c create mode 100644 libc/misc/ctype/isdigit_l.c create mode 100644 libc/misc/ctype/isgraph.c create mode 100644 libc/misc/ctype/isgraph_l.c create mode 100644 libc/misc/ctype/islower.c create mode 100644 libc/misc/ctype/islower_l.c create mode 100644 libc/misc/ctype/isprint.c create mode 100644 libc/misc/ctype/isprint_l.c create mode 100644 libc/misc/ctype/ispunct.c create mode 100644 libc/misc/ctype/ispunct_l.c create mode 100644 libc/misc/ctype/isspace.c create mode 100644 libc/misc/ctype/isspace_l.c create mode 100644 libc/misc/ctype/isupper.c create mode 100644 libc/misc/ctype/isupper_l.c create mode 100644 libc/misc/ctype/isxdigit.c create mode 100644 libc/misc/ctype/isxdigit_l.c create mode 100644 libc/misc/ctype/toascii.c create mode 100644 libc/misc/ctype/toascii_l.c create mode 100644 libc/misc/ctype/tolower.c create mode 100644 libc/misc/ctype/tolower_l.c create mode 100644 libc/misc/ctype/toupper.c create mode 100644 libc/misc/ctype/toupper_l.c create mode 100644 libc/misc/dirent/Makefile create mode 100644 libc/misc/dirent/Makefile.in create mode 100644 libc/misc/dirent/alphasort.c create mode 100644 libc/misc/dirent/alphasort64.c create mode 100644 libc/misc/dirent/closedir.c create mode 100644 libc/misc/dirent/dirfd.c create mode 100644 libc/misc/dirent/dirstream.h create mode 100644 libc/misc/dirent/opendir.c create mode 100644 libc/misc/dirent/readdir.c create mode 100644 libc/misc/dirent/readdir64.c create mode 100644 libc/misc/dirent/readdir64_r.c create mode 100644 libc/misc/dirent/readdir_r.c create mode 100644 libc/misc/dirent/rewinddir.c create mode 100644 libc/misc/dirent/scandir.c create mode 100644 libc/misc/dirent/scandir64.c create mode 100644 libc/misc/dirent/seekdir.c create mode 100644 libc/misc/dirent/telldir.c create mode 100644 libc/misc/error/Makefile create mode 100644 libc/misc/error/Makefile.in create mode 100644 libc/misc/error/err.c create mode 100644 libc/misc/error/error.c create mode 100644 libc/misc/file/Makefile create mode 100644 libc/misc/file/Makefile.in create mode 100644 libc/misc/file/lockf.c create mode 100644 libc/misc/file/lockf64.c create mode 100644 libc/misc/fnmatch/.indent.pro create mode 100644 libc/misc/fnmatch/Makefile create mode 100644 libc/misc/fnmatch/Makefile.in create mode 100644 libc/misc/fnmatch/fnmatch.c create mode 100644 libc/misc/fnmatch/fnmatch_loop.c create mode 100644 libc/misc/fnmatch/fnmatch_old.c create mode 100644 libc/misc/ftw/Makefile create mode 100644 libc/misc/ftw/Makefile.in create mode 100644 libc/misc/ftw/ftw.c create mode 100644 libc/misc/ftw/ftw64.c create mode 100644 libc/misc/glob/.indent.pro create mode 100644 libc/misc/glob/Makefile create mode 100644 libc/misc/glob/Makefile.in create mode 100644 libc/misc/glob/glob-susv3.c create mode 100644 libc/misc/glob/glob.c create mode 100644 libc/misc/glob/glob64-susv3.c create mode 100644 libc/misc/glob/glob64.c create mode 100644 libc/misc/gnu/Makefile create mode 100644 libc/misc/gnu/Makefile.in create mode 100644 libc/misc/gnu/obstack.c create mode 100644 libc/misc/internals/Makefile create mode 100644 libc/misc/internals/Makefile.in create mode 100644 libc/misc/internals/__errno_location.c create mode 100644 libc/misc/internals/__h_errno_location.c create mode 100644 libc/misc/internals/__uClibc_main.c create mode 100644 libc/misc/internals/errno.c create mode 100644 libc/misc/internals/internal_errno.h create mode 100644 libc/misc/internals/shared_flat_add_library.c create mode 100644 libc/misc/internals/shared_flat_initfini.c create mode 100644 libc/misc/internals/shared_flat_lib.h create mode 100644 libc/misc/internals/tempname.c create mode 100644 libc/misc/internals/tempname.h create mode 100644 libc/misc/locale/Makefile create mode 100644 libc/misc/locale/Makefile.in create mode 100644 libc/misc/locale/__curlocale.c create mode 100644 libc/misc/locale/__locale_mbrtowc_l.c create mode 100644 libc/misc/locale/_locale_init.c create mode 100644 libc/misc/locale/duplocale.c create mode 100644 libc/misc/locale/freelocale.c create mode 100644 libc/misc/locale/locale.c create mode 100644 libc/misc/locale/localeconv.c create mode 100644 libc/misc/locale/newlocale.c create mode 100644 libc/misc/locale/nl_langinfo.c create mode 100644 libc/misc/locale/nl_langinfo_l.c create mode 100644 libc/misc/locale/setlocale.c create mode 100644 libc/misc/locale/uselocale.c create mode 100644 libc/misc/mntent/.indent.pro create mode 100644 libc/misc/mntent/Makefile create mode 100644 libc/misc/mntent/Makefile.in create mode 100644 libc/misc/mntent/mntent.c create mode 100644 libc/misc/pthread/Makefile create mode 100644 libc/misc/pthread/Makefile.in create mode 100644 libc/misc/pthread/unlock.c create mode 100644 libc/misc/pthread/weaks.c create mode 100644 libc/misc/regex/.indent.pro create mode 100644 libc/misc/regex/Makefile create mode 100644 libc/misc/regex/Makefile.in create mode 100644 libc/misc/regex/_regex.h create mode 100644 libc/misc/regex/regcomp.c create mode 100644 libc/misc/regex/regex.c create mode 100644 libc/misc/regex/regex_internal.c create mode 100644 libc/misc/regex/regex_internal.h create mode 100644 libc/misc/regex/regex_old.c create mode 100644 libc/misc/regex/regexec.c create mode 100644 libc/misc/search/Makefile create mode 100644 libc/misc/search/Makefile.in create mode 100644 libc/misc/search/_hsearch_r.c create mode 100644 libc/misc/search/_lsearch.c create mode 100644 libc/misc/search/_tsearch.c create mode 100644 libc/misc/search/hcreate_r.c create mode 100644 libc/misc/search/hdestroy_r.c create mode 100644 libc/misc/search/hsearch.c create mode 100644 libc/misc/search/hsearch_r.c create mode 100644 libc/misc/search/insque.c create mode 100644 libc/misc/search/insremque.c create mode 100644 libc/misc/search/lfind.c create mode 100644 libc/misc/search/lsearch.c create mode 100644 libc/misc/search/remque.c create mode 100644 libc/misc/search/tdelete.c create mode 100644 libc/misc/search/tdestroy.c create mode 100644 libc/misc/search/tfind.c create mode 100644 libc/misc/search/tsearch.c create mode 100644 libc/misc/search/twalk.c create mode 100644 libc/misc/statfs/Makefile create mode 100644 libc/misc/statfs/Makefile.in create mode 100644 libc/misc/statfs/fstatfs64.c create mode 100644 libc/misc/statfs/fstatvfs.c create mode 100644 libc/misc/statfs/fstatvfs64.c create mode 100644 libc/misc/statfs/internal_statvfs.c create mode 100644 libc/misc/statfs/statfs64.c create mode 100644 libc/misc/statfs/statvfs.c create mode 100644 libc/misc/statfs/statvfs64.c create mode 100644 libc/misc/syslog/Makefile create mode 100644 libc/misc/syslog/Makefile.in create mode 100644 libc/misc/syslog/syslog.c create mode 100644 libc/misc/sysvipc/.indent.pro create mode 100644 libc/misc/sysvipc/Makefile create mode 100644 libc/misc/sysvipc/Makefile.in create mode 100644 libc/misc/sysvipc/__syscall_ipc.c create mode 100644 libc/misc/sysvipc/ftok.c create mode 100644 libc/misc/sysvipc/ipc.h create mode 100644 libc/misc/sysvipc/msgctl.c create mode 100644 libc/misc/sysvipc/msgget.c create mode 100644 libc/misc/sysvipc/msgq.c create mode 100644 libc/misc/sysvipc/msgrcv.c create mode 100644 libc/misc/sysvipc/msgsnd.c create mode 100644 libc/misc/sysvipc/sem.c create mode 100644 libc/misc/sysvipc/semctl.c create mode 100644 libc/misc/sysvipc/semget.c create mode 100644 libc/misc/sysvipc/semop.c create mode 100644 libc/misc/sysvipc/semtimedop.c create mode 100644 libc/misc/sysvipc/shm.c create mode 100644 libc/misc/sysvipc/shmat.c create mode 100644 libc/misc/sysvipc/shmctl.c create mode 100644 libc/misc/sysvipc/shmdt.c create mode 100644 libc/misc/sysvipc/shmget.c create mode 100644 libc/misc/time/.indent.pro create mode 100644 libc/misc/time/Makefile create mode 100644 libc/misc/time/Makefile.in create mode 100644 libc/misc/time/__time_tm.c create mode 100644 libc/misc/time/_time_localtime_tzi.c create mode 100644 libc/misc/time/_time_mktime.c create mode 100644 libc/misc/time/_time_mktime_tzi.c create mode 100644 libc/misc/time/_time_t2tm.c create mode 100644 libc/misc/time/adjtime.c create mode 100644 libc/misc/time/asctime.c create mode 100644 libc/misc/time/asctime_r.c create mode 100644 libc/misc/time/clock.c create mode 100644 libc/misc/time/ctime.c create mode 100644 libc/misc/time/ctime_r.c create mode 100644 libc/misc/time/difftime.c create mode 100644 libc/misc/time/dysize.c create mode 100644 libc/misc/time/ftime.c create mode 100644 libc/misc/time/gmtime.c create mode 100644 libc/misc/time/gmtime_r.c create mode 100644 libc/misc/time/localtime.c create mode 100644 libc/misc/time/localtime_r.c create mode 100644 libc/misc/time/mktime.c create mode 100644 libc/misc/time/strftime.c create mode 100644 libc/misc/time/strftime_l.c create mode 100644 libc/misc/time/strptime.c create mode 100644 libc/misc/time/strptime_l.c create mode 100644 libc/misc/time/time.c create mode 100644 libc/misc/time/timegm.c create mode 100644 libc/misc/time/tzset.c create mode 100644 libc/misc/time/wcsftime.c create mode 100644 libc/misc/time/wcsftime_l.c create mode 100644 libc/misc/ttyent/Makefile create mode 100644 libc/misc/ttyent/Makefile.in create mode 100644 libc/misc/ttyent/getttyent.c create mode 100644 libc/misc/utmp/Makefile create mode 100644 libc/misc/utmp/Makefile.in create mode 100644 libc/misc/utmp/utent.c create mode 100644 libc/misc/utmp/wtent.c create mode 100644 libc/misc/wchar/Makefile create mode 100644 libc/misc/wchar/Makefile.in create mode 100644 libc/misc/wchar/_wchar_utf8sntowcs.c create mode 100644 libc/misc/wchar/_wchar_wcsntoutf8s.c create mode 100644 libc/misc/wchar/btowc.c create mode 100644 libc/misc/wchar/iconv.c create mode 100644 libc/misc/wchar/mbrlen.c create mode 100644 libc/misc/wchar/mbrtowc.c create mode 100644 libc/misc/wchar/mbsinit.c create mode 100644 libc/misc/wchar/mbsnrtowcs.c create mode 100644 libc/misc/wchar/mbsrtowcs.c create mode 100644 libc/misc/wchar/wchar.c create mode 100644 libc/misc/wchar/wcrtomb.c create mode 100644 libc/misc/wchar/wcsnrtombs.c create mode 100644 libc/misc/wchar/wcsrtombs.c create mode 100644 libc/misc/wchar/wcswidth.c create mode 100644 libc/misc/wchar/wctob.c create mode 100644 libc/misc/wchar/wcwidth.c create mode 100644 libc/misc/wctype/Makefile create mode 100644 libc/misc/wctype/Makefile.in create mode 100644 libc/misc/wctype/_wctype.c create mode 100644 libc/misc/wctype/iswalnum.c create mode 100644 libc/misc/wctype/iswalnum_l.c create mode 100644 libc/misc/wctype/iswalpha.c create mode 100644 libc/misc/wctype/iswalpha_l.c create mode 100644 libc/misc/wctype/iswblank.c create mode 100644 libc/misc/wctype/iswblank_l.c create mode 100644 libc/misc/wctype/iswcntrl.c create mode 100644 libc/misc/wctype/iswcntrl_l.c create mode 100644 libc/misc/wctype/iswctype.c create mode 100644 libc/misc/wctype/iswctype_l.c create mode 100644 libc/misc/wctype/iswdigit.c create mode 100644 libc/misc/wctype/iswdigit_l.c create mode 100644 libc/misc/wctype/iswgraph.c create mode 100644 libc/misc/wctype/iswgraph_l.c create mode 100644 libc/misc/wctype/iswlower.c create mode 100644 libc/misc/wctype/iswlower_l.c create mode 100644 libc/misc/wctype/iswprint.c create mode 100644 libc/misc/wctype/iswprint_l.c create mode 100644 libc/misc/wctype/iswpunct.c create mode 100644 libc/misc/wctype/iswpunct_l.c create mode 100644 libc/misc/wctype/iswspace.c create mode 100644 libc/misc/wctype/iswspace_l.c create mode 100644 libc/misc/wctype/iswupper.c create mode 100644 libc/misc/wctype/iswupper_l.c create mode 100644 libc/misc/wctype/iswxdigit.c create mode 100644 libc/misc/wctype/iswxdigit_l.c create mode 100644 libc/misc/wctype/towctrans.c create mode 100644 libc/misc/wctype/towctrans_l.c create mode 100644 libc/misc/wctype/towlower.c create mode 100644 libc/misc/wctype/towlower_l.c create mode 100644 libc/misc/wctype/towupper.c create mode 100644 libc/misc/wctype/towupper_l.c create mode 100644 libc/misc/wctype/wctrans.c create mode 100644 libc/misc/wctype/wctrans_l.c create mode 100644 libc/misc/wctype/wctype.c create mode 100644 libc/misc/wctype/wctype_l.c create mode 100644 libc/misc/wordexp/Makefile create mode 100644 libc/misc/wordexp/Makefile.in create mode 100644 libc/misc/wordexp/wordexp.c create mode 100644 libc/pwd_grp/.indent.pro create mode 100644 libc/pwd_grp/Makefile create mode 100644 libc/pwd_grp/Makefile.in create mode 100644 libc/pwd_grp/__getgrouplist_internal.c create mode 100644 libc/pwd_grp/__parsegrent.c create mode 100644 libc/pwd_grp/__parsepwent.c create mode 100644 libc/pwd_grp/__parsespent.c create mode 100644 libc/pwd_grp/__pgsreader.c create mode 100644 libc/pwd_grp/fgetgrent.c create mode 100644 libc/pwd_grp/fgetgrent_r.c create mode 100644 libc/pwd_grp/fgetpwent.c create mode 100644 libc/pwd_grp/fgetpwent_r.c create mode 100644 libc/pwd_grp/fgetspent.c create mode 100644 libc/pwd_grp/fgetspent_r.c create mode 100644 libc/pwd_grp/getgrent.c create mode 100644 libc/pwd_grp/getgrent_r.c create mode 100644 libc/pwd_grp/getgrgid.c create mode 100644 libc/pwd_grp/getgrgid_r.c create mode 100644 libc/pwd_grp/getgrnam.c create mode 100644 libc/pwd_grp/getgrnam_r.c create mode 100644 libc/pwd_grp/getgrouplist.c create mode 100644 libc/pwd_grp/getpw.c create mode 100644 libc/pwd_grp/getpwent.c create mode 100644 libc/pwd_grp/getpwent_r.c create mode 100644 libc/pwd_grp/getpwnam.c create mode 100644 libc/pwd_grp/getpwnam_r.c create mode 100644 libc/pwd_grp/getpwuid.c create mode 100644 libc/pwd_grp/getpwuid_r.c create mode 100644 libc/pwd_grp/getspent.c create mode 100644 libc/pwd_grp/getspent_r.c create mode 100644 libc/pwd_grp/getspnam.c create mode 100644 libc/pwd_grp/getspnam_r.c create mode 100644 libc/pwd_grp/initgroups.c create mode 100644 libc/pwd_grp/lckpwdf.c create mode 100644 libc/pwd_grp/putgrent.c create mode 100644 libc/pwd_grp/putpwent.c create mode 100644 libc/pwd_grp/putspent.c create mode 100644 libc/pwd_grp/pwd_grp.c create mode 100644 libc/pwd_grp/pwd_grp_internal.c create mode 100644 libc/pwd_grp/sgetspent.c create mode 100644 libc/pwd_grp/sgetspent_r.c create mode 100644 libc/signal/Makefile create mode 100644 libc/signal/Makefile.in create mode 100644 libc/signal/allocrtsig.c create mode 100644 libc/signal/killpg.c create mode 100644 libc/signal/raise.c create mode 100644 libc/signal/sigaction.c create mode 100644 libc/signal/sigaddset.c create mode 100644 libc/signal/sigandset.c create mode 100644 libc/signal/sigblock.c create mode 100644 libc/signal/sigdelset.c create mode 100644 libc/signal/sigempty.c create mode 100644 libc/signal/sigfillset.c create mode 100644 libc/signal/siggetmask.c create mode 100644 libc/signal/sighold.c create mode 100644 libc/signal/sigignore.c create mode 100644 libc/signal/sigintr.c create mode 100644 libc/signal/sigisempty.c create mode 100644 libc/signal/sigismem.c create mode 100644 libc/signal/sigjmp.c create mode 100644 libc/signal/signal.c create mode 100644 libc/signal/sigorset.c create mode 100644 libc/signal/sigpause.c create mode 100644 libc/signal/sigrelse.c create mode 100644 libc/signal/sigset-cvt-mask.h create mode 100644 libc/signal/sigset.c create mode 100644 libc/signal/sigsetmask.c create mode 100644 libc/signal/sigsetops.c create mode 100644 libc/signal/sigsetops.h create mode 100644 libc/signal/sigwait.c create mode 100644 libc/signal/sysv_signal.c create mode 100644 libc/stdio/.indent.pro create mode 100644 libc/stdio/Makefile create mode 100644 libc/stdio/Makefile.in create mode 100644 libc/stdio/_READ.c create mode 100644 libc/stdio/_WRITE.c create mode 100644 libc/stdio/__fbufsize.c create mode 100644 libc/stdio/__flbf.c create mode 100644 libc/stdio/__fpending.c create mode 100644 libc/stdio/__fpurge.c create mode 100644 libc/stdio/__freadable.c create mode 100644 libc/stdio/__freading.c create mode 100644 libc/stdio/__fsetlocking.c create mode 100644 libc/stdio/__fwritable.c create mode 100644 libc/stdio/__fwriting.c create mode 100644 libc/stdio/__psfs_do_numeric.c create mode 100644 libc/stdio/__psfs_parse_spec.c create mode 100644 libc/stdio/__scan_cookie.c create mode 100644 libc/stdio/_adjust_pos.c create mode 100644 libc/stdio/_cs_funcs.c create mode 100644 libc/stdio/_flushlbf.c create mode 100644 libc/stdio/_fopen.c create mode 100644 libc/stdio/_fpmaxtostr.c create mode 100644 libc/stdio/_fwrite.c create mode 100644 libc/stdio/_load_inttype.c create mode 100644 libc/stdio/_ppfs_init.c create mode 100644 libc/stdio/_ppfs_parsespec.c create mode 100644 libc/stdio/_ppfs_prepargs.c create mode 100644 libc/stdio/_ppfs_setargs.c create mode 100644 libc/stdio/_rfill.c create mode 100644 libc/stdio/_scanf.c create mode 100644 libc/stdio/_stdio.c create mode 100644 libc/stdio/_stdio.h create mode 100644 libc/stdio/_store_inttype.c create mode 100644 libc/stdio/_trans2r.c create mode 100644 libc/stdio/_trans2w.c create mode 100644 libc/stdio/_uintmaxtostr.c create mode 100644 libc/stdio/_vfprintf.c create mode 100644 libc/stdio/_vfprintf_internal.c create mode 100644 libc/stdio/_vfwprintf_internal.c create mode 100644 libc/stdio/_wcommit.c create mode 100644 libc/stdio/_wfwrite.c create mode 100644 libc/stdio/asprintf.c create mode 100644 libc/stdio/clearerr.c create mode 100644 libc/stdio/clearerr_unlocked.c create mode 100644 libc/stdio/ctermid.c create mode 100644 libc/stdio/dprintf.c create mode 100644 libc/stdio/fclose.c create mode 100644 libc/stdio/fcloseall.c create mode 100644 libc/stdio/fdopen.c create mode 100644 libc/stdio/feof.c create mode 100644 libc/stdio/feof_unlocked.c create mode 100644 libc/stdio/ferror.c create mode 100644 libc/stdio/ferror_unlocked.c create mode 100644 libc/stdio/fflush.c create mode 100644 libc/stdio/fflush_unlocked.c create mode 100644 libc/stdio/fgetc.c create mode 100644 libc/stdio/fgetc_unlocked.c create mode 100644 libc/stdio/fgetpos.c create mode 100644 libc/stdio/fgetpos64.c create mode 100644 libc/stdio/fgets.c create mode 100644 libc/stdio/fgets_unlocked.c create mode 100644 libc/stdio/fgetwc.c create mode 100644 libc/stdio/fgetwc_unlocked.c create mode 100644 libc/stdio/fgetws.c create mode 100644 libc/stdio/fgetws_unlocked.c create mode 100644 libc/stdio/fileno.c create mode 100644 libc/stdio/fileno_unlocked.c create mode 100644 libc/stdio/flockfile.c create mode 100644 libc/stdio/fmemopen.c create mode 100644 libc/stdio/fopen.c create mode 100644 libc/stdio/fopen64.c create mode 100644 libc/stdio/fopencookie.c create mode 100644 libc/stdio/fprintf.c create mode 100644 libc/stdio/fputc.c create mode 100644 libc/stdio/fputc_unlocked.c create mode 100644 libc/stdio/fputs.c create mode 100644 libc/stdio/fputs_unlocked.c create mode 100644 libc/stdio/fputwc.c create mode 100644 libc/stdio/fputwc_unlocked.c create mode 100644 libc/stdio/fputws.c create mode 100644 libc/stdio/fputws_unlocked.c create mode 100644 libc/stdio/fread.c create mode 100644 libc/stdio/fread_unlocked.c create mode 100644 libc/stdio/freopen.c create mode 100644 libc/stdio/freopen64.c create mode 100644 libc/stdio/fscanf.c create mode 100644 libc/stdio/fseeko.c create mode 100644 libc/stdio/fseeko64.c create mode 100644 libc/stdio/fsetpos.c create mode 100644 libc/stdio/fsetpos64.c create mode 100644 libc/stdio/ftello.c create mode 100644 libc/stdio/ftello64.c create mode 100644 libc/stdio/ftrylockfile.c create mode 100644 libc/stdio/funlockfile.c create mode 100644 libc/stdio/fwide.c create mode 100644 libc/stdio/fwprintf.c create mode 100644 libc/stdio/fwrite.c create mode 100644 libc/stdio/fwrite_unlocked.c create mode 100644 libc/stdio/fwscanf.c create mode 100644 libc/stdio/getchar.c create mode 100644 libc/stdio/getchar_unlocked.c create mode 100644 libc/stdio/getdelim.c create mode 100644 libc/stdio/getline.c create mode 100644 libc/stdio/gets.c create mode 100644 libc/stdio/getw.c create mode 100644 libc/stdio/getwchar.c create mode 100644 libc/stdio/getwchar_unlocked.c create mode 100644 libc/stdio/old_vfprintf.c create mode 100644 libc/stdio/open_memstream.c create mode 100644 libc/stdio/parse_printf_format.c create mode 100644 libc/stdio/perror.c create mode 100644 libc/stdio/popen.c create mode 100644 libc/stdio/printf.c create mode 100644 libc/stdio/putchar.c create mode 100644 libc/stdio/putchar_unlocked.c create mode 100644 libc/stdio/puts.c create mode 100644 libc/stdio/putw.c create mode 100644 libc/stdio/putwchar.c create mode 100644 libc/stdio/putwchar_unlocked.c create mode 100644 libc/stdio/register_printf_function.c create mode 100644 libc/stdio/remove.c create mode 100644 libc/stdio/rewind.c create mode 100644 libc/stdio/scanf.c create mode 100644 libc/stdio/setbuf.c create mode 100644 libc/stdio/setbuffer.c create mode 100644 libc/stdio/setlinebuf.c create mode 100644 libc/stdio/setvbuf.c create mode 100644 libc/stdio/snprintf.c create mode 100644 libc/stdio/sprintf.c create mode 100644 libc/stdio/sscanf.c create mode 100644 libc/stdio/swprintf.c create mode 100644 libc/stdio/swscanf.c create mode 100644 libc/stdio/tempnam.c create mode 100644 libc/stdio/tmpfile.c create mode 100644 libc/stdio/tmpnam.c create mode 100644 libc/stdio/tmpnam_r.c create mode 100644 libc/stdio/ungetc.c create mode 100644 libc/stdio/ungetwc.c create mode 100644 libc/stdio/vasprintf.c create mode 100644 libc/stdio/vdprintf.c create mode 100644 libc/stdio/vfprintf.c create mode 100644 libc/stdio/vfscanf.c create mode 100644 libc/stdio/vfwprintf.c create mode 100644 libc/stdio/vfwscanf.c create mode 100644 libc/stdio/vprintf.c create mode 100644 libc/stdio/vscanf.c create mode 100644 libc/stdio/vsnprintf.c create mode 100644 libc/stdio/vsprintf.c create mode 100644 libc/stdio/vsscanf.c create mode 100644 libc/stdio/vswprintf.c create mode 100644 libc/stdio/vswscanf.c create mode 100644 libc/stdio/vwprintf.c create mode 100644 libc/stdio/vwscanf.c create mode 100644 libc/stdio/wprintf.c create mode 100644 libc/stdio/wscanf.c create mode 100644 libc/stdlib/.indent.pro create mode 100644 libc/stdlib/Makefile create mode 100644 libc/stdlib/Makefile.in create mode 100644 libc/stdlib/__cxa_atexit.c create mode 100644 libc/stdlib/__cxa_finalize.c create mode 100644 libc/stdlib/__exit_handler.c create mode 100644 libc/stdlib/__fp_range_check.c create mode 100644 libc/stdlib/__strtofpmax.c create mode 100644 libc/stdlib/__strtofpmax_l.c create mode 100644 libc/stdlib/__uc_malloc.c create mode 100644 libc/stdlib/__wcstofpmax.c create mode 100644 libc/stdlib/__wcstofpmax_l.c create mode 100644 libc/stdlib/_atexit.c create mode 100644 libc/stdlib/_stdlib_mb_cur_max.c create mode 100644 libc/stdlib/_stdlib_strto_l.c create mode 100644 libc/stdlib/_stdlib_strto_l_l.c create mode 100644 libc/stdlib/_stdlib_strto_ll.c create mode 100644 libc/stdlib/_stdlib_strto_ll_l.c create mode 100644 libc/stdlib/_stdlib_wcsto_l.c create mode 100644 libc/stdlib/_stdlib_wcsto_l_l.c create mode 100644 libc/stdlib/_stdlib_wcsto_ll.c create mode 100644 libc/stdlib/_stdlib_wcsto_ll_l.c create mode 100644 libc/stdlib/_strtod.c create mode 100644 libc/stdlib/a64l.c create mode 100644 libc/stdlib/abort.c create mode 100644 libc/stdlib/abs.c create mode 100644 libc/stdlib/arc4random.c create mode 100644 libc/stdlib/atexit.c create mode 100644 libc/stdlib/atof.c create mode 100644 libc/stdlib/atoi.c create mode 100644 libc/stdlib/atol.c create mode 100644 libc/stdlib/atoll.c create mode 100644 libc/stdlib/bsd_getpt.c create mode 100644 libc/stdlib/bsearch.c create mode 100644 libc/stdlib/div.c create mode 100644 libc/stdlib/drand48-iter.c create mode 100644 libc/stdlib/drand48.c create mode 100644 libc/stdlib/drand48_r.c create mode 100644 libc/stdlib/erand48.c create mode 100644 libc/stdlib/erand48_r.c create mode 100644 libc/stdlib/exit.c create mode 100644 libc/stdlib/gcvt.c create mode 100644 libc/stdlib/getenv.c create mode 100644 libc/stdlib/getpt.c create mode 100644 libc/stdlib/grantpt.c create mode 100644 libc/stdlib/jrand48.c create mode 100644 libc/stdlib/jrand48_r.c create mode 100644 libc/stdlib/l64a.c create mode 100644 libc/stdlib/labs.c create mode 100644 libc/stdlib/ldiv.c create mode 100644 libc/stdlib/llabs.c create mode 100644 libc/stdlib/lldiv.c create mode 100644 libc/stdlib/lrand48.c create mode 100644 libc/stdlib/lrand48_r.c create mode 100644 libc/stdlib/malloc-simple/Makefile create mode 100644 libc/stdlib/malloc-simple/Makefile.in create mode 100644 libc/stdlib/malloc-simple/alloc.c create mode 100644 libc/stdlib/malloc-simple/calloc.c create mode 100644 libc/stdlib/malloc-simple/free.c create mode 100644 libc/stdlib/malloc-simple/malloc.c create mode 100644 libc/stdlib/malloc-simple/memalign.c create mode 100644 libc/stdlib/malloc-simple/realloc.c create mode 100644 libc/stdlib/malloc-standard/Makefile create mode 100644 libc/stdlib/malloc-standard/Makefile.in create mode 100644 libc/stdlib/malloc-standard/calloc.c create mode 100644 libc/stdlib/malloc-standard/free.c create mode 100644 libc/stdlib/malloc-standard/mallinfo.c create mode 100644 libc/stdlib/malloc-standard/malloc.c create mode 100644 libc/stdlib/malloc-standard/malloc.h create mode 100644 libc/stdlib/malloc-standard/mallopt.c create mode 100644 libc/stdlib/malloc-standard/memalign.c create mode 100644 libc/stdlib/malloc-standard/realloc.c create mode 100644 libc/stdlib/malloc/Makefile create mode 100644 libc/stdlib/malloc/Makefile.in create mode 100644 libc/stdlib/malloc/calloc.c create mode 100644 libc/stdlib/malloc/free.c create mode 100644 libc/stdlib/malloc/heap.h create mode 100644 libc/stdlib/malloc/heap_alloc.c create mode 100644 libc/stdlib/malloc/heap_alloc_at.c create mode 100644 libc/stdlib/malloc/heap_debug.c create mode 100644 libc/stdlib/malloc/heap_free.c create mode 100644 libc/stdlib/malloc/malloc.c create mode 100644 libc/stdlib/malloc/malloc.h create mode 100644 libc/stdlib/malloc/malloc_debug.c create mode 100644 libc/stdlib/malloc/memalign.c create mode 100644 libc/stdlib/malloc/realloc.c create mode 100644 libc/stdlib/mblen.c create mode 100644 libc/stdlib/mbstowcs.c create mode 100644 libc/stdlib/mbtowc.c create mode 100644 libc/stdlib/mkdtemp.c create mode 100644 libc/stdlib/mkstemp.c create mode 100644 libc/stdlib/mkstemp64.c create mode 100644 libc/stdlib/mktemp.c create mode 100644 libc/stdlib/mrand48.c create mode 100644 libc/stdlib/mrand48_r.c create mode 100644 libc/stdlib/nrand48.c create mode 100644 libc/stdlib/nrand48_r.c create mode 100644 libc/stdlib/old_atexit.c create mode 100644 libc/stdlib/on_exit.c create mode 100644 libc/stdlib/posix_memalign.c create mode 100644 libc/stdlib/ptsname.c create mode 100644 libc/stdlib/pty-private.h create mode 100644 libc/stdlib/qsort.c create mode 100644 libc/stdlib/rand.c create mode 100644 libc/stdlib/rand_r.c create mode 100644 libc/stdlib/random.c create mode 100644 libc/stdlib/random_r.c create mode 100644 libc/stdlib/realpath.c create mode 100644 libc/stdlib/seed48.c create mode 100644 libc/stdlib/seed48_r.c create mode 100644 libc/stdlib/setenv.c create mode 100644 libc/stdlib/srand48.c create mode 100644 libc/stdlib/srand48_r.c create mode 100644 libc/stdlib/stdlib.c create mode 100644 libc/stdlib/strtod.c create mode 100644 libc/stdlib/strtod_l.c create mode 100644 libc/stdlib/strtof.c create mode 100644 libc/stdlib/strtof_l.c create mode 100644 libc/stdlib/strtol.c create mode 100644 libc/stdlib/strtol_l.c create mode 100644 libc/stdlib/strtold.c create mode 100644 libc/stdlib/strtold_l.c create mode 100644 libc/stdlib/strtoll.c create mode 100644 libc/stdlib/strtoll_l.c create mode 100644 libc/stdlib/strtoul.c create mode 100644 libc/stdlib/strtoul_l.c create mode 100644 libc/stdlib/strtoull.c create mode 100644 libc/stdlib/strtoull_l.c create mode 100644 libc/stdlib/system.c create mode 100644 libc/stdlib/unix_grantpt.c create mode 100644 libc/stdlib/unlockpt.c create mode 100644 libc/stdlib/valloc.c create mode 100644 libc/stdlib/wcstod.c create mode 100644 libc/stdlib/wcstod_l.c create mode 100644 libc/stdlib/wcstof.c create mode 100644 libc/stdlib/wcstof_l.c create mode 100644 libc/stdlib/wcstol.c create mode 100644 libc/stdlib/wcstol_l.c create mode 100644 libc/stdlib/wcstold.c create mode 100644 libc/stdlib/wcstold_l.c create mode 100644 libc/stdlib/wcstoll.c create mode 100644 libc/stdlib/wcstoll_l.c create mode 100644 libc/stdlib/wcstombs.c create mode 100644 libc/stdlib/wcstoul.c create mode 100644 libc/stdlib/wcstoul_l.c create mode 100644 libc/stdlib/wcstoull.c create mode 100644 libc/stdlib/wcstoull_l.c create mode 100644 libc/stdlib/wctomb.c create mode 100644 libc/string/.indent.pro create mode 100644 libc/string/Makefile create mode 100644 libc/string/Makefile.in create mode 100644 libc/string/__glibc_strerror_r.c create mode 100644 libc/string/__xpg_basename.c create mode 100644 libc/string/__xpg_strerror_r.c create mode 100644 libc/string/_collate.c create mode 100644 libc/string/_string.h create mode 100644 libc/string/_string_syserrmsgs.c create mode 100644 libc/string/_string_syssigmsgs.c create mode 100644 libc/string/_syserrmsg.h create mode 100644 libc/string/arm/Makefile create mode 100644 libc/string/arm/_memcpy.S create mode 100644 libc/string/arm/bcopy.S create mode 100644 libc/string/arm/bzero.S create mode 100644 libc/string/arm/memcmp.S create mode 100644 libc/string/arm/memcpy.S create mode 100644 libc/string/arm/memmove.S create mode 100644 libc/string/arm/memset.S create mode 100644 libc/string/arm/strcmp.S create mode 100644 libc/string/arm/strlen.S create mode 100644 libc/string/avr32/Makefile create mode 100644 libc/string/avr32/bcopy.S create mode 100644 libc/string/avr32/bzero.S create mode 100644 libc/string/avr32/memcmp.S create mode 100644 libc/string/avr32/memcpy.S create mode 100644 libc/string/avr32/memmove.S create mode 100644 libc/string/avr32/memset.S create mode 100644 libc/string/avr32/strcmp.S create mode 100644 libc/string/avr32/strlen.S create mode 100644 libc/string/basename.c create mode 100644 libc/string/bcopy.c create mode 100644 libc/string/bfin/Makefile create mode 100644 libc/string/bfin/memchr.S create mode 100644 libc/string/bfin/memcmp.S create mode 100644 libc/string/bfin/memcpy.S create mode 100644 libc/string/bfin/memmove.S create mode 100644 libc/string/bfin/memset.S create mode 100644 libc/string/bfin/strcmp.S create mode 100644 libc/string/bzero.c create mode 100644 libc/string/cris/memcopy.h create mode 100644 libc/string/cris/memcpy.c create mode 100644 libc/string/cris/memmove.c create mode 100644 libc/string/cris/memset.c create mode 100644 libc/string/cris/strcpy.c create mode 100644 libc/string/cris/strncpy.c create mode 100644 libc/string/dirname.c create mode 100644 libc/string/ffs.c create mode 100644 libc/string/frv/Makefile create mode 100644 libc/string/frv/memcpy.S create mode 100644 libc/string/frv/memset.S create mode 100644 libc/string/generic/Makefile create mode 100644 libc/string/generic/_memcpy_fwd.c create mode 100644 libc/string/generic/bp-checks.h create mode 100644 libc/string/generic/memchr.c create mode 100644 libc/string/generic/memcmp.c create mode 100644 libc/string/generic/memcopy.h create mode 100644 libc/string/generic/memcpy.c create mode 100644 libc/string/generic/memmem.c create mode 100644 libc/string/generic/memmove.c create mode 100644 libc/string/generic/mempcpy.c create mode 100644 libc/string/generic/memrchr.c create mode 100644 libc/string/generic/memset.c create mode 100644 libc/string/generic/pagecopy.h create mode 100644 libc/string/generic/rawmemchr.c create mode 100644 libc/string/generic/strcat.c create mode 100644 libc/string/generic/strchr.c create mode 100644 libc/string/generic/strchrnul.c create mode 100644 libc/string/generic/strcmp.c create mode 100644 libc/string/generic/strcpy.c create mode 100644 libc/string/generic/strcspn.c create mode 100644 libc/string/generic/strlen.c create mode 100644 libc/string/generic/strncat.c create mode 100644 libc/string/generic/strncmp.c create mode 100644 libc/string/generic/strncpy.c create mode 100644 libc/string/generic/strnlen.c create mode 100644 libc/string/generic/strrchr.c create mode 100644 libc/string/generic/strsep.c create mode 100644 libc/string/generic/strspn.c create mode 100644 libc/string/generic/strstr.c create mode 100644 libc/string/generic/strtok_r.c create mode 100644 libc/string/i386/Makefile create mode 100644 libc/string/i386/memchr.c create mode 100644 libc/string/i386/memcpy.c create mode 100644 libc/string/i386/memmove.c create mode 100644 libc/string/i386/memset.c create mode 100644 libc/string/i386/strcat.c create mode 100644 libc/string/i386/strchr.c create mode 100644 libc/string/i386/strcmp.c create mode 100644 libc/string/i386/strcpy.c create mode 100644 libc/string/i386/strlen.c create mode 100644 libc/string/i386/strncat.c create mode 100644 libc/string/i386/strncmp.c create mode 100644 libc/string/i386/strncpy.c create mode 100644 libc/string/i386/strnlen.c create mode 100644 libc/string/i386/strrchr.c create mode 100644 libc/string/ia64/Makefile create mode 100644 libc/string/ia64/bcopy.S create mode 100644 libc/string/ia64/bzero.S create mode 100644 libc/string/ia64/memccpy.S create mode 100644 libc/string/ia64/memchr.S create mode 100644 libc/string/ia64/memcmp.S create mode 100644 libc/string/ia64/memcpy.S create mode 100644 libc/string/ia64/memmove.S create mode 100644 libc/string/ia64/memset.S create mode 100644 libc/string/ia64/softpipe.h create mode 100644 libc/string/ia64/strchr.S create mode 100644 libc/string/ia64/strcmp.S create mode 100644 libc/string/ia64/strcpy.S create mode 100644 libc/string/ia64/strlen.S create mode 100644 libc/string/ia64/strncmp.S create mode 100644 libc/string/ia64/strncpy.S create mode 100644 libc/string/ia64/sysdep.h create mode 100644 libc/string/memccpy.c create mode 100644 libc/string/memchr.c create mode 100644 libc/string/memcmp.c create mode 100644 libc/string/memcpy.c create mode 100644 libc/string/memmem.c create mode 100644 libc/string/memmove.c create mode 100644 libc/string/mempcpy.c create mode 100644 libc/string/memrchr.c create mode 100644 libc/string/memset.c create mode 100644 libc/string/mips/Makefile create mode 100644 libc/string/mips/memcpy.S create mode 100644 libc/string/mips/memset.S create mode 100644 libc/string/mips/sysdep.h create mode 100644 libc/string/powerpc/Makefile create mode 100644 libc/string/powerpc/memcpy.c create mode 100644 libc/string/powerpc/memmove.c create mode 100644 libc/string/powerpc/memset.c create mode 100644 libc/string/psignal.c create mode 100644 libc/string/rawmemchr.c create mode 100644 libc/string/sh/sh4/memcpy.S create mode 100644 libc/string/sh64/Makefile create mode 100644 libc/string/sh64/memcpy.S create mode 100644 libc/string/sh64/memset.S create mode 100644 libc/string/sh64/strcpy.S create mode 100644 libc/string/sh64/strlen.S create mode 100644 libc/string/sparc/Makefile create mode 100644 libc/string/sparc/_glibc_inc.h create mode 100644 libc/string/sparc/bcopy.c create mode 100644 libc/string/sparc/bzero.c create mode 100644 libc/string/sparc/memchr.S create mode 100644 libc/string/sparc/memcpy.S create mode 100644 libc/string/sparc/memmove.c create mode 100644 libc/string/sparc/memset.S create mode 100644 libc/string/sparc/sparc32/memchr.S create mode 100644 libc/string/sparc/sparc32/memcpy.S create mode 100644 libc/string/sparc/sparc32/memset.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/memchr.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/memcpy.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/memset.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/stpcpy.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/strcat.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/strchr.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/strcmp.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/strcpy.S create mode 100644 libc/string/sparc/sparc32/sparcv9b/strlen.S create mode 100644 libc/string/sparc/sparc32/stpcpy.S create mode 100644 libc/string/sparc/sparc32/strcat.S create mode 100644 libc/string/sparc/sparc32/strchr.S create mode 100644 libc/string/sparc/sparc32/strcmp.S create mode 100644 libc/string/sparc/sparc32/strcpy.S create mode 100644 libc/string/sparc/sparc32/strlen.S create mode 100644 libc/string/sparc/sparc64/memchr.S create mode 100644 libc/string/sparc/sparc64/memcpy.S create mode 100644 libc/string/sparc/sparc64/memset.S create mode 100644 libc/string/sparc/sparc64/sparcv9b/memcpy.S create mode 100644 libc/string/sparc/sparc64/stpcpy.S create mode 100644 libc/string/sparc/sparc64/strcat.S create mode 100644 libc/string/sparc/sparc64/strchr.S create mode 100644 libc/string/sparc/sparc64/strcmp.S create mode 100644 libc/string/sparc/sparc64/strcpy.S create mode 100644 libc/string/sparc/sparc64/strlen.S create mode 100644 libc/string/sparc/stpcpy.S create mode 100644 libc/string/sparc/strcat.S create mode 100644 libc/string/sparc/strchr.S create mode 100644 libc/string/sparc/strcmp.S create mode 100644 libc/string/sparc/strcpy.S create mode 100644 libc/string/sparc/strlen.S create mode 100644 libc/string/sparc/strrchr.c create mode 100644 libc/string/stpcpy.c create mode 100644 libc/string/stpncpy.c create mode 100644 libc/string/strcasecmp.c create mode 100644 libc/string/strcasecmp_l.c create mode 100644 libc/string/strcasestr.c create mode 100644 libc/string/strcat.c create mode 100644 libc/string/strchr.c create mode 100644 libc/string/strchrnul.c create mode 100644 libc/string/strcmp.c create mode 100644 libc/string/strcpy.c create mode 100644 libc/string/strcspn.c create mode 100644 libc/string/strdup.c create mode 100644 libc/string/strerror.c create mode 100644 libc/string/strlcat.c create mode 100644 libc/string/strlcpy.c create mode 100644 libc/string/strlen.c create mode 100644 libc/string/strncasecmp.c create mode 100644 libc/string/strncasecmp_l.c create mode 100644 libc/string/strncat.c create mode 100644 libc/string/strncmp.c create mode 100644 libc/string/strncpy.c create mode 100644 libc/string/strndup.c create mode 100644 libc/string/strnlen.c create mode 100644 libc/string/strpbrk.c create mode 100644 libc/string/strrchr.c create mode 100644 libc/string/strsep.c create mode 100644 libc/string/strsignal.c create mode 100644 libc/string/strspn.c create mode 100644 libc/string/strstr.c create mode 100644 libc/string/strtok.c create mode 100644 libc/string/strtok_r.c create mode 100644 libc/string/strxfrm.c create mode 100644 libc/string/strxfrm_l.c create mode 100644 libc/string/sys_errlist.c create mode 100644 libc/string/sys_siglist.c create mode 100644 libc/string/wcpcpy.c create mode 100644 libc/string/wcpncpy.c create mode 100644 libc/string/wcscasecmp.c create mode 100644 libc/string/wcscasecmp_l.c create mode 100644 libc/string/wcscat.c create mode 100644 libc/string/wcschr.c create mode 100644 libc/string/wcschrnul.c create mode 100644 libc/string/wcscmp.c create mode 100644 libc/string/wcscpy.c create mode 100644 libc/string/wcscspn.c create mode 100644 libc/string/wcsdup.c create mode 100644 libc/string/wcslcpy.c create mode 100644 libc/string/wcslen.c create mode 100644 libc/string/wcsncasecmp.c create mode 100644 libc/string/wcsncasecmp_l.c create mode 100644 libc/string/wcsncat.c create mode 100644 libc/string/wcsncmp.c create mode 100644 libc/string/wcsncpy.c create mode 100644 libc/string/wcsnlen.c create mode 100644 libc/string/wcspbrk.c create mode 100644 libc/string/wcsrchr.c create mode 100644 libc/string/wcsspn.c create mode 100644 libc/string/wcsstr.c create mode 100644 libc/string/wcstok.c create mode 100644 libc/string/wcsxfrm.c create mode 100644 libc/string/wcsxfrm_l.c create mode 100644 libc/string/wmemchr.c create mode 100644 libc/string/wmemcmp.c create mode 100644 libc/string/wmemcpy.c create mode 100644 libc/string/wmemmove.c create mode 100644 libc/string/wmempcpy.c create mode 100644 libc/string/wmemset.c create mode 100644 libc/string/x86_64/Makefile create mode 100644 libc/string/x86_64/_glibc_inc.h create mode 100644 libc/string/x86_64/bzero.S create mode 100644 libc/string/x86_64/memcpy.S create mode 100644 libc/string/x86_64/mempcpy.S create mode 100644 libc/string/x86_64/memset.S create mode 100644 libc/string/x86_64/stpcpy.S create mode 100644 libc/string/x86_64/strcat.S create mode 100644 libc/string/x86_64/strchr.S create mode 100644 libc/string/x86_64/strcmp.S create mode 100644 libc/string/x86_64/strcpy.S create mode 100644 libc/string/x86_64/strcspn.S create mode 100644 libc/string/x86_64/strlen.S create mode 100644 libc/string/x86_64/strpbrk.S create mode 100644 libc/string/x86_64/strspn.S create mode 100644 libc/string/xtensa/Makefile create mode 100644 libc/string/xtensa/memcpy.S create mode 100644 libc/string/xtensa/memset.S create mode 100644 libc/string/xtensa/strcmp.S create mode 100644 libc/string/xtensa/strcpy.S create mode 100644 libc/string/xtensa/strlen.S create mode 100644 libc/string/xtensa/strncpy.S create mode 100644 libc/sysdeps/Makefile create mode 100644 libc/sysdeps/Makefile.in create mode 100644 libc/sysdeps/README create mode 100644 libc/sysdeps/linux/Makefile create mode 100644 libc/sysdeps/linux/Makefile.commonarch create mode 100644 libc/sysdeps/linux/Makefile.in create mode 100644 libc/sysdeps/linux/README create mode 100644 libc/sysdeps/linux/alpha/Makefile create mode 100644 libc/sysdeps/linux/alpha/Makefile.arch create mode 100644 libc/sysdeps/linux/alpha/__longjmp.S create mode 100644 libc/sysdeps/linux/alpha/__syscall_error.c create mode 100644 libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S create mode 100644 libc/sysdeps/linux/alpha/bits/atomic.h create mode 100644 libc/sysdeps/linux/alpha/bits/dirent.h create mode 100644 libc/sysdeps/linux/alpha/bits/elfclass.h create mode 100644 libc/sysdeps/linux/alpha/bits/endian.h create mode 100644 libc/sysdeps/linux/alpha/bits/fcntl.h create mode 100644 libc/sysdeps/linux/alpha/bits/fenv.h create mode 100644 libc/sysdeps/linux/alpha/bits/ioctls.h create mode 100644 libc/sysdeps/linux/alpha/bits/ipc.h create mode 100644 libc/sysdeps/linux/alpha/bits/kernel_sigaction.h create mode 100644 libc/sysdeps/linux/alpha/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/alpha/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/alpha/bits/mathdef.h create mode 100644 libc/sysdeps/linux/alpha/bits/mathinline.h create mode 100644 libc/sysdeps/linux/alpha/bits/mman.h create mode 100644 libc/sysdeps/linux/alpha/bits/msq.h create mode 100644 libc/sysdeps/linux/alpha/bits/netdb.h create mode 100644 libc/sysdeps/linux/alpha/bits/resource.h create mode 100644 libc/sysdeps/linux/alpha/bits/sem.h create mode 100644 libc/sysdeps/linux/alpha/bits/setjmp.h create mode 100644 libc/sysdeps/linux/alpha/bits/shm.h create mode 100644 libc/sysdeps/linux/alpha/bits/sigaction.h create mode 100644 libc/sysdeps/linux/alpha/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/alpha/bits/siginfo.h create mode 100644 libc/sysdeps/linux/alpha/bits/signum.h create mode 100644 libc/sysdeps/linux/alpha/bits/sigstack.h create mode 100644 libc/sysdeps/linux/alpha/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/alpha/bits/stat.h create mode 100644 libc/sysdeps/linux/alpha/bits/statfs.h create mode 100644 libc/sysdeps/linux/alpha/bits/statvfs.h create mode 100644 libc/sysdeps/linux/alpha/bits/syscalls.h create mode 100644 libc/sysdeps/linux/alpha/bits/termios.h create mode 100644 libc/sysdeps/linux/alpha/bits/typesizes.h create mode 100644 libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h create mode 100644 libc/sysdeps/linux/alpha/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/alpha/bits/wordsize.h create mode 100644 libc/sysdeps/linux/alpha/brk.S create mode 100644 libc/sysdeps/linux/alpha/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/alpha/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/alpha/clone.S create mode 100644 libc/sysdeps/linux/alpha/crt1.S create mode 100644 libc/sysdeps/linux/alpha/crti.S create mode 100644 libc/sysdeps/linux/alpha/crtn.S create mode 100644 libc/sysdeps/linux/alpha/divl.S create mode 100644 libc/sysdeps/linux/alpha/divq.S create mode 100644 libc/sysdeps/linux/alpha/divrem.h create mode 100644 libc/sysdeps/linux/alpha/fpu_control.h create mode 100644 libc/sysdeps/linux/alpha/pipe.S create mode 100644 libc/sysdeps/linux/alpha/reml.S create mode 100644 libc/sysdeps/linux/alpha/remq.S create mode 100644 libc/sysdeps/linux/alpha/setjmp.S create mode 100644 libc/sysdeps/linux/alpha/sigprocmask.c create mode 100644 libc/sysdeps/linux/alpha/sys/acct.h create mode 100644 libc/sysdeps/linux/alpha/sys/io.h create mode 100644 libc/sysdeps/linux/alpha/sys/procfs.h create mode 100644 libc/sysdeps/linux/alpha/sys/regdef.h create mode 100644 libc/sysdeps/linux/alpha/sys/ucontext.h create mode 100644 libc/sysdeps/linux/alpha/sys/user.h create mode 100644 libc/sysdeps/linux/alpha/syscall.S create mode 100644 libc/sysdeps/linux/arm/Makefile create mode 100644 libc/sysdeps/linux/arm/Makefile.arch create mode 100644 libc/sysdeps/linux/arm/__longjmp.S create mode 100644 libc/sysdeps/linux/arm/__syscall_error.c create mode 100644 libc/sysdeps/linux/arm/aeabi_assert.c create mode 100644 libc/sysdeps/linux/arm/aeabi_atexit.c create mode 100644 libc/sysdeps/linux/arm/aeabi_errno_addr.c create mode 100644 libc/sysdeps/linux/arm/aeabi_lcsts.c create mode 100644 libc/sysdeps/linux/arm/aeabi_localeconv.c create mode 100644 libc/sysdeps/linux/arm/aeabi_math.c create mode 100644 libc/sysdeps/linux/arm/aeabi_mb_cur_max.c create mode 100644 libc/sysdeps/linux/arm/aeabi_memclr.c create mode 100644 libc/sysdeps/linux/arm/aeabi_memcpy.c create mode 100644 libc/sysdeps/linux/arm/aeabi_memmove.c create mode 100644 libc/sysdeps/linux/arm/aeabi_memset.c create mode 100644 libc/sysdeps/linux/arm/aeabi_sighandlers.S create mode 100644 libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c create mode 100644 libc/sysdeps/linux/arm/bits/arm_asm.h create mode 100644 libc/sysdeps/linux/arm/bits/armsigctx.h create mode 100644 libc/sysdeps/linux/arm/bits/endian.h create mode 100644 libc/sysdeps/linux/arm/bits/fcntl.h create mode 100644 libc/sysdeps/linux/arm/bits/fenv.h create mode 100644 libc/sysdeps/linux/arm/bits/huge_val.h create mode 100644 libc/sysdeps/linux/arm/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/arm/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/arm/bits/mathdef.h create mode 100644 libc/sysdeps/linux/arm/bits/mman.h create mode 100644 libc/sysdeps/linux/arm/bits/setjmp.h create mode 100644 libc/sysdeps/linux/arm/bits/shm.h create mode 100644 libc/sysdeps/linux/arm/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/arm/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/arm/bits/syscalls.h create mode 100644 libc/sysdeps/linux/arm/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/arm/bits/wordsize.h create mode 100644 libc/sysdeps/linux/arm/brk.c create mode 100644 libc/sysdeps/linux/arm/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/arm/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/arm/clone.S create mode 100644 libc/sysdeps/linux/arm/crt1.S create mode 100644 libc/sysdeps/linux/arm/crti.S create mode 100644 libc/sysdeps/linux/arm/crtn.S create mode 100644 libc/sysdeps/linux/arm/find_exidx.c create mode 100644 libc/sysdeps/linux/arm/fpu_control.h create mode 100644 libc/sysdeps/linux/arm/ioperm.c create mode 100644 libc/sysdeps/linux/arm/iopl.c create mode 100644 libc/sysdeps/linux/arm/mmap.c create mode 100644 libc/sysdeps/linux/arm/mmap64.S create mode 100644 libc/sysdeps/linux/arm/posix_fadvise.c create mode 100644 libc/sysdeps/linux/arm/posix_fadvise64.c create mode 100644 libc/sysdeps/linux/arm/setjmp.S create mode 100644 libc/sysdeps/linux/arm/sigaction.c create mode 100644 libc/sysdeps/linux/arm/sigrestorer.S create mode 100644 libc/sysdeps/linux/arm/sys/elf.h create mode 100644 libc/sysdeps/linux/arm/sys/io.h create mode 100644 libc/sysdeps/linux/arm/sys/procfs.h create mode 100644 libc/sysdeps/linux/arm/sys/ucontext.h create mode 100644 libc/sysdeps/linux/arm/sys/user.h create mode 100644 libc/sysdeps/linux/arm/syscall-eabi.S create mode 100644 libc/sysdeps/linux/arm/syscall.c create mode 100644 libc/sysdeps/linux/arm/vfork.S create mode 100644 libc/sysdeps/linux/avr32/Makefile create mode 100644 libc/sysdeps/linux/avr32/Makefile.arch create mode 100644 libc/sysdeps/linux/avr32/__longjmp.S create mode 100644 libc/sysdeps/linux/avr32/bits/atomic.h create mode 100644 libc/sysdeps/linux/avr32/bits/byteswap.h create mode 100644 libc/sysdeps/linux/avr32/bits/endian.h create mode 100644 libc/sysdeps/linux/avr32/bits/fcntl.h create mode 100644 libc/sysdeps/linux/avr32/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/avr32/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/avr32/bits/mman.h create mode 100644 libc/sysdeps/linux/avr32/bits/setjmp.h create mode 100644 libc/sysdeps/linux/avr32/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/avr32/bits/syscalls.h create mode 100644 libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/avr32/bits/wordsize.h create mode 100644 libc/sysdeps/linux/avr32/brk.c create mode 100644 libc/sysdeps/linux/avr32/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/avr32/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/avr32/clone.c create mode 100644 libc/sysdeps/linux/avr32/crt1.S create mode 100644 libc/sysdeps/linux/avr32/crti.S create mode 100644 libc/sysdeps/linux/avr32/crtn.S create mode 100644 libc/sysdeps/linux/avr32/mmap.c create mode 100644 libc/sysdeps/linux/avr32/setjmp.S create mode 100644 libc/sysdeps/linux/avr32/sigaction.c create mode 100644 libc/sysdeps/linux/avr32/sigrestorer.S create mode 100644 libc/sysdeps/linux/avr32/sys/elf.h create mode 100644 libc/sysdeps/linux/avr32/sys/procfs.h create mode 100644 libc/sysdeps/linux/avr32/sys/ucontext.h create mode 100644 libc/sysdeps/linux/avr32/sys/user.h create mode 100644 libc/sysdeps/linux/avr32/syscall.S create mode 100644 libc/sysdeps/linux/avr32/vfork.S create mode 100644 libc/sysdeps/linux/bfin/Makefile create mode 100644 libc/sysdeps/linux/bfin/Makefile.arch create mode 100644 libc/sysdeps/linux/bfin/__longjmp.S create mode 100644 libc/sysdeps/linux/bfin/bfin_l1layout.h create mode 100644 libc/sysdeps/linux/bfin/bfin_sram.h create mode 100644 libc/sysdeps/linux/bfin/bits/byteswap.h create mode 100644 libc/sysdeps/linux/bfin/bits/elf-fdpic.h create mode 100644 libc/sysdeps/linux/bfin/bits/endian.h create mode 100644 libc/sysdeps/linux/bfin/bits/fcntl.h create mode 100644 libc/sysdeps/linux/bfin/bits/huge_val.h create mode 100644 libc/sysdeps/linux/bfin/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/bfin/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/bfin/bits/mman.h create mode 100644 libc/sysdeps/linux/bfin/bits/setjmp.h create mode 100644 libc/sysdeps/linux/bfin/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/bfin/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/bfin/bits/syscalls.h create mode 100644 libc/sysdeps/linux/bfin/bits/typesizes.h create mode 100644 libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/bfin/bits/wordsize.h create mode 100644 libc/sysdeps/linux/bfin/brk.c create mode 100644 libc/sysdeps/linux/bfin/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/bfin/bsdsetjmp.c create mode 100644 libc/sysdeps/linux/bfin/clone.c create mode 100644 libc/sysdeps/linux/bfin/crt1.S create mode 100644 libc/sysdeps/linux/bfin/crti.S create mode 100644 libc/sysdeps/linux/bfin/crtn.S create mode 100644 libc/sysdeps/linux/bfin/crtreloc.c create mode 100644 libc/sysdeps/linux/bfin/dma-memcpy.c create mode 100644 libc/sysdeps/linux/bfin/setjmp.S create mode 100644 libc/sysdeps/linux/bfin/sram-alloc.c create mode 100644 libc/sysdeps/linux/bfin/sram-free.c create mode 100644 libc/sysdeps/linux/bfin/sys/elf.h create mode 100644 libc/sysdeps/linux/bfin/sys/io.h create mode 100644 libc/sysdeps/linux/bfin/sys/procfs.h create mode 100644 libc/sysdeps/linux/bfin/sys/reg.h create mode 100644 libc/sysdeps/linux/bfin/sys/ucontext.h create mode 100644 libc/sysdeps/linux/bfin/syscall.c create mode 100644 libc/sysdeps/linux/bfin/sysdep.h create mode 100644 libc/sysdeps/linux/bfin/vfork.S create mode 100644 libc/sysdeps/linux/common/.indent.pro create mode 100644 libc/sysdeps/linux/common/Makefile create mode 100644 libc/sysdeps/linux/common/Makefile.in create mode 100644 libc/sysdeps/linux/common/__rt_sigtimedwait.c create mode 100644 libc/sysdeps/linux/common/__socketcall.c create mode 100644 libc/sysdeps/linux/common/__syscall_fcntl.c create mode 100644 libc/sysdeps/linux/common/__syscall_fcntl64.c create mode 100644 libc/sysdeps/linux/common/__syscall_rt_sigaction.c create mode 100644 libc/sysdeps/linux/common/__syscall_sigaction.c create mode 100644 libc/sysdeps/linux/common/_exit.c create mode 100644 libc/sysdeps/linux/common/access.c create mode 100644 libc/sysdeps/linux/common/acct.c create mode 100644 libc/sysdeps/linux/common/adjtimex.c create mode 100644 libc/sysdeps/linux/common/alarm.c create mode 100644 libc/sysdeps/linux/common/arch_prctl.c create mode 100644 libc/sysdeps/linux/common/bdflush.c create mode 100644 libc/sysdeps/linux/common/bits/atomic.h create mode 100644 libc/sysdeps/linux/common/bits/byteswap.h create mode 100644 libc/sysdeps/linux/common/bits/cmathcalls.h create mode 100644 libc/sysdeps/linux/common/bits/confname.h create mode 100644 libc/sysdeps/linux/common/bits/dirent.h create mode 100644 libc/sysdeps/linux/common/bits/dlfcn.h create mode 100644 libc/sysdeps/linux/common/bits/elfclass.h create mode 100644 libc/sysdeps/linux/common/bits/endian.h create mode 100644 libc/sysdeps/linux/common/bits/environments.h create mode 100644 libc/sysdeps/linux/common/bits/errno.h create mode 100644 libc/sysdeps/linux/common/bits/fcntl.h create mode 100644 libc/sysdeps/linux/common/bits/fenv.h create mode 100644 libc/sysdeps/linux/common/bits/fenvinline.h create mode 100644 libc/sysdeps/linux/common/bits/getopt.h create mode 100644 libc/sysdeps/linux/common/bits/huge_val.h create mode 100644 libc/sysdeps/linux/common/bits/huge_valf.h create mode 100644 libc/sysdeps/linux/common/bits/huge_vall.h create mode 100644 libc/sysdeps/linux/common/bits/in.h create mode 100644 libc/sysdeps/linux/common/bits/inf.h create mode 100644 libc/sysdeps/linux/common/bits/initspin.h create mode 100644 libc/sysdeps/linux/common/bits/ioctl-types.h create mode 100644 libc/sysdeps/linux/common/bits/ioctls.h create mode 100644 libc/sysdeps/linux/common/bits/ipc.h create mode 100644 libc/sysdeps/linux/common/bits/kernel_sigaction.h create mode 100644 libc/sysdeps/linux/common/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/common/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/common/bits/local_lim.h create mode 100644 libc/sysdeps/linux/common/bits/locale.h create mode 100644 libc/sysdeps/linux/common/bits/mathcalls.h create mode 100644 libc/sysdeps/linux/common/bits/mathdef.h create mode 100644 libc/sysdeps/linux/common/bits/mathinline.h create mode 100644 libc/sysdeps/linux/common/bits/mman.h create mode 100644 libc/sysdeps/linux/common/bits/mqueue.h create mode 100644 libc/sysdeps/linux/common/bits/msq.h create mode 100644 libc/sysdeps/linux/common/bits/nan.h create mode 100644 libc/sysdeps/linux/common/bits/netdb.h create mode 100644 libc/sysdeps/linux/common/bits/poll.h create mode 100644 libc/sysdeps/linux/common/bits/posix1_lim.h create mode 100644 libc/sysdeps/linux/common/bits/posix2_lim.h create mode 100644 libc/sysdeps/linux/common/bits/posix_opt.h create mode 100644 libc/sysdeps/linux/common/bits/resource.h create mode 100644 libc/sysdeps/linux/common/bits/sched.h create mode 100644 libc/sysdeps/linux/common/bits/select.h create mode 100644 libc/sysdeps/linux/common/bits/sem.h create mode 100644 libc/sysdeps/linux/common/bits/setjmp.h create mode 100644 libc/sysdeps/linux/common/bits/shm.h create mode 100644 libc/sysdeps/linux/common/bits/sigaction.h create mode 100644 libc/sysdeps/linux/common/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/common/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/common/bits/siginfo.h create mode 100644 libc/sysdeps/linux/common/bits/signum.h create mode 100644 libc/sysdeps/linux/common/bits/sigset.h create mode 100644 libc/sysdeps/linux/common/bits/sigstack.h create mode 100644 libc/sysdeps/linux/common/bits/sigthread.h create mode 100644 libc/sysdeps/linux/common/bits/sockaddr.h create mode 100644 libc/sysdeps/linux/common/bits/socket.h create mode 100644 libc/sysdeps/linux/common/bits/stab.def create mode 100644 libc/sysdeps/linux/common/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/common/bits/stat.h create mode 100644 libc/sysdeps/linux/common/bits/statfs.h create mode 100644 libc/sysdeps/linux/common/bits/statvfs.h create mode 100644 libc/sysdeps/linux/common/bits/stdio.h create mode 100644 libc/sysdeps/linux/common/bits/stdio_lim.h create mode 100644 libc/sysdeps/linux/common/bits/syscalls.h create mode 100644 libc/sysdeps/linux/common/bits/termios.h create mode 100644 libc/sysdeps/linux/common/bits/time.h create mode 100644 libc/sysdeps/linux/common/bits/types.h create mode 100644 libc/sysdeps/linux/common/bits/typesizes.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_clk_tck.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_ctype.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_errno.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_fpmax.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_local_lim.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_locale.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_mutex.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_pthread.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_stdio.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_touplow.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_uwchar.h create mode 100644 libc/sysdeps/linux/common/bits/uClibc_va_copy.h create mode 100644 libc/sysdeps/linux/common/bits/uio.h create mode 100644 libc/sysdeps/linux/common/bits/ustat.h create mode 100644 libc/sysdeps/linux/common/bits/utmp.h create mode 100644 libc/sysdeps/linux/common/bits/utmpx.h create mode 100644 libc/sysdeps/linux/common/bits/utsname.h create mode 100644 libc/sysdeps/linux/common/bits/waitflags.h create mode 100644 libc/sysdeps/linux/common/bits/waitstatus.h create mode 100644 libc/sysdeps/linux/common/bits/wchar.h create mode 100644 libc/sysdeps/linux/common/bits/wordsize.h create mode 100644 libc/sysdeps/linux/common/bits/xopen_lim.h create mode 100644 libc/sysdeps/linux/common/capget.c create mode 100644 libc/sysdeps/linux/common/capset.c create mode 100644 libc/sysdeps/linux/common/chdir.c create mode 100644 libc/sysdeps/linux/common/chmod.c create mode 100644 libc/sysdeps/linux/common/chown.c create mode 100644 libc/sysdeps/linux/common/chroot.c create mode 100644 libc/sysdeps/linux/common/clock_getres.c create mode 100644 libc/sysdeps/linux/common/clock_gettime.c create mode 100644 libc/sysdeps/linux/common/clock_settime.c create mode 100644 libc/sysdeps/linux/common/close.c create mode 100644 libc/sysdeps/linux/common/cmsg_nxthdr.c create mode 100644 libc/sysdeps/linux/common/creat64.c create mode 100644 libc/sysdeps/linux/common/create_module.c create mode 100644 libc/sysdeps/linux/common/delete_module.c create mode 100644 libc/sysdeps/linux/common/dl-osinfo.h create mode 100644 libc/sysdeps/linux/common/dup.c create mode 100644 libc/sysdeps/linux/common/dup2.c create mode 100644 libc/sysdeps/linux/common/epoll.c create mode 100644 libc/sysdeps/linux/common/execve.c create mode 100644 libc/sysdeps/linux/common/fchdir.c create mode 100644 libc/sysdeps/linux/common/fchmod.c create mode 100644 libc/sysdeps/linux/common/fchown.c create mode 100644 libc/sysdeps/linux/common/fdatasync.c create mode 100644 libc/sysdeps/linux/common/flock.c create mode 100644 libc/sysdeps/linux/common/fork.c create mode 100644 libc/sysdeps/linux/common/fpu_control.h create mode 100644 libc/sysdeps/linux/common/fstat.c create mode 100644 libc/sysdeps/linux/common/fstat64.c create mode 100644 libc/sysdeps/linux/common/fstatfs.c create mode 100644 libc/sysdeps/linux/common/fsync.c create mode 100644 libc/sysdeps/linux/common/ftruncate.c create mode 100644 libc/sysdeps/linux/common/ftruncate64.c create mode 100644 libc/sysdeps/linux/common/get_kernel_syms.c create mode 100644 libc/sysdeps/linux/common/getcwd.c create mode 100644 libc/sysdeps/linux/common/getdents.c create mode 100644 libc/sysdeps/linux/common/getdents64.c create mode 100644 libc/sysdeps/linux/common/getdirname.c create mode 100644 libc/sysdeps/linux/common/getdomainname.c create mode 100644 libc/sysdeps/linux/common/getdtablesize.c create mode 100644 libc/sysdeps/linux/common/getegid.c create mode 100644 libc/sysdeps/linux/common/geteuid.c create mode 100644 libc/sysdeps/linux/common/getgid.c create mode 100644 libc/sysdeps/linux/common/getgroups.c create mode 100644 libc/sysdeps/linux/common/gethostname.c create mode 100644 libc/sysdeps/linux/common/getitimer.c create mode 100644 libc/sysdeps/linux/common/getpagesize.c create mode 100644 libc/sysdeps/linux/common/getpgid.c create mode 100644 libc/sysdeps/linux/common/getpgrp.c create mode 100644 libc/sysdeps/linux/common/getpid.c create mode 100644 libc/sysdeps/linux/common/getppid.c create mode 100644 libc/sysdeps/linux/common/getpriority.c create mode 100644 libc/sysdeps/linux/common/getresgid.c create mode 100644 libc/sysdeps/linux/common/getresuid.c create mode 100644 libc/sysdeps/linux/common/getrlimit.c create mode 100644 libc/sysdeps/linux/common/getrlimit64.c create mode 100644 libc/sysdeps/linux/common/getrusage.c create mode 100644 libc/sysdeps/linux/common/getsid.c create mode 100644 libc/sysdeps/linux/common/gettimeofday.c create mode 100644 libc/sysdeps/linux/common/getuid.c create mode 100644 libc/sysdeps/linux/common/hp-timing.h create mode 100644 libc/sysdeps/linux/common/init_module.c create mode 100644 libc/sysdeps/linux/common/inotify.c create mode 100644 libc/sysdeps/linux/common/ioctl.c create mode 100644 libc/sysdeps/linux/common/ioperm.c create mode 100644 libc/sysdeps/linux/common/iopl.c create mode 100644 libc/sysdeps/linux/common/kill.c create mode 100644 libc/sysdeps/linux/common/klogctl.c create mode 100644 libc/sysdeps/linux/common/lchown.c create mode 100644 libc/sysdeps/linux/common/link.c create mode 100644 libc/sysdeps/linux/common/llseek.c create mode 100644 libc/sysdeps/linux/common/longjmp.c create mode 100644 libc/sysdeps/linux/common/lseek.c create mode 100644 libc/sysdeps/linux/common/lstat.c create mode 100644 libc/sysdeps/linux/common/lstat64.c create mode 100644 libc/sysdeps/linux/common/madvise.c create mode 100644 libc/sysdeps/linux/common/mincore.c create mode 100644 libc/sysdeps/linux/common/mkdir.c create mode 100644 libc/sysdeps/linux/common/mkfifo.c create mode 100644 libc/sysdeps/linux/common/mknod.c create mode 100644 libc/sysdeps/linux/common/mlock.c create mode 100644 libc/sysdeps/linux/common/mlockall.c create mode 100644 libc/sysdeps/linux/common/mmap.c create mode 100644 libc/sysdeps/linux/common/mmap64.c create mode 100644 libc/sysdeps/linux/common/modify_ldt.c create mode 100644 libc/sysdeps/linux/common/mount.c create mode 100644 libc/sysdeps/linux/common/mprotect.c create mode 100644 libc/sysdeps/linux/common/mremap.c create mode 100644 libc/sysdeps/linux/common/msync.c create mode 100644 libc/sysdeps/linux/common/munlock.c create mode 100644 libc/sysdeps/linux/common/munlockall.c create mode 100644 libc/sysdeps/linux/common/munmap.c create mode 100644 libc/sysdeps/linux/common/nanosleep.c create mode 100644 libc/sysdeps/linux/common/nice.c create mode 100644 libc/sysdeps/linux/common/noophooks.c create mode 100644 libc/sysdeps/linux/common/ntp_gettime.c create mode 100644 libc/sysdeps/linux/common/open.c create mode 100644 libc/sysdeps/linux/common/open64.c create mode 100644 libc/sysdeps/linux/common/pause.c create mode 100644 libc/sysdeps/linux/common/personality.c create mode 100644 libc/sysdeps/linux/common/pipe.c create mode 100644 libc/sysdeps/linux/common/pivot_root.c create mode 100644 libc/sysdeps/linux/common/poll.c create mode 100644 libc/sysdeps/linux/common/posix_fadvise.c create mode 100644 libc/sysdeps/linux/common/posix_fadvise64.c create mode 100644 libc/sysdeps/linux/common/ppoll.c create mode 100644 libc/sysdeps/linux/common/prctl.c create mode 100644 libc/sysdeps/linux/common/pread_write.c create mode 100644 libc/sysdeps/linux/common/pselect.c create mode 100644 libc/sysdeps/linux/common/ptrace.c create mode 100644 libc/sysdeps/linux/common/query_module.c create mode 100644 libc/sysdeps/linux/common/quotactl.c create mode 100644 libc/sysdeps/linux/common/read.c create mode 100644 libc/sysdeps/linux/common/readahead.c create mode 100644 libc/sysdeps/linux/common/readlink.c create mode 100644 libc/sysdeps/linux/common/readv.c create mode 100644 libc/sysdeps/linux/common/reboot.c create mode 100644 libc/sysdeps/linux/common/remap_file_pages.c create mode 100644 libc/sysdeps/linux/common/rename.c create mode 100644 libc/sysdeps/linux/common/rmdir.c create mode 100644 libc/sysdeps/linux/common/sbrk.c create mode 100644 libc/sysdeps/linux/common/sched_get_priority_max.c create mode 100644 libc/sysdeps/linux/common/sched_get_priority_min.c create mode 100644 libc/sysdeps/linux/common/sched_getaffinity.c create mode 100644 libc/sysdeps/linux/common/sched_getparam.c create mode 100644 libc/sysdeps/linux/common/sched_getscheduler.c create mode 100644 libc/sysdeps/linux/common/sched_rr_get_interval.c create mode 100644 libc/sysdeps/linux/common/sched_setaffinity.c create mode 100644 libc/sysdeps/linux/common/sched_setparam.c create mode 100644 libc/sysdeps/linux/common/sched_setscheduler.c create mode 100644 libc/sysdeps/linux/common/sched_yield.c create mode 100644 libc/sysdeps/linux/common/select.c create mode 100644 libc/sysdeps/linux/common/sendfile.c create mode 100644 libc/sysdeps/linux/common/sendfile64.c create mode 100644 libc/sysdeps/linux/common/setdomainname.c create mode 100644 libc/sysdeps/linux/common/setegid.c create mode 100644 libc/sysdeps/linux/common/seteuid.c create mode 100644 libc/sysdeps/linux/common/setfsgid.c create mode 100644 libc/sysdeps/linux/common/setfsuid.c create mode 100644 libc/sysdeps/linux/common/setgid.c create mode 100644 libc/sysdeps/linux/common/setgroups.c create mode 100644 libc/sysdeps/linux/common/sethostname.c create mode 100644 libc/sysdeps/linux/common/setitimer.c create mode 100644 libc/sysdeps/linux/common/setpgid.c create mode 100644 libc/sysdeps/linux/common/setpgrp.c create mode 100644 libc/sysdeps/linux/common/setpriority.c create mode 100644 libc/sysdeps/linux/common/setregid.c create mode 100644 libc/sysdeps/linux/common/setresgid.c create mode 100644 libc/sysdeps/linux/common/setresuid.c create mode 100644 libc/sysdeps/linux/common/setreuid.c create mode 100644 libc/sysdeps/linux/common/setrlimit.c create mode 100644 libc/sysdeps/linux/common/setrlimit64.c create mode 100644 libc/sysdeps/linux/common/setsid.c create mode 100644 libc/sysdeps/linux/common/settimeofday.c create mode 100644 libc/sysdeps/linux/common/setuid.c create mode 100644 libc/sysdeps/linux/common/sigaltstack.c create mode 100644 libc/sysdeps/linux/common/signalfd.c create mode 100644 libc/sysdeps/linux/common/sigpending.c create mode 100644 libc/sysdeps/linux/common/sigprocmask.c create mode 100644 libc/sysdeps/linux/common/sigqueue.c create mode 100644 libc/sysdeps/linux/common/sigsuspend.c create mode 100644 libc/sysdeps/linux/common/splice.c create mode 100644 libc/sysdeps/linux/common/ssp-local.c create mode 100644 libc/sysdeps/linux/common/ssp.c create mode 100644 libc/sysdeps/linux/common/stat.c create mode 100644 libc/sysdeps/linux/common/stat64.c create mode 100644 libc/sysdeps/linux/common/statfs.c create mode 100644 libc/sysdeps/linux/common/stime.c create mode 100644 libc/sysdeps/linux/common/swapoff.c create mode 100644 libc/sysdeps/linux/common/swapon.c create mode 100644 libc/sysdeps/linux/common/symlink.c create mode 100644 libc/sysdeps/linux/common/sync.c create mode 100644 libc/sysdeps/linux/common/sync_file_range.c create mode 100644 libc/sysdeps/linux/common/sys/acct.h create mode 100644 libc/sysdeps/linux/common/sys/epoll.h create mode 100644 libc/sysdeps/linux/common/sys/inotify.h create mode 100644 libc/sysdeps/linux/common/sys/prctl.h create mode 100644 libc/sysdeps/linux/common/sys/ptrace.h create mode 100644 libc/sysdeps/linux/common/sys/user.h create mode 100644 libc/sysdeps/linux/common/syscalls.h create mode 100644 libc/sysdeps/linux/common/sysctl.c create mode 100644 libc/sysdeps/linux/common/sysfs.c create mode 100644 libc/sysdeps/linux/common/sysinfo.c create mode 100644 libc/sysdeps/linux/common/tee.c create mode 100644 libc/sysdeps/linux/common/time.c create mode 100644 libc/sysdeps/linux/common/times.c create mode 100644 libc/sysdeps/linux/common/truncate.c create mode 100644 libc/sysdeps/linux/common/truncate64.c create mode 100644 libc/sysdeps/linux/common/ulimit.c create mode 100644 libc/sysdeps/linux/common/umask.c create mode 100644 libc/sysdeps/linux/common/umount.c create mode 100644 libc/sysdeps/linux/common/umount2.c create mode 100644 libc/sysdeps/linux/common/uname.c create mode 100644 libc/sysdeps/linux/common/unlink.c create mode 100644 libc/sysdeps/linux/common/uselib.c create mode 100644 libc/sysdeps/linux/common/ustat.c create mode 100644 libc/sysdeps/linux/common/utime.c create mode 100644 libc/sysdeps/linux/common/utimes.c create mode 100644 libc/sysdeps/linux/common/vfork.c create mode 100644 libc/sysdeps/linux/common/vhangup.c create mode 100644 libc/sysdeps/linux/common/vmsplice.c create mode 100644 libc/sysdeps/linux/common/wait.c create mode 100644 libc/sysdeps/linux/common/wait3.c create mode 100644 libc/sysdeps/linux/common/wait4.c create mode 100644 libc/sysdeps/linux/common/waitid.c create mode 100644 libc/sysdeps/linux/common/waitpid.c create mode 100644 libc/sysdeps/linux/common/write.c create mode 100644 libc/sysdeps/linux/common/writev.c create mode 100644 libc/sysdeps/linux/common/xattr.c create mode 100644 libc/sysdeps/linux/common/xstatconv.c create mode 100644 libc/sysdeps/linux/common/xstatconv.h create mode 100644 libc/sysdeps/linux/cris/Makefile create mode 100644 libc/sysdeps/linux/cris/Makefile.arch create mode 100644 libc/sysdeps/linux/cris/__init_brk.c create mode 100644 libc/sysdeps/linux/cris/__longjmp.S create mode 100644 libc/sysdeps/linux/cris/bits/byteswap.h create mode 100644 libc/sysdeps/linux/cris/bits/endian.h create mode 100644 libc/sysdeps/linux/cris/bits/fcntl.h create mode 100644 libc/sysdeps/linux/cris/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/cris/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/cris/bits/mman.h create mode 100644 libc/sysdeps/linux/cris/bits/setjmp.h create mode 100644 libc/sysdeps/linux/cris/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/cris/bits/syscalls.h create mode 100644 libc/sysdeps/linux/cris/bits/termios.h create mode 100644 libc/sysdeps/linux/cris/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/cris/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/cris/bits/wordsize.h create mode 100644 libc/sysdeps/linux/cris/brk.c create mode 100644 libc/sysdeps/linux/cris/clone.S create mode 100644 libc/sysdeps/linux/cris/crt1.S create mode 100644 libc/sysdeps/linux/cris/crti.S create mode 100644 libc/sysdeps/linux/cris/crtn.S create mode 100644 libc/sysdeps/linux/cris/fork.c create mode 100644 libc/sysdeps/linux/cris/libc.map create mode 100644 libc/sysdeps/linux/cris/sbrk.c create mode 100644 libc/sysdeps/linux/cris/setjmp.S create mode 100644 libc/sysdeps/linux/cris/sys/procfs.h create mode 100644 libc/sysdeps/linux/cris/sys/ucontext.h create mode 100644 libc/sysdeps/linux/cris/syscall.S create mode 100644 libc/sysdeps/linux/cris/sysdep.S create mode 100644 libc/sysdeps/linux/cris/sysdep.h create mode 100644 libc/sysdeps/linux/e1/Makefile create mode 100644 libc/sysdeps/linux/e1/bits/endian.h create mode 100644 libc/sysdeps/linux/e1/bits/fcntl.h create mode 100644 libc/sysdeps/linux/e1/bits/fenv.h create mode 100644 libc/sysdeps/linux/e1/bits/fenvinline.h create mode 100644 libc/sysdeps/linux/e1/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/e1/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/e1/bits/mman.h create mode 100644 libc/sysdeps/linux/e1/bits/proto.h create mode 100644 libc/sysdeps/linux/e1/bits/setjmp.h create mode 100644 libc/sysdeps/linux/e1/bits/syscalls.h create mode 100644 libc/sysdeps/linux/e1/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/e1/bits/unistd.h create mode 100644 libc/sysdeps/linux/e1/bits/wordsize.h create mode 100644 libc/sysdeps/linux/e1/crt0.S create mode 100644 libc/sysdeps/linux/e1/crt1.c create mode 100644 libc/sysdeps/linux/e1/longjmp.c create mode 100644 libc/sysdeps/linux/e1/setjmp.c create mode 100644 libc/sysdeps/linux/e1/sys/procfs.h create mode 100644 libc/sysdeps/linux/e1/sys/reg.h create mode 100644 libc/sysdeps/linux/e1/sys/ucontext.h create mode 100644 libc/sysdeps/linux/e1/syscalls.c create mode 100644 libc/sysdeps/linux/e1/vfork.c create mode 100644 libc/sysdeps/linux/frv/Makefile create mode 100644 libc/sysdeps/linux/frv/__init_brk.c create mode 100644 libc/sysdeps/linux/frv/__longjmp.S create mode 100644 libc/sysdeps/linux/frv/bits/elf-fdpic.h create mode 100644 libc/sysdeps/linux/frv/bits/endian.h create mode 100644 libc/sysdeps/linux/frv/bits/fcntl.h create mode 100644 libc/sysdeps/linux/frv/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/frv/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/frv/bits/mman.h create mode 100644 libc/sysdeps/linux/frv/bits/setjmp.h create mode 100644 libc/sysdeps/linux/frv/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/frv/bits/stat.h create mode 100644 libc/sysdeps/linux/frv/bits/syscalls.h create mode 100644 libc/sysdeps/linux/frv/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/frv/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/frv/bits/wordsize.h create mode 100644 libc/sysdeps/linux/frv/brk.c create mode 100644 libc/sysdeps/linux/frv/clone.S create mode 100644 libc/sysdeps/linux/frv/crt0.S create mode 100644 libc/sysdeps/linux/frv/crti.S create mode 100644 libc/sysdeps/linux/frv/crtn.S create mode 100644 libc/sysdeps/linux/frv/crtreloc.c create mode 100644 libc/sysdeps/linux/frv/dl-iterate-phdr.c create mode 100644 libc/sysdeps/linux/frv/fstat.c create mode 100644 libc/sysdeps/linux/frv/fstat64.c create mode 100644 libc/sysdeps/linux/frv/lstat.c create mode 100644 libc/sysdeps/linux/frv/lstat64.c create mode 100644 libc/sysdeps/linux/frv/mmap.c create mode 100644 libc/sysdeps/linux/frv/sbrk.c create mode 100644 libc/sysdeps/linux/frv/setjmp.S create mode 100644 libc/sysdeps/linux/frv/stat.c create mode 100644 libc/sysdeps/linux/frv/stat64.c create mode 100644 libc/sysdeps/linux/frv/sys/procfs.h create mode 100644 libc/sysdeps/linux/frv/sys/ptrace.h create mode 100644 libc/sysdeps/linux/frv/sys/ucontext.h create mode 100644 libc/sysdeps/linux/frv/syscall.c create mode 100644 libc/sysdeps/linux/frv/sysdep.c create mode 100644 libc/sysdeps/linux/frv/vfork.S create mode 100644 libc/sysdeps/linux/frv/xstatconv.c create mode 100644 libc/sysdeps/linux/h8300/Makefile create mode 100644 libc/sysdeps/linux/h8300/__longjmp.S create mode 100644 libc/sysdeps/linux/h8300/bits/byteswap.h create mode 100644 libc/sysdeps/linux/h8300/bits/endian.h create mode 100644 libc/sysdeps/linux/h8300/bits/fcntl.h create mode 100644 libc/sysdeps/linux/h8300/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/h8300/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/h8300/bits/mman.h create mode 100644 libc/sysdeps/linux/h8300/bits/setjmp.h create mode 100644 libc/sysdeps/linux/h8300/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/h8300/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/h8300/bits/syscalls.h create mode 100644 libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/h8300/bits/wordsize.h create mode 100644 libc/sysdeps/linux/h8300/brk.c create mode 100644 libc/sysdeps/linux/h8300/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/h8300/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/h8300/clone.S create mode 100644 libc/sysdeps/linux/h8300/crt0.S create mode 100644 libc/sysdeps/linux/h8300/crti.S create mode 100644 libc/sysdeps/linux/h8300/crtn.S create mode 100644 libc/sysdeps/linux/h8300/float.h create mode 100644 libc/sysdeps/linux/h8300/ptrace.c create mode 100644 libc/sysdeps/linux/h8300/setjmp.S create mode 100644 libc/sysdeps/linux/h8300/sys/procfs.h create mode 100644 libc/sysdeps/linux/h8300/sys/ucontext.h create mode 100644 libc/sysdeps/linux/h8300/vfork.S create mode 100644 libc/sysdeps/linux/hppa/Makefile create mode 100644 libc/sysdeps/linux/hppa/Makefile.arch create mode 100644 libc/sysdeps/linux/hppa/__longjmp.S create mode 100644 libc/sysdeps/linux/hppa/__syscall_error.c create mode 100644 libc/sysdeps/linux/hppa/add_n.s create mode 100644 libc/sysdeps/linux/hppa/bits/endian.h create mode 100644 libc/sysdeps/linux/hppa/bits/fcntl.h create mode 100644 libc/sysdeps/linux/hppa/bits/fenv.h create mode 100644 libc/sysdeps/linux/hppa/bits/ipc.h create mode 100644 libc/sysdeps/linux/hppa/bits/kernel_sigaction.h create mode 100644 libc/sysdeps/linux/hppa/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/hppa/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/hppa/bits/mman.h create mode 100644 libc/sysdeps/linux/hppa/bits/setjmp.h create mode 100644 libc/sysdeps/linux/hppa/bits/sigaction.h create mode 100644 libc/sysdeps/linux/hppa/bits/signum.h create mode 100644 libc/sysdeps/linux/hppa/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/hppa/bits/syscalls.h create mode 100644 libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/hppa/bits/wordsize.h create mode 100644 libc/sysdeps/linux/hppa/brk.c create mode 100644 libc/sysdeps/linux/hppa/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/hppa/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/hppa/clone.S create mode 100644 libc/sysdeps/linux/hppa/crt1.S create mode 100644 libc/sysdeps/linux/hppa/crti.S create mode 100644 libc/sysdeps/linux/hppa/crtn.S create mode 100644 libc/sysdeps/linux/hppa/lshift.s create mode 100644 libc/sysdeps/linux/hppa/mmap.c create mode 100644 libc/sysdeps/linux/hppa/rshift.s create mode 100644 libc/sysdeps/linux/hppa/setjmp.S create mode 100644 libc/sysdeps/linux/hppa/sub_n.s create mode 100644 libc/sysdeps/linux/hppa/sys/procfs.h create mode 100644 libc/sysdeps/linux/hppa/sys/ucontext.h create mode 100644 libc/sysdeps/linux/hppa/syscall.c create mode 100644 libc/sysdeps/linux/hppa/udiv_qrnnd.s create mode 100644 libc/sysdeps/linux/i386/Makefile create mode 100644 libc/sysdeps/linux/i386/Makefile.arch create mode 100644 libc/sysdeps/linux/i386/__longjmp.S create mode 100644 libc/sysdeps/linux/i386/__syscall_error.c create mode 100644 libc/sysdeps/linux/i386/bits/atomic.h create mode 100644 libc/sysdeps/linux/i386/bits/byteswap.h create mode 100644 libc/sysdeps/linux/i386/bits/endian.h create mode 100644 libc/sysdeps/linux/i386/bits/fcntl.h create mode 100644 libc/sysdeps/linux/i386/bits/fenv.h create mode 100644 libc/sysdeps/linux/i386/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/i386/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/i386/bits/mathdef.h create mode 100644 libc/sysdeps/linux/i386/bits/mathinline.h create mode 100644 libc/sysdeps/linux/i386/bits/mman.h create mode 100644 libc/sysdeps/linux/i386/bits/select.h create mode 100644 libc/sysdeps/linux/i386/bits/setjmp.h create mode 100644 libc/sysdeps/linux/i386/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/i386/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/i386/bits/syscalls.h create mode 100644 libc/sysdeps/linux/i386/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/i386/bits/wchar.h create mode 100644 libc/sysdeps/linux/i386/bits/wordsize.h create mode 100644 libc/sysdeps/linux/i386/brk.c create mode 100644 libc/sysdeps/linux/i386/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/i386/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/i386/clone.S create mode 100644 libc/sysdeps/linux/i386/crt1.S create mode 100644 libc/sysdeps/linux/i386/crti.S create mode 100644 libc/sysdeps/linux/i386/crtn.S create mode 100644 libc/sysdeps/linux/i386/fpu_control.h create mode 100644 libc/sysdeps/linux/i386/mmap.S create mode 100644 libc/sysdeps/linux/i386/mmap64.S create mode 100644 libc/sysdeps/linux/i386/posix_fadvise64.S create mode 100644 libc/sysdeps/linux/i386/setjmp.S create mode 100644 libc/sysdeps/linux/i386/sigaction.c create mode 100644 libc/sysdeps/linux/i386/sync_file_range.S create mode 100644 libc/sysdeps/linux/i386/sys/debugreg.h create mode 100644 libc/sysdeps/linux/i386/sys/elf.h create mode 100644 libc/sysdeps/linux/i386/sys/io.h create mode 100644 libc/sysdeps/linux/i386/sys/perm.h create mode 100644 libc/sysdeps/linux/i386/sys/procfs.h create mode 100644 libc/sysdeps/linux/i386/sys/reg.h create mode 100644 libc/sysdeps/linux/i386/sys/ucontext.h create mode 100644 libc/sysdeps/linux/i386/sys/user.h create mode 100644 libc/sysdeps/linux/i386/sys/vm86.h create mode 100644 libc/sysdeps/linux/i386/syscall.S create mode 100644 libc/sysdeps/linux/i386/vfork.S create mode 100644 libc/sysdeps/linux/i960/AUTHORS create mode 100644 libc/sysdeps/linux/i960/Makefile create mode 100644 libc/sysdeps/linux/i960/README create mode 100644 libc/sysdeps/linux/i960/bits/endian.h create mode 100644 libc/sysdeps/linux/i960/bits/fcntl.h create mode 100644 libc/sysdeps/linux/i960/bits/mman.h create mode 100644 libc/sysdeps/linux/i960/bits/setjmp.h create mode 100644 libc/sysdeps/linux/i960/bits/syscalls.h create mode 100644 libc/sysdeps/linux/i960/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/i960/bits/wordsize.h create mode 100644 libc/sysdeps/linux/i960/clone.S create mode 100644 libc/sysdeps/linux/i960/crt0.S create mode 100644 libc/sysdeps/linux/i960/mmap.S create mode 100644 libc/sysdeps/linux/i960/setjmp.S create mode 100644 libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff create mode 100644 libc/sysdeps/linux/i960/sys/procfs.h create mode 100644 libc/sysdeps/linux/i960/sys/ucontext.h create mode 100644 libc/sysdeps/linux/i960/vfork.S create mode 100644 libc/sysdeps/linux/ia64/Makefile create mode 100644 libc/sysdeps/linux/ia64/Makefile.arch create mode 100644 libc/sysdeps/linux/ia64/__longjmp.S create mode 100644 libc/sysdeps/linux/ia64/__syscall_error.c create mode 100644 libc/sysdeps/linux/ia64/bits/atomic.h create mode 100644 libc/sysdeps/linux/ia64/bits/byteswap.h create mode 100644 libc/sysdeps/linux/ia64/bits/endian.h create mode 100644 libc/sysdeps/linux/ia64/bits/fcntl.h create mode 100644 libc/sysdeps/linux/ia64/bits/fenv.h create mode 100644 libc/sysdeps/linux/ia64/bits/ipc.h create mode 100644 libc/sysdeps/linux/ia64/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/ia64/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/ia64/bits/mathdef.h create mode 100644 libc/sysdeps/linux/ia64/bits/mathinline.h create mode 100644 libc/sysdeps/linux/ia64/bits/mman.h create mode 100644 libc/sysdeps/linux/ia64/bits/msq.h create mode 100644 libc/sysdeps/linux/ia64/bits/sem.h create mode 100644 libc/sysdeps/linux/ia64/bits/setjmp.h create mode 100644 libc/sysdeps/linux/ia64/bits/shm.h create mode 100644 libc/sysdeps/linux/ia64/bits/sigaction.h create mode 100644 libc/sysdeps/linux/ia64/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/ia64/bits/siginfo.h create mode 100644 libc/sysdeps/linux/ia64/bits/sigstack.h create mode 100644 libc/sysdeps/linux/ia64/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/ia64/bits/stat.h create mode 100644 libc/sysdeps/linux/ia64/bits/syscalls.h create mode 100644 libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/ia64/bits/wordsize.h create mode 100644 libc/sysdeps/linux/ia64/brk.S create mode 100644 libc/sysdeps/linux/ia64/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/ia64/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/ia64/clone2.S create mode 100644 libc/sysdeps/linux/ia64/crt1.S create mode 100644 libc/sysdeps/linux/ia64/crti.S create mode 100644 libc/sysdeps/linux/ia64/crtn.S create mode 100644 libc/sysdeps/linux/ia64/fork.S create mode 100644 libc/sysdeps/linux/ia64/pipe.S create mode 100644 libc/sysdeps/linux/ia64/setjmp.S create mode 100644 libc/sysdeps/linux/ia64/sys/io.h create mode 100644 libc/sysdeps/linux/ia64/sys/procfs.h create mode 100644 libc/sysdeps/linux/ia64/sys/ptrace.h create mode 100644 libc/sysdeps/linux/ia64/sys/ucontext.h create mode 100644 libc/sysdeps/linux/ia64/sys/user.h create mode 100644 libc/sysdeps/linux/ia64/syscall.S create mode 100644 libc/sysdeps/linux/ia64/sysdep.h create mode 100644 libc/sysdeps/linux/ia64/vfork.S create mode 100644 libc/sysdeps/linux/m68k/Makefile create mode 100644 libc/sysdeps/linux/m68k/Makefile.arch create mode 100644 libc/sysdeps/linux/m68k/README.m68k create mode 100644 libc/sysdeps/linux/m68k/__longjmp.S create mode 100644 libc/sysdeps/linux/m68k/__syscall_error.c create mode 100644 libc/sysdeps/linux/m68k/bits/byteswap.h create mode 100644 libc/sysdeps/linux/m68k/bits/endian.h create mode 100644 libc/sysdeps/linux/m68k/bits/fcntl.h create mode 100644 libc/sysdeps/linux/m68k/bits/fenv.h create mode 100644 libc/sysdeps/linux/m68k/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/m68k/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/m68k/bits/mathdef.h create mode 100644 libc/sysdeps/linux/m68k/bits/mathinline.h create mode 100644 libc/sysdeps/linux/m68k/bits/mman.h create mode 100644 libc/sysdeps/linux/m68k/bits/poll.h create mode 100644 libc/sysdeps/linux/m68k/bits/setjmp.h create mode 100644 libc/sysdeps/linux/m68k/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/m68k/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/m68k/bits/stat.h create mode 100644 libc/sysdeps/linux/m68k/bits/syscalls.h create mode 100644 libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/m68k/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/m68k/bits/wordsize.h create mode 100644 libc/sysdeps/linux/m68k/brk.c create mode 100644 libc/sysdeps/linux/m68k/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/m68k/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/m68k/clone.S create mode 100644 libc/sysdeps/linux/m68k/crt1.S create mode 100644 libc/sysdeps/linux/m68k/crti.S create mode 100644 libc/sysdeps/linux/m68k/crtn.S create mode 100644 libc/sysdeps/linux/m68k/float.h create mode 100644 libc/sysdeps/linux/m68k/fpu_control.h create mode 100644 libc/sysdeps/linux/m68k/m68k_pic.S create mode 100644 libc/sysdeps/linux/m68k/setjmp.S create mode 100644 libc/sysdeps/linux/m68k/sys/procfs.h create mode 100644 libc/sysdeps/linux/m68k/sys/reg.h create mode 100644 libc/sysdeps/linux/m68k/sys/ucontext.h create mode 100644 libc/sysdeps/linux/m68k/sys/user.h create mode 100644 libc/sysdeps/linux/m68k/syscall.c create mode 100644 libc/sysdeps/linux/m68k/vfork.S create mode 100644 libc/sysdeps/linux/microblaze/Makefile create mode 100644 libc/sysdeps/linux/microblaze/__longjmp.S create mode 100644 libc/sysdeps/linux/microblaze/bits/byteswap.h create mode 100644 libc/sysdeps/linux/microblaze/bits/endian.h create mode 100644 libc/sysdeps/linux/microblaze/bits/fcntl.h create mode 100644 libc/sysdeps/linux/microblaze/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/microblaze/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/microblaze/bits/mman.h create mode 100644 libc/sysdeps/linux/microblaze/bits/poll.h create mode 100644 libc/sysdeps/linux/microblaze/bits/select.h create mode 100644 libc/sysdeps/linux/microblaze/bits/setjmp.h create mode 100644 libc/sysdeps/linux/microblaze/bits/syscalls.h create mode 100644 libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/microblaze/bits/wordsize.h create mode 100644 libc/sysdeps/linux/microblaze/clinkage.h create mode 100644 libc/sysdeps/linux/microblaze/clone.c create mode 100644 libc/sysdeps/linux/microblaze/crt0.S create mode 100644 libc/sysdeps/linux/microblaze/mmap.c create mode 100644 libc/sysdeps/linux/microblaze/setjmp.S create mode 100644 libc/sysdeps/linux/microblaze/sys/ptrace.h create mode 100644 libc/sysdeps/linux/microblaze/sys/ucontext.h create mode 100644 libc/sysdeps/linux/microblaze/syscall.c create mode 100644 libc/sysdeps/linux/microblaze/vfork.S create mode 100644 libc/sysdeps/linux/mips/Makefile create mode 100644 libc/sysdeps/linux/mips/Makefile.arch create mode 100644 libc/sysdeps/linux/mips/__longjmp.c create mode 100644 libc/sysdeps/linux/mips/__syscall_error.c create mode 100644 libc/sysdeps/linux/mips/_test_and_set.c create mode 100644 libc/sysdeps/linux/mips/bits/atomic.h create mode 100644 libc/sysdeps/linux/mips/bits/dirent.h create mode 100644 libc/sysdeps/linux/mips/bits/dlfcn.h create mode 100644 libc/sysdeps/linux/mips/bits/endian.h create mode 100644 libc/sysdeps/linux/mips/bits/fcntl.h create mode 100644 libc/sysdeps/linux/mips/bits/fenv.h create mode 100644 libc/sysdeps/linux/mips/bits/ioctl-types.h create mode 100644 libc/sysdeps/linux/mips/bits/ipc.h create mode 100644 libc/sysdeps/linux/mips/bits/kernel_sigaction.h create mode 100644 libc/sysdeps/linux/mips/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/mips/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/mips/bits/mathdef.h create mode 100644 libc/sysdeps/linux/mips/bits/mman.h create mode 100644 libc/sysdeps/linux/mips/bits/msq.h create mode 100644 libc/sysdeps/linux/mips/bits/poll.h create mode 100644 libc/sysdeps/linux/mips/bits/resource.h create mode 100644 libc/sysdeps/linux/mips/bits/sem.h create mode 100644 libc/sysdeps/linux/mips/bits/setjmp.h create mode 100644 libc/sysdeps/linux/mips/bits/shm.h create mode 100644 libc/sysdeps/linux/mips/bits/sigaction.h create mode 100644 libc/sysdeps/linux/mips/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/mips/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/mips/bits/siginfo.h create mode 100644 libc/sysdeps/linux/mips/bits/signum.h create mode 100644 libc/sysdeps/linux/mips/bits/sigstack.h create mode 100644 libc/sysdeps/linux/mips/bits/socket.h create mode 100644 libc/sysdeps/linux/mips/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/mips/bits/stat.h create mode 100644 libc/sysdeps/linux/mips/bits/statfs.h create mode 100644 libc/sysdeps/linux/mips/bits/syscalls.h create mode 100644 libc/sysdeps/linux/mips/bits/termios.h create mode 100644 libc/sysdeps/linux/mips/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/mips/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/mips/bits/wordsize.h create mode 100644 libc/sysdeps/linux/mips/brk.c create mode 100644 libc/sysdeps/linux/mips/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/mips/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/mips/cacheflush.c create mode 100644 libc/sysdeps/linux/mips/clone.S create mode 100644 libc/sysdeps/linux/mips/crt1.S create mode 100644 libc/sysdeps/linux/mips/crti.S create mode 100644 libc/sysdeps/linux/mips/crtn.S create mode 100644 libc/sysdeps/linux/mips/fpu_control.h create mode 100644 libc/sysdeps/linux/mips/mmap.c create mode 100644 libc/sysdeps/linux/mips/pipe.S create mode 100644 libc/sysdeps/linux/mips/posix_fadvise.c create mode 100644 libc/sysdeps/linux/mips/posix_fadvise64.c create mode 100644 libc/sysdeps/linux/mips/pread_write.c create mode 100644 libc/sysdeps/linux/mips/readahead.c create mode 100644 libc/sysdeps/linux/mips/setjmp.S create mode 100644 libc/sysdeps/linux/mips/setjmp_aux.c create mode 100644 libc/sysdeps/linux/mips/sgidefs.h create mode 100644 libc/sysdeps/linux/mips/sigaction.c create mode 100644 libc/sysdeps/linux/mips/sys/asm.h create mode 100644 libc/sysdeps/linux/mips/sys/cachectl.h create mode 100644 libc/sysdeps/linux/mips/sys/fpregdef.h create mode 100644 libc/sysdeps/linux/mips/sys/procfs.h create mode 100644 libc/sysdeps/linux/mips/sys/regdef.h create mode 100644 libc/sysdeps/linux/mips/sys/sysmips.h create mode 100644 libc/sysdeps/linux/mips/sys/tas.h create mode 100644 libc/sysdeps/linux/mips/sys/ucontext.h create mode 100644 libc/sysdeps/linux/mips/sys/user.h create mode 100644 libc/sysdeps/linux/mips/syscall.S create mode 100644 libc/sysdeps/linux/mips/sysmips.c create mode 100644 libc/sysdeps/linux/nios/Makefile create mode 100644 libc/sysdeps/linux/nios/Makefile.arch create mode 100644 libc/sysdeps/linux/nios/NM_Macros.S create mode 100644 libc/sysdeps/linux/nios/NR_Math1.S create mode 100644 libc/sysdeps/linux/nios/__longjmp.S create mode 100644 libc/sysdeps/linux/nios/bits/endian.h create mode 100644 libc/sysdeps/linux/nios/bits/fcntl.h create mode 100644 libc/sysdeps/linux/nios/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/nios/bits/mathdef.h create mode 100644 libc/sysdeps/linux/nios/bits/mman.h create mode 100644 libc/sysdeps/linux/nios/bits/setjmp.h create mode 100644 libc/sysdeps/linux/nios/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/nios/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/nios/bits/stat.h create mode 100644 libc/sysdeps/linux/nios/bits/syscalls.h create mode 100644 libc/sysdeps/linux/nios/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/nios/bits/wordsize.h create mode 100644 libc/sysdeps/linux/nios/brk.c create mode 100644 libc/sysdeps/linux/nios/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/nios/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/nios/clone.S create mode 100644 libc/sysdeps/linux/nios/crt1.S create mode 100644 libc/sysdeps/linux/nios/crtbegin.c create mode 100644 libc/sysdeps/linux/nios/crtend.c create mode 100644 libc/sysdeps/linux/nios/fpu_control.h create mode 100644 libc/sysdeps/linux/nios/setjmp.S create mode 100644 libc/sysdeps/linux/nios/sys/procfs.h create mode 100644 libc/sysdeps/linux/nios/sys/ucontext.h create mode 100644 libc/sysdeps/linux/nios/vfork.S create mode 100644 libc/sysdeps/linux/nios2/Makefile create mode 100644 libc/sysdeps/linux/nios2/Makefile.arch create mode 100644 libc/sysdeps/linux/nios2/__longjmp.S create mode 100644 libc/sysdeps/linux/nios2/bits/endian.h create mode 100644 libc/sysdeps/linux/nios2/bits/fcntl.h create mode 100644 libc/sysdeps/linux/nios2/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/nios2/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/nios2/bits/mathdef.h create mode 100644 libc/sysdeps/linux/nios2/bits/mman.h create mode 100644 libc/sysdeps/linux/nios2/bits/setjmp.h create mode 100644 libc/sysdeps/linux/nios2/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/nios2/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/nios2/bits/stat.h create mode 100644 libc/sysdeps/linux/nios2/bits/syscalls.h create mode 100644 libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/nios2/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/nios2/bits/wordsize.h create mode 100644 libc/sysdeps/linux/nios2/brk.c create mode 100644 libc/sysdeps/linux/nios2/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/nios2/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/nios2/clone.S create mode 100644 libc/sysdeps/linux/nios2/clone.c create mode 100644 libc/sysdeps/linux/nios2/crt1.S create mode 100644 libc/sysdeps/linux/nios2/crti.S create mode 100644 libc/sysdeps/linux/nios2/crtn.S create mode 100644 libc/sysdeps/linux/nios2/fpu_control.h create mode 100644 libc/sysdeps/linux/nios2/setjmp.S create mode 100644 libc/sysdeps/linux/nios2/sys/procfs.h create mode 100644 libc/sysdeps/linux/nios2/sys/ucontext.h create mode 100644 libc/sysdeps/linux/nios2/syscall.c create mode 100644 libc/sysdeps/linux/nios2/vfork.S create mode 100644 libc/sysdeps/linux/powerpc/Makefile create mode 100644 libc/sysdeps/linux/powerpc/Makefile.arch create mode 100644 libc/sysdeps/linux/powerpc/README.bits create mode 100644 libc/sysdeps/linux/powerpc/__longjmp.S create mode 100644 libc/sysdeps/linux/powerpc/__syscall_error.c create mode 100644 libc/sysdeps/linux/powerpc/__uClibc_syscall.S create mode 100644 libc/sysdeps/linux/powerpc/bits/atomic.h create mode 100644 libc/sysdeps/linux/powerpc/bits/endian.h create mode 100644 libc/sysdeps/linux/powerpc/bits/fcntl.h create mode 100644 libc/sysdeps/linux/powerpc/bits/fenv.h create mode 100644 libc/sysdeps/linux/powerpc/bits/fenvinline.h create mode 100644 libc/sysdeps/linux/powerpc/bits/ioctl-types.h create mode 100644 libc/sysdeps/linux/powerpc/bits/ipc.h create mode 100644 libc/sysdeps/linux/powerpc/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/powerpc/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/powerpc/bits/mathdef.h create mode 100644 libc/sysdeps/linux/powerpc/bits/mathinline.h create mode 100644 libc/sysdeps/linux/powerpc/bits/mman.h create mode 100644 libc/sysdeps/linux/powerpc/bits/msq.h create mode 100644 libc/sysdeps/linux/powerpc/bits/sem.h create mode 100644 libc/sysdeps/linux/powerpc/bits/setjmp.h create mode 100644 libc/sysdeps/linux/powerpc/bits/shm.h create mode 100644 libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/powerpc/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/powerpc/bits/stat.h create mode 100644 libc/sysdeps/linux/powerpc/bits/syscalls.h create mode 100644 libc/sysdeps/linux/powerpc/bits/sysdep.h create mode 100644 libc/sysdeps/linux/powerpc/bits/termios.h create mode 100644 libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/powerpc/bits/wordsize.h create mode 100644 libc/sysdeps/linux/powerpc/brk.S create mode 100644 libc/sysdeps/linux/powerpc/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/powerpc/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/powerpc/clone.S create mode 100644 libc/sysdeps/linux/powerpc/crt1.S create mode 100644 libc/sysdeps/linux/powerpc/crti.S create mode 100644 libc/sysdeps/linux/powerpc/crtn.S create mode 100644 libc/sysdeps/linux/powerpc/fenv.h create mode 100644 libc/sysdeps/linux/powerpc/fpu_control.h create mode 100644 libc/sysdeps/linux/powerpc/ioctl.c create mode 100644 libc/sysdeps/linux/powerpc/ppc_asm.h create mode 100644 libc/sysdeps/linux/powerpc/pread_write.c create mode 100644 libc/sysdeps/linux/powerpc/setjmp.S create mode 100644 libc/sysdeps/linux/powerpc/sys/procfs.h create mode 100644 libc/sysdeps/linux/powerpc/sys/ptrace.h create mode 100644 libc/sysdeps/linux/powerpc/sys/ucontext.h create mode 100644 libc/sysdeps/linux/powerpc/sys/user.h create mode 100644 libc/sysdeps/linux/powerpc/syscall.S create mode 100644 libc/sysdeps/linux/powerpc/vfork.S create mode 100644 libc/sysdeps/linux/sh/Makefile create mode 100644 libc/sysdeps/linux/sh/Makefile.arch create mode 100644 libc/sysdeps/linux/sh/___fpscr_values.S create mode 100644 libc/sysdeps/linux/sh/__init_brk.c create mode 100644 libc/sysdeps/linux/sh/__longjmp.S create mode 100644 libc/sysdeps/linux/sh/bits/atomic.h create mode 100644 libc/sysdeps/linux/sh/bits/endian.h create mode 100644 libc/sysdeps/linux/sh/bits/fcntl.h create mode 100644 libc/sysdeps/linux/sh/bits/fenv.h create mode 100644 libc/sysdeps/linux/sh/bits/huge_val.h create mode 100644 libc/sysdeps/linux/sh/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/sh/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/sh/bits/mathdef.h create mode 100644 libc/sysdeps/linux/sh/bits/mman.h create mode 100644 libc/sysdeps/linux/sh/bits/setjmp.h create mode 100644 libc/sysdeps/linux/sh/bits/shm.h create mode 100644 libc/sysdeps/linux/sh/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/sh/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/sh/bits/syscalls.h create mode 100644 libc/sysdeps/linux/sh/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/sh/bits/wordsize.h create mode 100644 libc/sysdeps/linux/sh/brk.c create mode 100644 libc/sysdeps/linux/sh/clone.S create mode 100644 libc/sysdeps/linux/sh/crt1.S create mode 100644 libc/sysdeps/linux/sh/crti.S create mode 100644 libc/sysdeps/linux/sh/crtn.S create mode 100644 libc/sysdeps/linux/sh/fpu_control.h create mode 100644 libc/sysdeps/linux/sh/mmap.c create mode 100644 libc/sysdeps/linux/sh/pipe.c create mode 100644 libc/sysdeps/linux/sh/pread_write.c create mode 100644 libc/sysdeps/linux/sh/sbrk.c create mode 100644 libc/sysdeps/linux/sh/setjmp.S create mode 100644 libc/sysdeps/linux/sh/sys/io.h create mode 100644 libc/sysdeps/linux/sh/sys/procfs.h create mode 100644 libc/sysdeps/linux/sh/sys/ucontext.h create mode 100644 libc/sysdeps/linux/sh/sys/user.h create mode 100644 libc/sysdeps/linux/sh/syscall.c create mode 100644 libc/sysdeps/linux/sh/syscall_error.S create mode 100644 libc/sysdeps/linux/sh/vfork.S create mode 100644 libc/sysdeps/linux/sh64/Makefile create mode 100644 libc/sysdeps/linux/sh64/Makefile.arch create mode 100644 libc/sysdeps/linux/sh64/__init_brk.c create mode 100644 libc/sysdeps/linux/sh64/__longjmp.S create mode 100644 libc/sysdeps/linux/sh64/bits/endian.h create mode 100644 libc/sysdeps/linux/sh64/bits/fcntl.h create mode 100644 libc/sysdeps/linux/sh64/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/sh64/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/sh64/bits/mman.h create mode 100644 libc/sysdeps/linux/sh64/bits/setjmp.h create mode 100644 libc/sysdeps/linux/sh64/bits/shm.h create mode 100644 libc/sysdeps/linux/sh64/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/sh64/bits/syscalls.h create mode 100644 libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/sh64/bits/wordsize.h create mode 100644 libc/sysdeps/linux/sh64/brk.c create mode 100644 libc/sysdeps/linux/sh64/crt1.S create mode 100644 libc/sysdeps/linux/sh64/crti.S create mode 100644 libc/sysdeps/linux/sh64/crtn.S create mode 100644 libc/sysdeps/linux/sh64/sbrk.c create mode 100644 libc/sysdeps/linux/sh64/setjmp.S create mode 100644 libc/sysdeps/linux/sh64/sys/procfs.h create mode 100644 libc/sysdeps/linux/sh64/sys/ucontext.h create mode 100644 libc/sysdeps/linux/sh64/syscall.c create mode 100644 libc/sysdeps/linux/sparc/Makefile create mode 100644 libc/sysdeps/linux/sparc/Makefile.arch create mode 100644 libc/sysdeps/linux/sparc/__longjmp.S create mode 100644 libc/sysdeps/linux/sparc/__syscall_error.c create mode 100644 libc/sysdeps/linux/sparc/_math_inc.h create mode 100644 libc/sysdeps/linux/sparc/bits/endian.h create mode 100644 libc/sysdeps/linux/sparc/bits/fcntl.h create mode 100644 libc/sysdeps/linux/sparc/bits/fenv.h create mode 100644 libc/sysdeps/linux/sparc/bits/ioctls.h create mode 100644 libc/sysdeps/linux/sparc/bits/ipc.h create mode 100644 libc/sysdeps/linux/sparc/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/sparc/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/sparc/bits/mathdef.h create mode 100644 libc/sysdeps/linux/sparc/bits/mathinline.h create mode 100644 libc/sysdeps/linux/sparc/bits/mman.h create mode 100644 libc/sysdeps/linux/sparc/bits/msq.h create mode 100644 libc/sysdeps/linux/sparc/bits/poll.h create mode 100644 libc/sysdeps/linux/sparc/bits/resource.h create mode 100644 libc/sysdeps/linux/sparc/bits/sem.h create mode 100644 libc/sysdeps/linux/sparc/bits/setjmp.h create mode 100644 libc/sysdeps/linux/sparc/bits/shm.h create mode 100644 libc/sysdeps/linux/sparc/bits/sigaction.h create mode 100644 libc/sysdeps/linux/sparc/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/sparc/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/sparc/bits/siginfo.h create mode 100644 libc/sysdeps/linux/sparc/bits/signum.h create mode 100644 libc/sysdeps/linux/sparc/bits/sigstack.h create mode 100644 libc/sysdeps/linux/sparc/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/sparc/bits/stat.h create mode 100644 libc/sysdeps/linux/sparc/bits/statvfs.h create mode 100644 libc/sysdeps/linux/sparc/bits/syscalls.h create mode 100644 libc/sysdeps/linux/sparc/bits/termios.h create mode 100644 libc/sysdeps/linux/sparc/bits/typesizes.h create mode 100644 libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/sparc/bits/wordsize.h create mode 100644 libc/sysdeps/linux/sparc/brk.c create mode 100644 libc/sysdeps/linux/sparc/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/sparc/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/sparc/clone.S create mode 100644 libc/sysdeps/linux/sparc/crt1.S create mode 100644 libc/sysdeps/linux/sparc/crti.S create mode 100644 libc/sysdeps/linux/sparc/crtn.S create mode 100644 libc/sysdeps/linux/sparc/fork.S create mode 100644 libc/sysdeps/linux/sparc/fpu_control.h create mode 100644 libc/sysdeps/linux/sparc/qp_ops.c create mode 100644 libc/sysdeps/linux/sparc/rem.S create mode 100644 libc/sysdeps/linux/sparc/sdiv.S create mode 100644 libc/sysdeps/linux/sparc/setjmp.S create mode 100644 libc/sysdeps/linux/sparc/sparcv7/rem.S create mode 100644 libc/sysdeps/linux/sparc/sparcv7/sdiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv7/udiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv7/umul.S create mode 100644 libc/sysdeps/linux/sparc/sparcv7/urem.S create mode 100644 libc/sysdeps/linux/sparc/sparcv8/rem.S create mode 100644 libc/sysdeps/linux/sparc/sparcv8/sdiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv8/udiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv8/umul.S create mode 100644 libc/sysdeps/linux/sparc/sparcv8/urem.S create mode 100644 libc/sysdeps/linux/sparc/sparcv9/rem.S create mode 100644 libc/sysdeps/linux/sparc/sparcv9/sdiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv9/udiv.S create mode 100644 libc/sysdeps/linux/sparc/sparcv9/umul.S create mode 100644 libc/sysdeps/linux/sparc/sparcv9/urem.S create mode 100644 libc/sysdeps/linux/sparc/sys/procfs.h create mode 100644 libc/sysdeps/linux/sparc/sys/ptrace.h create mode 100644 libc/sysdeps/linux/sparc/sys/ucontext.h create mode 100644 libc/sysdeps/linux/sparc/sys/user.h create mode 100644 libc/sysdeps/linux/sparc/syscall.S create mode 100644 libc/sysdeps/linux/sparc/udiv.S create mode 100644 libc/sysdeps/linux/sparc/umul.S create mode 100644 libc/sysdeps/linux/sparc/urem.S create mode 100644 libc/sysdeps/linux/sparc/vfork.S create mode 100644 libc/sysdeps/linux/v850/Makefile create mode 100644 libc/sysdeps/linux/v850/__longjmp.S create mode 100644 libc/sysdeps/linux/v850/bits/byteswap.h create mode 100644 libc/sysdeps/linux/v850/bits/endian.h create mode 100644 libc/sysdeps/linux/v850/bits/fcntl.h create mode 100644 libc/sysdeps/linux/v850/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/v850/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/v850/bits/mman.h create mode 100644 libc/sysdeps/linux/v850/bits/poll.h create mode 100644 libc/sysdeps/linux/v850/bits/select.h create mode 100644 libc/sysdeps/linux/v850/bits/setjmp.h create mode 100644 libc/sysdeps/linux/v850/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/v850/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/v850/bits/syscalls.h create mode 100644 libc/sysdeps/linux/v850/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/v850/bits/wordsize.h create mode 100644 libc/sysdeps/linux/v850/clinkage.h create mode 100644 libc/sysdeps/linux/v850/clone.c create mode 100644 libc/sysdeps/linux/v850/crt0.S create mode 100644 libc/sysdeps/linux/v850/crti.S create mode 100644 libc/sysdeps/linux/v850/crtn.S create mode 100644 libc/sysdeps/linux/v850/mmap.c create mode 100644 libc/sysdeps/linux/v850/setjmp.S create mode 100644 libc/sysdeps/linux/v850/sys/procfs.h create mode 100644 libc/sysdeps/linux/v850/sys/ptrace.h create mode 100644 libc/sysdeps/linux/v850/sys/ucontext.h create mode 100644 libc/sysdeps/linux/v850/syscall.c create mode 100644 libc/sysdeps/linux/v850/vfork.S create mode 100644 libc/sysdeps/linux/vax/Makefile create mode 100644 libc/sysdeps/linux/vax/Makefile.arch create mode 100644 libc/sysdeps/linux/vax/__longjmp.S create mode 100644 libc/sysdeps/linux/vax/_setjmp.S create mode 100644 libc/sysdeps/linux/vax/bits/byteswap.h create mode 100644 libc/sysdeps/linux/vax/bits/endian.h create mode 100644 libc/sysdeps/linux/vax/bits/fcntl.h create mode 100644 libc/sysdeps/linux/vax/bits/ipc.h create mode 100644 libc/sysdeps/linux/vax/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/vax/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/vax/bits/machine-gmon.h create mode 100644 libc/sysdeps/linux/vax/bits/mman.h create mode 100644 libc/sysdeps/linux/vax/bits/sem.h create mode 100644 libc/sysdeps/linux/vax/bits/setjmp.h create mode 100644 libc/sysdeps/linux/vax/bits/shm.h create mode 100644 libc/sysdeps/linux/vax/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/vax/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/vax/bits/statfs.h create mode 100644 libc/sysdeps/linux/vax/bits/syscalls.h create mode 100644 libc/sysdeps/linux/vax/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/vax/bits/wordsize.h create mode 100644 libc/sysdeps/linux/vax/brk.c create mode 100644 libc/sysdeps/linux/vax/clone.S create mode 100644 libc/sysdeps/linux/vax/crt1.S create mode 100644 libc/sysdeps/linux/vax/crti.S create mode 100644 libc/sysdeps/linux/vax/crtn.S create mode 100644 libc/sysdeps/linux/vax/mmap.c create mode 100644 libc/sysdeps/linux/vax/setjmp.S create mode 100644 libc/sysdeps/linux/vax/sys/procfs.h create mode 100644 libc/sysdeps/linux/vax/sys/ucontext.h create mode 100644 libc/sysdeps/linux/x86_64/Makefile create mode 100644 libc/sysdeps/linux/x86_64/Makefile.arch create mode 100644 libc/sysdeps/linux/x86_64/__longjmp.S create mode 100644 libc/sysdeps/linux/x86_64/__syscall_error.c create mode 100644 libc/sysdeps/linux/x86_64/bits/atomic.h create mode 100644 libc/sysdeps/linux/x86_64/bits/byteswap.h create mode 100644 libc/sysdeps/linux/x86_64/bits/endian.h create mode 100644 libc/sysdeps/linux/x86_64/bits/environments.h create mode 100644 libc/sysdeps/linux/x86_64/bits/fcntl.h create mode 100644 libc/sysdeps/linux/x86_64/bits/fenv.h create mode 100644 libc/sysdeps/linux/x86_64/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/x86_64/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/x86_64/bits/mathdef.h create mode 100644 libc/sysdeps/linux/x86_64/bits/mathinline.h create mode 100644 libc/sysdeps/linux/x86_64/bits/mman.h create mode 100644 libc/sysdeps/linux/x86_64/bits/msq.h create mode 100644 libc/sysdeps/linux/x86_64/bits/sem.h create mode 100644 libc/sysdeps/linux/x86_64/bits/setjmp.h create mode 100644 libc/sysdeps/linux/x86_64/bits/shm.h create mode 100644 libc/sysdeps/linux/x86_64/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/x86_64/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/x86_64/bits/stat.h create mode 100644 libc/sysdeps/linux/x86_64/bits/syscalls.h create mode 100644 libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/x86_64/bits/wordsize.h create mode 100644 libc/sysdeps/linux/x86_64/brk.c create mode 100644 libc/sysdeps/linux/x86_64/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/x86_64/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/x86_64/clone.S create mode 100644 libc/sysdeps/linux/x86_64/crt1.S create mode 100644 libc/sysdeps/linux/x86_64/crti.S create mode 100644 libc/sysdeps/linux/x86_64/crtn.S create mode 100644 libc/sysdeps/linux/x86_64/fpu_control.h create mode 100644 libc/sysdeps/linux/x86_64/mmap.c create mode 100644 libc/sysdeps/linux/x86_64/setjmp.S create mode 100644 libc/sysdeps/linux/x86_64/sigaction.c create mode 100644 libc/sysdeps/linux/x86_64/sys/debugreg.h create mode 100644 libc/sysdeps/linux/x86_64/sys/epoll.h create mode 100644 libc/sysdeps/linux/x86_64/sys/io.h create mode 100644 libc/sysdeps/linux/x86_64/sys/perm.h create mode 100644 libc/sysdeps/linux/x86_64/sys/procfs.h create mode 100644 libc/sysdeps/linux/x86_64/sys/reg.h create mode 100644 libc/sysdeps/linux/x86_64/sys/ucontext.h create mode 100644 libc/sysdeps/linux/x86_64/sys/user.h create mode 100644 libc/sysdeps/linux/x86_64/syscall.S create mode 100644 libc/sysdeps/linux/x86_64/vfork.S create mode 100644 libc/sysdeps/linux/xtensa/Makefile create mode 100644 libc/sysdeps/linux/xtensa/Makefile.arch create mode 100644 libc/sysdeps/linux/xtensa/__longjmp.S create mode 100644 libc/sysdeps/linux/xtensa/__syscall_error.c create mode 100644 libc/sysdeps/linux/xtensa/bits/endian.h create mode 100644 libc/sysdeps/linux/xtensa/bits/fcntl.h create mode 100644 libc/sysdeps/linux/xtensa/bits/ipc.h create mode 100644 libc/sysdeps/linux/xtensa/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/xtensa/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/xtensa/bits/mathdef.h create mode 100644 libc/sysdeps/linux/xtensa/bits/mman.h create mode 100644 libc/sysdeps/linux/xtensa/bits/msq.h create mode 100644 libc/sysdeps/linux/xtensa/bits/setjmp.h create mode 100644 libc/sysdeps/linux/xtensa/bits/shm.h create mode 100644 libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h create mode 100644 libc/sysdeps/linux/xtensa/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/xtensa/bits/stat.h create mode 100644 libc/sysdeps/linux/xtensa/bits/syscalls.h create mode 100644 libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/xtensa/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/xtensa/bits/wordsize.h create mode 100644 libc/sysdeps/linux/xtensa/bits/xtensa-config.h create mode 100644 libc/sysdeps/linux/xtensa/brk.c create mode 100644 libc/sysdeps/linux/xtensa/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/xtensa/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/xtensa/clone.S create mode 100644 libc/sysdeps/linux/xtensa/crt1.S create mode 100644 libc/sysdeps/linux/xtensa/crti.S create mode 100644 libc/sysdeps/linux/xtensa/crtn.S create mode 100644 libc/sysdeps/linux/xtensa/fork.c create mode 100644 libc/sysdeps/linux/xtensa/mmap.S create mode 100644 libc/sysdeps/linux/xtensa/posix_fadvise.c create mode 100644 libc/sysdeps/linux/xtensa/posix_fadvise64.c create mode 100644 libc/sysdeps/linux/xtensa/pread_write.c create mode 100644 libc/sysdeps/linux/xtensa/setjmp.S create mode 100644 libc/sysdeps/linux/xtensa/sigaction.c create mode 100644 libc/sysdeps/linux/xtensa/sigrestorer.S create mode 100644 libc/sysdeps/linux/xtensa/sys/procfs.h create mode 100644 libc/sysdeps/linux/xtensa/sys/ptrace.h create mode 100644 libc/sysdeps/linux/xtensa/sys/ucontext.h create mode 100644 libc/sysdeps/linux/xtensa/syscall.S create mode 100644 libc/sysdeps/linux/xtensa/sysdep.h create mode 100644 libc/sysdeps/linux/xtensa/vfork.S create mode 100644 libc/sysdeps/linux/xtensa/windowspill.S create mode 100644 libc/termios/.indent.pro create mode 100644 libc/termios/Makefile create mode 100644 libc/termios/Makefile.in create mode 100644 libc/termios/cfmakeraw.c create mode 100644 libc/termios/cfsetspeed.c create mode 100644 libc/termios/isatty.c create mode 100644 libc/termios/kernel_termios.h create mode 100644 libc/termios/speed.c create mode 100644 libc/termios/tcdrain.c create mode 100644 libc/termios/tcflow.c create mode 100644 libc/termios/tcflush.c create mode 100644 libc/termios/tcgetattr.c create mode 100644 libc/termios/tcgetpgrp.c create mode 100644 libc/termios/tcgetsid.c create mode 100644 libc/termios/tcsendbrk.c create mode 100644 libc/termios/tcsetattr.c create mode 100644 libc/termios/tcsetpgrp.c create mode 100644 libc/termios/ttyname.c create mode 100644 libc/unistd/.indent.pro create mode 100644 libc/unistd/Makefile create mode 100644 libc/unistd/Makefile.in create mode 100644 libc/unistd/__exec_alloc.c create mode 100644 libc/unistd/confstr.c create mode 100644 libc/unistd/daemon.c create mode 100644 libc/unistd/exec.c create mode 100644 libc/unistd/execl.c create mode 100644 libc/unistd/execle.c create mode 100644 libc/unistd/execlp.c create mode 100644 libc/unistd/execv.c create mode 100644 libc/unistd/execvp.c create mode 100644 libc/unistd/fpathconf.c create mode 100644 libc/unistd/getlogin.c create mode 100644 libc/unistd/getopt-susv3.c create mode 100644 libc/unistd/getopt.c create mode 100644 libc/unistd/getopt_int.h create mode 100644 libc/unistd/getopt_long-simple.c create mode 100644 libc/unistd/getpass.c create mode 100644 libc/unistd/getsubopt-susv3.c create mode 100644 libc/unistd/getsubopt.c create mode 100644 libc/unistd/pathconf.c create mode 100644 libc/unistd/sleep.c create mode 100644 libc/unistd/swab.c create mode 100644 libc/unistd/sysconf.c create mode 100644 libc/unistd/ualarm.c create mode 100644 libc/unistd/usershell.c create mode 100644 libc/unistd/usleep.c create mode 100644 libcrypt/Makefile create mode 100644 libcrypt/Makefile.in create mode 100644 libcrypt/crypt.c create mode 100644 libcrypt/crypt_stub.c create mode 100644 libcrypt/des.c create mode 100644 libcrypt/libcrypt.h create mode 100644 libcrypt/md5.c create mode 100644 libintl/Makefile create mode 100644 libintl/Makefile.in create mode 100644 libintl/intl.c create mode 100644 libm/Makefile create mode 100644 libm/Makefile.in create mode 100644 libm/README create mode 100644 libm/carg.c create mode 100644 libm/e_acos.c create mode 100644 libm/e_acosh.c create mode 100644 libm/e_asin.c create mode 100644 libm/e_atan2.c create mode 100644 libm/e_atanh.c create mode 100644 libm/e_cosh.c create mode 100644 libm/e_exp.c create mode 100644 libm/e_fmod.c create mode 100644 libm/e_gamma.c create mode 100644 libm/e_gamma_r.c create mode 100644 libm/e_hypot.c create mode 100644 libm/e_j0.c create mode 100644 libm/e_j1.c create mode 100644 libm/e_jn.c create mode 100644 libm/e_lgamma.c create mode 100644 libm/e_lgamma_r.c create mode 100644 libm/e_log.c create mode 100644 libm/e_log10.c create mode 100644 libm/e_log2.c create mode 100644 libm/e_pow.c create mode 100644 libm/e_rem_pio2.c create mode 100644 libm/e_remainder.c create mode 100644 libm/e_scalb.c create mode 100644 libm/e_sinh.c create mode 100644 libm/e_sqrt.c create mode 100644 libm/float_wrappers.c create mode 100644 libm/i386/Makefile.arch create mode 100644 libm/i386/fclrexcpt.c create mode 100644 libm/i386/fedisblxcpt.c create mode 100644 libm/i386/feenablxcpt.c create mode 100644 libm/i386/fegetenv.c create mode 100644 libm/i386/fegetexcept.c create mode 100644 libm/i386/fegetround.c create mode 100644 libm/i386/feholdexcpt.c create mode 100644 libm/i386/fesetenv.c create mode 100644 libm/i386/fesetround.c create mode 100644 libm/i386/feupdateenv.c create mode 100644 libm/i386/fgetexcptflg.c create mode 100644 libm/i386/fraiseexcpt.c create mode 100644 libm/i386/fsetexcptflg.c create mode 100644 libm/i386/ftestexcept.c create mode 100644 libm/k_cos.c create mode 100644 libm/k_rem_pio2.c create mode 100644 libm/k_sin.c create mode 100644 libm/k_standard.c create mode 100644 libm/k_tan.c create mode 100644 libm/ldouble_wrappers.c create mode 100644 libm/math_private.h create mode 100644 libm/nan.c create mode 100644 libm/powerpc/classic/Makefile.arch create mode 100644 libm/powerpc/e500/Makefile.arch create mode 100644 libm/powerpc/e500/README.txt create mode 100644 libm/powerpc/e500/fpu/Makefile.arch create mode 100644 libm/powerpc/e500/fpu/fclrexcpt.c create mode 100644 libm/powerpc/e500/fpu/fe_nomask.c create mode 100644 libm/powerpc/e500/fpu/fedisblxcpt.c create mode 100644 libm/powerpc/e500/fpu/feenablxcpt.c create mode 100644 libm/powerpc/e500/fpu/fegetenv.c create mode 100644 libm/powerpc/e500/fpu/fegetexcept.c create mode 100644 libm/powerpc/e500/fpu/fegetround.c create mode 100644 libm/powerpc/e500/fpu/feholdexcpt.c create mode 100644 libm/powerpc/e500/fpu/fenv_const.c create mode 100644 libm/powerpc/e500/fpu/fenv_libc.h create mode 100644 libm/powerpc/e500/fpu/fesetenv.c create mode 100644 libm/powerpc/e500/fpu/fesetround.c create mode 100644 libm/powerpc/e500/fpu/feupdateenv.c create mode 100644 libm/powerpc/e500/fpu/fgetexcptflg.c create mode 100644 libm/powerpc/e500/fpu/fraiseexcpt.c create mode 100644 libm/powerpc/e500/fpu/fsetexcptflg.c create mode 100644 libm/powerpc/e500/fpu/ftestexcept.c create mode 100644 libm/powerpc/e500/spe-raise.c create mode 100644 libm/s_asinh.c create mode 100644 libm/s_atan.c create mode 100644 libm/s_cbrt.c create mode 100644 libm/s_ceil.c create mode 100644 libm/s_copysign.c create mode 100644 libm/s_cos.c create mode 100644 libm/s_erf.c create mode 100644 libm/s_expm1.c create mode 100644 libm/s_fabs.c create mode 100644 libm/s_fdim.c create mode 100644 libm/s_finite.c create mode 100644 libm/s_finitef.c create mode 100644 libm/s_floor.c create mode 100644 libm/s_fma.c create mode 100644 libm/s_fmax.c create mode 100644 libm/s_fmin.c create mode 100644 libm/s_fpclassify.c create mode 100644 libm/s_fpclassifyf.c create mode 100644 libm/s_frexp.c create mode 100644 libm/s_ilogb.c create mode 100644 libm/s_isinf.c create mode 100644 libm/s_isinff.c create mode 100644 libm/s_isnan.c create mode 100644 libm/s_isnanf.c create mode 100644 libm/s_ldexp.c create mode 100644 libm/s_lib_version.c create mode 100644 libm/s_llrint.c create mode 100644 libm/s_llround.c create mode 100644 libm/s_log1p.c create mode 100644 libm/s_logb.c create mode 100644 libm/s_lrint.c create mode 100644 libm/s_lround.c create mode 100644 libm/s_matherr.c create mode 100644 libm/s_modf.c create mode 100644 libm/s_nearbyint.c create mode 100644 libm/s_nextafter.c create mode 100644 libm/s_remquo.c create mode 100644 libm/s_rint.c create mode 100644 libm/s_round.c create mode 100644 libm/s_scalbln.c create mode 100644 libm/s_scalbn.c create mode 100644 libm/s_signbit.c create mode 100644 libm/s_signbitf.c create mode 100644 libm/s_signgam.c create mode 100644 libm/s_significand.c create mode 100644 libm/s_sin.c create mode 100644 libm/s_tan.c create mode 100644 libm/s_tanh.c create mode 100644 libm/s_trunc.c create mode 100644 libm/w_acos.c create mode 100644 libm/w_acosh.c create mode 100644 libm/w_asin.c create mode 100644 libm/w_atan2.c create mode 100644 libm/w_atanh.c create mode 100644 libm/w_cabs.c create mode 100644 libm/w_cosh.c create mode 100644 libm/w_drem.c create mode 100644 libm/w_exp.c create mode 100644 libm/w_exp2.c create mode 100644 libm/w_fmod.c create mode 100644 libm/w_gamma.c create mode 100644 libm/w_gamma_r.c create mode 100644 libm/w_hypot.c create mode 100644 libm/w_j0.c create mode 100644 libm/w_j1.c create mode 100644 libm/w_jn.c create mode 100644 libm/w_lgamma.c create mode 100644 libm/w_lgamma_r.c create mode 100644 libm/w_log.c create mode 100644 libm/w_log10.c create mode 100644 libm/w_log2.c create mode 100644 libm/w_pow.c create mode 100644 libm/w_remainder.c create mode 100644 libm/w_scalb.c create mode 100644 libm/w_sinh.c create mode 100644 libm/w_sqrt.c create mode 100644 libm/w_tgamma.c create mode 100644 libnsl/Makefile create mode 100644 libnsl/Makefile.in create mode 100644 libnsl/nsl.c create mode 100644 libpthread/Makefile create mode 100644 libpthread/Makefile.in create mode 100644 libpthread/linuxthreads.old/Makefile create mode 100644 libpthread/linuxthreads.old/Makefile.in create mode 100644 libpthread/linuxthreads.old/attr.c create mode 100644 libpthread/linuxthreads.old/cancel.c create mode 100644 libpthread/linuxthreads.old/condvar.c create mode 100644 libpthread/linuxthreads.old/debug.h create mode 100644 libpthread/linuxthreads.old/errno.c create mode 100644 libpthread/linuxthreads.old/events.c create mode 100644 libpthread/linuxthreads.old/forward.c create mode 100644 libpthread/linuxthreads.old/internals.h create mode 100644 libpthread/linuxthreads.old/join.c create mode 100644 libpthread/linuxthreads.old/libc_pthread_init.c create mode 100644 libpthread/linuxthreads.old/linuxthreads.texi create mode 100644 libpthread/linuxthreads.old/locale.c create mode 100644 libpthread/linuxthreads.old/lockfile.c create mode 100644 libpthread/linuxthreads.old/manager.c create mode 100644 libpthread/linuxthreads.old/mutex.c create mode 100644 libpthread/linuxthreads.old/oldsemaphore.c create mode 100644 libpthread/linuxthreads.old/pt-machine.c create mode 100644 libpthread/linuxthreads.old/ptfork.c create mode 100644 libpthread/linuxthreads.old/pthread.c create mode 100644 libpthread/linuxthreads.old/ptlongjmp.c create mode 100644 libpthread/linuxthreads.old/queue.h create mode 100644 libpthread/linuxthreads.old/restart.h create mode 100644 libpthread/linuxthreads.old/rwlock.c create mode 100644 libpthread/linuxthreads.old/semaphore.c create mode 100644 libpthread/linuxthreads.old/semaphore.h create mode 100644 libpthread/linuxthreads.old/signals.c create mode 100644 libpthread/linuxthreads.old/specific.c create mode 100644 libpthread/linuxthreads.old/spinlock.c create mode 100644 libpthread/linuxthreads.old/spinlock.h create mode 100644 libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/i386/tls.h create mode 100644 libpthread/linuxthreads.old/sysdeps/i386/useldt.h create mode 100644 libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/ia64/tls.h create mode 100644 libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/pthread.h create mode 100644 libpthread/linuxthreads.old/sysdeps/pthread/tls.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sh/tls.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch create mode 100644 libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c create mode 100644 libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h create mode 100644 libpthread/linuxthreads.old/sysdeps/x86_64/tls.h create mode 100644 libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h create mode 100644 libpthread/linuxthreads.old/wrapsyscall.c create mode 100644 libpthread/linuxthreads.old_db/Banner create mode 100644 libpthread/linuxthreads.old_db/Makefile create mode 100644 libpthread/linuxthreads.old_db/Makefile.in create mode 100644 libpthread/linuxthreads.old_db/Versions create mode 100644 libpthread/linuxthreads.old_db/proc_service.h create mode 100644 libpthread/linuxthreads.old_db/td_init.c create mode 100644 libpthread/linuxthreads.old_db/td_log.c create mode 100644 libpthread/linuxthreads.old_db/td_symbol_list.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_clear_event.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_delete.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_enable_stats.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_event_addr.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_event_getmsg.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_get_nthreads.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_get_ph.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_get_stats.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_map_id2thr.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_new.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_reset_stats.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_set_event.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_setconcurrency.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_thr_iter.c create mode 100644 libpthread/linuxthreads.old_db/td_ta_tsd_iter.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_clear_event.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_dbresume.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_dbsuspend.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_event_enable.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_event_getmsg.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_get_info.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_getfpregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_getgregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_getxregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_getxregsize.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_set_event.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_setfpregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_setgregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_setprio.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_setsigpending.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_setxregs.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_sigsetmask.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_tsd.c create mode 100644 libpthread/linuxthreads.old_db/td_thr_validate.c create mode 100644 libpthread/linuxthreads.old_db/thread_db.h create mode 100644 libpthread/linuxthreads.old_db/thread_dbP.h create mode 100644 libpthread/linuxthreads/.cvsignore create mode 100644 libpthread/linuxthreads/Makefile create mode 100644 libpthread/linuxthreads/Makefile.in create mode 100644 libpthread/linuxthreads/alloca_cutoff.c create mode 100644 libpthread/linuxthreads/attr.c create mode 100644 libpthread/linuxthreads/barrier.c create mode 100644 libpthread/linuxthreads/cancel.c create mode 100644 libpthread/linuxthreads/condvar.c create mode 100644 libpthread/linuxthreads/descr.h create mode 100644 libpthread/linuxthreads/errno.c create mode 100644 libpthread/linuxthreads/events.c create mode 100644 libpthread/linuxthreads/forward.c create mode 100644 libpthread/linuxthreads/internals.h create mode 100644 libpthread/linuxthreads/join.c create mode 100644 libpthread/linuxthreads/libc-cancellation.c create mode 100644 libpthread/linuxthreads/libc_pthread_init.c create mode 100644 libpthread/linuxthreads/lockfile.c create mode 100644 libpthread/linuxthreads/manager.c create mode 100644 libpthread/linuxthreads/mutex.c create mode 100644 libpthread/linuxthreads/pt-machine.c create mode 100644 libpthread/linuxthreads/ptcleanup.c create mode 100644 libpthread/linuxthreads/ptclock_gettime.c create mode 100644 libpthread/linuxthreads/ptclock_settime.c create mode 100644 libpthread/linuxthreads/ptfork.c create mode 100644 libpthread/linuxthreads/pthandles.c create mode 100644 libpthread/linuxthreads/pthread.c create mode 100644 libpthread/linuxthreads/pthread_atfork.c create mode 100644 libpthread/linuxthreads/pthread_setegid.c create mode 100644 libpthread/linuxthreads/pthread_seteuid.c create mode 100644 libpthread/linuxthreads/pthread_setgid.c create mode 100644 libpthread/linuxthreads/pthread_setregid.c create mode 100644 libpthread/linuxthreads/pthread_setresgid.c create mode 100644 libpthread/linuxthreads/pthread_setresuid.c create mode 100644 libpthread/linuxthreads/pthread_setreuid.c create mode 100644 libpthread/linuxthreads/pthread_setuid.c create mode 100644 libpthread/linuxthreads/queue.h create mode 100644 libpthread/linuxthreads/restart.h create mode 100644 libpthread/linuxthreads/rwlock.c create mode 100644 libpthread/linuxthreads/semaphore.c create mode 100644 libpthread/linuxthreads/semaphore.h create mode 100644 libpthread/linuxthreads/sighandler.c create mode 100644 libpthread/linuxthreads/signals.c create mode 100644 libpthread/linuxthreads/specific.c create mode 100644 libpthread/linuxthreads/spinlock.c create mode 100644 libpthread/linuxthreads/spinlock.h create mode 100644 libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/alpha/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/alpha/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/alpha/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/arm/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/arm/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/arm/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/avr32/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/cris/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/cris/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/hppa/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/hppa/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/i386/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/i386/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/i386/useldt.h create mode 100644 libpthread/linuxthreads/sysdeps/ia64/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/ia64/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/ia64/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/m68k/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/m68k/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/mips/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/mips/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/mips/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/powerpc/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/.cvsignore create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/errno-loc.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/flockfile.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/funlockfile.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/kernel-features.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/list.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/not-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/posix-timer.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/pthread.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/res-state.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/semaphore.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/sigaction.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_create.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_delete.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_routines.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/timer_settime.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/tst-timer.c create mode 100644 libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h create mode 100644 libpthread/linuxthreads/sysdeps/s390/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/s390/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/sh/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/sh/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/sh/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/sparc/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/sparc/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/sparc/tls.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h create mode 100644 libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h create mode 100644 libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym create mode 100644 libpthread/linuxthreads/sysdeps/x86_64/tls.h create mode 100644 libpthread/linuxthreads_db/.cvsignore create mode 100644 libpthread/linuxthreads_db/Banner create mode 100644 libpthread/linuxthreads_db/ChangeLog create mode 100644 libpthread/linuxthreads_db/Makefile create mode 100644 libpthread/linuxthreads_db/Makefile.in create mode 100644 libpthread/linuxthreads_db/Makefile.old create mode 100644 libpthread/linuxthreads_db/Versions create mode 100644 libpthread/linuxthreads_db/proc_service.h create mode 100644 libpthread/linuxthreads_db/shlib-versions create mode 100644 libpthread/linuxthreads_db/td_init.c create mode 100644 libpthread/linuxthreads_db/td_log.c create mode 100644 libpthread/linuxthreads_db/td_symbol_list.c create mode 100644 libpthread/linuxthreads_db/td_ta_clear_event.c create mode 100644 libpthread/linuxthreads_db/td_ta_delete.c create mode 100644 libpthread/linuxthreads_db/td_ta_enable_stats.c create mode 100644 libpthread/linuxthreads_db/td_ta_event_addr.c create mode 100644 libpthread/linuxthreads_db/td_ta_event_getmsg.c create mode 100644 libpthread/linuxthreads_db/td_ta_get_nthreads.c create mode 100644 libpthread/linuxthreads_db/td_ta_get_ph.c create mode 100644 libpthread/linuxthreads_db/td_ta_get_stats.c create mode 100644 libpthread/linuxthreads_db/td_ta_map_id2thr.c create mode 100644 libpthread/linuxthreads_db/td_ta_map_lwp2thr.c create mode 100644 libpthread/linuxthreads_db/td_ta_new.c create mode 100644 libpthread/linuxthreads_db/td_ta_reset_stats.c create mode 100644 libpthread/linuxthreads_db/td_ta_set_event.c create mode 100644 libpthread/linuxthreads_db/td_ta_setconcurrency.c create mode 100644 libpthread/linuxthreads_db/td_ta_thr_iter.c create mode 100644 libpthread/linuxthreads_db/td_ta_tsd_iter.c create mode 100644 libpthread/linuxthreads_db/td_thr_clear_event.c create mode 100644 libpthread/linuxthreads_db/td_thr_dbresume.c create mode 100644 libpthread/linuxthreads_db/td_thr_dbsuspend.c create mode 100644 libpthread/linuxthreads_db/td_thr_event_enable.c create mode 100644 libpthread/linuxthreads_db/td_thr_event_getmsg.c create mode 100644 libpthread/linuxthreads_db/td_thr_get_info.c create mode 100644 libpthread/linuxthreads_db/td_thr_getfpregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_getgregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_getxregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_getxregsize.c create mode 100644 libpthread/linuxthreads_db/td_thr_set_event.c create mode 100644 libpthread/linuxthreads_db/td_thr_setfpregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_setgregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_setprio.c create mode 100644 libpthread/linuxthreads_db/td_thr_setsigpending.c create mode 100644 libpthread/linuxthreads_db/td_thr_setxregs.c create mode 100644 libpthread/linuxthreads_db/td_thr_sigsetmask.c create mode 100644 libpthread/linuxthreads_db/td_thr_tls_get_addr.c create mode 100644 libpthread/linuxthreads_db/td_thr_tlsbase.c create mode 100644 libpthread/linuxthreads_db/td_thr_tsd.c create mode 100644 libpthread/linuxthreads_db/td_thr_validate.c create mode 100644 libpthread/linuxthreads_db/thread_db.h create mode 100644 libpthread/linuxthreads_db/thread_dbP.h create mode 100644 libresolv/Makefile create mode 100644 libresolv/Makefile.in create mode 100644 libresolv/resolv.c create mode 100644 librt/Makefile create mode 100644 librt/Makefile.in create mode 100644 librt/kernel-posix-timers.h create mode 100644 librt/mq_close.c create mode 100644 librt/mq_getsetattr.c create mode 100644 librt/mq_notify.c create mode 100644 librt/mq_open.c create mode 100644 librt/mq_receive.c create mode 100644 librt/mq_send.c create mode 100644 librt/mq_unlink.c create mode 100644 librt/timer_create.c create mode 100644 librt/timer_delete.c create mode 100644 librt/timer_getoverr.c create mode 100644 librt/timer_gettime.c create mode 100644 librt/timer_settime.c create mode 100644 libutil/Makefile create mode 100644 libutil/Makefile.in create mode 100644 libutil/forkpty.c create mode 100644 libutil/login.c create mode 100644 libutil/login_tty.c create mode 100644 libutil/logout.c create mode 100644 libutil/logwtmp.c create mode 100644 libutil/openpty.c create mode 100644 test/Makefile create mode 100644 test/README create mode 100644 test/Rules.mak create mode 100644 test/Test.mak create mode 100644 test/args/Makefile create mode 100644 test/args/arg_test.c create mode 100644 test/args/arg_test.out.good create mode 100644 test/args/arg_test_glibc.out.good create mode 100644 test/assert/Makefile create mode 100644 test/assert/assert.c create mode 100644 test/build/Makefile create mode 100644 test/build/check_config_options.sh create mode 100644 test/crypt/Makefile create mode 100644 test/crypt/crypt.c create mode 100644 test/crypt/crypt.input create mode 100644 test/crypt/crypt.out.good create mode 100644 test/crypt/md5c-test.c create mode 100644 test/ctype/Makefile create mode 100644 test/ctype/ctype.c create mode 100644 test/dlopen/Makefile create mode 100644 test/dlopen/dladdr.c create mode 100644 test/dlopen/dlafk.c create mode 100644 test/dlopen/dlstatic.c create mode 100644 test/dlopen/dltest.c create mode 100644 test/dlopen/dltest2.c create mode 100644 test/dlopen/dlundef.c create mode 100644 test/dlopen/libafk-temp.c create mode 100644 test/dlopen/libafk.c create mode 100644 test/dlopen/libstatic.c create mode 100644 test/dlopen/libtest.c create mode 100644 test/dlopen/libtest1.c create mode 100644 test/dlopen/libtest2.c create mode 100644 test/dlopen/libtest3.c create mode 100644 test/dlopen/libundef.c create mode 100644 test/dlopen/test1.c create mode 100644 test/dlopen/test2.c create mode 100644 test/dlopen/test3.c create mode 100644 test/inet/Makefile create mode 100644 test/inet/bug-if1.c create mode 100644 test/inet/gethost_r-align.c create mode 100644 test/inet/if_nameindex.c create mode 100644 test/inet/tst-aton.c create mode 100644 test/inet/tst-ethers-line.c create mode 100644 test/inet/tst-ethers.c create mode 100644 test/inet/tst-network.c create mode 100644 test/inet/tst-ntoa.c create mode 100644 test/locale-mbwc/Makefile create mode 100644 test/locale-mbwc/dat_isw-funcs.h create mode 100644 test/locale-mbwc/dat_iswalnum.c create mode 100644 test/locale-mbwc/dat_iswalpha.c create mode 100644 test/locale-mbwc/dat_iswcntrl.c create mode 100644 test/locale-mbwc/dat_iswctype.c create mode 100644 test/locale-mbwc/dat_iswdigit.c create mode 100644 test/locale-mbwc/dat_iswgraph.c create mode 100644 test/locale-mbwc/dat_iswlower.c create mode 100644 test/locale-mbwc/dat_iswprint.c create mode 100644 test/locale-mbwc/dat_iswpunct.c create mode 100644 test/locale-mbwc/dat_iswspace.c create mode 100644 test/locale-mbwc/dat_iswupper.c create mode 100644 test/locale-mbwc/dat_iswxdigit.c create mode 100644 test/locale-mbwc/dat_mblen.c create mode 100644 test/locale-mbwc/dat_mbrlen.c create mode 100644 test/locale-mbwc/dat_mbrtowc.c create mode 100644 test/locale-mbwc/dat_mbsrtowcs.c create mode 100644 test/locale-mbwc/dat_mbstowcs.c create mode 100644 test/locale-mbwc/dat_mbtowc.c create mode 100644 test/locale-mbwc/dat_strcoll.c create mode 100644 test/locale-mbwc/dat_strfmon.c create mode 100644 test/locale-mbwc/dat_strxfrm.c create mode 100644 test/locale-mbwc/dat_swscanf.c create mode 100644 test/locale-mbwc/dat_tow-funcs.h create mode 100644 test/locale-mbwc/dat_towctrans.c create mode 100644 test/locale-mbwc/dat_towlower.c create mode 100644 test/locale-mbwc/dat_towupper.c create mode 100644 test/locale-mbwc/dat_wcrtomb.c create mode 100644 test/locale-mbwc/dat_wcscat.c create mode 100644 test/locale-mbwc/dat_wcschr.c create mode 100644 test/locale-mbwc/dat_wcscmp.c create mode 100644 test/locale-mbwc/dat_wcscoll.c create mode 100644 test/locale-mbwc/dat_wcscpy.c create mode 100644 test/locale-mbwc/dat_wcscspn.c create mode 100644 test/locale-mbwc/dat_wcslen.c create mode 100644 test/locale-mbwc/dat_wcsncat.c create mode 100644 test/locale-mbwc/dat_wcsncmp.c create mode 100644 test/locale-mbwc/dat_wcsncpy.c create mode 100644 test/locale-mbwc/dat_wcspbrk.c create mode 100644 test/locale-mbwc/dat_wcsrtombs.c create mode 100644 test/locale-mbwc/dat_wcsspn.c create mode 100644 test/locale-mbwc/dat_wcsstr.c create mode 100644 test/locale-mbwc/dat_wcstod.c create mode 100644 test/locale-mbwc/dat_wcstok.c create mode 100644 test/locale-mbwc/dat_wcstombs.c create mode 100644 test/locale-mbwc/dat_wcswidth.c create mode 100644 test/locale-mbwc/dat_wcsxfrm.c create mode 100644 test/locale-mbwc/dat_wctob.c create mode 100644 test/locale-mbwc/dat_wctomb.c create mode 100644 test/locale-mbwc/dat_wctrans.c create mode 100644 test/locale-mbwc/dat_wctype.c create mode 100644 test/locale-mbwc/dat_wcwidth.c create mode 100644 test/locale-mbwc/tgn_funcdef.h create mode 100644 test/locale-mbwc/tgn_locdef.h create mode 100644 test/locale-mbwc/tsp_common.c create mode 100644 test/locale-mbwc/tst_funcs.h create mode 100644 test/locale-mbwc/tst_iswalnum.c create mode 100644 test/locale-mbwc/tst_iswalpha.c create mode 100644 test/locale-mbwc/tst_iswcntrl.c create mode 100644 test/locale-mbwc/tst_iswctype.c create mode 100644 test/locale-mbwc/tst_iswdigit.c create mode 100644 test/locale-mbwc/tst_iswgraph.c create mode 100644 test/locale-mbwc/tst_iswlower.c create mode 100644 test/locale-mbwc/tst_iswprint.c create mode 100644 test/locale-mbwc/tst_iswpunct.c create mode 100644 test/locale-mbwc/tst_iswspace.c create mode 100644 test/locale-mbwc/tst_iswupper.c create mode 100644 test/locale-mbwc/tst_iswxdigit.c create mode 100644 test/locale-mbwc/tst_mblen.c create mode 100644 test/locale-mbwc/tst_mbrlen.c create mode 100644 test/locale-mbwc/tst_mbrtowc.c create mode 100644 test/locale-mbwc/tst_mbsrtowcs.c create mode 100644 test/locale-mbwc/tst_mbstowcs.c create mode 100644 test/locale-mbwc/tst_mbtowc.c create mode 100644 test/locale-mbwc/tst_strcoll.c create mode 100644 test/locale-mbwc/tst_strfmon.c create mode 100644 test/locale-mbwc/tst_strxfrm.c create mode 100644 test/locale-mbwc/tst_swscanf.c create mode 100644 test/locale-mbwc/tst_towctrans.c create mode 100644 test/locale-mbwc/tst_towlower.c create mode 100644 test/locale-mbwc/tst_towupper.c create mode 100644 test/locale-mbwc/tst_types.h create mode 100644 test/locale-mbwc/tst_wcrtomb.c create mode 100644 test/locale-mbwc/tst_wcscat.c create mode 100644 test/locale-mbwc/tst_wcschr.c create mode 100644 test/locale-mbwc/tst_wcscmp.c create mode 100644 test/locale-mbwc/tst_wcscoll.c create mode 100644 test/locale-mbwc/tst_wcscpy.c create mode 100644 test/locale-mbwc/tst_wcscspn.c create mode 100644 test/locale-mbwc/tst_wcslen.c create mode 100644 test/locale-mbwc/tst_wcsncat.c create mode 100644 test/locale-mbwc/tst_wcsncmp.c create mode 100644 test/locale-mbwc/tst_wcsncpy.c create mode 100644 test/locale-mbwc/tst_wcspbrk.c create mode 100644 test/locale-mbwc/tst_wcsrtombs.c create mode 100644 test/locale-mbwc/tst_wcsspn.c create mode 100644 test/locale-mbwc/tst_wcsstr.c create mode 100644 test/locale-mbwc/tst_wcstod.c create mode 100644 test/locale-mbwc/tst_wcstok.c create mode 100644 test/locale-mbwc/tst_wcstombs.c create mode 100644 test/locale-mbwc/tst_wcswidth.c create mode 100644 test/locale-mbwc/tst_wcsxfrm.c create mode 100644 test/locale-mbwc/tst_wctob.c create mode 100644 test/locale-mbwc/tst_wctomb.c create mode 100644 test/locale-mbwc/tst_wctrans.c create mode 100644 test/locale-mbwc/tst_wctype.c create mode 100644 test/locale-mbwc/tst_wcwidth.c create mode 100644 test/locale/Makefile create mode 100644 test/locale/bug-iconv-trans.c create mode 100644 test/locale/bug-usesetlocale.c create mode 100644 test/locale/collate-test.c create mode 100644 test/locale/dump-ctype.c create mode 100644 test/locale/gen-unicode-ctype.c create mode 100644 test/locale/show-ucs-data.c create mode 100644 test/locale/tst-C-locale.c create mode 100644 test/locale/tst-ctype-de_DE.ISO-8859-1.in create mode 100644 test/locale/tst-ctype.c create mode 100644 test/locale/tst-digits.c create mode 100644 test/locale/tst-fmon.c create mode 100644 test/locale/tst-langinfo.c create mode 100644 test/locale/tst-langinfo.input create mode 100644 test/locale/tst-leaks.c create mode 100644 test/locale/tst-mbswcs1.c create mode 100644 test/locale/tst-mbswcs2.c create mode 100644 test/locale/tst-mbswcs3.c create mode 100644 test/locale/tst-mbswcs4.c create mode 100644 test/locale/tst-mbswcs5.c create mode 100644 test/locale/tst-mbswcs6.c create mode 100644 test/locale/tst-numeric.c create mode 100644 test/locale/tst-rpmatch.c create mode 100644 test/locale/tst-setlocale.c create mode 100644 test/locale/tst-sscanf.c create mode 100644 test/locale/tst-strfmon1.c create mode 100644 test/locale/tst-trans.c create mode 100644 test/locale/tst-wctype.c create mode 100644 test/locale/tst-xlocale1.c create mode 100644 test/locale/tst-xlocale2.c create mode 100644 test/locale/tst_nl_langinfo.c create mode 100644 test/locale/xfrm-test.c create mode 100644 test/malloc/Makefile create mode 100644 test/malloc/malloc-standard-alignment.c create mode 100644 test/malloc/malloc.c create mode 100644 test/malloc/mallocbug.c create mode 100644 test/malloc/realloc-can-shrink.c create mode 100644 test/malloc/realloc0.c create mode 100644 test/malloc/testmalloc.c create mode 100644 test/malloc/time_malloc.c create mode 100644 test/malloc/tst-calloc.c create mode 100644 test/malloc/tst-malloc.c create mode 100644 test/malloc/tst-mallocfork.c create mode 100644 test/malloc/tst-mcheck.c create mode 100644 test/malloc/tst-obstack.c create mode 100644 test/malloc/tst-valloc.c create mode 100644 test/math/Makefile create mode 100644 test/math/basic-test.c create mode 100644 test/math/fenv.h create mode 100755 test/math/gen-libm-test.pl create mode 100644 test/math/libm-test.inc create mode 100644 test/math/rint.c create mode 100644 test/math/test-double.c create mode 100644 test/math/test-float.c create mode 100644 test/math/test-fpucw.c create mode 100644 test/math/test-idouble.c create mode 100644 test/math/test-ifloat.c create mode 100644 test/math/test-ildoubl.c create mode 100644 test/math/test-ldouble.c create mode 100644 test/math/tst-definitions.c create mode 100644 test/misc/Makefile create mode 100644 test/misc/bug-glob1.c create mode 100644 test/misc/bug-glob2.c create mode 100644 test/misc/bug-readdir1.c create mode 100644 test/misc/dirent.c create mode 100644 test/misc/dirent64.c create mode 100644 test/misc/fdopen.c create mode 100644 test/misc/opendir-tst1.c create mode 100644 test/misc/outb.c create mode 100644 test/misc/popen.c create mode 100644 test/misc/seek.c create mode 100644 test/misc/sem.c create mode 100644 test/misc/stdarg.c create mode 100644 test/misc/tst-fnmatch.c create mode 100644 test/misc/tst-fnmatch.input create mode 100644 test/misc/tst-gnuglob.c create mode 100644 test/misc/tst-scandir.c create mode 100644 test/misc/tst-seekdir.c create mode 100644 test/misc/tst-utmp.c create mode 100644 test/mmap/Makefile create mode 100644 test/mmap/mmap.c create mode 100644 test/mmap/mmap2.c create mode 100644 test/mmap/mmap64.c create mode 100644 test/pthread/Makefile create mode 100644 test/pthread/cancellation-points.c create mode 100644 test/pthread/ex1.c create mode 100644 test/pthread/ex2.c create mode 100644 test/pthread/ex3.c create mode 100644 test/pthread/ex4.c create mode 100644 test/pthread/ex5.c create mode 100644 test/pthread/ex6.c create mode 100644 test/pthread/ex7.c create mode 100644 test/pthread/tst-too-many-cleanups.c create mode 100644 test/pwd_grp/.indent.pro create mode 100644 test/pwd_grp/Makefile create mode 100644 test/pwd_grp/getgroups.c create mode 100644 test/pwd_grp/grcat.c create mode 100644 test/pwd_grp/pwcat.c create mode 100644 test/pwd_grp/test_grp.c create mode 100644 test/pwd_grp/test_pwd.c create mode 100644 test/regex/.regex.ChangeLog.14 create mode 100644 test/regex/LICENSE create mode 100644 test/regex/Makefile create mode 100644 test/regex/basic.dat create mode 100644 test/regex/categorize.dat create mode 100644 test/regex/forcedassoc.dat create mode 100644 test/regex/interpretation.dat create mode 100644 test/regex/leftassoc.dat create mode 100644 test/regex/nullsubexpr.dat create mode 100644 test/regex/repetition.dat create mode 100644 test/regex/rightassoc.dat create mode 100644 test/regex/testregex.c create mode 100644 test/regex/testregexc.c create mode 100644 test/regex/testregexf.c create mode 100644 test/regex/testregexi.c create mode 100644 test/regex/testregexl.c create mode 100644 test/regex/testregexn.c create mode 100644 test/regex/testregexp.c create mode 100644 test/regex/testregexr.c create mode 100644 test/regex/tst-regex2.c create mode 100644 test/regex/tst-regexloc.c create mode 100644 test/rpc/Makefile create mode 100644 test/rpc/getrpcent.c create mode 100644 test/rpc/getrpcent_r.c create mode 100644 test/setjmp/Makefile create mode 100644 test/setjmp/bug269-setjmp.c create mode 100644 test/setjmp/jmpbug.c create mode 100644 test/setjmp/sigjmpbug.c create mode 100644 test/setjmp/tst-setjmp.c create mode 100644 test/setjmp/tst-vfork-longjmp.c create mode 100644 test/signal/.indent.pro create mode 100644 test/signal/Makefile create mode 100644 test/signal/sigchld.c create mode 100644 test/signal/signal.c create mode 100644 test/signal/tst-raise.c create mode 100644 test/signal/tst-signal.c create mode 100644 test/signal/tst-sigset.c create mode 100644 test/signal/tst-sigsimple.c create mode 100644 test/silly/Makefile create mode 100644 test/silly/hello.c create mode 100644 test/silly/tiny.c create mode 100644 test/stat/Makefile create mode 100644 test/stat/memcmp-stat.c create mode 100644 test/stat/stat.c create mode 100644 test/stat/stat64.c create mode 100644 test/stdio/64bit.c create mode 100644 test/stdio/Makefile create mode 100644 test/stdio/fclose-loop.c create mode 100644 test/stdlib/Makefile create mode 100644 test/stdlib/ptytest.c create mode 100644 test/stdlib/qsort.c create mode 100644 test/stdlib/test-canon.c create mode 100644 test/stdlib/testatexit.c create mode 100644 test/stdlib/teston_exit.c create mode 100644 test/stdlib/teststrtol.c create mode 100644 test/string/Makefile create mode 100644 test/string/bug-strcoll1.c create mode 100644 test/string/bug-strncat1.c create mode 100644 test/string/bug-strpbrk1.c create mode 100644 test/string/bug-strspn1.c create mode 100644 test/string/stratcliff.c create mode 100644 test/string/test-ffs.c create mode 100644 test/string/testcopy.c create mode 100644 test/string/tester.c create mode 100644 test/string/tst-bswap.c create mode 100644 test/string/tst-inlcall.c create mode 100644 test/string/tst-strlen.c create mode 100644 test/string/tst-strtok.c create mode 100644 test/string/tst-strxfrm.c create mode 100644 test/termios/Makefile create mode 100644 test/termios/termios.c create mode 100644 test/test-skeleton.c create mode 100644 test/testsuite.h create mode 100644 test/time/Makefile create mode 100644 test/time/bug-asctime.c create mode 100644 test/time/bug-asctime_r.c create mode 100644 test/time/clocktest.c create mode 100644 test/time/test_time.c create mode 100644 test/time/time.c create mode 100644 test/time/tst-ftime_l.c create mode 100644 test/time/tst-mktime.c create mode 100644 test/time/tst-mktime2.c create mode 100644 test/time/tst-mktime3.c create mode 100644 test/time/tst-posixtz.c create mode 100644 test/time/tst-strftime.c create mode 100644 test/time/tst-strptime.c create mode 100644 test/time/tst-strptime2.c create mode 100644 test/time/tst-timezone.c create mode 100644 test/time/tst_wcsftime.c create mode 100644 test/unistd/Makefile create mode 100644 test/unistd/clone.c create mode 100644 test/unistd/clone_cruft.h create mode 100644 test/unistd/errno.c create mode 100644 test/unistd/exec-null.c create mode 100644 test/unistd/fork.c create mode 100644 test/unistd/getcwd.c create mode 100644 test/unistd/getopt.c create mode 100644 test/unistd/getopt_long.c create mode 100644 test/unistd/tst-preadwrite.c create mode 100644 test/unistd/tst-preadwrite64.c create mode 100644 test/unistd/tstgetopt.c create mode 100644 test/unistd/vfork.c create mode 100644 utils/Makefile create mode 100644 utils/Makefile.in create mode 100644 utils/bswap.h create mode 100644 utils/chroot_realpath.c create mode 100644 utils/ldconfig.c create mode 100644 utils/ldd.c create mode 100644 utils/readelf.c create mode 100644 utils/readsoname2.c diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..8add30a --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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. + + + Copyright (C) + + 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 + +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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/COPYING.LIB.boilerplate b/COPYING.LIB.boilerplate new file mode 100644 index 0000000..82f597c --- /dev/null +++ b/COPYING.LIB.boilerplate @@ -0,0 +1 @@ +Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..52fd3ed --- /dev/null +++ b/Changelog @@ -0,0 +1,791 @@ +0.9.27 12 January 2005 + + This has been a long time in the making... Release highlights: + o New stdio implementation + o New optimized string functions + o Major improvements to the shared lib loader + o Shared libraries work properly on powerpc + o Debugging works on mips + o New architectures: frv, nios, nios2, bfin + o Linux 2.6.x kernel support + o Lots and lots of bug fixes + + This release is NOT binary compatible with uClibc 0.9.26 or any earlier + release, so be prepared to recompile your software if you are still using + an old version of uClibc. + + -Erik + + + +0.9.26 3 January 2004 + + This simply adds a fix for a pthread bug that was noticed a few hours + after the previous release. Otherwise identical to 0.9.25. + + This release remains binary compatible with uClibc 0.9.21-25 as long as + you take care to avoid any configuraton changes that will break things. + We _were_ planning to break binary compatibilty in this release, but + decided to hold those changes so we could push out a bugfix release. + + We _will_ break binary compatibilty in the upcoming 0.9.27 release to + implement a few things we have been postponing. That should hopefully be + the last ABI change before we freeze the ABI for the upcoming 1.0.x + stable uClibc series. + +Release highlights: + o A trivial fix for a pthread bug + o Nothing else + + -Erik + + + +0.9.25 3 January 2004 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with uClibc 0.9.21-24 as long as + you take care to avoid any configuraton changes that will break things. + We _were_ planning to break binary compatibilty in this release, but + decided to hold those changes so we could push out a bugfix release. + + We _will_ break binary compatibilty in the upcoming 0.9.26 release to + implement a few things we have been postponing. That should hopefully be + the last ABI change before we freeze the ABI for the upcoming 1.0.x + stable uClibc series. + +Release highlights: + o Fixed a ton of problems found using the LTP and NIST test suites. + The few remaining test failures are obscure corner cases, such as + a few functions that fail (correctly) with incorrect errno values. + o Fixed a longstanding pthreads bug -- amoung other things, you no + longer need to explicitly add -lpthread for perl to work. + o Added some sh optimized string functions + o Added sh64 shared library support + o The default malloc implementation has been replaced, and will + now actually free memory when told to do so. + o Both popen() and exec*() now behave themselves per SuSv3 + o Better 2.6.x kernel header support + o Added support for Position Independent Executables (PIE) on x86 + o Lots of other minor cleanups + + -Erik + + + +0.9.24 15 December 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with uClibc 0.9.21-23 as + long as you take care to avoid any configuraton changes that will + break things. + + We currently plan to break binary compatibilty in the upcoming 0.9.25 to + implement a few things we have been postponing, which will hopefully be + the last change.... + +Release highlights: + o Fixed several silly configuration problems + o Added arm optimized string functions + o Lots of minor cleanups + + -Erik + + + + + +0.9.23 13 November 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is binary compatible with uClibc 0.9.21 and 0.9.22 as + long as you take care to avoid any configuraton changes that will + break things. Enabling or disabling things like soft-float, + locale, wide wchar support, or changing cpu type are all good + examples of things that will break binary compatibility. + +Release highlights: + o Fixed several silly configuration problems that were + present in the 0.9.22 release. + o Fixed compilation problem with soft-float support on + several architectures. + o Lots of cleanup work on the powepc shared lib loader + thanks to Joakim Tjernlund. + o Updated the debian packaging for use in a standalone uClibc + system, rather than being a subordinate library under a + glibc based system. + + -Erik + + + + + +0.9.22 8 November 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is binary compatible with the 0.9.21 release + if you take care to avoid any configuraton changes that + might break things for you (i.e. enabling or disabling things + like soft-float, locale, wide wchar support, or changing cpu + type are all good examples of binary incompatible config options). + +Release highlights: + o Added e1, microblaze, and sh64 architectures. + o Much improved soft-float support + o Rewrote the passwd and group handing functions + and implemented all SuSv3 required reentrant + versions. + o Reworked and updated the Config system. You now + get to select your target architecture with the + config system. + o Fixed pthreads for mmuless m68k systems + o Added some x86 optimized string functions. + o Lots and lots of bugs fixed. + + -Erik + + + + + +0.9.21 9 September 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is not binary compatible with earlier releases. + Sorry about that. We have never promised to provide binary + compatibility until we hit version 1.0, and even then, if + you change your configuration. + +Release highlights: + o uClibc now has full ANSI/ISO C99 locale support (except + for wcsftime() and collating items in regex). + o Added support for using pre-generated locale data, making + it easy for mere mortals to use uClibc w/locale support. + o Lots of new tuning options added to trade size + for features, allowing for smaller static binaries. + o The "dlopen()'ing libraries that depend on libraries" + problem was fixed. + o A new scanf implementation. Well tested, but + brand new so watch for obscure bugs... + o Reworked and updated the Config system, adding several + nice new features which we now use. + o Lots and lots of sundry bug fixes and cleanups. + + -Erik + + + + + +0.9.20 30 June 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with 0.9.18 and 0.9.19. + + +Release highlights: + o Some ldd, profiling, and gcc wrapper updates + o Updated to support and compile with gcc 3.3 + o Several needed mips updates + o Building under cygwin should now work... + o Prevent non-PIC code getting into PIC libs + o Added mmap64 support + o mmu-less systems now get a 16k default thread stack size + which is much more sane than the old 2 MB default... + o Implemented syscall() for powerpc + o Optionally struct tm extension support + o Lots of other sundry little fixes and cleanups. + o Prevent buffer overflows in the passwd and group functions. + + -Erik + + + + + +0.9.19 3 March 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with 0.9.18 (except + for mips, but then mips was unusable in stock 0.9.18 anyways). + + +Release highlights: + Stefan Allius + o Some Makefile and warning fixes + David Airlie + o Fixed gcc wrapper handling of ctor/dtor stuff when used in + with and w/o the nostdinc and nostdlib options + Erik Andersen + o Fixed a number of system call kernel type/user type translation + problems that scrambled a handful of system calls. + o Fixup powerpc syscalls to eliminate warnings with gcc-3.2 + o Fixed several ioctl special cases for powerpc + o Checked in forgotten mips kernel_types.h changes + o Fixed mips shared library loader bug that caused segfaults + o Major update to the pthreads library. Should improve performance. + o Fixed uClibc's shared library loader so we can properly debug + applications using pthreads (must use gdb 5.3 or newer which + was compiled using uClibc). + o Made uClibc's ldd act just the glibc provided one (i.e. relying + on the shared lib loader to do the work) when it is possible to + doi so, and only rummage about the ELF headers when we have no + other choice (such as when using 'ldd' on cross compiled stuff). + Miles Bader + o header file updates for v850 architecture + o Fixed v850 crt0.S __uClibc_main argument stack space + Jeffrey Damick + o Fixed res_init() so it properly reloads /etc/resolv.conf + Vadim Lebedev + o Fixed ARM setjmp when floating point was disabled + David McCullough + o Removed debug (-g) when building crti.o and crtn.o, as + debug would mess up the build for SH4 and probably others. + o Fixed SH setjmp when floating point was enabled + + + -Erik + + + + + +0.9.18 12 February 2003 + +See Changelog.full for the complete list of who did what. + +Note: + + Once again, this release is _NOT_ binary compatible with earlier + releases. I _think this will be the last time (with the possible + exception of some future changes to our locale support...) + + +Release highlights: + Stefan Allius + o fixed a compile problem when large file support was disabled + o fixed dlib_pic.o to compile with proper flags + o fixed a shared lib loader compile warning + o Made adding libgcc functions to uClibc optional + Erik Andersen + o Fixed scandir64 to not free the wrong pieces of memory + which caused segfaults + o Fixed mismatches between kernel and libc dirent structures + o Fixed mismatches between the size of uClibc's struct dirent + and struct dirent64 so that when _FILE_OFFSET_BITS=64 we + do not lose part of the filename + o Fixed getdents64.c so the build will not break when compiling + vs a 2.0.x Linux kernel when UCLIBC_HAS_LFS is enabled + o Create stub crti.o and crtn.o files when UCLIBC_CTOR_DTOR is disabled + o Fixed licenses for a few files that erroneously were listed as GPL + but were really LGPL after discussing with authors + o sigaction for x86 had an extra and unwanted sigaction syscall + o Fixed debugging of arm binaries by adding a .note.ABI-tag section + Miles Bader + o header file updates for v850 architecture + o Fixed v850 clone syscall + Christian Krause + o Fixed pthread_cond_timedwait to properly uses rt singals + when available + Christophe Massiot + o Added mips _flush_cache syscall + David McCullough + o Added m68k brk syscall + Marshall M. Midden + o Fixed pipe implementation for mips + + + -Erik + + + + + +0.9.17 25 January 2003 + +See Changelog.full for the complete list of who did what. + +Note: + + I have always reserved the right to make binary incompatible changes as + needed prior to the "1.0" release. This release is a good example of + that. A few bugs turned up that needed to be fixed and the only good way + to fix them was to change some fundamental data structure sizes. So I did + just that. As a result, this release is _NOT_ binary compatible with + earlier releases -- you will need to recompile your applications. + + +Release highlights: + Stefan Allius + o fixed a number of shared library loader bugs + o setjmp, longjmp, clone, and vfork cleanups for the SH architecture + o Don't build the config system with ncurses unless asked to + Tobias Anderberg + o cris architecture updates + Erik Andersen + o Changed 'struct stat' and 'struct stat64' so they use types that + are consistant with use elsewhere in the library. Without this, + subtle bugs would occur due to comparing signed and unsigned + types (for example, GNU tar wouldn't work) + o Fixed dlopen so it works with staticly linked apps + o Fixed sigaction on arm architecture so sa_restorer works properly + o Fixed sigaction on x86 architecture for (fixed debugging threads) + o Fixed a wide char related segfault in the regular expression code + o Powerpc pread and pwrite are now implemented correctly + o Powerpc syscall mechanism re-implemented + o Sparc architecture and syscall mechanism fixed up so things compile + o usershell reimplemented + o Fixed global destructors for staticly linked applications + o Added dynamic atexit support (needed for full C++ ctor/dtor support) + o The ldd utility now acts more like the GNU utility + o Added a stub libnsl library to make stupid configure scripts bahave + o Always build crt1.o as well as crt0.o to minimize the need to mess + with the compiler + o Rewrote powerpc crt0.S to properly handle ctors/dtors + o Removed unimplemented and legacy stuff from our header files to + make configure behave better + o Made the lib loader also support libs in /usr/X11R6/lib by default + o Config system updates + o networking function updates + o Large file support updates + o Lots of other little bug fixes and cleanups + Nick Fedchik + o Support ether_aton + Nathan Field + o Fixed pthread_mutex_lock and pthread_mutex_unlock so they + actually work as advertised on mips + o Fixed several nasty pthread bugs fixing debugging + Brett Hunt + o Fixed potential segfaults during 'make menuconfig' + Jay Kulpinski + o Fixed a subtle problem in the DNS resolver that prevented + uncompressed DNS lookup responses from working + David McCullough + o Fixed pclose error handling + David Meggy + o fixed the problem where arm binaries would crash on start + that Erik stupidly caused right before the last release. + Manuel Novoa III + o Major locale support update! + o Allow people to use pregenerated locale data instead of generating + approx 40Mb of glibc locales to get the 300+ locales currently + supported. + o locale dependent collation support + o Fixed locale support tools to work when cross-compiling + o Added the *wprintf functions + o Added the wcsto{inttype} functions + o Added iconv() and a mini iconv utility + o Added hsearch and hsearch_r + o Fixed a silly bug allowing wprintf %s to work correctly. + o Fixed fdopen when used with "a" (append). + o Fixed stdio file position handing to be sure fell() always + gives correct results + Luc Van Oostenryck + o Fixed a buffer overflow in getlogin_r + Yoshinori Sato + o Hitachi h8300 architecture update + Ronald Wahl + o Powerpc shared library relocation fixes + + -Erik + + + +0.9.16 8 November 2002 + +See Changelog.full for the complete list of who did what. + +Release highlights: + o CRIS architecture and shared library support from Tobias Anderberg + o New uClibc configuration system + o shared library global constructors and destructors initialization + ordering fixed by Stefan Allius + o More SuperH architecture fixes from Stefan Allius + o uClibc now compiles with newer versions of gcc (i.e. RedHat 8.0) + o uClibc no longer requires perl to compile + o mips dlopen was fixed by Steven J. Hill + o pty and tty handling fixes + o Manuel Novoa added support for a new /etc/TZ file for globally + setting the system timezone. + o Manuel also fixed up a number of remaining wide char issues. + o Lots of other little bug fixes and cleanups + + -Erik + + + +0.9.15 27 August 2002 + +This is a minor bugfix release. + +See Changelog.full for the complete list of who did what. +Release highlights: + o Eliminated the HAS_LONG_LONG option. gcc always supports + long long, and the option never excluded all long long anyways. + o ctype.h no longer allows multiple argument evaluation in + compliance with ANSI/ISO C99 + o Obscure printf fixes -- one involving %o and one involving %f. + o Bugfixes for locking and reentrance in password/group functions + o Directly use kernel types for most items, eliminating needless + translation and fixing several bugs. + o Directly use kernel struct stat -- no more translating + o More superH (sh) architecture merging from Stefan Allius + o Errno values and strerror are now correct on alpha, sparc, and mips + o Fixed an obscure bug with fclose when custom streams are enabled. + o Lots of other little bug fixes and cleanups + + -Erik + + + +0.9.14 12 August 2002 + +This is a minor bugfix release. + +See Changelog.full for the complete list of who did what. +Release highlights: + o Fix a compile error when RPC and Pthread support + were both enabled. + o Eliminate duplicate define warnings in wstring.c. + o Fix potentially broken preprocessor comparisons. + o Erik was an idiot and broke thread locking in exit(), + atexit() and friends. Fix that. + o Fix the gcc wrapper to use crtbeginS.o and crtendS.o when + compiling PIC code (crtbegin.o and crtend.o) otherwise. + + -Erik + + + + +0.9.13 9 August 2002 + +Security Fixes + o There was an off-by-one buffer overflow in the group + handling code, fix thanks to Joseph Chiu. + o There was an integer overflow bug in calloc, per + http://online.securityfocus.com/bid/5398 + o There was an integer overflow bug in the xdr_array + RPC code, per http://online.securityfocus.com/bid/5356 + +See Changelog.full for the complete list of who did what. +Release highlights: + o Add full shared library support for Hitachi SuperH (sh) + thanks to Stefan Allius and Edie C. Dost + o Lots of reentrance cleanups (we should now be fully + reentrant when compiled with pthread support). + o Miles Bader implemented a new mmap based malloc which is much + smarter than the old "malloc-simple", and actually works, unlike + the old "malloc". This is now the default for mmu-less systems + and should greatly help reduce memory fragmentation and wastage. + o Reworked syscall handling for i386 and ARM, smaller and cleaner. + o Support for the syscall() function on i386 and ARM + o The uClibc g++ wrapper now automagically adds the proper include + search path and and libraries. + o Lots of shared library loader updates + o dlopen'd shred libraries not properly run destructors + when ctor/dtor support is enabled + o pread/pwrite/pread64/pwrite64 now all work as expected + o Lots and lots of other bug fixes and cleanups. + + -Erik + + + + +0.9.12 20 June 2002 + +See Changelog.full for the complete list of who did what. +Release highlights: + o Add full shared library support for mips (big and little + endian), thanks to a lot of hard work from Steven J. Hill + o i960 architecture support, thanks to Martin Proulx + o An initial alpha port (works, but needs some cleanup) + o Fixes shared library support for powerpc + o Fixes for mmu-less systems + o Much improved thread locking and reentrance. + o More gcc wrapper updates. XFree86 really does link + this time around. It still didn't last time. + o Libcrypt now passes conformance tests + o Nearly complete locale supporti thanks to a lot + of hard work by Manuel Novoa III. This stuff is + _way_ smaller than glibc's + o Completely new time handling functions also by Manuel + o Lots of other bug fixes and cleanups. + + -Erik + + + + +Erik Andersen: +0.9.11 10 April 2002 + +Release highlights: + o Lots of bug fixes + o Much better large file support + o Several gcc wrapper bug fixes, so things like iproute2 and + XFree86 should now link properly. + o Fixes a stdio thread locking bug that could cause random + deadlocks on s*printf calls when threading was enabled. + +Erik Andersen: + o Added a generic implementation of truncate64.c and ftruncate64.c + o Added missing creat64, glob64, mkstemp64, getrlimit64, setrlimit64 + o Removed internal erroneous use of __USE_FILE_OFFSET64 + o Made libpthread compile on sparc and powerpc + o Made libpthread soname and symlinks match the other libraries. + o Added finite() to the C89 math lib, since some math functions use it. + o Added missing function pointer to error.c (some apps wanted it) + o Fixed initfini build for arches where gcc tries to be sneaky + o Fixed m68k/bits/setjmp.h which I has broken in the last release. + o Fixed a buffer overflow in the dynamic library loader + o Fixed a stdio thread locking bug that could cause random + deadlocks on s*printf calls when threading was enabled. + o Implemented sqrtf(), needed for libstdc++ on arm +Miles Bader: + o Make clean fixes to not blindly wipe all symlinks + o Re-enabled clnt_perror() + o Re-implemented swab() +Dwayne Fontenot: + o Many updates to the uClibc Working Application List +Steven J. Hill: + o Many updates to the mips dynamic loader. Not yet working but + getting very close now. + o Fixed locking bug in getttyent() + o Support libpthread on mips +Richard June: + o Fixed several bugs in utmp code (pututline was only writing the + first sizeof-a-pointer bytes to the utmpfile). + o setutent() was only opening utmp readonly. +m4@brecis.COM: + o Fixed a silly typing problem with the getuid syscall. +Manuel Novoa III: + o Fixed stdio FILE read/write auto-transition bugs. + o Better stdio errno handling + o Changed setvbuf() to more closely match glibc's behavior + o Fixed getpass() to not echo passwords to the console + o Fixed locale ISblank flag. + o Fixed an arg promotion handling bug in _do_one_spec for %c reported + by Ilguiz Latypov. +Kensuke Otake: + o Implemented swab() +Yoshinori Sato: + o Fixed h8300 architecture support for pthreads and changes to + the include files +David Schleef: + o Made powerpc assembly code PIC-compatible + o Removed powerpc R_PPC_REL24 handling, since it was deceptively useless. +John Traill: + o Several types on powerpc, such as dev_t, are different than on other + architectures. John spotted this, which fixed a _ton_ of problems since + anything calling stat() was previously broken. +Jim Treadway: + o Eliminated use of alarm() from the DNS resolver by converting + it to use select instead (much cleaner). + + + + + + + + +0.9.10 21 March 2002 + +Major new features: + o pthreads support (derived from glibc 2.1.3's linuxthreads library) + by Stefan Soucek and Erik Andersen + o pthreads support for MMU-less systems, by Stefan Soucek + o Complete rewrite of all stdio functions for standards compliance, + small size, pthreads support, wide/narrow stream support, large + file support, unbuffered support, etc, etc by Manuel Novoa III + o gcc wrapper reworked by Erik Andersen. Now operated correctly in + all known cases, and now wraps g++ as well for C++ support. + o constructor/destructor support, for C++ by Erik Andersen. + o Eliminated duplicate include/bits header files, by Erik Andersen. + Now all common include/bits headers are grouped together. + + +Erik Andersen: + o Lots of changes and improvements to the shared library loader + o Cleaned up a piles of bugs + o Fixed a segfault when scandir was called on empty directories. + o Several syscalls added: pread/pwrite + o Makefile/build system cleanups + o Sighandling fixes + o pthreads support (with Stefan Soucek) + o Added ldexp to the C89 math library, per POSIX + o fclose() EINTR handling is now correct per IEEE Std 1003.1-2001 + o Support isblank() + o Reworked libcrypt to avoid leaking private symbols into the namespace + o Added strtof(), strtold(), updwtmp(), strptime() + o Fix ldso build for older arm cross compilers +Miles Bader: + o atexit cleanups + o fixed gcc wrapper handling of -M* options + o Fixed truncate64/ftruncate64 to restrict them to 64-bit systems, + since we can't be sure that the _syscall macros can cope with 64 + bit args on 32 bit arches. + o Large File support on the v850 + o Fixed v850 headers after Erik messed them up + o Eliminate include/features.h namespace pollution +M. R. Brown: + o Fixed pthread support for SH, and fixed SH vfork as well + o Fixed SH headers after Erik messed them up +Geoffrey Espin: + o Mips architecture cleanups. Now works perfectly + with busybox, vi, ash, etc... + o Merged in the random number support (rand, srand, etc) from glibc. +Thomas Fritzsche: + o Fixes DNS resolver bug from 0.9.9 +Steven J. Hill: + o Fixed build to support both mips and mipsel + o Beginnings of a mips ldso port +Andrew Ip: + o Support for gnu error() functions +David McCullough: + o Coldfire platform updates: clone, setjmp + o Fixed simple malloc to work on systems with an MMU +Manuel Novoa III: + o Rewrote all stdio functions for standards compliance, small size, + pthreads support, wide/narrow stream support, large file support, + unbuffered support, etc, etc, etc. + o Rewrote the various string to int functions to be smaller, more + standards compilant, and reduce dependance on libgcc.a. +Yoshinori Sato: + o ptrace for the Hitachi h8300 fix +David Schleef: + o Debian packaging updates + o Check for proper 16-byte aliged stack pointer on powerpc +Stefan Soucek: + o pthreads support for MMU-less systems + o pthreads support (with Erik Andersen) +Brian Stafford: + o Rewrote strcasecmp() per SUSv2. +Bart Visscher: + o Added missing IPV6 support and reentrant networking function + additions so iptables now runs with IPV6 support. + + + + + + +0.9.9 February 4, 2002 + +Erik Andersen: + o A bunch of doc updates. Major update to the working + apps list. + o Added a configurator script (extra/Configs/uClibc_config_fix.pl) + which can simplify configuring uClibc. + o Fixed setjmp/longjmp on x86,arm,powerpc,mips,and sparc. + Hitting ^C in ash kills client apps now, not ash. + o Reworked signal handling code so it now passes POSIX + conformance tests. + o Fixed sleep and usleep to work correctly when + interrupted by signals. + o Made getopt behave the same when staticly linking + as when dynamicly linking. It was using different + implementations depending on how apps were linked. + o Added missing inttypes.h header file + o Eliminate all C++ style comments from header files + o Support statvfs and statfs + o Support getmntent_r + o Scandir and scandir64 were calling malloc without + checking for ENOMEM + o Fixed stpcpy function declaration + o Many large file support improvements. + o Fixed fcntl to work when DOLFS is enabled + o Fixed termios code to do the Right Thing(tm) + o Allow regex to be excluded at compile time + o Implemented mempcpy + o Build ldd and readelf for the target system and for the + host system + o Fix several cases where get-needed-libgcc-objects.sh + could fail, breaking the shared uClibc library. + o Include all shared library loader objects into a + single C file, thereby reducing its size further. + o Reworked the shared library linking process to be more + flexible so that gcc and ld can more easily be built to + target uClibc library. + o Better error checking in the Makefiles. Be more pedantic + about tar, chmod, etc to avoid system dependent failures. + o We can now autodetect the target architecture + o Hide references to wchar_t so GNU autoconf + configure scripts won't get confused and try to + enable wide char support. + o Fixed stdio.h so apps can use varargs.h if they want to. + o Added brk/sbrk support for ARM, powerpc, mips, and sparc + and set them to default to the much faster brk using malloc + o Added missing syscalls: get_kernel_syms, fcntl64, + fdatasync, sched_setparam, sched_getparam, + sched_setscheduler, sched_getscheduler, + sched_get_priority_max, sched_get_priority_min, + sched_rr_get_interval, sigaltstack, sendfile, + pivot_root, sigsuspend, setfsuid, and setfsgid + o Force DOPIC be true when HAVE_SHARED is true. + o Fixed hstrerror() + o Implemented gethostent(), sethostent(), and endhostent() + o Added arch specific support so that sparc and mips actually + compile and work +Miles Bader: + o Fixes for the v850 architecture: crt0, setjmp, + arch autodetection, etc. + o Fixed `make install' to not build ldso stuff on + non-shared-library systems. +Michael E Brown: + o Allow the gcc wrapper to support setting DEVEL_PREFIX + and BUILD_DIR at runtime (no more need to recompile). +M. R. Brown and Erik Andersen: + o Fixed the SH port so it now works. Tested and shown + working on an SH4 Dreamcast system. +Kim Heino: + o Made 'make clean' remove generated bits/syscall.h +David McCullough: + o SH architecture updates. Added brk, sbrk, + o Fixed simple malloc to work on systems with an MMU + o Taught getutent to return NULL if utmp doesn't exist. + o Added insque/remque support + o Fixed DNS resolver version number so apps won't get + confused and use the wrong API. + o Added Config selectable shadow password support +Yoshinori Sato + o Contributed support for the Hitach H8/300H architecture +Cédric Schieli: + o Add support for inet_netof, inet_lnaof, inet_makeaddr + and hstrerror. +David Schleef: + o Added libstrip, a nifty script to automagically + strip unneeded content from the uClibc shared + libraries. +Martin Sieper + o Added getw() and putw() + o Added missing header files -- lastlog.h, sgtty.h, + netipx/ipx.h, sys/perm.h +Stefan Soucek: + o Add rcmd support, i.e. rsh, rlogin, etc. + o Fix rcmd to avoid alloca, which is dangerous + on mmu-less systems +spudmonkey@racsa.co.cr: + o Eliminate a buffer overflow in the shared library loader +Brian Stafford: + o Enable support for Unix98 PTYs, and add option + to disable old style PTYs. + + diff --git a/DEDICATION.mjn3 b/DEDICATION.mjn3 new file mode 100644 index 0000000..bc26bc8 --- /dev/null +++ b/DEDICATION.mjn3 @@ -0,0 +1,22 @@ + +All of my uClibc and busybox work is dedicated to Toni, my love who +passed away on Feb. 12, 2003. + +I would ask that anyone benefiting from this work, especially those +using it in commercial products, consider making a donation in her +memory to our local non-profit hospice organization that did so much +for us in her last few months. + + In memory of Toni W. Hagan + + Hospice of Acadiana, Inc. + 2600 Johnston St., Suite 200 + Lafayette, LA 70503-3240 + + Phone (337) 232-1234 or 1-800-738-2226 + Fax (337) 232-1297 + + http://www.hospiceacadiana.com/ + + +Manuel Novoa III diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..79cde84 --- /dev/null +++ b/INSTALL @@ -0,0 +1,80 @@ +SOFTWARE REQUIREMENTS + + Compiling uClibc requires Linux kernel header files. uClibc will + be compiled to match the interfaces available in the provided + version of the Linux kernel headers. Linux kernel version 2.0, + version 2.2, version 2.4 and version 2.6 are known to work. Other + kernel versions may work but haven't been tested. Its also helpful + to have a working version of GNU binutils, and GNU gcc -- using + excessively old versions of these packages can cause very strange + errors that are difficult to find and fix. + + +CONFIGURING uClibc: + + - Users must have a valid configuration file to compile uClibc. Do not + skip this step. New configuration options are added in each + release, and odd configuration options are sometimes removed. + To configure uClibc, you can run: + + make menuconfig + or + make config + + If you have an existing .config file, you can update this file + using the + + make oldconfig + + command, which will only ask you about new configuration options. + + Available configuration commands are: + "make config" Text based configuration, no menus or colors. + "make menuconfig" Text based color menus, radiolists & dialogs. + "make oldconfig" Default all questions based on the contents of + your existing ./.config file. + "make defconfig" Use defaults for all options. + "make randconfig" Use random values for all options. + "make allyesconfig" Set all values to "yes" for all options. + "make allnoconfig" Set all values to "no" for all options. + + +COMPILING uClibc: + + - uClibc does not have proper dependancy checking (yet) so if you + change your uClibc configuration, you must current rebuild the + entire library, by first running + + make clean + + - Once you have a valid configuration file, just run + + make + + to compile uClibc. or if you are cross compiling, you would + instead run something like: + + make CROSS=arm-linux- + + +INSTALLING the uClibc development environment: + + - As root, if necessary, run something like: + + make PREFIX= install + + This will install the uClibc runtime and development system (i.e. + all the header files, libraries, etc) into the directories defined + within your .config file. + + +USING uClibc: + + - To compile programs with uClibc you will need a complete toolchain + (i.e. binutils, gcc, and uClibc) that was built expressly for use + with uClibc. + + - Native and cross compiling toolchains, as well as makefiles for creating + uClibc toolchains, are available from the uClibc website. You may want + to check out "buildroot", which is available from the uClibc download area, + which provides examples of how to build your own uClibc based system. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..621c3b7 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,150 @@ +Arch Maintainers List + +Note: For the hard of thinking, this list is meant to remain in alphabetical +order. If you could add yourselves to it in alphabetical order that would be +so much easier [Ed]. + +P: Person +E: Person's email address +W: Web-page with status/info +S: Status, one of the following: + + Supported: Someone is actually paid to look after this. + Maintained: Someone actually looks after it. + Patches: It has a maintainer but they don't have time to do + much other than throw the odd patch in. See below ... + Unmaintained: No current maintainer [but maybe you could take the + role as you write your new code]. + Obsolete: Old code. Something tagged obsolete generally means + it has been replaced by a better system and you + should be using that. + +---------------------------------------------------------------------- + +ALPHA +S: Unmaintained + + +ARM +N: Erik Andersen +E: andersen@codepoet.org +W: http://www.arm.linux.org.uk/ +S: Maintained + + +AVR32 +N: Hans-Christian Egtvedt +E: hans-christian.egtvedt@atmel.com +N: Haavard Skinnemoen +E: haavard.skinnemoen@atmel.com +W: http://avr32linux.org/ +S: Maintained + + +BFIN +N: Mike Frysinger +E: vapier.adi@gmail.com +W: http://blackfin.uclinux.org/ +S: Maintained + + +CRIS +P: Ricard Wanderlof +M: ricard.wanderlof@axis.com +W: http://developer.axis.com +S: Maintained + + +E1 +S: Unmaintained + + +FRV +S: Unmaintained + + +H8300 +S: Unmaintained + + +HPPA +S: Unmaintained + + +IA64 +S: Unmaintained + + +I386 +N: Erik Andersen +E: andersen@codepoet.org +S: Maintained + + +I960 +S: Unmaintained + + +M68K +S: Unmaintained + + +MICROBLAZE +S: Unmaintained + + +MIPS +N: Erik Andersen +E: andersen@codepoet.org +W: http://www.linux-mips.org +S: Maintained + + +NIOS and NIOS2 +S: Unmaintained + + +POWERPC +N: Joakim Tjernlund +E: joakim.tjernlund@lumentis.se +W: http://penguinppc.org/ +S: Maintained + + +SH and SH64 +P: Paul Mundt +E: lethal@linux-sh.org +W: http://www.linux-sh.org +S: Maintained + + +SH4 (NPTL/TLS) +P: Carmelo Amoroso +E: carmelo.amoroso@st.com +W: http://www.stlinux.com +S: Supported + + +SPARC +S: Unmaintained + +VAX +P: Jan-Benedict Glaw +E: jbglaw@lug-owl.de (personal), linux-vax@pergamentum.com (mailing list) +W: http://linux-vax.sourceforge.net/ +S: Maintained + +V850 +S: Unmaintained + + +X86_64 +S: Unmaintained + + +XTENSA +P: Chris Zankel +E: chris@zankel.net +W: http://linux-xtensa.org/ +S: Maintained + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..793ca78 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=./ +top_builddir=./ +#include $(top_builddir)Rules.mak +#all: libs +include Makefile.in +include $(top_srcdir)Makerules +include $(top_srcdir)Makefile.help diff --git a/Makefile.help b/Makefile.help new file mode 100644 index 0000000..b8d2edc --- /dev/null +++ b/Makefile.help @@ -0,0 +1,45 @@ +# Makefile.help for uClibc +# +# Copyright (C) 2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +help: + @echo 'Cleaning:' + @echo ' clean - delete temporary object files' + @echo ' realclean - delete temporary object file, including dependencies' + @echo ' distclean - delete all non-source files (including .config)' + @echo + @echo 'Build:' + @echo ' all - libraries and generated headers' + @echo ' pregen - generate headers' + @echo + @echo 'Configuration:' + @echo ' allnoconfig - disable all symbols in .config' + @echo ' allyesconfig - enable all symbols in .config (see defconfig)' + @echo ' config - text based configurator (of last resort)' + @echo ' defconfig - set .config to arch-specific defaults' + @echo ' menuconfig - interactive curses-based configurator' + @echo ' oldconfig - resolve any unresolved symbols in .config' + @echo ' silentoldconfig - resolve any unresolved symbols in .config, silently' + @echo ' randconfig - generate a random .config' + @echo + @echo 'Installation:' + @echo ' install - install both the runtime and the headers' + @echo ' install_runtime - install the libraries' + @echo ' install_dev - install all headers and static libs' + @echo ' install_headers - install headers excluding generated ones' + @echo + @echo 'Development:' + @echo ' check - run testsuite' + @echo ' test_compile - compile testsuite binaries' + @echo ' release - create a distribution tarball' + @echo + @echo 'Environment variables:' + @echo ' - Quiet build' + @echo ' V=1 - Verbose build' + @echo ' V=2 - Very verbose build' + @echo ' CROSS= - Override CROSS_COMPILER_PREFIX from .config' + @echo ' SHELL= - Shell to use for make' + @echo ' CONFIG_SHELL= - Shell to use for menuconfig' diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..4969cbf --- /dev/null +++ b/Makefile.in @@ -0,0 +1,510 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +#-------------------------------------------------------------- +# You shouldn't need to mess with anything beyond this point... +#-------------------------------------------------------------- +clean_targets := clean realclean distclean \ + objclean-y headers_clean-y utils_clean +noconfig_targets := menuconfig config oldconfig silentoldconfig randconfig \ + defconfig allyesconfig allnoconfig \ + release dist tags help + +include $(top_builddir)Rules.mak +sub_headers := headers + +ifeq ($(HAVE_DOT_CONFIG),y) + +all: pregen libs +libs: pregen + +# In this section, we need .config +-include .config.cmd + +else # ifeq ($(HAVE_DOT_CONFIG),y) + +all: menuconfig + +headers: + @echo "Need to make a config file first, run: make menuconfig" + @false + +endif # ifeq ($(HAVE_DOT_CONFIG),y) + +include $(top_srcdir)ldso/Makefile.in +include $(top_srcdir)libcrypt/Makefile.in +include $(top_srcdir)libintl/Makefile.in +include $(top_srcdir)libm/Makefile.in +include $(top_srcdir)libnsl/Makefile.in +include $(top_srcdir)libresolv/Makefile.in +include $(top_srcdir)libutil/Makefile.in +include $(top_srcdir)libpthread/Makefile.in +include $(top_srcdir)librt/Makefile.in +include $(top_srcdir)extra/locale/Makefile.in + +# last included to catch all the objects added by others (locales/threads) +include $(top_srcdir)libc/Makefile.in + +ifeq ($(HAVE_DOT_CONFIG),y) +# If the .config changes then we have to make sure that our includes are +# updated properly. This would normally work by saying that the headers +# have uClibc_config.h as prerequisite but since we _symlink_ the headers +# and do not (?) want to rely on 'make -L' we better update them right here, +# on spot to save us from alot of hazzle. +include/bits/uClibc_config.h: extra/config/conf .config $(top_srcdir)extra/scripts/conf-header.sh | include/bits + @$(disp_gen) + $(Q)@$< -s $(top_srcdir)extra/Configs/Config.in + $(Q)$(top_srcdir)extra/scripts/conf-header.sh .config > $@ + $(Q)$(MAKE) headers-y + +# The above doesn't work for threads, though. Just using check-symlinks for now. +# XXX: FIXME: this is ugly +MAKEFLAGS += -L +include/config/linuxthreads/old.h include/config/linuxthreads/new.h: + @true + +# For the moment, we have to keep re-running this target +# because the fix includes scripts rely on pre-processers +# in order to generate the headers correctly :(. That +# means we can't use the $(HOSTCC) in order to get the +# correct output. +ifeq ($(ARCH_USE_MMU),y) +export header_extra_args = +else +export header_extra_args = -n +endif +HEADERS_BITS_COMMON := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/common/bits/*.h)) +HEADERS_BITS_ARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/*.h)) +HEADERS_BITS_SUBARCH := +ifneq ($(TARGET_SUBARCH),) +HEADERS_BITS_SUBARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(TARGET_SUBARCH)/*.h)) +endif +HEADERS_BITS_COMMON := $(filter-out $(HEADERS_BITS_ARCH) $(HEADERS_BITS_SUBARCH) $(HEADERS_BITS_PTHREAD),$(HEADERS_BITS_COMMON)) + +HEADERS_SYS_COMMON := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/common/sys/*.h)) +HEADERS_SYS_ARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/sys/*.h)) +HEADERS_SYS_COMMON := $(filter-out $(HEADERS_SYS_ARCH),$(HEADERS_SYS_COMMON)) + +ALL_HEADERS_COMMON := include/fpu_control.h include/dl-osinfo.h \ + include/hp-timing.h +ALL_HEADERS_BITS_COMMON := $(addprefix include/bits/,$(HEADERS_BITS_COMMON)) +ALL_HEADERS_BITS_ARCH := $(addprefix include/bits/,$(HEADERS_BITS_ARCH)) +ifneq ($(TARGET_SUBARCH),) +ALL_HEADERS_BITS_SUBARCH := $(addprefix include/bits/,$(HEADERS_BITS_SUBARCH)) +else +ALL_HEADERS_BITS_SUBARCH := +endif +ALL_HEADERS_SYS_COMMON := $(addprefix include/sys/,$(HEADERS_SYS_COMMON)) +ALL_HEADERS_SYS_ARCH := $(addprefix include/sys/,$(HEADERS_SYS_ARCH)) + +target-headers-sysdep := \ + $(ALL_HEADERS_COMMON) \ + $(ALL_HEADERS_BITS_COMMON) \ + $(ALL_HEADERS_BITS_ARCH) \ + $(ALL_HEADERS_BITS_SUBARCH) \ + $(ALL_HEADERS_SYS_COMMON) \ + $(ALL_HEADERS_SYS_ARCH) + +include/fpu_control.h: + @$(disp_ln) + $(Q)[ -r libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) ] && \ + $(LN) -fs ../libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) $@ || \ + $(LN) -fs ../libc/sysdeps/linux/common/$(@F) $@ + +include/dl-osinfo.h include/hp-timing.h: + $(do_ln) ../libc/sysdeps/linux/common/$(@F) $@ + +$(ALL_HEADERS_BITS_COMMON): + $(do_ln) ../../libc/sysdeps/linux/common/bits/$(@F) $@ + +$(ALL_HEADERS_BITS_ARCH): + $(do_ln) ../../libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(@F) $@ + +ifneq ($(TARGET_SUBARCH),) +$(ALL_HEADERS_BITS_SUBARCH): + $(do_ln) ../../../libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(TARGET_SUBARCH)/$(@F) $@ +endif + +ifneq ($(strip $(ALL_HEADERS_SYS_COMMON)),) +$(ALL_HEADERS_SYS_COMMON): + $(do_ln) ../../libc/sysdeps/linux/common/sys/$(@F) $@ +endif + +ifneq ($(strip $(ALL_HEADERS_SYS_ARCH)),) +$(ALL_HEADERS_SYS_ARCH): + $(do_ln) ../../libc/sysdeps/linux/$(TARGET_ARCH)/sys/$(@F) $@ +endif + +$(target-headers-sysdep): | include/bits + +sysdep_common_headers-clean: + $(RM) $(ALL_HEADERS_COMMON) +headers_clean-y += sysdep_common_headers-clean + +# The headers. Arch specific headers are specified via ARCH_HEADERS in +# libc/sysdeps/linux/$(TARGET_ARCH)/Makefile.arch which appends those via +# libc/sysdeps/linux/Makefile.commonarch to headers-y +headers-y += $(target-headers-sysdep) + +headers: include/bits/uClibc_config.h + +pregen: include/bits/sysnum.h headers + +include/bits/sysnum.h: $(top_srcdir)extra/scripts/gen_bits_syscall_h.sh + $(Q)$(INSTALL) -d $(@D) + @$(disp_gen) + $(Q)set -e; \ + cd $(top_builddir); \ + tmp=`mktemp include/bits/sysnum.h.XXXXXX 2>/dev/null`; \ + [ -z "$$tmp" ] && tmp='include/bits/sysnum.h.new'; \ + KERNEL_HEADERS="${KERNEL_HEADERS}" top_builddir=. CC="$(CC) $(CPU_CFLAGS)" $(SHELL) extra/scripts/gen_bits_syscall_h.sh > $$tmp; \ + if cmp include/bits/sysnum.h $$tmp >/dev/null 2>&1; then \ + $(RM) $$tmp; \ + else \ + mv -f $$tmp include/bits/sysnum.h; \ + fi + +$(LOCAL_INSTALL_PATH): + $(Q)$(MAKE) PREFIX=$(shell pwd)/ RUNTIME_PREFIX=./ \ + DEVEL_PREFIX=$(LOCAL_INSTALL_PATH)/usr/ \ + HOSTCC="$(HOSTCC)" \ + install_kernel_headers + $(Q)$(MAKE) PREFIX=$(shell pwd)/ RUNTIME_PREFIX=./ \ + DEVEL_PREFIX=$(LOCAL_INSTALL_PATH)/usr/ \ + HOSTCC="$(HOSTCC)" \ + install_dev + +install: install_runtime install_dev + + +RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB=$(shell $(top_srcdir)extra/scripts/relative_path.sh $(DEVEL_PREFIX)lib $(RUNTIME_PREFIX)lib) + +$(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c + $(hcompile.u) + +# Installs kernel header files (linux/*, asm/*, asm-generic/*). +install_kernel_headers: headers + top_builddir=$(top_builddir) \ + $(top_srcdir)extra/scripts/install_kernel_headers.sh include $(PREFIX)$(DEVEL_PREFIX)include + +# Installs header files. +install_headers: headers $(top_builddir)extra/scripts/unifdef + $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include + top_builddir=$(top_builddir) \ + $(top_srcdir)extra/scripts/install_headers.sh include $(PREFIX)$(DEVEL_PREFIX)include + printf '#ifndef _LIBC_INTERNAL_H\n#define _LIBC_INTERNAL_H 1\n#endif\n' > \ + $(PREFIX)$(DEVEL_PREFIX)include/libc-internal.h + echo '/* Dont use _syscall#() macros; use the syscall() function */' > \ + $(PREFIX)$(DEVEL_PREFIX)include/bits/syscalls.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/dl-osinfo.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/_lfs_64.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/uClibc_uintmaxtostr.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/kernel_sigaction.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/kernel_stat.h +ifneq ($(UCLIBC_HAS_FLOATS),y) + # Remove floating point related headers since float support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/complex.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/fpu_control.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ieee754.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/math.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/tgmath.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/uClibc_fpmax.h +endif +ifneq ($(UCLIBC_HAS_FENV),y) + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/fenv.h \ + $(PREFIX)$(DEVEL_PREFIX)include/bits/fenv.h \ + $(PREFIX)$(DEVEL_PREFIX)include/bits/fenvinline.h +endif +ifneq ($(UCLIBC_HAS_WCHAR),y) + # Remove wide char headers since wide char support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wctype.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wchar.h +endif +ifneq ($(UCLIBC_HAS_LOCALE),y) + # Remove iconv header since locale support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/iconv.h +endif +ifneq ($(UCLIBC_HAS_GLIBC_CUSTOM_PRINTF),y) + # Remove printf header since custom print specifier support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/printf.h +endif +ifneq ($(UCLIBC_HAS_XLOCALE),y) + # Remove xlocale header since extended locale support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/xlocale.h +endif +ifneq ($(UCLIBC_HAS_GETTEXT_AWARENESS),y) + # Remove libintl header since gettext support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/libintl.h +endif +ifneq ($(UCLIBC_HAS_REGEX),y) + # Remove regex headers since regex support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/regex.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/regexp.h +endif +ifneq ($(UCLIBC_HAS_WORDEXP),y) + # Remove wordexp header since wordexp support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/wordexp.h +endif +ifneq ($(UCLIBC_HAS_FTW),y) + # Remove ftw header since ftw support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ftw.h +endif +ifneq ($(UCLIBC_HAS_GLOB),y) + # Remove glob header since glob support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/glob.h +endif +ifneq ($(UCLIBC_HAS_GNU_GETOPT),y) +ifneq ($(UCLIBC_HAS_GETOPT_LONG),y) + # Remove getopt header since gnu getopt support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/getopt.h +endif +endif +ifneq ($(UCLIBC_HAS_SHADOW),y) + # Remove shadow header since shadow password support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/shadow.h +endif +ifneq ($(PTHREADS_DEBUG_SUPPORT),y) + # Remove thread_db header since thread debug support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/thread_db.h +endif +ifneq ($(UCLIBC_HAS_THREADS),y) + # Remove pthread headers since thread support is disabled. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/*thread*.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/semaphore.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/*thread*.h +endif +ifneq ($(HAVE_SHARED),y) + # Remove dlfcn header if we don't have shared libraries. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/dlfcn.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/dlfcn.h +endif +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) + # Remove this as it is only used internally. + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/tls.h +endif +ifneq ($(UCLIBC_HAS_GNU_ERROR),y) + # Remove error.h upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/error.h +endif +ifneq ($(UCLIBC_HAS_BSD_ERR),y) + # Remove err.h upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/err.h +endif +ifneq ($(UCLIBC_SUSV3_LEGACY),y) + # Remove timeb.h since the LEGACY ftime() was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/timeb.h +endif +ifneq ($(UCLIBC_HAS_EPOLL),y) + # Remove epoll.h since epoll_*() were disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/epoll.h +endif +ifneq ($(UCLIBC_HAS_XATTR),y) + # Remove xattr.h since extended attributes were disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/xattr.h +endif +ifneq ($(UCLIBC_HAS_PTY),y) + # Remove pty.h since PTY support was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/pty.h +endif +ifneq ($(UCLIBC_LINUX_SPECIFIC),y) + # Remove linux-specific headers as requested + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/inotify.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/perm.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/personality.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/signalfd.h +endif +ifneq ($(UCLIBC_SV4_DEPRECATED),y) + # Remove ustat.h since deprecated SV4 support was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ustat.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/ustat.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/ustat.h +endif +ifeq ($(UCLIBC_HAS_REALTIME)$(UCLIBC_HAS_ADVANCED_REALTIME),) + # Remove SUSv-realtime related message-queue headers upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/mqueue.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/mqueue.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/mqueue.h +endif +ifneq ($(UCLIBC_HAS_REALTIME),y) + # Remove SUSv-realtime related headers upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sched.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/sched.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/sched.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/semaphore.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/semaphore.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/semaphore.h +endif +ifneq ($(UCLIBC_HAS_SOCKET),y) + # Remove socket related headers upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/socket.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/bits/socket.h + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/sys/socketvar.h +endif +ifneq ($(UCLIBC_HAS_CRYPT),y) + # Remove crypt.h since libcrypt was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/crypt.h +endif +ifneq ($(UCLIBC_SUPPORT_AI_ADDRCONFIG),y) + # Remove ifaddrs.h since the corresponding functionality is disabled + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/ifaddrs.h +endif + +# Installs development library links. +install_dev: install_headers all + $(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)lib + -$(INSTALL) -m 644 lib/*.[ao] $(PREFIX)$(DEVEL_PREFIX)lib/ +ifeq ($(HAVE_SHARED),y) + for i in `find lib/ -type l -name 'lib[a-zA-Z]*.so' | \ + $(SED) -e 's/lib\///'` ; do \ + $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)$$i.$(MAJOR_VERSION) \ + $(PREFIX)$(DEVEL_PREFIX)lib/$$i; \ + done + if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(RUNTIME_PREFIX)lib/$(SHARED_MAJORNAME) ] ; then \ + $(RM) $(PREFIX)$(DEVEL_PREFIX)lib/libc.so; \ + $(SED) -e 's:$(NONSHARED_LIBNAME):$(DEVEL_PREFIX)lib/$(NONSHARED_LIBNAME):' \ + -e 's:$(SHARED_MAJORNAME):$(RUNTIME_PREFIX)lib/$(SHARED_MAJORNAME):' \ + -e 's:$(UCLIBC_LDSO):$(RUNTIME_PREFIX)lib/$(UCLIBC_LDSO):' \ + $(top_builddir)lib/libc.so > $(PREFIX)$(DEVEL_PREFIX)lib/libc.so; \ + fi +ifeq ($(UCLIBC_HAS_THREADS),y) +ifneq ($(LINUXTHREADS_OLD),y) + if [ -f $(top_builddir)lib/libpthread.so -a -f $(PREFIX)$(RUNTIME_PREFIX)lib/libpthread.so.$(MAJOR_VERSION) ] ; then \ + $(RM) $(PREFIX)$(DEVEL_PREFIX)lib/libpthread.so; \ + cp $(top_srcdir)extra/scripts/format.lds $(PREFIX)$(DEVEL_PREFIX)lib/libpthread.so; \ + echo "GROUP ( $(RUNTIME_PREFIX)lib/libpthread.so.$(MAJOR_VERSION) $(DEVEL_PREFIX)lib/libpthread_nonshared.a )" \ + >> $(PREFIX)$(DEVEL_PREFIX)lib/libpthread.so; \ + fi +endif +endif +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) + $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)libthread_db.so.1 \ + $(PREFIX)$(DEVEL_PREFIX)lib/libthread_db.so +endif +ifeq ($(DOPIC),y) +# # If we build shared libraries then the static libs are PIC... +# # Make _pic.a symlinks to make mklibs.py and similar tools happy. + if [ -d lib ] ; then \ + for i in `find lib/ -type f -name 'lib*.a' | $(SED) -e 's/lib\///'` ; do \ + $(LN) -sf $$i $(PREFIX)$(DEVEL_PREFIX)lib/`echo $$i \ + | $(SED) -e 's/\.a$$/_pic.a/'`; \ + done ; \ + fi +endif +endif +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) + for file in lib/lib*.gdb; do \ + if test -f $$file; then \ + $(INSTALL) -m 755 $$file $(PREFIX)$(DEVEL_PREFIX)lib; \ + $(INSTALL) -m 755 `echo $$file | $(SED) 's/\.gdb$$//'` \ + $(PREFIX)$(DEVEL_PREFIX)lib; \ + fi; \ + done +endif + +# Installs run-time libraries +install_runtime: all +ifeq ($(HAVE_SHARED),y) + $(INSTALL) -d $(PREFIX)$(RUNTIME_PREFIX)lib + $(INSTALL) -m 644 lib/lib*-$(VERSION).so \ + $(PREFIX)$(RUNTIME_PREFIX)lib + cd lib && $(TAR) -cf - *.so.* | $(TAR) -xf - -C $(PREFIX)$(RUNTIME_PREFIX)lib + @if [ -x lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so ] ; then \ + set -e; \ + $(SHELL_SET_X); \ + $(INSTALL) -m 755 lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so \ + $(PREFIX)$(RUNTIME_PREFIX)lib; \ + fi +endif + +hostutils: + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" HOSTCC="$(HOSTCC)" -C utils hostutils +utils: + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils + +# Installs helper applications, such as 'ldd' and 'ldconfig' +install_utils: utils + $(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils utils_install + +endif # ifeq ($(HAVE_DOT_CONFIG),y) + +include/bits include/config: + @$(disp_mkdir) + $(Q)$(INSTALL) -d $@ + +# configuration +# --------------------------------------------------------------------------- +extra/config/conf extra/config/mconf: | include/config + $(Q)$(MAKE) -C extra/config $(notdir $@) + +menuconfig: extra/config/mconf + $(Q)./extra/config/mconf extra/Configs/Config.in + +config: extra/config/conf + $(Q)./extra/config/conf extra/Configs/Config.in + +oldconfig: extra/config/conf + $(Q)./extra/config/conf -o extra/Configs/Config.in + +silentoldconfig: extra/config/conf + $(Q)./extra/config/conf -s extra/Configs/Config.in + +randconfig: extra/config/conf + $(Q)./extra/config/conf -r extra/Configs/Config.in + +allyesconfig: extra/config/conf + $(Q)./extra/config/conf -y extra/Configs/Config.in + $(SED) -i -e "s/^DODEBUG=.*/# DODEBUG is not set/" .config + $(SED) -i -e "s/^DOASSERTS=.*/# DOASSERTS is not set/" .config + $(SED) -i -e "s/^SUPPORT_LD_DEBUG_EARLY=.*/# SUPPORT_LD_DEBUG_EARLY is not set/" .config + $(SED) -i -e "s/^SUPPORT_LD_DEBUG=.*/# SUPPORT_LD_DEBUG is not set/" .config + $(SED) -i -e "s/^UCLIBC_MJN3_ONLY=.*/# UCLIBC_MJN3_ONLY is not set/" .config + $(Q)./extra/config/conf -o extra/Configs/Config.in + +allnoconfig: extra/config/conf + $(Q)./extra/config/conf -n extra/Configs/Config.in + +defconfig: extra/config/conf + $(Q)./extra/config/conf -d extra/Configs/Config.in \ + -D extra/Configs/defconfigs/$(ARCH) + +include_clean: + $(Q)$(RM) include/fpu_control.h include/dl-osinfo.h include/hp-timing.h + @set -e; \ + for i in `(cd libc/sysdeps/linux/common/sys; ls *.h)` ; do \ + $(RM) include/sys/$$i; \ + done; \ + if [ -d libc/sysdeps/linux/$(TARGET_ARCH)/sys ] ; then \ + for i in `(cd libc/sysdeps/linux/$(TARGET_ARCH)/sys; ls *.h)` ; do \ + $(RM) include/sys/$$i; \ + done; \ + fi + +clean: include_clean + $(Q)$(RM) -r lib include/bits + @$(MAKE) -C utils utils_clean + +$(MAKE) -s -C test clean + @$(RM) include/linux include/asm* + $(Q)$(RM) $(top_builddir)extra/scripts/unifdef + $(Q)$(RM) -r $(LOCAL_INSTALL_PATH) + +distclean: clean + -find . \( -name core -o -name \*.orig -o -name \*~ -o -name .\*.dep \) -exec $(RM) {} \; + $(RM) .config .config.old .config.cmd + $(RM) extra/locale/*.tgz + $(MAKE) -C extra/config distclean + +dist release: + $(RM) -r ../uClibc-$(VERSION) ../uClibc-$(VERSION).tar.bz2 + svn -q export . ../uClibc-$(VERSION) + $(TAR) cjf ../uClibc-$(VERSION).tar.bz2 -C .. uClibc-$(VERSION) + du -b ../uClibc-$(VERSION).tar.bz2 + +test check: test_compile + $(Q)$(MAKE) -C test + +test_compile: $(LOCAL_INSTALL_PATH) + $(Q)$(MAKE) -C test compile diff --git a/Makerules b/Makerules new file mode 100644 index 0000000..9c80c96 --- /dev/null +++ b/Makerules @@ -0,0 +1,428 @@ +# +# Licensed under LGPL v2.1, see the file COPYING.LIB in this tarball for details. +# + +.SUFFIXES: .c .S .o .os .oS .so .a .s .i + +PHONY := FORCE + +.PHONY: dummy $(PHONY) \ + all check test $(clean_targets) \ + config dist menuconfig oldconfig release \ + subdirs utils help + +# order is important, the stripping uses STRIP_FLAGS for lib-so, but not for lib-a +ifeq ($(HAVE_SHARED),y) +.LIBPATTERNS: "lib%.so" +libs: $(lib-so-y) $(lib-a-y) +$(lib-so-y): | $(interp) +else +.LIBPATTERNS: "lib%.a" +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) +libs: $(lib-gdb-y) +endif +libs: $(lib-a-y) +endif +objs: all_objs + +shared_objs = $(libc-y:.o=.os) $(libc-shared-y) $(libc-nonshared-y) \ + $(libcrypt-so-y) $(libdl-so-y) \ + $(libintl-so-y) $(libm-so-y) $(libnsl-so-y) \ + $(libpthread-so-y) $(libpthread-nonshared-y) $(libthread_db-so-y) \ + $(libresolv-so-y) $(librt-so-y) \ + $(ldso-y) \ + $(libutil-so-y) + +ar_objs = $(libc-y) $(libc-static-y) $(libcrypt-a-y) \ + $(libdl-a-y) $(libintl-a-y) $(libm-a-y) $(libnsl-a-y) \ + $(libpthread-a-y) $(libthread_db-a-y) \ + $(libresolv-a-y) $(librt-a-y) $(libutil-a-y) +ifeq ($(DOPIC),y) +ar_objs := $(ar_objs:.o=.os) +endif +flat_objs = $(lib-gdb-y) + +ifeq ($(HAVE_SHARED),y) +all_objs: $(sort $(shared_objs) $(ar_objs)) +else +all_objs: $(ar_objs) +endif +$(shared_objs) $(ar_objs): | $(sub_headers) + +headers-y: $(headers-y) + @true + +MAKEFLAGS += --no-print-directory +SHELL_SET_X := set +x +ifneq ($(findstring s,$(MAKEFLAGS)),) +export MAKE_IS_SILENT := y +SECHO := -@false +DISP := sil +Q := @ +else +export MAKE_IS_SILENT := n +SECHO := @echo +ifneq ($(V)$(VERBOSE),) +SHELL_SET_X := set -x +DISP := ver +Q := +else +DISP := pur +Q := @ +endif +endif + +show_objs = $(subst ../,,$@) + +pur_disp_compile.c = echo " "CC $(show_objs) +pur_disp_compile.i = echo " "CPP $(show_objs) +pur_disp_compile.s = echo " "CC-S $(show_objs) +pur_disp_compile.u = echo " "CC $(show_objs) +pur_disp_compile.S = echo " "AS $(show_objs) +pur_disp_compile.m = $(pur_disp_compile.c) +pur_disp_compile-m = echo " "CC-m $(show_objs) +pur_disp_hcompile.u= echo " "HOSTCC $(show_objs) +pur_disp_hcompile.o= echo " "HOSTCC-o $(show_objs) +pur_disp_strip = echo " "STRIP $(STRIP_FLAGS) $@ +pur_disp_t_strip = echo " "STRIP $(STRIP_FLAGS) $@ +pur_disp_ar = echo " "AR $(ARFLAGS) $@ +pur_disp_ld = echo " "LD $(1) +pur_disp_ln = echo " "LN $@ +pur_disp_mkdir = echo " "MKDIR $@ +pur_disp_gen = echo " "GEN $@ +pur_disp_unifdef = echo " "UNIFDEF $@ +pur_disp_rm = echo " "CLEAN $(@:_clean=) + +sil_disp_compile.c = true +sil_disp_compile.i = true +sil_disp_compile.s = true +sil_disp_compile.u = true +sil_disp_compile.S = true +sil_disp_compile.m = true +sil_disp_compile-m = true +sil_disp_hcompile.u= true +sil_disp_hcompile.o= true +sil_disp_strip = true +sil_disp_t_strip = true +sil_disp_ar = true +sil_disp_ld = true +sil_disp_ln = true +sil_disp_mkdir = true +sil_disp_gen = true +sil_disp_unifdef = true +sil_disp_rm = true + +ver_disp_compile.c = echo $(cmd_compile.c) +ver_disp_compile.i = echo $(cmd_compile.i) +ver_disp_compile.s = echo $(cmd_compile.s) +ver_disp_compile.u = echo $(cmd_compile.u) +ver_disp_compile.S = echo $(cmd_compile.S) +ver_disp_compile.m = echo $(cmd_compile.m) +ver_disp_compile-m = echo $(cmd_compile-m) +ver_disp_hcompile.u= echo $(cmd_hcompile.u) +ver_disp_hcompile.o= echo $(cmd_hcompile.o) +ver_disp_strip = echo $(cmd_strip) +ver_disp_t_strip = echo $(cmd_t_strip) +ver_disp_ar = echo $(cmd_ar) +ver_disp_ld = +ver_disp_ln = +ver_disp_mkdir = +ver_disp_gen = +ver_disp_unifdef = echo $(cmd_unifdef) +ver_disp_rm = + +disp_compile.c = $($(DISP)_disp_compile.c) +disp_compile.i = $($(DISP)_disp_compile.i) +disp_compile.s = $($(DISP)_disp_compile.s) +disp_compile.u = $($(DISP)_disp_compile.u) +disp_compile.S = $($(DISP)_disp_compile.S) +disp_compile.m = $($(DISP)_disp_compile.m) +disp_compile-m = $($(DISP)_disp_compile-m) +disp_hcompile.u= $($(DISP)_disp_hcompile.u) +disp_hcompile.o= $($(DISP)_disp_hcompile.o) +disp_strip = $($(DISP)_disp_strip) +disp_t_strip = $($(DISP)_disp_t_strip) +disp_ar = $($(DISP)_disp_ar) +disp_ld = $($(DISP)_disp_ld) +disp_ln = $($(DISP)_disp_ln) +disp_mkdir = $($(DISP)_disp_mkdir) +disp_gen = $($(DISP)_disp_gen) +disp_unifdef = $($(DISP)_disp_unifdef) +disp_rm = $($(DISP)_disp_rm) + +any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) + +# ../foo/bar/baz.ext -> foo_bar_baz.ext +variablify = $(subst /,_,$(subst $(top_builddir),,$(1))) +# strip the top_builddir off everything to make the *string* idempotent for -C +dirify = $(subst $(top_builddir),,$(patsubst -L$(top_builddir)%,-L%,$(patsubst -I$(top_builddir)%,-I%,$(1)))) + +# True if not identical. Neither order nor whitespace nor identical flags +# matter. +compare_flags = \ + $(strip $(filter-out $(call dirify,$(cmd_$(call variablify,$(1)))), \ + $(call dirify,$(cmd_$(call variablify,$(@))))) \ + $(filter-out $(call dirify,$(cmd_$(call variablify,$(@)))), \ + $(call dirify,$(cmd_$(call variablify,$(1)))))) + +# Rebuild if any prerequisite, the used CC or flags changed. +# Previously used flags are stored in the corresponding .%.dep files +maybe_exec = \ + $(if $(strip $(compare_flags) $(any-prereq)), \ + @set -e; \ + $(disp_$(1)); \ + $(cmd_$(1)); \ + echo 'cmd_$(call variablify,$@) := $(call dirify,$(cmd_$(call variablify,$1)))' >> $(dir $@).$(notdir $@).dep) + + +CFLAGS_gen.dep = -MT $@ -MD -MP -MF $(dir $@).$(notdir $@).dep + +cmd_compile.c = $(CC) -c $< -o $@ $(CFLAGS) $(ARCH_CFLAGS) \ + $(CFLAGS-$(suffix $@)) \ + $(filter-out $(CFLAGS-OMIT-$(notdir $<)),$(CFLAGS-$(notdir $( $@ + $(Q)echo "#include " >> $@ + $(Q)echo "const char __dl_ldso__[] __attribute__ ((section " \ + "(\".interp\"))) =\""$(SHARED_LIB_LOADER_PREFIX)/$(UCLIBC_LDSO)"\";" >> $@ + +$(interp): $(top_builddir)lib/interp.c + $(compile.c) + $(Q)$(STRIPTOOL) -x -R .note -R .comment $@ + +$(ldso): + @cd $(top_builddir); $(MAKE) lib/$(patsubst %.$(MAJOR_VERSION),%,$(notdir $@)) + +$(libc): + @cd $(top_builddir); $(MAKE) lib/$(patsubst %.$(MAJOR_VERSION),%,$(notdir $@)) + +CRT := crt1 + +ifeq ($(HAVE_SHARED)$(UCLIBC_FORMAT_SHARED_FLAT),y) +CRTS=$(top_builddir)lib/$(CRT).o $(top_builddir)lib/S$(CRT).o +else +CRTS=$(top_builddir)lib/$(CRT).o +endif + +ASFLAGS-$(CRT).o := -DL_$(CRT) +ASFLAGS-S$(CRT).o := $(PIEFLAG) -DL_S$(CRT) +$(CRTS): $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(CRT).S + $(Q)$(INSTALL) -d $(dir $@) + $(compile.S) + $(Q)$(STRIPTOOL) -x -R .note -R .comment $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +CTOR_TARGETS=$(top_builddir)lib/crti.o $(top_builddir)lib/crtn.o +else +CTOR_TARGETS:= +endif + +ifeq ($(UCLIBC_FORMAT_FDPIC_ELF),y) +CRTRELOC=$(top_builddir)lib/crtreloc.o +$(CRTRELOC): $(top_builddir)lib/%.o : $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/%.c + $(Q)$(INSTALL) -d $(dir $@) + $(compile.c) +endif + +ifneq ($(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/initfini.c),) +CFLAGS-initfini.s := -S -g0 $(PICFLAG) -fno-inline-functions -finhibit-size-directive +$(top_builddir)lib/initfini.s: $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/initfini.c + $(compile.c) + +$(top_builddir)lib/defs.h: $(top_builddir)lib/initfini.s + $(Q)sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ + gawk -f $(top_srcdir)extra/scripts/defs.awk > $@.tmp + $(Q)mv $@.tmp $@ + +$(top_builddir)lib/crti.S: $(top_builddir)lib/initfini.s $(top_builddir)lib/defs.h + $(Q)sed -n -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(top_builddir)lib/crtn.S: $(top_builddir)lib/initfini.s + $(Q)sed -n -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(CTOR_TARGETS): $(top_builddir)lib/%.o : $(top_builddir)lib/%.S + $(Q)$(INSTALL) -d $(dir $@) + $(compile.S) $(PICFLAG) $(SSP_DISABLE_FLAGS) +else +$(CTOR_TARGETS): $(top_builddir)lib/%.o : $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/%.S + $(Q)$(INSTALL) -d $(dir $@) + $(compile.S) $(PICFLAG) $(SSP_DISABLE_FLAGS) +endif + +#ifeq ($(TARGET_ARCH),nios) +#CRTS_COMPAT := $(top_builddir)lib/crt0.o +#$(CRTS_COMPAT): +# ln -fs crt1.o $(top_builddir)lib/crt0.o +#else +CRTS_COMPAT := +#endif + +$(crt-y): $(CRTS) $(CTOR_TARGETS) $(CRTS_COMPAT) $(CRTRELOC) +$(CRTS) $(CTOR_TARGETS) $(CRTS_COMPAT) $(CRTRELOC): | headers + +$(top_builddir)lib/$(NONSHARED_LIBNAME): $(libc-nonshared-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libpthread_nonshared.a: $(libpthread-nonshared-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +files.dep := $(libc-a-y) $(libc-so-y) $(libc-nonshared-y) \ + $(libm-a-y) $(libm-so-y) \ + $(libpthread-a-y) $(libpthread-so-y) $(libpthread-nonshared-y) \ + $(libthread_db-a-y) $(libthread_db-so-y) \ + $(librt-a-y) $(librt-so-y) $(libresolv-a-y) $(libresolv-so-y) \ + $(libcrypt-a-y) $(libcrypt-so-y) $(libutil-a-y) $(libutil-so-y) \ + $(libnsl-a-y) $(libnsl-so-y) $(ldso-y) $(libdl-a-y) $(libdl-so-y) +.depends.dep := \ + $(patsubst %.o,%.o.dep,$(filter %.o,$(files.dep))) \ + $(patsubst %.os,%.os.dep,$(filter %.os,$(files.dep))) \ + $(patsubst %.oS,%.oS.dep,$(filter %.oS,$(files.dep))) +# Oh, and prepend a dot to the basename so i don't have to change my habit of +# calling 'size thefile.o*' +.depends.dep := $(foreach f,$(.depends.dep),$(dir $(f)).$(notdir $(f))) +.depends.dep := $(wildcard $(.depends.dep)) + +FORCE: + +clean: objclean-y headers_clean-y +realclean: clean + $(Q)$(RM) $(.depends.dep) + +objclean-y: $(objclean-y) +headers_clean-y: $(headers_clean-y) + +ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),) +ifneq ($(strip $(.depends.dep)),) +.NOEXPORT: +-include $(.depends.dep) +endif +endif + +# vi: ft=make : diff --git a/README b/README new file mode 100644 index 0000000..f8467fb --- /dev/null +++ b/README @@ -0,0 +1,73 @@ + + uClibc - a Small C Library for Linux + Erik Andersen + +uClibc (aka µClibc/pronounced yew-see-lib-see) is a C library for +developing embedded Linux systems. It is much smaller than the +GNU C Library, but nearly all applications supported by glibc +also work perfectly with uClibc. Porting applications from glibc +to uClibc typically involves just recompiling the source code. +uClibc even supports shared libraries and threading. It currently +runs on standard Linux and MMU-less (also known as µClinux) +systems with support for alpha, ARM, cris, e1, h8300, i386, i960, +m68k, microblaze, mips/mipsel, PowerPC, SH, SPARC, and v850 +processors. + +If you are building an embedded Linux system and you find that +glibc is eating up too much space, you should consider using +uClibc. If you are building a huge fileserver with 12 Terabytes +of storage, then using glibc may make more sense. Unless, for +example, that 12 Terabytes will be Network Attached Storage and +you plan to burn Linux into the system's firmware... + +uClibc is maintained by Erik Andersen and is licensed under the +GNU LESSER GENERAL PUBLIC LICENSE. This license allows you to +make closed source commercial applications using an unmodified +version of uClibc (Please consider sharing some of the money you +make ;-). You do not need to give away all your source code just +because you use uClibc and/or run on Linux. You should, however, +carefuly review the license and make certain you understand and +abide by it strictly. + + +For installation instructions, see the file INSTALL. + +uClibc strives to be standards compliant, which means that most +documentation written for SuSv3, or for glibc also applies to +uClibc functions. However, many GNU extensions are not supported +because they have not been ported, or more importantly, would +increase the size of uClibc disproportional to the added +functionality. There is some discussion of these differences +in the "docs" directory. + +Additional information (recent releases, FAQ, mailing list, bugs, +etc.) can be found at http://www.uclibc.org/. + +uClibc may be freely modified and distributed under the terms of +the GNU Lesser General Public License, which can be found in the +file COPYING.LIB. + +Please Note: + + There is an unwholesomely huge amount of code out there + that depends on the presence of GNU libc header files. + We have GNU libc compatible header files. So we have + committed a horrible sin in uClibc. We _lie_ and claim + to be GNU libc in order to force these applications to + work as their developers intended. This is IMHO, + pardonable, since these defines are not really intended + to check for the presence of a particular library, but + rather are used to define an _interface_. Some programs + are especially chummy with glibc, and may need this + behavior disabled by adding CFLAGS+=-D__FORCE_NOGLIBC + + If you want to make special exceptions in your code which are + specifically for uClibc, you can make certain to include features.h, + and then have your code check for uClibc as follows: + + #ifdef __UCLIBC__ + do_something_special(); + #endif + +And most of all, be sure to have some fun! :-) + -Erik diff --git a/Rules.mak b/Rules.mak new file mode 100644 index 0000000..d3cda90 --- /dev/null +++ b/Rules.mak @@ -0,0 +1,647 @@ +# Rules.make for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# check for proper make version +ifneq ($(findstring x3.7,x$(MAKE_VERSION)),) +$(error Your make is too old $(MAKE_VERSION). Go get at least 3.80) +endif + +#----------------------------------------------------------- +# This file contains rules which are shared between multiple +# Makefiles. All normal configuration options live in the +# file named ".config". Don't mess with this file unless +# you know what you are doing. + + +#----------------------------------------------------------- +# If you are running a cross compiler, you will want to set +# 'CROSS' to something more interesting ... Target +# architecture is determined by asking the CC compiler what +# arch it compiles things for, so unless your compiler is +# broken, you should not need to specify TARGET_ARCH. +# +# Most people will set this stuff on the command line, i.e. +# make CROSS=arm-linux- +# will build uClibc for 'arm'. + +ifndef CROSS +CROSS= +endif +CC = $(CROSS)gcc +AR = $(CROSS)ar +LD = $(CROSS)ld +NM = $(CROSS)nm +STRIPTOOL = $(CROSS)strip + +INSTALL = install +LN = ln +RM = rm -f +TAR = tar +SED = sed +AWK = awk + +STRIP_FLAGS ?= -x -R .note -R .comment + +UNIFDEF := $(top_builddir)extra/scripts/unifdef -UUCLIBC_INTERNAL + +# Select the compiler needed to build binaries for your development system +HOSTCC = gcc +BUILD_CFLAGS = -O2 -Wall +export ARCH := $(shell uname -m | $(SED) -e s/i.86/i386/ \ + -e s/sun.*/sparc/ -e s/sparc.*/sparc/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/sh.*/sh/ \ + -e s/s390x/s390/ -e s/parisc.*/hppa/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/xtensa.*/xtensa/ ) + + +#--------------------------------------------------------- +# Nothing beyond this point should ever be touched by mere +# mortals. Unless you hang out with the gods, you should +# probably leave all this stuff alone. + +# Pull in the user's uClibc configuration +ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),) +-include $(top_builddir).config +endif + +# Make certain these contain a final "/", but no "//"s. +TARGET_ARCH:=$(shell grep -s '^TARGET_ARCH' $(top_builddir)/.config | $(SED) -e 's/^TARGET_ARCH=//' -e 's/"//g') +TARGET_ARCH:=$(strip $(subst ",, $(strip $(TARGET_ARCH)))) +TARGET_SUBARCH:=$(shell grep -s '^TARGET_SUBARCH' $(top_builddir)/.config | $(SED) -e 's/^TARGET_SUBARCH=//' -e 's/"//g') +TARGET_SUBARCH:=$(strip $(subst ",, $(strip $(TARGET_SUBARCH)))) +RUNTIME_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(subst ",, $(strip $(RUNTIME_PREFIX)))))) +DEVEL_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(subst ",, $(strip $(DEVEL_PREFIX)))))) +KERNEL_HEADERS:=$(strip $(subst //,/, $(subst ,/, $(subst ",, $(strip $(KERNEL_HEADERS)))))) +export RUNTIME_PREFIX DEVEL_PREFIX KERNEL_HEADERS + + +# Now config hard core +MAJOR_VERSION := 0 +MINOR_VERSION := 9 +SUBLEVEL := 30 +EXTRAVERSION := +VERSION := $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL) +ifneq ($(EXTRAVERSION),) +VERSION := $(VERSION)$(EXTRAVERSION) +endif +# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc. +LC_ALL := C +export MAJOR_VERSION MINOR_VERSION SUBLEVEL VERSION LC_ALL + +LIBC := libc +SHARED_MAJORNAME := $(LIBC).so.$(MAJOR_VERSION) +ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 mips64 powerpc64 s390x sparc64 x86_64 ),) +UCLIBC_LDSO_NAME := ld64-uClibc +ARCH_NATIVE_BIT := 64 +else +UCLIBC_LDSO_NAME := ld-uClibc +ARCH_NATIVE_BIT := 32 +endif +UCLIBC_LDSO := $(UCLIBC_LDSO_NAME).so.$(MAJOR_VERSION) +NONSHARED_LIBNAME := uclibc_nonshared.a +libc := $(top_builddir)lib/$(SHARED_MAJORNAME) +libc.depend := $(top_builddir)lib/$(SHARED_MAJORNAME:.$(MAJOR_VERSION)=) +interp := $(top_builddir)lib/interp.os +ldso := $(top_builddir)lib/$(UCLIBC_LDSO) +headers_dep := $(top_builddir)include/bits/sysnum.h +sub_headers := $(headers_dep) + +#LIBS :=$(interp) -L$(top_builddir)lib -lc +LIBS := $(interp) -L$(top_builddir)lib $(libc:.$(MAJOR_VERSION)=) + +# Make sure DESTDIR and PREFIX can be used to install +# PREFIX is a uClibcism while DESTDIR is a common GNUism +ifndef PREFIX +PREFIX = $(DESTDIR) +endif + +ifneq ($(HAVE_SHARED),y) +libc := +interp := +ldso := +endif + +comma:=, +space:= # + +ifndef CROSS +CROSS=$(strip $(subst ",, $(CROSS_COMPILER_PREFIX))) +endif + +# A nifty macro to make testing gcc features easier +check_gcc=$(shell \ + if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then echo "$(1)"; else echo "$(2)"; fi) +check_as=$(shell \ + if $(CC) -Wa,$(1) -Wa,-Z -c -o /dev/null -xassembler /dev/null > /dev/null 2>&1; \ + then echo "-Wa,$(1)"; fi) +check_ld=$(shell \ + if $(LD) $(1) -o /dev/null -b binary /dev/null > /dev/null 2>&1; \ + then echo "$(1)"; fi) + +ARFLAGS:=cr + +# Flags in OPTIMIZATION are used only for non-debug builds +OPTIMIZATION:= +# Use '-Os' optimization if available, else use -O2, allow Config to override +OPTIMIZATION+=$(call check_gcc,-Os,-O2) +# Use the gcc 3.4 -funit-at-a-time optimization when available +OPTIMIZATION+=$(call check_gcc,-funit-at-a-time,) + +GCC_MAJOR_VER?=$(shell $(CC) -dumpversion | cut -d . -f 1) +#GCC_MINOR_VER?=$(shell $(CC) -dumpversion | cut -d . -f 2) + +ifeq ($(GCC_MAJOR_VER),4) +# shrinks code, results are from 4.0.2 +# 0.36% +OPTIMIZATION+=$(call check_gcc,-fno-tree-loop-optimize,) +# 0.34% +OPTIMIZATION+=$(call check_gcc,-fno-tree-dominator-opts,) +# 0.1% +OPTIMIZATION+=$(call check_gcc,-fno-strength-reduce,) +endif + +CPU_CFLAGS-$(UCLIBC_FORMAT_SHARED_FLAT) += -mid-shared-library +CPU_CFLAGS-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += -msep-data + +PICFLAG-y := -fPIC +PICFLAG-$(UCLIBC_FORMAT_FDPIC_ELF) := -mfdpic +PICFLAG := $(PICFLAG-y) +PIEFLAG_NAME:=-fPIE + +# Some nice CPU specific optimizations +ifeq ($(TARGET_ARCH),i386) + OPTIMIZATION+=$(call check_gcc,-fomit-frame-pointer,) + + # NB: this may make SSE insns segfault! + # -O1 -march=pentium3, -Os -msse etc are known to be affected. + # TODO: conditionally bump to 4 + # (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13685) + OPTIMIZATION+=$(call check_gcc,-mpreferred-stack-boundary=4,) + + # Choice of alignment (please document why!) + # -falign-labels: in-line labels + # (reachable by normal code flow, aligning will insert nops + # which will be executed - may even make things slower) + # -falign-jumps: reachable only by a jump + # Generic: no alignment at all (smallest code) + GCC_FALIGN=$(call check_gcc,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,-malign-jumps=1 -malign-loops=1) +ifeq ($(CONFIG_K7),y) + # Align functions to four bytes, use default for jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=4 -falign-labels=1,-malign-functions=4) +endif +ifeq ($(CONFIG_CRUSOE),y) + # Use compiler's default for functions, jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=0 -falign-labels=1,-malign-functions=0) +endif +ifeq ($(CONFIG_CYRIXIII),y) + # Use compiler's default for functions, jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=0 -falign-labels=1,-malign-functions=0) +endif + OPTIMIZATION+=$(GCC_FALIGN) + + # Putting each function and data object into its own section + # allows for kbytes of less text if users link against static uclibc + # using ld --gc-sections. + # ld 2.18 can't do that (yet?) for shared libraries, so we itself + # do not use --gc-sections at shared lib link time. + # However, in combination with sections being sorted by alignment + # it does result in much reduced padding: + # text data bss dec hex + # 235319 1472 5992 242783 3b45f old.so + # 234104 1472 5980 241556 3af94 new.so + # Without -ffunction-sections, all functions will get aligned + # to 4 byte boundary by as/ld. This is arguably a bug in as. + # It specifies 4 byte align for .text even if not told to do so: + # Idx Name Size VMA LMA File off Algn + # 0 .text xxxxxxxx 00000000 00000000 xxxxxxxx 2**2 <===! + CPU_CFLAGS-y += $(call check_gcc,-ffunction-sections -fdata-sections,) +ifneq ($(call check_ld,--sort-common,),) + CPU_LDFLAGS-y += -Wl,--sort-common +endif +ifneq ($(call check_ld,--sort-section alignment),) + CPU_LDFLAGS-y += -Wl,--sort-section,alignment +endif + + CPU_LDFLAGS-y+=-m32 + CPU_CFLAGS-y+=-m32 + CPU_CFLAGS-$(CONFIG_386)+=-march=i386 + CPU_CFLAGS-$(CONFIG_486)+=-march=i486 + CPU_CFLAGS-$(CONFIG_ELAN)+=-march=i486 + CPU_CFLAGS-$(CONFIG_586)+=-march=i586 + CPU_CFLAGS-$(CONFIG_586MMX)+=$(call check_gcc,-march=pentium-mmx,-march=i586) + CPU_CFLAGS-$(CONFIG_686)+=-march=i686 + CPU_CFLAGS-$(CONFIG_PENTIUMII)+=$(call check_gcc,-march=pentium2,-march=i686) + CPU_CFLAGS-$(CONFIG_PENTIUMIII)+=$(call check_gcc,-march=pentium3,-march=i686) + CPU_CFLAGS-$(CONFIG_PENTIUM4)+=$(call check_gcc,-march=pentium4,-march=i686) + CPU_CFLAGS-$(CONFIG_K6)+=$(call check_gcc,-march=k6,-march=i586) + CPU_CFLAGS-$(CONFIG_K7)+=$(call check_gcc,-march=athlon,-march=i686) + CPU_CFLAGS-$(CONFIG_CRUSOE)+=-march=i686 + CPU_CFLAGS-$(CONFIG_WINCHIPC6)+=$(call check_gcc,-march=winchip-c6,-march=i586) + CPU_CFLAGS-$(CONFIG_WINCHIP2)+=$(call check_gcc,-march=winchip2,-march=i586) + CPU_CFLAGS-$(CONFIG_CYRIXIII)+=$(call check_gcc,-march=c3,-march=i486) + CPU_CFLAGS-$(CONFIG_NEHEMIAH)+=$(call check_gcc,-march=c3-2,-march=i686) +endif + +ifeq ($(TARGET_ARCH),sparc) + CPU_CFLAGS-$(CONFIG_SPARC_V7)+=-mcpu=v7 + CPU_CFLAGS-$(CONFIG_SPARC_V8)+=-mcpu=v8 + CPU_CFLAGS-$(CONFIG_SPARC_V9)+=-mcpu=v9 + CPU_CFLAGS-$(CONFIG_SPARC_V9B)+=$(call check_gcc,-mcpu=v9b,-mcpu=ultrasparc) +endif + +ifeq ($(TARGET_ARCH),arm) + OPTIMIZATION+=-fstrict-aliasing + CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL + CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-mlittle-endian + CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mbig-endian + CPU_CFLAGS-$(CONFIG_GENERIC_ARM)+= + CPU_CFLAGS-$(CONFIG_ARM610)+=-mtune=arm610 -march=armv3 + CPU_CFLAGS-$(CONFIG_ARM710)+=-mtune=arm710 -march=armv3 + CPU_CFLAGS-$(CONFIG_ARM7TDMI)+=-mtune=arm7tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM720T)+=-mtune=arm7tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM920T)+=-mtune=arm9tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM922T)+=-mtune=arm9tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM926T)+=-mtune=arm9tdmi -march=armv5t + CPU_CFLAGS-$(CONFIG_ARM10T)+=-mtune=arm10tdmi -march=armv5t + CPU_CFLAGS-$(CONFIG_ARM1136JF_S)+=-mtune=arm1136jf-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM1176JZ_S)+=-mtune=arm1176jz-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM1176JZF_S)+=-mtune=arm1176jzf-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM_SA110)+=-mtune=strongarm110 -march=armv4 + CPU_CFLAGS-$(CONFIG_ARM_SA1100)+=-mtune=strongarm1100 -march=armv4 + CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) + CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=-march=armv5te -Wa,-mcpu=xscale + CPU_CFLAGS-$(CONFIG_ARM_IWMMXT)+=-march=iwmmxt -Wa,-mcpu=iwmmxt -mabi=iwmmxt + CPU_CFLAGS-$(CONFIG_ARM_CORTEX_M3)+=-mcpu=cortex-m3 -mthumb + CPU_CFLAGS-$(CONFIG_ARM_CORTEX_M1)+=-mcpu=cortex-m1 -mthumb +endif + +ifeq ($(TARGET_ARCH),mips) + CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL + CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB + CPU_CFLAGS-$(CONFIG_MIPS_ISA_1)+=-mips1 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_2)+=-mips2 -mtune=mips2 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_3)+=-mips3 -mtune=mips3 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_4)+=-mips4 -mtune=mips4 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32)+=-mips32 -mtune=mips32 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32R2)+=-march=mips32r2 -mtune=mips32r2 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS64)+=-mips64 -mtune=mips32 + ifeq ($(strip $(ARCH_BIG_ENDIAN)),y) + CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64btsmip + CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32btsmip + endif + ifeq ($(strip $(ARCH_LITTLE_ENDIAN)),y) + CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64ltsmip + CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32ltsmip + endif + CPU_CFLAGS-$(CONFIG_MIPS_N64_ABI)+=-mabi=64 + CPU_CFLAGS-$(CONFIG_MIPS_O32_ABI)+=-mabi=32 + CPU_CFLAGS-$(CONFIG_MIPS_N32_ABI)+=-mabi=n32 +endif + +ifeq ($(TARGET_ARCH),nios) + CPU_LDFLAGS-y+=-Wl,-m32 + CPU_CFLAGS-y+=-Wl,-m32 +endif + +ifeq ($(TARGET_ARCH),sh) + OPTIMIZATION+=-fstrict-aliasing + OPTIMIZATION+= $(call check_gcc,-mprefergot,) + CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL + CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-ml + CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mb + CPU_CFLAGS-$(CONFIG_SH2)+=-m2 + CPU_CFLAGS-$(CONFIG_SH3)+=-m3 +ifeq ($(UCLIBC_HAS_FLOATS),y) + CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a + CPU_CFLAGS-$(CONFIG_SH4)+=-m4 +else + CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a-nofpu + CPU_CFLAGS-$(CONFIG_SH4)+=-m4-nofpu +endif +endif + +ifeq ($(TARGET_ARCH),sh64) + OPTIMIZATION+=-fstrict-aliasing + CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN):=-Wl,-EL + CPU_LDFLAGS-$(ARCH_BIG_ENDIAN):=-Wl,-EB + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN):=-ml + CPU_CFLAGS-$(ARCH_BIG_ENDIAN):=-mb + CPU_CFLAGS-$(CONFIG_SH5)+=-m5-32media +endif + +ifeq ($(TARGET_ARCH),h8300) + SYMBOL_PREFIX=_ + CPU_LDFLAGS-$(CONFIG_H8300H)+= -Wl,-ms8300h + CPU_LDFLAGS-$(CONFIG_H8S) += -Wl,-ms8300s + CPU_CFLAGS-$(CONFIG_H8300H) += -mh -mint32 + CPU_CFLAGS-$(CONFIG_H8S) += -ms -mint32 +endif + +ifeq ($(TARGET_ARCH),cris) + CPU_LDFLAGS-$(CONFIG_CRIS)+=-Wl,-mcrislinux + CPU_LDFLAGS-$(CONFIG_CRISV32)+=-Wl,-mcrislinux + CPU_CFLAGS-$(CONFIG_CRIS)+=-mlinux + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif + +ifeq ($(TARGET_ARCH),m68k) + # -fPIC is only supported for 68020 and above. It is not supported + # for 68000, 68010, or Coldfire. + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif + +ifeq ($(TARGET_ARCH),powerpc) +# PowerPC can hold 8192 entries in its GOT with -fpic which is more than +# enough. Therefore use -fpic which will reduce code size and generates +# faster code. + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie + PPC_HAS_REL16:=$(shell echo -e "\t.text\n\taddis 11,30,_GLOBAL_OFFSET_TABLE_-.@ha" | $(CC) -c -x assembler -o /dev/null - 2> /dev/null && echo -n y || echo -n n) + CPU_CFLAGS-$(PPC_HAS_REL16)+= -DHAVE_ASM_PPC_REL16 + CPU_CFLAGS-$(CONFIG_E500) += "-D__NO_MATH_INLINES" + +endif + +ifeq ($(TARGET_ARCH),bfin) + SYMBOL_PREFIX=_ +ifeq ($(UCLIBC_FORMAT_FDPIC_ELF),y) + CPU_CFLAGS-y:=-mfdpic + CPU_LDFLAGS-y += -Wl,-melf32bfinfd + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) + PICFLAG := -mleaf-id-shared-library +endif +endif + +ifeq ($(TARGET_ARCH),frv) + CPU_LDFLAGS-$(CONFIG_FRV)+=-Wl,-melf32frvfd + # Using -pie causes the program to have an interpreter, which is + # forbidden, so we must make do with -shared. Unfortunately, + # -shared by itself would get us global function descriptors + # and calls through PLTs, dynamic resolution of symbols, etc, + # which would break as well, but -Bsymbolic comes to the rescue. + export LDPIEFLAG:=-Wl,-shared -Wl,-Bsymbolic + UCLIBC_LDSO=ld.so.1 +endif + +ifeq ($(strip $(TARGET_ARCH)),avr32) + CPU_CFLAGS-$(CONFIG_AVR32_AP7) += -march=ap + CPU_CFLAGS-$(CONFIG_LINKRELAX) += -mrelax + CPU_LDFLAGS-$(CONFIG_LINKRELAX) += --relax +endif + +ifeq ($(TARGET_ARCH),i960) + SYMBOL_PREFIX=_ +endif + +ifeq ($(TARGET_ARCH),microblaze) + SYMBOL_PREFIX=_ +endif + +ifeq ($(TARGET_ARCH),v850) + SYMBOL_PREFIX=_ +endif + +# Keep the check_gcc from being needlessly executed +ifndef PIEFLAG +ifneq ($(UCLIBC_BUILD_PIE),y) +export PIEFLAG:= +else +export PIEFLAG:=$(call check_gcc,$(PIEFLAG_NAME),$(PICFLAG)) +endif +endif +# We need to keep track of both the CC PIE flag (above) as +# well as the LD PIE flag (below) because we can't rely on +# gcc passing -pie if we used -fPIE +ifndef LDPIEFLAG +ifneq ($(UCLIBC_BUILD_PIE),y) +export LDPIEFLAG:= +else +export LDPIEFLAG:=$(shell $(LD) --help 2>/dev/null | grep -q -- -pie && echo "-Wl,-pie") +endif +endif + +# Check for AS_NEEDED support in linker script (binutils>=2.16.1 has it) +ifndef ASNEEDED +export ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -q -- --as-needed && echo "AS_NEEDED ( $(UCLIBC_LDSO) )" || echo "$(UCLIBC_LDSO)") +endif + +# Add a bunch of extra pedantic annoyingly strict checks +XWARNINGS=$(subst ",, $(strip $(WARNINGS))) -Wstrict-prototypes -fno-strict-aliasing +ifeq ($(EXTRA_WARNINGS),y) +XWARNINGS+=-Wnested-externs -Wshadow -Wmissing-noreturn -Wmissing-format-attribute -Wformat=2 +XWARNINGS+=-Wmissing-prototypes -Wmissing-declarations +XWARNINGS+=-Wnonnull -Wundef +# works only w/ gcc-3.4 and up, can't be checked for gcc-3.x w/ check_gcc() +#XWARNINGS+=-Wdeclaration-after-statement +endif +XARCH_CFLAGS=$(subst ",, $(strip $(ARCH_CFLAGS))) +CPU_CFLAGS=$(subst ",, $(strip $(CPU_CFLAGS-y))) + +SSP_DISABLE_FLAGS ?= $(call check_gcc,-fno-stack-protector,) +ifeq ($(UCLIBC_BUILD_SSP),y) +SSP_CFLAGS := $(call check_gcc,-fno-stack-protector-all,) +SSP_CFLAGS += $(call check_gcc,-fstack-protector,) +SSP_ALL_CFLAGS ?= $(call check_gcc,-fstack-protector-all,) +else +SSP_CFLAGS := $(SSP_DISABLE_FLAGS) +endif + +NOSTDLIB_CFLAGS:=$(call check_gcc,-nostdlib,) +# Some nice CFLAGS to work with +CFLAGS := -include $(top_builddir)include/libc-symbols.h \ + $(XWARNINGS) $(CPU_CFLAGS) $(SSP_CFLAGS) \ + -fno-builtin -nostdinc -I$(top_builddir)include -I. \ + -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) + +# Make sure that we can be built with non-C99 compilers, too. +# Use __\1__ instead. +CFLAGS += $(call check_gcc,-fno-asm,) +ifneq ($(strip $(UCLIBC_EXTRA_CFLAGS)),"") +CFLAGS += $(subst ",, $(UCLIBC_EXTRA_CFLAGS)) +endif + +LDADD_LIBFLOAT= +ifeq ($(UCLIBC_HAS_SOFT_FLOAT),y) +# If -msoft-float isn't supported, we want an error anyway. +# Hmm... might need to revisit this for arm since it has 2 different +# soft float encodings. +ifneq ($(TARGET_ARCH),nios) +ifneq ($(TARGET_ARCH),nios2) +ifneq ($(TARGET_ARCH),sh) +CFLAGS += -msoft-float +endif +endif +endif +ifeq ($(TARGET_ARCH),arm) +# No longer needed with current toolchains, but leave it here for now. +# If anyone is actually still using gcc 2.95 (say), they can uncomment it. +# LDADD_LIBFLOAT=-lfloat +endif +endif + +# Please let us see private headers' parts +CFLAGS += -DUCLIBC_INTERNAL + +# We need this to be checked within libc-symbols.h +ifneq ($(HAVE_SHARED),y) +CFLAGS += -DSTATIC +endif + +CFLAGS += $(call check_gcc,-std=gnu99,) + +LDFLAGS_NOSTRIP:=$(CPU_LDFLAGS-y) -Wl,-shared \ + -Wl,--warn-common -Wl,--warn-once -Wl,-z,combreloc +# binutils-2.16.1 warns about ignored sections, 2.16.91.0.3 and newer are ok +#LDFLAGS_NOSTRIP+=$(call check_ld,--gc-sections) + +ifeq ($(UCLIBC_BUILD_RELRO),y) +LDFLAGS_NOSTRIP+=-Wl,-z,relro +endif + +ifeq ($(UCLIBC_BUILD_NOW),y) +LDFLAGS_NOSTRIP+=-Wl,-z,now +endif + +ifeq ($(LDSO_GNU_HASH_SUPPORT),y) +# Be sure that binutils support it +LDFLAGS_GNUHASH:=$(call check_ld,--hash-style=gnu) +ifeq ($(LDFLAGS_GNUHASH),) +$(error Your binutils don't support --hash-style option, while you want to use it) +else +LDFLAGS_NOSTRIP += -Wl,$(LDFLAGS_GNUHASH) +endif +endif + +LDFLAGS:=$(LDFLAGS_NOSTRIP) -Wl,-z,defs +ifeq ($(DODEBUG),y) +CFLAGS += -O0 -g3 +else +CFLAGS += $(OPTIMIZATION) $(XARCH_CFLAGS) +endif +ifeq ($(DOSTRIP),y) +LDFLAGS += -Wl,-s +else +STRIPTOOL := true -Stripping_disabled +endif + +ifeq ($(DOMULTI),y) +# we try to compile all sources at once into an object (IMA), but +# gcc-3.3.x does not support it +# gcc-3.4.x supports it, but does not need and support --combine. though fails on many sources +# gcc-4.0.x supports it, supports the --combine flag, but does not need it +# gcc-4.1(200506xx) supports it, but needs the --combine flag, else libs are useless +ifeq ($(GCC_MAJOR_VER),3) +DOMULTI:=n +else +CFLAGS+=$(call check_gcc,--combine,) +endif +else +DOMULTI:=n +endif + +ifneq ($(strip $(UCLIBC_EXTRA_LDFLAGS)),"") +LDFLAGS += $(subst ",, $(UCLIBC_EXTRA_LDFLAGS)) +endif + +ifeq ($(UCLIBC_HAS_THREADS),y) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) + PTNAME := nptl +else +ifeq ($(LINUXTHREADS_OLD),y) + PTNAME := linuxthreads.old +else + PTNAME := linuxthreads +endif +endif +PTDIR := $(top_builddir)libpthread/$(PTNAME) +# set up system dependencies include dirs (NOTE: order matters!) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +PTINC:= -I$(PTDIR) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(PTDIR)/sysdeps/pthread \ + -I$(PTDIR)/sysdeps/pthread/bits \ + -I$(PTDIR)/sysdeps/generic \ + -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) \ + -I$(top_srcdir)ldso/include +# +# Test for TLS if NPTL support was selected. +# +GCC_HAS_TLS=$(shell \ + echo "extern __thread int foo;" | $(CC) -o /dev/null -S -xc - 2>&1) +ifneq ($(GCC_HAS_TLS),) +gcc_tls_test_fail: + @echo "####"; + @echo "#### Your compiler does not support TLS and you are trying to build uClibc"; + @echo "#### with NPTL support. Upgrade your binutils and gcc to versions which"; + @echo "#### support TLS for your architecture. Do not contact uClibc maintainers"; + @echo "#### about this problem."; + @echo "####"; + @echo "#### Exiting..."; + @echo "####"; + @exit 1; +endif +else +PTINC := \ + -I$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(PTDIR)/sysdeps/pthread \ + -I$(PTDIR) \ + -I$(top_builddir)libpthread +endif +CFLAGS+=$(PTINC) +else + PTNAME := + PTINC := +endif +CFLAGS += -I$(KERNEL_HEADERS) + +#CFLAGS += -iwithprefix include-fixed -iwithprefix include +CC_IPREFIX:=$(shell $(CC) --print-file-name=include) +CFLAGS += -I$(dir $(CC_IPREFIX))/include-fixed -I$(CC_IPREFIX) + +ifneq ($(DOASSERTS),y) +CFLAGS+=-DNDEBUG +endif + +ifeq ($(SYMBOL_PREFIX),_) +CFLAGS+=-D__UCLIBC_UNDERSCORES__ +endif + +# Keep the check_as from being needlessly executed +ifndef ASFLAGS_NOEXEC +ifeq ($(UCLIBC_BUILD_NOEXECSTACK),y) +export ASFLAGS_NOEXEC := $(call check_as,--noexecstack) +else +export ASFLAGS_NOEXEC := +endif +endif +ASFLAGS = $(ASFLAGS_NOEXEC) + +LIBGCC_CFLAGS ?= $(CFLAGS) $(CPU_CFLAGS-y) +LIBGCC:=$(shell $(CC) $(LIBGCC_CFLAGS) -print-libgcc-file-name) +LIBGCC_DIR:=$(dir $(LIBGCC)) + +# moved from libpthread/linuxthreads +ifeq ($(UCLIBC_CTOR_DTOR),y) +SHARED_START_FILES:=$(top_builddir)lib/crti.o $(LIBGCC_DIR)crtbeginS.o +SHARED_END_FILES:=$(LIBGCC_DIR)crtendS.o $(top_builddir)lib/crtn.o +endif + +LOCAL_INSTALL_PATH := install_dir diff --git a/TODO b/TODO new file mode 100644 index 0000000..fa5a9bb --- /dev/null +++ b/TODO @@ -0,0 +1,179 @@ +TODO list for every uClibc release: +------------------------------------------------- + *) Test cris, i386, mips, mipsel, sh, x86_64, arm, armeb, and powerpc + with the latest LTP testsuite. Fix any regressions and post LTP + testsuite results for each architecture on uclibc.org. + *) Audit header files. Remove prototypes for all functions that + are not supported -- especially needed for the libm headers. + *) Audit header files. When options are disabled, also disable + them in the include files as well by checking for the proper + define from include/bits/uClibc_config.h (pulled in from features.h) + + + +General release feature sets: +------------------------------------------------- +.29 will be mostly as-is +.30 will be the NPTL merge +.31 for the no-kernel-headers fix, etc, etc. + + + +TODO list for the uClibc 0.9.29 release: +------------------------------------------------- + *) as many of the arch-specific issues as possible + *) Remove N instances of libc_hidden_proto() from uClibc internals. + Instead add internal only header(s) defining all hidden prototypes. + This will avoid clutter and guarantee prototype consistancy. + *) The __is*_l() functions were all removed, such that we now only export + the is*_l() functions (no prefix). Before, we had the prefixed versions + for use by libstdc++ and weak versions without prefixes exported because + those functions belong to no std (unless you call glibc a std). This should + be fixed. Similar problems likely were created elsewhere. + *) misc stdio bugs: + http://bugs.uclibc.org/view.php?id=420 + http://bugs.uclibc.org/view.php?id=539 + *) bug in getopt handling: + http://bugs.uclibc.org/view.php?id=61 + http://www.uclibc.org/lists/uclibc/2006-January/013851.html + *) Should integrate test subdir better ... need to propagate CPU + CFLAGS/LDFLAGS to the build/link for target binaries so that when we have + a multilib toolchain, the proper ABI is selected. + + +TODO list for the uClibc 1.0.0 release: +------------------------------------------------- + *) glob / fnmatch tests fail + *) regex should pass AT&T conformance tests + *) Finish hiding uClibc internal symbols from our exported namespace + *) Add system for generating minimal system call asm wrappers that abuse + the C ABI to minimize amount of register/stack manipulation + *) Explicity add some sortof CONFIG_LINUX_2_2_ABI, CONFIG_LINUX_2_4_ABI + and CONFIG_LINUX_2_6_ABI type options, rather than having the abi + depend on the selected set of kernel headers. This will likely also + require that we provide a set of kernel headers (probably a derivitive + of Mazur's linux-libc-headers) that can supplies the 2.2, 2.4, and 2.6 + kernel abi. + *) Documentation updates: + *) Write a uClibc HOWTO document + *) Update README document + *) Update INSTALL document + *) Update docs/Glibc_vs_uClibc_Differences.txt document + and fully document all differences between the feature + set of uClibc and glibc. + *) Update docs/uClibc_vs_SuSv3.txt document + *) Update docs/threads.txt document + *) Write man pages for ldd and ldconfig utility binaries + *) Implement some mechanism (perhaps encoded in the .so name, + perhaps using an abi tag magically embedded into each object) + for flagging config options that break the ABI. Options + such as UCLIBC_HAS_SOFT_FLOAT, UCLIBC_HAS_THREADS, UCLIBC_HAS_LOCALE, + and perhaps others (finalize list) produce a lib with a differing + ABI. Make it so apps cannot use an ABI mis-matched uClibc. + This is most easily done using symbol versioning... + *) Implement the long double versions of math funcs + using wrappers on top of the double versions (size / precision + trade off where size clearly wins). + *) Make all small objects (>~50 bytes) into either inlines or + into a static library + *) Cleanup / rewrite sysconf.c. It should get some information + from ldso (such as HZ). Other stuff it currently just makes + up, which is obviously wrong. Also bits/uClibc_clk_tck.h + needs to be updated at the same time to get proper HZ values. + *) poll emulation using select() for old 2.0.x uClinux kernels + in libc/sysdeps/linux/common/poll.c fails some python self-tests. + Of course, modern systems using the actuall poll() syscall work fine. + *) Cleanup/scrub all the Makefile copyright junk + *) Fix dlopen, for both static and dynamic cases, and make it + fully comply with SuSv3 + + +TODO list for AFTER the uClibc 1.0.0 release: +------------------------------------------------- + *) Add support for 64bit time (to deal withhttp://2038bug.com/): + date -s 011903142038 sets epoch to roll over in a few seconds (2^31) + *) Add support for Linux 2.6.x fast vsyscalls + *) Enable pristine source tree builds + *) Fix regex so it isn't so stinking big + *) Fix glob so it isn't so stinking big + *) run 'nm -D --size-sort -t d libuClibc-0.9.26.so' and work on the + biggest things (i.e. stuff at the end of the list) to make + them smaller. + + + +Arch specific TODO: +------------------------------------------------- + alpha: + ldso is not implemented + arm: + update crt1 code again for nommu (http://bugs.uclibc.org/view.php?id=538) + recruit jbowler and integrate thumb support + frv: + needs to be updated for the new ldso changes and unification of the + uClibc_main funcs (__uClibc_start_main doesnt exist anymore) + hppa: + errno.c test segfaults causes segfault in clone.S (seems to be in glibc too) + i386: + add support for fast system calls + ia64: + ldso is not implemented + m68k: + ldso lazy relocation doesnt work + sh64: + ldso is reasonably broken, presently requiring additional + coaxing/threatening. + sparc: + need a sigaction.c since common one doesnt work (signal tests) + ldso needs to be updated since it's totally broken atm + vax: + pthread support, linktime warning support (implies GAS patches), + general touchups, testing, ldso. + + +----------------------------------------------------------------------------- +Manuel's todo: + + 1) Little things that need fixing: + ---------------------------------- + a) Fix bug in *printf: outdigit precison bug + b) Check that gnu/bsd extension members tm_gmtoff and tm_zone in struct tm + are respected where they should be. + c) Implement the obstack printf funcs for glibc compat. + d) Implement glibc 'a' flag for scanf string conversions. + e) Allow use of the older non-table-based ctype functions when using + stub locale support. (smaller) + f) __drand48_iterate should be void + g) alphasort vs. versionsort. The former seems to be SVID, the latter GNU + i.e. reverse to what we currently do. The latter is unimplemented. + h) ponder removal/configs to turn off: __xpg_*, bsd_signal, dysize, + getw/putw, utimes, + + 2) Additional str{f|p}time issues. + ---------------------------------- + a) Spacing issue wrt strptime. + b) Support locale specific alternate digits. (data is in place) + c) Support locale era in year designations. (data is in place) + d) Deal with mb format string issues in strftime. + e) Implement wcsftime. + + 3) Other locale issues (my implementation): + ------------------------------------------- + a) Do a little more clean up of ctype and wctype. + b) Rework of the locale data organization to make using locales reasonable + when staticly linking. (mmap) + c) Rewrite the locale data generation tools to process the text specifications + rather than relying on glibc. + d) Adapt regex lib to use my collation data and add the necessary collating + item tables to support SUSv3 required features. + e) transliteration of unsupported wchars in 8-bit locales (like glibc). + f) Support ISO/IEC 14652 draft locale extensions (LC_PAPER, etc). + g) Implement strfrom. + h) Shift-state codeset locale support? + + 4) Misc: + -------- + a) Port uClibc to other OSs (including elks), or even bare metal (libgloss). + b) Write a space-efficient gettext substitute, to avoid storing large amounts + of redundant data. + diff --git a/docs/Glibc_vs_uClibc_Differences.txt b/docs/Glibc_vs_uClibc_Differences.txt new file mode 100644 index 0000000..4ed2463 --- /dev/null +++ b/docs/Glibc_vs_uClibc_Differences.txt @@ -0,0 +1,215 @@ + uClibc and Glibc are not the same -- there are a number of differences which +may or may not cause you problems. This document attempts to list these +differences and, when completed, will contain a full list of all relevant +differences. + + +1) uClibc is smaller than glibc. We attempt to maintain a glibc compatible +interface, allowing applications that compile with glibc to easily compile with +uClibc. However, we do not include _everything_ that glibc includes, and +therefore some applications may not compile. If this happens to you, please +report the failure to the uclibc mailing list, with detailed error messages. + +2) uClibc is much more configurable then glibc. This means that a developer +may have compiled uClibc in such a way that significant amounts of +functionality have been omitted. + +3) uClibc does not even attempt to ensure binary compatibility across releases. +When a new version of uClibc is released, you may or may not need to recompile +all your binaries. + +4) malloc(0) in glibc returns a valid pointer to something(!?!?) while in +uClibc calling malloc(0) returns a NULL. The behavior of malloc(0) is listed +as implementation-defined by SuSv3, so both libraries are equally correct. +This difference also applies to realloc(NULL, 0). I personally feel glibc's +behavior is not particularly safe. To enable glibc behavior, one has to +explicitly enable the MALLOC_GLIBC_COMPAT option. + +4.1) glibc's malloc() implementation has behavior that is tunable via the +MALLOC_CHECK_ environment variable. This is primarily used to provide extra +malloc debugging features. These extended malloc debugging features are not +available within uClibc. There are many good malloc debugging libraries +available for Linux (dmalloc, electric fence, valgrind, etc) that work much +better than the glibc extended malloc debugging. So our omitting this +functionality from uClibc is not a great loss. + +5) uClibc does not provide a database library (libdb). + +6) uClibc does not support NSS (/lib/libnss_*), which allows glibc to easily +support various methods of authentication and DNS resolution. uClibc only +supports flat password files and shadow password files for storing +authentication information. If you need something more complex than this, +you can compile and install pam. + +7) uClibc's libresolv is only a stub. Some, but not all of the functionality +provided by glibc's libresolv is provided internal to uClibc. Other functions +are not at all implemented. + +8) libnsl provides support for Network Information Service (NIS) which was +originally called "Yellow Pages" or "YP", which is an extension of RPC invented +by Sun to share Unix password files over the network. I personally think NIS +is an evil abomination and should not be used. These days, using ldap is much +more effective mechanism for doing the same thing. uClibc provides a stub +libnsl, but has no actual support for Network Information Service (NIS). +We therefore, also do not provide any of the headers files provided by glibc +under /usr/include/rpcsvc. + +9) uClibc's locale support is not 100% complete yet. We are working on it. + +10) uClibc's math library only supports long double as inlines, and even +then the long double support is quite limited. Also, very few of the +float math functions are implemented. Stick with double and you should +be just fine. + +11) uClibc's libcrypt does not support the reentrant crypt_r, setkey_r and +encrypt_r, since these are not required by SuSv3. + +12) uClibc directly uses kernel types to define most opaque data types. + +13) uClibc directly uses the linux kernel's arch specific 'stuct stat'. + +14) uClibc's librt library currently lacks all aio routines, all clock + routines, and all shm routines (only the timer routines and the mq + routines are implemented). + + + + + +****************************** Manuel's Notes ****************************** + +Some general comments... + +The intended target for all my uClibc code is ANSI/ISO C99 and SUSv3 +compliance. While some glibc extensions are present, many will eventually +be configurable. Also, even when present, the glibc-like extensions may +differ slightly or be more restrictive than the native glibc counterparts. +They are primarily meant to be porting _aides_ and not necessarily +drop-in replacements. + +Now for some details... + +time functions +-------------- +1) Leap seconds are not supported. +2) /etc/timezone and the whole zoneinfo directory tree are not supported. + To set the timezone, set the TZ environment variable as specified in + http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html + or you may also create an /etc/TZ file of a single line, ending with a + newline, containing the TZ setting. For example + echo CST6CDT > /etc/TZ +3) Currently, locale specific eras and alternate digits are not supported. + They are on my TODO list. + +wide char support +----------------- +1) The only multibyte encoding currently supported is UTF-8. The various + ISO-8859-* encodings are (optionally) supported. The internal + representation of wchar's is assumed to be 31 bit unicode values in + native endian representation. Also, the underlying char encoding is + assumed to match ASCII in the range 0-0x7f. +2) In the next iteration of locale support, I plan to add support for + (at least some) other multibyte encodings. + +locale support +-------------- +1) The target for support is SUSv3 locale functionality. While nl_langinfo + has been extended, similar to glibc, it only returns values for related + locale entries. +2) Currently, all SUSv3 libc locale functionality should be implemented + except for wcsftime and collating item support in regex. + +stdio +----- +1) Conversion of large magnitude floating-point values by printf suffers a loss + of precision due to the algorithm used. +2) uClibc's printf is much stricter than glibcs, especially regarding positional + args. The entire format string is parsed first and an error is returned if + a problem is detected. In locales other than C, the format string is checked + to be a valid multibyte sequence as well. Also, currently at most 10 positional + args are allowed (although this is configurable). +3) BUFSIZ is configurable, but no attempt is made at automatic tuning of internal + buffer sizes for stdio streams. In fact, the stdio code in general sacrifices + sophistication/performace for minimal size. +4) uClibc allows glibc-like custom printf functions. However, while not + currently checked, the specifier must be <= 0x7f. +5) uClibc allows glibc-like custom streams. However, no in-buffer seeking is + done. +6) The functions fcloseall() and __fpending() can behave differently than their + glibc counterparts. +7) uClibc's setvbuf is more restrictive about when it can be called than glibc's + is. The standards specify that setvbuf must occur before any other operations + take place on the stream. +8) Right now, %m is not handled properly by printf when the format uses positional + args. +9) The FILEs created by glibc's fmemopen(), open_memstream(), and fopencookie() + are not capable of wide orientation. The corresponding uClibc routines do + not have this limitation. +10) For scanf, the C99 standard states "The fscanf function returns the value of + the macro EOF if an input failure occurs before any conversion." But glibc's + scanf does not respect conversions for which assignment was surpressed, even + though the standard states that the value is converted but not stored. + +glibc bugs that Ulrich Drepper has refused to acknowledge or comment on + ( http://sources.redhat.com/ml/libc-alpha/2003-09/ ) +----------------------------------------------------------------------- +1) The C99 standard says that for printf, a %s conversion makes no special + provisions for multibyte characters. SUSv3 is even more clear, stating + that bytes are written and a specified precision is in bytes. Yet glibc + treats the arg as a multibyte string when a precision is specified and + not otherwise. +2) Both C99 and C89 state that the %c conversion for scanf reads the exact + number of bytes specified by the optional field width (or 1 if not specified). + uClibc complies with the standard. There is an argument that perhaps the + specified width should be treated as an upper bound, based on some historical + use. However, such behavior should be mentioned in the Conformance document. +3) glibc's scanf is broken regarding some numeric patterns. Some invalid + strings are accepted as valid ("0x.p", "1e", digit grouped strings). + In spite of my posting examples clearly illustrating the bugs, they remain + unacknowledged by the glibc developers. +4) glibc's scanf seems to require a 'p' exponent for hexadecimal float strings. + According to the standard, this is optional. +5) C99 requires that once an EOF is encountered, the stream should be treated + as if at end-of-file even if more data becomes available. Further reading + can be attempted by clearing the EOF flag though, via clearerr() or a file + positioning function. For details concerning the original change, see + Defect Report #141. glibc is currently non-compliant, and the developers + did not comment when I asked for their official position on this issue. +6) glibc's collation routines and/or localedef are broken regarding implicit + and explicit UNDEFINED rules. + +More to follow as I think of it... + + + + +Profiling: +------------------------------------------------------------------- + +uClibc no longer supports 'gcc -fprofile-arcs -pg' style profiling, which +causes your application to generate a 'gmon.out' file that can then be analyzed +by 'gprof'. Not only does this require explicit extra support in uClibc, it +requires that you rebuild everything with profiling support. There is both a +size and performance penalty to profiling your applications this way, as well +as Heisenberg effects, where the act of measuring changes what is measured. + +There exist a number of less invasive alternatives that do not require you to +specially instrument your application, and recompile and relink everything. + +The OProfile system-wide profiler is an excellent alternative: + http://oprofile.sourceforge.net/ + +Many people have had good results using the combination of Valgrind +to generate profiling information and KCachegrind for analysis: + http://developer.kde.org/~sewardj/ + http://kcachegrind.sourceforge.net/ + +Prospect is another alternative based on OProfile: + http://prospect.sourceforge.net/ + +And the Linux Trace Toolkit (LTT) is also a fine tool: + http://www.opersys.com/LTT/ + +FunctionCheck: + http://www710.univ-lyon1.fr/~yperret/fnccheck/ + diff --git a/docs/PORTING b/docs/PORTING new file mode 100644 index 0000000..cadb323 --- /dev/null +++ b/docs/PORTING @@ -0,0 +1,138 @@ +Some notes to help future porters. Replace 'ARCH' with whatever arch +you are hacking on. + +==================== +=== Config Files === +==================== +- create extra/Configs/Config.ARCH + See the other arch files for some good examples. powerpc/sparc/alpha + should be pretty simple templates. +- add ARCH to the 'Target Architecture' list in extra/Configs/Config.in +- Initially you will want to disable shared libraries, since making + the shared library loader work requires you first have basic architecture + support working. Thus you should add ARCH_HAS_NO_SHARED and + ARCH_HAS_NO_LDSO to Config.ARCH's TARGET_ARCH + +==================== +=== libc sysdeps === +==================== +(note: if glibc has already been ported to your arch, you can usually just + copy a lot of files from them rather than coding from scratch) +- create libc/sysdeps/linux/ARCH +- copy Makefile and Makefile.arch from libc/sysdeps/linux/i386/ +- set CSRC and SSRC to nothing in Makefile.arch for now + +- create crt1.S which defines the _start function ... you will probably want + to clear the frame pointer to make gdb happy, and then you will want to call + the funcion __uClibc_main() which takes these parameters: + __uClibc_main(main(), argc, argv, _init(), _fini()) + Initially if you wish to make things easier on yourself, you can disable the + UCLIBC_CTOR_DTOR option and just set the init/fini arguments to NULL. + glibc generally stores this function in libc/sysdeps/ARCH/elf/start.S + +- create these additional files in ARCH/bits/ + + (template versions can be found in common/bits/ for you to tweak) + endian.h fcntl.h setjmp.h stackinfo.h uClibc_arch_features.h wordsize.h + + kernel_types.h should be created based upon linux asm-ARCH/posix_types.h + + copy linux asm-ARCH/stat.h to bits/kernel_stat.h + + create syscalls.h based upon linux's unistd.h / glibc's sysdeps.h ... really + you just want to define the _syscall[0-6] macros. It is important that + these syscalls should be PIC safe (or you should provide a PIC and non-PIC + version) if you wish to properly support shared libraries. + +- at this point, you should have enough to generate a working HELLO WORLD + static binary (see test/silly/*.c files) + +- if you want UCLIBC_CTOR_DTOR support, you will need to create crti.S and + crtn.S files which define function prologues/epilogues. + +- for a more stable static port, you will need to create these files (and + update the Makefile.arch values accordingly) + __longjmp bsd-_setjmp bsd-setjmp brk clone setjmp syscall vfork + usually these are written in assembler, but you may be able to cheat and + write them in C ... see other ports for more information + +==================== +=== pthread deps === +==================== + +TODO: nptl / linuxthreads / linuxthreads.old + +==================== +=== ldso sysdeps === +==================== +- elf.h - presumably you've already taught binutils all about the random ELF + relocations your arch needs, so now you need to make sure the defines exist + for uClibc. make sure the EM_### define exists and all of the R_###_### + reloc defines. + +- enable ldso/shared options in your extra/Configs/Config.ARCH file +- you will need to create the following files in ldso/ldso/ARCH/ + dl-debug.h dl-startup.h dl-syscalls.h dl-sysdep.h elfinterp.c resolve.S + +- dl-debug.h: define string versions of all the relocations of your arch in the + _dl_reltypes_tab array ... the index should match the actual reloc type, so + if the value of say R_X86_64_PC16 is 13, then "R_X86_64_PC16" better be at + index 13 of the array + +- dl-startup.h: + - define the _start function which should call _dl_start which takes just one + parameter ... a pointer to argc (usually on the stack) + glibc stores this function in libc/sysdeps/ARCH/dl-machine.h as RTLD_START + - define the GET_ARGV() macro which calculates the value of argv based upon + the parameter passed to _dl_start (usually it's simply just ARGS+1) + - define PERFORM_BOOTSTRAP_RELOC() macro which will handle just the relocs + that the ldso itself will generate + +- dl-syscalls.h: + if you wrote your bits/syscalls.h file correctly in the libc step above, you + can simply copy this file from another arch and be done ... otherwise you + will have to define the syscall[0-6] macros again, but this time setting + _dl_errno instead of just errno + +- dl-sysdep.h: + misc cruft goes in here ... you want to: + - either define or undefine ELF_USES_RELOCA + - define the INIT_GOT macro + - define MAGIC1 to the EM_### value your ELF arch uses + - define ELF_TARGET to a string name for your arch + - define the do_rem() macro + - define misc ALIGN macro's + - define elf_machine_type_class() macro + - define the inline functions elf_machine_dynamic, elf_machine_load_address, + and elf_machine_relative + glibc stores a bunch of these values in libc/sysdeps/ARCH/dl-machine.h + +- elfinterp.c: + define all the relocation functions ... it's best if you just copy from + another arch which uses the same type of relocations (REL or RELA) and + start from there. + +- resolve.S: + front end of lazy relocation ... define the _dl_linux_resolve symbol which + is called by a PLT entry which has yet to be setup ... you will want to: + - set up arguments for _dl_linux_resolver() + - call _dl_linux_resolver() + - clean up after call + - jump to function address now stored in PLT + glibc stores this function in libc/sysdeps/ARCH/dl-trampoline.S + +- utils/ldd.c - if you want support for ldso cache files (spoiler: you do), + then you'll need to teach ldd a little. generally, the fallback code + should be smart and "just work", but you should be explicit. just pop + it open and add an appropriate ifdef for your arch and set MATCH_MACHINE() + and ELFCLASSM. there are plenty examples and you're (hopefully) smart. + +==================== +=== Misc Cruft === +==================== +- utils/readelf.c - not really needed generally speaking, but might as well + add your arch to the giant EM_* list (describe_elf_hdr) + +- MAINTAINERS - presumably you're going to submit this code back to mainline + and since you're the only one who cares about this arch (right now), you + should add yourself to the toplevel MAINTAINERS file. do it. diff --git a/docs/man/ldconfig.8 b/docs/man/ldconfig.8 new file mode 100644 index 0000000..208d63d --- /dev/null +++ b/docs/man/ldconfig.8 @@ -0,0 +1,73 @@ +.TH LDCONFIG 8 2005-08-15 uClibc "Linux Programmer's Manual" +.SH NAME +ldconfig \- updates symlinks and cache for shared libraries +.SH SYNOPSIS +.B ldconfig +[ +.B -DvqnNX +] [ +.B -f conf +] [ +.B -C cache +] [ +.B -r root +] +.B dir ... +.br +.B ldconfig -l +[ +.B -Dv +] +.B lib ... +.br +.B ldconfig -p +.SH DESCRIPTION +.B ldconfig +creates the necessary links and cache to the most recent shared libraries +found in the directories specified on the command line, in the file +\fI/etc/ld.so.conf\fR, and in the default trusted directories (\fI/lib\fR and +\fI/usr/lib\fR). The cache is used by the run-time linker. +.B ldconfig +checks the header and file names of the libraries it encounters when +determining which versions should have their links updated. + +.B Note: +Some features may not exist depending on how uClibc was built +.SH OPTIONS +.TP +.B -C cache +use specified \fIcache\fR instead of default +.TP +.B -D +debug mode, do not update links +.TP +.B -f conf +use specified \fIconf\fR instead of default +.TP +.B -l +library mode, manually link libraries +.TP +.B -n +do not process standard trusted directories +.TP +.B -N +do not update the library cache +.TP +.B -p +print the current library cache +.TP +.B -q +quiet mode, do not print warnings you should actually be reading +.TP +.B -r root +chroot to \fIroot\fR before running +.TP +.B -v +verbose mode, print things as we go, and generally be annoying +.TP +.B -X +do not update the library links +.SH BUGS +Probably, make sure you complain when you find them: +.br +http://bugs.uclibc.org/ diff --git a/docs/man/ldd.1 b/docs/man/ldd.1 new file mode 100644 index 0000000..0b69f73 --- /dev/null +++ b/docs/man/ldd.1 @@ -0,0 +1,17 @@ +.TH LDD 1 2005-08-15 uClibc "Linux Programmer's Manual" +.SH NAME +ldd \- Print shared library dependencies +.SH SYNOPSIS +.B ldd +[ +.B OPTIONS +] +.B FILE ... +.SH DESCRIPTION +Prints shared library dependencies. +.SH OPTIONS +None actually, we lied about that part. +.SH BUGS +Probably, make sure you complain when you find them: +.br +http://bugs.uclibc.org/ diff --git a/docs/threads.txt b/docs/threads.txt new file mode 100644 index 0000000..182f1be --- /dev/null +++ b/docs/threads.txt @@ -0,0 +1,56 @@ +uClibc thread-safety analysis + +Things that are still known to be needed for thread safety: + + none + + + + +Things that might be nice, but are not required: + + getnetent_r + gethostent_r + getprotoent_r + getnetbyname_r + getnetbyaddr_r + + + + + +Functions that use static data and may still need locking: + + + -------------------------------------------------------------------- + + libc/inet/rpc/rpc_thread.c: + + __rpc_thread_variables is currently disabled, since thread + local storage seems to not be correctly specified as + weak functions. + + -------------------------------------------------------------------- + + unistd/getpass.c: + + static char buf[PWD_BUFFER_SIZE]; + + getpass <--- + + NOTE: This function returns a pointer to a static data structure. + This seems like it requires an _r version of this function. Glibc + does the same thing. Oops! So much for thread-safe glibc! + + -------------------------------------------------------------------- + + unistd/sysconf.c: + + static long int ret_vals[_UCLIBC_SYSCONF_NUM_VALID_ARGS]; + + find_or_add_in_table <--- + main <--- + + NOTE: I'm not sure if this needs to be made reentrant... + + -------------------------------------------------------------------- diff --git a/docs/uClibc_vs_SuSv3.txt b/docs/uClibc_vs_SuSv3.txt new file mode 100644 index 0000000..a5a9dcd --- /dev/null +++ b/docs/uClibc_vs_SuSv3.txt @@ -0,0 +1,105 @@ +uClibc attempts to fully (and rigorously) support "The Open Group Base +Specifications Issue 6 IEEE Std 1003.1, 2003 Edition" (aka SuSv3). However, as +with any standard, they sometimes require things that are either impossible or +are Completely Stupid(tm). Therefore, we cannot claim full compliance, and +there may be some areas of uClibc that differ from the requirements of this +specification. This document attempts to list these differences and, when +completed, will contain a full list of all relevant differences between uClibc +and the requirements of the SuSv3. + + +*) The uClibc setlocale() function is not threadsafe. + + SuSv3 states that "The locale state is common to all threads + within a process.". But it does not explicitly mention + setlocale() as a function that need not be thread-safe. + Making setlocale() threadsafe would require an absurd amount + of locking (i.e. inside each and every ctype call such as + isalpha()). Furthermore, we consider calling setlocale() + from N threads concurrently while using string functions to + be a terribly dumb thing to do. Therefore, we have decided + that setlocale() shall not be threadsafe. If you are + multi-threaded, and you wish to change the global locale + state, please take care to prevent all other threads from + using any locale or ctype functions until the setlocale() + call has finished. + + + + +---------------------------------------------------------------- +heukelum -- heukelum at freemail dot nl writes: + +Hi everyone, + +I think uClibc is a great project! And, since I found the file +docs/uClibc_vs_SuSv3.txt in the source tarball which mentioned only +fmtmsg as a missing function compared to the SUSv3, I got curious about +the length of the list denoted by "". So I built the +20040305-snapshot using allyesconfig, extracted the symbols from the +(dynamic) libraries, and compared that list to the SUSv3 header files... + +The largest source of omissions was the mathematical interface +(183/355), followed by optional interfaces (134/355). The result: only +38 non-mathematical interfaces are missing compared to the minimal +SUSv3! Naming only one function as missing was over-enthousiastic, but +the result was better than I anticipated. + +A compact list of omissions is appended. +I hope this was a helpful exercise ;) + +Greetings, + Alexander + +P.S. uClibc was compiled with thread support, but did not provide the +interfaces pthread_cleanup_push and pthread_cleanup_pop. + + + +Omissions from obligatory interfaces: +------------------------------------- +stdlib.h: _Exit, lcong48, lldiv, posix_openpt; + ecvt, fcvt +ndbm.h: [all=9] dbm_* +utmpx.h: [all=6] *utx* (but functions without "x" do exist!) +nl_types.h: [all] catclose, catgets, catopen +unistd.h: getwd, ualarm +inttypes.h: imaxdiv +fmtmsg.h: fmtmsg +string.h: strerror_r +setjmp.h: setsigjmp +monetary.h: strfmon +sys/select.h: pselect +sys/socket.h: sockatmark +sys/wait.h: waitid + + +Unimplemented optional interfaces: +---------------------------------- +trace.h: (depends on TRC) [all=50] posix_trace_* +pthread.h: (depends on THR) pthread_cleanup_{push,pop}; + pthread_attr_{g,s}etstack (depend on TSA TSS); + [7] pthread_barrier* (depend on BAR); + pthread_condattr_{g,s}et_clock (depend on CS); + pthread_getcpuclockid (depends on TCT); + pthread_mutex{,attr}_{g,s}etprioceiling (depend on TPP); + pthread_mutexattr_{g,s}etprotocol (depend on TPP|TPI); + pthread_rwlock_timed{rd,rw}lock (depend on TMO); + pthread_setschedprio (depends on TPS); + [5] pthread_spin_* (depend on SPI) +spawn.h: (depends on SPN) [all=21] posix_spawn* +aio.h: (depends on AIO) [all=8] aio_*, lio_* +stropts.h: (depends on XSR) isastream, {g,s}et{,p}msg, fattach, fdetach +sys/mman.h: posix_madvice (depends on ADV); posix_mem_offset, + posix_typed_mem_getinfo, posix_typed_mem_open (depend on TYM); + shm_open, shm_unlink (depend on SHM) +fcntl.h: posix_fallocate (depend on ADV) +signal.h: sigqueue (depends on RTS) + + +Unimplemented mathematical interfaces: +-------------------------------------- +math.h: [126] many +complex.h: [46] all, except cabs +fenv.h: [11] all +_______________________________________________ diff --git a/extra/Configs/Config.alpha b/extra/Configs/Config.alpha new file mode 100644 index 0000000..fd2d7a8 --- /dev/null +++ b/extra/Configs/Config.alpha @@ -0,0 +1,19 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "alpha" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + select ARCH_HAS_NO_LDSO + select UCLIBC_HAS_LFS + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.arm b/extra/Configs/Config.arm new file mode 100644 index 0000000..2b91a34 --- /dev/null +++ b/extra/Configs/Config.arm @@ -0,0 +1,136 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "arm" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +config ARCH_CFLAGS + string + +choice + prompt "Target ABI" + default CONFIG_ARM_OABI + help + If you choose "EABI" here, functions and constants required by the + ARM EABI will be built into the library. You should choose "EABI" + if your compiler uses the ARM EABI, in which case you will also + need a kernel supporting the EABI system call interface, or "OABI" + for a compiler using the old Linux ABI. + +config CONFIG_ARM_OABI + bool "OABI" + +config CONFIG_ARM_EABI + bool "EABI" + +endchoice + +config USE_BX + bool "Use BX in function return" + default y + depends on !CONFIG_GENERIC_ARM && !CONFIG_ARM610 && !CONFIG_ARM710 + help + Use BX instruction for THUMB aware architectures. + +choice + prompt "Target Processor Type" + default CONFIG_GENERIC_ARM + help + This is the processor type of your CPU. This information is used for + optimizing purposes. To build a library that will run on all ARMCPU + types (albeit not optimally fast), you can specify "Generic Arm" here. + If you pick anything other than "Generic Arm", there is no guarantee + that uClibc will even run on anything other than the selected + processor type. + + Here are the settings recommended for greatest speed: + - "Generic Arm" select this if your compiler is already setup to + optimize things properly, or if you want to run on pretty much + everything, or you just don't much care. + - For anything else, pick the ARM core type that best matches the + cpu you will be using on your device. + + If you don't know what to do, choose "Generic Arm". + +config CONFIG_GENERIC_ARM + bool "Generic Arm" + +config CONFIG_ARM610 + bool "Arm 610" + select ARCH_HAS_MMU + +config CONFIG_ARM710 + bool "Arm 710" + select ARCH_HAS_MMU + +config CONFIG_ARM7TDMI + bool "Arm 7TDMI" + select ARCH_HAS_NO_MMU + +config CONFIG_ARM720T + bool "Arm 720T" + select ARCH_HAS_MMU + +config CONFIG_ARM920T + bool "Arm 920T" + select ARCH_HAS_MMU + +config CONFIG_ARM922T + bool "Arm 922T" + select ARCH_HAS_MMU + +config CONFIG_ARM926T + bool "Arm 926T" + select ARCH_HAS_MMU + +config CONFIG_ARM10T + bool "Arm 10T" + select ARCH_HAS_MMU + +config CONFIG_ARM1136JF_S + bool "Arm 1136JF-S" + select ARCH_HAS_MMU + +config CONFIG_ARM1176JZ_S + bool "Arm 1176JZ-S" + select ARCH_HAS_MMU + +config CONFIG_ARM1176JZF_S + bool "Arm 1176JZF-S" + select ARCH_HAS_MMU + +config CONFIG_ARM_CORTEX_M3 + bool "Arm Cortex-M3" + select ARCH_HAS_NO_MMU + select USE_BX + +config CONFIG_ARM_CORTEX_M1 + bool "Arm Cortex-M1" + select ARCH_HAS_NO_MMU + select USE_BX + +config CONFIG_ARM_SA110 + bool "Intel StrongArm SA-110" + select ARCH_HAS_MMU + +config CONFIG_ARM_SA1100 + bool "Intel StrongArm SA-1100" + select ARCH_HAS_MMU + +config CONFIG_ARM_XSCALE + bool "Intel Xscale" + select ARCH_HAS_MMU + +config CONFIG_ARM_IWMMXT + bool "Intel Xscale With WMMX PXA27x" + select ARCH_HAS_MMU + +endchoice diff --git a/extra/Configs/Config.avr32 b/extra/Configs/Config.avr32 new file mode 100644 index 0000000..8d70e6e --- /dev/null +++ b/extra/Configs/Config.avr32 @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "avr32" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select FORCE_SHAREABLE_TEXT_SEGMENTS + +config ARCH_CFLAGS + string + +choice + prompt "Target CPU Type" + default CONFIG_AVR32_AP7 + +config CONFIG_AVR32_AP7 + bool "AVR32 AP7" + select ARCH_HAS_MMU + +endchoice + +config LINKRELAX + bool "Enable linker optimizations" + default y diff --git a/extra/Configs/Config.bfin b/extra/Configs/Config.bfin new file mode 100644 index 0000000..d5a9eae --- /dev/null +++ b/extra/Configs/Config.bfin @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "bfin" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select UCLIBC_HAS_LFS + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.cris b/extra/Configs/Config.cris new file mode 100644 index 0000000..b3811d1 --- /dev/null +++ b/extra/Configs/Config.cris @@ -0,0 +1,37 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "cris" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + +config ARCH_CFLAGS + string + +choice + prompt "Target Architecture Type" + default CONFIG_CRIS + help + This is the architecture type of your CPU. This information + is used for optimizing purposes. + + Possible settings: + - CRIS Generic support for Axis' CRIS architecture. + - CRISv32 Support for Axis' CRISv32 architecture. + +config CONFIG_CRIS + select ARCH_HAS_MMU + bool "CRIS" + +config CONFIG_CRISV32 + select ARCH_HAS_MMU + bool "CRISv32" + +endchoice diff --git a/extra/Configs/Config.e1 b/extra/Configs/Config.e1 new file mode 100644 index 0000000..144d9d3 --- /dev/null +++ b/extra/Configs/Config.e1 @@ -0,0 +1,23 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "e1" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_SHARED + +config ARCH_E1 + bool + default y + +config ARCH_CFLAGS + string + default "-mgnu-param" diff --git a/extra/Configs/Config.frv b/extra/Configs/Config.frv new file mode 100644 index 0000000..63bbfed --- /dev/null +++ b/extra/Configs/Config.frv @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "frv" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select UCLIBC_HAS_FPU + select ARCH_HAS_NO_MMU + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.h8300 b/extra/Configs/Config.h8300 new file mode 100644 index 0000000..262a0d2 --- /dev/null +++ b/extra/Configs/Config.h8300 @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "h8300" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + select ARCH_HAS_NO_MMU + +choice + prompt "Target Processor" + default CONFIG_H8300H + help + This is the processor type of your CPU. + +config CONFIG_H8300H + bool "H8300H" + +config CONFIG_H8S + bool "H8S (edosk2674)" + +endchoice + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.hppa b/extra/Configs/Config.hppa new file mode 100644 index 0000000..1c264a8 --- /dev/null +++ b/extra/Configs/Config.hppa @@ -0,0 +1,20 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "hppa" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_MMU + select HAS_NO_THREADS + select ARCH_HAS_NO_LDSO + select HAVE_NO_SSP + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.i386 b/extra/Configs/Config.i386 new file mode 100644 index 0000000..850ab8e --- /dev/null +++ b/extra/Configs/Config.i386 @@ -0,0 +1,102 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "i386" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + +choice + prompt "Target x86 Processor Family" + default CONFIG_GENERIC_386 + help + This is the processor type of your CPU. This information is used for + optimizing purposes. To build a library that will run on all x86 CPU + types (albeit not optimally fast), you can specify "386" here. If + you pick anything other than "386", there is no guarantee that uClibc + will even run on anything other than the selected processor type. + + Here are the settings recommended for greatest speed: + - "Generic 386" select this if your compiler is already setup to + optimize things properly. + - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI + 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels + will run on a 386 class machine. + - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or + SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. + - "586" for Intel Pentium and other generic Pentium CPUs + - "Pentium-MMX" for the Intel Pentium MMX. + - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. + - "Pentium-III" for the Intel Pentium III + and Celerons based on the Coppermine core. + - "Pentium-4" for the Intel Pentium 4. + - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). + - "Elan" for the AMD Elan. + - "Crusoe" for the Transmeta Crusoe series. + - "Winchip-C6" for original IDT Winchip. + - "Winchip-2/Winchip-2A/Winchip-3" for IDT Winchip CPUs + - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. + - "VIA C3-2 Nehemiah" model 9 and above. + + If you don't know what to do, choose "386". + +config CONFIG_GENERIC_386 + bool "Generic 386" + +config CONFIG_386 + bool "386" + +config CONFIG_486 + bool "486" + +config CONFIG_586 + bool "Pentium/586/K5/5x86/6x86/6x86MX" + +config CONFIG_586MMX + bool "Pentium-MMX" + +config CONFIG_686 + bool "Pentium-Pro" + +config CONFIG_PENTIUMII + bool "Celeron/Pentium-II" + +config CONFIG_PENTIUMIII + bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" + +config CONFIG_PENTIUM4 + bool "Pentium-4/Celeron(P4-based)/Xeon" + +config CONFIG_K6 + bool "K6/K6-II/K6-III" + +config CONFIG_K7 + bool "Athlon/Duron/K7" + +config CONFIG_ELAN + bool "Elan" + +config CONFIG_CRUSOE + bool "Crusoe" + +config CONFIG_WINCHIPC6 + bool "Winchip-C6" + +config CONFIG_WINCHIP2 + bool "Winchip-2/Winchip-2A/Winchip-3" + +config CONFIG_CYRIXIII + bool "CyrixIII/VIA-C3" + +config CONFIG_NEHEMIAH + bool "VIA C3-2 (Nehemiah)" + +endchoice diff --git a/extra/Configs/Config.i960 b/extra/Configs/Config.i960 new file mode 100644 index 0000000..cb325c7 --- /dev/null +++ b/extra/Configs/Config.i960 @@ -0,0 +1,19 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "i960" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select HAS_NO_THREADS + +config ARCH_CFLAGS + string + default "-mh -mint32 -fsigned-char" diff --git a/extra/Configs/Config.ia64 b/extra/Configs/Config.ia64 new file mode 100644 index 0000000..dc13319 --- /dev/null +++ b/extra/Configs/Config.ia64 @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "ia64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + select ARCH_HAS_NO_LDSO + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in new file mode 100644 index 0000000..9e2112c --- /dev/null +++ b/extra/Configs/Config.in @@ -0,0 +1,2070 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +mainmenu "uClibc C Library Configuration" + +choice + prompt "Target Architecture" + help + The architecture of your target. + +config TARGET_alpha + bool "alpha" + +config TARGET_arm + bool "arm" + +config TARGET_avr32 + bool "avr32" + +config TARGET_bfin + bool "bfin" + +config TARGET_cris + bool "cris" + +config TARGET_e1 + bool "e1 (BROKEN)" + +config TARGET_frv + bool "frv (BROKEN)" + +config TARGET_h8300 + bool "h8300 (BROKEN)" + +config TARGET_hppa + bool "hppa" + +config TARGET_i386 + bool "i386" + +config TARGET_i960 + bool "i960 (BROKEN)" + +config TARGET_ia64 + bool "ia64" + +config TARGET_m68k + bool "m68k" + +config TARGET_microblaze + bool "microblaze (BROKEN)" + +config TARGET_mips + bool "mips" + +config TARGET_nios + bool "nios" + +config TARGET_nios2 + bool "nios2" + +config TARGET_powerpc + bool "powerpc" + +config TARGET_sh + bool "superh" + +config TARGET_sh64 + bool "sh64" + +config TARGET_sparc + bool "sparc" + +config TARGET_v850 + bool "v850 (BROKEN)" + +config TARGET_vax + bool "vax" + +config TARGET_x86_64 + bool "x86_64" + +config TARGET_xtensa + bool "xtensa" + +endchoice + + +menu "Target Architecture Features and Options" + +if TARGET_alpha +source "extra/Configs/Config.alpha" +endif + +if TARGET_arm +source "extra/Configs/Config.arm" +endif + +if TARGET_avr32 +source "extra/Configs/Config.avr32" +endif + +if TARGET_bfin +source "extra/Configs/Config.bfin" +endif + +if TARGET_cris +source "extra/Configs/Config.cris" +endif + +if TARGET_e1 +source "extra/Configs/Config.e1" +endif + +if TARGET_frv +source "extra/Configs/Config.frv" +endif + +if TARGET_h8300 +source "extra/Configs/Config.h8300" +endif + +if TARGET_hppa +source "extra/Configs/Config.hppa" +endif + +if TARGET_i386 +source "extra/Configs/Config.i386" +endif + +if TARGET_i960 +source "extra/Configs/Config.i960" +endif + +if TARGET_ia64 +source "extra/Configs/Config.ia64" +endif + +if TARGET_m68k +source "extra/Configs/Config.m68k" +endif + +if TARGET_nios +source "extra/Configs/Config.nios" +endif + +if TARGET_nios2 +source "extra/Configs/Config.nios2" +endif + +if TARGET_microblaze +source "extra/Configs/Config.microblaze" +endif + +if TARGET_mips +source "extra/Configs/Config.mips" +endif + +if TARGET_powerpc +source "extra/Configs/Config.powerpc" +endif + +if TARGET_sh +source "extra/Configs/Config.sh" +endif + +if TARGET_sh64 +source "extra/Configs/Config.sh64" +endif + +if TARGET_sparc +source "extra/Configs/Config.sparc" +endif + +if TARGET_v850 +source "extra/Configs/Config.v850" +endif + +if TARGET_vax +source "extra/Configs/Config.vax" +endif + +if TARGET_x86_64 +source "extra/Configs/Config.x86_64" +endif + +if TARGET_xtensa +source "extra/Configs/Config.xtensa" +endif + +config TARGET_SUBARCH + string + default "e500" if CONFIG_E500 + default "classic" if CONFIG_CLASSIC + default "sh4" if CONFIG_SH4 + default "" + +source "extra/Configs/Config.in.arch" + +endmenu + +menu "General Library Settings" + +config HAVE_NO_PIC + bool + default n + +config DOPIC + bool "Generate only Position Independent Code (PIC)" + default y + depends on !HAVE_NO_PIC + help + If you wish to build all of uClibc as PIC objects, then answer Y here. + If you are unsure, then you should answer N. + +config ARCH_HAS_NO_SHARED + bool + default n + +config ARCH_HAS_NO_LDSO + bool + select ARCH_HAS_NO_SHARED + default n + +config HAVE_SHARED + bool "Enable support for shared libraries" + depends on !ARCH_HAS_NO_SHARED + default y + help + If you wish to build uClibc with support for shared libraries then + answer Y here. If you only want to build uClibc as a static library, + then answer N. + +config FORCE_SHAREABLE_TEXT_SEGMENTS + bool "Only load shared libraries which can share their text segment" + depends on HAVE_SHARED + default n + help + If you answer Y here, the uClibc native shared library loader will + only load shared libraries, which do not need to modify any + non-writable segments. These libraries haven't set the DT_TEXTREL + tag in the dynamic section (==> objdump). + All your libraries must be compiled with -fPIC or -fpic, and all + assembler function must be written as position independent code (PIC). + Enabling this option will make uClibc's shared library loader a + little bit smaller and guarantee that no memory will be wasted by + badly coded shared libraries. + +config LDSO_LDD_SUPPORT + bool "Native 'ldd' support" + depends on HAVE_SHARED + default y + help + Enable this to enable all the code needed to support traditional ldd, + which executes the shared library loader to resolve all dependencies + and then provide a list of shared libraries that are required for an + application to function. Disabling this option will makes uClibc's + shared library loader a little bit smaller. + Most people will answer Y. + +config LDSO_CACHE_SUPPORT + bool "Enable library loader cache (ld.so.conf)" + depends on HAVE_SHARED + default y + help + Enable this to make use of /etc/ld.so.conf, the shared library loader + cache configuration file to support for non-standard library paths. + After updating this file, it is necessary to run 'ldconfig' to update + the /etc/ld.so.cache shared library loader cache file. + +config LDSO_PRELOAD_FILE_SUPPORT + bool "Enable library loader preload file (ld.so.preload)" + depends on HAVE_SHARED + default n + help + Enable this to make use of /etc/ld.so.preload. This file contains a + whitespace separated list of shared libraries to be loaded before + the program. + +config LDSO_BASE_FILENAME + string "Shared library loader naming prefix" + depends on HAVE_SHARED && (LDSO_CACHE_SUPPORT || LDSO_PRELOAD_FILE_SUPPORT) + default "ld.so" + help + If you wish to support both uClibc and glibc on the same system, it + is necessary to set this to something other than "ld.so" to avoid + conflicts with glibc, which also uses "ld.so". This prevents both + libraries from using the same /etc/ld.so.* files. If you wish to + support both uClibc and glibc on the same system then you should set + this to "ld-uClibc.so". + + Most people will leave this set to the default of "ld.so". + + WARNING: Changing the default prefix could cause problems with + binutils' ld ! + +config UCLIBC_STATIC_LDCONFIG + bool "Link ldconfig statically" + depends on HAVE_SHARED + default y + help + Enable this option to statically link the ldconfig binary. + + Making ldconfig static can be beneficial if you have a library + problem and need to use ldconfig to recover. Sometimes, it is + preferable to instead keep the size of the system down, in which + case you should disable this option. + +config LDSO_RUNPATH + bool "Enable ELF RUNPATH tag support" + depends on HAVE_SHARED + default y + help + ELF's may have dynamic RPATH/RUNPATH tags. These tags list paths + which extend the library search paths. They are really only useful + if a package installs libraries in non standard locations and + ld.so.conf support is disabled. + + Usage of RUNPATH tags is not too common, so disabling this feature + should be safe for most people. + +config UCLIBC_CTOR_DTOR + bool "Support global constructors and destructors" + default y + help + If you wish to build uClibc with support for global constructor + (ctor) and global destructor (dtor) support, then answer Y here. + When ctor/dtor support is enabled, binaries linked with uClibc must + also be linked with crtbegin.o and crtend.o which are provided by gcc + (the "*startfile:" and "*endfile:" settings in your gcc specs file + may need to be adjusted to include these files). This support will + also add a small amount of additional size to each binary compiled vs + uClibc. If you will be using uClibc with C++, or if you need the gcc + __attribute__((constructor)) and __attribute__((destructor)) to work, + then you definitely want to answer Y here. If you don't need ctors + or dtors and want your binaries to be as small as possible, then + answer N. + +config LDSO_GNU_HASH_SUPPORT + bool "Enable GNU hash style support" + depends on HAVE_SHARED + default n + help + Newest binutils support a new hash style named GNU-hash. The dynamic + linker will use the new GNU-hash section (.gnu.hash) for symbol lookup + if present into the ELF binaries, otherwise it will use the old SysV + hash style (.hash). This ensures that it is completely backward + compatible. + Further, being the hash table implementation self-contained into each + executable and shared libraries, objects with mixed hash style can + peacefully coexist in the same process. + + If you want to use this new feature, answer Y + +config HAS_NO_THREADS + bool + default n + +config UCLIBC_HAS_THREADS + bool "POSIX Threading support" + depends on !HAS_NO_THREADS + default y + # linuxthreads and linuxthreads.old need nanosleep() + select UCLIBC_HAS_REALTIME + help + If you want to compile uClibc with pthread support, then answer Y. + This will increase the size of uClibc by adding a bunch of locking + to critical data structures, and adding extra code to ensure that + functions are properly reentrant. + + If your applications require pthreads, answer Y. + +config PTHREADS_DEBUG_SUPPORT + bool "Build pthreads debugging support" + default n + depends on UCLIBC_HAS_THREADS + help + Say Y here if you wish to be able to debug applications that use + uClibc's pthreads library. By enabling this option, a library + named libthread_db will be built. This library will be dlopen()'d + by gdb and will allow gdb to debug the threads in your application. + + IMPORTANT NOTE! Because gdb must dlopen() the libthread_db library, + you must compile gdb with uClibc in order for pthread debugging to + work properly. + + If you are doing development and want to debug applications using + uClibc's pthread library, answer Y. Otherwise, answer N. + +config LINUXTHREADS_OLD + bool "Use the older (stable) version of linuxthreads" + default y + depends on UCLIBC_HAS_THREADS + help + There are two versions of linuxthreads. The older (stable) version + has been in uClibc for quite a long time but hasn't seen too many + updates other than bugfixes. + + The new version has not been tested much, and lacks ports for arches + which glibc does not support (like bfin/frv/etc...), but is based on + the latest code from glibc, so it may be the only choice for the + newer ports (like alpha/amd64/64bit arches and hppa). + +config LINUXTHREADS_NEW + def_bool y + depends on UCLIBC_HAS_THREADS && !LINUXTHREADS_OLD + +config UCLIBC_HAS_SYSLOG + bool "Syslog support" + default y + depends on UCLIBC_HAS_NETWORK_SUPPORT + select UCLIBC_HAS_SOCKET + help + Support sending messages to the system logger. + This requires socket-support. + +config UCLIBC_HAS_LFS + bool "Large File Support" + default y + help + If you wish to build uClibc with support for accessing large files + (i.e. files greater then 2 GiB) then answer Y. Do not enable this + if you are using an older Linux kernel (2.0.x) that lacks large file + support. Enabling this option will increase the size of uClibc. + +choice + prompt "Malloc Implementation" + default MALLOC if ! ARCH_USE_MMU + default MALLOC_STANDARD if ARCH_USE_MMU + +config MALLOC + bool "malloc" + help + "malloc" use mmap for all allocations and so works very well on + MMU-less systems that do not support the brk() system call. It is + pretty smart about reusing already allocated memory, and minimizing + memory wastage. + This is the default for uClinux MMU-less systems. + +config MALLOC_SIMPLE + bool "malloc-simple" + help + "malloc-simple" is trivially simple and slow as molasses. It + was written from scratch for uClibc, and is the simplest possible + (and therefore smallest) malloc implementation. + + This uses only the mmap() system call to allocate and free memory, + and does not use the brk() system call at all, making it a fine + choice for MMU-less systems with very limited memory. It's 100% + standards compliant, thread safe, very small, and releases freed + memory back to the OS immediately rather than keeping it in the + process's heap for reallocation. It is also VERY SLOW. + +config MALLOC_STANDARD + bool "malloc-standard" + depends on ARCH_USE_MMU + help + "malloc-standard" is derived from the public domain dlmalloc + implementation by Doug Lea. It is quite fast, and is pretty smart + about reusing already allocated memory, and minimizing memory + wastage. This uses brk() for small allocations, while using mmap() + for larger allocations. This is the default malloc implementation + for uClibc. + + If unsure, answer "malloc-standard". + +endchoice + +config MALLOC_GLIBC_COMPAT + bool "Malloc returns live pointer for malloc(0)" + default n + help + The behavior of malloc(0) is listed as implementation-defined by + SuSv3. Glibc returns a valid pointer to something, while uClibc + normally returns NULL. I personally feel glibc's behavior is + not particularly safe, and allows buggy applications to hide very + serious problems. + + When this option is enabled, uClibc will act just like glibc, and + return a live pointer when someone calls malloc(0). This pointer + provides a malloc'ed area with a size of 1 byte. This feature is + mostly useful when dealing with applications using autoconf's broken + AC_FUNC_MALLOC macro (which redefines malloc as rpl_malloc if it + does not detect glibc style returning-a-valid-pointer-for-malloc(0) + behavior). Most people can safely answer N. + +config UCLIBC_DYNAMIC_ATEXIT + bool "Dynamic atexit() Support" + default y + help + When this option is enabled, uClibc will support an infinite number, + of atexit() and on_exit() functions, limited only by your available + memory. This can be important when uClibc is used with C++, since + global destructors are implemented via atexit(), and it is quite + possible to exceed the default number when this option is disabled. + Enabling this option adds a few bytes, and more significantly makes + atexit and on_exit depend on malloc, which can be bad when compiling + static executables. + + Unless you use uClibc with C++, you should probably answer N. + +config COMPAT_ATEXIT + bool "Old (visible) atexit Support" + default n + help + Enable this option if you want to update from 0.9.28 to svn/0.9.29, + else you will be missing atexit() until you rebuild all apps. + +config UCLIBC_SUSV3_LEGACY + bool "Enable SuSv3 LEGACY functions" + default n + help + Enable this option if you want to have SuSv3 LEGACY functions + in the library, else they are replaced by SuSv3 proposed macros. + Currently applies to bcopy/bzero/bcmp/index/rindex/ftime. + WARNING! ABI incompatibility. + +config UCLIBC_SUSV3_LEGACY_MACROS + bool "Enable SuSv3 LEGACY macros" + default n + help + Enable this option if you want to have SuSv3 LEGACY macros. + Currently applies to bcopy/bzero/bcmp/index/rindex et al. + WARNING! ABI incompatibility. + +config UCLIBC_HAS_STUBS + bool "Provide stubs for unavailable functionality" + default n + help + With this option uClibc provides non-functional stubs for + functions which are impossible to implement on the target + architecture. Otherwise, such functions are simply omitted. + + As of 2008-07, this option makes uClibc provide fork() stub + on NOMMU targets. It always sets errno to ENOSYS and returns -1. + + This may be useful if you port a lot of software and cannot + audit all of it and replace or disable fork() usage. + With this option, a program which uses fork() will build + successfully. Of course, it may be useless if fork() + is essential for its operation. + +config UCLIBC_HAS_SHADOW + bool "Shadow Password Support" + default y + help + Answer N if you do not need shadow password support. + Most people will answer Y. + +config UCLIBC_HAS_PROGRAM_INVOCATION_NAME + bool "Support for program_invocation_name" + default n + help + Support for the GNU-specific program_invocation_name and + program_invocation_short_name strings. Some GNU packages + (like tar and coreutils) utilize these for extra useful + output, but in general are not required. + + At startup, these external strings are automatically set + up based on the value of ARGV[0]. + + If unsure, just answer N. + +config UCLIBC_HAS___PROGNAME + bool "Support for __progname" + default y + depends on UCLIBC_HAS_PROGRAM_INVOCATION_NAME + help + Some packages (like openssh) like to peek into internal libc + symbols to make their output a bit more user friendly. + + At startup, __progname is automatically set up based on the + value of ARGV[0]. + + If unsure, just answer N. + +config UCLIBC_HAS_PTY + bool "Support for pseudo-terminals" + default y + help + This enables support for pseudo-terminals (see man 4 pts + and man 7 pty). + + If unsure, just answer Y. + +config ASSUME_DEVPTS + bool "Assume that /dev/pts is a devpts or devfs file system" + default y + depends on UCLIBC_HAS_PTY + help + Enable this if /dev/pts is on a devpts or devfs filesystem. Both + these filesystems automatically manage permissions on the /dev/pts + devices. You may need to mount your devpts or devfs filesystem on + /dev/pts for this to work. + + Most people should answer Y. + +config UNIX98PTY_ONLY + bool "Support only Unix 98 PTYs" + default y + depends on UCLIBC_HAS_PTY + help + If you want to support only Unix 98 PTYs enable this. Some older + applications may need this disabled and will thus use legacy BSD + style PTY handling which is more complex and also bigger than + Unix 98 PTY handling. + + For most current programs, you can generally answer Y. + +if UNIX98PTY_ONLY +config UCLIBC_HAS_GETPT + bool "Support getpt() (glibc-compat)" + default n + depends on UCLIBC_HAS_PTY + help + Some packages may need getpt(). + All of those are non-standard and can be considered + GNU/libc compatibility. + Either use posix_openpt() or just open /dev/ptmx yourself. + + If unsure, just say N. +endif + +if !UNIX98PTY_ONLY +# Have to use __libc_ptyname{1,2}[] and related bloat +config UCLIBC_HAS_GETPT + def_bool y +endif + +config UCLIBC_HAS_TM_EXTENSIONS + bool "Support 'struct tm' timezone extension fields" + default y + help + Enabling this option adds fields to 'struct tm' in time.h for + tracking the number of seconds east of UTC, and an abbreviation for + the current timezone. These fields are not specified by the SuSv3 + standard, but they are commonly used in both GNU and BSD application + code. + + To strictly follow the SuSv3 standard, leave this disabled. + Most people will probably want to answer Y. + +config UCLIBC_HAS_TZ_CACHING + bool "Enable caching of the last valid timezone 'TZ' string" + default y + help + Answer Y to enable caching of the last valid 'TZ' string describing + the timezone setting. This allows a quick string compare to avoid + repeated parsing of unchanged 'TZ' strings when tzset() is called. + + Most people will answer Y. + +config UCLIBC_HAS_TZ_FILE + bool "Enable '/etc/TZ' file support to set a default timezone (uClibc-specific)" + default y + help + Answer Y to enable the setting of a default timezone for uClibc. + + Ordinarily, uClibc gets the timezone information exclusively from the + 'TZ' environment variable. In particular, there is no support for + the zoneinfo directory tree or the /etc/timezone file used by glibc. + + With this option enabled, uClibc will use the value stored in the + file '/etc/TZ' (default path) to obtain timezone information if the + 'TZ' environment variable is missing or has an invalid value. The + file consists of a single line (newline required) of text describing + the timezone in the format specified for the TZ environment variable. + + Doing 'echo CST6CDT > /etc/TZ' is enough to create a valid file. + See + http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html + for details on valid settings of 'TZ'. + + Most people will answer Y. + +config UCLIBC_HAS_TZ_FILE_READ_MANY + bool "Repeatedly read the '/etc/TZ' file" + depends on UCLIBC_HAS_TZ_FILE + default y + help + Answer Y to enable repeated reading of the '/etc/TZ' file even after + a valid value has been read. This incurs the overhead of an + open/read/close for each tzset() call (explicit or implied). However, + setting this will allow applications to update their timezone + information if the contents of the file change. + + Most people will answer Y. + +config UCLIBC_TZ_FILE_PATH + string "Path to the 'TZ' file for setting the global timezone" + depends on UCLIBC_HAS_TZ_FILE + default "/etc/TZ" + help + This is the path to the 'TZ' file. + + Most people will use the default of '/etc/TZ'. + +endmenu + +menu "Advanced Library Settings" + +config UCLIBC_PWD_BUFFER_SIZE + int "Buffer size for getpwnam() and friends" + default 256 + range 12 1024 + help + This sets the value of the buffer size for getpwnam() and friends. + By default, this is 256. (For reference, glibc uses 1024). + The value can be found using sysconf() with the _SC_GETPW_R_SIZE_MAX + parameter. + +config UCLIBC_GRP_BUFFER_SIZE + int "Buffer size for getgrnam() and friends" + default 256 + range 12 1024 + help + This sets the value of the buffer size for getgrnam() and friends. + By default, this is 256. (For reference, glibc uses 1024). + The value can be found using sysconf() with the _SC_GETGR_R_SIZE_MAX + parameter. + +comment "Support various families of functions" + +config UCLIBC_LINUX_MODULE_24 + bool "Linux kernel module functions" + default y + help + create_module, query_module + are used in linux (prior to 2.6) for loadable kernel modules. + + Say N if you do not use kernel modules. + +config UCLIBC_LINUX_SPECIFIC + bool "Linux specific functions" + default y + help + fstatfs(), inotify_*(), ioperm(), iopl(), madvise(), modify_ldt(), + personality(), ppoll(), setresuid(), signalfd() + +config UCLIBC_HAS_GNU_ERROR + bool "Support GNU extensions for error-reporting" + default y + help + Support for the GNU-specific error(), error_at_line(), + void (* error_print_progname)(), error_message_count + functions and variables. Some GNU packages + utilize these for extra useful output, but in general + are not required. + + If unsure, just answer N. + +config UCLIBC_BSD_SPECIFIC + bool "BSD specific functions" + default y + help + mincore(), getdomainname(), setdomainname() + + If unsure, say N. + +config UCLIBC_HAS_BSD_ERR + bool "BSD err functions" + default y + help + These functions are non-standard BSD extensions. + err(), errx(), warn(), warnx(), verr(), verrx(), vwarn(), vwarnx() + + If unsure, say N. + +config UCLIBC_HAS_OBSOLETE_BSD_SIGNAL + bool "BSD obsolete signal functions" + default n + help + These functions are provided as a compatibility interface for + programs that make use of the historical System V signal API. + This API is obsolete: + new applications should use the POSIX signal API (sigaction(2), + sigprocmask(2), etc.). + Affected functions: + + sigset(), sighold(), sigrelse(), sigignore() + + If unsure, say N. + +config UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL + bool "SYSV obsolete signal functions" + default n + help + Use of sysv_signal() should be avoided; use sigaction(2) instead. + + If unsure, say N. + +config UCLIBC_NTP_LEGACY + bool "ntp_*() aliases" + default n + help + Provide legacy aliases for ntp functions: + ntp_adjtime(), ntp_gettime() + + It is safe to say N here. + +config UCLIBC_SV4_DEPRECATED + bool "Enable SVr4 deprecated functions" + default n + help + These functions are DEPRECATED in System V release 4. + Say N unless you desparately need one of the functions below: + + ustat() [use statfs(2) in your code instead] + +config UCLIBC_HAS_REALTIME + bool "Realtime-related family of SUSv functions" + default y + help + These functions are part of the Timers option and need not + be available on all implementations. + Includes AIO, message-queue, scheduler, semaphore functions: + + aio.h + mqueue.h + sched.h + semaphore.h + + aio_cancel() + aio_error() + aio_fsync() + aio_read() + lio_listio() + aio_return() + aio_suspend() + aio_write() + clock_getres(), clock_gettime(), clock_settime() + fdatasync() + mlockall(), munlockall() + mlock(), munlock() + mq_close() + mq_getattr() + mq_notify() + mq_open() + mq_receive() + mq_send() + mq_setattr() + mq_unlink() + nanosleep() + sched_getparam() + sched_get_priority_max(), sched_get_priority_min() + sched_getscheduler() + sched_rr_get_interval() + sched_setparam() + sched_setscheduler() + sem_close() + sem_destroy() + sem_getvalue() + sem_init() + sem_open() + sem_post() + sem_trywait(), sem_wait() + sem_unlink() + sigqueue() + sigtimedwait(), sigwaitinfo() + timer_create() + timer_delete() + timer_getoverrun(), timer_gettime(), timer_settime() + +config UCLIBC_HAS_ADVANCED_REALTIME + bool "Advanced realtime-related family of SUSv functions" + default y + depends on UCLIBC_HAS_REALTIME + help + These functions are part of the Timers option and need not + be available on all implementations. + + clock_getcpuclockid() + clock_nanosleep() + mq_timedreceive() + mq_timedsend() + posix_fadvise() + posix_fallocate() + posix_madvise() + posix_memalign() + posix_mem_offset() + posix_spawnattr_destroy(), posix_spawnattr_init() + posix_spawnattr_getflags(), posix_spawnattr_setflags() + posix_spawnattr_getpgroup(), posix_spawnattr_setpgroup() + posix_spawnattr_getschedparam(), posix_spawnattr_setschedparam() + posix_spawnattr_getschedpolicy(), posix_spawnattr_setschedpolicy() + posix_spawnattr_getsigdefault(), posix_spawnattr_setsigdefault() + posix_spawnattr_getsigmask(), posix_spawnattr_setsigmask() + posix_spawn_file_actions_addclose() + posix_spawn_file_actions_adddup2() + posix_spawn_file_actions_addopen() + posix_spawn_file_actions_destroy() + posix_spawn_file_actions_init() + posix_spawn() + posix_spawnp() + posix_typed_mem_get_info() + pthread_mutex_timedlock() + sem_timedwait() + +#config UCLIBC_HAS_TERMIOS +# bool "termios functions" +# default y +# help +# Get and set terminal attributes, line control, get and set baud +# rate. +# termios(), tcgetattr(), tcsetattr(), tcsendbreak(), tcdrain(), +# tcflush(), tcflow(), cfmakeraw(), cfgetospeed(), cfgetispeed(), +# cfsetispeed(), cfsetospeed(), cfsetspeed() +# +# If unsure, say Y. + +config UCLIBC_HAS_EPOLL + bool "epoll" + default y + help + epoll_create(), epoll_ctl(), epoll_wait() functions. + +config UCLIBC_HAS_XATTR + bool "Extended Attributes" + default y + help + Extended Attributes support. + + setxattr() + lsetxattr() + fsetxattr() + getxattr() + lgetxattr() + fgetxattr() + listxattr() + llistxattr() + flistxattr() + removexattr() + lremovexattr() + fremovexattr() + + Say N unless you need support for extended attributes and the + filesystems do actually support them. + +config UCLIBC_HAS_PROFILING + bool "Profiling support" + default y + help + gcc's -finstrument-functions needs these. + + Most people can safely answer N. + +config UCLIBC_HAS_CRYPT_IMPL + bool "libcrypt support" + default y + help + libcrypt contains crypt(), setkey() and encrypt() + +config UCLIBC_HAS_CRYPT_STUB + bool "libcrypt stubs" + default y + depends on !UCLIBC_HAS_CRYPT_IMPL + help + Standards mandate that crypt(3) provides a stub if it is unavailable. + If you enable this option then stubs for + crypt(), setkey() and encrypt() + will be provided in a small libcrypt. + +config UCLIBC_HAS_CRYPT + def_bool y + depends on UCLIBC_HAS_CRYPT_IMPL || UCLIBC_HAS_CRYPT_STUB +endmenu + +menuconfig UCLIBC_HAS_NETWORK_SUPPORT + bool "Networking Support" + default y + help + Say N here if you do not need network support. + +if UCLIBC_HAS_NETWORK_SUPPORT +config UCLIBC_HAS_SOCKET + bool "Socket support" + default y + help + If you want to include support for sockets then answer Y. + +config UCLIBC_HAS_IPV4 + bool "IP version 4 support" + default y + select UCLIBC_HAS_SOCKET + help + If you want to include support for the Internet Protocol + (IP version 4) then answer Y. + + Most people will say Y. + +config UCLIBC_HAS_IPV6 + bool "IP version 6 support" + default n + select UCLIBC_HAS_SOCKET + help + If you want to include support for the next version of the Internet + Protocol (IP version 6) then answer Y. + + Most people should answer N. + +config UCLIBC_HAS_RPC + bool "Remote Procedure Call (RPC) support" + default n + # RPC+socket-ipvX doesn't currently work. + depends on UCLIBC_HAS_IPV4 || UCLIBC_HAS_IPV6 + help + If you want to include RPC support, enable this. RPC is rarely used + for anything except for the NFS filesystem. Unless you plan to use + NFS, you can probably leave this set to N and save some space. + + If you need to use NFS then you should answer Y. + +config UCLIBC_HAS_FULL_RPC + bool "Full RPC support" + depends on UCLIBC_HAS_RPC + default y if !HAVE_SHARED + help + Normally we enable just enough RPC support for things like rshd and + nfs mounts to work. If you find you need the rest of the RPC stuff, + then enable this option. Most people can safely answer N. + +config UCLIBC_HAS_REENTRANT_RPC + bool "Reentrant RPC support" + depends on UCLIBC_HAS_RPC + default y if !HAVE_SHARED + help + Most packages utilize the normal (non-reentrant) RPC functions, but + some (like exportfs from nfs-utils) need these reentrant versions. + + Most people can safely answer N. + +config UCLIBC_USE_NETLINK + bool "Use netlink to query interfaces" + default n + depends on UCLIBC_HAS_SOCKET + help + In newer versions of Linux (2.4.17+), support was added for querying + network device information via netlink rather than the old style + ioctl's. Most of the time, the older ioctl style is sufficient (and + it is smaller than netlink), but if you find that not all of your + devices are being returned by the if_nameindex() function, you will + have to use the netlink implementation. + + Most people can safely answer N. + +config UCLIBC_SUPPORT_AI_ADDRCONFIG + bool "Support the AI_ADDRCONFIG flag" + depends on UCLIBC_USE_NETLINK + default n + help + The implementation of AI_ADDRCONFIG is aligned with the glibc + implementation using netlink to query interfaces to find both + ipv4 and ipv6 support. This is only needed if an application uses + the AI_ADDRCONFIG flag. + + Most people can safely answer N. + +config UCLIBC_HAS_BSD_RES_CLOSE + bool "Support res_close() (bsd-compat)" + default n + help + Answer Y if you desperately want to support BSD compatibility in + the network code. + + Most people will say N. + +endif + + +menu "String and Stdio Support" + +config UCLIBC_HAS_STRING_GENERIC_OPT + bool "Use faster (but larger) generic string functions" + default y + help + Answer Y to use the (tweaked) glibc generic string functions. + + In general, they are faster (but 3-5K larger) than the base + uClibc string functions which are optimized solely for size. + + Many people will answer Y. + +config UCLIBC_HAS_STRING_ARCH_OPT + bool "Use arch-specific assembly string functions (where available)" + default y + help + Answer Y to use any archtecture-specific assembly language string + functions available for this target plaform. + + Note that assembly implementations are not available for all string + functions, so some generic (written in C) string functions may + still be used. + + These are small and fast, the only reason _not_ to say Y here is + for debugging purposes. + +config UCLIBC_HAS_CTYPE_TABLES + bool "Use Table Versions Of 'ctype.h' Functions." + default y + help + Answer Y to use table versions of the 'ctype.h' functions. + While the non-table versions are often smaller when building + statically linked apps, they work only in stub locale mode. + + Most people will answer Y. + +config UCLIBC_HAS_CTYPE_SIGNED + bool "Support Signed Characters In 'ctype.h' Functions." + depends on UCLIBC_HAS_CTYPE_TABLES + default y + help + Answer Y to enable support for passing signed char values to + the 'ctype.h' functions. ANSI/ISO C99 and SUSv3 specify that + these functions are only defined for unsigned char values and + EOF. However, glibc allows negative signed char values as well + in order to support 'broken old programs'. + + Most people will answer Y. + +choice + prompt "ctype argument checking" + depends on UCLIBC_HAS_CTYPE_TABLES + default UCLIBC_HAS_CTYPE_UNSAFE + help + Please select the invalid arg behavior you want for the 'ctype' + functions. + + The 'ctype' functions are now implemented using table lookups, with + the arg being the index. This can result in incorrect memory accesses + or even segfaults for args outside of the allowed range. + + NOTE: This only affects the 'ctype' _functions_. It does not affect + the macro implementations. + +config UCLIBC_HAS_CTYPE_UNSAFE + bool "Do not check -- unsafe" + +config UCLIBC_HAS_CTYPE_CHECKED + bool "Detect and handle appropriately" + +config UCLIBC_HAS_CTYPE_ENFORCED + bool "Issue a diagnostic and abort()" + +endchoice + + +config UCLIBC_HAS_WCHAR + bool "Wide Character Support" + default n + help + Answer Y to enable wide character support. This will make uClibc + much larger. It is also currently required for locale support. + + Most people will answer N. + +config UCLIBC_HAS_LOCALE + bool "Locale Support" + select UCLIBC_HAS_WCHAR + select UCLIBC_HAS_CTYPE_TABLES + default n + help + uClibc now has full ANSI/ISO C99 locale support (except for + wcsftime() and collating items in regex). Be aware that enabling + this option will make uClibc much larger. + + Enabling UCLIBC_HAS_LOCALE with the default set of supported locales + (169 UTF-8 locales, and 144 locales for other codesets) will enlarge + uClibc by around 300k. You can reduce this size by building your own + custom set of locate data (see extra/locale/LOCALES for details). + + uClibc's locale support is still under development. For example, + codesets using shift states are not currently supported. Support is + planned in the next iteration of locale support. + + Answer Y to enable locale support. Most people will answer N. + +config UCLIBC_PREGENERATED_LOCALE_DATA + bool "Use Pre-generated Locale Data" + depends on UCLIBC_HAS_LOCALE + default n + help + If you are selective and only want locale data for a few particular + locales, you can turn this option off. + + Mere mortals will answer Y and use the default set of pregenerated + locale data, which supports 169 UTF-8 locales, and 144 locales for + other codesets (for the complete list see extra/locale/LOCALES). + + Note that these pregenerated locales are sensitive to your + target architecture (endianess, bitcount). + + Saying N here is recommended. + +config UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA + bool "Automagically Download the Pre-generated Locale Data (if necessary)" + depends on UCLIBC_PREGENERATED_LOCALE_DATA + default n + help + If you would like the build process to use 'wget' to automatically + download the pregenerated locale data, enable this option. Otherwise + you will need to obtain the locale data yourself from: + http://www.uclibc.org/downloads/uClibc-locale-*.tgz + and place the uClibc-locale-*.tgz tarball in the extra/locale/ + directory. + + Go ahead and make life easy for yourself... Answer Y. + +config UCLIBC_HAS_XLOCALE + bool "Extended Locale Support (experimental/incomplete)" + depends on UCLIBC_HAS_LOCALE + default n + help + Answer Y to enable extended locale support similar to that provided + by glibc. This is primarily intended to support libstd++ + functionality. + However, it also allows thread-specific locale selection via + uselocale(). + + Most people will answer N. + +config UCLIBC_HAS_HEXADECIMAL_FLOATS + bool "Support hexadecimal float notation" + depends on UCLIBC_HAS_CTYPE_TABLES + depends on UCLIBC_HAS_FLOATS + default n + help + Answer Y to enable support for hexadecimal float notation in the + (wchar and) char string to floating point conversion functions, as + well as support for the %a and %A conversion specifiers in the + *printf() and *scanf() functions. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_DIGIT_GROUPING + bool "Support glibc's \"'\" flag for allowing locale-specific digit grouping" + depends on UCLIBC_HAS_LOCALE + depends on UCLIBC_HAS_FLOATS + default n + help + Answer Y to enable support for glibc's \"'\" flag for allowing + locale-specific digit grouping in base 10 integer conversions and + appropriate floating point conversions in the *printf() and *scanf() + functions. + + Most people will answer N. + +config UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING + bool "Do not require digit grouping when the \"'\" flag is specified" + depends on UCLIBC_HAS_GLIBC_DIGIT_GROUPING + default y + help + Answer Y to make digit grouping optional when the \"'\" flag is + specified. + This is the standard glibc behavior. If the initial string of digits + exceeds the maximum group number, the input will be treated as a + normal non-grouped number. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_CUSTOM_PRINTF + bool "Support glibc's register_printf_function() (glibc-compat)" + depends on !USE_OLD_VFPRINTF + default n + help + Answer Y to support glibc's register_printf_function() to allow an + application to add its own printf conversion specifiers. + + NOTE: Limits the number or registered specifiers to 10. + NOTE: Requires new conversion specifiers to be ASCII + characters (0-0x7f). This is to avoid problems with processing + format strings in locales with different multibyte conversions. + + Most people will answer N. + +config USE_OLD_VFPRINTF + bool "Use the old vfprintf implementation" + depends on !UCLIBC_HAS_WCHAR + default n + help + Set to true to use the old vfprintf instead of the new. This is + roughly C89 compliant with some extensions, and is much smaller. + However, it does not support wide chars, positional args, or glibc + custom printf specifiers. + + Most people will answer N. + +config UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS + int "Maximum number of positional args. Either 0 or >= 9." + depends on !USE_OLD_VFPRINTF + default 9 + help + Set the maximum number of positional args supported by the + printf/scanf functions. The Single Unix Specification Version 3 + requires a minimum value of 9. Setting this to a value lower than + 9 will disable positional arg support and cause the NL_ARGMAX macro + in limits.h to be #undef'd. + + WARNING! The workspace to support positional args is currently + allocated on the stack. You probably don't want to set + this to too high a value. + + Most people will answer 9. + + +config UCLIBC_HAS_SCANF_GLIBC_A_FLAG + bool "Support glibc's 'a' flag for scanf string conversions (not implemented)" + default n + help + NOTE!!! Currently Not Implemented!!! Just A Place Holder!! NOTE!!! + NOTE!!! Conflicts with an ANSI/ISO C99 scanf flag!! NOTE!!! + + Answer Y to enable support for glibc's 'a' flag for the scanf string + conversions '%s', '%[', '%ls', '%l[', and '%S'. This is used to + auto-allocate sufficient memory to hold the data retrieved. + + Most people will answer N. + +choice + prompt "Stdio buffer size" + default UCLIBC_HAS_STDIO_BUFSIZ_4096 + help + Please select a value for BUFSIZ. This will be used by the + stdio subsystem as the default buffer size for a file, and + affects fopen(), setvbuf(), etc. + + NOTE: Setting this to 'none' will disable buffering completely. + However, BUFSIZ will still be defined in stdio.h as 256 because + many applications use this value. + +config UCLIBC_HAS_STDIO_BUFSIZ_NONE + bool "none (WARNING - BUFSIZ will be 256 in stdio.h)" + depends on !UCLIBC_HAS_WCHAR + +config UCLIBC_HAS_STDIO_BUFSIZ_256 + bool "256 (minimum ANSI/ISO C99 value)" + +config UCLIBC_HAS_STDIO_BUFSIZ_512 + bool "512" + +config UCLIBC_HAS_STDIO_BUFSIZ_1024 + bool "1024" + +config UCLIBC_HAS_STDIO_BUFSIZ_2048 + bool "2048" + +config UCLIBC_HAS_STDIO_BUFSIZ_4096 + bool "4096" + +config UCLIBC_HAS_STDIO_BUFSIZ_8192 + bool "8192" + +# If you add more choices, you will need to update uClibc_stdio.h. + +endchoice + +choice + prompt "Stdio builtin buffer size (uClibc-specific)" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE + help + When a FILE is created with fopen(), an attempt is made to allocate + a BUFSIZ buffer for it. If the allocation fails, fopen() will still + succeed but the FILE will be unbuffered. + + This option adds a small amount of space to each FILE to act as an + emergency buffer in the event of a buffer allocation failure. + + Most people will answer None. + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE + bool "None" + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 + bool "4" + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 + bool "8" + +# If you add more choices, you will need to update uClibc_stdio.h. + +endchoice + +config UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT + bool "Attempt to shutdown stdio subsystem when abort() is called." + default n + help + ANSI/ISO C99 requires abort() to be asyn-signal-safe. So there was + a behavioral change made in SUSv3. Previously, abort() was required + to have the affect of fclose() on all open streams. The wording has + been changed to "may" from "shall". + + Most people will answer N. + +config UCLIBC_HAS_STDIO_GETC_MACRO + bool "Provide a macro version of getc()" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default y + help + Provide a macro version of getc(). + + Most people will answer Y. + +config UCLIBC_HAS_STDIO_PUTC_MACRO + bool "Provide a macro version of putc()" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default y + help + Provide a macro version of putc(). + + Most people will answer Y. + +config UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION + bool "Support auto-r/w transition" + default y + help + Answer Y to enable the stdio subsystem to automaticly transition + between reading and writing. This relaxes the ANSI/ISO C99 + requirement: + + When a file is opened with update mode ('+' as the second or third + character in the list of mode argument values), both input and output + may be performed on the associated stream. However, output shall not + be directly followed by input without an intervening call to the + fflush function or to a file positioning function (fseek, fsetpos, + or rewind), and input shall not be directly followed by output without + an intervening call to a file positioning function, unless the input + operation encounters end­of­file. + + Most people will answer Y. + +config UCLIBC_HAS_FOPEN_LARGEFILE_MODE + bool "Support an fopen() 'F' flag for large file mode (uClibc-specific)" + depends on UCLIBC_HAS_LFS + default n + help + Answer Y to enable a uClibc-specific extension to allow passing an + additional 'F' flag in the mode string for fopen() to specify that + the file should be open()ed with the O_LARGEFILE flag set. + + Most people will answer N. + +config UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE + bool "Support an fopen() 'x' flag for exclusive mode (glibc-compat)" + default n + help + Answer Y to support a glibc extension to allow passing + additional 'x' flag in the mode string for fopen() to specify that + the file should be open()ed with the O_EXCL flag set. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_CUSTOM_STREAMS + bool "Support fmemopen(), open_memstream(), and fopencookie() (glibc-compat)" + default n + help + Answer Y to support the glibc 'custom stream' extension functions + fmemopen(), open_memstream(), and fopencookie(). + + NOTE: There are some minor differences regarding seeking behavior. + + Most people will answer N. + +config UCLIBC_HAS_PRINTF_M_SPEC + bool "Support the '%m' specifier in printf format strings (glibc-compat)" + default n + help + Answer Y to support a glibc extension to interpret '%m' in printf + format strings as an instruction to output the error message string + (as generated by strerror) corresponding to the current value of + 'errno'. + + Most people will answer N. + +config UCLIBC_HAS_ERRNO_MESSAGES + bool "Include the errno message text in the library" + default y + help + Answer Y if you want to include the errno message text in the + library. This adds about 3K to the library, but enables strerror() + to generate text other than 'Unknown error '. + + Most people will answer Y. + +config UCLIBC_HAS_SYS_ERRLIST + bool "Support sys_errlist[] (obsolete-compat)" + depends on UCLIBC_HAS_ERRNO_MESSAGES + default n + help + Answer Y if you want to support the obsolete sys_errlist[]. + This adds about 0.5k to the library, except for the mips + arch where it adds over 4K. + + WARNING! In the future, support for sys_errlist[] may be unavailable + in at least some configurations. In fact, it may be removed + altogether. + + Most people will answer N. + + Application writers: use the strerror(3) function. + +config UCLIBC_HAS_SIGNUM_MESSAGES + bool "Include the signum message text in the library" + default y + help + Answer Y if you want to include the signum message text in the + library. This adds about 0.5K to the library, but enables strsignal() + to generate text other than 'Unknown signal '. + + Most people will answer Y. + +config UCLIBC_HAS_SYS_SIGLIST + bool "Support sys_siglist[] (bsd-compat)" + depends on UCLIBC_HAS_SIGNUM_MESSAGES + default n + help + Answer Y if you want to support sys_siglist[]. + + WARNING! In the future, support for sys_siglist[] may be unavailable + in at least some configurations. In fact, it may be removed + altogether. + + Most people will answer N. + +config UCLIBC_HAS_GETTEXT_AWARENESS + bool "Include gettext awareness" + depends on UCLIBC_HAS_LOCALE && UCLIBC_MJN3_ONLY + default n + help + NOTE!!! Not yet integrated with strerror and strsignal. NOTE!!! + + Answer Y if you want to include weak stub gettext support and + make the *strerror*() and strsignal() functions gettext-aware. + + Currently, to get functional gettext functionality you will need + to use gnu gettext. + + Most people will answer N. + +config UCLIBC_HAS_GNU_GETOPT + bool "Support gnu getopt" + default y + help + Answer Y if you want to include full gnu getopt() instead of a + (much smaller) SUSv3 compatible getopt(). + + Most people will answer Y. + +config UCLIBC_HAS_GETOPT_LONG + bool "Support getopt_long/getopt_long_only" + depends on !UCLIBC_HAS_GNU_GETOPT + default y + help + Answer Y if you want to include getopt_long[_only() used by many + apps, even busybox. + + Most people will answer Y. + +config UCLIBC_HAS_GNU_GETSUBOPT + bool "Support glibc getsubopt" + default y + help + Answer Y if you want to include glibc getsubopt() instead of a + smaller SUSv3 compatible getsubopt(). + + Most people will answer Y. +endmenu + + +menu "Big and Tall" + +config UCLIBC_HAS_REGEX + bool "Regular Expression Support" + default y + help + POSIX regular expression code is really big -- 53k all by itself. + If you don't use regular expressions, turn this off and save space. + Of course, if you only statically link, leave this on, since it will + only be included in your apps if you use regular expressions. + +config UCLIBC_HAS_REGEX_OLD + bool "Use the older (stable) regular expression code" + depends on UCLIBC_HAS_REGEX + default y + help + There are two versions of regex. The older (stable) version has + been in uClibc for quite a long time but hasn't seen too many + updates. It also has some known issues when dealing with uncommon + corner cases and multibyte/unicode strings. However, it is quite + a bit smaller than the newer version. + + If the older version has worked for you and you don't need unicode + support, then stick with the old version (and say Y here). + Otherwise, you should use the new version (and say N here). + +config UCLIBC_HAS_FNMATCH + bool "fnmatch Support" + default y + help + POSIX fnmatch. + +config UCLIBC_HAS_FNMATCH_OLD + bool "Use the older (stable) fnmatch code" + depends on UCLIBC_HAS_FNMATCH + default y + help + There are two versions of fnmatch. The older (stable) version has + been in uClibc for quite a long time but hasn't seen too many + updates. It also has some known issues when dealing with uncommon + corner cases and multibyte/unicode strings. However, it is quite + a bit smaller than the newer version. + + If the older version has worked for you and you don't need unicode + support, then stick with the old version (and say Y here). + Otherwise, you should use the new version (and say N here). + +config UCLIBC_HAS_WORDEXP + bool "Support the wordexp() interface" + depends on UCLIBC_HAS_GLOB + default n + help + The SuSv3 wordexp() interface performs word expansions per the Shell + and Utilities volume of IEEE Std 1003.1-2001, Section 2.6. It is + intended for use by applications that want to implement all of the + standard Bourne shell expansions on input data. + + This interface is rarely used, and very large. Unless you have a + pressing need for wordexp(), you should probably answer N. + +config UCLIBC_HAS_FTW + bool "Support the ftw() and nftw() interfaces" + default n + help + The SuSv3 ftw() and nftw() interfaces are used to recursively descend + directory paths while repeatedly calling a function. + + This interface is rarely used, and adds around 4.5k. Unless you have + a pressing need for ftw() or nftw(), you should probably answer N. + +config UCLIBC_HAS_GLOB + bool "Support the glob() interface" + depends on UCLIBC_HAS_FNMATCH + default y + help + + The glob interface is somewhat large (weighing in at about 2,5k). It + is used fairly often, but is an option since people wanting to go for + absolute minimum size may wish to omit it. + + Most people will answer Y. + +config UCLIBC_HAS_GNU_GLOB + bool "Support gnu glob() interface" + depends on UCLIBC_HAS_GLOB + default n + help + The gnu glob interface is somewhat larger (weighing in at about 4,2k) + than it's SuSv3 counterpart (and is out of date). It is an old copy + from glibc and does not support all the GNU specific options. + + Answer Y if you want to include full gnu glob() instead of the smaller + SUSv3 compatible glob(). + + Most people will answer N. + +endmenu + + + + +menu "Library Installation Options" + +config SHARED_LIB_LOADER_PREFIX + string "Shared library loader path" + depends on HAVE_SHARED + default "$(RUNTIME_PREFIX)lib" + help + When using shared libraries, this path is the location where the + shared library will be invoked. This value will be compiled into + every binary compiled with uClibc. + + For a typical target system this should be set to "/lib", such that + 'make install' will install /lib/ld-uClibc.so.0. + + BIG FAT WARNING: + If you do not have a shared library loader with the correct name + sitting in the directory this points to, your binaries will not + run. + +config RUNTIME_PREFIX + string "uClibc runtime library directory" + default "/usr/$(TARGET_ARCH)-linux-uclibc/" + help + RUNTIME_PREFIX is the directory into which the uClibc runtime + libraries will be installed. The result will look something + like the following: + $(RUNTIME_PREFIX)/ + lib/ + usr/bin/ldd + sbin/ldconfig + This value is used by the 'make install' Makefile target. Since this + directory is compiled into the shared library loader, you will need to + recompile uClibc if you change this value... + + For a typical target system this should be set to "/", such that + 'make install' will install /lib/libuClibc-.so + +config DEVEL_PREFIX + string "uClibc development environment directory" + default "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + help + DEVEL_PREFIX is the directory into which the uClibc development + environment will be installed. The result will look something + like the following: + $(DEVEL_PREFIX)/ + lib/ + include/ + This value is used by the 'make install' Makefile target when + installing a uClibc development environment. + + For a typical target system this should be set to "/usr", such that + 'make install' will install /usr/include/
. + +endmenu + + +menu "Security options" + +config UCLIBC_BUILD_PIE + bool "Build utilities as ET_DYN/PIE executables" + depends on HAVE_SHARED + depends on TARGET_arm || TARGET_frv || TARGET_i386 || TARGET_mips || TARGET_powerpc + select FORCE_SHAREABLE_TEXT_SEGMENTS + default n + help + If you answer Y here, ldd and iconv are built as ET_DYN/PIE + executables. + + It requires gcc-3.4 and binutils-2.15 (for arm 2.16) or later. + More about ET_DYN/PIE binaries on . + + WARNING: This option also enables FORCE_SHAREABLE_TEXT_SEGMENTS, so + all libraries have to be built with -fPIC or -fpic, and all + assembler functions must be written as position independent + code (PIC). + +config UCLIBC_HAS_ARC4RANDOM + bool "Include the arc4random() function" + default n + help + Answer Y to support the OpenBSD-like arc4random() function. This + function picks a random number between 0 and N, and will always return + something even if the random driver is dead. If urandom fails then + gettimeofday(2) will be used as the random seed. This function is + designed to be more dependable than invoking /dev/urandom directly. + OpenSSL and OpenNTPD currently support this function. + + Most people will answer N. + +config HAVE_NO_SSP + bool + default n + +config UCLIBC_HAS_SSP + bool "Support for GCC stack smashing protector" + depends on !HAVE_NO_SSP + default n + help + Add code to support GCC's -fstack-protector[-all] option to uClibc. + This requires GCC 4.1 or newer. GCC does not have to provide libssp, + the needed functions are added to ldso/libc instead. + + GCC's stack protector is a reimplementation of IBM's propolice. + See http://www.trl.ibm.com/projects/security/ssp/ and + http://www.linuxfromscratch.org/hints/downloads/files/ssp.txt + for details. + + Note that NOEXECSTACK on a kernel with address space randomization + is generally sufficient to prevent most buffer overflow exploits + without increasing code size. This option essentially adds debugging + code to catch them. + + Most people will answer N. + +config UCLIBC_HAS_SSP_COMPAT + bool "Support for gcc-3.x propolice smashing stack protector" + depends on UCLIBC_HAS_SSP + default n + help + Add gcc-3.x propolice smashing stack protector to the library. + + This requires a patched version of GCC, supporting the + -fstack-protector[-all] options, with the __guard and + __stack_smash_handler functions removed from libgcc. + These functions are added to ldso/libc instead. + + More information at: + + + Most people will answer N. + +config SSP_QUICK_CANARY + bool "Use simple guard values without accessing /dev/urandom" + depends on UCLIBC_HAS_SSP + default n + help + Use gettimeofday(2) to define the __guard without accessing + /dev/urandom. + WARNING: This makes smashing stack protector vulnerable to timing + attacks. + Most people will answer N. + +choice + prompt "Propolice protection blocking signal" + depends on UCLIBC_HAS_SSP + default PROPOLICE_BLOCK_ABRT if ! DODEBUG + default PROPOLICE_BLOCK_SEGV if DODEBUG + help + "abort" use SIGABRT to block offending programs. + This is the default implementation. + + "segfault" use SIGSEGV to block offending programs. + Use this for debugging. + + If unsure, answer "abort". + +config PROPOLICE_BLOCK_ABRT + bool "abort" + +config PROPOLICE_BLOCK_SEGV + bool "segfault" + +endchoice + +config UCLIBC_BUILD_SSP + bool "Build uClibc with -fstack-protector" + depends on UCLIBC_HAS_SSP + default n + help + Build all uClibc libraries and executables with -fstack-protector, + adding extra stack overflow checking to most uClibc functions. + +config UCLIBC_BUILD_RELRO + bool "Build uClibc with linker option -z RELRO" + depends on HAVE_SHARED + default y + help + Build all libraries and executables with "ld -z relro". + + This tells the linker to mark chunks of an executable or shared + library read-only after applying dynamic relocations. (This comes + up when a global const variable is initialized to the address of a + function or the value of another global variable.) + + This is a fairly obscure option the ld man page doesn't even bother + to document properly. It's a security paranoia issue that's more + likely to consume memory (by allocating an extra page) rather than + save it. + + This is explained in more depth at + http://www.airs.com/blog/archives/189 + + Nobody is likely to care whether you say Y or N here. + +config UCLIBC_BUILD_NOW + bool "Build uClibc with linker option -z NOW" + depends on HAVE_SHARED + default n + help + Build all libraries and executables with "ld -z now". + + This tells the linker to resolve all symbols when the library is + first loaded, rather than when each function is first called. This + increases start-up latency by a few microseconds and may do + unnecessary work (resolving symbols that are never used), but the + realtime people like it for making microbenchmark timings slightly + more predictable and in some cases it can be slightly faster due to + CPU cache behavior (not having to fault the linker back in to do + lazy symbol resolution). + + Most people can't tell the difference between selecting Y or N here. + +config UCLIBC_BUILD_NOEXECSTACK + bool "Build uClibc with noexecstack marking" + default y + help + Mark all assembler files as noexecstack, which will mark uClibc + as not requiring an executable stack. (This doesn't prevent other + files you link against from claiming to need an executable stack, it + just won't cause uClibc to request it unnecessarily.) + + This is a security thing to make buffer overflows harder to exploit. + By itself, it's kind of useless, as Linus Torvalds explained in 1998: + http://old.lwn.net/1998/0806/a/linus-noexec.html + + It only actually provides any security when combined with address + space randomization, explained here: http://lwn.net/Articles/121845/ + + Address space randomization is on by default in current linux + kernels (although it can be disabled using the option + CONFIG_COMPAT_BRK). + + You should probably say Y. + +endmenu + +menu "uClibc development/debugging options" + +config CROSS_COMPILER_PREFIX + string "Cross-compiling toolchain prefix" + default "" + help + The prefix used to execute your cross-compiling toolchain. For + example, if you run 'arm-linux-uclibc-gcc' to compile something, + then enter 'arm-linux-uclibc-' here. + +config UCLIBC_EXTRA_CFLAGS + string "Enter any extra CFLAGS to use to build uClibc" + default "" + help + Add any additional CFLAGS to be used to build uClibc. + +config DODEBUG + bool "Build uClibc with debugging symbols" + default n + select EXTRA_WARNINGS + help + Say Y here if you wish to compile uClibc with debugging symbols. + This will allow you to use a debugger to examine uClibc internals + while applications are running. This increases the size of the + library considerably and should only be used when doing development. + If you are doing development and want to debug uClibc, answer Y. + + Otherwise, answer N. + +config DODEBUG_PT + bool "Build pthread with debugging output" + depends on UCLIBC_HAS_THREADS && LINUXTHREADS_OLD + default n + help + Enable debug output in libpthread. This is only useful when doing + development in libpthread itself. + + Otherwise, answer N. + +config DOSTRIP + bool "Strip libraries and executables" + default y + depends on !DODEBUG + help + Say Y here if you do wish to strip all uClibc libraries and + executables. No stripping increases the size of the binaries + considerably, but makes it possible to debug uClibc libraries. + Most people will answer Y. + +config DOASSERTS + bool "Build uClibc with run-time assertion testing" + default n + help + Say Y here to include runtime assertion tests. + This enables runtime assertion testing in some code, which can + increase the size of the library and incur runtime overhead. + If you say N, then this testing will be disabled. + +config SUPPORT_LD_DEBUG + bool "Build the shared library loader with debugging support" + depends on HAVE_SHARED + default n + help + Answer Y here to enable all the extra code needed to debug the uClibc + native shared library loader. The level of debugging noise that is + generated depends on the LD_DEBUG environment variable... Just set + LD_DEBUG to something like: 'LD_DEBUG=token1,token2,.. prog' to + debug your application. Diagnostic messages will then be printed to + the stderr. + + For now these debugging tokens are available: + detail provide more information for some options + move display copy processing + symbols display symbol table processing + reloc display relocation processing; detail shows the + relocation patch + nofixups never fixes up jump relocations + bindings displays the resolve processing (function calls); + detail shows the relocation patch + all Enable everything! + + The additional environment variable: + LD_DEBUG_OUTPUT=file + redirects the diagnostics to an output file created using + the specified name and the process id as a suffix. + + An excellent start is simply: + $ LD_DEBUG=binding,move,symbols,reloc,detail ./appname + or to log everything to a file named 'logfile', try this + $ LD_DEBUG=all LD_DEBUG_OUTPUT=logfile ./appname + + If you are doing development and want to debug uClibc's shared library + loader, answer Y. Mere mortals answer N. + +config SUPPORT_LD_DEBUG_EARLY + bool "Build the shared library loader with early debugging support" + depends on HAVE_SHARED + default n + help + Answer Y here to if you find the uClibc shared library loader is + crashing or otherwise not working very early on. This is typical + only when starting a new port when you haven't figured out how to + properly get the values for argc, argv, environ, etc. This method + allows a degree of visibility into the very early shared library + loader initialization process. If you are doing development and want + to debug the uClibc shared library loader early initialization, + answer Y. Mere mortals answer N. + +config UCLIBC_MALLOC_DEBUGGING + bool "Build malloc with debugging support" + depends on MALLOC || MALLOC_STANDARD + default n + help + Answer Y here to compile extra debugging support code into malloc. + Malloc debugging output may then be enabled at runtime using the + MALLOC_DEBUG environment variable. + + The value of MALLOC_DEBUG should be an integer, which is interpreted + as a bitmask with the following bits: + 1 - do extra consistency checking + 2 - output messages for malloc/free calls and OS + allocation calls + 4 - output messages for the `MMB' layer + 8 - output messages for internal malloc heap manipulation + calls + + Because this increases the size of malloc appreciably (due to strings + etc), you should say N unless you need to debug a malloc problem. + +config WARNINGS + string "Compiler Warnings" + default "-Wall" + help + Set this to the set of gcc warnings you wish to see while compiling. + +config EXTRA_WARNINGS + bool "Enable extra annoying warnings" + default n + help + If you wish to build with extra warnings enabled, say Y here. + +config DOMULTI + bool "Compile all sources at once into an object" + default n + help + Set this to compile all sources at once into an object (IMA). + This mode of compilation uses alot of memory but may produce + smaller binaries. + + Note that you need a very recent GCC for this to work, like + gcc >= 4.3 plus eventually some patches. + + If unsure, keep the default of N. + +config UCLIBC_MJN3_ONLY + bool "Manuel's hidden warnings" + default n + help + Answer Y here to see all Manuel's personal notes, warnings, and todos. + + Most people will answer N. + +endmenu diff --git a/extra/Configs/Config.in.arch b/extra/Configs/Config.in.arch new file mode 100644 index 0000000..f4a44ef --- /dev/null +++ b/extra/Configs/Config.in.arch @@ -0,0 +1,209 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + + +# +# Binary format +# +if !ARCH_USE_MMU +choice + prompt "Target File Format" +config UCLIBC_FORMAT_ELF + bool "ELF" + depends on ARCH_USE_MMU +config UCLIBC_FORMAT_FDPIC_ELF + bool "FDPIC ELF" + depends on !ARCH_USE_MMU +config UCLIBC_FORMAT_FLAT + bool "STATIC FLAT" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO +config UCLIBC_FORMAT_FLAT_SEP_DATA + bool "STATIC FLAT (sep-data)" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO +config UCLIBC_FORMAT_SHARED_FLAT + bool "SHARED FLAT" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO + help + Pick this one if you are using uClinux and wish to build + uClibc as a flat-format shared library. +endchoice +endif +if ARCH_USE_MMU +comment "Using ELF file format" +endif + +config UCLIBC_SHARED_FLAT_ID + int "Shared library ID" + default 1 + depends on UCLIBC_FORMAT_SHARED_FLAT + help + When using flat shared libraries, every library has a unique + system-wide identifier. Identifier 0 is reserved for + executables and true shared libraries have identifiers + starting at 1. The maximum shared library identifier is + determined by the kernel and is usually 3. Shared library + N must be available on the target system as "/lib/libN.so". + + When a shared C library is used, it usually has identifier 1, + but you can use this option to select a different identifier + if you need to. + + + +# +# Endian Format +# +config ARCH_ANY_ENDIAN + bool +config ARCH_BIG_ENDIAN + bool +config ARCH_LITTLE_ENDIAN + bool +if ARCH_ANY_ENDIAN +choice + prompt "Target Processor Endianness" + help + This is the endianness you wish to use. Choose either Big + Endian, or Little Endian. +config ARCH_WANTS_BIG_ENDIAN + bool "Big Endian" + select ARCH_BIG_ENDIAN +config ARCH_WANTS_LITTLE_ENDIAN + bool "Little Endian" + select ARCH_LITTLE_ENDIAN +endchoice +endif +# if the arch only supports one endian, just display the setting +if !ARCH_ANY_ENDIAN && ARCH_LITTLE_ENDIAN +comment "Using Little Endian" +endif +if !ARCH_ANY_ENDIAN && ARCH_BIG_ENDIAN +comment "Using Big Endian" +endif + +config ARCH_HAS_NO_MMU + bool +if ARCH_HAS_NO_MMU +comment "Target CPU lacks a memory management unit (MMU)" +endif + +config ARCH_HAS_MMU + bool "Target CPU has a memory management unit (MMU)" + depends on !ARCH_HAS_NO_MMU + default y + help + If your target CPU does not have a memory management unit (MMU), + then answer N here. Normally, Linux runs on systems with an MMU. + If you are building a uClinux system, answer N. + + Most people will answer Y. + +config ARCH_USE_MMU + bool "Do you want to utilize the MMU?" + depends on ARCH_HAS_MMU + default y + help + If your target CPU has a MMU, and you wish to actually utilize it, + then answer Y here. Normal Linux requires an MMU. + + If you're unsure, answer Y. + +config UCLIBC_HAS_FLOATS + bool "Enable floating point number support" + default y + help + This option allows you to entirely omit all floating point number + support from uClibc. This will cause floating point functions like + strtod() to be omitted from uClibc. Other floating point functions, + such as printf() and scanf() will still be included in the library, + but will not contain support for floating point numbers. + + Answering N to this option can reduce the size of uClibc. + Most people will answer Y. + +config UCLIBC_HAS_FPU + bool "Target CPU has a floating point unit (FPU)" + depends on UCLIBC_HAS_FLOATS + default y + help + If your target CPU does not have a Floating Point Unit (FPU) or a + kernel FPU emulator, but you still wish to support floating point + functions, then uClibc will need to be compiled with soft floating + point support (-msoft-float). If your target CPU does not have an + FPU or an FPU emulator within the Linux kernel, then you should + answer N. + + Most people will answer Y. + +config UCLIBC_HAS_SOFT_FLOAT + bool + depends on UCLIBC_HAS_FLOATS && !UCLIBC_HAS_FPU + default y + +config DO_C99_MATH + bool "Enable full C99 math library support" + depends on UCLIBC_HAS_FLOATS + default n + help + If you want the uClibc math library to contain the full set C99 + math library features, then answer Y. If you leave this set to + N the math library will contain only the math functions that were + listed as part of the traditional POSIX/IEEE 1003.1b-1993 standard. + Leaving this option set to N will save around 35k on an x86 system. + + If your applications require the newer C99 math library functions, + then answer Y. + +config UCLIBC_HAS_FENV + bool "Enable C99 Floating-point environment" + depends on UCLIBC_HAS_FLOATS + default n + help + If you want the uClibc math library to contain the C99 floating + point environment, rounding and exception handling functions then + say Y here. + + NOTE: Supported architectures currently include: + i386 + +config UCLIBC_HAS_LONG_DOUBLE_MATH + bool "Enable long double support" + depends on DO_C99_MATH + depends on TARGET_i386 || TARGET_m68k || TARGET_sparc || TARGET_x86_64 || TARGET_powerpc + default y + help + If you want the uClibc math library to contain the full set of C99 + long double math library features, then answer Y. Don't enable it + for sparc w/ 32bit ABI. + +config KERNEL_HEADERS + string "Linux kernel header location" + default "/usr/include" + help + The kernel source you use to compile with should be the same + as the Linux kernel you run your apps on. uClibc doesn't even + try to achieve binary compatibility across kernel versions. + So don't expect, for example, uClibc compiled with Linux kernel + 2.0.x to implement lchown properly, since 2.0.x can't do that. + Similarly, if you compile uClibc vs Linux 2.4.x kernel headers, + but then run on Linux 2.0.x, lchown will be compiled into uClibc, + but won't work at all. You have been warned. + +config UCLIBC_UCLINUX_BROKEN_MUNMAP + bool + depends on !ARCH_USE_MMU + default y + +config EXCLUDE_BRK + bool + depends on !ARCH_USE_MMU + default y + +config HAVE_DOT_CONFIG + bool + default y diff --git a/extra/Configs/Config.m68k b/extra/Configs/Config.m68k new file mode 100644 index 0000000..95807c4 --- /dev/null +++ b/extra/Configs/Config.m68k @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "m68k" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN diff --git a/extra/Configs/Config.microblaze b/extra/Configs/Config.microblaze new file mode 100644 index 0000000..a89914e --- /dev/null +++ b/extra/Configs/Config.microblaze @@ -0,0 +1,21 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "microblaze" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_NO_MMU + +config ARCH_CFLAGS + string + +config CROSS + string + default "mb-" diff --git a/extra/Configs/Config.mips b/extra/Configs/Config.mips new file mode 100644 index 0000000..8350ea4 --- /dev/null +++ b/extra/Configs/Config.mips @@ -0,0 +1,77 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "mips" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +config ARCH_CFLAGS + string + default "-mno-split-addresses" + +choice + prompt "Target ABI" + default CONFIG_MIPS_O32_ABI + help + This is the ABI you wish to build use. Choose either O32, N32 + or N64. + +config CONFIG_MIPS_O32_ABI + bool "O32 ABI" + +config CONFIG_MIPS_N32_ABI + bool "N32 ABI" + +config CONFIG_MIPS_N64_ABI + bool "N64 ABI" + +endchoice + +choice + prompt "Target Processor Architecture" + default CONFIG_MIPS_ISA_1 if CONFIG_MIPS_O32_ABI + default CONFIG_MIPS_ISA_3 if CONFIG_MIPS_N32_ABI + default CONFIG_MIPS_ISA_3 if CONFIG_MIPS_N64_ABI + help + This selects the instruction set architecture of your MIPS CPU. This + information is used for optimizing purposes. To build a library that + will run on any MIPS CPU, you can specify "Generic (MIPS I)" here. + If you pick anything other than "Generic (MIPS I)," there is no + guarantee that uClibc will even run on anything other than the + selected processor type. + + You should probably select the MIPS ISA that best matches the + CPU you will be using on your device. uClibc will be tuned + for that architecture. + + If you don't know what to do, choose "Generic (MIPS I)" + +config CONFIG_MIPS_ISA_1 + bool "Generic (MIPS I)" + +config CONFIG_MIPS_ISA_2 + bool "MIPS II" + +config CONFIG_MIPS_ISA_3 + bool "MIPS III" + +config CONFIG_MIPS_ISA_4 + bool "MIPS IV" + +config CONFIG_MIPS_ISA_MIPS32 + bool "MIPS32" + +config CONFIG_MIPS_ISA_MIPS32R2 + bool "MIPS32r2" + +config CONFIG_MIPS_ISA_MIPS64 + bool "MIPS64" + +endchoice diff --git a/extra/Configs/Config.nios b/extra/Configs/Config.nios new file mode 100644 index 0000000..f1dbd6c --- /dev/null +++ b/extra/Configs/Config.nios @@ -0,0 +1,23 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "nios" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_LDSO + select HAVE_NO_PIC + +config ARCH_CFLAGS + string + default "-funaligned-struct-hack" + +config CROSS + string diff --git a/extra/Configs/Config.nios2 b/extra/Configs/Config.nios2 new file mode 100644 index 0000000..1f94555 --- /dev/null +++ b/extra/Configs/Config.nios2 @@ -0,0 +1,22 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "nios2" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_LDSO + select HAVE_NO_PIC + +config ARCH_CFLAGS + string + +config CROSS + string diff --git a/extra/Configs/Config.powerpc b/extra/Configs/Config.powerpc new file mode 100644 index 0000000..8ba267c --- /dev/null +++ b/extra/Configs/Config.powerpc @@ -0,0 +1,38 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "powerpc" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_MMU + +config ARCH_CFLAGS + string + +choice + prompt "Target Processor Type" + default CONFIG_CLASSIC + help + This is the processor core of your CPU. This information is used for + determining the correct assembler instructions to use for the core. + + The default is to build for a classic powerpc. + +config CONFIG_CLASSIC + bool "CLASSIC" + help + Classic powerpc architecture. + +config CONFIG_E500 + bool "E500" + help + e500 v1 and v2 core. + +endchoice diff --git a/extra/Configs/Config.sh b/extra/Configs/Config.sh new file mode 100644 index 0000000..8538bcc --- /dev/null +++ b/extra/Configs/Config.sh @@ -0,0 +1,55 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sh" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +config ARCH_CFLAGS + string + +choice + prompt "Target Processor Type" + default CONFIG_SH4 + help + This is the processor type of your CPU. This information is used for + optimizing purposes, as well as to determine if your CPU has an MMU, + an FPU, etc. If you pick the wrong CPU type, there is no guarantee + that uClibc will work at all.... + + Here are the available choices: + - "SH2A" Renesas SH-2A (SH7206) + - "SH2" SuperH SH-2 + - "SH3" SuperH SH-3 + - "SH4" SuperH SH-4 + +config CONFIG_SH2A + select ARCH_HAS_NO_MMU + select HAVE_NO_PIC + bool "SH2A" + +config CONFIG_SH2 + select ARCH_HAS_NO_MMU + bool "SH2" + +config CONFIG_SH3 + select ARCH_HAS_MMU + bool "SH3" + +config CONFIG_SH4 + select FORCE_SHAREABLE_TEXT_SEGMENTS + bool "SH4" + +endchoice + +config ARCH_HAS_BWD_MEMCPY + bool + default y + depends on CONFIG_SH4 diff --git a/extra/Configs/Config.sh64 b/extra/Configs/Config.sh64 new file mode 100644 index 0000000..54d738e --- /dev/null +++ b/extra/Configs/Config.sh64 @@ -0,0 +1,35 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sh64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +config ARCH_CFLAGS + string + +choice + prompt "Target Processor Type" + default CONFIG_SH5 + help + This is the processor type of your CPU. This information is used for + optimizing purposes, as well as to determine if your CPU has an MMU, + an FPU, etc. If you pick the wrong CPU type, there is no guarantee + that uClibc will work at all.... + + Here are the available choices: + - "SH5" SuperH SH-5 101, 103 + +config CONFIG_SH5 + select ARCH_HAS_MMU + select UCLIBC_HAS_LFS + bool "SH5" + +endchoice diff --git a/extra/Configs/Config.sparc b/extra/Configs/Config.sparc new file mode 100644 index 0000000..3b19f9d --- /dev/null +++ b/extra/Configs/Config.sparc @@ -0,0 +1,41 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sparc" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + +config ARCH_CFLAGS + string + +choice + prompt "Target Processor Type" + default CONFIG_SPARC_V8 + help + This is the processor type of your CPU. This information is used for + optimizing purposes. Building for a v8 SPARC is pretty safe nowadays. + + Warning: shared library support requires v8 or better, so building for + SPARC v7 will give you only static support. + +config CONFIG_SPARC_V7 + select ARCH_HAS_NO_SHARED + bool "SPARC v7" + +config CONFIG_SPARC_V8 + bool "SPARC v8" + +config CONFIG_SPARC_V9 + bool "SPARC v9" + +config CONFIG_SPARC_V9B + bool "SPARC v9b" + +endchoice diff --git a/extra/Configs/Config.v850 b/extra/Configs/Config.v850 new file mode 100644 index 0000000..a668bba --- /dev/null +++ b/extra/Configs/Config.v850 @@ -0,0 +1,22 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "v850" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select HAVE_NO_PIC + +config ARCH_CFLAGS + string + +config CROSS + string + default "v850e-elf-" diff --git a/extra/Configs/Config.vax b/extra/Configs/Config.vax new file mode 100644 index 0000000..4192e28 --- /dev/null +++ b/extra/Configs/Config.vax @@ -0,0 +1,24 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "vax" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_LDSO + +config ARCH_CFLAGS + string + +config ARCH_LDFLAGS + string + +config CROSS + string + default "vax-linux-uclibc-" diff --git a/extra/Configs/Config.x86_64 b/extra/Configs/Config.x86_64 new file mode 100644 index 0000000..7ae357f --- /dev/null +++ b/extra/Configs/Config.x86_64 @@ -0,0 +1,17 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "x86_64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + +config ARCH_CFLAGS + string diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa new file mode 100644 index 0000000..7513247 --- /dev/null +++ b/extra/Configs/Config.xtensa @@ -0,0 +1,12 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/kconfig-language.txt +# + +config TARGET_ARCH + string + default "xtensa" + +config ARCH_CFLAGS + string + diff --git a/extra/Configs/defconfigs/alpha b/extra/Configs/defconfigs/alpha new file mode 100644 index 0000000..05243d7 --- /dev/null +++ b/extra/Configs/defconfigs/alpha @@ -0,0 +1 @@ +TARGET_alpha=y diff --git a/extra/Configs/defconfigs/arm b/extra/Configs/defconfigs/arm new file mode 100644 index 0000000..aa67890 --- /dev/null +++ b/extra/Configs/defconfigs/arm @@ -0,0 +1 @@ +TARGET_arm=y diff --git a/extra/Configs/defconfigs/avr32 b/extra/Configs/defconfigs/avr32 new file mode 100644 index 0000000..0b890a2 --- /dev/null +++ b/extra/Configs/defconfigs/avr32 @@ -0,0 +1 @@ +TARGET_avr32=y diff --git a/extra/Configs/defconfigs/bfin b/extra/Configs/defconfigs/bfin new file mode 100644 index 0000000..fb5c5eb --- /dev/null +++ b/extra/Configs/defconfigs/bfin @@ -0,0 +1 @@ +TARGET_bfin=y diff --git a/extra/Configs/defconfigs/cris b/extra/Configs/defconfigs/cris new file mode 100644 index 0000000..4e98180 --- /dev/null +++ b/extra/Configs/defconfigs/cris @@ -0,0 +1 @@ +TARGET_cris=y diff --git a/extra/Configs/defconfigs/e1 b/extra/Configs/defconfigs/e1 new file mode 100644 index 0000000..e204c87 --- /dev/null +++ b/extra/Configs/defconfigs/e1 @@ -0,0 +1 @@ +TARGET_e1=y diff --git a/extra/Configs/defconfigs/frv b/extra/Configs/defconfigs/frv new file mode 100644 index 0000000..8230316 --- /dev/null +++ b/extra/Configs/defconfigs/frv @@ -0,0 +1 @@ +TARGET_frv=y diff --git a/extra/Configs/defconfigs/h8300 b/extra/Configs/defconfigs/h8300 new file mode 100644 index 0000000..66c4a33 --- /dev/null +++ b/extra/Configs/defconfigs/h8300 @@ -0,0 +1 @@ +TARGET_h8300=y diff --git a/extra/Configs/defconfigs/hppa b/extra/Configs/defconfigs/hppa new file mode 100644 index 0000000..6358dbd --- /dev/null +++ b/extra/Configs/defconfigs/hppa @@ -0,0 +1 @@ +TARGET_hppa=y diff --git a/extra/Configs/defconfigs/i386 b/extra/Configs/defconfigs/i386 new file mode 100644 index 0000000..7c35178 --- /dev/null +++ b/extra/Configs/defconfigs/i386 @@ -0,0 +1 @@ +TARGET_i386=y diff --git a/extra/Configs/defconfigs/i960 b/extra/Configs/defconfigs/i960 new file mode 100644 index 0000000..5abe6dc --- /dev/null +++ b/extra/Configs/defconfigs/i960 @@ -0,0 +1 @@ +TARGET_i960=y diff --git a/extra/Configs/defconfigs/ia64 b/extra/Configs/defconfigs/ia64 new file mode 100644 index 0000000..7f26470 --- /dev/null +++ b/extra/Configs/defconfigs/ia64 @@ -0,0 +1 @@ +TARGET_ia64=y diff --git a/extra/Configs/defconfigs/m68k b/extra/Configs/defconfigs/m68k new file mode 100644 index 0000000..da874a8 --- /dev/null +++ b/extra/Configs/defconfigs/m68k @@ -0,0 +1 @@ +TARGET_m68k=y diff --git a/extra/Configs/defconfigs/microblaze b/extra/Configs/defconfigs/microblaze new file mode 100644 index 0000000..4401200 --- /dev/null +++ b/extra/Configs/defconfigs/microblaze @@ -0,0 +1 @@ +TARGET_microblaze=y diff --git a/extra/Configs/defconfigs/mips b/extra/Configs/defconfigs/mips new file mode 100644 index 0000000..0114a9b --- /dev/null +++ b/extra/Configs/defconfigs/mips @@ -0,0 +1 @@ +TARGET_mips=y diff --git a/extra/Configs/defconfigs/nios b/extra/Configs/defconfigs/nios new file mode 100644 index 0000000..2a110b8 --- /dev/null +++ b/extra/Configs/defconfigs/nios @@ -0,0 +1 @@ +TARGET_nios=y diff --git a/extra/Configs/defconfigs/nios2 b/extra/Configs/defconfigs/nios2 new file mode 100644 index 0000000..870bd53 --- /dev/null +++ b/extra/Configs/defconfigs/nios2 @@ -0,0 +1 @@ +TARGET_nios2=y diff --git a/extra/Configs/defconfigs/powerpc b/extra/Configs/defconfigs/powerpc new file mode 100644 index 0000000..3868897 --- /dev/null +++ b/extra/Configs/defconfigs/powerpc @@ -0,0 +1 @@ +TARGET_powerpc=y diff --git a/extra/Configs/defconfigs/sh b/extra/Configs/defconfigs/sh new file mode 100644 index 0000000..650d280 --- /dev/null +++ b/extra/Configs/defconfigs/sh @@ -0,0 +1 @@ +TARGET_sh=y diff --git a/extra/Configs/defconfigs/sh64 b/extra/Configs/defconfigs/sh64 new file mode 100644 index 0000000..4f23a54 --- /dev/null +++ b/extra/Configs/defconfigs/sh64 @@ -0,0 +1 @@ +TARGET_sh64=y diff --git a/extra/Configs/defconfigs/sparc b/extra/Configs/defconfigs/sparc new file mode 100644 index 0000000..c2c74cb --- /dev/null +++ b/extra/Configs/defconfigs/sparc @@ -0,0 +1 @@ +TARGET_sparc=y diff --git a/extra/Configs/defconfigs/v850 b/extra/Configs/defconfigs/v850 new file mode 100644 index 0000000..046d5d4 --- /dev/null +++ b/extra/Configs/defconfigs/v850 @@ -0,0 +1 @@ +TARGET_v850=y diff --git a/extra/Configs/defconfigs/vax b/extra/Configs/defconfigs/vax new file mode 100644 index 0000000..77a464e --- /dev/null +++ b/extra/Configs/defconfigs/vax @@ -0,0 +1 @@ +TARGET_vax=y diff --git a/extra/Configs/defconfigs/x86_64 b/extra/Configs/defconfigs/x86_64 new file mode 100644 index 0000000..e03a36a --- /dev/null +++ b/extra/Configs/defconfigs/x86_64 @@ -0,0 +1 @@ +TARGET_x86_64=y diff --git a/extra/Makefile b/extra/Makefile new file mode 100644 index 0000000..1dae357 --- /dev/null +++ b/extra/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: objs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/Makefile.in b/extra/Makefile.in new file mode 100644 index 0000000..76f504d --- /dev/null +++ b/extra/Makefile.in @@ -0,0 +1,9 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)extra/locale/Makefile.in +include $(top_srcdir)extra/config/Makefile.in diff --git a/extra/config/.gitignore b/extra/config/.gitignore new file mode 100644 index 0000000..b49584c --- /dev/null +++ b/extra/config/.gitignore @@ -0,0 +1,19 @@ +# +# Generated files +# +config* +lex.*.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +lkc_defs.h + +# +# configuration programs +# +conf +mconf +qconf +gconf +kxgettext diff --git a/extra/config/Makefile b/extra/config/Makefile new file mode 100644 index 0000000..836f1f9 --- /dev/null +++ b/extra/config/Makefile @@ -0,0 +1,45 @@ +obj := . +src := . +top_srcdir=../../ +top_builddir=../../ +srctree := . +include $(top_builddir)Rules.mak + +include Makefile.kconfig + +ifeq ($(findstring mconf,$(MAKECMDGOALS)),mconf) +hostprogs-y += mconf +endif + +-include .depend +.depend: $(wildcard *.h *.c) + $(Q)$(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) -MM *.c > .depend 2>/dev/null || : + +__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) +host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) +host-cmulti := $(foreach m,$(__hostprogs),\ + $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) +host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) + +$(host-csingle): %: %.c + $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $< $(HOST_LOADLIBES) -o $@ + +$(host-cmulti): %: $(host-cobjs) $(host-cshlib) + $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) $($@-objs) $(HOST_LOADLIBES) -o $@ + +$(host-cobjs): %.o: %.c + $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS) $(HOSTCFLAGS_$@) -c $< -o $@ + +$(obj)/%:: $(src)/%_shipped + $(Q)cat $< > $@ + +clean: + $(Q)rm -f $(clean-files) conf +distclean: clean + $(Q)rm -f $(lxdialog) $(conf-objs) $(mconf-objs) $(kxgettext-objs) \ + $(hostprogs-y) $(qconf-cxxobjs) $(qconf-objs) $(gconf-objs) \ + .depend + $(Q)rm -r -f $(top_builddir)include/config + +FORCE: +.PHONY: FORCE clean distclean diff --git a/extra/config/Makefile.kconfig b/extra/config/Makefile.kconfig new file mode 100644 index 0000000..fa1a7d5 --- /dev/null +++ b/extra/config/Makefile.kconfig @@ -0,0 +1,285 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config + +Kconfig := arch/$(SRCARCH)/Kconfig + +xconfig: $(obj)/qconf + $< $(Kconfig) + +gconfig: $(obj)/gconf + $< $(Kconfig) + +menuconfig: $(obj)/mconf + $< $(Kconfig) + +config: $(obj)/conf + $< $(Kconfig) + +oldconfig: $(obj)/conf + $< -o $(Kconfig) + +silentoldconfig: $(obj)/conf + $< -s $(Kconfig) + +# Create new linux.pot file +# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files +# The symlink is used to repair a deficiency in arch/um +update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h + $(Q)echo " GEN config" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=scripts/kconfig/POTFILES.in \ + --output $(obj)/config.pot + $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot + $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch + $(Q)(for i in `ls arch/*/Kconfig`; \ + do \ + echo " GEN $$i"; \ + $(obj)/kxgettext $$i \ + >> $(obj)/config.pot; \ + done ) + $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ + --output $(obj)/linux.pot + $(Q)rm -f arch/um/Kconfig.arch + $(Q)rm -f $(obj)/config.pot + +PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig + +randconfig: $(obj)/conf + $< -r $(Kconfig) + +allyesconfig: $(obj)/conf + $< -y $(Kconfig) + +allnoconfig: $(obj)/conf + $< -n $(Kconfig) + +allmodconfig: $(obj)/conf + $< -m $(Kconfig) + +defconfig: $(obj)/conf +ifeq ($(KBUILD_DEFCONFIG),) + $< -d $(Kconfig) +else + @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" + $(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) +endif + +%_defconfig: $(obj)/conf + $(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig) + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a QT based front-end' + @echo ' gconfig - Update current config utilising a GTK based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' silentoldconfig - Same as oldconfig, but quietly' + @echo ' randconfig - New config with random answer to all options' + @echo ' defconfig - New config with default answer to all options' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allnoconfig - New config where all options are answered with no' + +# lxdialog stuff +check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) +HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +HOST_EXTRACFLAGS += -DLOCALE + + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# mconf: Used for the mconfig target. +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +kxgettext-objs := kxgettext.o zconf.tab.o + +hostprogs-y := conf qconf gconf kxgettext + +ifeq ($(MAKECMDGOALS),menuconfig) + hostprogs-y += mconf +endif + +ifeq ($(MAKECMDGOALS),xconfig) + qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) + gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) +qconf-cxxobjs := qconf.o +qconf-objs := kconfig_load.o zconf.tab.o +endif + +ifeq ($(gconf-target),1) +gconf-objs := gconf.o kconfig_load.o zconf.tab.o +endif + +clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ + .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h +clean-files += mconf qconf gconf +clean-files += config.pot linux.pot + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += $(obj)/dochecklxdialog +$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog +$(obj)/dochecklxdialog: + $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) + +always := dochecklxdialog + +# Add environment specific flags +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) + +# generated files seem to need this to find local include files +HOSTCFLAGS_lex.zconf.o := -I$(src) +HOSTCFLAGS_zconf.tab.o := -I$(src) + +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -D LKC_DIRECT_LINK + +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +$(obj)/.tmp_qtcheck: $(src)/Makefile +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ + else \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo "*"; \ + echo "* Unable to find the QT3 installation. Please make sure that"; \ + echo "* the QT3 development package is correctly installed and"; \ + echo "* either install pkg-config or set the QTDIR environment"; \ + echo "* variable to the correct location."; \ + echo "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ + fi; \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ + echo "*"; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ + echo "*"; \ + moc="/usr/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo "*"; \ + echo "* GTK+ is present but version >= 2.0.0 is required."; \ + echo "*"; \ + false; \ + fi \ + else \ + echo "*"; \ + echo "* Unable to find the GTK+ installation. Please make sure that"; \ + echo "* the GTK+ 2.0 development package is correctly installed..."; \ + echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo "*"; \ + false; \ + fi +endif + +$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c + +$(obj)/kconfig_load.o: $(obj)/lkc_defs.h + +$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h + +$(obj)/gconf.o: $(obj)/lkc_defs.h + +$(obj)/%.moc: $(src)/%.h + $(KC_QT_MOC) -i $< -o $@ + +$(obj)/lkc_defs.h: $(src)/lkc_proto.h + sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' + +# Extract gconf menu items for I18N support +$(obj)/gconf.glade.h: $(obj)/gconf.glade + intltool-extract --type=gettext/glade $(obj)/gconf.glade + +### +# The following requires flex/bison/gperf +# By default we use the _shipped versions, uncomment the following line if +# you are modifying the flex/bison src. +# LKC_GENPARSER := 1 + +ifdef LKC_GENPARSER + +$(obj)/zconf.tab.c: $(src)/zconf.y +$(obj)/lex.zconf.c: $(src)/zconf.l +$(obj)/zconf.hash.c: $(src)/zconf.gperf + +%.tab.c: %.y + bison -l -b $* -p $(notdir $*) $< + cp $@ $@_shipped + +lex.%.c: %.l + flex -L -P$(notdir $*) -o$@ $< + cp $@ $@_shipped + +%.hash.c: %.gperf + gperf < $< > $@ + cp $@ $@_shipped + +endif diff --git a/extra/config/POTFILES.in b/extra/config/POTFILES.in new file mode 100644 index 0000000..9674573 --- /dev/null +++ b/extra/config/POTFILES.in @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff --git a/extra/config/README.uClibc b/extra/config/README.uClibc new file mode 100644 index 0000000..b05cabc --- /dev/null +++ b/extra/config/README.uClibc @@ -0,0 +1,19 @@ +This is a copy of the kconfig code in the kernel tweaked to suit uClibc. + +To update: + cp -r /usr/src/linux/scripts/kconfig extra/config.new + cd extra/config.new + cp /usr/src/linux/Documentation/kbuild/kconfig-language.txt . + mv Makefile Makefile.kconfig + zcat ../config/kconfig-to-uclibc.patch.gz | patch -p1 + cp ../config/README.uClibc . + cp ../config/Makefile . + cd .. + rm -rf config + mv config.new config + +Then verify the toplevel targets work: + config + defconfig + menuconfig + oldconfig diff --git a/extra/config/check.sh b/extra/config/check.sh new file mode 100755 index 0000000..fa59cbf --- /dev/null +++ b/extra/config/check.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Needed for systems without gettext +$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi + diff --git a/extra/config/conf.c b/extra/config/conf.c new file mode 100644 index 0000000..02b2600 --- /dev/null +++ b/extra/config/conf.c @@ -0,0 +1,602 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); + +enum { + ask_all, + ask_new, + ask_silent, + set_default, + set_yes, + set_mod, + set_no, + set_random +} input_mode = ask_all; +char *defconfig_file; + +static int indent = 1; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[128]; +static struct menu *rootEntry; + +static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); + +static const char *get_help(struct menu *menu) +{ + if (menu_has_help(menu)) + return _(menu_get_help(menu)); + else + return nohelp_text; +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case ask_new: + case ask_silent: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, 128, stdin); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + printf("\n%s\n", get_help(menu)); + def = NULL; + break; + } + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + int type; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + type = sym_get_type(sym); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + printf("\n%s\n", get_help(menu)); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + int type; + bool is_new; + + sym = menu->sym; + type = sym_get_type(sym); + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case ask_new: + case ask_silent: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, 128, stdin); + strip(line); + if (line[0] == '?') { + printf("\n%s\n", get_help(menu)); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[strlen(line) - 1] == '?') { + printf("\n%s\n", get_help(child)); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if (input_mode == ask_silent && rootEntry != menu) { + check_conf(menu); + return; + } + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +int main(int ac, char **av) +{ + int opt; + const char *name; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { + switch (opt) { + case 'o': + input_mode = ask_silent; + break; + case 's': + input_mode = ask_silent; + sync_kconfig = 1; + break; + case 'd': + input_mode = set_default; + break; + case 'D': + input_mode = set_default; + defconfig_file = optarg; + break; + case 'n': + input_mode = set_no; + break; + case 'm': + input_mode = set_mod; + break; + case 'y': + input_mode = set_yes; + break; + case 'r': + input_mode = set_random; + srand(time(NULL)); + break; + case 'h': + printf(_("See README for usage info\n")); + exit(0); + break; + default: + fprintf(stderr, _("See README for usage info\n")); + exit(1); + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + if (stat(".config", &tmpstat)) { + fprintf(stderr, _("***\n" + "*** You have not yet configured!\n" + "*** (missing .config file)\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n")); + exit(1); + } + } + + switch (input_mode) { + case set_default: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case ask_silent: + case ask_all: + case ask_new: + conf_read(NULL); + break; + case set_no: + case set_mod: + case set_yes: + case set_random: + name = getenv("KCONFIG_ALLCONFIG"); + if (name && !stat(name, &tmpstat)) { + conf_read_simple(name, S_DEF_USER); + break; + } + switch (input_mode) { + case set_no: name = "allno.config"; break; + case set_mod: name = "allmod.config"; break; + case set_yes: name = "allyes.config"; break; + case set_random: name = "allrandom.config"; break; + default: break; + } + if (!stat(name, &tmpstat)) + conf_read_simple(name, S_DEF_USER); + else if (!stat("all.config", &tmpstat)) + conf_read_simple("all.config", S_DEF_USER); + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = isatty(0) && isatty(1) && isatty(2); + } + + switch (input_mode) { + case set_no: + conf_set_all_new_symbols(def_no); + break; + case set_yes: + conf_set_all_new_symbols(def_yes); + break; + case set_mod: + conf_set_all_new_symbols(def_mod); + break; + case set_random: + conf_set_all_new_symbols(def_random); + break; + case set_default: + conf_set_all_new_symbols(def_default); + break; + case ask_new: + case ask_all: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = ask_silent; + /* fall through */ + case ask_silent: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} diff --git a/extra/config/confdata.c b/extra/config/confdata.c new file mode 100644 index 0000000..9da48eb --- /dev/null +++ b/extra/config/confdata.c @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "extra/Configs/defconfigs/$ARCH"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + break; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char line[1024]; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) + return 1; + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + printf(_("#\n" + "# using defaults found in %s\n" + "#\n"), name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (fgets(line, sizeof(line), in)) { + conf_lineno++; + sym = NULL; + switch (line[0]) { + case '#': + if (line[1] != ' ') + continue; + p = strchr(line + 2, ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2); + if (!sym) { + sym_add_change_count(1); + break; + } + } else { + sym = sym_lookup(line + 2, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + p = strchr(line, '='); + if (!p) { + conf_warning("unexpected data '%s'", line); + continue; + } + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line); + if (!sym) { + sym_add_change_count(1); + break; + } + } else { + sym = sym_lookup(line, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + break; + case '\r': + case '\n': + break; + default: + conf_warning("unexpected data"); + continue; + } + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym, *choice_sym; + struct property *prop; + struct expr *e; + int i, flags; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + goto sym_ok; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + goto sym_ok; + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + goto sym_ok; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + goto sym_ok; + conf_unsaved++; + /* maybe print value in verbose mode... */ + sym_ok: + if (!sym_is_choice(sym)) + continue; + /* The choice symbol only has a set value (and thus is not new) + * if all its visible childs have values. + */ + prop = sym_get_choice_prop(sym); + flags = sym->flags; + expr_list_for_each_sym(prop->expr, e, choice_sym) + if (choice_sym->visible != no) + flags &= choice_sym->flags; + sym->flags &= flags | ~SYMBOL_DEF_USER; + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + char dirname[128], tmpname[128], newname[128]; + int type, l; + const char *str; + time_t now; + int use_timestamp = 1; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + time(&now); + env = getenv("KCONFIG_NOTIMESTAMP"); + if (env && *env) + use_timestamp = 0; + + fprintf(out, _("#\n" + "# Automatically generated make config: don't edit\n" + "# Version: %s\n" + "%s%s" + "#\n"), + sym_get_string_value(sym), + use_timestamp ? "# " : "", + use_timestamp ? ctime(&now) : ""); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + type = sym->type; + if (type == S_TRISTATE) { + sym_calc_value(modules_sym); + if (modules_sym->curr.tri == no) + type = S_BOOLEAN; + } + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + fprintf(out, "# %s is not set\n", sym->name); + break; + case mod: + fprintf(out, "%s=m\n", sym->name); + break; + case yes: + fprintf(out, "%s=y\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "%s=\"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str++); + } + fputs("\"\n", out); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "%s=%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "%s=%s\n", sym->name, str); + break; + } + } + + next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + printf(_("#\n" + "# configuration written to %s\n" + "#\n"), newname); + + sym_set_change_count(0); + + return 0; +} + +int conf_split_config(void) +{ + char *name, path[128]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = getenv("KCONFIG_AUTOCONFIG"); + if (!name) + name = "include/config/auto.conf"; + conf_read_simple(name, S_DEF_AUTO); + + if (chdir("include/config")) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("../..")) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *str; + char *name; + FILE *out, *out_h; + time_t now; + int i, l; + + sym_clear_all_valid(); + + file_write_dep("include/config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + return 1; + } + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + time(&now); + fprintf(out, "#\n" + "# Automatically generated make config: don't edit\n" + "# Version: %s\n" + "# %s" + "#\n", + sym_get_string_value(sym), ctime(&now)); + fprintf(out_h, "/*\n" + " * Automatically generated C config: don't edit\n" + " * Version: %s\n" + " * %s" + " */\n" + "#define AUTOCONF_INCLUDED\n", + sym_get_string_value(sym), ctime(&now)); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + break; + case mod: + fprintf(out, "CONFIG_%s=m\n", sym->name); + fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); + break; + case yes: + fprintf(out, "%s=y\n", sym->name); + fprintf(out_h, "#define %s 1\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "%s=\"", sym->name); + fprintf(out_h, "#define %s \"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + fwrite(str, l, 1, out_h); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str); + fprintf(out_h, "\\%c", *str); + str++; + } + fputs("\"\n", out); + fputs("\"\n", out_h); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "%s=%s\n", sym->name, str); + fprintf(out_h, "#define %s 0x%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "%s=%s\n", sym->name, str); + fprintf(out_h, "#define %s %s\n", sym->name, str); + break; + default: + break; + } + } + fclose(out); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/config/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_AUTOCONFIG"); + if (!name) + name = "include/config/auto.conf"; + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + + +void conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + struct property *prop; + struct expr *e; + int i, cnt, def; + + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + sym->def[S_DEF_USER].tri = (tristate)(rand() % 3); + break; + default: + continue; + } + if (!sym_is_choice(sym) || mode != def_random) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + if (modules_sym) + sym_calc_value(modules_sym); + + if (mode != def_random) + return; + + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + prop = sym_get_choice_prop(csym); + def = -1; + while (1) { + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (sym->visible == no) + continue; + if (def == cnt++) { + csym->def[S_DEF_USER].val = sym; + break; + } + } + if (def >= 0 || cnt < 2) + break; + def = (rand() % cnt) + 1; + } + csym->flags |= SYMBOL_DEF_USER; + } +} diff --git a/extra/config/expr.c b/extra/config/expr.c new file mode 100644 index 0000000..579ece4 --- /dev/null +++ b/extra/config/expr.c @@ -0,0 +1,1106 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = malloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + fwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + str_append((struct gstr*)data, str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/extra/config/expr.h b/extra/config/expr.h new file mode 100644 index 0000000..9d4cba1 --- /dev/null +++ b/extra/config/expr.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + char *name; + int lineno; + int flags; +}; + +#define FILE_BUSY 0x0001 +#define FILE_SCANNED 0x0002 + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[4]; + tristate visible; + int flags; + struct property *prop; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 +#define SYMBOL_CHECK 0x0008 +#define SYMBOL_CHOICE 0x0010 +#define SYMBOL_CHOICEVAL 0x0020 +#define SYMBOL_VALID 0x0080 +#define SYMBOL_OPTIONAL 0x0100 +#define SYMBOL_WRITE 0x0200 +#define SYMBOL_CHANGED 0x0400 +#define SYMBOL_AUTO 0x1000 +#define SYMBOL_CHECKED 0x2000 +#define SYMBOL_WARNED 0x8000 +#define SYMBOL_DEF 0x10000 +#define SYMBOL_DEF_USER 0x10000 +#define SYMBOL_DEF_AUTO 0x20000 +#define SYMBOL_DEF3 0x40000 +#define SYMBOL_DEF4 0x80000 + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 257 +#define SYMBOL_HASHMASK 0xff + +enum prop_type { + P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, + P_SELECT, P_RANGE, P_ENV +}; + +struct property { + struct property *next; + struct symbol *sym; + enum prop_type type; + const char *text; + struct expr_value visible; + struct expr *expr; + struct menu *menu; + struct file *file; + int lineno; +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +#ifndef SWIG + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/extra/config/gconf.c b/extra/config/gconf.c new file mode 100644 index 0000000..540a0ff --- /dev/null +++ b/extra/config/gconf.c @@ -0,0 +1,1632 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean show_all = FALSE; +static gboolean show_debug = FALSE; +static gboolean resizeable = FALSE; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + + +const char *dbg_print_stype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == S_UNKNOWN) + strcpy(buf, "unknown"); + if (val == S_BOOLEAN) + strcpy(buf, "boolean"); + if (val == S_TRISTATE) + strcpy(buf, "tristate"); + if (val == S_INT) + strcpy(buf, "int"); + if (val == S_HEX) + strcpy(buf, "hex"); + if (val == S_STRING) + strcpy(buf, "string"); + if (val == S_OTHER) + strcpy(buf, "other"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_ptype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == P_UNKNOWN) + strcpy(buf, "unknown"); + if (val == P_PROMPT) + strcpy(buf, "prompt"); + if (val == P_COMMENT) + strcpy(buf, "comment"); + if (val == P_MENU) + strcpy(buf, "menu"); + if (val == P_DEFAULT) + strcpy(buf, "default"); + if (val == P_CHOICE) + strcpy(buf, "choice"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + char title[256]; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + g_signal_emit_by_name(widget, "clicked"); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + g_signal_emit_by_name(widget, "clicked"); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + g_signal_emit_by_name(widget, "clicked"); + break; + } +#endif + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + sprintf(title, _("uClibc v%s Configuration"), + getenv("VERSION")); + gtk_window_set_title(GTK_WINDOW(main_wnd), title); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); +static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, + gchar * arg1, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + /*g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(renderer_toggled), NULL); */ + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + gchar *name; + const char *help; + + help = menu_get_help(menu); + + /* Gettextize if the help text not empty */ + if ((help != 0) && (help[0] != 0)) + help = _(help); + + if (menu->sym && menu->sym->name) + name = g_strdup_printf(menu->sym->name); + else + name = g_strdup(""); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, " ", 1); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, + NULL); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; + + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); // instead of update_tree to speed-up +} + + +void +on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; + update_tree(&rootmenu, NULL); +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "for uClibc.\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static void renderer_toggled(GtkCellRendererToggle * cell, + gchar * path_string, gpointer user_data) +{ + GtkTreePath *path, *sel_path = NULL; + GtkTreeIter iter, sel_iter; + GtkTreeSelection *sel; + struct menu *menu; + + path = gtk_tree_path_new_from_string(path_string); + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); + if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) + sel_path = gtk_tree_model_get_path(model2, &sel_iter); + if (!sel_path) + goto out1; + if (gtk_tree_path_compare(path, sel_path)) + goto out2; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + toggle_sym_value(menu); + + out2: + gtk_tree_path_free(sel_path); + out1: + gtk_tree_path_free(path); +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && sym_has_value(sym) ? "(NEW)" : ""); + + if (show_all && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct property *prop; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + prop = child1->prompt; + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if (!menu_is_visible(child1) && !show_all) { // remove node + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if (menu_is_visible(child) || show_all) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + dbg_print_ptype(ptype); + printf(" | "); + if (sym) { + dbg_print_stype(sym->type); + printf(" | "); + dbg_print_flags(sym->flags); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + +#ifndef LKC_DIRECT_LINK + kconfig_load(); +#endif + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff --git a/extra/config/gconf.glade b/extra/config/gconf.glade new file mode 100644 index 0000000..2e2e2f9 --- /dev/null +++ b/extra/config/gconf.glade @@ -0,0 +1,648 @@ + + + + + + + True + Gtk uClibc Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show all options + Show all _options + True + False + + + + + + + True + Show masked options + Show _debug info + True + False + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + True + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff --git a/extra/config/images.c b/extra/config/images.c new file mode 100644 index 0000000..d4f84bd --- /dev/null +++ b/extra/config/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/extra/config/kconfig-language.txt b/extra/config/kconfig-language.txt new file mode 100644 index 0000000..c412c24 --- /dev/null +++ b/extra/config/kconfig-language.txt @@ -0,0 +1,379 @@ +Introduction +------------ + +The configuration database is a collection of configuration options +organized in a tree structure: + + +- Code maturity level options + | +- Prompt for development and/or incomplete code/drivers + +- General setup + | +- Networking support + | +- System V IPC + | +- BSD Process Accounting + | +- Sysctl support + +- Loadable module support + | +- Enable loadable module support + | +- Set version information on all module symbols + | +- Kernel module loader + +- ... + +Every entry has its own dependencies. These dependencies are used +to determine the visibility of an entry. Any child entry is only +visible if its parent entry is also visible. + +Menu entries +------------ + +Most entries define a config option; all other entries help to organize +them. A single configuration option is defined like this: + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + help + Usually, modules have to be recompiled whenever you switch to a new + kernel. ... + +Every line starts with a key word and can be followed by multiple +arguments. "config" starts a new config entry. The following lines +define attributes for this config option. Attributes can be the type of +the config option, input prompt, dependencies, help text and default +values. A config option can be defined multiple times with the same +name, but every definition can have only a single input prompt and the +type must not conflict. + +Menu attributes +--------------- + +A menu entry can have a number of attributes. Not all of them are +applicable everywhere (see syntax). + +- type definition: "bool"/"tristate"/"string"/"hex"/"int" + Every config option must have a type. There are only two basic types: + tristate and string; the other types are based on these two. The type + definition optionally accepts an input prompt, so these two examples + are equivalent: + + bool "Networking support" + and + bool + prompt "Networking support" + +- input prompt: "prompt" ["if" ] + Every menu entry can have at most one prompt, which is used to display + to the user. Optionally dependencies only for this prompt can be added + with "if". + +- default value: "default" ["if" ] + A config option can have any number of default values. If multiple + default values are visible, only the first defined one is active. + Default values are not limited to the menu entry where they are + defined. This means the default can be defined somewhere else or be + overridden by an earlier definition. + The default value is only assigned to the config symbol if no other + value was set by the user (via the input prompt above). If an input + prompt is visible the default value is presented to the user and can + be overridden by him. + Optionally, dependencies only for this default value can be added with + "if". + +- type definition + default value: + "def_bool"/"def_tristate" ["if" ] + This is a shorthand notation for a type definition plus a value. + Optionally dependencies for this default value can be added with "if". + +- dependencies: "depends on" + This defines a dependency for this menu entry. If multiple + dependencies are defined, they are connected with '&&'. Dependencies + are applied to all other options within this menu entry (which also + accept an "if" expression), so these two examples are equivalent: + + bool "foo" if BAR + default y if BAR + and + depends on BAR + bool "foo" + default y + +- reverse dependencies: "select" ["if" ] + While normal dependencies reduce the upper limit of a symbol (see + below), reverse dependencies can be used to force a lower limit of + another symbol. The value of the current menu symbol is used as the + minimal value can be set to. If is selected multiple + times, the limit is set to the largest selection. + Reverse dependencies can only be used with boolean or tristate + symbols. + Note: + select should be used with care. select will force + a symbol to a value without visiting the dependencies. + By abusing select you are able to select a symbol FOO even + if FOO depends on BAR that is not set. + In general use select only for non-visible symbols + (no prompts anywhere) and for symbols with no dependencies. + That will limit the usefulness but on the other hand avoid + the illegal configurations all over. + kconfig should one day warn about such things. + +- numerical ranges: "range" ["if" ] + This allows to limit the range of possible input values for int + and hex symbols. The user can only input a value which is larger than + or equal to the first symbol and smaller than or equal to the second + symbol. + +- help text: "help" or "---help---" + This defines a help text. The end of the help text is determined by + the indentation level, this means it ends at the first line which has + a smaller indentation than the first line of the help text. + "---help---" and "help" do not differ in behaviour, "---help---" is + used to help visually separate configuration logic from help within + the file as an aid to developers. + +- misc options: "option" [=] + Various less common options can be defined via this option syntax, + which can modify the behaviour of the menu entry and its config + symbol. These options are currently possible: + + - "defconfig_list" + This declares a list of default entries which can be used when + looking for the default configuration (which is used when the main + .config doesn't exists yet.) + + - "modules" + This declares the symbol to be used as the MODULES symbol, which + enables the third modular state for all config symbols. + + - "env"= + This imports the environment variable into Kconfig. It behaves like + a default, except that the value comes from the environment, this + also means that the behaviour when mixing it with normal defaults is + undefined at this point. The symbol is currently not exported back + to the build environment (if this is desired, it can be done via + another symbol). + +Menu dependencies +----------------- + +Dependencies define the visibility of a menu entry and can also reduce +the input range of tristate symbols. The tristate logic used in the +expressions uses one more state than normal boolean logic to express the +module state. Dependency expressions have the following syntax: + + ::= (1) + '=' (2) + '!=' (3) + '(' ')' (4) + '!' (5) + '&&' (6) + '||' (7) + +Expressions are listed in decreasing order of precedence. + +(1) Convert the symbol into an expression. Boolean and tristate symbols + are simply converted into the respective expression values. All + other symbol types result in 'n'. +(2) If the values of both symbols are equal, it returns 'y', + otherwise 'n'. +(3) If the values of both symbols are equal, it returns 'n', + otherwise 'y'. +(4) Returns the value of the expression. Used to override precedence. +(5) Returns the result of (2-/expr/). +(6) Returns the result of min(/expr/, /expr/). +(7) Returns the result of max(/expr/, /expr/). + +An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 +respectively for calculations). A menu entry becomes visible when it's +expression evaluates to 'm' or 'y'. + +There are two types of symbols: constant and non-constant symbols. +Non-constant symbols are the most common ones and are defined with the +'config' statement. Non-constant symbols consist entirely of alphanumeric +characters or underscores. +Constant symbols are only part of expressions. Constant symbols are +always surrounded by single or double quotes. Within the quote, any +other character is allowed and the quotes can be escaped using '\'. + +Menu structure +-------------- + +The position of a menu entry in the tree is determined in two ways. First +it can be specified explicitly: + +menu "Network device support" + depends on NET + +config NETDEVICES + ... + +endmenu + +All entries within the "menu" ... "endmenu" block become a submenu of +"Network device support". All subentries inherit the dependencies from +the menu entry, e.g. this means the dependency "NET" is added to the +dependency list of the config option NETDEVICES. + +The other way to generate the menu structure is done by analyzing the +dependencies. If a menu entry somehow depends on the previous entry, it +can be made a submenu of it. First, the previous (parent) symbol must +be part of the dependency list and then one of these two conditions +must be true: +- the child entry must become invisible, if the parent is set to 'n' +- the child entry must only be visible, if the parent is visible + +config MODULES + bool "Enable loadable module support" + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + +comment "module support disabled" + depends on !MODULES + +MODVERSIONS directly depends on MODULES, this means it's only visible if +MODULES is different from 'n'. The comment on the other hand is always +visible when MODULES is visible (the (empty) dependency of MODULES is +also part of the comment dependencies). + + +Kconfig syntax +-------------- + +The configuration file describes a series of menu entries, where every +line starts with a keyword (except help texts). The following keywords +end a menu entry: +- config +- menuconfig +- choice/endchoice +- comment +- menu/endmenu +- if/endif +- source +The first five also start the definition of a menu entry. + +config: + + "config" + + +This defines a config symbol and accepts any of above +attributes as options. + +menuconfig: + "menuconfig" + + +This is similar to the simple config entry above, but it also gives a +hint to front ends, that all suboptions should be displayed as a +separate list of options. + +choices: + + "choice" + + + "endchoice" + +This defines a choice group and accepts any of the above attributes as +options. A choice can only be of type bool or tristate, while a boolean +choice only allows a single config entry to be selected, a tristate +choice also allows any number of config entries to be set to 'm'. This +can be used if multiple drivers for a single hardware exists and only a +single driver can be compiled/loaded into the kernel, but all drivers +can be compiled as modules. +A choice accepts another option "optional", which allows to set the +choice to 'n' and no entry needs to be selected. + +comment: + + "comment" + + +This defines a comment which is displayed to the user during the +configuration process and is also echoed to the output files. The only +possible options are dependencies. + +menu: + + "menu" + + + "endmenu" + +This defines a menu block, see "Menu structure" above for more +information. The only possible options are dependencies. + +if: + + "if" + + "endif" + +This defines an if block. The dependency expression is appended +to all enclosed menu entries. + +source: + + "source" + +This reads the specified configuration file. This file is always parsed. + +mainmenu: + + "mainmenu" + +This sets the config program's title bar if the config program chooses +to use it. + + +Kconfig hints +------------- +This is a collection of Kconfig tips, most of which aren't obvious at +first glance and most of which have become idioms in several Kconfig +files. + +Adding common features and make the usage configurable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is a common idiom to implement a feature/functionality that are +relevant for some architectures but not all. +The recommended way to do so is to use a config variable named HAVE_* +that is defined in a common Kconfig file and selected by the relevant +architectures. +An example is the generic IOMAP functionality. + +We would in lib/Kconfig see: + +# Generic IOMAP is used to ... +config HAVE_GENERIC_IOMAP + +config GENERIC_IOMAP + depends on HAVE_GENERIC_IOMAP && FOO + +And in lib/Makefile we would see: +obj-$(CONFIG_GENERIC_IOMAP) += iomap.o + +For each architecture using the generic IOMAP functionality we would see: + +config X86 + select ... + select HAVE_GENERIC_IOMAP + select ... + +Note: we use the existing config option and avoid creating a new +config variable to select HAVE_GENERIC_IOMAP. + +Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is +introduced to overcome the limitation of select which will force a +config option to 'y' no matter the dependencies. +The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the +situation where select forces a symbol equals to 'y'. + +Build as module only +~~~~~~~~~~~~~~~~~~~~ +To restrict a component build to module-only, qualify its config symbol +with "depends on m". E.g.: + +config FOO + depends on BAR && m + +limits FOO to module (=m) or disabled (=n). + diff --git a/extra/config/kconfig-to-uclibc.patch.gz b/extra/config/kconfig-to-uclibc.patch.gz new file mode 100644 index 0000000000000000000000000000000000000000..58c41730ec7a749d3fe02fe1b136268a1253e2b9 GIT binary patch literal 5816 zcmV;p7DwqHiwFpW%LPdQ18ZY%Zf0p`Ep%@!bz^L4Vq-3FVRU0?0PQ?$SKG*vpW#>Z zXg0y%2evUbcz`T`RHI;n>5rO$oDh2NQF`I{-Af@0VD=plxk!-8$NO8Q!kp1N-DgY@|PM z=C~o7@K8=F^0~<-ZsfCj?mOK6A=|4kwt~QNhVm_wM34wK5wy6<06%0QW27_Kn1abX zun#uZ1J3-&VSzj5F=jnN|!wOmCnR>`!E-;%- z7_*qg^4#u3na{(>cUVn4e#PHk1*i6QOSLAjN?e!oifyrD+h%S!;y%za9)r;bO!q;8 zjy+*f09qNkz)FV$iJa-mj78^dWg6Jp2Zr|ny))!yVH5dDt&hGH@Gz&j7VCm(WwZz9^_6iO%=*vSDgM6@+t*b>7Vu8bhAq*uFmwr!mxQm`p0(XJbgtKP zLs-3r4v>DsBgP!dU=OZkN)yw42Y7>m3qon(cjItfL8jZO13G&2bw9-*=pN{m4U==+ zQU-A#A0sD#z+ytL^>PX)y)*e8V*KMXcwSBSjnVdh9bcZj+lF=-FhSZ2JMpK`*SAjy zI7s>h0+EKJt~~V;t5hoB;r^8DtC#9^WFTFk$#!+KjS3P>#xORjIq6IAXobdz6_5*m zR6omDU|`hS_;I66W`HI#=3`^*5g047dWmT=$Us`q+T0|)MmWM#`^@m&zST-obCsC&!GbS3xfSbzKE9q8#4F@fJJu zb<>nFq;I&96B{!841BKN%ZINb@+rqPMUL&d_mP)kXLXjQEKFU%#DoDv`6!%tTul9@ z`@Y-z*xgJBRd3)5n@sVQen zK#Lqm8@Lfd%trsBiAf8@#~W=X?%u?AC-L2BeAkKZeu?ki#&_@HyR-Q2zvH|2@!ffR zcM;!p-g>_zWXh{`xxK-9^ZY6@BRra%`qe}qC;h4(ujbo z#id+j8?S;5kOJaR8k04euXD`0rG_jgL&jp9YqwrKK?HWYaqFZ_->YvbAJ?pwYCE8E zyL))esvO{~Cn&$Z*tS~>Z2NDw>((;6{sx=wUBByGrY*X$)5H+m*l8qdkW`+O4nMSr zkSoa_+$f|GQb`xgYKC0xedn^ACGm;rjPq9CONp5dV#UfG@?x9|TX`GzjoOVu$HK>BEIxKc}S+P~G<8>7kT$^E#8YVWK{zdQf=Dfpd`Hp+q zNhh&l^-wVlo=->)1^L!HCl<{cAQyA4rKcKl0@6wjYUOZLUWp~SQEYh-D=ub7ZqS>F zc}qfGCgQbr>$Dzk?N;%+ifT?ryOo07x5c{W29Fi>w)*saqR%odoVv=`NQn-^Ki-e^YCQ{&^g`k1iIF)&Dp+h(h0P@o299XgQ|) zD6{UNNW0n4)=in6GPb>?1>wZzz`GB}-M2k({GZM{{ob4NvtMsIC3z4>pmbs*cNwHM zhE`~ETAGVwL7rSbfL5NQk5OzB|KnNrwD++f*y5OwQPDe^km_cVe;5JBVlZhWJ2hmpxF|NeP9G@tT{AL} ztXf}(>jNZMg}34T1$UyeaGgR5JbonHY|FHC+Z`gI8JQ5Ce#oCfP}6<^ctx4fM{XN< z8jk0r_eP11r(iBcHuQCGglS#wAsE2Bw#erQ&7JFuWUeAow^ecHBP}LKg@h_1pQF}a zpq1;!h`AniDlwf6Y~8tM1NRB^(geIA4`{GEu7ibg+$u1wKp)uL1n?9tW5kX7R3|G$ zSg?Bu>X?Atbi)i@J(O^vn?g0fyngIKoQFOEbQ^=zY+hjuW?7PSXA)Sww4U?Z3 zkQIa@-;IVNdIk5K(>W0jXwEBn474_$HE(KK;yDQBW!__^>p~Ag+j6_)`_U2(gcUHu z)`Q?sBh^J~(wJo)YQnN=+R-|2^}zF8kNe?-yzZg)U0-X5)&XJN_q zG#2{06WDr)B0ba~!`6;qMCC>jt9Si0zT$K7Nl!8lU(Q@`yB7M!exrZg`*7a*t#iJl zpL9K*8(8G36pH?b-c`Tb>vop(2ffs7?dTWX4l*oUqH6Y&a4g$c`T{DP#Hraga}{qE z^tt-C7(=bzt~cA&=A1xA=g>{5h-?f0qwQ{OGIq=c(eTcCV(4_x6hG)gUOsgn9R@4{ zS&yklIq3m@Xv}?B^gfQb!_Gvx3HD;t3w;MY-FU+D8Id0V?ngJWO$OcqVg~~~`=0pJ zgzyKPF1bLfp_Y#kD}yK)>wd_6BH+>W?*s5`;8Sf2 zE2XIPhOh;bAmrnK75){$fKLWFCc=usj8Gp3W4k}#yCJ=czlK)3d`MaS4T#p00d4Q)KC;{wM^5Z z(PcEwLBcfI4TGQ!c@uQ;`PhBHaA=1vIDAkQ=y?qnPDNVafLvyP^MOQ2%ti9S(|zz% zpmPD(f(4Ntp>eMtIE%YXYTOdg7_u?y+klIiytpgVxC7ldrnVTrO>S6YNKnASM*K-v zk4`imAaZC1o5El;VVF~i1Vt0SF);%@M{5}Hq2)MK0%V0Fa4xp(KH}rR*A3vc&pn_9 zhECXz35F^jtko!X)@qGR@yv3SD=+#=>ZT4jS#IcU2-@~H^9POP$O}MBxF9|;Ufo!Ckk|t z6M6Zj$cBnJ&^cgA4#y!)hyw+(@CtKo;jSibB$6;9Fnn}nI*At2b1-ETIB-&d{(vHr zPIq=xoRUtA!EvY#))=`iR;R{gptZ&xNwU#;rX&R!Jt7Vi5Q24pHx|Tm{Xw^EwDPQD znJ@IRc1H9;NaMghq+2*@tfI_Ryh&z&mk&Z|6Ab5LOFLVNXE6fs79fNY1O8zE0hJeV zN$wzkVcO`mKu#lz`&f`QDN*IF3SP3#mQaypU39uPa?O3wJMDnbA1vQ>#waXQN^*u6 za#8(=jy~e4u+Ec?4y&Cg4vDL^2VTBdYqiMP)0nUn3qoJ4#DYXZYud5zLlC{^lK@hz z2WyB%qX-3c!X<)s&_VZd1SHttPXjQy0lp3xh~`KEy|acR8~!85z=x6>LkBi;L&Q#C zV-m2=jgs}S}v;UTp8a4LZ*5m zYnW$B+<;PK<`^4@F&;4nI|=zI)4<3e{ZB9=eIy#0&^*XC=q#+Zzc0_iKx<*fv~*8X zbd5u*37OpESp4i_qA0R55&uRy1|jg6sY?Cy@>Hx~wPS1odcp2WVloOd2|rE;(p`yj zjynSBW{E2!aa^$30oMQkiLa6gHoVHXn#!%*bXlourVk}MeKEfoE|J+0+i8a`uK-tg z?zBJ@R_ndp6F_3XWu$YdiVsGVJ5J`2(2Hli|+{DiVHe&?o zxl%ECk&%Pq1r_8%2e6a}q9)5n3K}A;X2OKzhnUkwprS^JQ3|I*bz0tpg!GEkS;s64 z$&d{BHUuy!;1?K$bvF^)L(}!$IrB%i9yv1mr3Ian@C8?#I;NHm@?We3<9tkosJg7H zu2*G70X^qg0h+CopjfDhX*}PoiQlY&-%;~AO1M&~NWM8TB@dvZ+fb%klG0VI-)S~z zDY(q-I@KW0V4!iPC<&764@>Mttu-CJA`HdMsM&{^08ig zek_ky0aIU!>h*}yspR~yO&^fV9#ZG@$p@APn0?*DBtilA1(nF(6qR$q(aO|kE6Aa} zed5sG{?1C@z2$$0CF(42ReZ?A7FB=31IMLLdrI-K5h~KDo6V`vz0p!keu*fHVI2OL zyTJTM{B>apa2A54APzcLCr9)P2UKOy6{)lWtXX1BS;vc2!Ni&UYO_?|Va5IGE?$@N zhR&L+?F^ShshhHdMc;7VI?2bFFZk3+b^Vll-8mJdg|Hy|MNiu8U5lt*QQvAl=Q}9X zhXz}56k@fu_!}|eV7W#tlpM-%hQ93Vh;4#QNm4#H1o#s-BFOwVu%v4PH2^bYGqZ?> zl*OM22ufu)Bv;bo6~J@1kn{R2JPNDTTXdQ(uh1j{-UV2{I0b9Br(5E(9`Xtz zO4WCppT)8AukpDr_((z4vFDYKOdi~au2-Nsk~q$1!@G>?-{)|B=@2hEY=>m(M5onW zA$^$sXqn+Cp70e9(X9mKBiuggMq^0z{7FIEmMe0ChM;GbkLb3r2}wt@Ay3|G%^j*w zkymy0J}Vf*b_3pdfMm4r>j~Z?DRW>k2{^+ecO^ZH(#=M<+tM zwaPI(OCP=q2l7n=%^4v+iI;Kk+YjOy9ltAdFF%E6sk3*5?Ry=;#~Xr8xq&OL^Oa;q z@C)FM2W}K53c{AiO$f?D^YJD=?h~@Y$tDBeQfHU$7*=@yv>+$5*})gO{!A56<#BWG zzT*1Bqe|@RwKvfa&mL&gANi{Ugx~OUT&d7@;B~NyKOn3lVe>thLHu!N5LK~E=^nd<@9Ce`1GP9 z$5I|W(>OO?WT2*kXES)>kXlL*RK3v9%K6Wfn7i%KucP6 zQ;~oF173dtgJG45s&kVs%As413}UjUhsLNf{KEcXbj!+K4TFuB>Xl_x1;m_r9gmNH zS-~*j4P5;(@LuINg3g4Ms(Fcs#KJf^30BW@1)~6-8_4teEezx>TK<)qbQ1id+=OQb zkXHeVDx;%pBiiv)qtA!@3ERpkz)7$jg#o7Y1P$=A2J`&=N&ochvU76XKR@ffPa)Fm zd!sTEPO8xq-+95hq8hs>^#P+y0}Hcz4yE-35)1pX9%*)mqO4jat$0P#7poTUr^JyB zFnAzJj@ii_mYfJ%#)XV%PgPRVqFn*Q2wZH2M6`qQ8V12!CU0frvJI7ZY zx%W|?`YKYCo5$^UwmuBlU-0JB#hczaRcgwYS#|+`aDo+|(;tu_C+DR~J>z@@U(jc* z@>|?xn={4f?=}^M>P0?@#kG7IJwo|aB*@@cqp_4)p9YA(*Mo-~9oSrEieD(z4fR1{ zjj5)&2AP7HvaLoVuh1f8lk>VZ+Pkeha~7MTyZd5Sl&;DKXf5ICevtopm@JOy&q$26 z8RSk{3Ml{k`3%53_3~Xeq;o;fhl~YlF=>|tr72npANqKf3GpnGl4mpKlB$#~J_q4U zjamj3dK*yRPoGXZZ*Ja78&yjFPx@+x-aumh3|;95Bg{q29HFXLtLTn`eXd_$f?{#u z^M7>d|BNn8vI3nf(V5B1^klNKZZulri~3gcKbrBsrWq+2_s&me>-Ac!w%^{_Ywxt4 zQ|4E1(Vr{YgD8^eR#TZ>wSlD{c%ko$=kCj^eejj`*wrTfihJz&;ORZ~; +#include +#include + +#include "lkc.h" + +#define P(name,type,arg) type (*name ## _p) arg +#include "lkc_proto.h" +#undef P + +void kconfig_load(void) +{ + void *handle; + char *error; + + handle = dlopen("./libkconfig.so", RTLD_LAZY); + if (!handle) { + handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "%s\n", dlerror()); + exit(1); + } + } + +#define P(name,type,arg) \ +{ \ + name ## _p = dlsym(handle, #name); \ + if ((error = dlerror())) { \ + fprintf(stderr, "%s\n", error); \ + exit(1); \ + } \ +} +#include "lkc_proto.h" +#undef P +} diff --git a/extra/config/kxgettext.c b/extra/config/kxgettext.c new file mode 100644 index 0000000..6eb72a7 --- /dev/null +++ b/extra/config/kxgettext.c @@ -0,0 +1,229 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + char* file; + int lineno; +}; + +static struct file_line *file_line__new(char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, char *file, int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, char *file, int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff --git a/extra/config/lex.zconf.c_shipped b/extra/config/lex.zconf.c_shipped new file mode 100644 index 0000000..09a1ec8 --- /dev/null +++ b/extra/config/lex.zconf.c_shipped @@ -0,0 +1,2413 @@ + +#line 3 "scripts/kconfig/lex.zconf.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( zconftext, zconfleng, 1, zconfout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("recursive scan (%s)?\n", name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("file %s already scanned?\n", name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff --git a/extra/config/lkc.h b/extra/config/lkc.h new file mode 100644 index 0000000..4a9af6f --- /dev/null +++ b/extra/config/lkc.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LKC_DIRECT_LINK +#define P(name,type,arg) extern type name arg +#else +#include "lkc_defs.h" +#define P(name,type,arg) extern type (*name ## _p) arg +#endif +#include "lkc_proto.h" +#undef P + +#define SRCTREE "srctree" + +#define PACKAGE "linux" +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +int zconfparse(void); +void zconfdump(FILE *out); + +extern int zconfdebug; +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +void conf_set_all_new_symbols(enum conf_def_mode mode); + +/* kconfig_load.c */ +void kconfig_load(void); + +/* menu.c */ +void menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { + size_t len; + char *s; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/extra/config/lkc_proto.h b/extra/config/lkc_proto.h new file mode 100644 index 0000000..8e69461 --- /dev/null +++ b/extra/config/lkc_proto.h @@ -0,0 +1,45 @@ + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible,bool,(struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int flags)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff --git a/extra/config/lxdialog/.gitignore b/extra/config/lxdialog/.gitignore new file mode 100644 index 0000000..90b08ff --- /dev/null +++ b/extra/config/lxdialog/.gitignore @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff --git a/extra/config/lxdialog/BIG.FAT.WARNING b/extra/config/lxdialog/BIG.FAT.WARNING new file mode 100644 index 0000000..a8999d8 --- /dev/null +++ b/extra/config/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/extra/config/lxdialog/check-lxdialog.sh b/extra/config/lxdialog/check-lxdialog.sh new file mode 100755 index 0000000..5552154 --- /dev/null +++ b/extra/config/lxdialog/check-lxdialog.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# Check ncurses compatibility + +# What library to link +ldflags() +{ + for ext in so a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -xc - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-header|-library]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff --git a/extra/config/lxdialog/checklist.c b/extra/config/lxdialog/checklist.c new file mode 100644 index 0000000..b2a878c --- /dev/null +++ b/extra/config/lxdialog/checklist.c @@ -0,0 +1,325 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, item_str()[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, (char *)item_str() + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + 6)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 6)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/extra/config/lxdialog/dialog.h b/extra/config/lxdialog/dialog.h new file mode 100644 index 0000000..b5211fc --- /dev/null +++ b/extra/config/lxdialog/dialog.h @@ -0,0 +1,230 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct dialog_info { + const char *backtitle; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* promtp displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); +int dialog_textbox(const char *title, const char *file, int height, int width); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +extern char dialog_input_result[]; +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff --git a/extra/config/lxdialog/inputbox.c b/extra/config/lxdialog/inputbox.c new file mode 100644 index 0000000..616c601 --- /dev/null +++ b/extra/config/lxdialog/inputbox.c @@ -0,0 +1,238 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, scroll = 0, key = 0, button = -1; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - 2)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - 2)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + input_x = strlen(instr); + + if (input_x >= box_width) { + scroll = input_x - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[scroll + i]); + } else { + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_LEFT: + continue; + case KEY_RIGHT: + continue; + case KEY_BACKSPACE: + case 127: + if (input_x || scroll) { + wattrset(dialog, dlg.inputbox.atr); + if (!input_x) { + scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, + instr[scroll + input_x + i] ? + instr[scroll + input_x + i] : ' '); + input_x = strlen(instr) - scroll; + } else + input_x--; + instr[scroll + input_x] = '\0'; + mvwaddch(dialog, box_y, input_x + box_x, ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (scroll + input_x < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + instr[scroll + input_x] = key; + instr[scroll + input_x + 1] = '\0'; + if (input_x == box_width - 1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr [scroll + i]); + } else { + wmove(dialog, box_y, input_x++ + box_x); + waddch(dialog, key); + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff --git a/extra/config/lxdialog/menubox.c b/extra/config/lxdialog/menubox.c new file mode 100644 index 0000000..c689fc0 --- /dev/null +++ b/extra/config/lxdialog/menubox.c @@ -0,0 +1,434 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 16; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < 15 || width < 65) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 2 : (button > 2 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 's': + return 3; + case 'y': + return 3; + case 'n': + return 4; + case 'm': + return 5; + case ' ': + return 6; + case '/': + return 7; + } + return 0; + case 'h': + case '?': + button = 2; + case '\n': + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + return button; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/extra/config/lxdialog/textbox.c b/extra/config/lxdialog/textbox.c new file mode 100644 index 0000000..c704712 --- /dev/null +++ b/extra/config/lxdialog/textbox.c @@ -0,0 +1,391 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW * win, int height, int width); +static void print_line(WINDOW * win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static const char *buf; +static const char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x) +{ + print_page(box, boxh, boxw); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + */ +int dialog_textbox(const char *title, const char *tbuf, + int initial_height, int initial_width) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + int passed_end; + WINDOW *dialog, *box; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + +do_resize: + getmaxyx(stdscr, height, width); + if (height < 8 || width < 8) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); + + while ((key != KEY_ESC) && (key != '\n')) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + delwin(box); + delwin(dialog); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines(page_length + 1); + + /* We don't call print_page() here but use + * scrolling to ensure faster screen update. + * However, 'end_reached' and 'page_length' + * should still be updated, and 'page' should + * point to start of next page. This is done + * by calling get_line() in the following + * 'for' loop. */ + scrollok(box, TRUE); + wscrl(box, -1); /* Scroll box region down one line */ + scrollok(box, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < boxh; i++) { + if (!i) { + /* print first line of page */ + print_line(box, 0, boxw); + wnoutrefresh(box); + } else + /* Called to update 'end_reached' and 'page' */ + get_line(); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok(box, TRUE); + scroll(box); /* Scroll box region up one line */ + scrollok(box, FALSE); + print_line(box, boxh - 1, boxw); + wnoutrefresh(box); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case KEY_NPAGE: /* Next page */ + case ' ': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + delwin(box); + delwin(dialog); + return key; /* ESC pressed */ +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void print_page(WINDOW * win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void print_line(WINDOW * win, int row, int width) +{ + int y, x; + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + getyx(win, y, x); + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + if (!end_reached) { + end_reached = 1; + break; + } + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff --git a/extra/config/lxdialog/util.c b/extra/config/lxdialog/util.c new file mode 100644 index 0000000..86d95cc --- /dev/null +++ b/extra/config/lxdialog/util.c @@ -0,0 +1,655 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + wmove(stdscr, 1, 1); + for (i = 1; i < COLS - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + getmaxyx(stdscr, height, width); + if (height < 19 || width < 80) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int i, prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + /* + * Remove newlines + */ + for (i = 0; i < prompt_len; i++) { + if (tempstr[i] == '\n') + tempstr[i] = ' '; + } + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strchr(word, ' '); + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strchr(sp, ' ')) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + cur_x++; + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff --git a/extra/config/lxdialog/yesno.c b/extra/config/lxdialog/yesno.c new file mode 100644 index 0000000..4e6e809 --- /dev/null +++ b/extra/config/lxdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + 4)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 4)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/extra/config/mconf.c b/extra/config/mconf.c new file mode 100644 index 0000000..18583bd --- /dev/null +++ b/extra/config/mconf.c @@ -0,0 +1,930 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"Some features may be built directly into uClibc. Some features\n" +"may be completely removed altogether. There are also certain\n" +"parameters which are not really features, but must be\n" +"entered in as decimal or hexadecimal numbers or possibly text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change or submenu wish to select and press .\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do and for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single\n" +"menu, rather than the default multimenu hierarchy, run the menuconfig\n" +"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => a LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus --->. " + "Highlighted letters are hotkeys. " + "Pressing selectes a feature, while will exclude a feature. " + "Press to exit, for Help, for Search. " + "Legend: [*] feature is selected [ ] feature is excluded"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +nohelp_text[] = N_( + "There is no help available for this option.\n"), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default, entering the name of the file here will allow you\n" + "to modify that configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different\n" + "configurations available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for CONFIG_ symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Prompt: Foo bus is used to drive the bar HW\n" + "Defined at drivers/pci/Kconfig:47\n" + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + "Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" + " -> PCI support (PCI [=y])\n" + " -> PCI access mode ( [=y])\n" + "Selects: LIBCRC32\n" + "Selected by: BAR\n" + "-----------------------------------------------------------------\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this CONFIG_ symbol\n" + "o The 'Defined at' line tell at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tell what symbols needs to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tell where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicate that this is a selectable\n" + " menu item - and current value is displayed inside brackets.\n" + "o The 'Selects:' line tell what symbol will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tell what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all CONFIG_ symbols containing USB\n" + " ^USB => find all CONFIG_ symbols starting with USB\n" + " USB$ => find all CONFIG_ symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static void get_prompt_str(struct gstr *r, struct property *prop) +{ + int i, j; + struct menu *submenu[8], *menu; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) + submenu[i++] = menu; + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +static void get_symbol_str(struct gstr *r, struct symbol *sym) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + for_all_prompts(sym, prop) + get_prompt_str(r, prop); + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +static struct gstr get_relations_str(struct symbol **sym_arr) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + struct symbol *sym; + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + _("%s - uClibc v%s Configuration"), + config_filename, sym_get_string_value(sym)); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + _("Enter CONFIG_ (sub)string to search for " + "(with or without \"CONFIG\")"), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip CONFIG_ if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) + dialog_input += 7; + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_textbox(_("Search Results"), str_get(&res), 0, 0); + str_free(&res); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s --->", indent + 1, ' ', prompt); + + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + struct menu *active_menu = NULL; + int res; + int s_scroll = 0; + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + if (menu == &rootmenu) { + item_make("--- "); + item_set_tag(':'); + item_make(_(" Load an Alternate Configuration File")); + item_set_tag('L'); + item_make(_(" Save an Alternate Configuration File")); + item_set_tag('S'); + } + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu); + break; + case 's': + conf_string(submenu); + break; + case 'L': + conf_load(); + break; + case 'S': + conf_save(); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else + show_helptext(_("README"), _(mconf_readme)); + break; + case 3: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 4: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 5: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 6: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case 7: + search_conf(); + break; + } + } +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + dialog_clear(); + dialog_textbox(title, text, r, c); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + struct symbol *sym = menu->sym; + + if (menu_has_help(menu)) + { + if (sym->name) { + str_printf(&help, "%s:\n\n", sym->name); + } + str_append(&help, _(menu_get_help(menu))); + str_append(&help, "\n"); + } else if (menu_has_help(sym->prop->menu->parent)) { + str_append(&help, _(menu_get_help(sym->prop->menu->parent))); + str_append(&help, "\n"); + } else { + str_append(&help, nohelp_text); + } + get_symbol_str(&help, sym); + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + item_make("%s", _(menu_get_prompt(child))); + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + 15, 70, 6); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +int main(int ac, char **av) +{ + int saved_x, saved_y; + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + getyx(stdscr, saved_y, saved_x); + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + do { + conf(&rootmenu); + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your " + "new configuration?\n" + " to continue."), + 6, 60); + else + res = -1; + } while (res == KEY_ESC); + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error during writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + case -1: + printf(_("\n\n" + "*** End of configuration.\n" + "*** Execute 'make' to build or try 'make help'." + "\n\n")); + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + } + + return conf_write_autoconf(); +} + diff --git a/extra/config/menu.c b/extra/config/menu.c new file mode 100644 index 0000000..07ff8d1 --- /dev/null +++ b/extra/config/menu.c @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt) + prop_warn(prop, "prompt redefined"); + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%'" + " must be a single symbol", sym->name); + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_range_valid_sym(sym, prop->expr->left.sym) || + !menu_range_valid_sym(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) + if (menu_is_visible(child)) + return true; + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} diff --git a/extra/config/qconf.cc b/extra/config/qconf.cc new file mode 100644 index 0000000..ec3b5bb --- /dev/null +++ b/extra/config/qconf.cc @@ -0,0 +1,1759 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +QAction *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +/** + * Reads a list of integer values from the application settings. + */ +QValueList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + QValueList result; + QStringList entryList = readListEntry(key, ok); + if (ok) { + QStringList::Iterator it; + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + } + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const QValueList& value) +{ + QStringList stringList; + QValueList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + return writeEntry(key, stringList); +} + + +#if QT_VERSION >= 300 +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ + Parent::okRename(col); + sym_set_string_value(menu->sym, text(dataColIdx).latin1()); + listView()->updateList(this); +} +#endif + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, 0); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && !list->showAll) { + setPixmap(promptColIdx, 0); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + +#if QT_VERSION >= 300 + int i = list->mapIdx(dataColIdx); + if (i >= 0) + setRenameEnabled(i, TRUE); +#endif + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ + ConfigList* list = listView(); + + if (visible) { + if (isSelected() && !list->hasFocus() && list->mode == menuMode) + Parent::paintCell(p, list->inactivedColorGroup, column, width, align); + else + Parent::paintCell(p, cg, column, width, align); + } else + Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setOpen(TRUE); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(lostFocus()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Key_Escape: + break; + case Key_Return: + case Key_Enter: + sym_set_string_value(item->menu->sym, text().latin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p, name), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showAll(false), showName(false), showRange(false), showData(false), + rootEntry(0), headerPopup(0) +{ + int i; + + setSorting(-1); + setRootIsDecorated(TRUE); + disabledColorGroup = palette().active(); + disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); + inactivedColorGroup = palette().active(); + inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + + connect(this, SIGNAL(selectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showAll = configSettings->readBoolEntry("/showAll", false); + showName = configSettings->readBoolEntry("/showName", false); + showRange = configSettings->readBoolEntry("/showRange", false); + showData = configSettings->readBoolEntry("/showData", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + for (i = 0; i < colNr; i++) + colMap[i] = colRevMap[i] = -1; + addColumn(promptColIdx, _("Option")); + + reinit(); +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx, _("Name")); + if (showRange) { + addColumn(noColIdx, "N"); + addColumn(modColIdx, "M"); + addColumn(yesColIdx, "Y"); + } + if (showData) + addColumn(dataColIdx, _("Value")); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showName", showName); + configSettings->writeEntry("/showRange", showRange); + configSettings->writeEntry("/showData", showData); + configSettings->writeEntry("/showAll", showAll); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + ConfigItem* item = (ConfigItem*)selectedItem(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + QListViewItemIterator it(this); + ConfigItem* item; + + for (; it.current(); ++it) { + item = (ConfigItem*)it.current(); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: + updateMenuList(this, rootEntry); + triggerUpdate(); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setOpen(TRUE); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setOpen(!item->isOpen()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setOpen(!item->isOpen()); + else if (oldexpr == no) + item->setOpen(TRUE); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: +#if QT_VERSION >= 300 + if (colMap[dataColIdx] >= 0) + item->startRename(colMap[dataColIdx]); + else +#endif + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + setSelected(currentItem(), hasFocus()); + ensureItemVisible(currentItem()); +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + QListViewItemIterator it(this); + for (; (item = (ConfigItem*)it.current()); it++) { + if (item->menu == oldroot) { + setCurrentItem(item); + ensureItemVisible(item); + break; + } + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (showAll || visible) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + QListViewItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Key_Return: + case Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Key_Space: + changeValue(item); + break; + case Key_N: + setValue(item, no); + break; + case Key_M: + setValue(item, mod); + break; + case Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + const QPixmap* pm; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = colRevMap[header()->sectionAt(x)]; + switch (idx) { + case promptColIdx: + pm = item->pixmap(promptColIdx); + if (pm) { + int off = header()->sectionPos(0) + itemMargin() + + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); + if (x >= off && x < off + pm->width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + setSelected(item, TRUE); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + QAction *action; + + headerPopup = new QPopupMenu(this); + action = new QAction(NULL, _("Show Name"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showName); + action->addTo(headerPopup); + action = new QAction(NULL, _("Show Range"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showRange); + action->addTo(headerPopup); + action = new QAction(NULL, _("Show Data"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showData); + action->addTo(headerPopup); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView* ConfigView::viewList; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent, name) +{ + list = new ConfigList(this, name); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setShowAll(bool b) +{ + if (list->showAll != b) { + list->showAll = b; + list->updateListAll(); + emit showAllChanged(b); + } +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + QListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent, name), menu(0), sym(0) +{ + if (name) { + configSettings->beginGroup(name); + _showDebug = configSettings->readBoolEntry("/showDebug", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (menu == m) + return; + menu = m; + sym = NULL; + if (!menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::setSource(const QString& name) +{ + const char *p = name.latin1(); + + menu = NULL; + sym = NULL; + + switch (p[0]) { + case 'm': + struct menu *m; + + if (sscanf(p, "m%p", &m) == 1 && menu != m) { + menu = m; + menuInfo(); + emit menuSelected(menu); + } + break; + case 's': + struct symbol *s; + + if (sscanf(p, "s%p", &s) == 1 && sym != s) { + sym = s; + symbolInfo(); + } + break; + } +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
"; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = menu->sym; + if (sym) { + if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

"; + + if (showDebug()) + debug = debug_info(sym); + + help = menu_get_help(menu); + /* Gettextize if the help text not empty */ + if (help.isEmpty()) + help = print_filter(menu_get_help(menu)); + else + help = print_filter(_(menu_get_help(menu))); + } else if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += "

"; + if (showDebug()) { + if (menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

", menu->file->name, menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) +{ + QPopupMenu* popup = Parent::createPopupMenu(pos); + QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setOn(showDebug()); + popup->insertSeparator(); + action->addTo(popup); + return popup; +} + +void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) +{ + Parent::contentsContextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent, name), result(NULL) +{ + setCaption("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); + QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(FALSE); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(QSplitter::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + int x, y, width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->readNumEntry("/window width", parent->width() / 2); + height = configSettings->readNumEntry("/window height", parent->height() / 2); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + QValueList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().latin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok; + int x, y, width, height; + char title[256]; + + QWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), _("uClibc v%s Configuration"), + getenv("VERSION")); + setCaption(title); + + width = configSettings->readNumEntry("/window width", d->width() - 64); + height = configSettings->readNumEntry("/window height", d->height() - 64); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + + split1 = new QSplitter(this); + split1->setOrientation(QSplitter::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(QSplitter::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + helpText->setTextFormat(Qt::RichText); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new QToolBar("Tools", this); + + backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this); + connect(backAction, SIGNAL(activated()), SLOT(goBack())); + backAction->setEnabled(FALSE); + QAction *quitAction = new QAction("Quit", _("&Quit"), CTRL+Key_Q, this); + connect(quitAction, SIGNAL(activated()), SLOT(close())); + QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), CTRL+Key_L, this); + connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); + saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), CTRL+Key_S, this); + connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this); + connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); + QAction *searchAction = new QAction("Find", _("&Find"), CTRL+Key_F, this); + connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); + QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); + connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); + QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); + connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); + QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); + connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + + QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this); + showNameAction->setToggleAction(TRUE); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); + showNameAction->setOn(configView->showName()); + QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this); + showRangeAction->setToggleAction(TRUE); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); + showRangeAction->setOn(configList->showRange); + QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this); + showDataAction->setToggleAction(TRUE); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); + showDataAction->setOn(configList->showData); + QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this); + showAllAction->setToggleAction(TRUE); + connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); + connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); + showAllAction->setOn(configList->showAll); + QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this); + showDebugAction->setToggleAction(TRUE); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); + showDebugAction->setOn(helpText->showDebug()); + + QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this); + connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); + QAction *showAboutAction = new QAction(NULL, _("About"), 0, this); + connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + + // init tool bar + backAction->addTo(toolBar); + toolBar->addSeparator(); + loadAction->addTo(toolBar); + saveAction->addTo(toolBar); + toolBar->addSeparator(); + singleViewAction->addTo(toolBar); + splitViewAction->addTo(toolBar); + fullViewAction->addTo(toolBar); + + // create config menu + QPopupMenu* config = new QPopupMenu(this); + menu->insertItem(_("&File"), config); + loadAction->addTo(config); + saveAction->addTo(config); + saveAsAction->addTo(config); + config->insertSeparator(); + quitAction->addTo(config); + + // create edit menu + QPopupMenu* editMenu = new QPopupMenu(this); + menu->insertItem(_("&Edit"), editMenu); + searchAction->addTo(editMenu); + + // create options menu + QPopupMenu* optionMenu = new QPopupMenu(this); + menu->insertItem(_("&Option"), optionMenu); + showNameAction->addTo(optionMenu); + showRangeAction->addTo(optionMenu); + showDataAction->addTo(optionMenu); + optionMenu->insertSeparator(); + showAllAction->addTo(optionMenu); + showDebugAction->addTo(optionMenu); + + // create help menu + QPopupMenu* helpMenu = new QPopupMenu(this); + menu->insertSeparator(); + menu->insertItem(_("&Help"), helpMenu); + showIntroAction->addTo(helpMenu); + showAboutAction->addTo(helpMenu); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->readEntry("/listMode", "symbol"); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + QValueList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = QFileDialog::getOpenFileName(".config", NULL, this); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +void ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = QFileDialog::getSaveFileName(".config", NULL, this); + if (s.isNull()) + return; + if (conf_write(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(FALSE); + else + backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (!menu_is_visible(menu) && !configView->showAll()) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + menuList->setSelected(item, TRUE); + menuList->ensureItemVisible(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + list->setSelected(item, TRUE); + list->ensureItemVisible(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(FALSE); + item = (ConfigItem*)menuList->selectedItem(); + while (item) { + if (item->menu == configList->rootEntry) { + menuList->setSelected(item, TRUE); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(TRUE); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(FALSE); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + conf_write(NULL); + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool for uClibc.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" + "Bug reports and feature request can also be entered at http://bugs.uClibc.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + } + configSettings->writeEntry("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s \n"), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + +#ifndef LKC_DIRECT_LINK + kconfig_load(); +#endif + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->setMainWidget(v); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + + return 0; +} diff --git a/extra/config/qconf.h b/extra/config/qconf.h new file mode 100644 index 0000000..b3b5657 --- /dev/null +++ b/extra/config/qconf.h @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#if QT_VERSION >= 300 +#include +#else +class QSettings { +public: + void beginGroup(const QString& group) { } + void endGroup(void) { } + bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + QStringList readListEntry(const QString& key, bool* ok = 0) const + { if (ok) *ok = FALSE; return QStringList(); } + template + bool writeEntry(const QString& key, t value) + { return TRUE; } +}; +#endif + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + + +class ConfigSettings : public QSettings { +public: + QValueList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const QValueList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; + +class ConfigList : public QListView { + Q_OBJECT + typedef class QListView Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + int mapIdx(colIdx idx) + { + return colMap[idx]; + } + void addColumn(colIdx idx, const QString& label) + { + colMap[idx] = Parent::addColumn(label); + colRevMap[colMap[idx]] = idx; + } + void removeColumn(colIdx idx) + { + int col = colMap[idx]; + if (col >= 0) { + Parent::removeColumn(col); + colRevMap[col] = colMap[idx] = -1; + } + } + void setAllOpen(bool open); + void setParentMenu(void); + + template + void updateMenuList(P*, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showAll, showName, showRange, showData; + enum listMode mode; + struct menu *rootEntry; + QColorGroup disabledColorGroup; + QColorGroup inactivedColorGroup; + QPopupMenu* headerPopup; + +private: + int colMap[colNr]; + int colRevMap[colNr]; +}; + +class ConfigItem : public QListViewItem { + typedef class QListViewItem Parent; +public: + ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(QListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); +#if QT_VERSION >= 300 + void okRename(int col); +#endif + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::listView(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + ConfigItem* nextSibling() const + { + return (ConfigItem *)Parent::nextSibling(); + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(listView()->mapIdx(idx), text); + } + QString text(colIdx idx) const + { + return Parent::text(listView()->mapIdx(idx)); + } + void setPixmap(colIdx idx, const QPixmap& pm) + { + Parent::setPixmap(listView()->mapIdx(idx), pm); + } + const QPixmap* pixmap(colIdx idx) const + { + return Parent::pixmap(listView()->mapIdx(idx)); + } + void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public QVBox { + Q_OBJECT + typedef class QVBox Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showAll(void) const { return list->showAll; } + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowAll(bool); + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); +signals: + void showAllChanged(bool); + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; +}; + +class ConfigInfoView : public QTextBrowser { + Q_OBJECT + typedef class QTextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setSource(const QString& name); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + QPopupMenu* createPopupMenu(const QPoint& pos); + void contentsContextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public QMainWindow { + Q_OBJECT + + static QAction *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + void saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + QToolBar *toolBar; + QAction *backAction; + QSplitter* split1; + QSplitter* split2; +}; diff --git a/extra/config/symbol.c b/extra/config/symbol.c new file mode 100644 index 0000000..b27047c --- /dev/null +++ b/extra/config/symbol.c @@ -0,0 +1,973 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + char *p; + static bool inited = false; + + if (inited) + return; + inited = true; + + p = getenv("VERSION"); + if (p) { + sym = sym_lookup("VERSION", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, p); + } +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* no choice? reset tristate value */ + sym->curr.tri = no; + return NULL; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + choice_sym->flags |= flags; + if (flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + int val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = malloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = malloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + return "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + const char *ptr; + char *new_name; + int hash = 0; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 256; + } + + symbol = malloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + const char *ptr; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + regex_t re; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 0, NULL, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp = sym_arr; + size += 16; + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); + if (!sym_arr) { + free(tmp); + return NULL; + } + } + sym_arr[cnt++] = sym; + } + if (sym_arr) + sym_arr[cnt] = NULL; + regfree(&re); + + return sym_arr; +} + + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + return sym2; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + } + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) { + fprintf(stderr, " -> %s", sym->name); + break; + } + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + fprintf(stderr, "%s:%d:error: found recursive dependency: %s", + sym->prop->file->name, sym->prop->lineno, + sym->name ? sym->name : ""); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + /* for choice groups start the check with main choice symbol */ + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2) { + fprintf(stderr, " -> %s", sym->name ? sym->name : ""); + if (sym2 == sym) { + fprintf(stderr, "\n"); + zconfnerrs++; + sym2 = NULL; + } + } + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff --git a/extra/config/util.c b/extra/config/util.c new file mode 100644 index 0000000..3cc9f93 --- /dev/null +++ b/extra/config/util.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) + return file; + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = strdup(name); + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\ninclude/config/auto.conf: \\\n" + "\t$(deps_config)\n\n"); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "include/config/auto.conf: FORCE\n"); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable sting */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = malloc(sizeof(char) * 64); + gs.len = 64; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + diff --git a/extra/config/zconf.gperf b/extra/config/zconf.gperf new file mode 100644 index 0000000..25ef5d0 --- /dev/null +++ b/extra/config/zconf.gperf @@ -0,0 +1,44 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +%% diff --git a/extra/config/zconf.hash.c_shipped b/extra/config/zconf.hash.c_shipped new file mode 100644 index 0000000..5c73d51 --- /dev/null +++ b/extra/config/zconf.hash.c_shipped @@ -0,0 +1,237 @@ +/* ANSI-C code produced by gperf version 3.0.3 */ +/* Command-line: gperf */ +/* Computed positions: -k'1,3' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +struct kconf_id; +/* maximum key range = 47, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static unsigned char asso_values[] = + { + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 11, 5, + 0, 0, 5, 49, 5, 20, 49, 49, 5, 20, + 5, 0, 30, 49, 0, 15, 0, 10, 0, 49, + 25, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("on")]; + char kconf_id_strings_str3[sizeof("env")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str6[sizeof("option")]; + char kconf_id_strings_str7[sizeof("endmenu")]; + char kconf_id_strings_str8[sizeof("optional")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str10[sizeof("range")]; + char kconf_id_strings_str11[sizeof("choice")]; + char kconf_id_strings_str12[sizeof("default")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("help")]; + char kconf_id_strings_str15[sizeof("bool")]; + char kconf_id_strings_str16[sizeof("config")]; + char kconf_id_strings_str17[sizeof("def_tristate")]; + char kconf_id_strings_str18[sizeof("boolean")]; + char kconf_id_strings_str19[sizeof("defconfig_list")]; + char kconf_id_strings_str21[sizeof("string")]; + char kconf_id_strings_str22[sizeof("if")]; + char kconf_id_strings_str23[sizeof("int")]; + char kconf_id_strings_str26[sizeof("select")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str28[sizeof("tristate")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("source")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("hex")]; + char kconf_id_strings_str35[sizeof("menuconfig")]; + char kconf_id_strings_str36[sizeof("prompt")]; + char kconf_id_strings_str37[sizeof("depends")]; + char kconf_id_strings_str48[sizeof("mainmenu")]; + }; +static struct kconf_id_strings_t kconf_id_strings_contents = + { + "on", + "env", + "endif", + "option", + "endmenu", + "optional", + "endchoice", + "range", + "choice", + "default", + "def_bool", + "help", + "bool", + "config", + "def_tristate", + "boolean", + "defconfig_list", + "string", + "if", + "int", + "select", + "modules", + "tristate", + "menu", + "source", + "comment", + "hex", + "menuconfig", + "prompt", + "depends", + "mainmenu" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#ifdef __GNUC_STDC_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 31, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 48 + }; + + static struct kconf_id wordlist[] = + { + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} + diff --git a/extra/config/zconf.l b/extra/config/zconf.l new file mode 100644 index 0000000..5164ef7 --- /dev/null +++ b/extra/config/zconf.l @@ -0,0 +1,356 @@ +%option backup nostdinit noyywrap never-interactive full ecs +%option 8bit backup nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} +%} + +ws [ \n\t] +n [A-Za-z0-9_] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + --- /* ignore */ + ({n}|[-/.])+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + . + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("recursive scan (%s)?\n", name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("file %s already scanned?\n", name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/extra/config/zconf.tab.c_shipped b/extra/config/zconf.tab.c_shipped new file mode 100644 index 0000000..08223ec --- /dev/null +++ b/extra/config/zconf.tab.c_shipped @@ -0,0 +1,2490 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_OPTIONAL = 272, + T_PROMPT = 273, + T_TYPE = 274, + T_DEFAULT = 275, + T_SELECT = 276, + T_RANGE = 277, + T_OPTION = 278, + T_ON = 279, + T_WORD = 280, + T_WORD_QUOTE = 281, + T_UNEQUAL = 282, + T_CLOSE_PAREN = 283, + T_OPEN_PAREN = 284, + T_EOL = 285, + T_OR = 286, + T_AND = 287, + T_EQUAL = 288, + T_NOT = 289 + }; +#endif +/* Tokens. */ +#define T_MAINMENU 258 +#define T_MENU 259 +#define T_ENDMENU 260 +#define T_SOURCE 261 +#define T_CHOICE 262 +#define T_ENDCHOICE 263 +#define T_COMMENT 264 +#define T_CONFIG 265 +#define T_MENUCONFIG 266 +#define T_HELP 267 +#define T_HELPTEXT 268 +#define T_IF 269 +#define T_ENDIF 270 +#define T_DEPENDS 271 +#define T_OPTIONAL 272 +#define T_PROMPT 273 +#define T_TYPE 274 +#define T_DEFAULT 275 +#define T_SELECT 276 +#define T_RANGE 277 +#define T_OPTION 278 +#define T_ON 279 +#define T_WORD 280 +#define T_WORD_QUOTE 281 +#define T_UNEQUAL 282 +#define T_CLOSE_PAREN 283 +#define T_OPEN_PAREN 284 +#define T_EOL 285 +#define T_OR 286 +#define T_AND 287 +#define T_EQUAL 288 +#define T_NOT 289 + + + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG +#define YYERROR_VERBOSE +#endif + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE + +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + struct kconf_id *id; +} +/* Line 187 of yacc.c. */ + + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 259 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 35 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 46 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 110 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 180 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 289 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 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 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, + 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, + 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, + 112, 117, 122, 128, 132, 133, 137, 138, 141, 145, + 148, 150, 154, 155, 158, 161, 164, 167, 170, 175, + 179, 182, 187, 188, 191, 195, 197, 201, 202, 205, + 208, 211, 215, 218, 220, 224, 225, 228, 231, 234, + 238, 242, 245, 248, 251, 252, 255, 258, 261, 266, + 267, 270, 272, 274, 277, 280, 283, 285, 288, 289, + 292, 294, 298, 302, 306, 309, 313, 317, 319, 321, + 322 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 36, 0, -1, 37, -1, -1, 37, 39, -1, 37, + 53, -1, 37, 64, -1, 37, 3, 74, 76, -1, + 37, 75, -1, 37, 25, 1, 30, -1, 37, 38, + 1, 30, -1, 37, 1, 30, -1, 16, -1, 18, + -1, 19, -1, 21, -1, 17, -1, 22, -1, 20, + -1, 30, -1, 59, -1, 68, -1, 42, -1, 44, + -1, 66, -1, 25, 1, 30, -1, 1, 30, -1, + 10, 25, 30, -1, 41, 45, -1, 11, 25, 30, + -1, 43, 45, -1, -1, 45, 46, -1, 45, 47, + -1, 45, 72, -1, 45, 70, -1, 45, 40, -1, + 45, 30, -1, 19, 73, 30, -1, 18, 74, 77, + 30, -1, 20, 78, 77, 30, -1, 21, 25, 77, + 30, -1, 22, 79, 79, 77, 30, -1, 23, 48, + 30, -1, -1, 48, 25, 49, -1, -1, 33, 74, + -1, 7, 80, 30, -1, 50, 54, -1, 75, -1, + 51, 56, 52, -1, -1, 54, 55, -1, 54, 72, + -1, 54, 70, -1, 54, 30, -1, 54, 40, -1, + 18, 74, 77, 30, -1, 19, 73, 30, -1, 17, + 30, -1, 20, 25, 77, 30, -1, -1, 56, 39, + -1, 14, 78, 76, -1, 75, -1, 57, 60, 58, + -1, -1, 60, 39, -1, 60, 64, -1, 60, 53, + -1, 4, 74, 30, -1, 61, 71, -1, 75, -1, + 62, 65, 63, -1, -1, 65, 39, -1, 65, 64, + -1, 65, 53, -1, 6, 74, 30, -1, 9, 74, + 30, -1, 67, 71, -1, 12, 30, -1, 69, 13, + -1, -1, 71, 72, -1, 71, 30, -1, 71, 40, + -1, 16, 24, 78, 30, -1, -1, 74, 77, -1, + 25, -1, 26, -1, 5, 30, -1, 8, 30, -1, + 15, 30, -1, 30, -1, 76, 30, -1, -1, 14, + 78, -1, 79, -1, 79, 33, 79, -1, 79, 27, + 79, -1, 29, 78, 28, -1, 34, 78, -1, 78, + 31, 78, -1, 78, 32, 78, -1, 25, -1, 26, + -1, -1, 25, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 104, 104, 106, 108, 109, 110, 111, 112, 113, + 114, 118, 122, 122, 122, 122, 122, 122, 122, 126, + 127, 128, 129, 130, 131, 135, 136, 142, 150, 156, + 164, 174, 176, 177, 178, 179, 180, 181, 184, 192, + 198, 208, 214, 220, 223, 225, 236, 237, 242, 251, + 256, 264, 267, 269, 270, 271, 272, 273, 276, 282, + 293, 299, 309, 311, 316, 324, 332, 335, 337, 338, + 339, 344, 351, 356, 364, 367, 369, 370, 371, 374, + 382, 389, 396, 402, 409, 411, 412, 413, 416, 424, + 426, 431, 432, 435, 436, 437, 441, 442, 445, 446, + 449, 450, 451, 452, 453, 454, 455, 458, 459, 462, + 463 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", + "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt", + "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", + "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", + "comment_stmt", "help_start", "help", "depends_list", "depends", + "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", + "word_opt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 35, 36, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, + 39, 39, 39, 39, 39, 40, 40, 41, 42, 43, + 44, 45, 45, 45, 45, 45, 45, 45, 46, 46, + 46, 46, 46, 47, 48, 48, 49, 49, 50, 51, + 52, 53, 54, 54, 54, 54, 54, 54, 55, 55, + 55, 55, 56, 56, 57, 58, 59, 60, 60, 60, + 60, 61, 62, 63, 64, 65, 65, 65, 65, 66, + 67, 68, 69, 70, 71, 71, 71, 71, 72, 73, + 73, 74, 74, 75, 75, 75, 76, 76, 77, 77, + 78, 78, 78, 78, 78, 78, 78, 79, 79, 80, + 80 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, + 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, + 4, 4, 5, 3, 0, 3, 0, 2, 3, 2, + 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, + 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, + 3, 2, 2, 2, 0, 2, 2, 2, 4, 0, + 2, 1, 1, 2, 2, 2, 1, 2, 0, 2, + 1, 3, 3, 3, 2, 3, 3, 1, 1, 0, + 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 3, 0, 0, 1, 0, 0, 0, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, + 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, + 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, + 84, 21, 8, 11, 91, 92, 0, 0, 93, 0, + 110, 0, 94, 0, 0, 0, 107, 108, 0, 0, + 0, 100, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 7, 71, 79, 48, 80, 27, + 29, 0, 104, 0, 0, 64, 0, 0, 9, 10, + 0, 0, 0, 0, 89, 0, 0, 0, 44, 0, + 37, 36, 32, 33, 0, 35, 34, 0, 0, 89, + 0, 56, 57, 53, 55, 54, 63, 51, 50, 68, + 70, 66, 69, 65, 86, 87, 85, 76, 78, 74, + 77, 73, 97, 103, 105, 106, 102, 101, 26, 82, + 0, 98, 0, 98, 98, 98, 0, 0, 0, 83, + 60, 98, 0, 98, 0, 0, 0, 38, 90, 0, + 0, 98, 46, 43, 25, 0, 59, 0, 88, 99, + 39, 40, 41, 0, 0, 45, 58, 61, 42, 47 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 2, 25, 26, 101, 27, 28, 29, 30, + 65, 102, 103, 147, 175, 31, 32, 117, 33, 67, + 113, 68, 34, 121, 35, 69, 36, 37, 129, 38, + 71, 39, 40, 41, 104, 105, 70, 106, 142, 143, + 42, 74, 156, 60, 61, 51 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -80 +static const yytype_int16 yypact[] = +{ + -80, 2, 132, -80, -13, -1, -1, -2, -1, 9, + 33, -1, 27, 40, -3, 38, -80, -80, -80, -80, + -80, -80, -80, 71, -80, 77, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, 57, 61, -80, 63, + -80, 76, -80, 87, 101, 133, -80, -80, -3, -3, + 195, -6, -80, 136, 149, 39, 104, 65, 150, 5, + 194, 5, 167, -80, 176, -80, -80, -80, -80, -80, + -80, 68, -80, -3, -3, 176, 72, 72, -80, -80, + 177, 187, 78, -1, -1, -3, 196, 72, -80, 222, + -80, -80, -80, -80, 221, -80, -80, 205, -1, -1, + 211, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, 206, -80, -80, -80, -80, -80, + -3, 223, 209, 223, 197, 223, 72, 7, 210, -80, + -80, 223, 212, 223, 201, -3, 213, -80, -80, 214, + 215, 223, 208, -80, -80, 216, -80, 217, -80, 113, + -80, -80, -80, 218, -1, -80, -80, -80, -80, -80 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -80, -80, -80, -80, 122, -34, -80, -80, -80, -80, + 220, -80, -80, -80, -80, -80, -80, -80, 59, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, 125, + -80, -80, -80, -80, -80, 183, 219, 22, 142, -5, + 147, 192, 69, -54, -79, -80 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -82 +static const yytype_int16 yytable[] = +{ + 46, 47, 3, 49, 81, 82, 53, 136, 137, 6, + 7, 8, 9, 10, 11, 12, 13, 43, 146, 14, + 15, 86, 56, 57, 44, 45, 58, 87, 48, 134, + 135, 59, 162, 112, 50, 24, 125, 163, 125, -28, + 90, 144, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 91, 54, -28, -28, 92, -28, 93, 94, 95, + 96, 97, 98, 52, 99, 55, 90, 161, 62, 100, + -49, -49, 63, -49, -49, -49, -49, 91, 64, -49, + -49, 92, 107, 108, 109, 110, 154, 73, 141, 115, + 99, 75, 126, 76, 126, 111, 133, 56, 57, 83, + 84, 169, 140, 151, -30, 90, 77, -30, -30, -30, + -30, -30, -30, -30, -30, -30, 91, 78, -30, -30, + 92, -30, 93, 94, 95, 96, 97, 98, 120, 99, + 128, 79, -2, 4, 100, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 83, 84, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 7, 8, 23, 10, 11, + 12, 13, 24, 80, 14, 15, 88, -81, 90, 179, + -81, -81, -81, -81, -81, -81, -81, -81, -81, 89, + 24, -81, -81, 92, -81, -81, -81, -81, -81, -81, + 116, 119, 99, 127, 122, 90, 130, 124, -72, -72, + -72, -72, -72, -72, -72, -72, 132, 138, -72, -72, + 92, 155, 158, 159, 160, 118, 123, 139, 131, 99, + 165, 145, 167, 148, 124, 73, 83, 84, 83, 84, + 173, 168, 83, 84, 149, 150, 153, 155, 84, 157, + 164, 174, 166, 170, 171, 172, 176, 177, 178, 66, + 114, 152, 85, 0, 0, 0, 0, 0, 0, 72 +}; + +static const yytype_int16 yycheck[] = +{ + 5, 6, 0, 8, 58, 59, 11, 86, 87, 4, + 5, 6, 7, 8, 9, 10, 11, 30, 97, 14, + 15, 27, 25, 26, 25, 26, 29, 33, 30, 83, + 84, 34, 25, 67, 25, 30, 70, 30, 72, 0, + 1, 95, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 30, 25, 25, 1, 146, 30, 30, + 5, 6, 1, 8, 9, 10, 11, 12, 1, 14, + 15, 16, 17, 18, 19, 20, 140, 30, 93, 67, + 25, 30, 70, 30, 72, 30, 28, 25, 26, 31, + 32, 155, 24, 108, 0, 1, 30, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 30, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 69, 25, + 71, 30, 0, 1, 30, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 31, 32, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 30, 0, 1, 174, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 30, + 30, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 68, 69, 25, 71, 69, 1, 71, 30, 4, 5, + 6, 7, 8, 9, 10, 11, 30, 30, 14, 15, + 16, 14, 143, 144, 145, 68, 69, 30, 71, 25, + 151, 25, 153, 1, 30, 30, 31, 32, 31, 32, + 161, 30, 31, 32, 13, 30, 25, 14, 32, 30, + 30, 33, 30, 30, 30, 30, 30, 30, 30, 29, + 67, 109, 60, -1, -1, -1, -1, -1, -1, 40 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 36, 37, 0, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 25, 30, 38, 39, 41, 42, 43, + 44, 50, 51, 53, 57, 59, 61, 62, 64, 66, + 67, 68, 75, 30, 25, 26, 74, 74, 30, 74, + 25, 80, 30, 74, 25, 25, 25, 26, 29, 34, + 78, 79, 30, 1, 1, 45, 45, 54, 56, 60, + 71, 65, 71, 30, 76, 30, 30, 30, 30, 30, + 30, 78, 78, 31, 32, 76, 27, 33, 30, 30, + 1, 12, 16, 18, 19, 20, 21, 22, 23, 25, + 30, 40, 46, 47, 69, 70, 72, 17, 18, 19, + 20, 30, 40, 55, 70, 72, 39, 52, 75, 39, + 53, 58, 64, 75, 30, 40, 72, 39, 53, 63, + 64, 75, 30, 28, 78, 78, 79, 79, 30, 30, + 24, 74, 73, 74, 78, 25, 79, 48, 1, 13, + 30, 74, 73, 25, 78, 14, 77, 30, 77, 77, + 77, 79, 25, 30, 30, 77, 30, 77, 30, 78, + 30, 30, 30, 77, 33, 49, 30, 30, 30, 74 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 51: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 57: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 62: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 8: + + { zconf_error("unexpected end statement"); ;} + break; + + case 9: + + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + break; + + case 10: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); +;} + break; + + case 11: + + { zconf_error("invalid statement"); ;} + break; + + case 25: + + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + break; + + case 26: + + { zconf_error("invalid option"); ;} + break; + + case 27: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 28: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 29: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 30: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 38: + + { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); +;} + break; + + case 39: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 40: + + { + menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); + if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[(1) - (4)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (4)].id)->stype); +;} + break; + + case 41: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 42: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[(3) - (3)].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); + free((yyvsp[(2) - (3)].string)); +;} + break; + + case 46: + + { (yyval.string) = NULL; ;} + break; + + case 47: + + { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + break; + + case 48: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 49: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 50: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 58: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 59: + + { + if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); + } else + YYERROR; +;} + break; + + case 60: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 61: + + { + if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 64: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[(2) - (3)].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 65: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 71: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 72: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 73: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 79: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); + zconf_nextfile((yyvsp[(2) - (3)].string)); +;} + break; + + case 80: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 81: + + { + menu_end_entry(); +;} + break; + + case 82: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 83: + + { + current_entry->help = (yyvsp[(2) - (2)].string); +;} + break; + + case 88: + + { + menu_add_dep((yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 90: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); +;} + break; + + case 93: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 94: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 95: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 98: + + { (yyval.expr) = NULL; ;} + break; + + case 99: + + { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + break; + + case 100: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + break; + + case 101: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 102: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 103: + + { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + break; + + case 104: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + break; + + case 105: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 106: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 107: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 108: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 109: + + { (yyval.string) = NULL; ;} + break; + + +/* Line 1267 of yacc.c. */ + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "uClibc Configuration", NULL); + +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + } + return ""; +} + +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +#if YYDEBUG + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif +} + +void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "choice\n"); + else + fprintf(out, "config %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } + fputc('\n', out); +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + fputs("\n", out); + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + diff --git a/extra/config/zconf.y b/extra/config/zconf.y new file mode 100644 index 0000000..029c9b6 --- /dev/null +++ b/extra/config/zconf.y @@ -0,0 +1,706 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG +#define YYERROR_VERBOSE +#endif +%} +%expect 26 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%% +input: stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list T_MAINMENU prompt nl + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "uClibc Configuration", NULL); + +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + } + return ""; +} + +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +#if YYDEBUG + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif +} + +void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "choice\n"); + else + fprintf(out, "config %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } + fputc('\n', out); +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + fputs("\n", out); + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/extra/libstrip/libstrip b/extra/libstrip/libstrip new file mode 100755 index 0000000..69a1043 --- /dev/null +++ b/extra/libstrip/libstrip @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w +# vi: set ts=4: + +# Libstrip - A utility to optimize libraries for specific executables +# Copyright (C) 2001 David A. Schleef +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This is a surprisingly simple script that gets a list of +# unresolved symbols in a list of executables specified on the +# command line, and then relinks the uClibc shared object file +# with only the those symbols and their dependencies. This +# results in a shared object that is optimized for the executables +# listed, and thus may not work with other executables. +# +# Example: optimizing uClibc for BusyBox +# Compile uClibc and BusyBox as normal. Then, in this +# directory, run: +# libstrip path/to/busybox +# After the script completes, there should be a new +# libuClibc-0.9.5.so in the current directory, which +# is optimized for busybox. +# +# How it works: +# The uClibc Makefiles create libuClibc.so by first creating +# the ar archive libc.a with all the object files, then links +# the final libuClibc.so by using 'ld --shared --whole-archive'. +# We take advantage of the linker command line option --undefined, +# which pulls in a symbol and all its dependencies, and so relink +# the library using --undefined for each symbol in place of +# --whole-archive. The linker script is used only to avoid +# having very long command lines. + +$topdir="../.."; + +# This is the name of the default ldscript for shared libs. The +# file name will be different for other architectures. +$ldscript="/usr/lib/ldscripts/elf_i386.xs"; + +my @syms; +my @allsyms; +my $s; + +while($exec = shift @ARGV){ + #print "$exec\n"; + @syms=`nm --dynamic $exec`; + for $s (@syms){ + chomp $s; + if($s =~ m/^.{8} [BUV] (.+)/){ + my $x = $1; + if(!grep { m/^$x$/; } @allsyms){ + unshift @allsyms, $x; + } + } + } +} + +open(LDSCRIPT, ">ldscript"); +print LDSCRIPT "INCLUDE $ldscript\n"; +for $s (@allsyms) { + print LDSCRIPT "EXTERN($s)\n"; +} + + +`gcc -s -nostdlib -Wl,-warn-common -shared \\ + -o libuClibc-0.9.5.so \\ + -Wl,-soname,libc.so.0 -Wl,--script=ldscript \\ + $topdir/libc/libc.a \\ + $topdir/libc/tmp/libgcc-need.a` + diff --git a/extra/locale/LOCALES b/extra/locale/LOCALES new file mode 100644 index 0000000..0a30cc1 --- /dev/null +++ b/extra/locale/LOCALES @@ -0,0 +1,346 @@ +# First some @modifier mappings. Internally, the modifier is signaled by +# replacing '_' in the locale name with a unique identifying character. +# For example, internally we map "ca_ES@euro" to "caeES". This allows for +# smaller code and easier processing of locale names. + +@euro e +@cyrillic c + +#--------------------------------------------------------------------------- +# Next, set to {y}es to enable and {n}o to disable the UTF-8 and the 8-bit +# codeset locales. Of course, you must have built the c8tables.h and +# the wctables.h files appropriately. + + +UTF-8 yes +8-BIT yes + +#--------------------------------------------------------------------------- +# Now the locales + +af_ZA ISO-8859-1 +af_ZA.UTF-8 UTF-8 +am_ET UTF-8 +ar_AE ISO-8859-6 +ar_AE.UTF-8 UTF-8 +ar_BH ISO-8859-6 +ar_BH.UTF-8 UTF-8 +ar_DZ ISO-8859-6 +ar_DZ.UTF-8 UTF-8 +ar_EG ISO-8859-6 +ar_EG.UTF-8 UTF-8 +ar_IN UTF-8 +ar_IQ ISO-8859-6 +ar_IQ.UTF-8 UTF-8 +ar_JO ISO-8859-6 +ar_JO.UTF-8 UTF-8 +ar_KW ISO-8859-6 +ar_KW.UTF-8 UTF-8 +ar_LB ISO-8859-6 +ar_LB.UTF-8 UTF-8 +ar_LY ISO-8859-6 +ar_LY.UTF-8 UTF-8 +ar_MA ISO-8859-6 +ar_MA.UTF-8 UTF-8 +ar_OM ISO-8859-6 +ar_OM.UTF-8 UTF-8 +ar_QA ISO-8859-6 +ar_QA.UTF-8 UTF-8 +ar_SA ISO-8859-6 +ar_SA.UTF-8 UTF-8 +ar_SD ISO-8859-6 +ar_SD.UTF-8 UTF-8 +ar_SY ISO-8859-6 +ar_SY.UTF-8 UTF-8 +ar_TN ISO-8859-6 +ar_TN.UTF-8 UTF-8 +ar_YE ISO-8859-6 +ar_YE.UTF-8 UTF-8 +# az_AZ ISO-8859-9E +az_AZ ISO-8859-9 +az_AZ.UTF-8 UTF-8 +be_BY CP1251 +be_BY.UTF-8 UTF-8 +bg_BG CP1251 +bg_BG.UTF-8 UTF-8 +bn_BD UTF-8 +bn_IN UTF-8 +br_FR ISO-8859-1 +br_FR.UTF-8 UTF-8 +bs_BA ISO-8859-2 +bs_BA.UTF-8 UTF-8 +ca_ES ISO-8859-1 +ca_ES.UTF-8 UTF-8 +ca_ES.UTF-8@euro UTF-8 +ca_ES@euro ISO-8859-15 +cs_CZ ISO-8859-2 +cs_CZ.UTF-8 UTF-8 +cy_GB ISO-8859-14 +cy_GB.UTF-8 UTF-8 +da_DK ISO-8859-1 +da_DK.UTF-8 UTF-8 +de_AT ISO-8859-1 +de_AT.UTF-8 UTF-8 +de_AT.UTF-8@euro UTF-8 +de_AT@euro ISO-8859-15 +de_BE ISO-8859-1 +de_BE.UTF-8 UTF-8 +de_BE.UTF-8@euro UTF-8 +de_BE@euro ISO-8859-15 +de_CH ISO-8859-1 +de_CH.UTF-8 UTF-8 +de_DE ISO-8859-1 +de_DE.UTF-8 UTF-8 +de_DE.UTF-8@euro UTF-8 +de_DE@euro ISO-8859-15 +de_LU ISO-8859-1 +de_LU.UTF-8 UTF-8 +de_LU.UTF-8@euro UTF-8 +de_LU@euro ISO-8859-15 +el_GR ISO-8859-7 +el_GR.UTF-8 UTF-8 +en_AU ISO-8859-1 +en_AU.UTF-8 UTF-8 +en_BW ISO-8859-1 +en_BW.UTF-8 UTF-8 +en_CA ISO-8859-1 +en_CA.UTF-8 UTF-8 +en_DK ISO-8859-1 +en_DK.UTF-8 UTF-8 +en_GB ISO-8859-1 +en_GB.UTF-8 UTF-8 +en_HK ISO-8859-1 +en_HK.UTF-8 UTF-8 +en_IE ISO-8859-1 +en_IE.UTF-8 UTF-8 +en_IE.UTF-8@euro UTF-8 +en_IE@euro ISO-8859-15 +en_IN UTF-8 +en_NZ ISO-8859-1 +en_NZ.UTF-8 UTF-8 +en_PH ISO-8859-1 +en_PH.UTF-8 UTF-8 +en_SG ISO-8859-1 +en_SG.UTF-8 UTF-8 +en_US ISO-8859-1 +en_US.UTF-8 UTF-8 +en_ZA ISO-8859-1 +en_ZA.UTF-8 UTF-8 +en_ZW ISO-8859-1 +en_ZW.UTF-8 UTF-8 +eo_EO.UTF-8 UTF-8 +es_AR ISO-8859-1 +es_AR.UTF-8 UTF-8 +es_BO ISO-8859-1 +es_BO.UTF-8 UTF-8 +es_CL ISO-8859-1 +es_CL.UTF-8 UTF-8 +es_CO ISO-8859-1 +es_CO.UTF-8 UTF-8 +es_CR ISO-8859-1 +es_CR.UTF-8 UTF-8 +es_DO ISO-8859-1 +es_DO.UTF-8 UTF-8 +es_EC ISO-8859-1 +es_EC.UTF-8 UTF-8 +es_ES ISO-8859-1 +es_ES.UTF-8 UTF-8 +es_ES.UTF-8@euro UTF-8 +es_ES@euro ISO-8859-15 +es_GT ISO-8859-1 +es_GT.UTF-8 UTF-8 +es_HN ISO-8859-1 +es_HN.UTF-8 UTF-8 +es_MX ISO-8859-1 +es_MX.UTF-8 UTF-8 +es_NI ISO-8859-1 +es_NI.UTF-8 UTF-8 +es_PA ISO-8859-1 +es_PA.UTF-8 UTF-8 +es_PE ISO-8859-1 +es_PE.UTF-8 UTF-8 +es_PR ISO-8859-1 +es_PR.UTF-8 UTF-8 +es_PY ISO-8859-1 +es_PY.UTF-8 UTF-8 +es_SV ISO-8859-1 +es_SV.UTF-8 UTF-8 +es_US ISO-8859-1 +es_US.UTF-8 UTF-8 +es_UY ISO-8859-1 +es_UY.UTF-8 UTF-8 +es_VE ISO-8859-1 +es_VE.UTF-8 UTF-8 +et_EE ISO-8859-1 +et_EE.UTF-8 UTF-8 +eu_ES ISO-8859-1 +eu_ES.UTF-8 UTF-8 +eu_ES.UTF-8@euro UTF-8 +eu_ES@euro ISO-8859-15 +fa_IR UTF-8 +fa_IR.UTF-8 UTF-8 +fi_FI ISO-8859-1 +fi_FI.UTF-8 UTF-8 +fi_FI.UTF-8@euro UTF-8 +fi_FI@euro ISO-8859-15 +fo_FO ISO-8859-1 +fo_FO.UTF-8 UTF-8 +fr_BE ISO-8859-1 +fr_BE.UTF-8 UTF-8 +fr_BE.UTF-8@euro UTF-8 +fr_BE@euro ISO-8859-15 +fr_CA ISO-8859-1 +fr_CA.UTF-8 UTF-8 +fr_CH ISO-8859-1 +fr_CH.UTF-8 UTF-8 +fr_FR ISO-8859-1 +fr_FR.UTF-8 UTF-8 +fr_FR.UTF-8@euro UTF-8 +fr_FR@euro ISO-8859-15 +fr_LU ISO-8859-1 +fr_LU.UTF-8 UTF-8 +fr_LU.UTF-8@euro UTF-8 +fr_LU@euro ISO-8859-15 +ga_IE ISO-8859-1 +ga_IE.UTF-8 UTF-8 +ga_IE.UTF-8@euro UTF-8 +ga_IE@euro ISO-8859-15 +gd_GB ISO-8859-15 +gd_GB.UTF-8 UTF-8 +gl_ES ISO-8859-1 +gl_ES.UTF-8 UTF-8 +gl_ES.UTF-8@euro UTF-8 +gl_ES@euro ISO-8859-15 +gv_GB ISO-8859-1 +gv_GB.UTF-8 UTF-8 +he_IL ISO-8859-8 +he_IL.UTF-8 UTF-8 +hi_IN UTF-8 +hi_IN.UTF-8 UTF-8 +hr_HR ISO-8859-2 +hr_HR.UTF-8 UTF-8 +hu_HU ISO-8859-2 +hu_HU.UTF-8 UTF-8 +hy_AM ARMSCII-8 +hy_AM.UTF-8 UTF-8 +id_ID ISO-8859-1 +id_ID.UTF-8 UTF-8 +is_IS ISO-8859-1 +is_IS.UTF-8 UTF-8 +it_CH ISO-8859-1 +it_CH.UTF-8 UTF-8 +it_IT ISO-8859-1 +it_IT.UTF-8 UTF-8 +it_IT.UTF-8@euro UTF-8 +it_IT@euro ISO-8859-15 +iw_IL ISO-8859-8 +iw_IL.UTF-8 UTF-8 +ja_JP.UTF-8 UTF-8 +ka_GE GEORGIAN-PS +ka_GE.UTF-8 UTF-8 +kl_GL ISO-8859-1 +kl_GL.UTF-8 UTF-8 +ko_KR.UTF-8 UTF-8 +kw_GB ISO-8859-1 +kw_GB.UTF-8 UTF-8 +lt_LT ISO-8859-13 +lt_LT.UTF-8 UTF-8 +lv_LV ISO-8859-13 +lv_LV.UTF-8 UTF-8 +mi_NZ ISO-8859-13 +mi_NZ.UTF-8 UTF-8 +mk_MK ISO-8859-5 +mk_MK.UTF-8 UTF-8 +mr_IN UTF-8 +mr_IN.UTF-8 UTF-8 +ms_MY ISO-8859-1 +ms_MY.UTF-8 UTF-8 +mt_MT ISO-8859-3 +mt_MT.UTF-8 UTF-8 +nl_BE ISO-8859-1 +nl_BE.UTF-8 UTF-8 +nl_BE.UTF-8@euro UTF-8 +nl_BE@euro ISO-8859-15 +nl_NL ISO-8859-1 +nl_NL.UTF-8 UTF-8 +nl_NL.UTF-8@euro UTF-8 +nl_NL@euro ISO-8859-15 +nn_NO ISO-8859-1 +nn_NO.UTF-8 UTF-8 +no_NO ISO-8859-1 +no_NO.UTF-8 UTF-8 +oc_FR ISO-8859-1 +oc_FR.UTF-8 UTF-8 +pl_PL ISO-8859-2 +pl_PL.UTF-8 UTF-8 +pt_BR ISO-8859-1 +pt_BR.UTF-8 UTF-8 +pt_PT ISO-8859-1 +pt_PT.UTF-8 UTF-8 +pt_PT.UTF-8@euro UTF-8 +pt_PT@euro ISO-8859-15 +ro_RO ISO-8859-2 +ro_RO.UTF-8 UTF-8 +ru_RU ISO-8859-5 +ru_RU.KOI8-R KOI8-R +ru_RU.UTF-8 UTF-8 +ru_UA KOI8-U +ru_UA.UTF-8 UTF-8 +se_NO UTF-8 +sk_SK ISO-8859-2 +sk_SK.UTF-8 UTF-8 +sl_SI ISO-8859-2 +sl_SI.UTF-8 UTF-8 +sq_AL ISO-8859-1 +sq_AL.UTF-8 UTF-8 +sr_YU ISO-8859-2 +sr_YU.UTF-8 UTF-8 +sr_YU.UTF-8@cyrillic UTF-8 +sr_YU@cyrillic ISO-8859-5 +sv_FI ISO-8859-1 +sv_FI.UTF-8 UTF-8 +sv_FI.UTF-8@euro UTF-8 +sv_FI@euro ISO-8859-15 +sv_SE ISO-8859-1 +sv_SE.UTF-8 UTF-8 +ta_IN UTF-8 +te_IN UTF-8 +tg_TJ KOI8-T +tg_TJ.UTF-8 UTF-8 +th_TH TIS-620 +th_TH.UTF-8 UTF-8 +ti_ER UTF-8 +ti_ET UTF-8 +tl_PH ISO-8859-1 +tl_PH.UTF-8 UTF-8 +tr_TR ISO-8859-9 +tr_TR.UTF-8 UTF-8 +# tt_RU TATAR-CYR +tt_RU.UTF-8 UTF-8 +uk_UA KOI8-U +uk_UA.UTF-8 UTF-8 +ur_PK UTF-8 +uz_UZ ISO-8859-1 +uz_UZ.UTF-8 UTF-8 +vi_VN UTF-8 +vi_VN.UTF-8 UTF-8 +wa_BE ISO-8859-1 +wa_BE.UTF-8 UTF-8 +wa_BE@euro ISO-8859-15 +yi_US CP1255 +yi_US.UTF-8 UTF-8 +zh_CN.UTF-8 UTF-8 +zh_HK.UTF-8 UTF-8 +zh_SG UTF-8 +zh_TW.UTF-8 UTF-8 + +# The following are standard locales, but we currently don't support +# the necessary multibyte encodings. +# ja_JP.EUC-JP EUC-JP +# ko_KR.EUC-KR EUC-KR +# zh_CN GB2312 +# zh_CN.GB18030 GB18030 +# zh_CN.GBK GBK +# zh_TW.EUC-TW EUC-TW +# zh_HK BIG5-HKSCS +# zh_TW BIG5 diff --git a/extra/locale/Makefile b/extra/locale/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/extra/locale/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/locale/Makefile.in b/extra/locale/Makefile.in new file mode 100644 index 0000000..b4801b0 --- /dev/null +++ b/extra/locale/Makefile.in @@ -0,0 +1,217 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +locale_DIR := $(top_srcdir)extra/locale +locale_OUT := $(top_builddir)extra/locale + +# command used to download source code +WGET := wget --passive-ftp + +LOCALE_DATA_FILENAME := uClibc-locale-20081111-$(ARCH_NATIVE_BIT)-$(if $(ARCH_LITTLE_ENDIAN),el,eb).tgz + +BUILD_CFLAGS-locale-common := \ + -D__UCLIBC_GEN_LOCALE \ + -I$(top_builddir) \ + -DUCLIBC_CTYPE_HEADER='"include/bits/uClibc_ctype.h"' + +BUILD_CFLAGS-gen_wc8bit := $(BUILD_CFLAGS-locale-common) -DCTYPE_PACKED=1 +BUILD_CFLAGS-gen_wctype := $(BUILD_CFLAGS-locale-common) +BUILD_CFLAGS-gen_ldc := +ifeq ($(UCLIBC_HAS_WCHAR),y) +BUILD_CFLAGS-gen_wc8bit += -DDO_WIDE_CHAR=1 +BUILD_CFLAGS-gen_ldc += -D__WCHAR_ENABLED=1 +endif +BUILD_CFLAGS-gen_locale := -D_GNU_SOURCE -I$(locale_OUT) +BUILD_CFLAGS-gen_collate := -D_GNU_SOURCE + +locale_headers-$(UCLIBC_HAS_LOCALE) := $(top_builddir)include/bits/uClibc_locale_data.h + +#DEPH-locale := $(top_builddir)include/bits/sysnum.h +DEPH-locale := $(top_builddir)include/bits/uClibc_config.h +DEPH-gen_collate := $(DEPH-locale) +DEPH-gen_ldc := $(addprefix $(locale_OUT)/,c8tables.h wctables.h locale_tables.h locale_collate.h) $(DEPH-locale) +DEPH-gen_locale := $(addprefix $(locale_OUT)/,c8tables.h) $(DEPH-locale) +DEPH-gen_wc8bit := $(top_builddir)/include/bits/uClibc_ctype.h $(DEPH-locale) +DEPH-gen_wctype := $(top_builddir)/include/bits/uClibc_ctype.h $(DEPH-locale) + +locale_HOBJ := gen_collate gen_ldc gen_locale gen_wc8bit gen_wctype +locale_HOBJ := $(addprefix $(locale_OUT)/,$(locale_HOBJ)) + +locale_SRC := $(locale_OUT)/locale_data.c +locale_OBJ := $(locale_OUT)/locale_data.o + +CFLAGS-locale_data.c := -D__WCHAR_ENABLED -I$(locale_OUT) -I$(locale_DIR) + +#headers-$(UCLIBC_HAS_LOCALE) += $(locale_headers-y) +headers: $(locale_headers-y) + +libc-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ) + +libc-nomulti-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ) + +locale_headers: headers $(top_builddir)include/bits/uClibc_locale_data.h + +# make sure that the host system has locales (this check is ok for uClibc/glibc) +# we do not know though which locales were really enabled for libc at build time +ifeq ($(wildcard /usr/include/iconv.h),) + +$(locale_OUT)/codesets.txt: + @if [ ! -f $@ ] ; then \ + set -e; \ + echo " "; \ + echo "You do not have a codesets.txt file. Please create this "; \ + echo "file in the $(locale_OUT) directory by running something like: "; \ + echo " cd $(locale_DIR)/ && find charmaps -name \"*.pairs\" > \\"; \ + echo " $@"; \ + echo "and then edit that file to disable/enable the codesets you wish to support. "; \ + echo " "; \ + false; \ + fi; + +$(locale_OUT)/locales.txt: + @if [ ! -f $@ ] ; then \ + set -e; \ + echo " "; \ + echo "You do not have a locales.txt file in the $(locale_OUT) "; \ + echo "directory, Please copy the LOCALES file to locales.txt by "; \ + echo "running something like: "; \ + echo " cp $(locale_DIR)/LOCALES \\ "; \ + echo " $@ "; \ + echo "then edit locales.txt to disable/enable the locales you wish "; \ + echo "to support. "; \ + echo " "; \ + false; \ + fi; + +else + +$(locale_OUT)/codesets.txt: + @$(disp_gen) +ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y) + $(Q)echo "charmaps/ASCII.pairs" > $@ ; \ + $(Q)echo "charmaps/ISO-8859-1.pairs" >> $@ +else + $(Q)(cd $(locale_DIR)/ && find charmaps/ -name '*.pairs' | sort ) > $@ +endif + +# the lines beginning w/ '#-' are mandatory +# at least one conversion is needed (euro/cyrillic) +$(locale_OUT)/locales.txt: $(locale_DIR)/LOCALES + @$(disp_gen) +ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y) + $(Q)echo "@euro e" > $@ ; \ + $(Q)echo "#-" >> $@ ; \ + $(Q)echo "UTF-8 yes" >> $@ ; \ + $(Q)echo "8-BIT yes" >> $@ ; \ + $(Q)echo "#-" >> $@ ; \ + $(Q)echo "en_US.UTF-8 UTF-8" >> $@ ; \ + $(Q)echo "en_US ISO-8859-1" >> $@ +else + $(Q)cat $< > $@ +endif + +endif + +$(locale_DIR)/gen_collate.c: $(DEPH-gen_collate) +$(locale_OUT)/gen_collate : $(locale_DIR)/gen_collate.c + $(hcompile.u) +$(locale_DIR)/gen_ldc.c: $(DEPH-gen_ldc) +$(locale_OUT)/gen_ldc : $(locale_DIR)/gen_ldc.c + $(hcompile.u) +$(locale_DIR)/gen_locale.c: $(DEPH-gen_locale) +$(locale_OUT)/gen_locale : $(locale_DIR)/gen_locale.c + $(hcompile.u) +$(locale_DIR)/gen_wc8bit.c: $(DEPH-gen_wc8bit) +$(locale_OUT)/gen_wc8bit : $(locale_DIR)/gen_wc8bit.c + $(hcompile.u) +$(locale_DIR)/gen_wctype.c: $(DEPH-gen_wctype) +$(locale_OUT)/gen_wctype : $(locale_DIR)/gen_wctype.c + $(hcompile.u) + +ifneq ($(V),) +ifeq ($(V),1) +FLAG-locale-verbose := -v +endif +ifeq ($(V),2) +FLAG-locale-verbose := -v -v +endif +endif + +# code needs to be modified to support top_builddir in almost all apps that write directly to a file +# grep fopen *.c +$(locale_OUT)/c8tables.h: $(locale_OUT)/gen_wc8bit $(locale_OUT)/codesets.txt + @$(disp_gen) + $(Q)(cd $( $@ + $(Q)grep "^#define __lc" $(word 2,$^) >> $@ + +$(locale_OUT)/locale_collate.h: $(locale_OUT)/gen_collate $(locale_OUT)/locale_tables.h + @$(disp_gen) + $(Q)grep COL_IDX_ $(word 2,$^) | \ + $(SED) -e "s/^.*COL_IDX_\([^, ]*\).*$$/\1/" | sort | uniq | \ + xargs $< $(locale_DIR)/collation $(FLAG-locale-verbose) -o $@ + +$(locale_OUT)/$(LOCALE_DATA_FILENAME): +ifeq ($(UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA),y) + ( cd $(dir $@); $(WGET) http://www.uclibc.org/downloads/$(notdir $@) ) +endif + +ifeq ($(UCLIBC_PREGENERATED_LOCALE_DATA),y) + +$(locale_SRC): $(locale_OUT)/$(LOCALE_DATA_FILENAME) + zcat $< | $(TAR) -xv -C $(dir $@) -f - + touch $@ + # we use the one in locale_DIR + #$(RM) $(locale_OUT)/locale_mmap.h + +# for arch specific versions we have to at least overwrite +# lt_defines.h/locale_data.c/uClibc_locale_data.h + +$(locale_OUT)/uClibc_locale_data.h: $(locale_SRC) + +else + +$(locale_SRC): $(locale_OUT)/gen_ldc $(locale_OUT)/lt_defines.h + @$(disp_gen) + $(Q)$< $@ + +$(locale_OUT)/uClibc_locale_data.h: $(locale_OUT)/lt_defines.h $(locale_OUT)/c8tables.h $(locale_OUT)/wctables.h $(locale_DIR)/locale_mmap.h | $(locale_SRC) + @$(disp_gen) + $(Q)grep -v "define __LC" $< > $@ + $(Q)cat $(wordlist 2,4,$^) >> $@ + +endif + +$(top_builddir)include/bits/uClibc_locale_data.h: $(locale_OUT)/uClibc_locale_data.h | $(top_builddir)include/bits/uClibc_config.h + @$(disp_gen) + $(Q)$(AWK) 'BEGIN{i=1}{if (/WANT_/) i=/endif/;else if (i) print $0}' \ + $< > $@ + +objclean-y += locale_clean + +# lmmtolso.c/gen_mmap.c/tst-*.c not used +locale_clean: + $(do_rm) $(locale_HOBJ) $(locale_SRC) $(addprefix $(locale_OUT)/*., o os txt) \ + $(addprefix $(locale_OUT)/,$(addsuffix .h,uClibc_locale_data lt_defines c8tables wctables locale_tables locale_collate) lmmtolso gen_mmap locale.mmap) diff --git a/extra/locale/README b/extra/locale/README new file mode 100644 index 0000000..244b925 --- /dev/null +++ b/extra/locale/README @@ -0,0 +1,71 @@ +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! + +The programs in this directory are strictly cut-and-paste hack jobs to +extract the data I needed from glibc's locale database. I'm ashamed to +even let them into the light of day, and I consider them complete garbage. + +However, they are currently necessary to build the data needed for the +locale support I've implemented, so I'm forced to include them here. + +NOTE: While its possible to use this stuff for native != target arch, +you'll have to either write a converter to account for endianess and +struct padding issues, or run the mmap file generator on your target +arch. But all these programs will be rewritten at some point. + +All that being said, LC_CTYPE support has been added and supports the +ctype.h and wctype.h function. Also, LC_TIME, LC_MONETARY, LC_NUMERIC, +and LC_MESSAGES are supported wrt SUSv3. localeconv() works in both +real and stub locale modes. nl_langinfo() currently only works with +real locales enabled. That will be fixed though. wc->mb unsupported +char replacement and basic translit support is on the way as well. +Finally, some basic 8-bit codeset LC_COLLATE support should be in place +in the next week or two (similar to what was in the previous locale +implementation). + +Also, as one can probably guess, I'm working towards having the locale +data accessed via a shared mmap. That will allow non-mmu platforms +to use this without the current bloat. + +Currently, the output of size for my locale_data.o file is + text data bss dec hex filename + 59072 4 0 59076 e6c4 extra/locale/locale_data.o +which is for the C locale (automatic of course) + all codesets in +charmaps/ and all 268 locales in LOCALES. I estimate that the +translit support for those 8-bit codesets will add another 7-10k. + +One difference of note is that the special case upper/lower mappings +in the turkish locale are currently not implemented. That will be +fixed. + +Manuel + +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! + + +1) In the toplevel dir, 'make headers'. + +2) Create a codesets.txt file in this dir listing the codesets you want + to support. The easiest way to do this is to edit the output of + 'find ./charmaps -name "*.pairs" > codesets.txt'. + NOTE: UTF-8 support is always included if you build with wide chars enabled. + NOTE: The files in charmaps/ were created from glibc's charmap files + with the awk script at the end of this file. You can add others + but only single byte codesets are supported. + +3) Create a locales.txt file to select the locales you want to support. + You can copy and edit the LOCALES file for example. Other locales could + added provided you've included the appropriate codesets in step 2. + NOTE: You have to have the approprite locales available for glibc! + +4) Run make here. + +5) Continue building uClibc from the toplevel dir. + + + + +Script used to generate the charmaps/*.pairs files: + +cat $1 | awk 'BEGIN { i = 0 } ; { if ($1 == "CHARMAP") i=1 ; else if ($1 == "END") i=0 ; else if (i==1) { sub("/","0",$2) ; sub("","",$1) ; print "{", $2, ",", $1, "}," } }' diff --git a/extra/locale/charmaps/ARMSCII-8.pairs b/extra/locale/charmaps/ARMSCII-8.pairs new file mode 100644 index 0000000..6a0f441 --- /dev/null +++ b/extra/locale/charmaps/ARMSCII-8.pairs @@ -0,0 +1,254 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa2 , 0x0587 }, +{ 0xa3 , 0x0589 }, +{ 0xa4 , 0x0029 }, +{ 0xa5 , 0x0028 }, +{ 0xa6 , 0x00BB }, +{ 0xa7 , 0x00AB }, +{ 0xa8 , 0x2014 }, +{ 0xa9 , 0x002E }, +{ 0xaa , 0x055D }, +{ 0xab , 0x002C }, +{ 0xac , 0x002D }, +{ 0xad , 0x058A }, +{ 0xae , 0x2026 }, +{ 0xaf , 0x055C }, +{ 0xb0 , 0x055B }, +{ 0xb1 , 0x055E }, +{ 0xb2 , 0x0531 }, +{ 0xb3 , 0x0561 }, +{ 0xb4 , 0x0532 }, +{ 0xb5 , 0x0562 }, +{ 0xb6 , 0x0533 }, +{ 0xb7 , 0x0563 }, +{ 0xb8 , 0x0534 }, +{ 0xb9 , 0x0564 }, +{ 0xba , 0x0535 }, +{ 0xbb , 0x0565 }, +{ 0xbc , 0x0536 }, +{ 0xbd , 0x0566 }, +{ 0xbe , 0x0537 }, +{ 0xbf , 0x0567 }, +{ 0xc0 , 0x0538 }, +{ 0xc1 , 0x0568 }, +{ 0xc2 , 0x0539 }, +{ 0xc3 , 0x0569 }, +{ 0xc4 , 0x053A }, +{ 0xc5 , 0x056A }, +{ 0xc6 , 0x053B }, +{ 0xc7 , 0x056B }, +{ 0xc8 , 0x053C }, +{ 0xc9 , 0x056C }, +{ 0xca , 0x053D }, +{ 0xcb , 0x056D }, +{ 0xcc , 0x053E }, +{ 0xcd , 0x056E }, +{ 0xce , 0x053F }, +{ 0xcf , 0x056F }, +{ 0xd0 , 0x0540 }, +{ 0xd1 , 0x0570 }, +{ 0xd2 , 0x0541 }, +{ 0xd3 , 0x0571 }, +{ 0xd4 , 0x0542 }, +{ 0xd5 , 0x0572 }, +{ 0xd6 , 0x0543 }, +{ 0xd7 , 0x0573 }, +{ 0xd8 , 0x0544 }, +{ 0xd9 , 0x0574 }, +{ 0xda , 0x0545 }, +{ 0xdb , 0x0575 }, +{ 0xdc , 0x0546 }, +{ 0xdd , 0x0576 }, +{ 0xde , 0x0547 }, +{ 0xdf , 0x0577 }, +{ 0xe0 , 0x0548 }, +{ 0xe1 , 0x0578 }, +{ 0xe2 , 0x0549 }, +{ 0xe3 , 0x0579 }, +{ 0xe4 , 0x054A }, +{ 0xe5 , 0x057A }, +{ 0xe6 , 0x054B }, +{ 0xe7 , 0x057B }, +{ 0xe8 , 0x054C }, +{ 0xe9 , 0x057C }, +{ 0xea , 0x054D }, +{ 0xeb , 0x057D }, +{ 0xec , 0x054E }, +{ 0xed , 0x057E }, +{ 0xee , 0x054F }, +{ 0xef , 0x057F }, +{ 0xf0 , 0x0550 }, +{ 0xf1 , 0x0580 }, +{ 0xf2 , 0x0551 }, +{ 0xf3 , 0x0581 }, +{ 0xf4 , 0x0552 }, +{ 0xf5 , 0x0582 }, +{ 0xf6 , 0x0553 }, +{ 0xf7 , 0x0583 }, +{ 0xf8 , 0x0554 }, +{ 0xf9 , 0x0584 }, +{ 0xfa , 0x0555 }, +{ 0xfb , 0x0585 }, +{ 0xfc , 0x0556 }, +{ 0xfd , 0x0586 }, +{ 0xfe , 0x055A }, diff --git a/extra/locale/charmaps/ASCII.pairs b/extra/locale/charmaps/ASCII.pairs new file mode 100644 index 0000000..038314d --- /dev/null +++ b/extra/locale/charmaps/ASCII.pairs @@ -0,0 +1,128 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, diff --git a/extra/locale/charmaps/CP1251.pairs b/extra/locale/charmaps/CP1251.pairs new file mode 100644 index 0000000..a5a80d6 --- /dev/null +++ b/extra/locale/charmaps/CP1251.pairs @@ -0,0 +1,255 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0402 }, +{ 0x81 , 0x0403 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0453 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x20AC }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x0409 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x040A }, +{ 0x8d , 0x040C }, +{ 0x8e , 0x040B }, +{ 0x8f , 0x040F }, +{ 0x90 , 0x0452 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x99 , 0x2122 }, +{ 0x9a , 0x0459 }, +{ 0x9b , 0x203A }, +{ 0x9c , 0x045A }, +{ 0x9d , 0x045C }, +{ 0x9e , 0x045B }, +{ 0x9f , 0x045F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x040E }, +{ 0xa2 , 0x045E }, +{ 0xa3 , 0x0408 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x0490 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0401 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0404 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x0407 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x0406 }, +{ 0xb3 , 0x0456 }, +{ 0xb4 , 0x0491 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x0451 }, +{ 0xb9 , 0x2116 }, +{ 0xba , 0x0454 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0458 }, +{ 0xbd , 0x0405 }, +{ 0xbe , 0x0455 }, +{ 0xbf , 0x0457 }, +{ 0xc0 , 0x0410 }, +{ 0xc1 , 0x0411 }, +{ 0xc2 , 0x0412 }, +{ 0xc3 , 0x0413 }, +{ 0xc4 , 0x0414 }, +{ 0xc5 , 0x0415 }, +{ 0xc6 , 0x0416 }, +{ 0xc7 , 0x0417 }, +{ 0xc8 , 0x0418 }, +{ 0xc9 , 0x0419 }, +{ 0xca , 0x041A }, +{ 0xcb , 0x041B }, +{ 0xcc , 0x041C }, +{ 0xcd , 0x041D }, +{ 0xce , 0x041E }, +{ 0xcf , 0x041F }, +{ 0xd0 , 0x0420 }, +{ 0xd1 , 0x0421 }, +{ 0xd2 , 0x0422 }, +{ 0xd3 , 0x0423 }, +{ 0xd4 , 0x0424 }, +{ 0xd5 , 0x0425 }, +{ 0xd6 , 0x0426 }, +{ 0xd7 , 0x0427 }, +{ 0xd8 , 0x0428 }, +{ 0xd9 , 0x0429 }, +{ 0xda , 0x042A }, +{ 0xdb , 0x042B }, +{ 0xdc , 0x042C }, +{ 0xdd , 0x042D }, +{ 0xde , 0x042E }, +{ 0xdf , 0x042F }, +{ 0xe0 , 0x0430 }, +{ 0xe1 , 0x0431 }, +{ 0xe2 , 0x0432 }, +{ 0xe3 , 0x0433 }, +{ 0xe4 , 0x0434 }, +{ 0xe5 , 0x0435 }, +{ 0xe6 , 0x0436 }, +{ 0xe7 , 0x0437 }, +{ 0xe8 , 0x0438 }, +{ 0xe9 , 0x0439 }, +{ 0xea , 0x043A }, +{ 0xeb , 0x043B }, +{ 0xec , 0x043C }, +{ 0xed , 0x043D }, +{ 0xee , 0x043E }, +{ 0xef , 0x043F }, +{ 0xf0 , 0x0440 }, +{ 0xf1 , 0x0441 }, +{ 0xf2 , 0x0442 }, +{ 0xf3 , 0x0443 }, +{ 0xf4 , 0x0444 }, +{ 0xf5 , 0x0445 }, +{ 0xf6 , 0x0446 }, +{ 0xf7 , 0x0447 }, +{ 0xf8 , 0x0448 }, +{ 0xf9 , 0x0449 }, +{ 0xfa , 0x044A }, +{ 0xfb , 0x044B }, +{ 0xfc , 0x044C }, +{ 0xfd , 0x044D }, +{ 0xfe , 0x044E }, +{ 0xff , 0x044F }, diff --git a/extra/locale/charmaps/CP1255.pairs b/extra/locale/charmaps/CP1255.pairs new file mode 100644 index 0000000..123bb5a --- /dev/null +++ b/extra/locale/charmaps/CP1255.pairs @@ -0,0 +1,233 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x20AC }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0192 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x02C6 }, +{ 0x89 , 0x2030 }, +{ 0x8b , 0x2039 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x98 , 0x02DC }, +{ 0x99 , 0x2122 }, +{ 0x9b , 0x203A }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x20AA }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00D7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00F7 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x05B0 }, +{ 0xc1 , 0x05B1 }, +{ 0xc2 , 0x05B2 }, +{ 0xc3 , 0x05B3 }, +{ 0xc4 , 0x05B4 }, +{ 0xc5 , 0x05B5 }, +{ 0xc6 , 0x05B6 }, +{ 0xc7 , 0x05B7 }, +{ 0xc8 , 0x05B8 }, +{ 0xc9 , 0x05B9 }, +{ 0xcb , 0x05BB }, +{ 0xcc , 0x05BC }, +{ 0xcd , 0x05BD }, +{ 0xce , 0x05BE }, +{ 0xcf , 0x05BF }, +{ 0xd0 , 0x05C0 }, +{ 0xd1 , 0x05C1 }, +{ 0xd2 , 0x05C2 }, +{ 0xd3 , 0x05C3 }, +{ 0xd4 , 0x05F0 }, +{ 0xd5 , 0x05F1 }, +{ 0xd6 , 0x05F2 }, +{ 0xd7 , 0x05F3 }, +{ 0xd8 , 0x05F4 }, +{ 0xe0 , 0x05D0 }, +{ 0xe1 , 0x05D1 }, +{ 0xe2 , 0x05D2 }, +{ 0xe3 , 0x05D3 }, +{ 0xe4 , 0x05D4 }, +{ 0xe5 , 0x05D5 }, +{ 0xe6 , 0x05D6 }, +{ 0xe7 , 0x05D7 }, +{ 0xe8 , 0x05D8 }, +{ 0xe9 , 0x05D9 }, +{ 0xea , 0x05DA }, +{ 0xeb , 0x05DB }, +{ 0xec , 0x05DC }, +{ 0xed , 0x05DD }, +{ 0xee , 0x05DE }, +{ 0xef , 0x05DF }, +{ 0xf0 , 0x05E0 }, +{ 0xf1 , 0x05E1 }, +{ 0xf2 , 0x05E2 }, +{ 0xf3 , 0x05E3 }, +{ 0xf4 , 0x05E4 }, +{ 0xf5 , 0x05E5 }, +{ 0xf6 , 0x05E6 }, +{ 0xf7 , 0x05E7 }, +{ 0xf8 , 0x05E8 }, +{ 0xf9 , 0x05E9 }, +{ 0xfa , 0x05EA }, +{ 0xfd , 0x200E }, +{ 0xfe , 0x200F }, diff --git a/extra/locale/charmaps/GEORGIAN-PS.pairs b/extra/locale/charmaps/GEORGIAN-PS.pairs new file mode 100644 index 0000000..815b2e6 --- /dev/null +++ b/extra/locale/charmaps/GEORGIAN-PS.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0192 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x02C6 }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x0160 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x0152 }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x98 , 0x02DC }, +{ 0x99 , 0x2122 }, +{ 0x9a , 0x0161 }, +{ 0x9b , 0x203A }, +{ 0x9c , 0x0153 }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x0178 }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x10D0 }, +{ 0xc1 , 0x10D1 }, +{ 0xc2 , 0x10D2 }, +{ 0xc3 , 0x10D3 }, +{ 0xc4 , 0x10D4 }, +{ 0xc5 , 0x10D5 }, +{ 0xc6 , 0x10D6 }, +{ 0xc7 , 0x10F1 }, +{ 0xc8 , 0x10D7 }, +{ 0xc9 , 0x10D8 }, +{ 0xca , 0x10D9 }, +{ 0xcb , 0x10DA }, +{ 0xcc , 0x10DB }, +{ 0xcd , 0x10DC }, +{ 0xce , 0x10F2 }, +{ 0xcf , 0x10DD }, +{ 0xd0 , 0x10DE }, +{ 0xd1 , 0x10DF }, +{ 0xd2 , 0x10E0 }, +{ 0xd3 , 0x10E1 }, +{ 0xd4 , 0x10E2 }, +{ 0xd5 , 0x10F3 }, +{ 0xd6 , 0x10E3 }, +{ 0xd7 , 0x10E4 }, +{ 0xd8 , 0x10E5 }, +{ 0xd9 , 0x10E6 }, +{ 0xda , 0x10E7 }, +{ 0xdb , 0x10E8 }, +{ 0xdc , 0x10E9 }, +{ 0xdd , 0x10EA }, +{ 0xde , 0x10EB }, +{ 0xdf , 0x10EC }, +{ 0xe0 , 0x10ED }, +{ 0xe1 , 0x10EE }, +{ 0xe2 , 0x10F4 }, +{ 0xe3 , 0x10EF }, +{ 0xe4 , 0x10F0 }, +{ 0xe5 , 0x10F5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/ISO-8859-1.pairs b/extra/locale/charmaps/ISO-8859-1.pairs new file mode 100644 index 0000000..97812a0 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-1.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/ISO-8859-10.pairs b/extra/locale/charmaps/ISO-8859-10.pairs new file mode 100644 index 0000000..a39892f --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-10.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0112 }, +{ 0xa3 , 0x0122 }, +{ 0xa4 , 0x012A }, +{ 0xa5 , 0x0128 }, +{ 0xa6 , 0x0136 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x013B }, +{ 0xa9 , 0x0110 }, +{ 0xaa , 0x0160 }, +{ 0xab , 0x0166 }, +{ 0xac , 0x017D }, +{ 0xad , 0x00AD }, +{ 0xae , 0x016A }, +{ 0xaf , 0x014A }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x0113 }, +{ 0xb3 , 0x0123 }, +{ 0xb4 , 0x012B }, +{ 0xb5 , 0x0129 }, +{ 0xb6 , 0x0137 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x013C }, +{ 0xb9 , 0x0111 }, +{ 0xba , 0x0161 }, +{ 0xbb , 0x0167 }, +{ 0xbc , 0x017E }, +{ 0xbd , 0x2015 }, +{ 0xbe , 0x016B }, +{ 0xbf , 0x014B }, +{ 0xc0 , 0x0100 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x012E }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x0116 }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x0145 }, +{ 0xd2 , 0x014C }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x0168 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x0172 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0101 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x012F }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x0117 }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x0146 }, +{ 0xf2 , 0x014D }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x0169 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x0173 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x0138 }, diff --git a/extra/locale/charmaps/ISO-8859-13.pairs b/extra/locale/charmaps/ISO-8859-13.pairs new file mode 100644 index 0000000..ff95fb4 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-13.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x201D }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x201E }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00D8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0156 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00C6 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x201C }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00F8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x0157 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00E6 }, +{ 0xc0 , 0x0104 }, +{ 0xc1 , 0x012E }, +{ 0xc2 , 0x0100 }, +{ 0xc3 , 0x0106 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x0118 }, +{ 0xc7 , 0x0112 }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0179 }, +{ 0xcb , 0x0116 }, +{ 0xcc , 0x0122 }, +{ 0xcd , 0x0136 }, +{ 0xce , 0x012A }, +{ 0xcf , 0x013B }, +{ 0xd0 , 0x0160 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x0145 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x014C }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x0172 }, +{ 0xd9 , 0x0141 }, +{ 0xda , 0x015A }, +{ 0xdb , 0x016A }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x017B }, +{ 0xde , 0x017D }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0105 }, +{ 0xe1 , 0x012F }, +{ 0xe2 , 0x0101 }, +{ 0xe3 , 0x0107 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x0119 }, +{ 0xe7 , 0x0113 }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x017A }, +{ 0xeb , 0x0117 }, +{ 0xec , 0x0123 }, +{ 0xed , 0x0137 }, +{ 0xee , 0x012B }, +{ 0xef , 0x013C }, +{ 0xf0 , 0x0161 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x0146 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x014D }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x0173 }, +{ 0xf9 , 0x0142 }, +{ 0xfa , 0x015B }, +{ 0xfb , 0x016B }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x017C }, +{ 0xfe , 0x017E }, +{ 0xff , 0x2019 }, diff --git a/extra/locale/charmaps/ISO-8859-14.pairs b/extra/locale/charmaps/ISO-8859-14.pairs new file mode 100644 index 0000000..8a8f06e --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-14.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x1E02 }, +{ 0xa2 , 0x1E03 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x010A }, +{ 0xa5 , 0x010B }, +{ 0xa6 , 0x1E0A }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x1E80 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x1E82 }, +{ 0xab , 0x1E0B }, +{ 0xac , 0x1EF2 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x0178 }, +{ 0xb0 , 0x1E1E }, +{ 0xb1 , 0x1E1F }, +{ 0xb2 , 0x0120 }, +{ 0xb3 , 0x0121 }, +{ 0xb4 , 0x1E40 }, +{ 0xb5 , 0x1E41 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x1E56 }, +{ 0xb8 , 0x1E81 }, +{ 0xb9 , 0x1E57 }, +{ 0xba , 0x1E83 }, +{ 0xbb , 0x1E60 }, +{ 0xbc , 0x1EF3 }, +{ 0xbd , 0x1E84 }, +{ 0xbe , 0x1E85 }, +{ 0xbf , 0x1E61 }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x0174 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x1E6A }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x0176 }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x0175 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x1E6B }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x0177 }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/ISO-8859-15.pairs b/extra/locale/charmaps/ISO-8859-15.pairs new file mode 100644 index 0000000..ca50e22 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-15.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x20AC }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x0160 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0161 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x017D }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x017E }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0152 }, +{ 0xbd , 0x0153 }, +{ 0xbe , 0x0178 }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/ISO-8859-16.pairs b/extra/locale/charmaps/ISO-8859-16.pairs new file mode 100644 index 0000000..6b74963 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-16.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0105 }, +{ 0xa3 , 0x0141 }, +{ 0xa4 , 0x20AC }, +{ 0xa5 , 0x00AB }, +{ 0xa6 , 0x0160 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0161 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0218 }, +{ 0xab , 0x201E }, +{ 0xac , 0x0179 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017A }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x010C }, +{ 0xb3 , 0x0142 }, +{ 0xb4 , 0x017D }, +{ 0xb5 , 0x201D }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x017E }, +{ 0xb9 , 0x010D }, +{ 0xba , 0x0219 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0152 }, +{ 0xbd , 0x0153 }, +{ 0xbe , 0x0178 }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x0102 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x0106 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0150 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x015A }, +{ 0xd8 , 0x0170 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0118 }, +{ 0xde , 0x021A }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x0103 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x0107 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0151 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x015B }, +{ 0xf8 , 0x0171 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0119 }, +{ 0xfe , 0x021B }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/ISO-8859-2.pairs b/extra/locale/charmaps/ISO-8859-2.pairs new file mode 100644 index 0000000..4e92f94 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-2.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x02D8 }, +{ 0xa3 , 0x0141 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x013D }, +{ 0xa6 , 0x015A }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0160 }, +{ 0xaa , 0x015E }, +{ 0xab , 0x0164 }, +{ 0xac , 0x0179 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017D }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x02DB }, +{ 0xb3 , 0x0142 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x013E }, +{ 0xb6 , 0x015B }, +{ 0xb7 , 0x02C7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0161 }, +{ 0xba , 0x015F }, +{ 0xbb , 0x0165 }, +{ 0xbc , 0x017A }, +{ 0xbd , 0x02DD }, +{ 0xbe , 0x017E }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x0154 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x0102 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x0139 }, +{ 0xc6 , 0x0106 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x011A }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x010E }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x0147 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0150 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x0158 }, +{ 0xd9 , 0x016E }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x0170 }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x0162 }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0155 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x0103 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x013A }, +{ 0xe6 , 0x0107 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x011B }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x010F }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x0148 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0151 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x0159 }, +{ 0xf9 , 0x016F }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x0171 }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x0163 }, +{ 0xff , 0x02D9 }, diff --git a/extra/locale/charmaps/ISO-8859-3.pairs b/extra/locale/charmaps/ISO-8859-3.pairs new file mode 100644 index 0000000..3a8814c --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-3.pairs @@ -0,0 +1,249 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0126 }, +{ 0xa2 , 0x02D8 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa6 , 0x0124 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0130 }, +{ 0xaa , 0x015E }, +{ 0xab , 0x011E }, +{ 0xac , 0x0134 }, +{ 0xad , 0x00AD }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0127 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x0125 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0131 }, +{ 0xba , 0x015F }, +{ 0xbb , 0x011F }, +{ 0xbc , 0x0135 }, +{ 0xbd , 0x00BD }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x010A }, +{ 0xc6 , 0x0108 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0120 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x011C }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x016C }, +{ 0xde , 0x015C }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x010B }, +{ 0xe6 , 0x0109 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0121 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x011D }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x016D }, +{ 0xfe , 0x015D }, +{ 0xff , 0x02D9 }, diff --git a/extra/locale/charmaps/ISO-8859-4.pairs b/extra/locale/charmaps/ISO-8859-4.pairs new file mode 100644 index 0000000..dda865c --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-4.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0138 }, +{ 0xa3 , 0x0156 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x0128 }, +{ 0xa6 , 0x013B }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0160 }, +{ 0xaa , 0x0112 }, +{ 0xab , 0x0122 }, +{ 0xac , 0x0166 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017D }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x02DB }, +{ 0xb3 , 0x0157 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x0129 }, +{ 0xb6 , 0x013C }, +{ 0xb7 , 0x02C7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0161 }, +{ 0xba , 0x0113 }, +{ 0xbb , 0x0123 }, +{ 0xbc , 0x0167 }, +{ 0xbd , 0x014A }, +{ 0xbe , 0x017E }, +{ 0xbf , 0x014B }, +{ 0xc0 , 0x0100 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x012E }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x0116 }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x012A }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0145 }, +{ 0xd2 , 0x014C }, +{ 0xd3 , 0x0136 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x0172 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0168 }, +{ 0xde , 0x016A }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0101 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x012F }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x0117 }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x012B }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0146 }, +{ 0xf2 , 0x014D }, +{ 0xf3 , 0x0137 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x0173 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0169 }, +{ 0xfe , 0x016B }, +{ 0xff , 0x02D9 }, diff --git a/extra/locale/charmaps/ISO-8859-5.pairs b/extra/locale/charmaps/ISO-8859-5.pairs new file mode 100644 index 0000000..08ebcae --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-5.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0401 }, +{ 0xa2 , 0x0402 }, +{ 0xa3 , 0x0403 }, +{ 0xa4 , 0x0404 }, +{ 0xa5 , 0x0405 }, +{ 0xa6 , 0x0406 }, +{ 0xa7 , 0x0407 }, +{ 0xa8 , 0x0408 }, +{ 0xa9 , 0x0409 }, +{ 0xaa , 0x040A }, +{ 0xab , 0x040B }, +{ 0xac , 0x040C }, +{ 0xad , 0x00AD }, +{ 0xae , 0x040E }, +{ 0xaf , 0x040F }, +{ 0xb0 , 0x0410 }, +{ 0xb1 , 0x0411 }, +{ 0xb2 , 0x0412 }, +{ 0xb3 , 0x0413 }, +{ 0xb4 , 0x0414 }, +{ 0xb5 , 0x0415 }, +{ 0xb6 , 0x0416 }, +{ 0xb7 , 0x0417 }, +{ 0xb8 , 0x0418 }, +{ 0xb9 , 0x0419 }, +{ 0xba , 0x041A }, +{ 0xbb , 0x041B }, +{ 0xbc , 0x041C }, +{ 0xbd , 0x041D }, +{ 0xbe , 0x041E }, +{ 0xbf , 0x041F }, +{ 0xc0 , 0x0420 }, +{ 0xc1 , 0x0421 }, +{ 0xc2 , 0x0422 }, +{ 0xc3 , 0x0423 }, +{ 0xc4 , 0x0424 }, +{ 0xc5 , 0x0425 }, +{ 0xc6 , 0x0426 }, +{ 0xc7 , 0x0427 }, +{ 0xc8 , 0x0428 }, +{ 0xc9 , 0x0429 }, +{ 0xca , 0x042A }, +{ 0xcb , 0x042B }, +{ 0xcc , 0x042C }, +{ 0xcd , 0x042D }, +{ 0xce , 0x042E }, +{ 0xcf , 0x042F }, +{ 0xd0 , 0x0430 }, +{ 0xd1 , 0x0431 }, +{ 0xd2 , 0x0432 }, +{ 0xd3 , 0x0433 }, +{ 0xd4 , 0x0434 }, +{ 0xd5 , 0x0435 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0437 }, +{ 0xd8 , 0x0438 }, +{ 0xd9 , 0x0439 }, +{ 0xda , 0x043A }, +{ 0xdb , 0x043B }, +{ 0xdc , 0x043C }, +{ 0xdd , 0x043D }, +{ 0xde , 0x043E }, +{ 0xdf , 0x043F }, +{ 0xe0 , 0x0440 }, +{ 0xe1 , 0x0441 }, +{ 0xe2 , 0x0442 }, +{ 0xe3 , 0x0443 }, +{ 0xe4 , 0x0444 }, +{ 0xe5 , 0x0445 }, +{ 0xe6 , 0x0446 }, +{ 0xe7 , 0x0447 }, +{ 0xe8 , 0x0448 }, +{ 0xe9 , 0x0449 }, +{ 0xea , 0x044A }, +{ 0xeb , 0x044B }, +{ 0xec , 0x044C }, +{ 0xed , 0x044D }, +{ 0xee , 0x044E }, +{ 0xef , 0x044F }, +{ 0xf0 , 0x2116 }, +{ 0xf1 , 0x0451 }, +{ 0xf2 , 0x0452 }, +{ 0xf3 , 0x0453 }, +{ 0xf4 , 0x0454 }, +{ 0xf5 , 0x0455 }, +{ 0xf6 , 0x0456 }, +{ 0xf7 , 0x0457 }, +{ 0xf8 , 0x0458 }, +{ 0xf9 , 0x0459 }, +{ 0xfa , 0x045A }, +{ 0xfb , 0x045B }, +{ 0xfc , 0x045C }, +{ 0xfd , 0x00A7 }, +{ 0xfe , 0x045E }, +{ 0xff , 0x045F }, diff --git a/extra/locale/charmaps/ISO-8859-6.pairs b/extra/locale/charmaps/ISO-8859-6.pairs new file mode 100644 index 0000000..ccba9f9 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-6.pairs @@ -0,0 +1,211 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa4 , 0x00A4 }, +{ 0xac , 0x060C }, +{ 0xad , 0x00AD }, +{ 0xbb , 0x061B }, +{ 0xbf , 0x061F }, +{ 0xc1 , 0x0621 }, +{ 0xc2 , 0x0622 }, +{ 0xc3 , 0x0623 }, +{ 0xc4 , 0x0624 }, +{ 0xc5 , 0x0625 }, +{ 0xc6 , 0x0626 }, +{ 0xc7 , 0x0627 }, +{ 0xc8 , 0x0628 }, +{ 0xc9 , 0x0629 }, +{ 0xca , 0x062A }, +{ 0xcb , 0x062B }, +{ 0xcc , 0x062C }, +{ 0xcd , 0x062D }, +{ 0xce , 0x062E }, +{ 0xcf , 0x062F }, +{ 0xd0 , 0x0630 }, +{ 0xd1 , 0x0631 }, +{ 0xd2 , 0x0632 }, +{ 0xd3 , 0x0633 }, +{ 0xd4 , 0x0634 }, +{ 0xd5 , 0x0635 }, +{ 0xd6 , 0x0636 }, +{ 0xd7 , 0x0637 }, +{ 0xd8 , 0x0638 }, +{ 0xd9 , 0x0639 }, +{ 0xda , 0x063A }, +{ 0xe0 , 0x0640 }, +{ 0xe1 , 0x0641 }, +{ 0xe2 , 0x0642 }, +{ 0xe3 , 0x0643 }, +{ 0xe4 , 0x0644 }, +{ 0xe5 , 0x0645 }, +{ 0xe6 , 0x0646 }, +{ 0xe7 , 0x0647 }, +{ 0xe8 , 0x0648 }, +{ 0xe9 , 0x0649 }, +{ 0xea , 0x064A }, +{ 0xeb , 0x064B }, +{ 0xec , 0x064C }, +{ 0xed , 0x064D }, +{ 0xee , 0x064E }, +{ 0xef , 0x064F }, +{ 0xf0 , 0x0650 }, +{ 0xf1 , 0x0651 }, +{ 0xf2 , 0x0652 }, diff --git a/extra/locale/charmaps/ISO-8859-7.pairs b/extra/locale/charmaps/ISO-8859-7.pairs new file mode 100644 index 0000000..36b8ba2 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-7.pairs @@ -0,0 +1,250 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x2018 }, +{ 0xa2 , 0x2019 }, +{ 0xa3 , 0x00A3 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xaf , 0x2015 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x0384 }, +{ 0xb5 , 0x0385 }, +{ 0xb6 , 0x0386 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x0388 }, +{ 0xb9 , 0x0389 }, +{ 0xba , 0x038A }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x038C }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x038E }, +{ 0xbf , 0x038F }, +{ 0xc0 , 0x0390 }, +{ 0xc1 , 0x0391 }, +{ 0xc2 , 0x0392 }, +{ 0xc3 , 0x0393 }, +{ 0xc4 , 0x0394 }, +{ 0xc5 , 0x0395 }, +{ 0xc6 , 0x0396 }, +{ 0xc7 , 0x0397 }, +{ 0xc8 , 0x0398 }, +{ 0xc9 , 0x0399 }, +{ 0xca , 0x039A }, +{ 0xcb , 0x039B }, +{ 0xcc , 0x039C }, +{ 0xcd , 0x039D }, +{ 0xce , 0x039E }, +{ 0xcf , 0x039F }, +{ 0xd0 , 0x03A0 }, +{ 0xd1 , 0x03A1 }, +{ 0xd3 , 0x03A3 }, +{ 0xd4 , 0x03A4 }, +{ 0xd5 , 0x03A5 }, +{ 0xd6 , 0x03A6 }, +{ 0xd7 , 0x03A7 }, +{ 0xd8 , 0x03A8 }, +{ 0xd9 , 0x03A9 }, +{ 0xda , 0x03AA }, +{ 0xdb , 0x03AB }, +{ 0xdc , 0x03AC }, +{ 0xdd , 0x03AD }, +{ 0xde , 0x03AE }, +{ 0xdf , 0x03AF }, +{ 0xe0 , 0x03B0 }, +{ 0xe1 , 0x03B1 }, +{ 0xe2 , 0x03B2 }, +{ 0xe3 , 0x03B3 }, +{ 0xe4 , 0x03B4 }, +{ 0xe5 , 0x03B5 }, +{ 0xe6 , 0x03B6 }, +{ 0xe7 , 0x03B7 }, +{ 0xe8 , 0x03B8 }, +{ 0xe9 , 0x03B9 }, +{ 0xea , 0x03BA }, +{ 0xeb , 0x03BB }, +{ 0xec , 0x03BC }, +{ 0xed , 0x03BD }, +{ 0xee , 0x03BE }, +{ 0xef , 0x03BF }, +{ 0xf0 , 0x03C0 }, +{ 0xf1 , 0x03C1 }, +{ 0xf2 , 0x03C2 }, +{ 0xf3 , 0x03C3 }, +{ 0xf4 , 0x03C4 }, +{ 0xf5 , 0x03C5 }, +{ 0xf6 , 0x03C6 }, +{ 0xf7 , 0x03C7 }, +{ 0xf8 , 0x03C8 }, +{ 0xf9 , 0x03C9 }, +{ 0xfa , 0x03CA }, +{ 0xfb , 0x03CB }, +{ 0xfc , 0x03CC }, +{ 0xfd , 0x03CD }, +{ 0xfe , 0x03CE }, diff --git a/extra/locale/charmaps/ISO-8859-8.pairs b/extra/locale/charmaps/ISO-8859-8.pairs new file mode 100644 index 0000000..8d32dd8 --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-8.pairs @@ -0,0 +1,220 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00D7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00F7 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xdf , 0x2017 }, +{ 0xe0 , 0x05D0 }, +{ 0xe1 , 0x05D1 }, +{ 0xe2 , 0x05D2 }, +{ 0xe3 , 0x05D3 }, +{ 0xe4 , 0x05D4 }, +{ 0xe5 , 0x05D5 }, +{ 0xe6 , 0x05D6 }, +{ 0xe7 , 0x05D7 }, +{ 0xe8 , 0x05D8 }, +{ 0xe9 , 0x05D9 }, +{ 0xea , 0x05DA }, +{ 0xeb , 0x05DB }, +{ 0xec , 0x05DC }, +{ 0xed , 0x05DD }, +{ 0xee , 0x05DE }, +{ 0xef , 0x05DF }, +{ 0xf0 , 0x05E0 }, +{ 0xf1 , 0x05E1 }, +{ 0xf2 , 0x05E2 }, +{ 0xf3 , 0x05E3 }, +{ 0xf4 , 0x05E4 }, +{ 0xf5 , 0x05E5 }, +{ 0xf6 , 0x05E6 }, +{ 0xf7 , 0x05E7 }, +{ 0xf8 , 0x05E8 }, +{ 0xf9 , 0x05E9 }, +{ 0xfa , 0x05EA }, +{ 0xfd , 0x200E }, +{ 0xfe , 0x200F }, diff --git a/extra/locale/charmaps/ISO-8859-9.pairs b/extra/locale/charmaps/ISO-8859-9.pairs new file mode 100644 index 0000000..a5748cd --- /dev/null +++ b/extra/locale/charmaps/ISO-8859-9.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x011E }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0130 }, +{ 0xde , 0x015E }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x011F }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0131 }, +{ 0xfe , 0x015F }, +{ 0xff , 0x00FF }, diff --git a/extra/locale/charmaps/KOI8-R.pairs b/extra/locale/charmaps/KOI8-R.pairs new file mode 100644 index 0000000..f34053d --- /dev/null +++ b/extra/locale/charmaps/KOI8-R.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x2500 }, +{ 0x81 , 0x2502 }, +{ 0x82 , 0x250C }, +{ 0x83 , 0x2510 }, +{ 0x84 , 0x2514 }, +{ 0x85 , 0x2518 }, +{ 0x86 , 0x251C }, +{ 0x87 , 0x2524 }, +{ 0x88 , 0x252C }, +{ 0x89 , 0x2534 }, +{ 0x8a , 0x253C }, +{ 0x8b , 0x2580 }, +{ 0x8c , 0x2584 }, +{ 0x8d , 0x2588 }, +{ 0x8e , 0x258C }, +{ 0x8f , 0x2590 }, +{ 0x90 , 0x2591 }, +{ 0x91 , 0x2592 }, +{ 0x92 , 0x2593 }, +{ 0x93 , 0x2320 }, +{ 0x94 , 0x25A0 }, +{ 0x95 , 0x2219 }, +{ 0x96 , 0x221A }, +{ 0x97 , 0x2248 }, +{ 0x98 , 0x2264 }, +{ 0x99 , 0x2265 }, +{ 0x9a , 0x00A0 }, +{ 0x9b , 0x2321 }, +{ 0x9c , 0x00B0 }, +{ 0x9d , 0x00B2 }, +{ 0x9e , 0x00B7 }, +{ 0x9f , 0x00F7 }, +{ 0xa0 , 0x2550 }, +{ 0xa1 , 0x2551 }, +{ 0xa2 , 0x2552 }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x2553 }, +{ 0xa5 , 0x2554 }, +{ 0xa6 , 0x2555 }, +{ 0xa7 , 0x2556 }, +{ 0xa8 , 0x2557 }, +{ 0xa9 , 0x2558 }, +{ 0xaa , 0x2559 }, +{ 0xab , 0x255A }, +{ 0xac , 0x255B }, +{ 0xad , 0x255C }, +{ 0xae , 0x255D }, +{ 0xaf , 0x255E }, +{ 0xb0 , 0x255F }, +{ 0xb1 , 0x2560 }, +{ 0xb2 , 0x2561 }, +{ 0xb3 , 0x0401 }, +{ 0xb4 , 0x2562 }, +{ 0xb5 , 0x2563 }, +{ 0xb6 , 0x2564 }, +{ 0xb7 , 0x2565 }, +{ 0xb8 , 0x2566 }, +{ 0xb9 , 0x2567 }, +{ 0xba , 0x2568 }, +{ 0xbb , 0x2569 }, +{ 0xbc , 0x256A }, +{ 0xbd , 0x256B }, +{ 0xbe , 0x256C }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/extra/locale/charmaps/KOI8-T.pairs b/extra/locale/charmaps/KOI8-T.pairs new file mode 100644 index 0000000..aeba582 --- /dev/null +++ b/extra/locale/charmaps/KOI8-T.pairs @@ -0,0 +1,237 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x049B }, +{ 0x81 , 0x0493 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0492 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x04B3 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x04B2 }, +{ 0x8d , 0x04B7 }, +{ 0x8e , 0x04B6 }, +{ 0x90 , 0x049A }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x99 , 0x2122 }, +{ 0x9b , 0x203A }, +{ 0xa1 , 0x04EF }, +{ 0xa2 , 0x04EE }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x04E3 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x0401 }, +{ 0xb5 , 0x04E2 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb9 , 0x2116 }, +{ 0xbb , 0x00BB }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/extra/locale/charmaps/KOI8-U.pairs b/extra/locale/charmaps/KOI8-U.pairs new file mode 100644 index 0000000..ff05ed2 --- /dev/null +++ b/extra/locale/charmaps/KOI8-U.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x2500 }, +{ 0x81 , 0x2502 }, +{ 0x82 , 0x250C }, +{ 0x83 , 0x2510 }, +{ 0x84 , 0x2514 }, +{ 0x85 , 0x2518 }, +{ 0x86 , 0x251C }, +{ 0x87 , 0x2524 }, +{ 0x88 , 0x252C }, +{ 0x89 , 0x2534 }, +{ 0x8a , 0x253C }, +{ 0x8b , 0x2580 }, +{ 0x8c , 0x2584 }, +{ 0x8d , 0x2588 }, +{ 0x8e , 0x258C }, +{ 0x8f , 0x2590 }, +{ 0x90 , 0x2591 }, +{ 0x91 , 0x2592 }, +{ 0x92 , 0x2593 }, +{ 0x93 , 0x2320 }, +{ 0x94 , 0x25A0 }, +{ 0x95 , 0x2219 }, +{ 0x96 , 0x221A }, +{ 0x97 , 0x2248 }, +{ 0x98 , 0x2264 }, +{ 0x99 , 0x2265 }, +{ 0x9a , 0x00A0 }, +{ 0x9b , 0x2321 }, +{ 0x9c , 0x00B0 }, +{ 0x9d , 0x00B2 }, +{ 0x9e , 0x00B7 }, +{ 0x9f , 0x00F7 }, +{ 0xa0 , 0x2550 }, +{ 0xa1 , 0x2551 }, +{ 0xa2 , 0x2552 }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x0454 }, +{ 0xa5 , 0x2554 }, +{ 0xa6 , 0x0456 }, +{ 0xa7 , 0x0457 }, +{ 0xa8 , 0x2557 }, +{ 0xa9 , 0x2558 }, +{ 0xaa , 0x2559 }, +{ 0xab , 0x255A }, +{ 0xac , 0x255B }, +{ 0xad , 0x0491 }, +{ 0xae , 0x255D }, +{ 0xaf , 0x255E }, +{ 0xb0 , 0x255F }, +{ 0xb1 , 0x2560 }, +{ 0xb2 , 0x2561 }, +{ 0xb3 , 0x0401 }, +{ 0xb4 , 0x0404 }, +{ 0xb5 , 0x2563 }, +{ 0xb6 , 0x0406 }, +{ 0xb7 , 0x0407 }, +{ 0xb8 , 0x2566 }, +{ 0xb9 , 0x2567 }, +{ 0xba , 0x2568 }, +{ 0xbb , 0x2569 }, +{ 0xbc , 0x256A }, +{ 0xbd , 0x0490 }, +{ 0xbe , 0x256C }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/extra/locale/charmaps/TIS-620.pairs b/extra/locale/charmaps/TIS-620.pairs new file mode 100644 index 0000000..618a3be --- /dev/null +++ b/extra/locale/charmaps/TIS-620.pairs @@ -0,0 +1,215 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0xa1 , 0x0E01 }, +{ 0xa2 , 0x0E02 }, +{ 0xa3 , 0x0E03 }, +{ 0xa4 , 0x0E04 }, +{ 0xa5 , 0x0E05 }, +{ 0xa6 , 0x0E06 }, +{ 0xa7 , 0x0E07 }, +{ 0xa8 , 0x0E08 }, +{ 0xa9 , 0x0E09 }, +{ 0xaa , 0x0E0A }, +{ 0xab , 0x0E0B }, +{ 0xac , 0x0E0C }, +{ 0xad , 0x0E0D }, +{ 0xae , 0x0E0E }, +{ 0xaf , 0x0E0F }, +{ 0xb0 , 0x0E10 }, +{ 0xb1 , 0x0E11 }, +{ 0xb2 , 0x0E12 }, +{ 0xb3 , 0x0E13 }, +{ 0xb4 , 0x0E14 }, +{ 0xb5 , 0x0E15 }, +{ 0xb6 , 0x0E16 }, +{ 0xb7 , 0x0E17 }, +{ 0xb8 , 0x0E18 }, +{ 0xb9 , 0x0E19 }, +{ 0xba , 0x0E1A }, +{ 0xbb , 0x0E1B }, +{ 0xbc , 0x0E1C }, +{ 0xbd , 0x0E1D }, +{ 0xbe , 0x0E1E }, +{ 0xbf , 0x0E1F }, +{ 0xc0 , 0x0E20 }, +{ 0xc1 , 0x0E21 }, +{ 0xc2 , 0x0E22 }, +{ 0xc3 , 0x0E23 }, +{ 0xc4 , 0x0E24 }, +{ 0xc5 , 0x0E25 }, +{ 0xc6 , 0x0E26 }, +{ 0xc7 , 0x0E27 }, +{ 0xc8 , 0x0E28 }, +{ 0xc9 , 0x0E29 }, +{ 0xca , 0x0E2A }, +{ 0xcb , 0x0E2B }, +{ 0xcc , 0x0E2C }, +{ 0xcd , 0x0E2D }, +{ 0xce , 0x0E2E }, +{ 0xcf , 0x0E2F }, +{ 0xd0 , 0x0E30 }, +{ 0xd1 , 0x0E31 }, +{ 0xd2 , 0x0E32 }, +{ 0xd3 , 0x0E33 }, +{ 0xd4 , 0x0E34 }, +{ 0xd5 , 0x0E35 }, +{ 0xd6 , 0x0E36 }, +{ 0xd7 , 0x0E37 }, +{ 0xd8 , 0x0E38 }, +{ 0xd9 , 0x0E39 }, +{ 0xda , 0x0E3A }, +{ 0xdf , 0x0E3F }, +{ 0xe0 , 0x0E40 }, +{ 0xe1 , 0x0E41 }, +{ 0xe2 , 0x0E42 }, +{ 0xe3 , 0x0E43 }, +{ 0xe4 , 0x0E44 }, +{ 0xe5 , 0x0E45 }, +{ 0xe6 , 0x0E46 }, +{ 0xe7 , 0x0E47 }, +{ 0xe8 , 0x0E48 }, +{ 0xe9 , 0x0E49 }, +{ 0xea , 0x0E4A }, +{ 0xeb , 0x0E4B }, +{ 0xec , 0x0E4C }, +{ 0xed , 0x0E4D }, +{ 0xee , 0x0E4E }, +{ 0xef , 0x0E4F }, +{ 0xf0 , 0x0E50 }, +{ 0xf1 , 0x0E51 }, +{ 0xf2 , 0x0E52 }, +{ 0xf3 , 0x0E53 }, +{ 0xf4 , 0x0E54 }, +{ 0xf5 , 0x0E55 }, +{ 0xf6 , 0x0E56 }, +{ 0xf7 , 0x0E57 }, +{ 0xf8 , 0x0E58 }, +{ 0xf9 , 0x0E59 }, +{ 0xfa , 0x0E5A }, +{ 0xfb , 0x0E5B }, diff --git a/extra/locale/collation/af_ZA b/extra/locale/collation/af_ZA new file mode 100644 index 0000000..d66184e --- /dev/null +++ b/extra/locale/collation/af_ZA @@ -0,0 +1 @@ +copy "en_DK" diff --git a/extra/locale/collation/am_ET b/extra/locale/collation/am_ET new file mode 100644 index 0000000..94a9181 --- /dev/null +++ b/extra/locale/collation/am_ET @@ -0,0 +1,26 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% Correct Unicode Addressing +script +order_start ;forward +# qW qWi + + +# QW QWi + + +# hW hWi + + +# kW kWi + + +# KW KWi + + +# gW gWi + + +order_end diff --git a/extra/locale/collation/ar_AE b/extra/locale/collation/ar_AE new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_AE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_BH b/extra/locale/collation/ar_BH new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_BH @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_DZ b/extra/locale/collation/ar_DZ new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_DZ @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_EG b/extra/locale/collation/ar_EG new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_EG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_IN b/extra/locale/collation/ar_IN new file mode 100644 index 0000000..d05f74d --- /dev/null +++ b/extra/locale/collation/ar_IN @@ -0,0 +1,3 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_IQ b/extra/locale/collation/ar_IQ new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_IQ @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_JO b/extra/locale/collation/ar_JO new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_JO @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_KW b/extra/locale/collation/ar_KW new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_KW @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_LB b/extra/locale/collation/ar_LB new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_LB @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_LY b/extra/locale/collation/ar_LY new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_LY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_MA b/extra/locale/collation/ar_MA new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_MA @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_OM b/extra/locale/collation/ar_OM new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_OM @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_QA b/extra/locale/collation/ar_QA new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_QA @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_SA b/extra/locale/collation/ar_SA new file mode 100644 index 0000000..a01c4ec --- /dev/null +++ b/extra/locale/collation/ar_SA @@ -0,0 +1,220 @@ + + +order_start forward; forward + + + + + + + + + + + + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + +% UCLIBC -- add an explicit UNDEFINED entry +UNDEFINED +order_end + + diff --git a/extra/locale/collation/ar_SD b/extra/locale/collation/ar_SD new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_SD @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_SY b/extra/locale/collation/ar_SY new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_SY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_TN b/extra/locale/collation/ar_TN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_TN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ar_YE b/extra/locale/collation/ar_YE new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ar_YE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/az_AZ b/extra/locale/collation/az_AZ new file mode 100644 index 0000000..daaeacc --- /dev/null +++ b/extra/locale/collation/az_AZ @@ -0,0 +1,137 @@ +% The new (1991) latin azeri alphabet is: +% , , , , , , , , , , , , +% (dotless i), (i with dot), , , , , , , , +% ,

, , , , , , , , , +% +% cyrillic alphabet: +% , , , , , , , , , , , +% , , , , , , , , , , , +% , , , , , , , , + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + + + + + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/be_BY b/extra/locale/collation/be_BY new file mode 100644 index 0000000..342a761 --- /dev/null +++ b/extra/locale/collation/be_BY @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/extra/locale/collation/bg_BG b/extra/locale/collation/bg_BG new file mode 100644 index 0000000..ddf84dc --- /dev/null +++ b/extra/locale/collation/bg_BG @@ -0,0 +1,106 @@ + +% We have made the following changes to the basic collation scheme in +% the file iso14651_t1: +% 1. The Cyrillic script is first in the order. +% 2. The non-Bulgarian Cyrillic letters are sorted according to +% their transliteration with Bulgarian Cyrillic letters. + +copy "iso14651_t1" +reorder-after <9> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +reorder-after + ;;;IGNORE % Mac. gje +reorder-after + "";"";"";IGNORE % CYR-DJE + "";"";"";IGNORE % CYR-DCHE + "";"";"";IGNORE % CYR-DZE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + "";"";"";IGNORE % CYR-LJE +reorder-after + "";"";"";IGNORE % CYR-NJE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE % Mac. gje +reorder-after + "";"";"";IGNORE % CYR-DJE + "";"";"";IGNORE % CYR-DCHE + "";"";"";IGNORE % CYR-DZE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + "";"";"";IGNORE % CYR-LJE +reorder-after + "";"";"";IGNORE % CYR-NJE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-end diff --git a/extra/locale/collation/bn_BD b/extra/locale/collation/bn_BD new file mode 100644 index 0000000..9a3ff3b --- /dev/null +++ b/extra/locale/collation/bn_BD @@ -0,0 +1,2 @@ +% TODO: Bengali sorting should be added +copy "iso14651_t1" diff --git a/extra/locale/collation/bn_IN b/extra/locale/collation/bn_IN new file mode 100644 index 0000000..0caba14 --- /dev/null +++ b/extra/locale/collation/bn_IN @@ -0,0 +1,4 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% diff --git a/extra/locale/collation/br_FR b/extra/locale/collation/br_FR new file mode 100644 index 0000000..0887c81 --- /dev/null +++ b/extra/locale/collation/br_FR @@ -0,0 +1,40 @@ +copy "iso14651_t1" + +%% a b c ch c'h d e f g h i j k l m n o p q r s t u v w x y z +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + + +reorder-after + + +reorder-after + + + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/bs_BA b/extra/locale/collation/bs_BA new file mode 100644 index 0000000..24be941 --- /dev/null +++ b/extra/locale/collation/bs_BA @@ -0,0 +1,91 @@ +copy "iso14651_t1" + +% a b c c' c< d dz< d// e f g h i j k l lj m n nj o p +% q r s s< t u v w x y z z< + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +%reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/ca_ES b/extra/locale/collation/ca_ES new file mode 100644 index 0000000..2c0a033 --- /dev/null +++ b/extra/locale/collation/ca_ES @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/comm b/extra/locale/collation/comm new file mode 100644 index 0000000..356df60 --- /dev/null +++ b/extra/locale/collation/comm @@ -0,0 +1,1872 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/cs_CZ b/extra/locale/collation/cs_CZ new file mode 100644 index 0000000..734f4a7 --- /dev/null +++ b/extra/locale/collation/cs_CZ @@ -0,0 +1,2162 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before letters, +% numbers after letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + + +% Definice písmene ch + +collating-element from "" +collating-element from "" +collating-element from "" + + +% letter;accent;case;specials + +%order_start forward;forward;forward;forward +order_start forward;forward;forward;forward + +% or letters first: + + + + + + +% Accents: +% Poøadí akcentù: nahoøe, dole, vzadu, vpøedu, uvnitø nebo pøes písmeno +% pokud toto nerozhodne zále¾í na poètu a tvaru + + +% nahoøe + % Teèka + % Vodorovná èárka nahoøe + % Èárka ' (napø: á) + % Zpìtná èárka ` + % Støí¹ka ^ (napø: â) + % Háèek + % Tilda (~) + % Dolní pùlkrou¾ek (vypadá jako sjednocení) +% Horní pùlkrou¾ek (vypadá jako prùnik) + % Krou¾ek + % netu¹ím jaké diakritické znaménko to je, pøedpokládám je nahoøe + % netu¹ím jaké diakritické znaménko to je, pøedpokládám je nahoøe + + % Dvì teèky + + % Dvì èárky + % Dvì zpìtné èárky + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% nahoøe a dole + % Zde si nejsem jist jak je to mínìno, zda obì pod + % nebo pouze to druhé + + + + + + + + +% nahoøe a uprostøed + + +% dole + + + + + % Zobáèek pod písmenem vypadá skoro jako s (º) + % Zobáèek pod písmenem obrácený k pøedchozímu (jako c)(ê) + +% za +% pøed + +% uprostøed + % ©krtnutí písmene v prostøedku (polské ³) + + + + + + + + + + + ;;; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Zde jsou v¹echna latinská písmena s diakritikou +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + + + ;;; + ;;; + "";"";"";"" + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + ;;; + ;;; + + + ;;; + "";"";"";"" + "";"";"";IGNORE + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Èíslice +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% V¹echny speciální znaky (sna¾il jsem se to seøadit podle normy, ale moc se +% mi nedaøilo) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% znaménka + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +% Uvozovky + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% ustálené znaèky + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% grafické znaèky a obrazce lineární + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% grafické znaèky a obrazce plo¹né + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% Akcenty, nevím kam je zaøadit (nìkteré jsou brány jako uvozovky) + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +% IGNORE;IGNORE;IGNORE; % pøemístìn do uvozovek +% IGNORE;IGNORE;IGNORE; % pøemístìn do obrazcù lineárních + IGNORE;IGNORE;IGNORE; +% tilda + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% Neseøazeno + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE;IGNORE + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Zbytek vìcí z unikodu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + +order_end + diff --git a/extra/locale/collation/cy_GB b/extra/locale/collation/cy_GB new file mode 100644 index 0000000..6cda676 --- /dev/null +++ b/extra/locale/collation/cy_GB @@ -0,0 +1,136 @@ +copy "iso14651_t1" + +% Welsh sorting order is: +% a b c ch d dd e f ff g ng h i l ll m n o p ph r rh s t th u w y + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + +reorder-after + + + +reorder-after + +reorder-after

+collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# / +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# GREC +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# CYRIL +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +# Ordre des symboles internes / Order of internal symbols +# +# SYMB. N° +# + + +# forme de base (bas de casse, arabe intrinsèque, +# hébreu intrinsèque, etc. +# basic form (lower case, intrinsic Arabic +# intrinsic Hebrew and so on) +# +# / +# +# + # voir + # isol. +# 3 + # final +# 4 + # initial +# 5 + # medial/mdian +# 6 +# + # 7 + # 8 + # 9 + # 10 + # 11 + +#alternate lower case/ +# 12 +# +#minuscules spéciales après majuscules +# / +# + # accent madda #13 + # accent hamza #14 + # accent hamza/waw #14 1 + # accent hamza under / hamza souscrit #14 2 + # accent under yeh / accent souscrit du ya' #14 3 + # accent hamza/yeh barree #14 4 +# + # 15 +# + # 16 + # 17 + # 18 + # 19 + # 20 + # 21 + # 22 + # 23 + # 24 + # 25 + # 26 + # 27 + # 28 + # 29 + # 30 + # 31 +# +# GREC +# + # accent aigu/tonos/acute accent + # trma/dialytica/diaeresis + # dialytika tonos +# +<0> # 48 +<1> # 49 +<2> # 50 +<3> # 51 +<4> # 52 +<5> # 53 +<6> # 54 +<7> # 55 +<8> # 56 +<9> # 57 +# + # 97 + # 98 + # 99 + # 100 + # 101 + # 102 + # 103 + # 104 + # 105 + # 106 + # 107 + # 108 + # 109 + # 110 + # 111 +

# 112 + # 113 + # 114 + # 115 + # 116 + # 117 + # 118 + # 119 + # 120 + # 121 + # 122 +# 122b +# +# / +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# +# +# + + + + + + + + + + + + + + + + + + + + + + + + + + + +# +#GREC +# + + + + + + + + + + + + + + + + + + + + + + + + +# +#CYRIL +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +order_start ;forward;backward;forward;forward,position +# +# Tout caractère non précisément défini sera considéré comme caractère spécial +# et considéré uniquement au dernier niveau. +# +# Any character not precisely specified will be considered as a special +# character and considered only at the last level. +# ...... IGNORE;IGNORE;IGNORE;...... +# +# SYMB. N° GLY +# + IGNORE;IGNORE;IGNORE; # 32 + IGNORE;IGNORE;IGNORE; # 33 _ + IGNORE;IGNORE;IGNORE; # 34 <"_> + IGNORE;IGNORE;IGNORE; # 35 - (MACRON) + IGNORE;IGNORE;IGNORE; # 36 + IGNORE;IGNORE;IGNORE; # 37 - + IGNORE;IGNORE;IGNORE; # 38 , + IGNORE;IGNORE;IGNORE; # 39 ; + IGNORE;IGNORE;IGNORE; # 40 : + IGNORE;IGNORE;IGNORE; # 41 ! + IGNORE;IGNORE;IGNORE; # 42 ¡ + IGNORE;IGNORE;IGNORE; # 43 ? + IGNORE;IGNORE;IGNORE; # 44 ¿ + IGNORE;IGNORE;IGNORE; # 45 / + IGNORE;IGNORE;IGNORE; # 46 <"/> + IGNORE;IGNORE;IGNORE; # 47 . + IGNORE;IGNORE;IGNORE; # 58 × + IGNORE;IGNORE;IGNORE; # 59 ¸ + IGNORE;IGNORE;IGNORE; # 60 <";> + IGNORE;IGNORE;IGNORE; # 61 ' + IGNORE;IGNORE;IGNORE; # 62 <'6> + IGNORE;IGNORE;IGNORE; # 63 <'9> + IGNORE;IGNORE;IGNORE; # 64 " + IGNORE;IGNORE;IGNORE; # 65 <"6> + IGNORE;IGNORE;IGNORE; # 66 <"9> + IGNORE;IGNORE;IGNORE; # 67 « + IGNORE;IGNORE;IGNORE; # 68 » + IGNORE;IGNORE;IGNORE; # 69 ( + IGNORE;IGNORE;IGNORE; # 70 <(S> + IGNORE;IGNORE;IGNORE; # 71 ) + IGNORE;IGNORE;IGNORE; # 72 <)S> + IGNORE;IGNORE;IGNORE; # 73 [ + IGNORE;IGNORE;IGNORE; # 74 ] + IGNORE;IGNORE;IGNORE; # 75 { + IGNORE;IGNORE;IGNORE; # 76 } + IGNORE;IGNORE;IGNORE; # 77 § + IGNORE;IGNORE;IGNORE; # 78 ¶ + IGNORE;IGNORE;IGNORE; # 79 © + IGNORE;IGNORE;IGNORE; # 80 ® + IGNORE;IGNORE;IGNORE; # 81 + IGNORE;IGNORE;IGNORE; # 82 @ + IGNORE;IGNORE;IGNORE; # 83 ¤ + IGNORE;IGNORE;IGNORE; # 84 ¢ + IGNORE;IGNORE;IGNORE; # 85 $ + IGNORE;IGNORE;IGNORE; # 86 £ + IGNORE;IGNORE;IGNORE; # 87 ¥ + IGNORE;IGNORE;IGNORE; # ecu + IGNORE;IGNORE;IGNORE; # colon + IGNORE;IGNORE;IGNORE; # cruzeiro + IGNORE;IGNORE;IGNORE; # french franc + IGNORE;IGNORE;IGNORE; # lira + IGNORE;IGNORE;IGNORE; # mill + IGNORE;IGNORE;IGNORE; # naira + IGNORE;IGNORE;IGNORE; # peseta + IGNORE;IGNORE;IGNORE; # rupee + IGNORE;IGNORE;IGNORE; # won + IGNORE;IGNORE;IGNORE; # new sheqel + IGNORE;IGNORE;IGNORE; # dong + IGNORE;IGNORE;IGNORE; # euro + IGNORE;IGNORE;IGNORE; # kip + IGNORE;IGNORE;IGNORE; # tugrik + IGNORE;IGNORE;IGNORE; # drachma + IGNORE;IGNORE;IGNORE; # 88 * + IGNORE;IGNORE;IGNORE; # 89 + IGNORE;IGNORE;IGNORE; # 90 & + IGNORE;IGNORE;IGNORE; # 91 # + IGNORE;IGNORE;IGNORE; # 92 % + IGNORE;IGNORE;IGNORE; # 93 <-S> + IGNORE;IGNORE;IGNORE; # 94 + + IGNORE;IGNORE;IGNORE; # 95 <+S> + IGNORE;IGNORE;IGNORE; # 96 ± + IGNORE;IGNORE;IGNORE;<0> # 123 ´ + IGNORE;IGNORE;IGNORE;<1> # 124 ` + IGNORE;IGNORE;IGNORE;<2> # 125 <"(> + IGNORE;IGNORE;IGNORE;<3> # 126 ^ + IGNORE;IGNORE;IGNORE;<4> # 127 <"<> + IGNORE;IGNORE;IGNORE;<5> # 128 <"0> + IGNORE;IGNORE;IGNORE;<6> # 129 ¨ + IGNORE;IGNORE;IGNORE;<7> # 130 <""> + IGNORE;IGNORE;IGNORE;<8> # 131 ~ + IGNORE;IGNORE;IGNORE;<9> # 132 <".> + IGNORE;IGNORE;IGNORE; # 133 ¸ + IGNORE;IGNORE;IGNORE; # 134 ´ + IGNORE;IGNORE;IGNORE; # 135 + IGNORE;IGNORE;IGNORE; # 136 < + IGNORE;IGNORE;IGNORE; # 137 <=<> + IGNORE;IGNORE;IGNORE; # 138 = + IGNORE;IGNORE;IGNORE; # 139 => + IGNORE;IGNORE;IGNORE; # 140 > + IGNORE;IGNORE;IGNORE; # 141 ¬ + IGNORE;IGNORE;IGNORE; # 142 | + IGNORE;IGNORE;IGNORE; # 143 | + IGNORE;IGNORE;IGNORE; # 144 ° + IGNORE;IGNORE;IGNORE; # 145 m + IGNORE;IGNORE;IGNORE; # 146 + IGNORE;IGNORE;IGNORE; # 147 + IGNORE;IGNORE;IGNORE;

# 148 <_V/>> + IGNORE;IGNORE;IGNORE; # 149 <_V-> + IGNORE;IGNORE;IGNORE; # 150 <_V + IGNORE;IGNORE;IGNORE; # 151 <_!/>> + IGNORE;IGNORE;IGNORE; # 152 <_!-> + IGNORE;IGNORE;IGNORE; # 153 <_!<> + IGNORE;IGNORE;IGNORE; # 154 <_A/>> + IGNORE;IGNORE;IGNORE; # 155 <_-A> + IGNORE;IGNORE;IGNORE; # 156 <_A<> + IGNORE;IGNORE;IGNORE; # 157 <_!> + IGNORE;IGNORE;IGNORE; # 158 <_-> # + IGNORE;IGNORE;IGNORE; # 159 <_=> + IGNORE;IGNORE;IGNORE; # 160 <<-> + IGNORE;IGNORE;IGNORE; # 161 <-/>> + IGNORE;IGNORE;IGNORE; # 162 <"7> + IGNORE;IGNORE;IGNORE; # 163 <-!> + IGNORE;IGNORE;IGNORE; # 164 <-v> + IGNORE;IGNORE;IGNORE; # 165 <_d!> + IGNORE;IGNORE;IGNORE; # 166 <_/>//> + IGNORE;IGNORE;IGNORE; # 167 <_<\> + IGNORE;IGNORE;IGNORE; # 168 <_./>//> + IGNORE;IGNORE;IGNORE; # 169 <_.<\> # # / # + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # # # # + IGNORE;IGNORE;IGNORE; #point_sheva + IGNORE;IGNORE;IGNORE; #point_hataf_segol + IGNORE;IGNORE;IGNORE; #point_hataf_patah + IGNORE;IGNORE;IGNORE; #point_hataf_qamats + IGNORE;IGNORE;IGNORE; #point_hiriq + IGNORE;IGNORE;IGNORE; #point_tsere + IGNORE;IGNORE;IGNORE; #point_segol + IGNORE;IGNORE;IGNORE; #point_patah + IGNORE;IGNORE;IGNORE; #point_qamats + IGNORE;IGNORE;IGNORE; #point_holam + IGNORE;IGNORE;IGNORE; #point_qubuts + IGNORE;IGNORE;IGNORE; #point_dagesh + IGNORE;IGNORE;IGNORE; #point_meteg + IGNORE;IGNORE;IGNORE; #maqaf + IGNORE;IGNORE;IGNORE; #point_rafe + IGNORE;IGNORE;IGNORE; #paseq + IGNORE;IGNORE;IGNORE; #point_shin_dot + IGNORE;IGNORE;IGNORE; #point_sin_dot + IGNORE;IGNORE;IGNORE; #sof pasuq + +# The comment at the beginning of this section mentions characters which +# are not otherwise covered. But this description cannot express this. +# Therefore we add here a few entries which are used in older implementations +# to be compatible. --drepper + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +order_start ;forward;backward;forward;forward,position +# + ;;;IGNORE # 170 +# + <0>;;;IGNORE # 171 0 + <1>;;;IGNORE # 172 1 + <2>;;;IGNORE # 173 2 + <3>;;;IGNORE # 174 3 + <4>;;;IGNORE # 175 4 + <5>;;;IGNORE # 176 5 + <6>;;;IGNORE # 177 6 + <7>;;;IGNORE # 178 7 + <8>;;;IGNORE # 179 8 + <9>;;;IGNORE # 180 9 +# + <0>;;;IGNORE # 181 <18> + <0>;;;IGNORE # 182 ¼ + <0>;;;IGNORE # 183 <38> + <0>;;;IGNORE # 184 <58> + <0>;;;IGNORE # 185 <78> + <0>;;;IGNORE # 186 ½ + <0>;;;IGNORE # 187 ¾ + <0>;;;IGNORE # 188 <0S> + <1>;;;IGNORE # 189 ¹ + <2>;;;IGNORE # 190 ² + <3>;;;IGNORE # 191 ³ + <4>;;;IGNORE # 192 <4S> + <5>;;;IGNORE # 193 <5S> + <6>;;;IGNORE # 194 <6S> + <7>;;;IGNORE # 195 <7S> + <8>;;;IGNORE # 196 <8S> + <9>;;;IGNORE # 197 <9S> +# + ;;;IGNORE # 198 a + ;;;IGNORE # 199 ª + ;;;IGNORE # 200 á + ;;;IGNORE # 201 à + ;;;IGNORE # 202 â + ;;;IGNORE # 203 ã + ;;;IGNORE # 204 ä + ;;;IGNORE # 205 å + ;;;IGNORE # 206 + ;;;IGNORE # 207 + ;;;IGNORE # 208 + "";"";"";IGNORE # 209 æ + ;;;IGNORE # 210 b + ;;;IGNORE # 211 c + ;;;IGNORE # 212 ç + ;;;IGNORE # 213 + ;;;IGNORE # 214 > + ;;;IGNORE # 215 + ;;;IGNORE # 216 + ;;;IGNORE # 217 d + ;;;IGNORE # 218 ð + ;;;IGNORE # 219 + ;;;IGNORE # 220 + ;;;IGNORE # 221 e + ;;;IGNORE # 222 é + ;;;IGNORE # 223 è + ;;;IGNORE # 224 ê + ;;;IGNORE # 225 ë + ;;;IGNORE # 226 + ;;;IGNORE # 227 + ;;;IGNORE # 228 + ;;;IGNORE # 229 + ;;;IGNORE # 230 f + ;;;IGNORE # 231 g + ;;;IGNORE # 232 + ;;;IGNORE # 233 > + ;;;IGNORE # 234 + ;;;IGNORE # 235 + ;;;IGNORE # 236 h + ;;;IGNORE # 237 > + ;;;IGNORE # 238 + ;;;IGNORE # 239 i + ;;;IGNORE # 240 í + ;;;IGNORE # 241 ì + ;;;IGNORE # 242 î + ;;;IGNORE # 243 ï + ;;;IGNORE # 244 + ;;;IGNORE # 245 + ;;;IGNORE # 246 + ;;;IGNORE # 247 + "";"";"";IGNORE # 248 + ;;;IGNORE # 249 j + ;;;IGNORE # 250 > + ;;;IGNORE # 251 k + ;;;IGNORE # 252 + ;;;IGNORE # 253 + ;;;IGNORE # 254 l + ;;;IGNORE # 255 + ;;;IGNORE # 256 + ;;;IGNORE # 257 + ;;;IGNORE # 258 + ;;;IGNORE # 259 + ;;;IGNORE # 260 m + ;;;IGNORE # 261 n + ;;;IGNORE # 262 ñ + ;;;IGNORE # 263 <'n> + ;;;IGNORE # 264 + ;;;IGNORE # 265 + ;;;IGNORE # 266 + "";"";"";IGNORE # 267 + ;;;IGNORE # 268 o + ;;;IGNORE # 269 º + ;;;IGNORE # 270 ó + ;;;IGNORE # 271 ò + ;;;IGNORE # 272 ô + ;;;IGNORE # 273 õ + ;;;IGNORE # 274 ö + ;;;IGNORE # 275 ø + ;;;IGNORE # 276 + ;;;IGNORE # 277 + "";"";"";IGNORE # 278 +

;;;IGNORE # 279 p + ;;;IGNORE # 280 q + ;;;IGNORE # 281 r + ;;;IGNORE # 282 + ;;;IGNORE # 283 + ;;;IGNORE # 284 + ;;;IGNORE # 285 s + ;;;IGNORE # 286 + ;;;IGNORE # 287 > + ;;;IGNORE # 288 + ;;;IGNORE # 289 + "";"";"";IGNORE # 290 ß + ;;;IGNORE # 291 t + ;;;IGNORE # 292 + ;;;IGNORE # 293 + ;;;IGNORE # 294 + ;;;IGNORE # 296 u + ;;;IGNORE # 297 ú + ;;;IGNORE # 298 ù + ;;;IGNORE # 299 û + ;;;IGNORE # 300 ü + ;;;IGNORE # 301 + ;;;IGNORE # 302 + ;;;IGNORE # 303 + ;;;IGNORE # 304 + ;;;IGNORE # 305 + ;;;IGNORE # 306 + ;;;IGNORE # 307 v + ;;;IGNORE # 308 w + ;;;IGNORE # 309 > + ;;;IGNORE # 310 x + ;;;IGNORE # 311 y + ;;;IGNORE # 312 ý + ;;;IGNORE # 313 _ + ;;;IGNORE # 314 > + ;;;IGNORE # 315 z + ;;;IGNORE # 316 + ;;;IGNORE # 317 + ;;;IGNORE # 318 + ;;;IGNORE # 318b Þ # + ;;;IGNORE # 319 A + ;;;IGNORE # 320 Á + ;;;IGNORE # 321 À + ;;;IGNORE # 322 Â + ;;;IGNORE # 323 Ã + ;;;IGNORE # 324 Ä + ;;;IGNORE # 325 Å + ;;;IGNORE # 326 + ;;;IGNORE # 327 + ;;;IGNORE # 328 + "";"";"";IGNORE # 329 Æ + ;;;IGNORE # 330 B + ;;;IGNORE # 331 C + ;;;IGNORE # 332 Ç + ;;;IGNORE # 333 + ;;;IGNORE # 334 > + ;;;IGNORE # 335 > + ;;;IGNORE # 336 + ;;;IGNORE # 337 D + ;;;IGNORE # 338 Ð + ;;;IGNORE # 339 + ;;;IGNORE # 340 + ;;;IGNORE # 341 E + ;;;IGNORE # 342 É + ;;;IGNORE # 343 È + ;;;IGNORE # 344 Ê + ;;;IGNORE # 345 Ë + ;;;IGNORE # 346 + ;;;IGNORE # 347 + ;;;IGNORE # 348 + ;;;IGNORE # 349 + ;;;IGNORE # 350 F + ;;;IGNORE # 351 G + ;;;IGNORE # 352 + ;;;IGNORE # 353 > + ;;;IGNORE # 354 + ;;;IGNORE # 355 + ;;;IGNORE # 356 H + ;;;IGNORE # 357 > + ;;;IGNORE # 358 + ;;;IGNORE # 359 I + ;;;IGNORE # 360 Í + ;;;IGNORE # 361 Ì + ;;;IGNORE # 362 Î + ;;;IGNORE # 363 Ï + ;;;IGNORE # 364 + ;;;IGNORE # 365 + ;;;IGNORE # 366 + ;;;IGNORE # 367 + "";"";"";IGNORE # 368 + ;;;IGNORE # 369 J + ;;;IGNORE # 370 > + ;;;IGNORE # 371 K + ;;;IGNORE # 372 + ;;;IGNORE # 373 L + ;;;IGNORE # 374 + ;;;IGNORE # 375 + ;;;IGNORE # 376 + ;;;IGNORE # 377 + ;;;IGNORE # 378 + ;;;IGNORE # 379 M + ;;;IGNORE # 380 N + ;;;IGNORE # 381 Ñ + ;;;IGNORE # 382 + ;;;IGNORE # 383 + ;;;IGNORE # 384 + "";"";"";IGNORE # 385 + ;;;IGNORE # 386 O + ;;;IGNORE # 387 Ó + ;;;IGNORE # 388 Ò + ;;;IGNORE # 389 Ô + ;;;IGNORE # 390 Õ + ;;;IGNORE # 391 Ö + ;;;IGNORE # 392 Ø + ;;;IGNORE # 393 + ;;;IGNORE # 394 + "";"";"";IGNORE # 395 +

;;;IGNORE # 396 P + ;;;IGNORE # 397 Q + ;;;IGNORE # 398 R + ;;;IGNORE # 399 + ;;;IGNORE # 400 + ;;;IGNORE # 401 + ;;;IGNORE # 402 S + ;;;IGNORE # 403 + ;;;IGNORE # 404 > + ;;;IGNORE # 405 + ;;;IGNORE # 406 + ;;;IGNORE # 407 T + ;;;IGNORE # 408 + ;;;IGNORE # 409 + ;;;IGNORE # 410 + ;;;IGNORE # 412 U + ;;;IGNORE # 413 Ú + ;;;IGNORE # 414 Ù + ;;;IGNORE # 415 Û + ;;;IGNORE # 416 Ü + ;;;IGNORE # 417 + ;;;IGNORE # 418 + ;;;IGNORE # 419 + ;;;IGNORE # 420 + ;;;IGNORE # 421 + ;;;IGNORE # 422 + ;;;IGNORE # 423 V + ;;;IGNORE # 424 W + ;;;IGNORE # 425 > + ;;;IGNORE # 426 X + ;;;IGNORE # 427 Y + ;;;IGNORE # 428 Ý + ;;;IGNORE # 429 > + ;;;IGNORE # 430 + ;;;IGNORE # 431 Z + ;;;IGNORE # 432 + ;;;IGNORE # 433 + ;;;IGNORE # 434 + ;;;IGNORE # 411 þ + +order_start ;forward;forward;forward;forward,position + <0>;;;IGNORE + <0>;;;IGNORE + <1>;;;IGNORE + <1>;;;IGNORE + <2>;;;IGNORE + <2>;;;IGNORE + <3>;;;IGNORE + <3>;;;IGNORE + <4>;;;IGNORE + <4>;;;IGNORE + <5>;;;IGNORE + <5>;;;IGNORE + <6>;;;IGNORE + <6>;;;IGNORE + <7>;;;IGNORE + <7>;;;IGNORE + <8>;;;IGNORE + <8>;;;IGNORE + <9>;;;IGNORE + <9>;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +order_start ;backward;backward;backward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +order_start ;forward;forward;forward;forward,position + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_start ;forward;backward;forward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # digamma copte + ;;;IGNORE + ;;;IGNORE # GANGIA COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # HORI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # koppa copte + ;;;IGNORE # KHEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # STIGMA ARCH. + ;;;IGNORE # SHIMA COPTE + ;;;IGNORE + ;;;IGNORE # DEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # FEI COPTE + ;;;IGNORE + ;;;IGNORE # sampi copte + ;;;IGNORE + ;;;IGNORE # SHEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # gangia copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # hori copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # yot + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # khei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # shima copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # dei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # fei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # shei copte + ;;;IGNORE + ;;;IGNORE + +order_start ;forward;forward;forward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +order_start ;forward;forward;forward;forward,position +UCLIBC_RANGE ..;IGNORE;IGNORE;IGNORE +# ;IGNORE;IGNORE;IGNORE +#.. ..;IGNORE;IGNORE;IGNORE +# ;IGNORE;IGNORE;IGNORE +# +order_end +# diff --git a/extra/locale/collation/it_CH b/extra/locale/collation/it_CH new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/it_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/it_IT b/extra/locale/collation/it_IT new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/it_IT @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/iw_IL b/extra/locale/collation/iw_IL new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/iw_IL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/ja_JP b/extra/locale/collation/ja_JP new file mode 100644 index 0000000..fa26bac --- /dev/null +++ b/extra/locale/collation/ja_JP @@ -0,0 +1,13188 @@ +order_start forward +% +% C0 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% ISO 646 IRV +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% C1 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0201 KATAKANA +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0208 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0212 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +UNDEFINED +order_end diff --git a/extra/locale/collation/ka_GE b/extra/locale/collation/ka_GE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/ka_GE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/kl_GL b/extra/locale/collation/kl_GL new file mode 100644 index 0000000..b7628e7 --- /dev/null +++ b/extra/locale/collation/kl_GL @@ -0,0 +1 @@ +copy "da_DK" diff --git a/extra/locale/collation/ko_KR b/extra/locale/collation/ko_KR new file mode 100644 index 0000000..d9898f1 --- /dev/null +++ b/extra/locale/collation/ko_KR @@ -0,0 +1,6010 @@ +order_start forward + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%%% +% HANGUL SYLLABLES +UCLIBC_RANGE +# +#.. +# +%%% +% HANJA. For the moment, Hanjas defined in KS X 1001 +% are enumerated in the order they're listed in KS X 1001. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +UNDEFINED +order_end diff --git a/extra/locale/collation/kw_GB b/extra/locale/collation/kw_GB new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/kw_GB @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/lt_LT b/extra/locale/collation/lt_LT new file mode 100644 index 0000000..707d08e --- /dev/null +++ b/extra/locale/collation/lt_LT @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/lv_LV b/extra/locale/collation/lv_LV new file mode 100644 index 0000000..8492731 --- /dev/null +++ b/extra/locale/collation/lv_LV @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/mi_NZ b/extra/locale/collation/mi_NZ new file mode 100644 index 0000000..c36305d --- /dev/null +++ b/extra/locale/collation/mi_NZ @@ -0,0 +1,44 @@ +copy "iso14651_t1" + +%% a b c d e f g h i j k l m n ng o p q r s t u v w wh x y z + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/mk_MK b/extra/locale/collation/mk_MK new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/mk_MK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/mr_IN b/extra/locale/collation/mr_IN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/mr_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/ms_MY b/extra/locale/collation/ms_MY new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ms_MY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/mt_MT b/extra/locale/collation/mt_MT new file mode 100644 index 0000000..bd028da --- /dev/null +++ b/extra/locale/collation/mt_MT @@ -0,0 +1,80 @@ + +% a b c c. d e f g. g gh/ h h/ i ie j k l m n o p q r s t u v w x y z. z + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/nl_BE b/extra/locale/collation/nl_BE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/nl_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/nl_NL b/extra/locale/collation/nl_NL new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/nl_NL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/nn_NO b/extra/locale/collation/nn_NO new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/nn_NO @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/no_NO b/extra/locale/collation/no_NO new file mode 100644 index 0000000..f32dc18 --- /dev/null +++ b/extra/locale/collation/no_NO @@ -0,0 +1,2070 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + +% before letters + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/oc_FR b/extra/locale/collation/oc_FR new file mode 100644 index 0000000..d66184e --- /dev/null +++ b/extra/locale/collation/oc_FR @@ -0,0 +1 @@ +copy "en_DK" diff --git a/extra/locale/collation/pl_PL b/extra/locale/collation/pl_PL new file mode 100644 index 0000000..b4c9a3b --- /dev/null +++ b/extra/locale/collation/pl_PL @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/pt_BR b/extra/locale/collation/pt_BR new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/pt_BR @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/pt_PT b/extra/locale/collation/pt_PT new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/pt_PT @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/ro_RO b/extra/locale/collation/ro_RO new file mode 100644 index 0000000..862db75 --- /dev/null +++ b/extra/locale/collation/ro_RO @@ -0,0 +1,54 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% a a> a( b c d e f g h i i> j k l m n o p q r s s, t t, u v w x y z + +collating-symbol > +collating-symbol +collating-symbol > +collating-symbol +collating-symbol + +reorder-after + + + +reorder-after +> + +reorder-after +> +reorder-after + +reorder-after + + +reorder-after + >;;;IGNORE + ;;;IGNORE +reorder-after + >;;;IGNORE + ;;;IGNORE + +reorder-after + >;;;IGNORE +reorder-after + >;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/ru_RU b/extra/locale/collation/ru_RU new file mode 100644 index 0000000..342a761 --- /dev/null +++ b/extra/locale/collation/ru_RU @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/extra/locale/collation/ru_UA b/extra/locale/collation/ru_UA new file mode 100644 index 0000000..342a761 --- /dev/null +++ b/extra/locale/collation/ru_UA @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/extra/locale/collation/se_NO b/extra/locale/collation/se_NO new file mode 100644 index 0000000..9718edc --- /dev/null +++ b/extra/locale/collation/se_NO @@ -0,0 +1,149 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% +reorder-after + + +reorder-after + + + + + + +reorder-after + + + + + +reorder-after + + + +reorder-after + + +reorder-after + + + +reorder-after + + +reorder-after + + + +reorder-after + + + + + + +reorder-after + ;;;IGNORE % 201 à + ;;;IGNORE % 200 á + ;;;IGNORE % 202 â + ;;;IGNORE % 203 ã + +reorder-after + ;;;IGNORE % 321 À + ;;;IGNORE % 320 Á + ;;;IGNORE % 322 Â + ;;;IGNORE % 323 Ã + +reorder-after + ;;;IGNORE % 212 ç + ;;;IGNORE % 215 + +reorder-after + ;;;IGNORE % 332 Ç + ;;;IGNORE % 335 + +reorder-after + ;;;IGNORE % ezh + ;;;IGNORE % ezh caron + +reorder-after + ;;;IGNORE % EZH + ;;;IGNORE % EZH caron + +reorder-after + ;;;IGNORE % 218 ð + ;;;IGNORE % 220 + +reorder-after + ;;;IGNORE % 338 Ð + ;;;IGNORE % 340 + +reorder-after + ;;;IGNORE % f WITH HOOK + +reorder-after + ;;;IGNORE % gcaron + ;;;IGNORE % gstroke + +reorder-after + ;;;IGNORE % Gcaron + ;;;IGNORE % Gstroke + +reorder-after + ;;;IGNORE % kcaron +reorder-after + ;;;IGNORE % Kcaron + +reorder-after + ;"";"";IGNORE % ß + ;;;IGNORE % 288 + ;;;IGNORE % 405 + + +reorder-after + ;;;IGNORE % ä + ;;;IGNORE % å + ;;;IGNORE % æ +reorder-after + ;;;IGNORE % ö + ;;;IGNORE % ø + +reorder-after + ;;;IGNORE % Ä + ;;;IGNORE % Å + ;;;IGNORE % Æ +reorder-after + ;;;IGNORE % Ö + ;;;IGNORE % Ø + +% ü/Ü is treated like y/Y but is sorted after the latter +reorder-after + ;;;IGNORE % ü +reorder-after + ;;;IGNORE % Ü +reorder-end + diff --git a/extra/locale/collation/sk_SK b/extra/locale/collation/sk_SK new file mode 100644 index 0000000..245653c --- /dev/null +++ b/extra/locale/collation/sk_SK @@ -0,0 +1 @@ +copy "cs_CZ" diff --git a/extra/locale/collation/sl_SI b/extra/locale/collation/sl_SI new file mode 100644 index 0000000..7f7ad23 --- /dev/null +++ b/extra/locale/collation/sl_SI @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/sq_AL b/extra/locale/collation/sq_AL new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/sq_AL @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/sr_YU b/extra/locale/collation/sr_YU new file mode 100644 index 0000000..1dcd15c --- /dev/null +++ b/extra/locale/collation/sr_YU @@ -0,0 +1,90 @@ +copy "iso14651_t1" + +% a b c c' c< d dz< d// e f g h i j k l lj m n nj o p +% q r s s< t u v w x y z z< + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end diff --git a/extra/locale/collation/sv_FI b/extra/locale/collation/sv_FI new file mode 100644 index 0000000..ab50386 --- /dev/null +++ b/extra/locale/collation/sv_FI @@ -0,0 +1 @@ +copy "fi_FI" diff --git a/extra/locale/collation/sv_SE b/extra/locale/collation/sv_SE new file mode 100644 index 0000000..2d299a4 --- /dev/null +++ b/extra/locale/collation/sv_SE @@ -0,0 +1,51 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% æ is sorted after ä and å etc. +reorder-after + + +reorder-after + + + + + +% The letter w is normally not present in the Swedish alphabet. It +% exists in some names in Swedish and foreign words, but is accounted +% for as a variant of 'v'. Words and names with 'w' are in Swedish +% ordered alphabetically among the words and names with 'v'. If two +% words or names are only to be distinguished by 'v' or % 'w', 'v' is +% placed before 'w'. +reorder-after + ;;; % W +reorder-after + ;;; % w + +reorder-after + ;;;IGNORE % ä + ;;;IGNORE % å + ;;;IGNORE % æ +reorder-after + ;;;IGNORE % ö + ;;;IGNORE % ø + +reorder-after + ;;;IGNORE % Ä + ;;;IGNORE % Å + ;;;IGNORE % Æ +reorder-after + ;;;IGNORE % Ö + ;;;IGNORE % Ø + +% ü/Ü is treated like y/Y but is sorted after the latter +reorder-after + ;;;IGNORE % ü +reorder-after + ;;;IGNORE % Ü +reorder-end + diff --git a/extra/locale/collation/ta_IN b/extra/locale/collation/ta_IN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/ta_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/te_IN b/extra/locale/collation/te_IN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/te_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/tg_TJ b/extra/locale/collation/tg_TJ new file mode 100644 index 0000000..e2f01ae --- /dev/null +++ b/extra/locale/collation/tg_TJ @@ -0,0 +1,63 @@ + +% Tadjik cyrillic alphabet is: +% , , , , (cyr ghe with stroke), , , +% , , , , (cyr i with macron), , , +% (cyr k with descender), , , , , , , +% , , , (cyr u with macron), , , +% (cyr ha with descender), , (cyr che with descender), +% , (cyr hard sign), , , + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/th_TH b/extra/locale/collation/th_TH new file mode 100644 index 0000000..6e3230f --- /dev/null +++ b/extra/locale/collation/th_TH @@ -0,0 +1,746 @@ + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +order_start forward;forward;forward;forward + +% definitions of extra collating symbols + + + + + + +UNDEFINED IGNORE;IGNORE;IGNORE;IGNORE + +% punctuation marks, ordered after ISO/IEC 14651 + IGNORE;IGNORE;;IGNORE % SPACE + IGNORE;IGNORE;;IGNORE % LOW LINE + IGNORE;IGNORE;;IGNORE % HYPHEN-MINUS + IGNORE;IGNORE;;IGNORE % COMMA + IGNORE;IGNORE;;IGNORE % SEMICOLON + IGNORE;IGNORE;;IGNORE % COLON + IGNORE;IGNORE;;IGNORE % EXCLAMATION MARK + IGNORE;IGNORE;;IGNORE % QUESTION MARK + IGNORE;IGNORE;;IGNORE % SOLIDUS + IGNORE;IGNORE;;IGNORE % FULL STOP + IGNORE;IGNORE;;IGNORE % THAI CHARACTER PAIYANNOI + IGNORE;IGNORE;;IGNORE % THAI CHARACTER MAIYAMOK + IGNORE;IGNORE;;IGNORE % GRAVE ACCENT + IGNORE;IGNORE;;IGNORE % CIRCUMFLEX + IGNORE;IGNORE;;IGNORE % TILDE + IGNORE;IGNORE;;IGNORE % APOSTROPHE + IGNORE;IGNORE;;IGNORE % QUOTATION MARK + IGNORE;IGNORE;;IGNORE % LEFT PAREN. + IGNORE;IGNORE;;IGNORE % LT BRACKET + IGNORE;IGNORE;;IGNORE % LEFT CURLY BRACKET + IGNORE;IGNORE;;IGNORE % RIGHT CURLY BRACKET + IGNORE;IGNORE;;IGNORE % RT BRACKET + IGNORE;IGNORE;;IGNORE % RIGHT PAREN. + IGNORE;IGNORE;;IGNORE % COMMERCIAL AT + IGNORE;IGNORE;;IGNORE % THAI CHARACTER SYMBOL BAHT + IGNORE;IGNORE;;IGNORE % DOLLAR SIGN + IGNORE;IGNORE;;IGNORE % THAI CHARACTER FONGMAN + IGNORE;IGNORE;;IGNORE % THAI CHARACTER ANGKHANKHU + IGNORE;IGNORE;;IGNORE % THAI CHARACTER KHOMUT + IGNORE;IGNORE;;IGNORE % ASTERISK + IGNORE;IGNORE;;IGNORE % BACK SOLIDUS + IGNORE;IGNORE;;IGNORE % AMPERSAND + IGNORE;IGNORE;;IGNORE % NUMBER SIGN + IGNORE;IGNORE;;IGNORE % PERCENT + IGNORE;IGNORE;;IGNORE % PLUS + IGNORE;IGNORE;;IGNORE % LESS THAN + IGNORE;IGNORE;;IGNORE % EQUAL + IGNORE;IGNORE;;IGNORE % GREATER THAN + IGNORE;IGNORE;;IGNORE % VERTICAL LINE + +% Thai tone marks and diacritics + IGNORE;;; % THAI CHARACTER YAMAKKAN + IGNORE;;; % THAI CHARACTER PINTHU + IGNORE;;; % THAI CHARACTER THANTHAKHAT + IGNORE;;; % THAI CHARACTER MAITAIKHU + IGNORE;;; % THAI CHARACTER MAI EK + IGNORE;;; % THAI CHARACTER MAI THO + IGNORE;;; % THAI CHARACTER MAI TRI + IGNORE;;; % THAI CHARACTER MAI CHATTAWA + +% Arabic and Thai decimal digits + ;;; % DIGIT ZERO + ;;; % THAI DIGIT ZERO + ;;; % DIGIT ONE + ;;; % THAI DIGIT ONE + ;;; % DIGIT TWO + ;;; % THAI DIGIT TWO + ;;; % DIGIT THREE + ;;; % THAI DIGIT THREE + ;;; % DIGIT FOUR + ;;; % THAI DIGIT FOUR + ;;; % DIGIT FIVE + ;;; % THAI DIGIT FIVE + ;;; % DIGIT SIX + ;;; % THAI DIGIT SIX + ;;; % DIGIT SEVEN + ;;; % THAI DIGIT SEVEN + ;;; % DIGIT EIGHT + ;;; % THAI DIGIT EIGHT + ;;; % DIGIT NINE + ;;; % THAI DIGIT NINE + +% Latin alphabet + ;;; % A + ;;; % a + ;;; % B + ;;; % b + ;;; % C + ;;; % c + ;;; % D + ;;; % d + ;;; % E + ;;; % e + ;;; % F + ;;; % f + ;;; % G + ;;; % g + ;;; % H + ;;; % h + ;;; % I + ;;; % i + ;;; % J + ;;; % j + ;;; % K + ;;; % k + ;;; % L + ;;; % l + ;;; % M + ;;; % m + ;;; % N + ;;; % n + ;;; % O + ;;; % o + ;;; % P + ;;; % p + ;;; % Q + ;;; % q + ;;; % R + ;;; % r + ;;; % S + ;;; % s + ;;; % T + ;;; % t + ;;; % U + ;;; % u + ;;; % V + ;;; % v + ;;; % W + ;;; % w + ;;; % X + ;;; % x + ;;; % Y + ;;; % y + ;;; % Z + ;;; % z + +% +% Thai consonants, with leading vowels rearrangement +% + ;;; % THAI CHARACTER KO KAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHUAT + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHWAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHON + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO RAKHANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NGO NGU + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHOE + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER YO YING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER DO CHADA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER TO PATAK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO NANGMONTHO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO PHUTHAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NO NEN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER DO DEK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER TO TAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THUNG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THAHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THONG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NO NU + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER BO BAIMAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PO PLA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO PHUNG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER FO FA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO PHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER FO FAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO SAMPHAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER MO MA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER YO YAK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER RO RUA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER RU + + ;;; % THAI CHARACTER LO LING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER LU + + ;;; % THAI CHARACTER WO WAEN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SALA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO RUSI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SUA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER HO HIP + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER LO CHULA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER O ANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER HO NOKHUK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NIKHAHIT + +% order of Thai vowels + ;;; % THAI CHARACTER SARA A + ;;; % THAI CHARACTER MAI HAN-AKAT + ;;; % THAI CHARACTER SARA AA + ;;; % THAI CHARACTER LAKKHANGYAO + ;;; % THAI CHARACTER SARA AM + ;;; % THAI CHARACTER SARA I + ;;; % THAI CHARACTER SARA II + ;;; % THAI CHARACTER SARA UE + ;;; % THAI CHARACTER SARA UEE + ;;; % THAI CHARACTER SARA U + ;;; % THAI CHARACTER SARA UU + ;;; % THAI CHARACTER SARA E + ;;; % THAI CHARACTER SARA AE + ;;; % THAI CHARACTER SARA O + ;;; % THAI CHARACTER SARA AI MAIMUAN + ;;; % THAI CHARACTER SARA AI MAIMALAI + +order_end + diff --git a/extra/locale/collation/ti_ER b/extra/locale/collation/ti_ER new file mode 100644 index 0000000..61b292b --- /dev/null +++ b/extra/locale/collation/ti_ER @@ -0,0 +1 @@ +copy "am_ET" diff --git a/extra/locale/collation/ti_ET b/extra/locale/collation/ti_ET new file mode 100644 index 0000000..61b292b --- /dev/null +++ b/extra/locale/collation/ti_ET @@ -0,0 +1 @@ +copy "am_ET" diff --git a/extra/locale/collation/tl_PH b/extra/locale/collation/tl_PH new file mode 100644 index 0000000..420168c --- /dev/null +++ b/extra/locale/collation/tl_PH @@ -0,0 +1,30 @@ +copy "iso14651_t1" + +%% a b c d e f g h i j k l m n ng o p q r s t u v w x y z + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/tr_TR b/extra/locale/collation/tr_TR new file mode 100644 index 0000000..a96c2cf --- /dev/null +++ b/extra/locale/collation/tr_TR @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/tt_RU b/extra/locale/collation/tt_RU new file mode 100644 index 0000000..1ca9685 --- /dev/null +++ b/extra/locale/collation/tt_RU @@ -0,0 +1,162 @@ + +% The new (2000) latin tatar alphabet is: +% a, sw, b, c, c,, d, e, f, g, g(, h, i (dotless i), +% i. (i with dot), j, k, q, l, m, n, ng, o, o--, p, r, s, s,, +% t, u, u:, v, w, x, y, z +% ,,,,,,,,,,, +% , , ,,,,,,, +% ,,,,,,,,,,???, ,, +% +% However, a commonly used alphabet in internet uses , and +% for respectively , and + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +% FIXME: check order of cyrillic letters (I copied from cyr Azeri) +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + + diff --git a/extra/locale/collation/uk_UA b/extra/locale/collation/uk_UA new file mode 100644 index 0000000..342a761 --- /dev/null +++ b/extra/locale/collation/uk_UA @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/extra/locale/collation/ur_PK b/extra/locale/collation/ur_PK new file mode 100644 index 0000000..d66184e --- /dev/null +++ b/extra/locale/collation/ur_PK @@ -0,0 +1 @@ +copy "en_DK" diff --git a/extra/locale/collation/uz_UZ b/extra/locale/collation/uz_UZ new file mode 100644 index 0000000..afdc7d4 --- /dev/null +++ b/extra/locale/collation/uz_UZ @@ -0,0 +1,28 @@ +copy "iso14651_t1" + +%% a b c d e f g g' h i j k l m n o o' p q r s t u v x y z +collating-symbol +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" + +reorder-after + + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/vi_VN b/extra/locale/collation/vi_VN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/vi_VN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/wa_BE b/extra/locale/collation/wa_BE new file mode 100644 index 0000000..be8221c --- /dev/null +++ b/extra/locale/collation/wa_BE @@ -0,0 +1 @@ +copy "fr_BE" diff --git a/extra/locale/collation/yi_US b/extra/locale/collation/yi_US new file mode 100644 index 0000000..91de1b9 --- /dev/null +++ b/extra/locale/collation/yi_US @@ -0,0 +1,43 @@ +copy "iso14651_t1" + +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + + + +reorder-after + ;;;IGNORE +reorder-after + "";"";IGNORE;IGNORE + "";"";IGNORE;IGNORE +reorder-after + "";"";IGNORE;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/zh_CN b/extra/locale/collation/zh_CN new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/zh_CN @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/zh_HK b/extra/locale/collation/zh_HK new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/zh_HK @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/zh_SG b/extra/locale/collation/zh_SG new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/zh_SG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/zh_TW b/extra/locale/collation/zh_TW new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/zh_TW @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/gen_collate.c b/extra/locale/gen_collate.c new file mode 100644 index 0000000..44f6215 --- /dev/null +++ b/extra/locale/gen_collate.c @@ -0,0 +1,3997 @@ +/* + * Usage: + * gen_collate [-o OUTPUTFILE] LOCALE ... + * + * Generate collation data from locales LOCALE. + * Reads all LOCALE from INPUTDIR and writes collation data to OUTPUTFILE. + * + * The output file defaults to "locales_collate.h". + */ +/* TODO: + * + * add UNDEFINED at end if not specified + * convert POSITION -> FORWARD,POSITION + * + * + * deal with lowercase in + * + * what about reorders that keep the same rule? + * + * remove "unused" collation elements? (probably doesn't save much) + * + * add_rule function ... returns index into rule table after possibly adding custom-indexed rule + * but don't forget about multichar weights... replace with strings of indexes + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + char *name; /* */ + + int num_weights; /* */ + + int ii_shift; /* */ + int ti_shift; /* */ + int ii_len; /* */ + int ti_len; /* */ + int max_weight; /* */ + int num_col_base; /* */ + int max_col_index; /* */ + int undefined_idx; /* */ + int range_low; /* */ + int range_count; /* high - low */ + int range_base_weight; /* */ + int num_starters; /* */ + + int range_rule_offset; /* */ + int wcs2colidt_offset; /* */ + int index2weight_offset; /* */ + int index2ruleidx_offset; /* */ + int multistart_offset; /* */ + +} base_locale_t; + +#define BASE_LOCALE_LEN 20 +static base_locale_t base_locale_array[BASE_LOCALE_LEN]; +static size_t base_locale_len; + +typedef struct { + char *name; /* */ + + int base_idx; /* */ + + int undefined_idx; /* */ + + int overrides_offset; /* */ + int multistart_offset; /* */ +} der_locale_t; + +#define DER_LOCALE_LEN 300 +static der_locale_t der_locale_array[DER_LOCALE_LEN]; +static size_t der_locale_len; + + +#define OVERRIDE_LEN 50000 +static uint16_t override_buffer[OVERRIDE_LEN]; +static size_t override_len; + +#define MULTISTART_LEN 10000 +static uint16_t multistart_buffer[MULTISTART_LEN]; +static size_t multistart_len; + +#define WCS2COLIDT_LEN 200000 +static uint16_t wcs2colidt_buffer[WCS2COLIDT_LEN]; +static size_t wcs2colidt_len; + +#define INDEX2WEIGHT_LEN 200000 +static uint16_t index2weight_buffer[INDEX2WEIGHT_LEN]; +static size_t index2weight_len; + +static uint16_t index2ruleidx_buffer[INDEX2WEIGHT_LEN]; +static size_t index2ruleidx_len; + +#define WEIGHTSTR_LEN 10000 +static uint16_t weightstr_buffer[WEIGHTSTR_LEN]; +static size_t weightstr_len; + +#define RULETABLE_LEN (1L<<16) +static uint16_t ruletable_buffer[RULETABLE_LEN]; +static size_t ruletable_len; + + +#define RANGE (0x10000UL) + +typedef uint16_t tbl_item; + +static uint16_t u16_buf[10000]; +static int u16_buf_len; +static int u16_starter; + +typedef struct { + uint16_t ii_len; + uint16_t ti_len; + uint16_t ut_len; + + unsigned char ii_shift; + unsigned char ti_shift; + + tbl_item *ii; + tbl_item *ti; + tbl_item *ut; +} table_data; + + +static size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl); + + +#define MAX_COLLATION_WEIGHTS 4 + +#define MAX_FNO 1 +#define MAX_FILES (MAX_FNO + 1) + +static FILE *fstack[MAX_FILES]; +static char *fname[MAX_FILES]; +static int lineno[MAX_FILES]; +static int fno = -1; + +static tbl_item wcs2index[RANGE]; + +static char linebuf[1024]; +static char *pos; +static char *pos_e = NULL; +static char end_of_token = 0; /* slot to save */ + +#define IN_ORDER 0x01 +#define IN_REORDER 0x02 +#define IN_REORDER_SECTIONS 0x04 +static int order_state; +static int cur_num_weights; /* number of weights in current use */ +static char cur_rule[MAX_COLLATION_WEIGHTS]; + +static int anonsection = 0; + +typedef struct ll_item_struct ll_item_t; + +struct ll_item_struct { + ll_item_t *next; + ll_item_t *prev; + void *data; + int data_type; + int idx; +}; + +static ll_item_t *reorder_section_ptr = NULL; +static int superset; +static int superset_order_start_cnt; /* only support one order for now */ +static int superset_in_sync; +static ll_item_t *comm_cur_ptr; +static ll_item_t *comm_prev_ptr; + +enum { + R_FORWARD = 0x01, + R_POSITION = 0x02, + R_BACKWARD = 0x04 /* must be largest in value */ +}; + +typedef struct { + size_t num_weights; + char rule[MAX_COLLATION_WEIGHTS]; + const char *colitem[MAX_COLLATION_WEIGHTS]; +} weight_t; + +static void *root_weight = NULL; +size_t unique_weights = 0; + +typedef struct { + const char *symbol; + weight_t *weight; +} weighted_item_t; + +typedef struct { + const char *symbol1; + const char *symbol2; + int length; + weight_t *weight; +} range_item_t; + +typedef struct { + const char *name; + ll_item_t *itm_list; /* weighted_item_t list .. circular!!! */ + size_t num_items; + size_t num_rules; + char rules[MAX_COLLATION_WEIGHTS]; +} section_t; + +static section_t *cur_section = NULL; + +typedef struct { + const char *symbol; + ll_item_t *node; +} wi_index_t; + +typedef struct col_locale_struct col_locale_t; + +struct col_locale_struct { + char *name; + void *root_colitem; /* all base and derived, or just derived */ + void *root_element; + void *root_scripts; + void *root_wi_index; + void *root_wi_index_reordered; + ll_item_t *section_list; + col_locale_t *base_locale; /* null if this is a base */ + void *root_derived_wi; + ll_item_t *derived_list; + void *root_starter_char; + void *root_starter_all; + ll_item_t *undefined_idx; +}; + +typedef struct { + const char *symbol; + int idx; +} col_index_t; + +static void *root_col_locale = NULL; + +typedef struct { + const char *keyword; + void (*handler)(void); +} keyword_table_t; + +typedef struct { + const char *string; + const char *element; /* NULL if collating symbol */ +} colitem_t; + +static col_locale_t *cur_base = NULL; +static col_locale_t *cur_derived = NULL; +static col_locale_t *cur_col = NULL; + +static void *root_sym = NULL; +static size_t num_sym = 0; +static size_t mem_sym = 0; + +static const char *inputdir; +static size_t inputdir_len; +static unsigned verbose = 0; +enum { + VINFO = (1<<0), + VDETAIL = (1<<1), +}; + +static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +static void *xmalloc(size_t n); +static char *xsymdup(const char *s); /* only allocate once... store in a tree */ +static void pushfile(char *filename); +static void popfile(void); +static void processfile(void); +static int iscommentchar(int); +static void eatwhitespace(void); +static int next_line(void); +static char *next_token(void); +static void do_unrecognized(void); +static col_locale_t *new_col_locale(char *name); +static ll_item_t *new_ll_item(int data_type, void *data); +static weight_t *register_weight(weight_t *w); +static size_t ll_len(ll_item_t *l); +static size_t ll_count(ll_item_t *l, int mask); +static void add_wi_index(ll_item_t *l); +static size_t tnumnodes(const void *root); +static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl); +static void mark_reordered(const char *sym); +static ll_item_t *find_wi_index_reordered(const char *sym); +static ll_item_t *next_comm_ptr(void); +static ll_item_t *init_comm_ptr(void); +static ll_item_t *find_ll_last(ll_item_t *p); +static void dump_weights(const char *name); +static void finalize_base(void); +static int is_ucode(const char *s); +static int sym_cmp(const void *n1, const void *n2); +static void do_starter_lists(col_locale_t *cl); +static void dump_base_locale(int n); +static void dump_der_locale(int n); +static void dump_collate(FILE *fp); + +enum { + DT_SECTION = 0x01, + DT_WEIGHTED = 0x02, + DT_REORDER = 0x04, /* a section to support reorder_after */ + DT_COL_LOCALE = 0x08, + DT_RANGE = 0x10, +}; + +static int verbose_msg(const unsigned lvl, const char *fmt, ...) +{ + va_list arg; + int ret = 0; + + if (verbose & lvl) { + va_start(arg, fmt); + ret = vfprintf(stderr, fmt, arg); + va_end(arg); + } + return ret; +} +static section_t *new_section(const char *name) +{ + section_t *p; + char buf[128]; + + p = xmalloc(sizeof(section_t)); + if (!name) { /* anonymous section */ + name = buf; + snprintf(buf, sizeof(buf), "anon%05d", anonsection); + ++anonsection; + } else if (*name != '<') { /* reorder */ + name = buf; + snprintf(buf, sizeof(buf), "%s %05d", cur_col->name, anonsection); + ++anonsection; + } +#warning devel code +/* verbose_msg(VDETAIL, "section %s\n", name); */ + p->name = xsymdup(name); + p->itm_list = NULL; + p->num_items = 0; + p->num_rules = 0; + memset(p->rules, 0, MAX_COLLATION_WEIGHTS); +/* cur_num_weights = p->num_rules = 0; */ +/* memset(p->rules, 0, MAX_COLLATION_WEIGHTS); */ +/* memset(cur_rule, R_FORWARD, 4); */ + +#warning devel code + if (*p->name == 'a') { + cur_num_weights = p->num_rules = 4; + memset(p->rules, R_FORWARD, 4); + memset(cur_rule, R_FORWARD, 4); + p->rules[3] |= R_POSITION; + cur_rule[3] |= R_POSITION; + } +/* verbose_msg(VDETAIL, "new section %s -- cur_num_weights = %d\n", p->name, cur_num_weights); */ + + return p; +} + + + +static void do_order_start(void); +static void do_order_end(void); +static void do_reorder_after(void); +static void do_reorder_end(void); +static void do_reorder_sections_after(void); +static void do_reorder_sections_end(void); +static void do_copy(void); +static void do_colsym(void); +static void do_colele(void); +static void do_script(void); +static void do_range(void); + +static col_locale_t *new_col_locale(char *name); +static int colitem_cmp(const void *n1, const void *n2); +static int colelement_cmp(const void *n1, const void *n2); +static void del_colitem(colitem_t *p); +static colitem_t *new_colitem(char *item, char *def); +static void add_colitem(char *item, char *def); +static void add_script(const char *s); +static unsigned int add_rule(weighted_item_t *wi); +static unsigned int add_range_rule(range_item_t *ri); + +static const keyword_table_t keyword_table[] = { + { "collating-symbol", do_colsym }, + { "collating-element", do_colele }, + { "script", do_script }, + { "copy", do_copy }, + { "order_start", do_order_start }, + { "order_end", do_order_end }, + { "order-end", do_order_end }, + { "reorder-after", do_reorder_after }, + { "reorder-end", do_reorder_end }, + { "reorder-sections-after", do_reorder_sections_after }, + { "reorder-sections-end", do_reorder_sections_end }, + { "UCLIBC_RANGE", do_range }, + { NULL, do_unrecognized } +}; + + +static void do_unrecognized(void) +{ +#if 1 + error_msg("warning: unrecognized: %s", pos); +#else +/* verbose_msg(VDETAIL, "warning: unrecognized initial keyword \"%s\"\n", pos); */ + fprintf(stderr, "warning: unrecognized: %s", pos); + if (end_of_token) { + fprintf(stderr, "%c%s", end_of_token, pos_e+1); + } + fprintf(stderr, "\n"); +#endif +} + +/* typedef struct { */ +/* const char *symbol1; */ +/* const char *symbol2; */ +/* int length; */ +/* weight_t *weight; */ +/* } range_item_t; */ + +static void do_range(void) +{ + range_item_t *ri; + weight_t w; + int i; + char *s; + char *s1; + char *s2; + const char **ci; + ll_item_t *lli; + + assert(!superset); + assert(order_state == IN_ORDER); + + s1 = next_token(); + if (!s1) { + error_msg("missing start of range"); + } + if (!is_ucode(s1)) { + error_msg("start of range is not a ucode: %s", s1); + } + s1 = xsymdup(s1); + + s2 = next_token(); + if (!s2) { + error_msg("missing end of range"); + } + if (!is_ucode(s2)) { + error_msg("end of range is not a ucode: %s", s2); + } + s2 = xsymdup(s2); + + ri = (range_item_t *) xmalloc(sizeof(range_item_t)); + ri->symbol1 = s1; + ri->symbol2 = s2; + ri->length = strtoul(s2+2, NULL, 16) - strtoul(s1+2, NULL, 16); + if (ri->length <= 0) { + error_msg("illegal range length %d", ri->length); + } + + s = next_token(); + w.num_weights = cur_num_weights; + + for (i=0 ; i < cur_num_weights ; i++) { + w.rule[i] = cur_rule[i]; + } + ci = w.colitem + (i-1); + /* now i == cur_num_weights */ + +#define STR_DITTO "." + + while (s && *s && i) { + --i; + if (*s == ';') { + ci[-i] = xsymdup(STR_DITTO); + if (*++s) { + continue; + } + } + if (*s) { + ci[-i] = xsymdup(s); + } + s = next_token(); + if (s) { + if (*s == ';') { + ++s; + } else if (i) { + error_msg("missing seperator"); + } + } + } + if (s) { + error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s); + } + + while (i) { /* missing weights are not an error */ + --i; + ci[-i] = xsymdup(STR_DITTO); + } + + ri->weight = register_weight(&w); + +/* if ((i = is_ucode(t)) != 0) { */ +/* assert(!t[i]); */ +/* add_colitem(t, NULL); */ +/* } */ + + lli = new_ll_item(DT_RANGE, ri); + if (!cur_section->itm_list) { +/* printf("creating new item list: %s\n", wi->symbol); */ + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); +/* printf("adding item to list: %d - %s\n", ll_len(cur_section->itm_list), wi->symbol); */ + ++cur_section->num_items; + } +/* add_wi_index(lli); */ + + +} + +static weighted_item_t *add_weight(char *t) +{ + weighted_item_t *wi; + weight_t w; + int i; + char *s; + const char **ci; + + t = xsymdup(t); + + s = next_token(); + w.num_weights = cur_num_weights; + + for (i=0 ; i < cur_num_weights ; i++) { + w.rule[i] = cur_rule[i]; + } + ci = w.colitem + (i-1); + /* now i == cur_num_weights */ + + while (s && *s && i) { + --i; + if (*s == ';') { + ci[-i] = xsymdup(STR_DITTO); + if (*++s) { + continue; + } + } + if (*s) { + if (!strcmp(s,t)) { + s = STR_DITTO; + } + ci[-i] = xsymdup(s); + } + s = next_token(); + if (s) { + if (*s == ';') { + ++s; + } else if (i) { + error_msg("missing seperator"); + } + } + } + if (s) { + error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s); + } + + while (i) { /* missing weights are not an error */ + --i; + ci[-i] = xsymdup(STR_DITTO); + } + + wi = xmalloc(sizeof(weighted_item_t)); + wi->symbol = t; + wi->weight = register_weight(&w); + + if ((i = is_ucode(t)) != 0) { + assert(!t[i]); + add_colitem(t, NULL); + } + + return wi; +} + +static void add_superset_weight(char *t) +{ + ll_item_t *lli; + weighted_item_t *wi; + + if (!comm_cur_ptr + || (strcmp(t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol) != 0) + ) { /* now out of sync */ + if (superset_in_sync) { /* need a new section */ + superset_in_sync = 0; + + cur_section = new_section("R"); + cur_num_weights = cur_section->num_rules + = ((section_t *)(cur_base->section_list->data))->num_rules; + memcpy(cur_rule, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + + insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list)); + assert(comm_prev_ptr); + lli = new_ll_item(DT_REORDER, cur_section); + lli->prev = lli->next = lli; + insque(lli, comm_prev_ptr); +/* verbose_msg(VDETAIL, " subsection -----------------------\n"); */ + } + +/* verbose_msg(VDETAIL, " %s %s\n", t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol); */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + mark_reordered(wi->symbol); + /* printf("reorder: %s\n", t); */ + if (!cur_section->itm_list) { + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); + ++cur_section->num_items; + } + add_wi_index(lli); + + } else { /* in sync */ + superset_in_sync = 1; + next_comm_ptr(); + } +} + +static void do_weight(char *t) +{ + weighted_item_t *wi; + ll_item_t *lli; + + if (superset) { + add_superset_weight(t); + return; + } + + switch(order_state) { + case 0: +/* fprintf(stdout, "no-order weight: %s\n", t); */ +/* break; */ + case IN_ORDER: + /* in a section */ +/* fprintf(stdout, "weight: %s\n", t); */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + if (!cur_section->itm_list) { +/* fprintf(stdout, "creating new item list: %s %s %p\n", wi->symbol, cur_section->name, lli); */ + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); +/* fprintf(stdout, "adding item to list: %d - %s %p\n", ll_len(cur_section->itm_list), wi->symbol, lli); */ + ++cur_section->num_items; + } + add_wi_index(lli); + break; + case IN_REORDER: + /* std rule - but in a block with an insert-after pt */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + mark_reordered(wi->symbol); +/* fprintf(stdout, "reorder: %s %s %p\n", t, cur_section->name, lli); */ + if (!cur_section->itm_list) { + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); + ++cur_section->num_items; + } + add_wi_index(lli); + break; + case IN_REORDER_SECTIONS: + t = xsymdup(t); + if (next_token() != NULL) { + error_msg("trailing text in reorder section item: %s", pos); + } + lli = cur_col->section_list; + do { + if (lli->data_type & DT_SECTION) { + if (!strcmp(((section_t *)(lli->data))->name, t)) { + lli->data_type = DT_REORDER; + lli = new_ll_item(DT_REORDER, (section_t *)(lli->data)); + insque(lli, reorder_section_ptr); + reorder_section_ptr = lli; + return; + } + } + lli = lli->next; + } while (lli); + error_msg("reorder_sections_after for non-base item currently not supported: %s", t); +/* fprintf(stdout, "reorder_secitons: %s\n", t); */ + break; + default: + error_msg("invalid order_state %d", order_state); + } +} + +static int col_locale_cmp(const void *n1, const void *n2) +{ + return strcmp(((const col_locale_t *) n1)->name, ((const col_locale_t *) n2)->name); +} + +static void processfile(void) +{ + char *t; + const keyword_table_t *k; + + order_state = 0; +#warning devel code +/* cur_num_weights = 0; */ +/* cur_num_weights = 4; */ +/* memset(cur_rule, R_FORWARD, 4); */ + + if (cur_col != cur_base) { + cur_col->base_locale = cur_base; + cur_col->undefined_idx = cur_base->undefined_idx; + if (!cur_base->derived_list) { + cur_base->derived_list = new_ll_item(DT_COL_LOCALE, cur_col); + } else { + insque(new_ll_item(DT_COL_LOCALE, cur_col), find_ll_last(cur_base->derived_list)); + } + } + + if (tfind(cur_col, &root_col_locale, col_locale_cmp)) { + error_msg("attempt to read locale: %s", cur_col->name); + } + if (!tsearch(cur_col, &root_col_locale, col_locale_cmp)) { + error_msg("OUT OF MEMORY!"); + } + + if (superset) { + superset_order_start_cnt = 0; + superset_in_sync = 0; + init_comm_ptr(); + } + + while (next_line()) { +/* printf("%5d:", lineno[fno]); */ +/* while ((t = next_token()) != NULL) { */ +/* printf(" |%s|", t); */ +/* printf("\n"); */ +/* } */ + t = next_token(); + assert(t); + assert(t == pos); + if ((*t == '<') || (!strcmp(t, "UNDEFINED"))) { + do_weight(t); + } else { + for (k = keyword_table ; k->keyword ; k++) { + if (!strcmp(k->keyword, t)) { + break; + } + } + k->handler(); + } + } + + if (cur_base == cur_col) { + verbose_msg(VDETAIL, "Base: %15s", cur_col->name); + } else { +#if 1 + if (!cur_col->undefined_idx) { +#if 0 + if (superset) { + if (superset_order_start_cnt == 1) { + --superset_order_start_cnt; /* ugh.. hack this */ + } + } +#endif + /* This is an awful hack to get around the problem of unspecified UNDEFINED + * definitions in the supported locales derived from iso14651_t1. */ + if (!strcmp(cur_base->name, "iso14651_t1")) { + fprintf(stderr, "Warning: adding UNDEFINED entry for %s\n", cur_col->name); + strcpy(linebuf, "script \n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_script(); + strcpy(linebuf, "order_start ;forward;backward;forward;forward,position\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_order_start(); + strcpy(linebuf, "UNDEFINED IGNORE;IGNORE;IGNORE\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_weight(t); + strcpy(linebuf, "order_end\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_order_end(); + } else { + error_msg("no definition of UNDEFINED for %s", cur_col->name); + } + } +#endif + + verbose_msg(VDETAIL, " Der: %15s", cur_col->name); + } + { +#if 0 + ll_item_t *p = cur_col->section_list; +#endif + verbose_msg(VDETAIL, "%6u weights", tnumnodes(cur_col->root_wi_index)); + if (cur_base) { + verbose_msg(VDETAIL, " %6u der %6u reor %6u starter - %u new stubs", + tnumnodes(cur_base->root_derived_wi), + tnumnodes(cur_base->root_wi_index_reordered), + tnumnodes(cur_base->root_starter_char), + ll_count(cur_col->section_list, DT_REORDER)); + } + verbose_msg(VDETAIL, "\n"); + +#if 0 + while (p) { + assert(((section_t *)(p->data))->num_items == + ll_len(((section_t *)(p->data))->itm_list)); + + + if (!p->next && + ((*((section_t *)(p->data))->name == 'a') + && (((section_t *)(p->data))->num_items == 0)) + ) { + break; + } + + if (!(p->data_type & DT_REORDER)) { + if ((*((section_t *)(p->data))->name != 'a') + || (((section_t *)(p->data))->num_items > 0) + ) { + verbose_msg(VDETAIL, +/* "\t%-15s %zu\n", */ + "\t%-15s %6u\n", + ((section_t *)(p->data))->name, + ((section_t *)(p->data))->num_items); + } + } + p = p->next; + } +#endif + } + + +} + +static void print_colnode(const void *ptr, VISIT order, int level) +{ + const colitem_t *p = *(const colitem_t **) ptr; + + if (order == postorder || order == leaf) { + printf("collating item = \"%s\"", p->string); + if (p->element) { + printf(" is %s", p->element); + } + printf("\n"); + } +} + +static void print_weight_node(const void *ptr, VISIT order, int level) +{ + const weight_t *p = *(const weight_t **) ptr; + int i; + + if (order == postorder || order == leaf) { + printf("weight: (%d) ", p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); + } +} + + +typedef struct { + const char *der_name; + int base_locale; +} deps_t; + +enum { + BASE_iso14651_t1, + BASE_comm, + BASE_cs_CZ, + BASE_ar_SA, + BASE_th_TH, + BASE_ja_JP, + BASE_ko_KR, + BASE_MAX +}; + +static const char *base_name[] = { + "iso14651_t1", + "comm", + "cs_CZ", + "ar_SA", + "th_TH", + "ja_JP", + "ko_KR" +}; + + + +static ll_item_t *locale_list[BASE_MAX]; + +static void init_locale_list(void) +{ + int i; + + for (i=0 ; i < BASE_MAX ; i++) { + locale_list[i] = (ll_item_t *) xmalloc(sizeof(ll_item_t)); + locale_list[i]->prev = locale_list[i]->next = locale_list[i]; + locale_list[i]->data = (void *) base_name[i]; + } +} + + +deps_t deps[] = { + { "af_ZA", BASE_iso14651_t1 }, + { "am_ET", BASE_iso14651_t1 }, + { "ar_AE", BASE_iso14651_t1 }, + { "ar_BH", BASE_iso14651_t1 }, + { "ar_DZ", BASE_iso14651_t1 }, + { "ar_EG", BASE_iso14651_t1 }, + { "ar_IN", BASE_iso14651_t1 }, + { "ar_IQ", BASE_iso14651_t1 }, + { "ar_JO", BASE_iso14651_t1 }, + { "ar_KW", BASE_iso14651_t1 }, + { "ar_LB", BASE_iso14651_t1 }, + { "ar_LY", BASE_iso14651_t1 }, + { "ar_MA", BASE_iso14651_t1 }, + { "ar_OM", BASE_iso14651_t1 }, + { "ar_QA", BASE_iso14651_t1 }, + { "ar_SA", BASE_ar_SA }, + { "ar_SD", BASE_iso14651_t1 }, + { "ar_SY", BASE_iso14651_t1 }, + { "ar_TN", BASE_iso14651_t1 }, + { "ar_YE", BASE_iso14651_t1 }, + { "az_AZ", BASE_iso14651_t1 }, + { "be_BY", BASE_iso14651_t1 }, + { "bg_BG", BASE_iso14651_t1 }, + { "bn_BD", BASE_iso14651_t1 }, + { "bn_IN", BASE_iso14651_t1 }, + { "br_FR", BASE_iso14651_t1 }, + { "bs_BA", BASE_iso14651_t1 }, + { "ca_ES", BASE_comm }, + { "cs_CZ", BASE_cs_CZ }, + { "cy_GB", BASE_iso14651_t1 }, + { "da_DK", BASE_comm }, + { "de_AT", BASE_iso14651_t1 }, + { "de_BE", BASE_iso14651_t1 }, + { "de_CH", BASE_iso14651_t1 }, + { "de_DE", BASE_iso14651_t1 }, + { "de_LU", BASE_iso14651_t1 }, + { "el_GR", BASE_iso14651_t1 }, + { "en_AU", BASE_iso14651_t1 }, + { "en_BW", BASE_iso14651_t1 }, + { "en_CA", BASE_comm }, + { "en_DK", BASE_iso14651_t1 }, + { "en_GB", BASE_iso14651_t1 }, + { "en_HK", BASE_iso14651_t1 }, + { "en_IE", BASE_iso14651_t1 }, + { "en_IN", BASE_iso14651_t1 }, + { "en_NZ", BASE_iso14651_t1 }, + { "en_PH", BASE_iso14651_t1 }, + { "en_SG", BASE_iso14651_t1 }, + { "en_US", BASE_iso14651_t1 }, + { "en_ZA", BASE_iso14651_t1 }, + { "en_ZW", BASE_iso14651_t1 }, + { "eo_EO", BASE_iso14651_t1 }, + { "es_AR", BASE_comm }, + { "es_BO", BASE_comm }, + { "es_CL", BASE_comm }, + { "es_CO", BASE_comm }, + { "es_CR", BASE_comm }, + { "es_DO", BASE_comm }, + { "es_EC", BASE_comm }, + { "es_ES", BASE_comm }, + { "es_GT", BASE_comm }, + { "es_HN", BASE_comm }, + { "es_MX", BASE_comm }, + { "es_NI", BASE_comm }, + { "es_PA", BASE_comm }, + { "es_PE", BASE_comm }, + { "es_PR", BASE_comm }, + { "es_PY", BASE_comm }, + { "es_SV", BASE_comm }, + { "es_US", BASE_comm }, + { "es_UY", BASE_comm }, + { "es_VE", BASE_comm }, + { "et_EE", BASE_comm }, + { "eu_ES", BASE_iso14651_t1 }, + { "fa_IR", BASE_iso14651_t1 }, + { "fi_FI", BASE_comm }, + { "fo_FO", BASE_comm }, + { "fr_BE", BASE_iso14651_t1 }, + { "fr_CA", BASE_comm }, + { "fr_CH", BASE_iso14651_t1 }, + { "fr_FR", BASE_iso14651_t1 }, + { "fr_LU", BASE_iso14651_t1 }, + { "ga_IE", BASE_iso14651_t1 }, + { "gd_GB", BASE_iso14651_t1 }, + { "gl_ES", BASE_comm }, + { "gv_GB", BASE_iso14651_t1 }, + { "he_IL", BASE_iso14651_t1 }, + { "hi_IN", BASE_iso14651_t1 }, + { "hr_HR", BASE_comm }, + { "hu_HU", BASE_iso14651_t1 }, + { "hy_AM", BASE_iso14651_t1 }, + { "id_ID", BASE_iso14651_t1 }, + { "is_IS", BASE_comm }, + { "it_CH", BASE_iso14651_t1 }, + { "it_IT", BASE_iso14651_t1 }, + { "iw_IL", BASE_iso14651_t1 }, + { "ja_JP", BASE_ja_JP }, + { "ka_GE", BASE_iso14651_t1 }, + { "kl_GL", BASE_comm }, + { "ko_KR", BASE_ko_KR }, + { "kw_GB", BASE_iso14651_t1 }, + { "lt_LT", BASE_comm }, + { "lv_LV", BASE_comm }, + { "mi_NZ", BASE_iso14651_t1 }, + { "mk_MK", BASE_iso14651_t1 }, + { "mr_IN", BASE_iso14651_t1 }, + { "ms_MY", BASE_iso14651_t1 }, + { "mt_MT", BASE_iso14651_t1 }, + { "nl_BE", BASE_iso14651_t1 }, + { "nl_NL", BASE_iso14651_t1 }, + { "nn_NO", BASE_iso14651_t1 }, + { "no_NO", BASE_comm }, + { "oc_FR", BASE_iso14651_t1 }, + { "pl_PL", BASE_comm }, + { "pt_BR", BASE_iso14651_t1 }, + { "pt_PT", BASE_iso14651_t1 }, + { "ro_RO", BASE_iso14651_t1 }, + { "ru_RU", BASE_iso14651_t1 }, + { "ru_UA", BASE_iso14651_t1 }, + { "se_NO", BASE_iso14651_t1 }, + { "sk_SK", BASE_cs_CZ }, + { "sl_SI", BASE_comm }, + { "sq_AL", BASE_iso14651_t1 }, + { "sr_YU", BASE_iso14651_t1 }, + { "sv_FI", BASE_comm }, + { "sv_SE", BASE_iso14651_t1 }, + { "ta_IN", BASE_iso14651_t1 }, + { "te_IN", BASE_iso14651_t1 }, + { "tg_TJ", BASE_iso14651_t1 }, + { "th_TH", BASE_th_TH }, + { "ti_ER", BASE_iso14651_t1 }, + { "ti_ET", BASE_iso14651_t1 }, + { "tl_PH", BASE_iso14651_t1 }, + { "tr_TR", BASE_comm }, + { "tt_RU", BASE_iso14651_t1 }, + { "uk_UA", BASE_iso14651_t1 }, + { "ur_PK", BASE_iso14651_t1 }, + { "uz_UZ", BASE_iso14651_t1 }, + { "vi_VN", BASE_iso14651_t1 }, + { "wa_BE", BASE_iso14651_t1 }, + { "yi_US", BASE_iso14651_t1 }, + { "zh_CN", BASE_iso14651_t1 }, + { "zh_HK", BASE_iso14651_t1 }, + { "zh_SG", BASE_iso14651_t1 }, + { "zh_TW", BASE_iso14651_t1 }, +}; + + +static int der_count[BASE_MAX]; +static const char *new_args[500]; +static int new_arg_count; + +static int dep_cmp(const void *s1, const void *s2) +{ + return strcmp( (const char *) s1, ((const deps_t *) s2)->der_name); +} + +static int old_main(int argc, char **argv); + +int main(int argc, char **argv) +{ + const deps_t *p; + ll_item_t *lli; + int i; + int total; + char *output_file = "locale_collate.h"; + unsigned verbosity = 0; + + if (argc < 3) { + return EXIT_FAILURE; + } + --argc; + inputdir = strdup(*++argv); + inputdir_len = strlen(inputdir); + init_locale_list(); + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-o")) { + --argc; + if (*++argv == NULL) { + printf("-o requires an argument\n"); + return EXIT_FAILURE; + } + output_file = strdup(*argv); + continue; + } else if (!strcmp(*argv, "-v")) { + verbosity++; + continue; + } + p = (const deps_t *) bsearch(*argv, deps, sizeof(deps)/sizeof(deps[0]), sizeof(deps[0]), dep_cmp); + if (!p) { + if (!strcmp("C", *argv)) { + printf("ignoring %s locale\n", *argv); + continue; + } else { + printf("%s not found\n", *argv); + return EXIT_FAILURE; + } + } + + i = p->base_locale; + ++der_count[i]; + + if (!strcmp(base_name[i], *argv)) { + /* same name as base, so skip after count incremented */ + continue; + } + + /* add it to the list. the main body will catch duplicates */ + lli = (ll_item_t *) xmalloc(sizeof(ll_item_t)); + lli->prev = lli->next = NULL; + lli->data = (void *) *argv; + insque(lli, locale_list[i]); + } + + total = 0; + for (i=0 ; i < BASE_MAX ; i++) { +/* printf("der_count[%2d] = %3d\n", i, der_count[i]); */ + total += der_count[i]; + } +/* printf("total = %d\n", total); */ + + new_args[new_arg_count++] = "dummyprogramname"; + for (i=0 ; i < BASE_MAX ; i++) { + if (!der_count[i]) { + continue; + } + new_args[new_arg_count++] = (i == BASE_comm) ? "-c" : "-b"; + lli = locale_list[i]; + do { + new_args[new_arg_count++] = (const char *) (lli->data); + lli = lli->next; + } while (lli != locale_list[i]); + new_args[new_arg_count++] = "-f"; + } + for (i=0; i < verbosity; i++) + new_args[new_arg_count++] = "-v"; + + new_args[new_arg_count++] = "-o"; + new_args[new_arg_count++] = output_file; +/* + for (i=0 ; i < new_arg_count ; i++) { + printf("%3d: %s\n", i, new_args[i]); + } +*/ + return old_main(new_arg_count, (char **) new_args); +} + + +/* usage... prog -b basefile derived {derived} -s single {single} */ + +static int old_main(int argc, char **argv) +{ + int next_is_base = 0; + int next_is_subset = 0; + char *output_file = NULL; + + superset = 0; + + while (--argc) { + ++argv; + if (**argv == '-') { + if ((*argv)[1] == 'd') { + dump_weights((*argv) + 2); + } else if ((*argv)[1] == 'f') { /* dump all weight rules */ + finalize_base(); + } else if ((*argv)[1] == 'R') { /* dump all weight rules */ + twalk(root_weight, print_weight_node); + } else if (((*argv)[1] == 'c') && !(*argv)[2]) { /* new common subset */ + cur_base = cur_derived = NULL; + next_is_subset = 1; + next_is_base = 1; + superset = 0; + } else if (((*argv)[1] == 'b') && !(*argv)[2]) { /* new base locale */ + cur_base = cur_derived = NULL; + next_is_subset = 0; + next_is_base = 1; + superset = 0; + } else if (((*argv)[1] == 's') && !(*argv)[2]) { /* single locales follow */ + cur_base = cur_derived = NULL; + next_is_subset = 0; + next_is_base = 2; + superset = 0; + } else if (((*argv)[1] == 'o') && !(*argv)[2]) { /* output file */ + --argc; + output_file = *++argv; + } else if (((*argv)[1] == 'v') && !(*argv)[2]) { /* verbose */ + ++verbose; + } else { + error_msg("unrecognized option %s", *argv); + } + continue; + } + /* new file */ + new_col_locale(*argv); /* automaticly sets cur_col */ + if (next_is_base) { + cur_base = cur_col; + } else { + cur_derived = cur_col; + } + pushfile(*argv); +/* verbose_msg(VDETAIL, "processing file %s\n", *argv); */ + processfile(); /* this does a popfile */ + +/* twalk(cur_col->root_colitem, print_colnode); */ + + if (next_is_base == 1) { + next_is_base = 0; + } + if (next_is_subset) { + next_is_subset = 0; + superset = 1; + } + } + + verbose_msg(VINFO, "success!\n"); + verbose_msg(VINFO, +/* "num_sym=%zu mem_sym=%zu unique_weights=%zu\n", */ + "num_sym=%u mem_sym=%u unique_weights=%u\n", + num_sym, mem_sym, unique_weights); +/* twalk(root_weight, print_weight_node); */ + + verbose_msg(VINFO, "num base locales = %d num derived locales = %d\n", + base_locale_len, der_locale_len); + + verbose_msg(VINFO, + "override_len = %d multistart_len = %d weightstr_len = %d\n" + "wcs2colidt_len = %d index2weight_len = %d index2ruleidx_len = %d\n" + "ruletable_len = %d\n" + "total size is %d bytes or %d kB\n", + override_len, multistart_len, weightstr_len, + wcs2colidt_len, index2weight_len, index2ruleidx_len, + ruletable_len, +#warning mult by 2 for rule indecies + (override_len + multistart_len + weightstr_len + + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len) * 2, + (override_len + multistart_len + weightstr_len + + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len + 511) / 512); + +#if 0 + { + int i; + + for (i=0 ; i < base_locale_len ; i++) { + dump_base_locale(i); + } + for (i=0 ; i < der_locale_len ; i++) { + dump_der_locale(i); + } + } +#endif + + { + FILE *fp = fopen(output_file, "w"); + + if (!fp) { + error_msg("cannot open output file '%s'!", output_file); + } + dump_collate(fp); + if (ferror(fp) || fclose(fp)) { + error_msg("write error or close error for output file!\n"); + } + } + + return EXIT_SUCCESS; +} + +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + fprintf(stderr, "Error: "); + if (fno >= 0) { + fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]); + } + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + +static void pushfile(char *filename) +{ + char *inputfile; + size_t inputfile_len; + + if (fno >= MAX_FNO) { + error_msg("file stack size exceeded"); + } + + inputfile_len = inputdir_len + strlen(filename) + 2; + inputfile = xmalloc(inputfile_len); + memset(inputfile, 0, inputfile_len); + sprintf(inputfile, "%s/%s", inputdir, filename); + if (!(fstack[++fno] = fopen(inputfile, "r"))) { + --fno; /* oops */ + error_msg("cannot open file %s: %s", inputfile, strerror(errno)); + } + + fname[fno] = xsymdup(inputfile); + lineno[fno] = 0; +} + +static void popfile(void) +{ + if (fno < 0) { + error_msg("pop on empty file stack"); + } + +/* free(fname[fno]); */ + fclose(fstack[fno]); + --fno; +} + +static void eatwhitespace(void) +{ + while (isspace(*pos)) { + ++pos; + } +} + +static int iscommentchar(int c) +{ + return ((c == '#') || (c == '%')); +} + +static int next_line(void) +{ + size_t n; + char *s = linebuf; + + assert(fno >= 0); + + pos_e = NULL; + do { + if (fgets(s, sizeof(linebuf), fstack[fno]) != NULL) { + ++lineno[fno]; + n = strlen(linebuf); + if ((n == sizeof(linebuf) - 1) && (linebuf[n-1] != '\n')) { + /* Either line is too long or last line is very long with + * no trailing newline. But we'll always treat it as an + * errro. */ + error_msg("line too long?"); + } + + --n; + /* Be careful... last line doesn't need a newline. */ + if (linebuf[n] == '\n') { + linebuf[n--] = 0; /* trim trailing newline */ + } + + pos = linebuf; + eatwhitespace(); + if (*pos && !iscommentchar(*pos)) { /* not empty or comment line */ + return 1; /* got a line */ + } + } else { /* eof */ + popfile(); + } + } while (fno >= 0); + + return 0; +} + +static char *next_token(void) +{ + char *p; + +#if 0 + if (pos_e == NULL) { + return NULL + pos = pos_e; + *pos = end_of_token; + end_of_token = 0; + } +#else + if (pos_e != NULL) { + pos = pos_e; + *pos = end_of_token; + end_of_token = 0; + } +#endif + eatwhitespace(); + p = pos; + + if (!*p || iscommentchar(*p)) { /* end of line or start of comment */ + pos = pos_e = NULL; + *p = 0; /* treat comment as end of line */ +/* fprintf(stdout, "returning NUL token |%s|\n", pos); */ + return NULL; +#if 1 + } else if (*p == '<') { /* collating symbol, element, or value */ + while (*++p) { + if ((*p == '/') && p[1]) { + ++p; + continue; + } + if (*p == '>') { + pos_e = ++p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning col token |%s|\n", pos); */ + return pos; + } + } + } else if (*p == '"') { /* collating element value? */ + while (*++p) { + if (*p == '"') { /* found the end of the quoted string */ + pos_e = ++p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning quote token |%s|\n", pos); */ + return pos; + } + } +#endif + } else { /* some kind of keyword */ + while (*++p) { + if (isspace(*p) || (*p == ';')) { + break; + } + } + pos_e = p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning key token |%s|\n", pos); */ + return pos; + } + + error_msg("illegal token |%s|", pos); +} + +static void *xmalloc(size_t n) +{ + void *p; + + if (!(p = malloc(n))) { + error_msg("OUT OF MEMORY"); + } + return p; +} + +static void do_copy(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strchr(s + 1, '"'); + if ((*s == '"') && e && (*e == '"') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + *e = 0; + ++s; + if (cur_base && !strcmp(cur_base->name,s)) { +/* verbose_msg(VDETAIL, "skipping copy of base file %s\n", s); */ +#warning need to update last in order and position or check + return; + } +/* verbose_msg(VDETAIL, "full copy of %s\n", s); */ + pushfile(s); + return; + } + } + error_msg("illegal or missing arg for copy: %s", s); +} + +static void do_colsym(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + add_colitem(s,NULL); + return; + } + } + error_msg("illegal or missing arg for collating-symbol: %s", s); +} + +static void do_colele(void) +{ + char *s; + char *e; + char *s1; + char *e1; + int n; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (((s1 = next_token()) == NULL) + || (strcmp(s1,"from") != 0) + || ((s1 = next_token()) == NULL) + || (*s1 != '\"') + ) { + error_msg("illegal format for collating-element spec"); + } + e1 = strchr(s1 + 1, '"'); + if ((*s1 != '"') || !e1 || (*e1 != '"') || (e1[1] != 0)) { + error_msg("illegal definition for collating-element: %s", s1); + } + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + e1[1] = 0; + add_colitem(s,s1); + ++s1; + if (!(n = is_ucode(s1))) { + error_msg("starting char must be a code: %s", s1); + } + assert(s1[n] == '<'); + s1[n] = 0; + s = xsymdup(s1); + if (!(tsearch(s, &cur_base->root_starter_char, sym_cmp))) { + error_msg("OUT OF MEMORY"); + } + + return; + } + } + error_msg("illegal or missing arg for collating-element: %s", s); +} + +static ll_item_t *find_section_list_item(const char *name, col_locale_t *loc) +{ + ll_item_t *p; + + if (!loc) { + return NULL; + } + + p = loc->section_list; + + while (p) { +#warning devel code +/* if (!((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER))) { */ +/* verbose_msg(VDETAIL, "fsli = %d\n", p->data_type); */ +/* } */ + assert((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER)); + if (!strcmp(name, ((section_t *)(p->data))->name)) { + break; + } + p = p->next; + } + return p; +} + +static ll_item_t *find_ll_last(ll_item_t *p) +{ + assert(p); + + while (p->next) { + p = p->next; + } + return p; +} + +static void do_script(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + add_script(s); + return; + } + } + error_msg("illegal or missing arg for script: %s", s); +} + +static col_locale_t *new_col_locale(char *name) +{ + ll_item_t *lli; + ll_item_t *lli2; + + cur_col = (col_locale_t *) xmalloc(sizeof(col_locale_t)); + cur_col->name = name; + cur_col->root_colitem = NULL; + cur_col->root_element = NULL; + cur_col->root_scripts = NULL; + cur_col->base_locale = NULL; + if (!superset) { + /* start with an anonymous section */ + cur_section = new_section(NULL); + cur_col->section_list = new_ll_item(DT_SECTION, cur_section); + } else { + /* start with a reorder section */ + cur_section = new_section("R"); + cur_num_weights = cur_section->num_rules + = ((section_t *)(cur_base->section_list->data))->num_rules; + memcpy(cur_rule, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + cur_col->section_list = new_ll_item(DT_REORDER, cur_section); + assert(cur_base->section_list->next == NULL); /* currently only one section allowed */ + lli = ((section_t *)(cur_base->section_list->data))->itm_list; + assert(lli); + lli2 = new_ll_item(DT_REORDER, cur_section); + lli2->prev = lli2->next = lli2; + insque(lli2, lli->prev); + ((section_t *)(cur_base->section_list->data))->itm_list = lli2; + } +/* cur_col->section_list = NULL; */ +/* add_script(((section_t *)(cur_col->section_list->data))->name); */ + cur_col->root_wi_index = NULL; + cur_col->root_wi_index_reordered = NULL; + cur_col->root_derived_wi = NULL; + cur_col->derived_list = NULL; + cur_col->root_starter_char = NULL; + cur_col->root_starter_all = NULL; + cur_col->undefined_idx = NULL; + return cur_col; +} + +static int colitem_cmp(const void *n1, const void *n2) +{ + return strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string); +} + +static int colelement_cmp(const void *n1, const void *n2) +{ + int r; + + r = strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string); + if (!r) { + if (((colitem_t *)n1)->element && ((colitem_t *)n2)->element) { + r = strcmp(((colitem_t *)n1)->element, ((colitem_t *)n2)->element); + } else if (((colitem_t *)n1)->element == ((colitem_t *)n2)->element) { + r = 0; /* both null */ + } else { + r = (((colitem_t *)n1)->element == NULL) ? -1 : 1; + } + } + return r; +} + +static void del_colitem(colitem_t *p) +{ +/* free((void *) p->element); */ +/* free((void *) p->string); */ + free(p); +} + +static colitem_t *new_colitem(char *item, char *def) +{ + colitem_t *p; + + p = xmalloc(sizeof(colitem_t)); + p->string = xsymdup(item); + p->element = (!def) ? def : xsymdup(def); + + return p; +} + +static void add_colitem(char *item, char *def) +{ + colitem_t *p; + +#if 0 + printf("adding collation item %s", item); + if (def) { + printf(" with definition %s", def); + } + printf("\n"); +#endif + + p = new_colitem(item, def); + +#warning devel code + if (superset) { + if (tfind(p, &cur_base->root_colitem, colitem_cmp)) { +/* verbose_msg(VDETAIL, "skipping superset duplicate collating item \"%s\"\n", p->string); */ + del_colitem(p); + return; +/* } else { */ +/* verbose_msg(VDETAIL, "superset: new collating item \"%s\" = %s\n", p->string, p->element); */ + } + } + + if (cur_col == cur_derived) { + if (!tfind(p, &cur_base->root_colitem, colitem_cmp)) { + /* not in current but could be in base */ + if (!tsearch(p, &cur_base->root_colitem, colitem_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } else if (!tfind(p, &cur_base->root_colitem, colelement_cmp)) { + error_msg("collating element/symbol mismatch: item=%s def=%s", item, def); + } + } + + + if (!tfind(p, &cur_col->root_colitem, colitem_cmp)) { + /* not in current but could be in base */ + if (!tsearch(p, &cur_col->root_colitem, colitem_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } else if (!tfind(p, &cur_col->root_colitem, colelement_cmp)) { + error_msg("collating element/symbol mismatch"); + } else { /* already there */ + fprintf(stderr, "duplicate collating item \"%s\"\n", p->string); + del_colitem(p); + } +} + +/* add a script (section) to the current locale */ +static void add_script(const char *s) +{ + ll_item_t *l; + + /* make sure it isn't in base if working with derived */ + if (cur_base != cur_col) { + if (find_section_list_item(s, cur_base)) { + error_msg("attempt to add script %s for derived when already in base", s); + } + } + + if (find_section_list_item(s, cur_col)) { + error_msg("attempt to readd script %s", s); + } + + l = find_ll_last(cur_col->section_list); + insque(new_ll_item(DT_SECTION, new_section(s)), l); +} + +static const char str_forward[] = "forward"; +static const char str_backward[] = "backward"; +static const char str_position[] = "position"; + +static void do_order_start(void) +{ + const char *s; + char *e; + ll_item_t *l; + section_t *sect; + int rule; + + if (order_state & ~IN_ORDER) { + error_msg("order_start following reorder{_sections}_after"); + } + order_state |= IN_ORDER; + + if (superset) { + if (++superset_order_start_cnt > 1) { + error_msg("currently only a common order_start is supported in superset"); + } + return; + } + + if (!(s = next_token())) { + s = str_forward; /* if no args */ + } + + if (*s == '<') { /* section (script) */ + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + e[1] = 0; /* cleanup in case next_token stored something */ + + if (!(l = find_section_list_item(s, cur_col))) { + error_msg("ref of undefined sections: %s", s); + } + sect = (section_t *)(l->data); + if (sect->num_rules) { + error_msg("sections already defined: %s", s); + } + } else { + error_msg("illegal section ref: %s", s); + } + + if (!(s = next_token())) { + s = str_forward; /* if no args */ + } else if (*s != ';') { + error_msg("missing seperator!"); + } + } else { /* need an anonymous section */ + if ((*cur_section->name != '<') && (cur_section->num_items == 0)) { /* already in an empty anonymous section */ + sect = cur_section; +/* fprintf(stdout, "using empty anon section %s\n", sect->name); */ + } else { + sect = new_section(NULL); + l = find_ll_last(cur_col->section_list); + insque(new_ll_item(DT_SECTION, sect), l); +/* fprintf(stdout, "adding order section after section %s\n", ((section_t *)(l->data))->name); */ +/* fprintf(stdout, " last section is %s\n", ((section_t *)(l->next->data))->name); */ + } + sect->num_rules = 0; /* setting this below so nix default */ + } + cur_section = sect; +/* fprintf(stdout, "cur_section now %s\n", cur_section->name); */ + +#warning need to add section to weight list? + + /* now do rules */ + do { + rule = 0; + if (*s == ';') { + ++s; + } + while (*s) { + if (!strncmp(str_forward, s, 7)) { + rule |= R_FORWARD; + s += 7; + } else if (!strncmp(str_backward, s, 8)) { + rule |= R_BACKWARD; + s += 8; + } else if (!strncmp(str_position, s, 8)) { + rule |= R_POSITION; + s += 8; + } + + if (*s == ',') { + ++s; + continue; + } + + if (!*s || (*s == ';')) { + if (sect->num_rules >= MAX_COLLATION_WEIGHTS) { + error_msg("more than %d weight rules!", MAX_COLLATION_WEIGHTS); + } + if (!rule) { + error_msg("missing weight rule!"); + } + if ((rule & (R_FORWARD|R_BACKWARD|R_POSITION)) > R_BACKWARD) { + error_msg("backward paired with forward and/or position!"); + } + + sect->rules[sect->num_rules++] = rule; + rule = 0; + continue; + } + + error_msg("illegal weight rule: %s", s); + } + } while ((s = next_token()) != NULL); + + cur_section = sect; + +/* verbose_msg(VDETAIL, "setting cur_num_weights to %d for %s\n", sect->num_rules, sect->name); */ + cur_num_weights = sect->num_rules; + memcpy(cur_rule, sect->rules, MAX_COLLATION_WEIGHTS); +} + +static void do_order_end(void) +{ + if (!(order_state & IN_ORDER)) { + error_msg("order_end with no matching order_start"); + } + order_state &= ~IN_ORDER; + + cur_section = new_section(NULL); +} + +static void do_reorder_after(void) +{ + char *t; + ll_item_t *lli; + const weight_t *w; + int save_cur_num_weights; + char save_cur_rule[MAX_COLLATION_WEIGHTS]; + + + if (order_state & ~IN_REORDER) { + error_msg("reorder_after following order_start or reorder_sections_after"); + } + order_state |= IN_REORDER; + + if (superset) { + error_msg("currently reorder_after is not supported in supersets"); + } + +#warning have to use rule for current section!!! + + if (!(t = next_token())) { + error_msg("missing arg for reorder_after"); + } + + t = xsymdup(t); + + if (next_token() != NULL) { + error_msg("trailing text reorder_after: %s", pos); + } + + if (cur_col == cur_base) { + error_msg("sorry.. reorder_after in base locale is not currently supported"); + } + + if (!(lli = find_wi_index(t, cur_base))) { + error_msg("reorder_after for non-base item currently not supported: %s", t); + } + + w = ((weighted_item_t *)(lli->data))->weight; + + + save_cur_num_weights = cur_num_weights; + memcpy(save_cur_rule, cur_rule, MAX_COLLATION_WEIGHTS); + + cur_section = new_section("R"); + insque(new_ll_item(DT_REORDER, cur_section), lli); + +#if 0 + + { + ll_item_t *l1; + ll_item_t *l2; + ll_item_t *l3; + l1 = new_ll_item(DT_REORDER, cur_section); + l2 = find_ll_last(cur_col->section_list); + insque(l1, l2); + l3 = find_ll_last(cur_col->section_list); + + verbose_msg(VDETAIL, "reorder_after %p %p %p %s\n", l1, l2, l3, cur_section->name); + } +#else + insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list)); +#endif + + cur_num_weights = cur_section->num_rules = save_cur_num_weights; + memcpy(cur_rule, save_cur_rule, MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, save_cur_rule, MAX_COLLATION_WEIGHTS); + + +#warning devel code +/* verbose_msg(VDETAIL, "reorder -- %s %d\n", ((weighted_item_t *)(lli->data))->symbol, w->num_weights); */ + +#warning hack to get around hu_HU reorder-after problem +/* if (!w->num_weights) { */ + +/* } else { */ +/* cur_num_weights = w->num_weights; */ +/* memcpy(cur_rule, w->rule, MAX_COLLATION_WEIGHTS); */ +/* } */ + +/* verbose_msg(VDETAIL, "reorder_after succeeded for %s\n", t); */ +} + +static void do_reorder_end(void) +{ + if (!(order_state & IN_REORDER)) { + error_msg("reorder_end with no matching reorder_after"); + } + order_state &= ~IN_REORDER; +} + +static void do_reorder_sections_after(void) +{ + const char *t; + ll_item_t *lli; + + if (order_state & ~IN_REORDER_SECTIONS) { + error_msg("reorder_sections_after following order_start or reorder_after"); + } + order_state |= IN_REORDER_SECTIONS; + + if (superset) { + error_msg("currently reorder_sections_after is not supported in supersets"); + } + + if (!(t = next_token())) { + error_msg("missing arg for reorder_sections_after"); + } + + t = xsymdup(t); + + if (next_token() != NULL) { + error_msg("trailing text reorder_sections_after: %s", pos); + } + + if (cur_col == cur_base) { + error_msg("sorry.. reorder_sections_after in base locale is not currently supported"); + } + + lli = cur_base->section_list; + do { +/* verbose_msg(VDETAIL, "hmm -- |%s|%d|\n", ((section_t *)(lli->data))->name, lli->data_type); */ + if (lli->data_type & DT_SECTION) { +/* verbose_msg(VDETAIL, "checking |%s|%s|\n", ((section_t *)(lli->data))->name, t); */ + if (!strcmp(((section_t *)(lli->data))->name, t)) { + reorder_section_ptr = lli; + return; + } + } + lli = lli->next; + } while (lli); + + error_msg("reorder_sections_after for non-base item currently not supported: %s", t); +} + +static void do_reorder_sections_end(void) +{ + if (!(order_state & IN_REORDER_SECTIONS)) { + error_msg("reorder_sections_end with no matching reorder_sections_after"); + } + order_state &= ~IN_REORDER_SECTIONS; + + reorder_section_ptr = NULL; +} + +static ll_item_t *new_ll_item(int data_type, void *data) +{ + ll_item_t *p; + + p = xmalloc(sizeof(ll_item_t)); + p->next = p->prev = NULL; + p->data_type = data_type; + p->data = data; + p->idx = INT_MIN; + + return p; +} + +static int sym_cmp(const void *n1, const void *n2) +{ +/* verbose_msg(VDETAIL, "sym_cmp: |%s| |%s|\n", (const char *)n1, (const char *)n2); */ + return strcmp((const char *) n1, (const char *) n2); +} + +static char *xsymdup(const char *s) +{ + void *p; + + if (!(p = tfind(s, &root_sym, sym_cmp))) { /* not a currently known symbol */ + if (!(s = strdup(s)) || !(p = tsearch(s, &root_sym, sym_cmp))) { + error_msg("OUT OF MEMORY!"); + } + ++num_sym; + mem_sym += strlen(s) + 1; +/* verbose_msg(VDETAIL, "xsymdup: alloc |%s| %p |%s| %p\n", *(char **)p, p, s, s); */ +/* } else { */ +/* verbose_msg(VDETAIL, "xsymdup: found |%s| %p\n", *(char **)p, p); */ + } + return *(char **) p; +} + +static int weight_cmp(const void *n1, const void *n2) +{ + const weight_t *w1 = (const weight_t *) n1; + const weight_t *w2 = (const weight_t *) n2; + int i, r; + + if (w1->num_weights != w2->num_weights) { + return w1->num_weights - w2->num_weights; + } + + for (i=0 ; i < w1->num_weights ; i++) { + if (w1->rule[i] != w2->rule[i]) { + return w1->rule[i] - w2->rule[i]; + } + if ((r = strcmp(w1->colitem[i], w2->colitem[i])) != 0) { + return r; + } + } + return 0; +} + +static weight_t *register_weight(weight_t *w) +{ + void *p; + + if (!(p = tfind(w, &root_weight, weight_cmp))) { /* new weight */ + p = xmalloc(sizeof(weight_t)); + memcpy(p, w, sizeof(weight_t)); + if (!(p = tsearch(p, &root_weight, weight_cmp))) { + error_msg("OUT OF MEMORY!"); + } + ++unique_weights; +/* } else { */ +/* verbose_msg(VDETAIL, "rw: found\n"); */ + } + return *(weight_t **)p; +} + +static size_t ll_len(ll_item_t *l) +{ + size_t n = 0; + ll_item_t *p = l; + + while (p) { + ++n; + p = p->next; + if (p == l) { /* work for circular too */ + break; + } + } + return n; +} + +static size_t ll_count(ll_item_t *l, int mask) +{ + size_t n = 0; + ll_item_t *p = l; + + while (p) { + if (p->data_type & mask) { + ++n; + } + p = p->next; + if (p == l) { /* work for circular too */ + break; + } + } + return n; +} + + +static int wi_index_cmp(const void *n1, const void *n2) +{ + const char *s1 = ((weighted_item_t *)(((ll_item_t *) n1)->data))->symbol; + const char *s2 = ((weighted_item_t *)(((ll_item_t *) n2)->data))->symbol; + + return strcmp(s1, s2); +} + +static void add_wi_index(ll_item_t *l) +{ + assert(l->data_type == DT_WEIGHTED); + + if (!strcmp(((weighted_item_t *)(l->data))->symbol, "UNDEFINED")) { + cur_col->undefined_idx = l; + } + + if (!tfind(l, &cur_col->root_wi_index, wi_index_cmp)) { /* new wi_index */ + if (!tsearch(l, &cur_col->root_wi_index, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } + + if (cur_base != cur_col) { + if (!tfind(l, &cur_base->root_wi_index, wi_index_cmp)) {/* not a base val */ +/* printf("derived: %s\n", ((weighted_item_t *)(l->data))->symbol); */ + if (!tfind(l, &cur_base->root_derived_wi, wi_index_cmp)) { /* new derived */ + if (!tsearch(l, &cur_base->root_derived_wi, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } + } + } +} + +static int final_index; + + +static int is_ucode(const char *s) +{ + if ((s[0] == '<') + && (s[1] == 'U') + && isxdigit(s[2]) + && isxdigit(s[3]) + && isxdigit(s[4]) + && isxdigit(s[5]) + && (s[6] == '>') + ) { + return 7; + } else { + return 0; + } +} + +static void add_final_col_index(const char *s) +{ + ENTRY e; + + e.key = (char *) s; + e.data = (void *)(final_index); + if (!hsearch(e, FIND)) { /* not in the table */ + if (!hsearch(e, ENTER)) { + error_msg("OUT OF MEMORY! (hsearch)"); + } +#if 0 + { + int n; + void *v; + colitem_t ci; + colitem_t *p; + const char *t; + + if (!strcmp(s, "UNDEFINED")) { + printf("%6d: %s\n", final_index, s); + } else { + assert(*s == '<'); + if ((n = is_ucode(s)) != 0) { + assert(!s[n]); + printf("%6d: %s\n", final_index, s); + } else { + ci.string = (char *) s; + ci.element = NULL; /* don't care */ + v = tfind(&ci, &cur_base->root_colitem, colitem_cmp); + if (!v) { + verbose_msg(VDETAIL, "%s NOT DEFINED!!!\n", s); + } else { + p = *((colitem_t **) v); + if (p->element != NULL) { + t = p->element; + assert(*t == '"'); + ++t; + n = is_ucode(t); + assert(n); + printf("%6d: %.*s | ", final_index, n, t); + do { + t += n; + assert(*t); + if (*t == '"') { + assert(!t[1]); + break; + } + n = is_ucode(t); + assert(n); + printf("%.*s", n, t); + } while (1); + printf(" collating-element %s\n", s); + } else { + printf("%6d: %s (collating-symbol)\n", final_index, s); + } + } + } + } + } +#endif + ++final_index; + } + +} + +static int final_index_val0(const char *s) +{ + ENTRY *p; + ENTRY e; + e.key = (char *) s; + + if (!(p = hsearch(e, FIND))) { /* not in the table */ + return 0; + } + + return (int)(p->data); +} + +static int final_index_val(const char *s) +{ + ENTRY *p; + ENTRY e; + e.key = (char *) s; + + if (!(p = hsearch(e, FIND))) { /* not in the table */ + error_msg("can't find final index: %s", s); + } + + return (int)(p->data); +} + +static size_t num_tree_nodes; + +static void count_nodes(const void *ptr, VISIT order, int level) +{ + if ((order == postorder) || (order == leaf)) { + ++num_tree_nodes; + } +} + +static size_t tnumnodes(const void *root) +{ + num_tree_nodes = 0; + + twalk(root, count_nodes); + + return num_tree_nodes; + +} + +static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl) +{ + weighted_item_t w; + ll_item_t l; + void *p; + + w.symbol = sym; + l.data = &w; + l.data_type = DT_WEIGHTED; + + p = tfind(&l, &cl->root_wi_index, wi_index_cmp); + + if (p) { + p = *(ll_item_t **)p; + } + + return (ll_item_t *) p; +} + +static void mark_reordered(const char *sym) +{ + ll_item_t *lli; + + lli = find_wi_index(sym, cur_base); + + if (lli) { + if (!tsearch(lli, &cur_base->root_wi_index_reordered, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } +} + +static ll_item_t *find_wi_index_reordered(const char *sym) +{ + weighted_item_t w; + ll_item_t l; + void *p; + + w.symbol = sym; + l.data = &w; + l.data_type = DT_WEIGHTED; + + p = tfind(&l, &cur_base->root_wi_index_reordered, wi_index_cmp); + + if (p) { + p = *(ll_item_t **)p; + } + + return (ll_item_t *) p; +} + +static ll_item_t *init_comm_ptr(void) +{ + assert(cur_base); + assert(cur_base->section_list); + /* at the moment, only support one section in comm */ + assert(cur_base->section_list->next == NULL); + + comm_cur_ptr = ((section_t *)(cur_base->section_list->data))->itm_list; + + while (comm_cur_ptr && (comm_cur_ptr->data_type & DT_REORDER)) { + comm_cur_ptr = comm_cur_ptr->next; + } + +#warning devel code +/* { */ +/* ll_item_t *p = comm_cur_ptr; */ +/* verbose_msg(VDETAIL, "init_comm_ptr\n"); */ + +/* while (p != comm_cur_ptr) { */ +/* if (p->data_type & DT_WEIGHTED) { */ +/* verbose_msg(VDETAIL, "%s", ((weighted_item_t *)p)->symbol); */ +/* } */ +/* p = p->next; */ +/* } */ +/* } */ + + assert(comm_cur_ptr); + +/* verbose_msg(VDETAIL, "init_comm_ptr -- %s %p %p %p %d\n", */ +/* ((weighted_item_t *)(comm_cur_ptr->data))->symbol, */ +/* comm_cur_ptr, comm_cur_ptr->prev, comm_cur_ptr->next, */ +/* ll_len(comm_cur_ptr)); */ + + comm_prev_ptr = NULL; + return comm_cur_ptr; +} + +static ll_item_t *next_comm_ptr(void) +{ + /* at the moment, only support one section in comm */ + assert(cur_base->section_list->next == NULL); + + comm_prev_ptr = comm_cur_ptr; + + while (comm_cur_ptr && ((comm_cur_ptr = comm_cur_ptr->next) != NULL)) { + if (!(comm_cur_ptr->data_type & DT_REORDER)) { + break; + } + } + + return comm_cur_ptr; +} + +static int dump_count; + +#if 0 +static void dump_section(section_t *s, int mask, col_locale_t *der) +{ + ll_item_t *lli; + ll_item_t *lli0; + weighted_item_t *w; + weight_t *p; + int i; + + lli0 = lli = s->itm_list; + + if (!lli0) { + return; + } + + do { + if (!(lli->data_type & mask)) { + lli = lli->next; + continue; + } + if (lli->data_type & DT_WEIGHTED) { + ++dump_count; + w = (weighted_item_t *)(lli->data); + p = w->weight; + printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); + } else if (lli->data_type & (DT_SECTION|DT_REORDER)) { + + if (lli->data_type == DT_REORDER) { + assert(der); + if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) { + lli = lli->next; + continue; + } + } + + if (lli->data_type & DT_SECTION) { + printf("SECTION -----------------\n"); + } else { + printf("REORDER -----------------\n"); + } + + dump_section((section_t *)(lli->data), mask, der); + printf("DONE --------------------\n"); + } + lli = lli->next; + } while (lli != lli0); +} +#else +static int in_reorder_section = 0; + +static void dump_section(section_t *s, int mask, col_locale_t *der) +{ + ll_item_t *lli; + ll_item_t *lli0; + weighted_item_t *w; + weight_t *p; + int i; + + lli0 = lli = s->itm_list; + + if (!lli0) { + return; + } + + do { + if (!(lli->data_type & mask)) { + lli = lli->next; + continue; + } + if (lli->data_type & DT_WEIGHTED) { + ++dump_count; + w = (weighted_item_t *)(lli->data); + p = w->weight; +#if 1 + if (in_reorder_section) { + printf(" %p", w); + } +#else + printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); +#endif + } else if (lli->data_type & (DT_SECTION|DT_REORDER)) { + + if (lli->data_type == DT_REORDER) { + assert(der); + if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) { + lli = lli->next; + continue; + } + } + + if (lli->data_type & DT_SECTION) { +/* printf("SECTION -----------------\n"); */ + assert(0); + } else { +/* printf("REORDER -----------------\n"); */ + in_reorder_section = 1; + } + + dump_section((section_t *)(lli->data), mask, der); +/* printf("DONE --------------------\n"); */ + printf("\n"); + in_reorder_section = 0; + } + lli = lli->next; + } while (lli != lli0); +} +#endif + +static void dump_weights(const char *name) +{ + ll_item_t *lli; + col_locale_t *base; + col_locale_t *der; + col_locale_t cl; + void *p; + + assert(name); + + if (!*name) { /* use last */ + base = cur_base; + der = cur_derived; + } else { + cl.name = (char *) name; + if (!(p = tfind(&cl, &root_col_locale, col_locale_cmp))) { + error_msg("unknown locale: %s", name); + } + base = *((col_locale_t **) p); + der = NULL; + if (base->base_locale) { /* oops... really derived */ + der = base; + base = der->base_locale; + } + } + + dump_count = 0; + + if (base) { +/* printf("BASE - %s\n", base->name); */ + for (lli = base->section_list ; lli ; lli = lli->next) { +/* printf("SECTION %s\n", ((section_t *)(lli->data))->name); */ + dump_section((section_t *)(lli->data), ~0, der); + } + } + + assert(der != base); + + if (der) { +/* printf("DERIVED - %s\n", der->name); */ + for (lli = der->section_list ; lli ; lli = lli->next) { + if (lli->data_type == DT_SECTION) { + dump_section((section_t *)(lli->data), DT_WEIGHTED, der); + } + } + } +/* printf("DONE\n"); */ +} + +static void print_starter_node(const void *ptr, VISIT order, int level) +{ + if (order == postorder || order == leaf) { + fprintf(stderr, " %s\n", *(const char **) ptr); + } +} + +static void finalize_base(void) +{ + ll_item_t *s; + ll_item_t *h; + ll_item_t *lli; + ll_item_t *h2; + ll_item_t *l2; + ll_item_t *cli; + ll_item_t *rli = NULL; + weighted_item_t *w; + weight_t *p; + int i, n, mr, r, mi; + col_locale_t *cl; + void *mm; + + int num_invariant = 0; + int num_varying = 0; + int max_weight; + int index2weight_len_inc = 1; + + assert(cur_base); + assert(base_locale_len+1 < BASE_LOCALE_LEN); + + base_locale_array[base_locale_len].name = cur_base->name; + base_locale_array[base_locale_len].num_weights = 1; + base_locale_array[base_locale_len].index2weight_offset = index2weight_len; + base_locale_array[base_locale_len].index2ruleidx_offset = index2ruleidx_len; + if (!strcmp(cur_base->name,"ja_JP") || !strcmp(cur_base->name,"ko_KR")) { +#warning fix the index2weight check!! + index2weight_len_inc = 0; + } +/* printf("%s -- index2weight_len = %d\n", cur_base->name, index2weight_len); */ + + if (!hcreate(30000)) { + error_msg("OUT OF MEMORY!"); + } + + /* first pass ... set the fixed indexes */ + final_index = i = 1; + mr = 0; + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { /* a reordered section */ + verbose_msg(VDETAIL, "pass1: reordered section %s - xxx\n", ((section_t *)(s->data))->name); + lli = ((section_t *)(s->data))->itm_list; + r = 0; + if (lli) { +/* r = ll_len( ((section_t *)(lli->data))->itm_list ); */ + r = ll_len(lli) + 1; + } + if (r > mr) { + mr = r; + } + verbose_msg(VDETAIL, "pass1: reordered section %s - %d\n", ((section_t *)(s->data))->name, r); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_RANGE) { + i += mr; + mr = 0; +#warning check ko_kR and 9 +/* ++i; */ + lli->idx = i; + assert(!rli); + rli = lli; + verbose_msg(VDETAIL, "range pre = %d after = ", i); + i += ((range_item_t *)(lli->data))->length + 1; +#warning check ko_kR and 9 +/* ++i; */ + verbose_msg(VDETAIL, "%d\n", i); + if (!index2weight_len_inc) { /* ko_KR hack */ + final_index += ((range_item_t *)(lli->data))->length + 1; + } +/* add_final_col_index("RANGE"); */ + } else if (lli->data_type & DT_WEIGHTED) { + i += mr; + mr = 0; + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + ++num_varying; + ++i; + continue; + } + ++num_invariant; + index2weight_buffer[index2weight_len] = lli->idx = i++; + index2weight_len += index2weight_len_inc; + add_final_col_index(w->symbol); + + } else { + assert(lli->data_type & DT_REORDER); + r = ll_len( ((section_t *)(lli->data))->itm_list ); +#warning check ko_kR and 9 + if (r > mr) { + mr = r; + } +/* r = 0; */ + } + } while ((lli = lli->next) != h); + } + + /* second pass ... set the reordered indexes */ + mi = i + mr; + mr = i = 0; + for (s = cur_base->section_list ; s ; s = s->next) { + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_RANGE) { + i += mr; + mr = 0; + i = lli->idx + ((range_item_t *)(lli->data))->length + 1; +#warning check + } else if ((lli->data_type & DT_WEIGHTED) && !(s->data_type & DT_REORDER)) { + i += mr; + mr = 0; + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol) /* reordered symbol skipped on first pass */ +#if 0 + || (s->data_type & DT_REORDER) /* or in a reordered section */ +#endif + ) { + assert(!(s->data_type & DT_REORDER)); + index2weight_buffer[index2weight_len] = lli->idx = ++i; + index2weight_len += index2weight_len_inc; + add_final_col_index(w->symbol); + +/* fprintf(stdout, "%11s: r %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + + continue; + } + i = lli->idx; + +/* fprintf(stdout, "%11s: w %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + + } else { +/* verbose_msg(VDETAIL, "section: %s %d %d\n", ((section_t *)(s->data))->name, */ +/* s->data_type, lli->data_type); */ +/* assert(!(s->data_type & DT_REORDER)); */ +/* assert(lli->data_type & DT_REORDER); */ +#if 1 + if (s->data_type & DT_REORDER) { + h2 = l2 = lli; + if (!h2) { + continue; + } + } else { + assert(s->data_type & DT_SECTION); + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } + } + + +#else + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } +#endif + r = 0; + do { + assert(l2->data_type & DT_WEIGHTED); + ++r; + l2->idx = i + r; + +/* fprintf(stdout, "%s: R %6d %s\n", */ +/* ((section_t *)(lli->data))->name, l2->idx, ((weighted_item_t *)(l2->data))->symbol); */ + + } while ((l2 = l2->next) != h2); + if (r > mr) { + mr = r; + } + } + } while ((lli = lli->next) != h); + } + + /* finally, walk through all derived locales and set non-reordered section items */ + mr = mi; + for (cli = cur_base->derived_list ; cli ; cli = cli->next) { + cl = (col_locale_t *)(cli->data); +/* verbose_msg(VDETAIL, "pass3: %d %s\n", cli->data_type, cl->name); */ + +/* fprintf(stdout, "pass3: %d %s\n", cli->data_type, cl->name); */ + + assert(cli->data_type == DT_COL_LOCALE); + + i = mi; + for (s = cl->section_list ; s ; s = s->next) { +/* if (s->data_type & DT_REORDER) { */ +/* continue; */ +/* } */ + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + assert(!(lli->data_type & DT_RANGE)); + if (lli->data_type & DT_WEIGHTED) { +/* verbose_msg(VDETAIL, " %d %d %s\n", lli->data_type, lli->idx, ((weighted_item_t *)(lli->data))->symbol); */ + add_final_col_index(((weighted_item_t *)(lli->data))->symbol); + if (s->data_type & DT_REORDER) { + continue; + } + assert(lli->idx == INT_MIN); + lli->idx = ++i; + +/* fprintf(stdout, "%11s: S %6d %6d %s\n", */ +/* cl->name, lli->idx, */ +/* final_index_val(((weighted_item_t *)(lli->data))->symbol), */ +/* ((weighted_item_t *)(lli->data))->symbol); */ + + } else { + assert(0); + assert(lli->data_type & DT_SECTION); + + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } + do { + assert(l2->data_type & DT_WEIGHTED); + assert(l2->idx == INT_MIN); + l2->idx = ++i; + add_final_col_index(((weighted_item_t *)(l2->data))->symbol); + } while ((l2 = l2->next) != h2); + } + } while ((lli = lli->next) != h); + } + if (i > mr) { + mr = i; + } + } + max_weight = mr; + + assert(num_varying == tnumnodes(cur_base->root_wi_index_reordered)); + + /* we can now initialize the wcs2index array */ + { + ENTRY *p; + ENTRY e; + char buf[8]; + static const char xd[] = "0123456789ABCDEF"; + int starter_index = final_index; + int wcs2index_count = 0; + + strcpy(buf, ""); + memset(wcs2index, 0, sizeof(wcs2index)); + e.key = (char *) buf; + for (i=1 ; i <= 0xffff ; i++) { + buf[5] = xd[ i & 0xf ]; + buf[4] = xd[ (i >> 4) & 0xf ]; + buf[3] = xd[ (i >> 8) & 0xf ]; + buf[2] = xd[ (i >> 12) & 0xf ]; + + if ((p = hsearch(e, FIND)) != NULL) { + ++wcs2index_count; + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { + wcs2index[i] = ++starter_index; +/* verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d (starter)\n", i, wcs2index[i]); */ + } else { + wcs2index[i] = (int)(p->data); +/* verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d\n", i, wcs2index[i]); */ + } + } else { + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { + error_msg("marked starter but not in hash: %s", buf); + } + } + } + + + /* ---------------------------------------------------------------------- */ + { + int i, n; + table_data table; + size_t t, smallest; + + n = 0; + smallest = SIZE_MAX; + table.ii = NULL; + for (i=0 ; i < 14 ; i++) { + if ((RANGE >> i) < 4) { + break; + } + t = newopt(wcs2index, RANGE, i, &table); + if (smallest >= t) { + n = i; + smallest = t; + /* } else { */ + /* break; */ + } + } + + +/* printf("smallest = %u for range %#x (%u)\n", smallest, RANGE, RANGE); */ + assert(smallest != SIZE_MAX); + if (smallest + wcs2colidt_len >= WCS2COLIDT_LEN) { + error_msg("WCS2COLIDT_LEN too small"); + } + base_locale_array[base_locale_len].wcs2colidt_offset = wcs2colidt_len; + table.ii = wcs2colidt_buffer + wcs2colidt_len; + t = smallest; + smallest = SIZE_MAX; + smallest = newopt(wcs2index, RANGE, n, &table); + assert(t == smallest); + wcs2colidt_len += smallest; +/* verbose_msg(VDETAIL, "smallest = %d wcs2colidt_len = %d\n", smallest, wcs2colidt_len); */ + +#if 0 + { + unsigned int sc, n, i0, i1; + unsigned int u = 0xe40; + table_data *tbl = &table; + +#define __LOCALE_DATA_WCctype_TI_MASK ((1 << tbl->ti_shift)-1) +#define __LOCALE_DATA_WCctype_TI_SHIFT (tbl->ti_shift) +#define __LOCALE_DATA_WCctype_TI_LEN (tbl->ti_len) +#define __LOCALE_DATA_WCctype_II_MASK ((1 << tbl->ii_shift)-1) +#define __LOCALE_DATA_WCctype_II_SHIFT (tbl->ii_shift) +#define __LOCALE_DATA_WCctype_II_LEN (tbl->ii_len) + + sc = u & __LOCALE_DATA_WCctype_TI_MASK; + u >>= __LOCALE_DATA_WCctype_TI_SHIFT; + n = u & __LOCALE_DATA_WCctype_II_MASK; + u >>= __LOCALE_DATA_WCctype_II_SHIFT; + + i0 = tbl->ii[u]; + verbose_msg(VDETAIL, "i0 = %d\n", i0); + i0 <<= __LOCALE_DATA_WCctype_II_SHIFT; + i1 = tbl->ii[__LOCALE_DATA_WCctype_II_LEN + i0 + n]; + /* i1 = tbl->ti[i0 + n]; */ + verbose_msg(VDETAIL, "i1 = %d\n", i1); + i1 <<= __LOCALE_DATA_WCctype_TI_SHIFT; + /* return *(uint16_t *)(&(tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc])); */ + verbose_msg(VDETAIL, "i2 = %d\n", __LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc); + verbose_msg(VDETAIL, "val = %d\n", tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc]); + /* return tbl->ut[i1 + sc]; */ + + + } +#endif + base_locale_array[base_locale_len].ii_shift = table.ii_shift; + base_locale_array[base_locale_len].ti_shift = table.ti_shift; + base_locale_array[base_locale_len].ii_len = table.ii_len; + base_locale_array[base_locale_len].ti_len = table.ti_len; + } + /* ---------------------------------------------------------------------- */ + + base_locale_array[base_locale_len].num_col_base = num_invariant + num_varying; + base_locale_array[base_locale_len].max_col_index = final_index; + base_locale_array[base_locale_len].max_weight = max_weight; + + verbose_msg(VDETAIL, "%s: %6u invariant %6u varying %6u derived %6u total %6u max weight %6u wcs2\n", + cur_base->name, num_invariant, num_varying, + tnumnodes(cur_base->root_derived_wi), final_index, max_weight, + wcs2index_count); + + } + +#if 1 + /* ok, now we need to dump out the base and derived tables... */ + /* don't forget to break up collating elements!!! */ + +/* fprintf(stdout, "**************************************************\n"); */ + /* first pass ... set the invariants */ + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { + verbose_msg(VDETAIL, "1: skipping reordered section %s\n", ((section_t *)(s->data))->name); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + continue; + } + if (index2weight_len_inc) { + index2ruleidx_buffer[index2ruleidx_len++] = + add_rule((weighted_item_t *)(lli->data)); + } +/* fprintf(stdout, "%11s: w %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + } + } while ((lli = lli->next) != h); + } + + /* second pass ... set varying */ + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { + verbose_msg(VDETAIL, "2: skipping reordered section %s\n", ((section_t *)(s->data))->name); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + if (index2weight_len_inc) { + index2ruleidx_buffer[index2ruleidx_len++] = + add_rule((weighted_item_t *)(lli->data)); + } +/* fprintf(stdout, "%11s: r %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + continue; + } + } + } while ((lli = lli->next) != h); + } + + do_starter_lists(cur_base); + + +/* verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */ + + if (rli) { + base_locale_array[base_locale_len].range_low + = strtoul(((range_item_t *)(rli->data))->symbol1 + 2, NULL, 16); + base_locale_array[base_locale_len].range_count + = ((range_item_t *)(rli->data))->length; + base_locale_array[base_locale_len].range_base_weight = rli->idx; + base_locale_array[base_locale_len].range_rule_offset = add_range_rule((range_item_t *)(rli->data)); +/* fprintf(stdout, "%11s: %6d %6d %s %s (%d)\n", */ +/* "RANGE", rli->idx, -1, */ +/* ((range_item_t *)(rli->data))->symbol1, */ +/* ((range_item_t *)(rli->data))->symbol2, */ +/* ((range_item_t *)(rli->data))->length); */ + } + +/* fprintf(stdout,"\nDerived\n\n"); */ + + /* first, if base name is of the form ll_CC, add a derived locale for it */ + if ((strlen(cur_base->name) == 5) + && islower(cur_base->name[0]) + && islower(cur_base->name[1]) + && (cur_base->name[2] == '_') + && isupper(cur_base->name[3]) + && isupper(cur_base->name[4]) + ) { + + verbose_msg(VDETAIL, "adding special derived for %s\n", cur_base->name); +/* verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */ + + + assert(der_locale_len+1 < DER_LOCALE_LEN); + + der_locale_array[der_locale_len].name = cur_base->name; + der_locale_array[der_locale_len].base_idx = base_locale_len; + + u16_buf[0] = 1; + u16_buf[1] = 0; + u16_buf_len = 2; + + mm = NULL; + if ((u16_buf_len > override_len) || + !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(override_len + u16_buf_len < OVERRIDE_LEN); + memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + der_locale_array[der_locale_len].overrides_offset = override_len; + override_len += u16_buf_len; +/* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */ + } else if (!(u16_buf_len > override_len)) { + assert(mm); + der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer; +/* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + der_locale_array[der_locale_len].multistart_offset + = base_locale_array[base_locale_len].multistart_offset; + der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED"); + + if (!der_locale_array[der_locale_len].undefined_idx) { + error_msg("no UNDEFINED definition for %s", cur_base->name); + } + + ++der_locale_len; + } else { + verbose_msg(VDETAIL, "NOT adding special derived for %s\n", cur_base->name); + } + + /* now all the derived... */ + for (cli = cur_base->derived_list ; cli ; cli = cli->next) { + cl = (col_locale_t *)(cli->data); + assert(cli->data_type == DT_COL_LOCALE); + + assert(der_locale_len+1 < DER_LOCALE_LEN); + + der_locale_array[der_locale_len].name = cl->name; + der_locale_array[der_locale_len].base_idx = base_locale_len; + + u16_buf_len = 0; + + for (i = 0 ; i < 2 ; i++) { + if (i) { +/* fprintf(stdout, " section --- (singles)\n"); */ + u16_buf[u16_buf_len++] = 1; /* single */ + } + /* we do this in two passes... first all sequences, then all single reorders */ + for (s = cl->section_list ; s ; s = s->next) { +/* verbose_msg(VDETAIL, "doing section %s\n", ((section_t *)(s->data))->name); */ + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { +/* fprintf(stdout, "EMPTY ITEM LIST IN SECTION %s\n", ((section_t *)(s->data))->name ); */ + continue; + } + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + if ((!i && (ll_len(h) > 1) ) || (ll_len(h) == i)) { + if (!i) { +/* fprintf(stdout, " section ----------------- %d %d\n", i, ll_len(h)); */ + u16_buf[u16_buf_len++] = ll_len(h); /* multi */ + assert(lli->data_type & DT_WEIGHTED); +#if 0 + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); /* start index */ +#endif + u16_buf[u16_buf_len++] = lli->idx; /* start weight */ + } + do { + assert(lli->data_type & DT_WEIGHTED); + if (lli->data_type & DT_WEIGHTED) { +/* fprintf(stdout, "%11s: S %6d %6d %s\n", */ +/* cl->name, lli->idx, */ +/* final_index_val(((weighted_item_t *)(lli->data))->symbol), */ +/* ((weighted_item_t *)(lli->data))->symbol); */ +#if 0 + if (i) { + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); + assert(u16_buf[u16_buf_len-1]); + u16_buf[u16_buf_len++] = lli->idx; /* weight */ + } +#else + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); + assert(u16_buf[u16_buf_len-1]); + if (i) { + u16_buf[u16_buf_len++] = lli->idx; /* weight */ + } +#endif + u16_buf[u16_buf_len++] = add_rule((weighted_item_t *)(lli->data)); + + } + } while ((lli = lli->next) != h); + } + } + } + u16_buf[u16_buf_len++] = 0; + + mm = NULL; + if ((u16_buf_len > override_len) || + !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(override_len + u16_buf_len < OVERRIDE_LEN); + memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + der_locale_array[der_locale_len].overrides_offset = override_len; + override_len += u16_buf_len; +/* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */ + } else if (!(u16_buf_len > override_len)) { + assert(mm); + der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer; +/* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + + do_starter_lists(cl); + + der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED"); +#if 0 + assert(der_locale_array[der_locale_len].undefined_idx); + if (!der_locale_array[der_locale_len].undefined_idx) { + der_locale_array[der_locale_len].undefined_idx = base_locale_array[base_locale_len].undefined_idx; + } +#endif + + if (!der_locale_array[der_locale_len].undefined_idx) { + error_msg("no UNDEFINED definition for %s", cl->name); + } + + ++der_locale_len; + } + +#endif + +#warning handle UNDEFINED idx specially? what if in only some of derived? +/* base_locale_array[base_locale_len].undefined_idx = final_index_val0("UNDEFINED"); */ + base_locale_array[base_locale_len].undefined_idx = 0; + + + hdestroy(); + + ++base_locale_len; + +/* if (tnumnodes(cur_base->root_starter_char)) { */ +/* verbose_msg(VDETAIL, "starter nodes\n"); */ +/* twalk(cur_base->root_starter_char, print_starter_node); */ +/* } */ +} + +static int starter_all_cmp(const void *n1, const void *n2) +{ + const char *s1 = ((weighted_item_t *) n1)->symbol; + const char *s2 = ((weighted_item_t *) n2)->symbol; + colitem_t x; + colitem_t *p; + int n; + + /* sort by 1st char ... then inverse for string */ + + x.element = NULL; + if (!is_ucode(s1)) { + x.string = s1; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + s1 = (*((colitem_t **) p))->element + 1; + } + if (!is_ucode(s2)) { + x.string = s2; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + s2 = (*((colitem_t **) p))->element + 1; + } + + /* < */ + /* 01234567 */ + + assert(is_ucode(s1)); + assert(is_ucode(s2)); + + n = strncmp(s1+2, s2+2, 4); + if (n) { + return n; + } + + s1 += 7; + s2 += 7; + + return strcmp(s2, s1); +} + +static void print_starter_all_node(const void *ptr, VISIT order, int level) +{ + const weighted_item_t *w = *(const weighted_item_t **) ptr; + colitem_t *ci; + void *p; + int n; + colitem_t x; + + if (order == postorder || order == leaf) { +#if 0 + if ((n = is_ucode(w->symbol)) != 0) { + printf(" %s\n", w->symbol); + } else { + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + assert(p); + ci = *((colitem_t **) p); + printf("%s = %s\n", ci->element, w->symbol); + } +#else + printf("%s|", w->symbol); +/* if ((n = is_ucode(w->symbol)) != 0) { */ +/* printf("\n"); */ +/* } */ +#endif + } +} + +static void process_starter_node(const void *ptr, VISIT order, int level) +{ + const weighted_item_t *w = *(const weighted_item_t **) ptr; + colitem_t *ci; + void *p; + int n; + colitem_t x; + const char *s; + char buf[32]; + + /* store index of collation item followed by (unprefixed) nul-terminated string */ + if (order == postorder || order == leaf) { + if ((n = is_ucode(w->symbol)) != 0) { + u16_buf[u16_buf_len++] = final_index_val(w->symbol); + assert(u16_buf[u16_buf_len-1]); + u16_buf[u16_buf_len++] = 0; + if (++u16_starter < base_locale_array[base_locale_len].num_starters) { + u16_buf[u16_starter] = u16_buf_len; + } +/* verbose_msg(VDETAIL, "ucode - %d %d\n", u16_buf[u16_starter-1], u16_buf_len); */ + } else { + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + assert(p); + ci = *((colitem_t **) p); + s = ci->element; + u16_buf[u16_buf_len++] = final_index_val(w->symbol); + assert(u16_buf[u16_buf_len-1]); + assert(*s == '"'); + n = is_ucode(++s); +/* verbose_msg(VDETAIL, "s is |%s| with len %d (%d)\n", s, strlen(s), n); */ + assert(n); + s += n; + while (*s != '"') { + n = is_ucode(s); + assert(n); + strncpy(buf, s, n+1); + buf[n] = 0; +/* verbose_msg(VDETAIL, "buf is |%s| with len %d (%d)\n", buf, strlen(buf), n); */ + u16_buf[u16_buf_len++] = final_index_val(buf); + assert(u16_buf[u16_buf_len-1]); + s += n; + } + u16_buf[u16_buf_len++] = 0; + } + } +} + +static void **p_cl_root_starter_all; + +static void complete_starter_node(const void *ptr, VISIT order, int level) +{ + weighted_item_t w; + weighted_item_t *p; + + if (order == postorder || order == leaf) { + w.symbol = *(const char **) ptr; + w.weight = NULL; + if (!tfind(&w, p_cl_root_starter_all, starter_all_cmp)) { + p = xmalloc(sizeof(weighted_item_t)); + p->symbol = w.symbol; + p->weight = NULL; +/* verbose_msg(VDETAIL, "complete_starter_node: %s\n", *(const char **) ptr); */ + if (!tsearch(p, p_cl_root_starter_all, starter_all_cmp)) { + error_msg("OUT OF MEMORY"); + } + } + } +} + +static void do_starter_lists(col_locale_t *cl) +{ + ll_item_t *s; + ll_item_t *h; + ll_item_t *lli; + col_locale_t *c; + colitem_t *ci; + weighted_item_t *w; + void *p; + char buf[32]; + int n; + colitem_t x; + void *mm; + + c = cl; + if (c != cur_base) { + c = cur_base; + } + +/* printf("STARTERS %s --------------------\n", cl->name); */ + LOOP: + for (s = c->section_list ; s ; s = s->next) { + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + ci = NULL; + if ((n = is_ucode(w->symbol)) != 0) { + strcpy(buf, w->symbol); + } else { +/* fprintf(stdout, "looking for |%s|\n", w->symbol); */ + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + if (!p) { +/* verbose_msg(VDETAIL, "Whoa... processing starters for %s and couldn't find %s\n", */ +/* cl->name, w->symbol); */ + continue; + } + ci = *((colitem_t **) p); + if (!ci->element) { /* just a collating symbol */ + continue; + } + assert(ci->element[0] == '"'); + n = is_ucode(ci->element + 1); + assert(n); + strncpy(buf, ci->element + 1, n); + } + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { +/* fprintf(stdout, "adding from %s: %s", c->name, w->symbol); */ +/* if (ci) { */ +/* fprintf(stdout, " = %s", ci->element); */ +/* } */ +/* fprintf(stdout, "\n"); */ + + if (!tsearch(w, &cl->root_starter_all, starter_all_cmp)) { + error_msg("OUT OF MEMORY"); + } + } + } + } while ((lli = lli->next) != h); + } + + if (c != cl) { + c = cl; + goto LOOP; + } + + p_cl_root_starter_all = &cl->root_starter_all; + twalk(cur_base->root_starter_char, complete_starter_node); + + if (cl == cur_base) { + base_locale_array[base_locale_len].num_starters = tnumnodes(cur_base->root_starter_char); + } + +#if 0 + printf("\nNow walking tree...\n\n"); + twalk(cl->root_starter_all, print_starter_all_node); + printf("\n\n"); + +#endif + u16_starter = 0; + u16_buf[0] = u16_buf_len = base_locale_array[base_locale_len].num_starters; + twalk(cl->root_starter_all, process_starter_node); +/* verbose_msg(VDETAIL, "s=%d n=%d\n", u16_starter, base_locale_array[base_locale_len].num_starters); */ + assert(u16_starter == base_locale_array[base_locale_len].num_starters); + +#if 0 + { int i; + for (i=0 ; i < u16_buf_len ; i++) { + verbose_msg(VDETAIL, "starter %2d: %d - %#06x\n", i, u16_buf[i], u16_buf[i]); + }} +#endif + + mm = NULL; + if (u16_buf_len) { +/* assert(base_locale_array[base_locale_len].num_starters); */ + if ((u16_buf_len > multistart_len) || + !(mm = memmem(multistart_buffer, multistart_len*sizeof(multistart_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(multistart_len + u16_buf_len < MULTISTART_LEN); + memcpy(multistart_buffer + multistart_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + if (cl == cur_base) { + base_locale_array[base_locale_len].multistart_offset = multistart_len; + } else { + der_locale_array[der_locale_len].multistart_offset = multistart_len; + } + multistart_len += u16_buf_len; +/* verbose_msg(VDETAIL, "%s: multistart_len = %d u16_buf_len = %d\n", cl->name, multistart_len, u16_buf_len); */ + } else if (!(u16_buf_len > multistart_len)) { + assert(mm); + if (cl == cur_base) { + base_locale_array[base_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer; + } else { + der_locale_array[der_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer; + } +/* verbose_msg(VDETAIL, "%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + } else { + assert(!base_locale_array[base_locale_len].num_starters); + } + +/* printf("u16_buf_len = %d\n", u16_buf_len); */ + +/* printf("STARTERS %s DONE ---------------\n", cl->name); */ +} + + +/* For sorting the blocks of unsigned chars. */ +static size_t nu_val; + +int nu_memcmp(const void *a, const void *b) +{ + return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val * sizeof(tbl_item)); +} + + +size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl) +{ + static int recurse; + tbl_item *ti[RANGE]; /* table index */ + size_t numblocks; + size_t blocksize; + size_t uniq; + size_t i, j; + size_t smallest, t; + tbl_item *ii_save; + int uniqblock[1 << (8*sizeof(tbl_item) - 1)]; + tbl_item uit[RANGE]; + int shift2; + + if (shift > 15) { + return SIZE_MAX; + } + + ii_save = NULL; + blocksize = 1 << shift; + numblocks = usize >> shift; + + /* init table index */ + for (i=j=0 ; i < numblocks ; i++) { + ti[i] = ut + j; + j += blocksize; + } + + /* sort */ + nu_val = blocksize; + qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp); + + uniq = 1; + uit[(ti[0]-ut)/blocksize] = 0; + for (i=1 ; i < numblocks ; i++) { + if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) < 0) { + if (++uniq > (1 << (8*sizeof(tbl_item) - 1))) { + break; + } + uniqblock[uniq - 1] = i; + } +#if 1 + else if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) > 0) { + printf("bad sort %i!\n", i); + abort(); + } +#endif + uit[(ti[i]-ut)/blocksize] = uniq - 1; + } + + smallest = SIZE_MAX; + shift2 = -1; + if (uniq <= (1 << (8*sizeof(tbl_item) - 1))) { + smallest = numblocks + uniq * blocksize; + if (!recurse) { + ++recurse; + for (j=1 ; j < 14 ; j++) { + if ((numblocks >> j) < 2) break; + if (tbl) { + ii_save = tbl->ii; + tbl->ii = NULL; + } + if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) { + t += uniq * blocksize; + } + if (tbl) { + tbl->ii = ii_save; + } + if (smallest >= t) { + shift2 = j; + smallest = t; +/* if (!tbl->ii) { */ +/* printf("ishift %u tshift %u size %u\n", */ +/* shift2, shift, t); */ +/* } */ +/* } else { */ +/* break; */ + } + } + --recurse; + } + } else { + return SIZE_MAX; + } + + if (tbl->ii) { + if (recurse) { + tbl->ii_shift = shift; + tbl->ii_len = numblocks; + memcpy(tbl->ii, uit, numblocks*sizeof(tbl_item)); + tbl->ti = tbl->ii + tbl->ii_len; + tbl->ti_len = uniq * blocksize; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item)); + } + } else { + ++recurse; +/* printf("setting ishift %u tshift %u\n", shift2, shift); */ + newopt(uit, numblocks, shift2, tbl); + --recurse; + tbl->ti_shift = shift; + tbl->ut_len = uniq * blocksize; + tbl->ut = tbl->ti + tbl->ti_len; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item)); + } + } + } + return smallest; +} + +static const int rule2val[8] = { + -1, + (1 << 14), /* forward */ + (2 << 14), /* position */ + (3 << 14), /* forward,position */ + 0, /* backward */ + -1, + -1, + -1, +}; + + +static int final_index_val_x(const char *s, const char *sym) +{ + int r; + + if (!(r = final_index_val0(s))) { + if (!strcmp(s, "IGNORE")) { + r = 0; + } else if (!strcmp(s, "..") || !strcmp(sym, "RANGE")) { + if (*sym == '.') { + final_index_val(sym); /* make sure it's known */ + } + r = 0x3fff; + } else if (!strcmp(s, ".")) { + r = 0x3ffe; + } else { + error_msg("can't find final index: %s", s); + } + } + return r; +} + +/* store rule2val in 2 high bits and collation index in lower. + * for sort strings, store (offset from base) + max colindex as index. + */ +static unsigned int add_rule(weighted_item_t *wi) +{ + weight_t *w = wi->weight; + int i, j, r, n; + uint16_t rbuf[MAX_COLLATION_WEIGHTS]; + uint16_t ws_buf[32]; + void *mm; + char buf[32]; + const char *s; + const char *e; + + for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) { + rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */ + } + + if (base_locale_array[base_locale_len].num_weights < w->num_weights) { + base_locale_array[base_locale_len].num_weights = w->num_weights; + } + + for (i=0 ; i < w->num_weights ; i++) { + assert(rule2val[(int)(w->rule[i])] >= 0); + assert(w->colitem[i] && *w->colitem[i]); + if (*w->colitem[i] == '"') { /* string... */ + s = w->colitem[i] + 1; + assert(*s == '<'); + n = 0; + do { + e = s; + do { + if (*e == '/') { + e += 2; + continue; + } + } while (*e++ != '>'); + assert(((size_t)(e-s) < sizeof(buf))); + memcpy(buf, s, (size_t)(e-s)); + buf[(size_t)(e-s)] = 0; + + r = final_index_val_x(buf, wi->symbol); + assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0])); + ws_buf[n++] = r | rule2val[(int)(w->rule[i])]; + + s = e; + } while (*s != '"'); + ws_buf[n++] = 0; /* terminator */ + + mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]), + ws_buf, n*sizeof(ws_buf[0])); + + if (!mm) { + assert(weightstr_len + n < WEIGHTSTR_LEN); + memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0])); + mm = weightstr_buffer + weightstr_len; + weightstr_len += n; + } + r = (((uint16_t *)(mm)) - weightstr_buffer) + + base_locale_array[base_locale_len].max_col_index + 2; + assert(r < (1 << 14)); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } else { /* item */ + r = final_index_val_x(w->colitem[i], wi->symbol); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } + } + + for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) { + if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) { + return i/MAX_COLLATION_WEIGHTS; + } + } + + memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0])); + ruletable_len += MAX_COLLATION_WEIGHTS; + + return (ruletable_len / MAX_COLLATION_WEIGHTS)-1; +} + +static unsigned int add_range_rule(range_item_t *ri) +{ + weight_t *w = ri->weight; + int i, j, r, n; + uint16_t rbuf[MAX_COLLATION_WEIGHTS]; + uint16_t ws_buf[32]; + void *mm; + char buf[32]; + const char *s; + const char *e; + + for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) { + rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */ + } + + if (base_locale_array[base_locale_len].num_weights < w->num_weights) { + base_locale_array[base_locale_len].num_weights = w->num_weights; + } + + for (i=0 ; i < w->num_weights ; i++) { + assert(rule2val[(int)(w->rule[i])] >= 0); + assert(w->colitem[i] && *w->colitem[i]); + if (*w->colitem[i] == '"') { /* string... */ + s = w->colitem[i] + 1; + assert(*s == '<'); + n = 0; + do { + e = s; + do { + if (*e == '/') { + e += 2; + continue; + } + } while (*e++ != '>'); + assert(((size_t)(e-s) < sizeof(buf))); + memcpy(buf, s, (size_t)(e-s)); + buf[(size_t)(e-s)] = 0; + + r = final_index_val_x(buf, "RANGE"); + assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0])); + ws_buf[n++] = r | rule2val[(int)(w->rule[i])]; + + s = e; + } while (*s != '"'); + ws_buf[n++] = 0; /* terminator */ + + mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]), + ws_buf, n*sizeof(ws_buf[0])); + + if (!mm) { + assert(weightstr_len + n < WEIGHTSTR_LEN); + memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0])); + mm = weightstr_buffer + weightstr_len; + weightstr_len += n; + } + r = (((uint16_t *)(mm)) - weightstr_buffer) + + base_locale_array[base_locale_len].max_col_index + 2; + assert(r < (1 << 14)); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } else { /* item */ + r = final_index_val_x(w->colitem[i], "RANGE"); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } + } + + for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) { + if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) { + return i/MAX_COLLATION_WEIGHTS; + } + } + + memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0])); + ruletable_len += MAX_COLLATION_WEIGHTS; + + return (ruletable_len / MAX_COLLATION_WEIGHTS)-1; +} + +#define DUMPn(X) fprintf(stderr, "%10d-%-.20s", base_locale_array[n]. X, #X); + +static void dump_base_locale(int n) +{ + assert(n < base_locale_len); + + fprintf(stderr, "Base Locale: %s\n", base_locale_array[n].name); + + DUMPn(num_weights); + + DUMPn(ii_shift); + DUMPn(ti_shift); + DUMPn(ii_len); + DUMPn(ti_len); + DUMPn(max_weight); + fprintf(stderr, "\n"); + DUMPn(num_col_base); + DUMPn(max_col_index); + DUMPn(undefined_idx); + DUMPn(range_low); + DUMPn(range_count); + fprintf(stderr, "\n"); + DUMPn(range_base_weight); + DUMPn(num_starters); + + fprintf(stderr, "\n"); + DUMPn(range_rule_offset); + DUMPn(wcs2colidt_offset); + DUMPn(index2weight_offset); + fprintf(stderr, "\n"); + DUMPn(index2ruleidx_offset); + DUMPn(multistart_offset); + fprintf(stderr, "\n"); +} + +#undef DUMPn +#define DUMPn(X) fprintf(stderr, "%10d-%s", der_locale_array[n]. X, #X); + +static void dump_der_locale(int n) +{ + assert(n < der_locale_len); + + fprintf(stderr, "Derived Locale: %s (%.12s)", + der_locale_array[n].name, + base_locale_array[der_locale_array[n].base_idx].name); + + + DUMPn(base_idx); + + DUMPn(undefined_idx); + + DUMPn(overrides_offset); + DUMPn(multistart_offset); + + fprintf(stderr, "\n"); +} + + +static unsigned long collate_pos; + +static void dump_u16_array(FILE *fp, uint16_t *u, int len, const char *name) +{ + int i; + + fprintf(fp, "\t/* %8lu %s */\n", collate_pos, name); + for (i=0 ; i < len ; i++) { + if (!(i & 7)) { + fprintf(fp, "\n\t"); + } + fprintf(fp," %#06x,", (unsigned int)(u[i])); + } + fprintf(fp,"\n"); + collate_pos += len; +} + +#define OUT_U16C(X,N) fprintf(fp,"\t%10d, /* %8lu %s */\n", X, collate_pos++, N); + +static void dump_collate(FILE *fp) +{ + int n; + + fprintf(fp, "const uint16_t __locale_collate_tbl[] = {\n"); + + OUT_U16C(base_locale_len, "numbef of base locales"); + OUT_U16C(der_locale_len, "number of derived locales"); + OUT_U16C(MAX_COLLATION_WEIGHTS, "max collation weights"); + OUT_U16C(index2weight_len, "number of index2{weight|ruleidx} elements"); + OUT_U16C(weightstr_len, "number of weightstr elements"); + OUT_U16C(multistart_len, "number of multistart elements"); + OUT_U16C(override_len, "number of override elements"); + OUT_U16C(ruletable_len, "number of ruletable elements"); + +#undef DUMPn +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", base_locale_array[n]. X, collate_pos++, #X); + for (n=0 ; n < base_locale_len ; n++) { + unsigned wcs2colidt_offset_low = base_locale_array[n].wcs2colidt_offset & 0xffffU; + unsigned wcs2colidt_offset_hi = base_locale_array[n].wcs2colidt_offset >> 16; + fprintf(fp, "\t/* Base Locale %2d: %s */\n", n, base_locale_array[n].name); + DUMPn(num_weights); + DUMPn(num_starters); + DUMPn(ii_shift); + DUMPn(ti_shift); + DUMPn(ii_len); + DUMPn(ti_len); + DUMPn(max_weight); + DUMPn(num_col_base); + DUMPn(max_col_index); + DUMPn(undefined_idx); + DUMPn(range_low); + DUMPn(range_count); + DUMPn(range_base_weight); + DUMPn(range_rule_offset); + DUMPn(index2weight_offset); + DUMPn(index2ruleidx_offset); + DUMPn(multistart_offset); +#undef DUMPn +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", X, collate_pos++, #X); + DUMPn(wcs2colidt_offset_low); + DUMPn(wcs2colidt_offset_hi); + } +#undef DUMPn + + + fprintf(fp, "#define COL_IDX_C %5d\n", 0); +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", der_locale_array[n]. X, collate_pos++, #X); + for (n=0 ; n < der_locale_len ; n++) { + fprintf(fp, "#define COL_IDX_%s %5d\n", der_locale_array[n].name, n+1); + fprintf(fp, "\t/* Derived Locale %4d: %s (%.12s) */\n", + n, der_locale_array[n].name, + base_locale_array[der_locale_array[n].base_idx].name); + DUMPn(base_idx); + DUMPn(undefined_idx); + DUMPn(overrides_offset); + DUMPn(multistart_offset); + } +#undef DUMPn + + fprintf(fp, "\n"); + + dump_u16_array(fp, index2weight_buffer, index2weight_len, "index2weight"); + dump_u16_array(fp, index2ruleidx_buffer, index2ruleidx_len, "index2ruleidx"); + dump_u16_array(fp, multistart_buffer, multistart_len, "multistart"); + dump_u16_array(fp, override_buffer, override_len, "override"); + dump_u16_array(fp, ruletable_buffer, ruletable_len, "ruletable"); + dump_u16_array(fp, weightstr_buffer, weightstr_len, "weightstr"); + dump_u16_array(fp, wcs2colidt_buffer, wcs2colidt_len, "wcs2colidt"); + + + fprintf(fp,"}; /* %8lu */\n", collate_pos); + + fprintf(fp,"#define __lc_collate_data_LEN %d\n\n", collate_pos); +} diff --git a/extra/locale/gen_ldc.c b/extra/locale/gen_ldc.c new file mode 100644 index 0000000..2cedbdd --- /dev/null +++ b/extra/locale/gen_ldc.c @@ -0,0 +1,298 @@ +#include +#include +#include +#include +#include +#include + +#ifndef __WCHAR_ENABLED +#warning WHOA!!! __WCHAR_ENABLED is not defined! defining it now... +#define __WCHAR_ENABLED +#endif + +#define WANT_DATA +#include "c8tables.h" +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#warning __CTYPE_HAS_8_BIT_LOCALES is not defined... +/* #define __CTYPE_HAS_8_BIT_LOCALES */ +#endif + +/* #define __LOCALE_DATA_Cctype_TBL_LEN 328 */ +/* #define __LOCALE_DATA_Cuplow_TBL_LEN 400 */ +/* #define __LOCALE_DATA_Cc2wc_TBL_LEN 1448 */ +/* #define __LOCALE_DATA_Cwc2c_TBL_LEN 3744 */ + +#define WANT_WCctype_data +#define WANT_WCuplow_data +#define WANT_WCuplow_diff_data +/* #define WANT_WCcomb_data */ +/* #define WANT_WCwidth_data */ +#include "wctables.h" +#undef WANT_WCctype_data +#undef WANT_WCuplow_data +#undef WANT_WCuplow_diff_data +/* #undef WANT_WCcomb_data */ +/* #undef WANT_WCwidth_data */ + + #define __LOCALE_DATA_WCctype_TBL_LEN (__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + __LOCALE_DATA_WCctype_UT_LEN) + #define __LOCALE_DATA_WCuplow_TBL_LEN (__LOCALE_DATA_WCuplow_II_LEN + __LOCALE_DATA_WCuplow_TI_LEN + __LOCALE_DATA_WCuplow_UT_LEN) + #define __LOCALE_DATA_WCuplow_diff_TBL_LEN (2 * __LOCALE_DATA_WCuplow_diffs) +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ + +#include "locale_collate.h" +#include "locale_tables.h" + +#include "locale_mmap.h" + +/* #undef __PASTE2 */ +/* #define __PASTE2(A,B) A ## B */ +/* #undef __PASTE3 */ +/* #define __PASTE3(A,B,C) A ## B ## C */ + + +/* #define __LOCALE_DATA_MAGIC_SIZE 64 */ + +/* #define COMMON_MMAP(X) \ */ +/* unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; */ + +/* #define COMMON_MMIDX(X) \ */ +/* unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ */ + +/* ---------------------------------------------------------------------- */ + +#define COMMON_OFFSETS(X) \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)) \ + + +static const size_t common_tbl_offsets[__LOCALE_DATA_CATEGORIES*4] = { + COMMON_OFFSETS(ctype), + COMMON_OFFSETS(numeric), + COMMON_OFFSETS(monetary), + COMMON_OFFSETS(time), + 0, 0, 0, 0, /* collate */ + COMMON_OFFSETS(messages), +}; + + +void out_uc(FILE *f, const unsigned char *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#04x, ", p[i]); + } else { + fprintf(f, "%#4x, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + +void out_u16(FILE *f, const uint16_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#06x, ", p[i]); + } else { + fprintf(f, "%#6x, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + +void out_i16(FILE *f, const int16_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + fprintf(f, "%6d, ", p[i]); + } + fprintf(f, "\n},\n"); +} + +void out_size_t(FILE *f, const size_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 3)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#010zx, ", p[i]); + } else { + fprintf(f, "%#10zx, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + + +int main(int argc, char **argv) +{ + char *output_file = "locale_data.c"; + FILE *lso; /* static object */ + int i; +#ifdef __LOCALE_DATA_MAGIC_SIZE + unsigned char magic[__LOCALE_DATA_MAGIC_SIZE]; + + memset(magic, 0, __LOCALE_DATA_MAGIC_SIZE); +#endif /* __LOCALE_DATA_MAGIC_SIZE */ + + if (argc == 2) + output_file = argv[1]; + if (!(lso = fopen(output_file, "w"))) { + printf("cannot open output file '%s'!\n", output_file); + return EXIT_FAILURE; + } + + fprintf(lso, + "#include \n" + "#include \n" +/* "#define __CTYPE_HAS_8_BIT_LOCALES\n" */ + "#ifndef __WCHAR_ENABLED\n" + "#error __WCHAR_ENABLED not defined\n" + "#endif\n" + "#include \"c8tables.h\"\n" + "#include \"wctables.h\"\n" + "#include \"lt_defines.h\"\n" + "#include \"locale_mmap.h\"\n\n" + "static const __locale_mmap_t locale_mmap = {\n\n" + ); +#ifdef __LOCALE_DATA_MAGIC_SIZE + out_uc(lso, magic, __LOCALE_DATA_MAGIC_SIZE, "magic"); +#endif /* __LOCALE_DATA_MAGIC_SIZE */ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + out_uc(lso, __LOCALE_DATA_Cctype_data, __LOCALE_DATA_Cctype_TBL_LEN, "tbl8ctype"); + out_uc(lso, __LOCALE_DATA_Cuplow_data, __LOCALE_DATA_Cuplow_TBL_LEN, "tbl8uplow"); +#ifdef __WCHAR_ENABLED + out_u16(lso, __LOCALE_DATA_Cc2wc_data, __LOCALE_DATA_Cc2wc_TBL_LEN, "tbl8c2wc"); + out_uc(lso, __LOCALE_DATA_Cwc2c_data, __LOCALE_DATA_Cwc2c_TBL_LEN, "tbl8wc2c"); + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __WCHAR_ENABLED + out_uc(lso, __LOCALE_DATA_WCctype_data, __LOCALE_DATA_WCctype_TBL_LEN, "tblwctype"); + out_uc(lso, __LOCALE_DATA_WCuplow_data, __LOCALE_DATA_WCuplow_TBL_LEN, "tblwuplow"); + out_i16(lso, __LOCALE_DATA_WCuplow_diff_data, __LOCALE_DATA_WCuplow_diff_TBL_LEN, "tblwuplow_diff"); +/* const unsigned char tblwcomb[WCcomb_TBL_LEN]; */ + /* width?? */ +#endif /* __WCHAR_ENABLED */ + out_uc(lso, __lc_ctype_data, __lc_ctype_data_LEN, "lc_ctype_data"); + out_uc(lso, __lc_numeric_data, __lc_numeric_data_LEN, "lc_numeric_data"); + out_uc(lso, __lc_monetary_data, __lc_monetary_data_LEN, "lc_monetary_data"); + out_uc(lso, __lc_time_data, __lc_time_data_LEN, "lc_time_data"); + /* TODO -- collate*/ + out_uc(lso, __lc_messages_data, __lc_messages_data_LEN, "lc_messages_data"); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fprintf(lso, "{ /* codeset_8_bit array */\n"); + for (i = 0 ; i < __LOCALE_DATA_NUM_CODESETS ; i++) { + fprintf(lso, "{ /* codeset_8_bit[%d] */\n", i); + out_uc(lso, codeset_8_bit[i].idx8ctype, __LOCALE_DATA_Cctype_IDX_LEN, "idx8ctype"); + out_uc(lso, codeset_8_bit[i].idx8uplow, __LOCALE_DATA_Cuplow_IDX_LEN, "idx8uplow"); + out_uc(lso, codeset_8_bit[i].idx8c2wc, __LOCALE_DATA_Cc2wc_IDX_LEN, "idx8c2wc"); + out_uc(lso, codeset_8_bit[i].idx8wc2c, __LOCALE_DATA_Cwc2c_II_LEN, "idx8wc2c"); + fprintf(lso, "},\n"); + } + fprintf(lso, "},\n"); +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + out_uc(lso, __lc_ctype_rows, __lc_ctype_rows_LEN, "lc_ctype_rows"); + out_u16(lso, __lc_ctype_item_offsets, __lc_ctype_item_offsets_LEN, "lc_ctype_item_offsets"); + out_u16(lso, __lc_ctype_item_idx, __lc_ctype_item_idx_LEN, "lc_ctype_item_idx"); + + out_uc(lso, __lc_numeric_rows, __lc_numeric_rows_LEN, "lc_numeric_rows"); + out_u16(lso, __lc_numeric_item_offsets, __lc_numeric_item_offsets_LEN, "lc_numeric_item_offsets"); + out_u16(lso, __lc_numeric_item_idx, __lc_numeric_item_idx_LEN, "lc_numeric_item_idx"); + + out_uc(lso, __lc_monetary_rows, __lc_monetary_rows_LEN, "lc_monetary_rows"); + out_u16(lso, __lc_monetary_item_offsets, __lc_monetary_item_offsets_LEN, "lc_monetary_item_offsets"); + out_u16(lso, __lc_monetary_item_idx, __lc_monetary_item_idx_LEN, "lc_monetary_item_idx"); + + out_uc(lso, __lc_time_rows, __lc_time_rows_LEN, "lc_time_rows"); + out_u16(lso, __lc_time_item_offsets, __lc_time_item_offsets_LEN, "lc_time_item_offsets"); + out_u16(lso, __lc_time_item_idx, __lc_time_item_idx_LEN, "lc_time_item_idx"); + + out_uc(lso, __lc_messages_rows, __lc_messages_rows_LEN, "lc_messages_rows"); + out_u16(lso, __lc_messages_item_offsets, __lc_messages_item_offsets_LEN, "lc_messages_item_offsets"); + out_u16(lso, __lc_messages_item_idx, __lc_messages_item_idx_LEN, "lc_messages_item_idx"); + + /* collate should be last*/ + assert(sizeof(__locale_collate_tbl)/sizeof(__locale_collate_tbl[0]) == __lc_collate_data_LEN) ; + out_u16(lso, __locale_collate_tbl, __lc_collate_data_LEN, "collate_data"); + + + { + unsigned char co_buf[__LOCALE_DATA_CATEGORIES] = { + __lc_ctype_item_offsets_LEN, + __lc_numeric_item_offsets_LEN, + __lc_monetary_item_offsets_LEN, + __lc_time_item_offsets_LEN, + 0, + __lc_messages_item_offsets_LEN + }; + out_uc(lso, co_buf, __LOCALE_DATA_CATEGORIES, "lc_common_item_offsets_LEN"); + } + + out_size_t(lso, common_tbl_offsets, __LOCALE_DATA_CATEGORIES * 4, "lc_common_tbl_offsets"); + /* offsets from start of locale_mmap_t */ + /* rows, item_offsets, item_idx, data */ + +#ifdef __LOCALE_DATA_NUM_LOCALES + out_uc(lso, __locales, __LOCALE_DATA_NUM_LOCALES * __LOCALE_DATA_WIDTH_LOCALES, "locales"); + out_uc(lso, __locale_names5, 5 * __LOCALE_DATA_NUM_LOCALE_NAMES, "locale_names5"); +#ifdef __LOCALE_DATA_AT_MODIFIERS_LENGTH + out_uc(lso, __locale_at_modifiers, __LOCALE_DATA_AT_MODIFIERS_LENGTH, "locale_at_modifiers"); +#else +#error __LOCALE_DATA_AT_MODIFIERS_LENGTH not defined! +#endif /* __LOCALE_DATA_AT_MODIFIERS_LENGTH */ +#endif /* __LOCALE_DATA_NUM_LOCALES */ + + out_uc(lso, lc_names, __lc_names_LEN, "lc_names"); +#ifdef __CTYPE_HAS_8_BIT_LOCALES + out_uc(lso, (const unsigned char*) __LOCALE_DATA_CODESET_LIST, sizeof(__LOCALE_DATA_CODESET_LIST), "codeset_list"); +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + fprintf(lso, + "\n};\n\n" + "const __locale_mmap_t *__locale_mmap = &locale_mmap;\n\n" + ); + + if (ferror(lso) || fclose(lso)) { + printf("error writing!\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* ---------------------------------------------------------------------- */ + +/* TODO: + * collate data (8-bit weighted single char only) + * @ mappings! + * codeset list? yes, since we'll want to be able to inspect them... + * that means putting some header stuff in magic + * fix ctype LEN defines in gen_c8tables + */ diff --git a/extra/locale/gen_locale.c b/extra/locale/gen_locale.c new file mode 100644 index 0000000..5e89360 --- /dev/null +++ b/extra/locale/gen_locale.c @@ -0,0 +1,1337 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c8tables.h" + + +#define __LOCALE_DATA_CATEGORIES 6 + +/* must agree with ordering of gen_mmap! */ +static const char *lc_names[] = { + "LC_CTYPE", + "LC_NUMERIC", + "LC_MONETARY", + "LC_TIME", + "LC_COLLATE", + "LC_MESSAGES", +#if __LOCALE_DATA_CATEGORIES == 12 + "LC_PAPER", + "LC_NAME", + "LC_ADDRESS", + "LC_TELEPHONE", + "LC_MEASUREMENT", + "LC_IDENTIFICATION", +#elif __LOCALE_DATA_CATEGORIES != 6 +#error unsupported __LOCALE_DATA_CATEGORIES value! +#endif +}; + + + +typedef struct { + char *glibc_name; + char name[5]; + char dot_cs; /* 0 if no codeset specified */ + char cs; + unsigned char idx_name; + unsigned char lc_time_row; + unsigned char lc_numeric_row; + unsigned char lc_monetary_row; + unsigned char lc_messages_row; + unsigned char lc_ctype_row; +#if __LOCALE_DATA_CATEGORIES != 6 +#error unsupported __LOCALE_DATA_CATEGORIES value +#endif +} locale_entry; + +static void read_at_mappings(void); +static void read_enable_disable(void); +static void read_locale_list(void); + +static int find_codeset_num(const char *cs); +static int find_at_string_num(const char *as); +static int le_cmp(const void *, const void *); +static void dump_table8(const char *name, const char *tbl, int len); +static void dump_table8c(const char *name, const char *tbl, int len); +static void dump_table16(const char *name, const int *tbl, int len); + +static void do_lc_time(void); +static void do_lc_numeric(void); +static void do_lc_monetary(void); + +static void do_lc_messages(void); +static void do_lc_ctype(void); + + +static FILE *fp; +static FILE *ofp; +static char line_buf[80]; +static char at_mappings[256]; +static char at_mapto[256]; +static char at_strings[1024]; +static char *at_strings_end; +static locale_entry locales[700]; +static char glibc_locale_names[60000]; + +static int num_locales; + +static int default_utf8; +static int default_8bit; + +static int total_size; +static int null_count; + +static unsigned verbose = 0; +enum { + VINFO = (1<<0), + VDETAIL = (1<<1), +}; +static int verbose_msg(const unsigned lvl, const char *fmt, ...) +{ + va_list arg; + int ret = 0; + + if (verbose & lvl) { + va_start(arg, fmt); + ret = vfprintf(stderr, fmt, arg); + va_end(arg); + } + return ret; +} + +static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + fprintf(stderr, "Error: "); +/* if (fno >= 0) { + fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]); + } */ + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + +static void do_locale_names(void) +{ + /* "C" locale name is handled specially by the setlocale code. */ + int uniq = 0; + int i; + + if (num_locales <= 1) { +/* error_msg("only C locale?"); */ + fprintf(ofp, "static const unsigned char __locales[%d];\n", (3 + __LOCALE_DATA_CATEGORIES)); + fprintf(ofp, "static const unsigned char __locale_names5[5];\n"); + } else { + if (default_utf8) { + fprintf(ofp, "#define __CTYPE_HAS_UTF_8_LOCALES\t\t\t1\n"); + } + fprintf(ofp, "#define __LOCALE_DATA_CATEGORIES\t\t\t%d\n", __LOCALE_DATA_CATEGORIES); + fprintf(ofp, "#define __LOCALE_DATA_WIDTH_LOCALES\t\t\t%d\n", 3+__LOCALE_DATA_CATEGORIES); + fprintf(ofp, "#define __LOCALE_DATA_NUM_LOCALES\t\t\t%d\n", num_locales); + fprintf(ofp, "static const unsigned char __locales[%d] = {\n", + (num_locales) * (3 + __LOCALE_DATA_CATEGORIES)); + for (i=0 ; i < num_locales ; i++) { + if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) { + locales[i].idx_name = uniq; + ++uniq; + } else { + locales[i].idx_name = uniq - 1; + } + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].idx_name)); + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].dot_cs)); + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].cs)); + /* lc_ctype would store translit flags and turkish up/low flag. */ + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_ctype_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_numeric_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_monetary_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_time_row)); +#if 1 + /* lc_collate */ + if (strlen(locales[i].glibc_name) >= 5) { + fprintf(ofp, "COL_IDX_%.2s_%.2s, ", locales[i].glibc_name, locales[i].glibc_name+3); + } else if (!strcmp(locales[i].glibc_name, "C")) { + fprintf(ofp, "COL_IDX_C , "); + } else { + error_msg("don't know how to handle COL_IDX_ for %s", locales[i].glibc_name); + } +#else + fprintf(ofp, "%#4x, ", 0); /* place holder for lc_collate */ +#endif + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_messages_row)); + fprintf(ofp, "\t/* %s */\n", locales[i].glibc_name); + } + fprintf(ofp, "};\n\n"); + + fprintf(ofp, "#define __LOCALE_DATA_NUM_LOCALE_NAMES\t\t%d\n", uniq ); + fprintf(ofp, "static const unsigned char __locale_names5[%d] = \n\t", uniq * 5); + uniq = 0; + for (i=1 ; i < num_locales ; i++) { + if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) { + fprintf(ofp, "\"%5.5s\" ", locales[i].name); + ++uniq; + if ((uniq % 8) == 0) { + fprintf(ofp, "\n\t"); + } + } + } + fprintf(ofp,";\n\n"); + + if (at_strings_end > at_strings) { + int i, j; + char *p; + i = 0; + p = at_strings; + while (*p) { + ++i; + p += 1 + (unsigned char) *p; + } + /* len, char, string\0 */ + fprintf(ofp, "#define __LOCALE_DATA_AT_MODIFIERS_LENGTH\t\t%d\n", + i + (at_strings_end - at_strings)); + fprintf(ofp, "static const unsigned char __locale_at_modifiers[%d] = {", + i + (at_strings_end - at_strings)); + i = 0; + p = at_strings; + while (*p) { + fprintf(ofp, "\n\t%4d, '%c',", + (unsigned char) *p, /* len of string\0 */ + at_mapto[i]); + for (j=1 ; j < ((unsigned char) *p) ; j++) { + fprintf(ofp, " '%c',", p[j]); + } + fprintf(ofp, " 0,"); + ++i; + p += 1 + (unsigned char) *p; + } + fprintf(ofp, "\n};\n\n"); + } + + { + int pos[__LOCALE_DATA_CATEGORIES]; + pos[0] = __LOCALE_DATA_CATEGORIES; + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "#define __%s\t\t%d\n", lc_names[i], i); + if (i + 1 < __LOCALE_DATA_CATEGORIES) { + pos[i+1] = 1 + strlen(lc_names[i]) + pos[i]; + } + } + if (pos[__LOCALE_DATA_CATEGORIES-1] > 255) { + error_msg("lc_names is too big (%d)", pos[__LOCALE_DATA_CATEGORIES-1]); + } + fprintf(ofp, "#define __LC_ALL\t\t%d\n\n", i); + + fprintf(ofp, "#define __lc_names_LEN\t\t%d\n", + pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1); + total_size += pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1; + + fprintf(ofp, "static unsigned const char lc_names[%d] =\n", + pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1); + fprintf(ofp, "\t\""); + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "\\x%02x", (unsigned char) pos[i]); + } + fprintf(ofp, "\""); + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "\n\t\"%s\\0\"", lc_names[i]); + } + fprintf(ofp, ";\n\n"); + } + + verbose_msg(VDETAIL,"locale data = %d name data = %d for %d uniq\n", + num_locales * (3 + __LOCALE_DATA_CATEGORIES), uniq * 5, uniq); + + total_size += num_locales * (3 + __LOCALE_DATA_CATEGORIES) + uniq * 5; + } + +} + +static void read_at_mappings(void) +{ + char *p; + char *m; + int mc = 0; + + do { + if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + if (*p == '@') { + if (p[1] == 0) { + error_msg("missing @modifier name"); + } + m = p; /* save the modifier name */ + if (!(p = strtok(NULL, " \t\n")) || p[1] || (((unsigned char) *p) > 0x7f)) { + error_msg("missing or illegal @modifier mapping char"); + } + if (at_mappings[(int)((unsigned char) *p)]) { + error_msg("reused @modifier mapping char"); + } + at_mappings[(int)((unsigned char) *p)] = 1; + at_mapto[mc] = *p; + ++mc; + *at_strings_end = (char)( (unsigned char) (strlen(m)) ); + strcpy(++at_strings_end, m+1); + at_strings_end += (unsigned char) at_strings_end[-1]; + + verbose_msg(VDETAIL,"@mapping: \"%s\" to '%c'\n", m, *p); + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + fprintf(stderr,"ignoring trailing text: %s...\n", p); + } + *line_buf = 0; + continue; + } + break; + } while (1); + +#if 0 + { + p = at_strings; + + if (!*p) { + verbose_msg(VDETAIL,"no @ strings\n"); + return; + } + + do { + verbose_msg(VDETAIL,"%s\n", p+1); + p += 1 + (unsigned char) *p; + } while (*p); + } +#endif +} + +static void read_enable_disable(void) +{ + char *p; + + do { + if (!(p = strtok(line_buf, " =\t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + if (!strcmp(p, "UTF-8")) { + if (!(p = strtok(NULL, " =\t\n")) + || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) { + error_msg("missing or illegal UTF-8 setting"); + } + default_utf8 = (toupper(*p) == 'Y'); + verbose_msg(VINFO,"UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2)); + } else if (!strcmp(p, "8-BIT")) { + if (!(p = strtok(NULL, " =\t\n")) + || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) { + error_msg("missing or illegal 8-BIT setting"); + } + default_8bit = (toupper(*p) == 'Y'); + verbose_msg(VINFO,"8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2)); + } else { + break; + } + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + fprintf(stderr,"ignoring trailing text: %s...\n", p); + } + *line_buf = 0; + continue; + + } while (1); +} + +#ifdef __LOCALE_DATA_CODESET_LIST + +static int find_codeset_num(const char *cs) +{ + int r = 2; + char *s = __LOCALE_DATA_CODESET_LIST; + + /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */ + + if (strcmp(cs, "UTF-8") != 0) { + ++r; + while (*s && strcmp(__LOCALE_DATA_CODESET_LIST+ ((unsigned char) *s), cs)) { +/* verbose_msg(VDETAIL,"tried %s\n", __LOCALE_DATA_CODESET_LIST + ((unsigned char) *s)); */ + ++r; + ++s; + } + if (!*s) { + error_msg("unsupported codeset %s", cs); + } + } + return r; +} + +#else + +static int find_codeset_num(const char *cs) +{ + int r = 2; + + /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */ + + if (strcmp(cs, "UTF-8") != 0) { + error_msg("unsupported codeset %s", cs); + } + return r; +} + +#endif + +static int find_at_string_num(const char *as) +{ + int i = 0; + char *p = at_strings; + + while (*p) { + if (!strcmp(p+1, as)) { + return i; + } + ++i; + p += 1 + (unsigned char) *p; + } + + error_msg("error: unmapped @string %s", as); +} + +static void read_locale_list(void) +{ + char *p; + char *s; + char *ln; /* locale name */ + char *ls; /* locale name ll_CC */ + char *as; /* at string */ + char *ds; /* dot string */ + char *cs; /* codeset */ + int i; + + typedef struct { + char *glibc_name; + char name[5]; + char dot_cs; /* 0 if no codeset specified */ + char cs; + } locale_entry; + + /* First the C locale. */ + locales[0].glibc_name = locales[0].name; + strncpy(locales[0].name,"C",5); + locales[0].dot_cs = 0; + locales[0].cs = 1; /* 7-bit encoding */ + ++num_locales; + + do { + if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + + s = glibc_locale_names; + for (i=0 ; i < num_locales ; i++) { + if (!strcmp(s+1, p)) { + break; + } + s += 1 + ((unsigned char) *s); + } + if (i < num_locales) { + fprintf(stderr,"ignoring duplicate locale name: %s", p); + *line_buf = 0; + continue; + } + + /* New locale, but don't increment num until codeset verified! */ + *s = (char)((unsigned char) (strlen(p) + 1)); + strcpy(s+1, p); + locales[num_locales].glibc_name = s+1; + ln = p; /* save locale name */ + + if (!(p = strtok(NULL, " \t\n"))) { + error_msg("missing codeset for locale %s", ln); + } + cs = p; + i = find_codeset_num(p); + if ((i == 2) && !default_utf8) { + fprintf(stderr,"ignoring UTF-8 locale %s\n", ln); + *line_buf = 0; + continue; + } else if ((i > 2) && !default_8bit) { + fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln); + *line_buf = 0; + continue; + } + locales[num_locales].cs = (char)((unsigned char) i); + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + verbose_msg(VINFO,"ignoring trailing text: %s...\n", p); + } + + /* Now go back to locale string for .codeset and @modifier */ + as = strtok(ln, "@"); + if (as) { + as = strtok(NULL, "@"); + } + ds = strtok(ln, "."); + if (ds) { + ds = strtok(NULL, "."); + } + ls = ln; + + if ((strlen(ls) != 5) || (ls[2] != '_')) { + error_msg("illegal locale name %s", ls); + } + + i = 0; /* value for unspecified codeset */ + if (ds) { + i = find_codeset_num(ds); + if ((i == 2) && !default_utf8) { + fprintf(stderr,"ignoring UTF-8 locale %s\n", ln); + *line_buf = 0; + continue; + } else if ((i > 2) && !default_8bit) { + fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln); + *line_buf = 0; + continue; + } + } + locales[num_locales].dot_cs = (char)((unsigned char) i); + + if (as) { + i = find_at_string_num(as); + ls[2] = at_mapto[i]; + } + memcpy(locales[num_locales].name, ls, 5); +/* verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n", */ +/* locales[num_locales].name, */ +/* locales[num_locales].cs, */ +/* locales[num_locales].dot_cs, */ +/* locales[num_locales].glibc_name */ +/* ); */ + ++num_locales; + *line_buf = 0; + } while (1); +} + +static int le_cmp(const void *a, const void *b) +{ + const locale_entry *p; + const locale_entry *q; + int r; + + p = (const locale_entry *) a; + q = (const locale_entry *) b; + + if (!(r = p->name[0] - q->name[0]) + && !(r = p->name[1] - q->name[1]) + && !(r = p->name[3] - q->name[3]) + && !(r = p->name[4] - q->name[4]) + && !(r = p->name[2] - q->name[2]) + && !(r = -(p->cs - q->cs)) + ) { + r = -(p->dot_cs - q->dot_cs); + /* Reverse the ordering of the codesets so UTF-8 comes last. + * Work-around (hopefully) for glibc bug affecting at least + * the euro currency symbol. */ + } + + return r; +} + +int main(int argc, char **argv) +{ + char *output_file = NULL; + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-o")) { + --argc; + output_file = strdup(*++argv); + } else if (!strcmp(*argv, "-v")) { + verbose++; + } else if (!(fp = fopen(*argv, "r"))) { +no_inputfile: + error_msg("missing filename or file!"); + } + } + if (fp == NULL) + goto no_inputfile; + if (output_file == NULL) + output_file = strdup("locale_tables.h"); + + at_strings_end = at_strings; + + read_at_mappings(); + read_enable_disable(); + read_locale_list(); + + fclose(fp); + + /* handle C locale specially */ + qsort(locales+1, num_locales-1, sizeof(locale_entry), le_cmp); + +#if 0 + for (i=0 ; i < num_locales ; i++) { + verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n", + locales[i].name, + locales[i].cs, + locales[i].dot_cs, + locales[i].glibc_name + ); + } +#endif + if (argc == 3) + output_file = *++argv; + if (output_file == NULL || !(ofp = fopen(output_file, "w"))) { + error_msg("cannot open output file '%s'!", output_file); + } + + do_lc_time(); + do_lc_numeric(); + do_lc_monetary(); + do_lc_messages(); + do_lc_ctype(); + + do_locale_names(); + + fclose(ofp); + + verbose_msg(VINFO, "total data size = %d\n", total_size); + verbose_msg(VDETAIL, "null count = %d\n", null_count); + + return EXIT_SUCCESS; +} + +static char *idx[10000]; +static char buf[100000]; +static char *last; +static int uniq; + +static int addblock(const char *s, size_t n) /* l includes nul terminator */ +{ + int j; + + if (!s) { + ++null_count; + return 0; + } + + for (j=0 ; (j < uniq) && (idx[j] + n < last) ; j++) { + if (!memcmp(s, idx[j], n)) { + return idx[j] - buf; + } + } + if (uniq >= sizeof(idx)) { + error_msg("too many uniq strings!"); + } + if (last + n >= buf + sizeof(buf)) { + error_msg("need to increase size of buf!"); + } + + idx[uniq] = last; + ++uniq; + memcpy(last, s, n); + last += n; + return idx[uniq - 1] - buf; +} + +static int addstring(const char *s) +{ + int j; + size_t l; + + if (!s) { + ++null_count; + return 0; + } + + for (j=0 ; j < uniq ; j++) { + if (!strcmp(s, idx[j])) { + return idx[j] - buf; + } + } + if (uniq >= sizeof(idx)) { + error_msg("too many uniq strings!"); + } + l = strlen(s) + 1; + if (last + l >= buf + sizeof(buf)) { + error_msg("need to increase size of buf!"); + } + + idx[uniq] = last; + ++uniq; + strcpy(last, s); + last += l; + return idx[uniq - 1] - buf; +} + +#define DO_LC_COMMON(CATEGORY) \ + verbose_msg(VDETAIL, "buf-size=%d uniq=%d rows=%d\n", \ + (int)(last - buf), uniq, lc_##CATEGORY##_uniq); \ + verbose_msg(VDETAIL, "total = %d + %d * %d + %d = %d\n", \ + num_locales, lc_##CATEGORY##_uniq, NUM_NL_##CATEGORY, (int)(last - buf), \ + i = num_locales + lc_##CATEGORY##_uniq*NUM_NL_##CATEGORY + (int)(last - buf)); \ + total_size += i; \ + dump_table8c("__lc_" #CATEGORY "_data", buf, (int)(last - buf)); \ + for (i=0 ; i < lc_##CATEGORY##_uniq ; i++) { \ + m = locales[i].lc_##CATEGORY##_row; \ + for (k=0 ; k < NUM_NL_##CATEGORY ; k++) { \ + buf[NUM_NL_##CATEGORY*i + k] = (char)((unsigned char) lc_##CATEGORY##_uniq_X[i][k]); \ + } \ + } \ + dump_table8("__lc_" #CATEGORY "_rows", buf, lc_##CATEGORY##_uniq * NUM_NL_##CATEGORY); \ + buf16[0] =0; \ + for (i=0 ; i < NUM_NL_##CATEGORY - 1 ; i++) { \ + buf16[i+1] = buf16[i] + lc_##CATEGORY##_count[i]; \ + } \ + dump_table16("__lc_" #CATEGORY "_item_offsets", buf16, NUM_NL_##CATEGORY); \ + m = 0; \ + for (k=0 ; k < NUM_NL_##CATEGORY ; k++) { \ + for (i=0 ; i < lc_##CATEGORY##_count[k] ; i++) { \ + buf16[m] = lc_##CATEGORY##_item[k][i]; \ + ++m; \ + } \ + } \ + dump_table16("__lc_" #CATEGORY "_item_idx", buf16, m); + + +#define DL_LC_LOOPTAIL(CATEGORY) \ + if (k > NUM_NL_##CATEGORY) { \ + error_msg("lc_" #CATEGORY " nl_item count > %d!", NUM_NL_##CATEGORY); \ + } \ + { \ + int r; \ + for (r=0 ; r < lc_##CATEGORY##_uniq ; r++) { \ + if (!memcmp(lc_##CATEGORY##_uniq_X[lc_##CATEGORY##_uniq], \ + lc_##CATEGORY##_uniq_X[r], NUM_NL_##CATEGORY)) { \ + break; \ + } \ + } \ + if (r == lc_##CATEGORY##_uniq) { /* new locale row */ \ + ++lc_##CATEGORY##_uniq; \ + if (lc_##CATEGORY##_uniq > 255) { \ + error_msg("too many unique lc_" #CATEGORY " rows!"); \ + } \ + } \ + locales[i].lc_##CATEGORY##_row = r; \ + } + + + +static int buf16[100*256]; + +static void dump_table8(const char *name, const char *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const unsigned char %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 12) == 0) { + fprintf(ofp, "\n\t"); + } + fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i])); + } + fprintf(ofp, "\n};\n\n"); +} + +#define __C_isdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((unsigned int)((c) - '0')) < 10)) +#define __C_isalpha(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \ + : (((unsigned int)(((c) | 0x20) - 'a')) < 26)) +#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c)) + +static void dump_table8c(const char *name, const char *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const unsigned char %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 12) == 0) { + fprintf(ofp, "\n\t"); + } + if (__C_isalnum(tbl[i]) || (tbl[i] == ' ')) { + fprintf(ofp, " '%c', ", (int)((unsigned char) tbl[i])); + } else { + fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i])); + } + } + fprintf(ofp, "\n};\n\n"); +} + +static void dump_table16(const char *name, const int *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const uint16_t %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 8) == 0) { + fprintf(ofp, "\n\t"); + } + if (tbl[i] != (uint16_t) tbl[i]) { + error_msg("falls outside uint16 range!"); + } + fprintf(ofp, "%#6x, ", tbl[i]); + } + fprintf(ofp, "\n};\n\n"); +} + + +#define NUM_NL_time 50 + +static int lc_time_item[NUM_NL_time][256]; +static int lc_time_count[NUM_NL_time]; +static unsigned char lc_time_uniq_X[700][NUM_NL_time]; +static int lc_time_uniq; + +#define DO_NL_S(X) lc_time_S(X, k++) + +static void lc_time_S(int X, int k) +{ + size_t len; + int j, m; + const char *s = nl_langinfo(X); + const char *p; + static const char nulbuf[] = ""; + + if (X == ALT_DIGITS) { + len = 1; + if (!s) { + s = nulbuf; + } + if (*s) { + p = s; + for (j = 0 ; j < 100 ; j++) { + while (*p) { + ++p; + } + ++p; + } + len = p - s; + } + j = addblock(s, len); +/* if (len > 1) verbose_msg(VDETAIL, "alt_digit: called addblock with len %zd\n", len); */ + } else if (X == ERA) { + if (!s) { + s = nulbuf; + } + p = s; + while (*p) { + while (*p) { + ++p; + } + ++p; + } + ++p; + j = addblock(s, p - s); +/* if (p-s > 1) verbose_msg(VDETAIL, "era: called addblock with len %d\n", p-s); */ + } else { + j = addstring(s); + } + for (m=0 ; m < lc_time_count[k] ; m++) { + if (lc_time_item[k][m] == j) { + break; + } + } + if (m == lc_time_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_time", k); + } + lc_time_item[k][m] = j; + ++lc_time_count[k]; + } + lc_time_uniq_X[lc_time_uniq][k] = m; +} + +static void do_lc_time(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(ABDAY_1); + DO_NL_S(ABDAY_2); + DO_NL_S(ABDAY_3); + DO_NL_S(ABDAY_4); + DO_NL_S(ABDAY_5); + DO_NL_S(ABDAY_6); + DO_NL_S(ABDAY_7); + + DO_NL_S(DAY_1); + DO_NL_S(DAY_2); + DO_NL_S(DAY_3); + DO_NL_S(DAY_4); + DO_NL_S(DAY_5); + DO_NL_S(DAY_6); + DO_NL_S(DAY_7); + + DO_NL_S(ABMON_1); + DO_NL_S(ABMON_2); + DO_NL_S(ABMON_3); + DO_NL_S(ABMON_4); + DO_NL_S(ABMON_5); + DO_NL_S(ABMON_6); + DO_NL_S(ABMON_7); + DO_NL_S(ABMON_8); + DO_NL_S(ABMON_9); + DO_NL_S(ABMON_10); + DO_NL_S(ABMON_11); + DO_NL_S(ABMON_12); + + DO_NL_S(MON_1); + DO_NL_S(MON_2); + DO_NL_S(MON_3); + DO_NL_S(MON_4); + DO_NL_S(MON_5); + DO_NL_S(MON_6); + DO_NL_S(MON_7); + DO_NL_S(MON_8); + DO_NL_S(MON_9); + DO_NL_S(MON_10); + DO_NL_S(MON_11); + DO_NL_S(MON_12); + + DO_NL_S(AM_STR); + DO_NL_S(PM_STR); + + DO_NL_S(D_T_FMT); + DO_NL_S(D_FMT); + DO_NL_S(T_FMT); + DO_NL_S(T_FMT_AMPM); + DO_NL_S(ERA); + + DO_NL_S(ERA_YEAR); /* non SuSv3 */ + DO_NL_S(ERA_D_FMT); + DO_NL_S(ALT_DIGITS); + DO_NL_S(ERA_D_T_FMT); + DO_NL_S(ERA_T_FMT); + + DL_LC_LOOPTAIL(time) + } + + DO_LC_COMMON(time) +} + +#undef DO_NL_S + +#define NUM_NL_numeric 3 + +static int lc_numeric_item[NUM_NL_numeric][256]; +static int lc_numeric_count[NUM_NL_numeric]; +static unsigned char lc_numeric_uniq_X[700][NUM_NL_numeric]; +static int lc_numeric_uniq; + +#define DO_NL_S(X) lc_numeric_S(X, k++) + +static void lc_numeric_S(int X, int k) +{ + int j, m; + char buf[256]; + char *e; + char *s; + char c; + + s = nl_langinfo(X); + if (X == GROUPING) { + if (s) { + if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */ + s = ""; + } + e = s; + c = 0; + while (*e) { /* find end of string */ + if (*e == CHAR_MAX) { + c = CHAR_MAX; + ++e; + break; + } + ++e; + } + if ((e - s) > sizeof(buf)) { + error_msg("grouping specifier too long"); + } + strncpy(buf, s, (e-s)); + e = buf + (e-s); + *e = 0; /* Make sure we're null-terminated. */ + + if (c != CHAR_MAX) { /* remove duplicate repeats */ + while (e > buf) { + --e; + if (*e != e[-1]) { + break; + } + } + *++e = 0; + } + s = buf; + } + } + j = addstring(s); + for (m=0 ; m < lc_numeric_count[k] ; m++) { + if (lc_numeric_item[k][m] == j) { + break; + } + } + if (m == lc_numeric_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_numeric", k); + } + lc_numeric_item[k][m] = j; + ++lc_numeric_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_numeric_uniq_X[lc_numeric_uniq][k] = m; +} + +static void do_lc_numeric(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */ + DO_NL_S(THOUSEP); /* THOUSANDS_SEP */ + DO_NL_S(GROUPING); + + DL_LC_LOOPTAIL(numeric) + } + + DO_LC_COMMON(numeric) +} + +#undef DO_NL_S + +#define NUM_NL_monetary (7+14+1) + +static int lc_monetary_item[NUM_NL_monetary][256]; +static int lc_monetary_count[NUM_NL_monetary]; +static unsigned char lc_monetary_uniq_X[700][NUM_NL_monetary]; +static int lc_monetary_uniq; + +#define DO_NL_S(X) lc_monetary_S(X, k++) + +/* #define DO_NL_C(X) verbose_msg(VDETAIL,"%#02x", (int)(unsigned char)(*nl_langinfo(X))); */ +#define DO_NL_C(X) lc_monetary_C(X, k++) + +static void lc_monetary_C(int X, int k) +{ + int j, m; + char c_buf[2]; + +#warning fix the char entries for monetary... target signedness of char may be different! + + c_buf[1] = 0; + c_buf[0] = *nl_langinfo(X); + j = addstring(c_buf); + for (m=0 ; m < lc_monetary_count[k] ; m++) { + if (lc_monetary_item[k][m] == j) { + break; + } + } + if (m == lc_monetary_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_monetary", k); + } + lc_monetary_item[k][m] = j; + ++lc_monetary_count[k]; + } +/* verbose_msg(VDETAIL,"\\x%02x", m); */ + lc_monetary_uniq_X[lc_monetary_uniq][k] = m; +} + + +static void lc_monetary_S(int X, int k) +{ + int j, m; + char buf[256]; + char *e; + char *s; + char c; + + s = nl_langinfo(X); + if (X == MON_GROUPING) { + if (s) { + if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */ + s = ""; + } + e = s; + c = 0; + while (*e) { /* find end of string */ + if (*e == CHAR_MAX) { + c = CHAR_MAX; + ++e; + break; + } + ++e; + } + if ((e - s) > sizeof(buf)) { + error_msg("mon_grouping specifier too long"); + } + strncpy(buf, s, (e-s)); + e = buf + (e-s); + *e = 0; /* Make sure we're null-terminated. */ + + if (c != CHAR_MAX) { /* remove duplicate repeats */ + while (e > buf) { + --e; + if (*e != e[-1]) { + break; + } + } + *++e = 0; + } + s = buf; + } + } + j = addstring(s); + for (m=0 ; m < lc_monetary_count[k] ; m++) { + if (lc_monetary_item[k][m] == j) { + break; + } + } + if (m == lc_monetary_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_monetary", k); + } + lc_monetary_item[k][m] = j; + ++lc_monetary_count[k]; + } +/* verbose_msg(VDETAIL,"\\x%02x", m); */ + lc_monetary_uniq_X[lc_monetary_uniq][k] = m; +} + +static void do_lc_monetary(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + + /* non SUSv3 */ + DO_NL_S(INT_CURR_SYMBOL); + DO_NL_S(CURRENCY_SYMBOL); + DO_NL_S(MON_DECIMAL_POINT); + DO_NL_S(MON_THOUSANDS_SEP); + DO_NL_S(MON_GROUPING); + DO_NL_S(POSITIVE_SIGN); + DO_NL_S(NEGATIVE_SIGN); + DO_NL_C(INT_FRAC_DIGITS); + DO_NL_C(FRAC_DIGITS); + DO_NL_C(P_CS_PRECEDES); + DO_NL_C(P_SEP_BY_SPACE); + DO_NL_C(N_CS_PRECEDES); + DO_NL_C(N_SEP_BY_SPACE); + DO_NL_C(P_SIGN_POSN); + DO_NL_C(N_SIGN_POSN); + DO_NL_C(INT_P_CS_PRECEDES); + DO_NL_C(INT_P_SEP_BY_SPACE); + DO_NL_C(INT_N_CS_PRECEDES); + DO_NL_C(INT_N_SEP_BY_SPACE); + DO_NL_C(INT_P_SIGN_POSN); + DO_NL_C(INT_N_SIGN_POSN); + + DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */ + + DL_LC_LOOPTAIL(monetary) + } + + DO_LC_COMMON(monetary) +} + + +#undef DO_NL_S + +#define NUM_NL_messages 4 + +static int lc_messages_item[NUM_NL_messages][256]; +static int lc_messages_count[NUM_NL_messages]; +static unsigned char lc_messages_uniq_X[700][NUM_NL_messages]; +static int lc_messages_uniq; + +#define DO_NL_S(X) lc_messages_S(X, k++) + +static void lc_messages_S(int X, int k) +{ + int j, m; + j = addstring(nl_langinfo(X)); + for (m=0 ; m < lc_messages_count[k] ; m++) { + if (lc_messages_item[k][m] == j) { + break; + } + } + if (m == lc_messages_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_messages", k); + } + lc_messages_item[k][m] = j; + ++lc_messages_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_messages_uniq_X[lc_messages_uniq][k] = m; +} + +static void do_lc_messages(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(YESEXPR); + DO_NL_S(NOEXPR); + DO_NL_S(YESSTR); + DO_NL_S(NOSTR); + + DL_LC_LOOPTAIL(messages) + } + + DO_LC_COMMON(messages) +} + +#undef DO_NL_S + +#define NUM_NL_ctype 10 + +static int lc_ctype_item[NUM_NL_ctype][256]; +static int lc_ctype_count[NUM_NL_ctype]; +static unsigned char lc_ctype_uniq_X[700][NUM_NL_ctype]; +static int lc_ctype_uniq; + +#define DO_NL_S(X) lc_ctype_S(X, k++) + +static void lc_ctype_S(int X, int k) +{ + int j, m; + j = addstring(nl_langinfo(X)); + for (m=0 ; m < lc_ctype_count[k] ; m++) { + if (lc_ctype_item[k][m] == j) { + break; + } + } + if (m == lc_ctype_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_ctype", k); + } + lc_ctype_item[k][m] = j; + ++lc_ctype_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_ctype_uniq_X[lc_ctype_uniq][k] = m; +} + +static void do_lc_ctype(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB); + + DL_LC_LOOPTAIL(ctype) + } + + DO_LC_COMMON(ctype) +} diff --git a/extra/locale/gen_mmap.c b/extra/locale/gen_mmap.c new file mode 100644 index 0000000..1cf0bb9 --- /dev/null +++ b/extra/locale/gen_mmap.c @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include + +#define WANT_DATA +#include "c8tables.h" + +/* #define Cctype_TBL_LEN 328 */ +/* #define Cuplow_TBL_LEN 400 */ +/* #define Cc2wc_TBL_LEN 1448 */ +/* #define Cwc2c_TBL_LEN 3744 */ + +#define WANT_WCctype_data +#define WANT_WCuplow_data +#define WANT_WCuplow_diff_data +/* #define WANT_WCcomb_data */ +/* #define WANT_WCwidth_data */ +#include "wctables.h" +#undef WANT_WCctype_data +#undef WANT_WCuplow_data +#undef WANT_WCuplow_diff_data +/* #undef WANT_WCcomb_data */ +/* #undef WANT_WCwidth_data */ + +/* #define WCctype_TBL_LEN (WCctype_II_LEN + WCctype_TI_LEN + WCctype_UT_LEN) */ +/* #define WCuplow_TBL_LEN (WCuplow_II_LEN + WCuplow_TI_LEN + WCuplow_UT_LEN) */ +/* #define WCuplow_diff_TBL_LEN (2 * WCuplow_diffs) */ +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ + +#include "locale_tables.h" + +#include "locale_mmap.h" + +/* #undef __PASTE2 */ +/* #define __PASTE2(A,B) A ## B */ +/* #undef __PASTE3 */ +/* #define __PASTE3(A,B,C) A ## B ## C */ + + +/* #define MAGIC_SIZE 64 */ + +/* #define COMMON_MMAP(X) \ */ +/* unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; */ + +/* #define COMMON_MMIDX(X) \ */ +/* unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ */ + +#define WRITE_COMMON_MMAP(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_data_LEN) ; i++) { \ + putc(__PASTE3(__lc_,X,_data)[i], fp); \ + } + +#define WRITE_COMMON_MMIDX(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_rows_LEN) ; i++) { \ + putc(__PASTE3(__lc_,X,_rows)[i], fp); \ + } \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_item_offsets_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[1], fp); \ + } \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_item_idx_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[1], fp); \ + } + +#define WRITE_WC_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \ + putc(__PASTE3(WC,X,_data)[i], fp); \ + } + +#define WRITE_WC_I16_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[1], fp); \ + } + +#define WRITE_C_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \ + putc(__PASTE3(C,X,_data)[i], fp); \ + } + +#define WRITE_C_U16_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[1], fp); \ + } + +/**********************************************************************/ + +#define COMMON_OFFSETS(X) \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)) \ + + +static const size_t common_tbl_offsets[CATEGORIES*4] = { + 0, 0, 0, 0, /* ctype */ + COMMON_OFFSETS(numeric), + COMMON_OFFSETS(monetary), + COMMON_OFFSETS(time), + 0, 0, 0, 0, /* collate */ + COMMON_OFFSETS(messages), +}; + + + + + +int main(void) +{ + FILE *fp; + size_t i; + unsigned char *p; + + if (!(fp = fopen("locale.mmap", "w"))) { + printf("cannot open locale.mmap for writing!"); + return EXIT_FAILURE; + } + + for (i=0 ; i < sizeof(__locale_mmap_t) ; i++) { + putc(0, fp); /* Zero out the file. */ + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + WRITE_C_DATA(ctype); + WRITE_C_DATA(uplow); +#ifdef __WCHAR_ENABLED + WRITE_C_U16_DATA(c2wc); + WRITE_C_DATA(wc2c); + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __WCHAR_ENABLED + WRITE_WC_DATA(ctype); + WRITE_WC_DATA(uplow); + WRITE_WC_I16_DATA(uplow_diff); +/* WRITE_WC_DATA(comb); */ + /* width?? */ +#endif /* __WCHAR_ENABLED */ + + WRITE_COMMON_MMAP(numeric); + WRITE_COMMON_MMAP(monetary); + WRITE_COMMON_MMAP(time); + /* TODO -- collate*/ + WRITE_COMMON_MMAP(messages); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, codeset_8_bit), SEEK_SET); \ + p = (unsigned char *) codeset_8_bit; + for (i=0 ; i < sizeof(codeset_8_bit) ; i++) { + putc(p[i], fp); + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + WRITE_COMMON_MMIDX(numeric); + WRITE_COMMON_MMIDX(monetary); + WRITE_COMMON_MMIDX(time); + /* TODO -- collate*/ + WRITE_COMMON_MMIDX(messages); + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_item_offsets_LEN), SEEK_SET); + putc(1, fp); /* ctype -- (codeset) handled specially */ + putc(__lc_numeric_item_offsets_LEN, fp); + putc(__lc_monetary_item_offsets_LEN, fp); + putc(__lc_time_item_offsets_LEN, fp); + putc(0, fp); /* collate */ + putc(__lc_messages_item_offsets_LEN, fp); + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_tbl_offsets), SEEK_SET); + for (i=0 ; i < sizeof(common_tbl_offsets) ; i++) { + putc(((unsigned char *)common_tbl_offsets)[i], fp); + } + +#ifdef NUM_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, locales), SEEK_SET); + for (i=0 ; i < (NUM_LOCALES * WIDTH_LOCALES) ; i++) { + putc(__locales[i], fp); + } + + fseek(fp, (long) offsetof(__locale_mmap_t, locale_names5), SEEK_SET); + for (i=0 ; i < 5 * NUM_LOCALE_NAMES ; i++) { + putc(__locale_names5[i], fp); + } + +#ifdef LOCALE_AT_MODIFIERS_LENGTH + fseek(fp, (long) offsetof(__locale_mmap_t, locale_at_modifiers), SEEK_SET); + for (i=0 ; i < LOCALE_AT_MODIFIERS_LENGTH ; i++) { + putc(__locale_at_modifiers[i], fp); + } +#endif /* LOCALE_AT_MODIFIERS_LENGTH */ +#endif /* NUM_LOCALES */ + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_names), SEEK_SET); + for (i=0 ; i < lc_names_LEN ; i++) { + putc(lc_names[i], fp); + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, codeset_list), SEEK_SET); + for (i=0 ; i < sizeof(CODESET_LIST) ; i++) { + putc((unsigned char)(CODESET_LIST[i]), fp); + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + + if (ferror(fp) || (fclose(fp) == EOF)) { + printf("error - stream in error state or fclose failed!"); + return EXIT_FAILURE; + } + + printf("sizeof(__locale_mmap_t) = %zd\n", sizeof(__locale_mmap_t)); + + return EXIT_SUCCESS; +} + +/* TODO: + * collate data (8-bit weighted single char only) + * @ mappings! + * codeset list? yes, since we'll want to be able to inspect them... + * that means putting some header stuff in magic + * fix ctype LEN defines in gen_c8tables + */ diff --git a/extra/locale/gen_wc8bit.c b/extra/locale/gen_wc8bit.c new file mode 100644 index 0000000..20f8f64 --- /dev/null +++ b/extra/locale/gen_wc8bit.c @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#ifndef _CTYPE_H +#define _CTYPE_H +#endif +#ifndef _WCTYPE_H +#define _WCTYPE_H +#endif +#include UCLIBC_CTYPE_HEADER + + +/* #define CTYPE_PACKED */ +#define UPLOW_IDX_SHIFT 3 +/* best if 2 unpacked or 3 packed */ +#define CTYPE_IDX_SHIFT 3 +/* 3 or 4 are very similar */ +#define C2WC_IDX_SHIFT 3 + +#define CTYPE_IDX_LEN (128 >> (CTYPE_IDX_SHIFT)) +#define UPLOW_IDX_LEN (128 >> (UPLOW_IDX_SHIFT)) +#define C2WC_IDX_LEN (128 >> (C2WC_IDX_SHIFT)) + +/* #ifdef CTYPE_PACKED */ +/* #define CTYPE_ROW_LEN (1 << ((CTYPE_IDX_SHIFT)-1)) */ +/* #else */ +#define CTYPE_ROW_LEN (1 << (CTYPE_IDX_SHIFT)) +/* #endif */ +#define UPLOW_ROW_LEN (1 << (UPLOW_IDX_SHIFT)) +#define C2WC_ROW_LEN (1 << (C2WC_IDX_SHIFT)) + + + +#define MAX_WCHAR (0x2600-1) + +static unsigned char ctype_tbl[256 * CTYPE_ROW_LEN]; +static unsigned char uplow_tbl[256 * UPLOW_ROW_LEN]; +#ifdef DO_WIDE_CHAR +static unsigned short c2wc_tbl[256 * C2WC_ROW_LEN]; +#endif +static unsigned char tt[MAX_WCHAR+1]; +static unsigned char ti[MAX_WCHAR+1]; +static unsigned char xi[MAX_WCHAR+1]; + +static int n_ctype_rows; +static int n_uplow_rows; +#ifdef DO_WIDE_CHAR +static int n_c2wc_rows; +#endif +static int tt_num; +static int ti_num; + +#define RANGE MAX_WCHAR + +#define TT_SHIFT 4 +#define TI_SHIFT 4 + +#define II_LEN ((MAX_WCHAR+1) >> (TT_SHIFT+TI_SHIFT)) + +typedef struct { + unsigned long c2w[256]; + unsigned char w2c[MAX_WCHAR]; + unsigned char ii[II_LEN]; + unsigned char ctype_idx[CTYPE_IDX_LEN]; + unsigned char uplow_idx[UPLOW_IDX_LEN]; + unsigned char c2wc_idx[C2WC_IDX_LEN]; +} charset_data; + +int main(int argc, char **argv) +{ + FILE *fp; + FILE *out; + charset_data csd[30]; + unsigned long max_wchar; + unsigned char *p; + int numsets; + int i; + int j; + char buf[80]; + unsigned char row[256]; +#ifdef DO_WIDE_CHAR + unsigned short wrow[256]; +#endif + char codeset_list[500]; + char codeset_index[30]; + int codeset_list_end = 0; + int total_size = 0; + + if (!setlocale(LC_CTYPE, "en_US.UTF-8")) { + printf("setlocale(LC_CTYPE,\"en_US.UTF-8\") failed!\n"); + return EXIT_FAILURE; + } + + if (!(out = fopen("c8tables.h","w"))) { + printf("cannot open output file 'c8tables.h'!\n"); + return EXIT_FAILURE; + } + +#if 0 + if (argc == 1) { + /* User requested 8-bit codesets, but didn't list any... */ + /* Allow to build, just so this feature can be left on in config. */ + fprintf(out, "#ifdef __CTYPE_HAS_8_BIT_LOCALES\n"); + fprintf(out, "#warning ignoring 8 bit codesets request" + " as no codesets specified.\n"); + fprintf(out, "#endif\n"); + fprintf(out, "#undef __CTYPE_HAS_8_BIT_LOCALES\n\n"); + + fprintf(out, "#define __LOCALE_DATA_NUM_CODESETS\t\t0\n"); + fprintf(out, "#define __LOCALE_DATA_CODESET_LIST\t\t\"\"\n"); + fclose(out); + return EXIT_SUCCESS; + } + +/* fprintf(out, "#define __CTYPE_HAS_8_BIT_LOCALES\t1\n\n"); */ + fprintf(out, "#ifdef __CTYPE_HAS_8_BIT_LOCALES\n\n"); +#endif + + if (argc == 1) { + fprintf(out, "#undef __CTYPE_HAS_8_BIT_LOCALES\n\n"); + + fprintf(out, "#define __LOCALE_DATA_NUM_CODESETS\t\t0\n"); + fprintf(out, "#define __LOCALE_DATA_CODESET_LIST\t\t\"\"\n"); + } else { + fprintf(out, "#define __CTYPE_HAS_8_BIT_LOCALES\t\t1\n\n"); + } + + fprintf(out, "#define __LOCALE_DATA_Cctype_IDX_SHIFT\t%d\n", CTYPE_IDX_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cctype_IDX_LEN\t\t%d\n", CTYPE_IDX_LEN); +#ifdef CTYPE_PACKED + fprintf(out, "#define __LOCALE_DATA_Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN >> 1); + fprintf(out, "#define __LOCALE_DATA_Cctype_PACKED\t\t1\n"); +#else + fprintf(out, "#define __LOCALE_DATA_Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN); + fprintf(out, "#undef __LOCALE_DATA_Cctype_PACKED\n"); +#endif + + fprintf(out, "\n#define __LOCALE_DATA_Cuplow_IDX_SHIFT\t%d\n", UPLOW_IDX_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cuplow_IDX_LEN\t\t%d\n", UPLOW_IDX_LEN); + fprintf(out, "#define __LOCALE_DATA_Cuplow_ROW_LEN\t\t%d\n", UPLOW_ROW_LEN); + +#ifdef DO_WIDE_CHAR + fprintf(out, "\n#define __LOCALE_DATA_Cc2wc_IDX_LEN\t\t%d\n", C2WC_IDX_LEN); + fprintf(out, "#define __LOCALE_DATA_Cc2wc_IDX_SHIFT\t\t%d\n", C2WC_IDX_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cc2wc_ROW_LEN\t\t%d\n", C2WC_ROW_LEN); +#endif + + fprintf(out, "\ntypedef struct {\n"); + fprintf(out, "\tunsigned char idx8ctype[%d];\n", CTYPE_IDX_LEN); + fprintf(out, "\tunsigned char idx8uplow[%d];\n", UPLOW_IDX_LEN); +#ifdef DO_WIDE_CHAR + fprintf(out, "\tunsigned char idx8c2wc[%d];\n", C2WC_IDX_LEN); + fprintf(out, "\tunsigned char idx8wc2c[%d];\n", II_LEN); +#endif + fprintf(out, "} __codeset_8_bit_t;\n\n"); + + fprintf(out, "#ifdef WANT_DATA\n\n"); + fprintf(out, "static const __codeset_8_bit_t codeset_8_bit[%d] = {\n", argc-1); + + max_wchar = 0x7f; + numsets = 0; + codeset_index[0] = 0; + while (--argc) { + if (!(fp = fopen(*++argv,"r"))) { + printf("cannot open file \"%s\"\n", *argv); + return EXIT_FAILURE; + } + printf("processing %s... ", *argv); + + { + char *s0; + char *s1; + int n; + + s0 = strrchr(*argv, '/'); + if (!s0) { + s0 = *argv; + } else { + ++s0; + } + s1 = strrchr(s0, '.'); + if (!s1) { + n = strlen(s0); + } else { + n = s1 - s0; + } + +/* if ((numsets == 0) && strncmp("ASCII", s0, n)) { */ +/* printf("error - first codeset isn't ASCII!\n"); */ +/* return EXIT_FAILURE; */ +/* } */ + + if (numsets >= sizeof(codeset_index)) { + printf("error - too many codesets!\n"); + return EXIT_FAILURE; + } + + if (codeset_list_end + n + 1 + numsets + 1 + 1 >= 256) { + printf("error - codeset list to big!\n"); + return EXIT_FAILURE; + } + + codeset_index[numsets+1] = codeset_index[numsets] + n+1; + strncpy(codeset_list + codeset_list_end, s0, n); + codeset_list_end += (n+1); + codeset_list[codeset_list_end - 1] = 0; + + fprintf(out, "\t{ /* %.*s */", n, s0); + } + + memset(&csd[numsets],sizeof(charset_data),0); + memset(xi, sizeof(xi), 0); + { + unsigned long c, wc; + int lines; + lines = 0; + while (fgets(buf,sizeof(buf),fp)) { + if ((2 != sscanf(buf, "{ %lx , %lx", &c, &wc)) + || (c >= 256) || (wc > MAX_WCHAR)) { + printf("error: scanf failure! \"%s\"\n", buf); + return EXIT_FAILURE; + } + + /* don't put in w2c... dynamicly build tt instead. */ + + if (c <= 0x7f) { /* check the 7bit entries but don't store */ + if (c != wc) { + printf("error: c != wc in %s\n", buf); + return EXIT_FAILURE; + } + csd[numsets].c2w[c] = wc; + csd[numsets].w2c[wc] = 0; /* ignore */ + if (wc > max_wchar) { + max_wchar = wc; + } + } else { + csd[numsets].c2w[c] = wc; + csd[numsets].w2c[wc] = c; + if (wc > max_wchar) { + max_wchar = wc; + } + } + ++lines; + } + printf("%d lines ", lines); + + for (i = 0 ; i <= MAX_WCHAR ; i += (1 << TT_SHIFT)) { + p = &csd[numsets].w2c[i]; + for (j = 0 ; j < tt_num ; j++) { + if (!memcmp(p, &tt[j << TT_SHIFT], (1 << TT_SHIFT))) { + break; + } + } + if (j == tt_num) { /* new entry */ + memcpy(&tt[j << TT_SHIFT], p, (1 << TT_SHIFT)); + ++tt_num; + } + xi[i >> TT_SHIFT] = j; + } + + for (i = 0 ; i <= (MAX_WCHAR >> TT_SHIFT) ; i += (1 << TI_SHIFT)) { + p = &xi[i]; + for (j = 0 ; j < ti_num ; j++) { + if (!memcmp(p, &ti[j << TI_SHIFT], (1 << TI_SHIFT))) { + break; + } + } + if (j == ti_num) { /* new entry */ + memcpy(&ti[j << TI_SHIFT], p, (1 << TI_SHIFT)); + ++ti_num; + } + csd[numsets].ii[i >> TI_SHIFT] = j; +/* printf("%d ", i >> TI_SHIFT); */ + } + +#if 1 + fprintf(out, "\n\t\t/* idx8ctype data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { + wchar_t c; + unsigned int d; + +/* if (!(i & 0x7)) { */ +/* fprintf(out, "\n"); */ +/* } */ + + c = csd[numsets].c2w[i]; + + if (c == 0) { /* non-existant char in codeset */ + d = __CTYPE_unclassified; + } else if (iswdigit(c)) { + d = __CTYPE_digit; + } else if (iswalpha(c)) { + d = __CTYPE_alpha_nonupper_nonlower; + if (iswlower(c)) { + d = __CTYPE_alpha_lower; + if (iswupper(c)) { + d = __CTYPE_alpha_upper_lower; + } + } else if (iswupper(c)) { + d = __CTYPE_alpha_upper; + } + } else if (iswpunct(c)) { + d = __CTYPE_punct; + } else if (iswgraph(c)) { + d = __CTYPE_graph; + } else if (iswprint(c)) { + d = __CTYPE_print_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_print_space_blank; + } + } else if (iswspace(c) && !iswcntrl(c)) { + d = __CTYPE_space_nonblank_noncntrl; + if (iswblank(c)) { + d = __CTYPE_space_blank_noncntrl; + } + } else if (iswcntrl(c)) { + d = __CTYPE_cntrl_nonspace; + if (iswspace(c)) { + d = __CTYPE_cntrl_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_cntrl_space_blank; + } + } + } else { + d = __CTYPE_unclassified; + } + +#if 1 + row[i & (CTYPE_ROW_LEN-1)] = d; + if ((i & (CTYPE_ROW_LEN-1)) == (CTYPE_ROW_LEN-1)) { + p = ctype_tbl; + for (j=0 ; j < n_ctype_rows ; j++) { + if (!memcmp(p, row, CTYPE_ROW_LEN)) { + break; + } + p += CTYPE_ROW_LEN; + } + if (j == n_ctype_rows) { /* new entry */ + if (++n_ctype_rows > 256) { + printf("error -- to many ctype rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, row, CTYPE_ROW_LEN); + } + csd[numsets].ctype_idx[i >> CTYPE_IDX_SHIFT] = j; + if (!((i >> CTYPE_IDX_SHIFT) & 0x7) + && (i != (127 + CTYPE_ROW_LEN)) + ) { + fprintf(out, "\n\t\t "); + } + fprintf(out, " %#4x,", j); + } +#else + fprintf(out, " %#4x,", d); +#endif + } +#endif + fprintf(out, " }"); + +#if 1 + fprintf(out, ",\n\t\t/* idx8uplow data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { + wchar_t c, u, l; +/* if (!(i & 0x7)) { */ +/* fprintf(out, "\n"); */ +/* } */ + c = csd[numsets].c2w[i]; + if ((c != 0) || 1) { + u = towupper(c); + l = towlower(c); + + if (u >= 0x80) u = csd[numsets].w2c[u]; + if (l >= 0x80) l = csd[numsets].w2c[l]; + + if (u == 0) u = i; /* upper is missing, so ignore */ + if (l == 0) l = i; /* lower is missing, so ignore */ + +#if 1 + /* store as unsigned char and let overflow handle it. */ +/* if ((((u-i) < CHAR_MIN) || ((u-i) > CHAR_MAX)) */ +/* || (((i-l) < CHAR_MIN) || ((i-l) > CHAR_MAX)) */ +/* ) { */ +/* printf("error - uplow diff out of range! %d %ld %ld\n", */ +/* i, u, l); */ +/* return EXIT_FAILURE; */ +/* } */ + + row[i & (UPLOW_ROW_LEN-1)] = ((l==i) ? (u-i) : (i-l)); + if ((i & (UPLOW_ROW_LEN-1)) == (UPLOW_ROW_LEN-1)) { + p = uplow_tbl; + for (j=0 ; j < n_uplow_rows ; j++) { + if (!memcmp(p, row, UPLOW_ROW_LEN)) { + break; + } + p += UPLOW_ROW_LEN; + } + if (j == n_uplow_rows) { /* new entry */ + if (++n_uplow_rows > 256) { + printf("error -- to many uplow rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, row, UPLOW_ROW_LEN); + } + csd[numsets].uplow_idx[i >> UPLOW_IDX_SHIFT] = j; + if (!((i >> UPLOW_IDX_SHIFT) & 0x7) + && (i != (127 + UPLOW_ROW_LEN)) + ) { + fprintf(out, "\n\t\t "); + } + fprintf(out, " %#4x,", j); + } + +#elif 0 + if (!(i & 0x7) && i) { + fprintf(out, "\n"); + } + fprintf(out, " %4ld,", (l==i) ? (u-i) : (i-l)); +/* fprintf(out, " %4ld,", (l==i) ? u : l); */ +#else + if ((u != i) || (l != i)) { +#if 0 + fprintf(out, " %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, \n", + (unsigned long) i, + (unsigned long) c, + (unsigned long) l, + (unsigned long) towlower(c), + (unsigned long) u, + (unsigned long) towupper(c)); + +#else + fprintf(out, " %#08lx, %8ld, %d, %8ld, %d, %#08lx\n", + (unsigned long) i, + (long) (l - i), + iswupper(c), + (long) (i - u), + iswlower(c), + (unsigned long) c); +#endif + } +#endif + } + } + fprintf(out, " }"); +#endif + +#ifndef DO_WIDE_CHAR + fprintf(out,"\n"); +#else /* DO_WIDE_CHAR */ + +#if 1 + fprintf(out, ",\n\t\t/* idx8c2wc data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { +#if 1 + wrow[i & (C2WC_ROW_LEN-1)] = csd[numsets].c2w[i]; + if ((i & (C2WC_ROW_LEN-1)) == (C2WC_ROW_LEN-1)) { + p = (unsigned char *) c2wc_tbl; + for (j=0 ; j < n_c2wc_rows ; j++) { + if (!memcmp(p, (char *) wrow, 2*C2WC_ROW_LEN)) { + break; + } + p += 2*C2WC_ROW_LEN; + } + if (j == n_c2wc_rows) { /* new entry */ + if (++n_c2wc_rows > 256) { + printf("error -- to many c2wc rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, (char *) wrow, 2*C2WC_ROW_LEN); + } + csd[numsets].c2wc_idx[i >> C2WC_IDX_SHIFT] = j; + if (!((i >> C2WC_IDX_SHIFT) & 0x7) + && (i != (127 + C2WC_ROW_LEN)) + ) { + fprintf(out, "\n\t\t "); + } + fprintf(out, " %#4x,", j); + } +#else + if (!(i & 0x7) && i) { + fprintf(out, "\n"); + } + fprintf(out, " %#6lx,", csd[numsets].c2w[i]); +#endif + } + fprintf(out, " },\n"); +#endif + +#if 1 +/* fprintf(out, "\nII_LEN = %d\n", II_LEN); */ + fprintf(out, "\t\t/* idx8wc2c data */\n\t\t{"); + for (i = 0 ; i < II_LEN ; i++) { + if (!(i & 0x7) && i) { + fprintf(out, "\n\t\t "); + } + fprintf(out, " %#4x,", csd[numsets].ii[i]); + } + fprintf(out, " }\n"); +#endif + +#endif /* DO_WIDE_CHAR */ + fprintf(out, "\t},\n"); + + } + ++numsets; + printf("done\n"); + } + fprintf(out, "};\n"); + fprintf(out, "\n#endif /* WANT_DATA */\n"); + +#ifdef DO_WIDE_CHAR + fprintf(out, "\n"); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_DOMAIN_MAX\t%#x\n", RANGE); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_TI_SHIFT\t\t%d\n", TI_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_TT_SHIFT\t\t%d\n", TT_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_II_LEN\t\t%d\n", II_LEN); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_TI_LEN\t\t%d\n", ti_num << TI_SHIFT); + fprintf(out, "#define __LOCALE_DATA_Cwc2c_TT_LEN\t\t%d\n", tt_num << TT_SHIFT); + fprintf(out, "\n"); + + fprintf(out, "\n#define __LOCALE_DATA_Cwc2c_TBL_LEN\t\t%d\n", + (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT)); + + fprintf(out, "#ifdef WANT_DATA\n\n"); + fprintf(out, "static const unsigned char __LOCALE_DATA_Cwc2c_data[%d] = {\n", + (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT)); + fprintf(out, "\t/* ti_table */\n\t"); + for (i=0 ; i < ti_num << TI_SHIFT ; i++) { + if (!(i & 7) && i) { + fprintf(out, "\n\t"); + } + fprintf(out, " %#4x,", ti[i]); + } + fprintf(out, "\n"); + fprintf(out, "\t/* tt_table */\n\t"); + for (i=0 ; i < tt_num << TT_SHIFT ; i++) { + if (!(i & 7) && i) { + fprintf(out, "\n\t"); + } + fprintf(out, " %#4x,", tt[i]); + } + fprintf(out, "\n};\n"); + + fprintf(out, "\n#endif /* WANT_DATA */\n"); +#endif /* DO_WIDE_CHAR */ + + fprintf(out, "\n#define __LOCALE_DATA_Cuplow_TBL_LEN\t\t%d\n", + n_uplow_rows * UPLOW_ROW_LEN); + fprintf(out, "\n#ifdef WANT_DATA\n\n"); + + fprintf(out, "\nstatic const unsigned char __LOCALE_DATA_Cuplow_data[%d] = {\n", + n_uplow_rows * UPLOW_ROW_LEN); + p = uplow_tbl; + for (j=0 ; j < n_uplow_rows ; j++) { + fprintf(out, "\t"); + for (i=0 ; i < UPLOW_ROW_LEN ; i++) { + fprintf(out, " %#4x,", (unsigned int)((unsigned char) p[i])); + } + fprintf(out, "\n"); + p += UPLOW_ROW_LEN; + } + fprintf(out, "};\n"); + + fprintf(out, "\n#endif /* WANT_DATA */\n"); + fprintf(out, "\n#define __LOCALE_DATA_Cctype_TBL_LEN\t\t%d\n", +#ifdef CTYPE_PACKED + n_ctype_rows * CTYPE_ROW_LEN / 2 +#else + n_ctype_rows * CTYPE_ROW_LEN +#endif + ); + fprintf(out, "\n#ifdef WANT_DATA\n\n"); + + + fprintf(out, "\nstatic const unsigned char __LOCALE_DATA_Cctype_data[%d] = {\n", +#ifdef CTYPE_PACKED + n_ctype_rows * CTYPE_ROW_LEN / 2 +#else + n_ctype_rows * CTYPE_ROW_LEN +#endif + ); + p = ctype_tbl; + for (j=0 ; j < n_ctype_rows ; j++) { + fprintf(out, "\t"); + for (i=0 ; i < CTYPE_ROW_LEN ; i++) { +#ifdef CTYPE_PACKED + fprintf(out, " %#4x,", (unsigned int)(p[i] + (p[i+1] << 4))); + ++i; +#else + fprintf(out, " %#4x,", (unsigned int)p[i]); +#endif + } + fprintf(out, "\n"); + p += CTYPE_ROW_LEN; + } + fprintf(out, "};\n"); + + fprintf(out, "\n#endif /* WANT_DATA */\n"); + +#ifdef DO_WIDE_CHAR + + fprintf(out, "\n#define __LOCALE_DATA_Cc2wc_TBL_LEN\t\t%d\n", + n_c2wc_rows * C2WC_ROW_LEN); + fprintf(out, "\n#ifdef WANT_DATA\n\n"); + + fprintf(out, "\nstatic const unsigned short __LOCALE_DATA_Cc2wc_data[%d] = {\n", + n_c2wc_rows * C2WC_ROW_LEN); + p = (unsigned char *) c2wc_tbl; + for (j=0 ; j < n_c2wc_rows ; j++) { + fprintf(out, "\t"); + for (i=0 ; i < C2WC_ROW_LEN ; i++) { + fprintf(out, " %#6x,", (unsigned int)(((unsigned short *)p)[i])); + } + fprintf(out, "\n"); + p += 2*C2WC_ROW_LEN; + } + fprintf(out, "};\n"); + fprintf(out, "\n#endif /* WANT_DATA */\n"); +#endif /* DO_WIDE_CHAR */ + fprintf(out, "\n\n"); + + fprintf(out, "#define __LOCALE_DATA_NUM_CODESETS\t\t%d\n", numsets); + fprintf(out, "#define __LOCALE_DATA_CODESET_LIST \\\n\t\""); + for (i=0 ; i < numsets ; i++) { + fprintf(out, "\\x%02x", numsets + 1 + (unsigned char) codeset_index[i]); + if (((i & 7) == 7) && (i + 1 < numsets)) { + fprintf(out, "\" \\\n\t\""); + } + } + fprintf(out, "\" \\\n\t\"\\0\""); + for (i=0 ; i < numsets ; i++) { + fprintf(out, " \\\n\t\"%s\\0\"", + codeset_list + ((unsigned char)codeset_index[i])); + } + + fprintf(out, "\n\n"); + for (i=0 ; i < numsets ; i++) { + char buf[30]; + char *z; + strcpy(buf, codeset_list + ((unsigned char)codeset_index[i])); + for (z=buf ; *z ; z++) { + if (*z == '-') { + *z = '_'; + } + } + fprintf(out, "#define __CTYPE_HAS_CODESET_%s\n", buf); + } +#ifdef DO_WIDE_CHAR + fprintf(out, "#define __CTYPE_HAS_CODESET_UTF_8\n"); +#endif /* DO_WIDE_CHAR */ + +#if 0 + fprintf(out, "\n#endif /* __CTYPE_HAS_8_BIT_LOCALES */\n\n"); +#endif + + fclose(out); + + total_size = 0; +#ifdef DO_WIDE_CHAR + printf("tt_num = %d ti_num = %d\n", tt_num, ti_num); + printf("max_wchar = %#lx\n", max_wchar); + + printf("size is %d * %d + %d * %d + %d * %d = %d\n", + tt_num, 1 << TT_SHIFT, ti_num, 1 << TI_SHIFT, + ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1), numsets, + j = tt_num * (1 << TT_SHIFT) + ti_num * (1 << TI_SHIFT) + + ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1) * numsets); + total_size += j; +#endif /* DO_WIDE_CHAR */ + +#ifdef CTYPE_PACKED + i = 2; +#else + i = 1; +#endif + + printf("ctype - CTYPE_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n", + CTYPE_IDX_SHIFT, numsets, CTYPE_IDX_LEN, n_ctype_rows, CTYPE_ROW_LEN / i, + j = numsets * CTYPE_IDX_LEN + n_ctype_rows * CTYPE_ROW_LEN / i); + total_size += j; + + printf("uplow - UPLOW_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n", + UPLOW_IDX_SHIFT, numsets, UPLOW_IDX_LEN, n_uplow_rows, UPLOW_ROW_LEN, + j = numsets * UPLOW_IDX_LEN + n_uplow_rows * UPLOW_ROW_LEN); + total_size += j; + +#ifdef DO_WIDE_CHAR + + printf("c2wc - C2WC_IDX_SHIFT = %d -- %d * %d + 2 * %d * %d = %d\n", + C2WC_IDX_SHIFT, numsets, C2WC_IDX_LEN, n_c2wc_rows, C2WC_ROW_LEN, + j = numsets * C2WC_IDX_LEN + 2 * n_c2wc_rows * C2WC_ROW_LEN); + total_size += j; + +#endif /* DO_WIDE_CHAR */ + + printf("total size = %d\n", total_size); + +/* for (i=0 ; i < numsets ; i++) { */ +/* printf("codeset_index[i] = %d codeset_list[ci[i]] = \"%s\"\n", */ +/* (unsigned char) codeset_index[i], */ +/* codeset_list + ((unsigned char)codeset_index[i])); */ +/* } */ + + return EXIT_SUCCESS; +} diff --git a/extra/locale/gen_wctype.c b/extra/locale/gen_wctype.c new file mode 100644 index 0000000..a0542e6 --- /dev/null +++ b/extra/locale/gen_wctype.c @@ -0,0 +1,892 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _CTYPE_H +#define _CTYPE_H +#endif +#ifndef _WCTYPE_H +#define _WCTYPE_H +#endif +#include UCLIBC_CTYPE_HEADER + +/* 0x9 : space blank */ +/* 0xa : space */ +/* 0xb : space */ +/* 0xc : space */ +/* 0xd : space */ +/* 0x20 : space blank */ +/* 0x1680 : space blank */ +/* 0x2000 : space blank */ +/* 0x2001 : space blank */ +/* 0x2002 : space blank */ +/* 0x2003 : space blank */ +/* 0x2004 : space blank */ +/* 0x2005 : space blank */ +/* 0x2006 : space blank */ +/* 0x2008 : space blank */ +/* 0x2009 : space blank */ +/* 0x200a : space blank */ +/* 0x200b : space blank */ +/* 0x2028 : space */ +/* 0x2029 : space */ +/* 0x3000 : space blank */ + +/* typecount[ 0] = 88670 C_alpha_nonupper_nonlower */ +/* typecount[ 1] = 742 C_alpha_lower */ +/* typecount[ 2] = 4 C_alpha_upper_lower */ +/* typecount[ 3] = 731 C_alpha_upper */ +/* typecount[ 4] = 10 C_digit */ +/* typecount[ 5] = 10270 C_punct */ +/* typecount[ 6] = 0 C_graph */ +/* typecount[ 7] = 0 C_print_space_nonblank */ +/* typecount[ 8] = 14 C_print_space_blank */ +/* typecount[ 9] = 0 C_space_nonblank_noncntrl */ +/* typecount[10] = 0 C_space_blank_noncntrl */ +/* typecount[11] = 6 C_cntrl_space_nonblank */ +/* typecount[12] = 1 C_cntrl_space_blank */ +/* typecount[13] = 60 C_cntrl_nonspace */ +/* typecount[14] = 96100 C_unclassified */ +/* typecount[15] = 0 empty_slot */ + + + +/* Set to #if 0 to restrict wchars to 16 bits. */ +#if 1 +#define RANGE 0x2ffffUL +#elif 0 +#define RANGE 0x1ffffUL +#else +#define RANGE 0xffffUL /* Restrict for 16-bit wchar_t... */ +#endif + +#if 0 +/* Classification codes. */ + +static const char *typename[] = { + "C_unclassified", + "C_alpha_nonupper_nonlower", + "C_alpha_lower", + "C_alpha_upper_lower", + "C_alpha_upper", + "C_digit", + "C_punct", + "C_graph", + "C_print_space_nonblank", + "C_print_space_blank", + "C_space_nonblank_noncntrl", + "C_space_blank_noncntrl", + "C_cntrl_space_nonblank", + "C_cntrl_space_blank", + "C_cntrl_nonspace", + "empty_slot" +}; +#endif + +#if 0 +/* Taking advantage of the C99 mutual-exclusion guarantees for the various + * (w)ctype classes, including the descriptions of printing and control + * (w)chars, we can place each in one of the following mutually-exlusive + * subsets. Since there are less than 16, we can store the data for + * each (w)chars in a nibble. In contrast, glibc uses an unsigned int + * per (w)char, with one bit flag for each is* type. While this allows + * a simple '&' operation to determine the type vs. a range test and a + * little special handling for the "blank" and "xdigit" types in my + * approach, it also uses 8 times the space for the tables on the typical + * 32-bit archs we supported.*/ +enum { + __CTYPE_unclassified = 0, + __CTYPE_alpha_nonupper_nonlower, + __CTYPE_alpha_lower, + __CTYPE_alpha_upper_lower, + __CTYPE_alpha_upper, + __CTYPE_digit, + __CTYPE_punct, + __CTYPE_graph, + __CTYPE_print_space_nonblank, + __CTYPE_print_space_blank, + __CTYPE_space_nonblank_noncntrl, + __CTYPE_space_blank_noncntrl, + __CTYPE_cntrl_space_nonblank, + __CTYPE_cntrl_space_blank, + __CTYPE_cntrl_nonspace, +}; +#endif + +#define __CTYPE_isxdigit(D,X) \ + (__CTYPE_isdigit(D) || (((unsigned int)(((X)|0x20) - 'a')) <= 5)) + +#define mywalnum(x) __CTYPE_isalnum(d) +#define mywalpha(x) __CTYPE_isalpha(d) +#define mywblank(x) __CTYPE_isblank(d) +#define mywcntrl(x) __CTYPE_iscntrl(d) +#define mywdigit(x) __CTYPE_isdigit(d) +#define mywgraph(x) __CTYPE_isgraph(d) +#define mywlower(x) __CTYPE_islower(d) +#define mywprint(x) __CTYPE_isprint(d) +#define mywpunct(x) __CTYPE_ispunct(d) +#define mywspace(x) __CTYPE_isspace(d) +#define mywupper(x) __CTYPE_isupper(d) +#define mywxdigit(x) __CTYPE_isxdigit(d,x) + +typedef struct { + short l; + short u; +} uldiff_entry; + +typedef struct { + uint16_t ii_len; + uint16_t ti_len; + uint16_t ut_len; + + unsigned char ii_shift; + unsigned char ti_shift; + + unsigned char *ii; + unsigned char *ti; + unsigned char *ut; +} table_data; + +static unsigned verbose; +#define verbose_msg(msg...) if (verbose) fprintf(stderr, msg) + +void output_table(FILE *fp, const char *name, table_data *tbl) +{ + size_t i; + + fprintf(fp, "#define __LOCALE_DATA_WC%s_II_LEN %7u\n", name, tbl->ii_len); + fprintf(fp, "#define __LOCALE_DATA_WC%s_TI_LEN %7u\n", name, tbl->ti_len); + fprintf(fp, "#define __LOCALE_DATA_WC%s_UT_LEN %7u\n", name, tbl->ut_len); + + fprintf(fp, "#define __LOCALE_DATA_WC%s_II_SHIFT %7u\n", name, tbl->ii_shift); + fprintf(fp, "#define __LOCALE_DATA_WC%s_TI_SHIFT %7u\n", name, tbl->ti_shift); + + fprintf(fp, "\n#ifdef WANT_WC%s_data\n", name); + + i = tbl->ii_len + tbl->ti_len + tbl->ut_len; + fprintf(fp, "\nstatic const unsigned char __LOCALE_DATA_WC%s_data[%zu] = {", name, i); + for (i=0 ; i < tbl->ii_len ; i++) { + if (i % 12 == 0) { + fprintf(fp, "\n"); + } + fprintf(fp, " %#04x,", tbl->ii[i]); + } + for (i=0 ; i < tbl->ti_len ; i++) { + if (i % 12 == 0) { + fprintf(fp, "\n"); + } + fprintf(fp, " %#04x,", tbl->ti[i]); + } + for (i=0 ; i < tbl->ut_len ; i++) { + if (i % 12 == 0) { + fprintf(fp, "\n"); + } + fprintf(fp, " %#04x,", tbl->ut[i]); + } + fprintf(fp, "\n};\n\n"); + + fprintf(fp, "#endif /* WANT_WC%s_data */\n\n", name); +} + +static void dump_table_data(table_data *tbl) +{ + verbose_msg("ii_shift = %d ti_shift = %d\n" + "ii_len = %d ti_len = %d ut_len = %d\n" + "total = %d\n", + tbl->ii_shift, tbl->ti_shift, + tbl->ii_len, tbl->ti_len, tbl->ut_len, + (int) tbl->ii_len + (int) tbl->ti_len + (int) tbl->ut_len); +} + +/* For sorting the blocks of unsigned chars. */ +static size_t nu_val; + +int nu_memcmp(const void *a, const void *b) +{ + return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val); +} + +static size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl); + +#define MAXTO 255 /* Restrict to minimal unsigned char max. */ + +int main(int argc, char **argv) +{ + long int u, l, tt; + size_t smallest, t; + unsigned int c; + unsigned int d; + int i, n; + int ul_count = 0; + uldiff_entry uldiff[MAXTO]; + table_data cttable; + table_data ultable; +#if 0 + table_data combtable; + table_data widthtable; + long int last_comb = 0; +#endif + unsigned char wct[(RANGE/2)+1]; /* wctype table (nibble per wchar) */ + unsigned char ult[RANGE+1]; /* upper/lower table */ + unsigned char combt[(RANGE/4)+1]; /* combining */ + unsigned char widtht[(RANGE/4)+1]; /* width */ + wctrans_t totitle; + wctype_t is_comb, is_comb3; + + long int typecount[16]; + const char *typename[16]; + static const char empty_slot[] = "empty_slot"; + int built = 0; + +#define INIT_TYPENAME(X) typename[__CTYPE_##X] = "C_" #X + + for (i=0 ; i < 16 ; i++) { + typename[i] = empty_slot; + } + + INIT_TYPENAME(unclassified); + INIT_TYPENAME(alpha_nonupper_nonlower); + INIT_TYPENAME(alpha_lower); + INIT_TYPENAME(alpha_upper_lower); + INIT_TYPENAME(alpha_upper); + INIT_TYPENAME(digit); + INIT_TYPENAME(punct); + INIT_TYPENAME(graph); + INIT_TYPENAME(print_space_nonblank); + INIT_TYPENAME(print_space_blank); + INIT_TYPENAME(space_nonblank_noncntrl); + INIT_TYPENAME(space_blank_noncntrl); + INIT_TYPENAME(cntrl_space_nonblank); + INIT_TYPENAME(cntrl_space_blank); + INIT_TYPENAME(cntrl_nonspace); + + memset(&cttable, 0, sizeof(table_data)); + memset(&ultable, 0, sizeof(table_data)); +#if 0 + memset(combtable, 0, sizeof table_data); + memset(widthtable, 0, sizeof table_data); +#endif + setvbuf(stdout, NULL, _IONBF, 0); + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-v")) { + ++verbose; + continue; + } else if (!setlocale(LC_CTYPE, *argv)) { + verbose_msg("setlocale(LC_CTYPE,%s) failed! Skipping this locale...\n", *argv); + continue; + } + + if (!(totitle = wctrans("totitle"))) { + verbose_msg("no totitle transformation.\n"); + } + if (!(is_comb = wctype("combining"))) { + verbose_msg("no combining wctype.\n"); + } + if (!(is_comb3 = wctype("combining_level3"))) { + verbose_msg("no combining_level3 wctype.\n"); + } + + if (!built) { + built = 1; + ul_count = 1; + uldiff[0].u = uldiff[0].l = 0; + + memset(wct, 0, sizeof(wct)); + memset(combt, 0, sizeof(combt)); + memset(widtht, 0, sizeof(widtht)); + + for (i = 0 ; i < 16 ; i++) { + typecount[i] = 0; + } + + for (c=0 ; c <= RANGE ; c++) { + if (iswdigit(c)) { + d = __CTYPE_digit; + } else if (iswalpha(c)) { + d = __CTYPE_alpha_nonupper_nonlower; + if (iswlower(c)) { + d = __CTYPE_alpha_lower; + if (iswupper(c)) { + d = __CTYPE_alpha_upper_lower; + } + } else if (iswupper(c)) { + d = __CTYPE_alpha_upper; + } + } else if (iswpunct(c)) { + d = __CTYPE_punct; + } else if (iswgraph(c)) { + d = __CTYPE_graph; + } else if (iswprint(c)) { + d = __CTYPE_print_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_print_space_blank; + } + } else if (iswspace(c) && !iswcntrl(c)) { + d = __CTYPE_space_nonblank_noncntrl; + if (iswblank(c)) { + d = __CTYPE_space_blank_noncntrl; + } + } else if (iswcntrl(c)) { + d = __CTYPE_cntrl_nonspace; + if (iswspace(c)) { + d = __CTYPE_cntrl_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_cntrl_space_blank; + } + } + } else { + d = __CTYPE_unclassified; + } + + ++typecount[d]; + +#if 0 + if (iswspace(c)) { + if (iswblank(c)) { + verbose_msg("%#8x : space blank\n", c); + } else { + verbose_msg("%#8x : space\n", c); + } + } +#endif + +#if 0 + if (c < 256) { + unsigned int glibc; + + glibc = 0; + if (isalnum(c)) ++glibc; glibc <<= 1; + if (isalpha(c)) ++glibc; glibc <<= 1; + if (isblank(c)) ++glibc; glibc <<= 1; + if (iscntrl(c)) ++glibc; glibc <<= 1; + if (isdigit(c)) ++glibc; glibc <<= 1; + if (isgraph(c)) ++glibc; glibc <<= 1; + if (islower(c)) ++glibc; glibc <<= 1; + if (isprint(c)) ++glibc; glibc <<= 1; + if (ispunct(c)) ++glibc; glibc <<= 1; + if (isspace(c)) ++glibc; glibc <<= 1; + if (isupper(c)) ++glibc; glibc <<= 1; + if (isxdigit(c)) ++glibc; + verbose_msg("%#8x : ctype %#4x\n", c, glibc); + } +#endif + +#if 1 + /* Paranoid checking... */ + { + unsigned int glibc; + unsigned int mine; + + glibc = 0; + if (iswalnum(c)) ++glibc; glibc <<= 1; + if (iswalpha(c)) ++glibc; glibc <<= 1; + if (iswblank(c)) ++glibc; glibc <<= 1; + if (iswcntrl(c)) ++glibc; glibc <<= 1; + if (iswdigit(c)) ++glibc; glibc <<= 1; + if (iswgraph(c)) ++glibc; glibc <<= 1; + if (iswlower(c)) ++glibc; glibc <<= 1; + if (iswprint(c)) ++glibc; glibc <<= 1; + if (iswpunct(c)) ++glibc; glibc <<= 1; + if (iswspace(c)) ++glibc; glibc <<= 1; + if (iswupper(c)) ++glibc; glibc <<= 1; + if (iswxdigit(c)) ++glibc; + + mine = 0; + if (mywalnum(c)) ++mine; mine <<= 1; + if (mywalpha(c)) ++mine; mine <<= 1; + if (mywblank(c)) ++mine; mine <<= 1; + if (mywcntrl(c)) ++mine; mine <<= 1; + if (mywdigit(c)) ++mine; mine <<= 1; + if (mywgraph(c)) ++mine; mine <<= 1; + if (mywlower(c)) ++mine; mine <<= 1; + if (mywprint(c)) ++mine; mine <<= 1; + if (mywpunct(c)) ++mine; mine <<= 1; + if (mywspace(c)) ++mine; mine <<= 1; + if (mywupper(c)) ++mine; mine <<= 1; + if (mywxdigit(c)) ++mine; + + if (glibc != mine) { + verbose_msg("%#8x : glibc %#4x != %#4x mine %u\n", c, glibc, mine, d); + return EXIT_FAILURE; + } + +#if 0 + if (iswctype(c,is_comb) || iswctype(c,is_comb3)) { +/* if (!iswpunct(c)) { */ + verbose_msg("%#8x : %d %d %#4x\n", + c, iswctype(c,is_comb),iswctype(c,is_comb3), glibc); +/* } */ + } +#endif +#if 0 + if (iswctype(c,is_comb) || iswctype(c,is_comb3)) { + if (!last_comb) { + verbose_msg("%#8x - ", c); + last_comb = c; + } else if (last_comb + 1 < c) { + verbose_msg("%#8x\n%#8x - ", last_comb, c); + last_comb = c; + } else { + last_comb = c; + } + } +#endif + } +#endif + + combt[c/4] |= ((((!!iswctype(c,is_comb)) << 1) | !!iswctype(c,is_comb3)) + << ((c & 3) << 1)); +/* comb3t[c/8] |= ((!!iswctype(c,is_comb3)) << (c & 7)); */ + +/* widtht[c/4] |= (wcwidth(c) << ((c & 3) << 1)); */ + + if (c & 1) { /* Use the high nibble for odd numbered wchars. */ + d <<= 4; + } + wct[c/2] |= d; + + l = (long)(int) towlower(c) - c; + u = (long)(int) towupper(c) - c; + ult[c] = 0; + if (l || u) { + if ((l != (short)l) || (u != (short)u)) { + verbose_msg("range assumption error! %x %ld %ld\n", c, l, u); + return EXIT_FAILURE; + } + for (i=0 ; i < ul_count ; i++) { + if ((l == uldiff[i].l) && (u == uldiff[i].u)) { + goto found; + } + } + uldiff[ul_count].l = l; + uldiff[ul_count].u = u; + ++ul_count; + if (ul_count > MAXTO) { + verbose_msg("too many touppers/tolowers!\n"); + return EXIT_FAILURE; + } + found: + ult[c] = i; + } + } + + for (i = 0 ; i < 16 ; i++) { + verbose_msg("typecount[%2d] = %8ld %s\n", i, typecount[i], typename[i]); + } + + verbose_msg("optimizing is* table..\n"); + n = -1; + smallest = SIZE_MAX; + cttable.ii = NULL; + for (i=0 ; i < 14 ; i++) { + t = newopt(wct, (RANGE/2)+1, i, &cttable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(cttable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(wct, (RANGE/2)+1, n, &cttable); + ++cttable.ti_shift; /* correct for nibble mode */ + + + + verbose_msg("optimizing u/l-to table..\n"); + smallest = SIZE_MAX; + ultable.ii = NULL; + for (i=0 ; i < 14 ; i++) { + t = newopt(ult, RANGE+1, i, &ultable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("%zu (smallest) + %zu (u/l diffs) = %zu\n", + smallest, 4 * ul_count, smallest + 4 * ul_count); + verbose_msg("smallest = %zu\n", smallest); + if (!(ultable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(ult, RANGE+1, n, &ultable); + + +#if 0 + verbose_msg("optimizing comb table..\n"); + smallest = SIZE_MAX; + combtable.ii = NULL; + for (i=0 ; i < 14 ; i++) { + t = newopt(combt, sizeof(combt), i, &combtable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(combtable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(combt, sizeof(combt), n, &combtable); + combtable.ti_shift += 4; /* correct for 4 entries per */ +#endif + + +#if 0 + verbose_msg("optimizing width table..\n"); + smallest = SIZE_MAX; + widthtable.ii = NULL; + for (i=0 ; i < 14 ; i++) { + t = newopt(widtht, sizeof(widtht), i, &widthtable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(widthtable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(widtht, sizeof(widtht), n, &widthtable); + widthtable.ti_shift += 4; /* correct for 4 entries per */ +#endif + +#if 0 + verbose_msg("optimizing comb3 table..\n"); + smallest = SIZE_MAX; + comb3table.ii = NULL; + for (i=0 ; i < 14 ; i++) { + t = newopt(comb3t, sizeof(comb3t), i, &comb3table); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(comb3table.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(comb3t, sizeof(comb3t), n, &comb3table); + comb3table.ti_shift += 8; /* correct for 4 entries per */ +#endif + + dump_table_data(&cttable); + dump_table_data(&ultable); +#if 0 + dump_table_data(&combtable); +#endif + } + + verbose_msg("verifying for %s...\n", *argv); +#if RANGE == 0xffffU + for (c=0 ; c <= 0xffffUL ; c++) +#else + for (c=0 ; c <= 0x10ffffUL ; c++) +#endif + { + unsigned int glibc; + unsigned int mine; + unsigned int upper, lower; + +#if 0 +#if RANGE < 0x10000UL + if (c == 0x10000UL) { + c = 0x30000UL; /* skip 1st and 2nd sup planes */ + } +#elif RANGE < 0x20000UL + if (c == 0x20000UL) { + c = 0x30000UL; /* skip 2nd sup planes */ + } +#endif +#endif + + glibc = 0; + if (iswalnum(c)) ++glibc; glibc <<= 1; + if (iswalpha(c)) ++glibc; glibc <<= 1; + if (iswblank(c)) ++glibc; glibc <<= 1; + if (iswcntrl(c)) ++glibc; glibc <<= 1; + if (iswdigit(c)) ++glibc; glibc <<= 1; + if (iswgraph(c)) ++glibc; glibc <<= 1; + if (iswlower(c)) ++glibc; glibc <<= 1; + if (iswprint(c)) ++glibc; glibc <<= 1; + if (iswpunct(c)) ++glibc; glibc <<= 1; + if (iswspace(c)) ++glibc; glibc <<= 1; + if (iswupper(c)) ++glibc; glibc <<= 1; + if (iswxdigit(c)) ++glibc; + + { + unsigned int u; + int n, sc; + int i0, i1; + + u = c; + if (u <= RANGE) { + sc = u & ((1 << cttable.ti_shift) - 1); + u >>= cttable.ti_shift; + n = u & ((1 << cttable.ii_shift) - 1); + u >>= cttable.ii_shift; + + i0 = cttable.ii[u]; + i0 <<= cttable.ii_shift; + i1 = cttable.ti[i0 + n]; + i1 <<= (cttable.ti_shift-1); + d = cttable.ut[i1 + (sc >> 1)]; + + if (sc & 1) { + d >>= 4; + } + d &= 0x0f; + } else if ((((unsigned int)(c - 0xe0020UL)) <= 0x5f) || (c == 0xe0001UL)){ + d = __CTYPE_punct; + } else if (((unsigned int)(c - 0xf0000UL)) < 0x20000UL) { + if ((c & 0xffffU) <= 0xfffdU) { + d = __CTYPE_punct; + } else { + d = __CTYPE_unclassified; + } + } else { + d = __CTYPE_unclassified; + } + + mine = 0; + if (mywalnum(c)) ++mine; mine <<= 1; + if (mywalpha(c)) ++mine; mine <<= 1; + if (mywblank(c)) ++mine; mine <<= 1; + if (mywcntrl(c)) ++mine; mine <<= 1; + if (mywdigit(c)) ++mine; mine <<= 1; + if (mywgraph(c)) ++mine; mine <<= 1; + if (mywlower(c)) ++mine; mine <<= 1; + if (mywprint(c)) ++mine; mine <<= 1; + if (mywpunct(c)) ++mine; mine <<= 1; + if (mywspace(c)) ++mine; mine <<= 1; + if (mywupper(c)) ++mine; mine <<= 1; + if (mywxdigit(c)) ++mine; + + if (glibc != mine) { + verbose_msg("%#8x : glibc %#4x != %#4x mine %d\n", c, glibc, mine, d); + if (c < 0x30000UL) { + verbose_msg("sc=%#x u=%#x n=%#x i0=%#x i1=%#x\n", sc, u, n, i0, i1); + } + } + upper = lower = u = c; + if (u <= RANGE) { + sc = u & ((1 << ultable.ti_shift) - 1); + u >>= ultable.ti_shift; + n = u & ((1 << ultable.ii_shift) - 1); + u >>= ultable.ii_shift; + + i0 = ultable.ii[u]; + i0 <<= ultable.ii_shift; + i1 = ultable.ti[i0 + n]; + i1 <<= (ultable.ti_shift); + i1 += sc; + i0 = ultable.ut[i1]; + upper = c + uldiff[i0].u; + lower = c + uldiff[i0].l; + } + + if (towupper(c) != upper) { + verbose_msg("%#8x : towupper glibc %#4x != %#4x mine\n", + c, towupper(c), upper); + } + + if (towlower(c) != lower) { + verbose_msg("%#8x : towlower glibc %#4x != %#4x mine i0 = %d\n", + c, towlower(c), lower, i0); + } + + if (totitle && ((tt = towctrans(c, totitle)) != upper)) { + verbose_msg("%#8x : totitle glibc %#4lx != %#4x mine i0 = %d\n", + c, tt, upper, i0); + } + } + + + if ((c & 0xfff) == 0xfff) verbose_msg("."); + } + verbose_msg("done\n"); + } + + if (built) { + FILE *fp; + + if (!(fp = fopen("wctables.h", "w"))) { + verbose_msg("cannot open output file 'wctables.h'!\n"); + return EXIT_FAILURE; + } + + fprintf(fp, "#define __LOCALE_DATA_WC_TABLE_DOMAIN_MAX %#8lx\n\n", + (unsigned long) RANGE); + output_table(fp, "ctype", &cttable); + output_table(fp, "uplow", &ultable); + + +#warning fix the upper bound on the upper/lower tables... save 200 bytes or so + fprintf(fp, "#define __LOCALE_DATA_WCuplow_diffs %7u\n", ul_count); + fprintf(fp, "\n#ifdef WANT_WCuplow_diff_data\n\n"); + fprintf(fp, "\nstatic const short __LOCALE_DATA_WCuplow_diff_data[%zu] = {", + 2 * (size_t) ul_count); + for (i=0 ; i < ul_count ; i++) { + if (i % 4 == 0) { + fprintf(fp, "\n"); + } + fprintf(fp, " %6d, %6d,", uldiff[i].u, uldiff[i].l); + } + fprintf(fp, "\n};\n\n"); + fprintf(fp, "#endif /* WANT_WCuplow_diff_data */\n\n"); + + +/* output_table(fp, "comb", &combtable); */ +/* output_table(fp, "width", &widthtable); */ + + fclose(fp); + } + + return !built; +} + +size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl) +{ + static int recurse; + unsigned char *ti[RANGE+1]; /* table index */ + size_t numblocks; + size_t blocksize; + size_t uniq; + size_t i, j; + size_t smallest, t; + unsigned char *ii_save; + int uniqblock[256]; + unsigned char uit[RANGE+1]; + int shift2; + + memset(uniqblock, 0x00, sizeof(uniqblock)); + + ii_save = NULL; + blocksize = 1 << shift; + numblocks = usize >> shift; + + /* init table index */ + for (i=j=0 ; i < numblocks ; i++) { + ti[i] = ut + j; + j += blocksize; + } + + /* sort */ + nu_val = blocksize; + qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp); + + uniq = 1; + uit[(ti[0]-ut)/blocksize] = 0; + for (i=1 ; i < numblocks ; i++) { + if (memcmp(ti[i-1], ti[i], blocksize) < 0) { + if (++uniq > 255) { + break; + } + uniqblock[uniq - 1] = i; + } +#if 1 + else if (memcmp(ti[i-1], ti[i], blocksize) > 0) { + verbose_msg("bad sort %i!\n", i); + abort(); + } +#endif + uit[(ti[i]-ut)/blocksize] = uniq - 1; + } + + smallest = SIZE_MAX; + shift2 = -1; + if (uniq <= 255) { + smallest = numblocks + uniq * blocksize; + if (!recurse) { + ++recurse; + for (j=1 ; j < 14 ; j++) { + if ((numblocks >> j) < 2) break; + if (tbl) { + ii_save = tbl->ii; + tbl->ii = NULL; + } + if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) { + t += uniq * blocksize; + } + if (tbl) { + tbl->ii = ii_save; + } + if (smallest >= t) { + shift2 = j; + smallest = t; + if (!tbl->ii) { + verbose_msg("ishift %zu tshift %zu size %zu\n", + shift2, shift, t); + } +/* } else { */ +/* break; */ + } + } + --recurse; + } + } else { + return SIZE_MAX; + } + + if (tbl->ii) { + if (recurse) { + tbl->ii_shift = shift; + tbl->ii_len = numblocks; + memcpy(tbl->ii, uit, numblocks); + tbl->ti = tbl->ii + tbl->ii_len; + tbl->ti_len = uniq * blocksize; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize); + } + } else { + ++recurse; + verbose_msg("setting ishift %zu tshift %zu\n", + shift2, shift); + newopt(uit, numblocks, shift2, tbl); + --recurse; + tbl->ti_shift = shift; + tbl->ut_len = uniq * blocksize; + tbl->ut = tbl->ti + tbl->ti_len; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize); + } + } + } + return smallest; +} +/* vi: set sw=4 ts=4: */ diff --git a/extra/locale/lmmtolso.c b/extra/locale/lmmtolso.c new file mode 100644 index 0000000..2437a8f --- /dev/null +++ b/extra/locale/lmmtolso.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + FILE *lmm; /* mmap-able file */ + FILE *lso; /* static object */ + struct stat fd_stat; + int c; + size_t i; + + if (!(lmm = fopen("locale.mmap", "r"))) { + printf("cannot open locale.mmap!\n"); + return EXIT_FAILURE; + } + + if (fstat(fileno(lmm), &fd_stat)) { + printf("cannot stat locale.mmap!\n"); + fclose(lmm); + return EXIT_FAILURE; + } + + if (!(lso = fopen("locale_data.c", "w"))) { + printf("cannot open locale_data.c!\n"); + fclose(lmm); + return EXIT_FAILURE; + } + + fprintf(lso, + "#include \n" + "#include \n" + "#include \"lt_defines.h\"\n" + "#include \"locale_mmap.h\"\n\n" + "typedef union {\n" + "\tunsigned char buf[%zu];\n" + "\t__locale_mmap_t lmm;\n" + "} locale_union_t;\n\n" + "static const locale_union_t locale_union = { {", + (size_t) fd_stat.st_size + ); + + i = 0; + while ((c = getc(lmm)) != EOF) { + if (!(i & 0x7)) { + fprintf(lso, "\n\t"); + } + fprintf(lso, "%#04x, ", c); + ++i; + } + fprintf(lso, + "\n} };\n\n" + "const __locale_mmap_t *__locale_mmap = &locale_union.lmm;\n\n" + ); + + if (ferror(lmm)) { + printf("error reading!\n"); + return EXIT_FAILURE; + } + + if (ferror(lso) || fclose(lso)) { + printf("error writing!\n"); + return EXIT_FAILURE; + } + + fclose(lmm); + + return EXIT_SUCCESS; +} diff --git a/extra/locale/locale_mmap.h b/extra/locale/locale_mmap.h new file mode 100644 index 0000000..1b74823 --- /dev/null +++ b/extra/locale/locale_mmap.h @@ -0,0 +1,93 @@ +/* #define __LOCALE_DATA_MAGIC_SIZE 64 */ +#ifndef __WCHAR_ENABLED +#if 0 +#warning WHOA!!! __WCHAR_ENABLED is not defined! defining it now... +#endif +#define __WCHAR_ENABLED +#endif + +/* TODO - fix */ +#ifdef __WCHAR_ENABLED +#define __LOCALE_DATA_WCctype_TBL_LEN (__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + __LOCALE_DATA_WCctype_UT_LEN) +#define __LOCALE_DATA_WCuplow_TBL_LEN (__LOCALE_DATA_WCuplow_II_LEN + __LOCALE_DATA_WCuplow_TI_LEN + __LOCALE_DATA_WCuplow_UT_LEN) +#define __LOCALE_DATA_WCuplow_diff_TBL_LEN (2 * __LOCALE_DATA_WCuplow_diffs) +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ +#endif + +#undef __PASTE2 +#define __PASTE2(A,B) A ## B +#undef __PASTE3 +#define __PASTE3(A,B,C) A ## B ## C + +#define __LOCALE_DATA_COMMON_MMAP(X) \ + unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; + +#define __LOCALE_DATA_COMMON_MMIDX(X) \ + unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ + uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ + uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ + + +typedef struct { +#ifdef __LOCALE_DATA_MAGIC_SIZE + unsigned char magic[__LOCALE_DATA_MAGIC_SIZE]; +#endif /* __LOCALE_DATA_MAGIC_SIZE */ + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const unsigned char tbl8ctype[__LOCALE_DATA_Cctype_TBL_LEN]; + const unsigned char tbl8uplow[__LOCALE_DATA_Cuplow_TBL_LEN]; +#ifdef __WCHAR_ENABLED + const uint16_t tbl8c2wc[__LOCALE_DATA_Cc2wc_TBL_LEN]; /* char > 0x7f to wide char */ + const unsigned char tbl8wc2c[__LOCALE_DATA_Cwc2c_TBL_LEN]; + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __WCHAR_ENABLED + const unsigned char tblwctype[__LOCALE_DATA_WCctype_TBL_LEN]; + const unsigned char tblwuplow[__LOCALE_DATA_WCuplow_TBL_LEN]; + const int16_t tblwuplow_diff[__LOCALE_DATA_WCuplow_diff_TBL_LEN]; +/* const unsigned char tblwcomb[WCcomb_TBL_LEN]; */ + /* width?? */ +#endif /* __WCHAR_ENABLED */ + + __LOCALE_DATA_COMMON_MMAP(ctype); + __LOCALE_DATA_COMMON_MMAP(numeric); + __LOCALE_DATA_COMMON_MMAP(monetary); + __LOCALE_DATA_COMMON_MMAP(time); + /* collate is different */ + __LOCALE_DATA_COMMON_MMAP(messages); + + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const __codeset_8_bit_t codeset_8_bit[__LOCALE_DATA_NUM_CODESETS]; +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + __LOCALE_DATA_COMMON_MMIDX(ctype); + __LOCALE_DATA_COMMON_MMIDX(numeric); + __LOCALE_DATA_COMMON_MMIDX(monetary); + __LOCALE_DATA_COMMON_MMIDX(time); + /* collate is different */ + __LOCALE_DATA_COMMON_MMIDX(messages); + + const uint16_t collate_data[__lc_collate_data_LEN]; + + unsigned char lc_common_item_offsets_LEN[__LOCALE_DATA_CATEGORIES]; + size_t lc_common_tbl_offsets[__LOCALE_DATA_CATEGORIES * 4]; + /* offsets from start of locale_mmap_t */ + /* rows, item_offsets, item_idx, data */ + +#ifdef __LOCALE_DATA_NUM_LOCALES + unsigned char locales[__LOCALE_DATA_NUM_LOCALES * __LOCALE_DATA_WIDTH_LOCALES]; + unsigned char locale_names5[5*__LOCALE_DATA_NUM_LOCALE_NAMES]; + unsigned char locale_at_modifiers[__LOCALE_DATA_AT_MODIFIERS_LENGTH]; +#endif /* __LOCALE_DATA_NUM_LOCALES */ + + unsigned char lc_names[__lc_names_LEN]; +#ifdef __CTYPE_HAS_8_BIT_LOCALES + unsigned char codeset_list[sizeof(__LOCALE_DATA_CODESET_LIST)]; /* TODO - fix */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + +} __locale_mmap_t; + +extern const __locale_mmap_t *__locale_mmap; diff --git a/extra/locale/programs/categories.def b/extra/locale/programs/categories.def new file mode 100644 index 0000000..c248ba7 --- /dev/null +++ b/extra/locale/programs/categories.def @@ -0,0 +1,357 @@ +/* + * + * Copyright (c) 2008 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Taken from glibc 2.6 + * + */ + + +/* Definition of all available locale categories and their items. -*- C -*- + + These definitions are used by the 'locale' the program. + + The general format of the descriptions is like this: + + DEFINE_CATEGORY (ID, name, ( items ), setlocale-postload) + + where items itself is an array of entries in the form + + { ID, name, standard, value-type, min, max } + + The usage of the load, check, output functions depends on the individual + program code which loads this file. + + The various value types for the items are `string', `stringarray', `byte' + `bytearray', and `word'. These cover all possible values in the current + locale definitions. `min' and `max' can be individually used again. */ + +#ifndef NO_POSTLOAD +#define NO_POSTLOAD NULL +#endif + +#if 0 +DEFINE_CATEGORY +( + LC_COLLATE, "LC_COLLATE", + ( + DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word) + DEFINE_ELEMENT (_NL_COLLATE_RULESETS, "collate-rulesets", std, string) + DEFINE_ELEMENT (_NL_COLLATE_TABLEMB, "collate-tablemb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_WEIGHTMB, "collate-weightmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_EXTRAMB, "collate-extramb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_INDIRECTMB, "collate-indirectmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_TABLEWC, "collate-tablewc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_WEIGHTWC, "collate-weightwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_EXTRAWC, "collate-extrawc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_INDIRECTWC, "collate-indirectwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_SIZEMB, "collate-symb-hash-sizemb", std, word) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_TABLEMB, "collate-symb-tablemb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_EXTRAMB, "collate-symb-extramb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string) + ), NO_POSTLOAD) +#endif + + +/* The actual definition of ctype is meaningless here. It is hard coded in + the code because it has to be handled very specially. Only the names of + the functions and the value types are important. */ +DEFINE_CATEGORY +( + LC_CTYPE, "LC_CTYPE", + ( +#if 0 + DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOUPPER, "ctype-toupper", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOLOWER, "ctype-tolower", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS32, "ctype-class32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, stringlist, 10, 32) + DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, stringlist, 2, 32) + DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray) + DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX, "ctype-mb-cur-max", std, word) + DEFINE_ELEMENT (_NL_CTYPE_CODESET_NAME, "charmap", std, string) + DEFINE_ELEMENT (_NL_CTYPE_TOUPPER32, "ctype-toupper32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOLOWER32, "ctype-tolower32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS_OFFSET, "ctype-class-offset", std, word) + DEFINE_ELEMENT (_NL_CTYPE_MAP_OFFSET, "ctype-map-offset", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_MB_LEN, "ctype-indigits_mb-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_MB, "ctype-indigits0_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_MB, "ctype-indigits1_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_MB, "ctype-indigits2_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_MB, "ctype-indigits3_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_MB, "ctype-indigits4_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_MB, "ctype-indigits5_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_MB, "ctype-indigits6_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_MB, "ctype-indigits7_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_MB, "ctype-indigits8_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_MB, "ctype-indigits9_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_WC_LEN, "ctype-indigits_wc-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_WC, "ctype-indigits0_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_WC, "ctype-indigits1_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_WC, "ctype-indigits2_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_WC, "ctype-indigits3_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_WC, "ctype-indigits4_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_WC, "ctype-indigits5_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_WC, "ctype-indigits6_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_WC, "ctype-indigits7_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_WC, "ctype-indigits8_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_WC, "ctype-indigits9_wc", std, wstring) +#endif + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_MB, "ctype-outdigit0_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_MB, "ctype-outdigit1_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_MB, "ctype-outdigit2_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_MB, "ctype-outdigit3_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_MB, "ctype-outdigit4_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_MB, "ctype-outdigit5_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_MB, "ctype-outdigit6_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_MB, "ctype-outdigit7_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_MB, "ctype-outdigit8_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_MB, "ctype-outdigit9_mb", std, string) +#if 0 + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_WC, "ctype-outdigit0_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_WC, "ctype-outdigit1_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_WC, "ctype-outdigit2_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_WC, "ctype-outdigit3_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_WC, "ctype-outdigit4_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_WC, "ctype-outdigit5_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_WC, "ctype-outdigit6_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_WC, "ctype-outdigit7_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_WC, "ctype-outdigit8_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_WC, "ctype-outdigit9_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TAB_SIZE, "ctype-translit-tab-size", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_IDX, "ctype-translit-from-idx", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_TBL, "ctype-translit-from-tbl", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_IDX, "ctype-translit-to-idx", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_TBL, "ctype-translit-to-tbl", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN, "ctype-translit-default-missing-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING, "ctype-translit-default-missing", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE_LEN, "ctype-translit-ignore-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE, "ctype-translit-ignore", std, string) + DEFINE_ELEMENT (_NL_CTYPE_MAP_TO_NONASCII, "map-to-nonascii", std, word) +#endif + ), _nl_postload_ctype) + + +DEFINE_CATEGORY +( + LC_MONETARY, "LC_MONETARY", + ( + DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string) + DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string) + DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string) + DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string) + DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray) + DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string) + DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string) + DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte) + DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte) + DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (__INT_P_CS_PRECEDES, "int_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (__INT_P_SEP_BY_SPACE, "int_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (__INT_N_CS_PRECEDES, "int_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (__INT_N_SEP_BY_SPACE, "int_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (__INT_P_SIGN_POSN, "int_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (__INT_N_SIGN_POSN, "int_n_sign_posn", std, byte, 0, 4) +#if 0 + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_CURR_SYMBOL, "duo_int_curr_symbol", std, string) + DEFINE_ELEMENT (_NL_MONETARY_DUO_CURRENCY_SYMBOL, "duo_currency_symbol", std, string) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_FRAC_DIGITS, "duo_int_frac_digits", std, byte) + DEFINE_ELEMENT (_NL_MONETARY_DUO_FRAC_DIGITS, "duo_frac_digits", std, byte) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_CS_PRECEDES, "duo_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SEP_BY_SPACE, "duo_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_CS_PRECEDES, "duo_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SEP_BY_SPACE, "duo_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_CS_PRECEDES, "duo_int_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, "duo_int_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_CS_PRECEDES, "duo_int_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, "duo_int_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SIGN_POSN, "duo_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SIGN_POSN, "duo_n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SIGN_POSN, "duo_int_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SIGN_POSN, "duo_int_n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_FROM, "uno_valid_from", std, word) + DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_TO, "uno_valid_to", std, word) + DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_FROM, "duo_valid_from", std, word) + DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_TO, "duo_valid_to", std, word) + DEFINE_ELEMENT (_NL_MONETARY_CONVERSION_RATE, "conversion_rate", std, wordarray, 2, 2) + DEFINE_ELEMENT (_NL_MONETARY_DECIMAL_POINT_WC, "monetary-decimal-point-wc", std, word) + DEFINE_ELEMENT (_NL_MONETARY_THOUSANDS_SEP_WC, "monetary-thousands-sep-wc", std, word) + DEFINE_ELEMENT (_NL_MONETARY_CODESET, "monetary-codeset", std, string) +#else + DEFINE_ELEMENT (_NL_MONETARY_CRNCYSTR, "monetary-crncystr", std, string) +#endif + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_NUMERIC, "LC_NUMERIC", + ( + DEFINE_ELEMENT (DECIMAL_POINT, "decimal_point", std, string) + DEFINE_ELEMENT (THOUSANDS_SEP, "thousands_sep", std, string) + DEFINE_ELEMENT (GROUPING, "grouping", std, bytearray) +#if 0 + DEFINE_ELEMENT (_NL_NUMERIC_DECIMAL_POINT_WC, "numeric-decimal-point-wc", std, word) + DEFINE_ELEMENT (_NL_NUMERIC_THOUSANDS_SEP_WC, "numeric-thousands-sep-wc", std, word) + DEFINE_ELEMENT (_NL_NUMERIC_CODESET, "numeric-codeset", std, string) +#endif + + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_TIME, "LC_TIME", + ( + DEFINE_ELEMENT (ABDAY_1, "abday", std, stringarray, 7, 7) + DEFINE_ELEMENT (DAY_1, "day", std, stringarray, 7, 7) + DEFINE_ELEMENT (ABMON_1, "abmon", std, stringarray, 12, 12) + DEFINE_ELEMENT (MON_1, "mon", std, stringarray, 12, 12) + DEFINE_ELEMENT (AM_STR, "am_pm", std, stringarray, 2, 2) + DEFINE_ELEMENT (D_T_FMT, "d_t_fmt", std, string) + DEFINE_ELEMENT (D_FMT, "d_fmt", std, string) + DEFINE_ELEMENT (T_FMT, "t_fmt", std, string) + DEFINE_ELEMENT (T_FMT_AMPM, "t_fmt_ampm", std, string) + DEFINE_ELEMENT (ERA, "era", opt, stringlist, 0, 100) + DEFINE_ELEMENT (ERA_YEAR, "era_year", opt, string) + DEFINE_ELEMENT (ERA_D_FMT, "era_d_fmt", opt, string) + DEFINE_ELEMENT (ALT_DIGITS, "alt_digits", opt, stringlist, 100, 100) + DEFINE_ELEMENT (ERA_D_T_FMT, "era_d_t_fmt", opt, string) + DEFINE_ELEMENT (ERA_T_FMT, "era_t_fmt", opt, string) +#if 0 + DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES, "time-era-num-entries", opt, word) + DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES, "time-era-entries", opt, string) + DEFINE_ELEMENT (_NL_WABDAY_1, "wide-abday", std, wstringarray, 7, 7) + DEFINE_ELEMENT (_NL_WDAY_1, "wide-day", std, wstringarray, 7, 7) + DEFINE_ELEMENT (_NL_WABMON_1, "wide-abmon", std, wstringarray, 12, 12) + DEFINE_ELEMENT (_NL_WMON_1, "wide-mon", std, wstringarray, 12, 12) + DEFINE_ELEMENT (_NL_WAM_STR, "wide-am_pm", std, wstringarray, 2, 2) + DEFINE_ELEMENT (_NL_WD_T_FMT, "wide-d_t_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WD_FMT, "wide-d_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WT_FMT, "wide-t_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WT_FMT_AMPM, "wide-t_fmt_ampm", std, wstring) + DEFINE_ELEMENT (_NL_WERA_YEAR, "wide-era_year", opt, wstring) + DEFINE_ELEMENT (_NL_WERA_D_FMT, "wide-era_d_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_WALT_DIGITS, "wide-alt_digits", opt, wstringlist, 1000, 100) + DEFINE_ELEMENT (_NL_WERA_D_T_FMT, "wide-era_d_t_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_WERA_T_FMT, "wide-era_t_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_TIME_WEEK_NDAYS, "week-ndays", std, byte) + DEFINE_ELEMENT (_NL_TIME_WEEK_1STDAY, "week-1stday", std, word) + DEFINE_ELEMENT (_NL_TIME_WEEK_1STWEEK, "week-1stweek", std, byte) + DEFINE_ELEMENT (_NL_TIME_FIRST_WEEKDAY, "first_weekday", std, byte) + DEFINE_ELEMENT (_NL_TIME_FIRST_WORKDAY, "first_workday", std, byte) + DEFINE_ELEMENT (_NL_TIME_CAL_DIRECTION, "cal_direction", std, byte) + DEFINE_ELEMENT (_NL_TIME_TIMEZONE, "timezone", std, string) + DEFINE_ELEMENT (_DATE_FMT, "date_fmt", opt, string) + DEFINE_ELEMENT (_NL_W_DATE_FMT, "wide-date_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_TIME_CODESET, "time-codeset", std, string) +#endif + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_MESSAGES, "LC_MESSAGES", + ( + DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string) + DEFINE_ELEMENT (NOEXPR, "noexpr", std, string) + DEFINE_ELEMENT (YESSTR, "yesstr", opt, string) + DEFINE_ELEMENT (NOSTR, "nostr", opt, string) +#if 0 + DEFINE_ELEMENT (_NL_MESSAGES_CODESET, "messages-codeset", std, string) +#endif + ), NO_POSTLOAD) + +#if 0 +DEFINE_CATEGORY +( + LC_PAPER, "LC_PAPER", + ( + DEFINE_ELEMENT (_NL_PAPER_HEIGHT, "height", std, word) + DEFINE_ELEMENT (_NL_PAPER_WIDTH, "width", std, word) + DEFINE_ELEMENT (_NL_PAPER_CODESET, "paper-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_NAME, "LC_NAME", + ( + DEFINE_ELEMENT (_NL_NAME_NAME_FMT, "name_fmt", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_GEN, "name_gen", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MR, "name_mr", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MRS, "name_mrs", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MISS, "name_miss", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MS, "name_ms", std, string) + DEFINE_ELEMENT (_NL_NAME_CODESET, "name-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_ADDRESS, "LC_ADDRESS", + ( + DEFINE_ELEMENT (_NL_ADDRESS_POSTAL_FMT, "postal_fmt", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NAME, "country_name", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_POST, "country_post", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB2, "country_ab2", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB3, "country_ab3", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_CAR, "country_car", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NUM, "country_num", std, word) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_ISBN, "country_isbn", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_NAME, "lang_name", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_AB, "lang_ab", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_TERM, "lang_term", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_LIB, "lang_lib", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_CODESET, "address-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_TELEPHONE, "LC_TELEPHONE", + ( + DEFINE_ELEMENT (_NL_TELEPHONE_TEL_INT_FMT, "tel_int_fmt", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_TEL_DOM_FMT, "tel_dom_fmt", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_INT_SELECT, "int_select", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_INT_PREFIX, "int_prefix", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_CODESET, "telephone-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_MEASUREMENT, "LC_MEASUREMENT", + ( + DEFINE_ELEMENT (_NL_MEASUREMENT_MEASUREMENT, "measurement", std, byte) + DEFINE_ELEMENT (_NL_MEASUREMENT_CODESET, "measurement-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_IDENTIFICATION, "LC_IDENTIFICATION", + ( + DEFINE_ELEMENT (_NL_IDENTIFICATION_TITLE, "title", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_SOURCE, "source", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_ADDRESS, "address", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CONTACT, "contact", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_EMAIL, "email", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_TEL, "tel", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_FAX, "fax", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_LANGUAGE, "language", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_TERRITORY, "territory", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_AUDIENCE, "audience", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_APPLICATION, "application", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_ABBREVIATION, "abbreviation", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_REVISION, "revision", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_DATE, "date", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 13, 13) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CODESET, "identification-codeset", std, string) + ), NO_POSTLOAD) +#endif diff --git a/extra/locale/programs/locale.c b/extra/locale/programs/locale.c new file mode 100644 index 0000000..c8b76bd --- /dev/null +++ b/extra/locale/programs/locale.c @@ -0,0 +1,462 @@ +/* + * + * Copyright (c) 2008 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * A 'locale' command implementation for uClibc. + * + */ + + +#include +#include +#include +#include +#include + +typedef struct { + unsigned char idx_name; + char dot_cs; /* 0 if no codeset specified */ + char cs; + unsigned char lc_ctype_row; + unsigned char lc_numeric_row; + unsigned char lc_monetary_row; + unsigned char lc_time_row; + unsigned char lc_collate_row; + unsigned char lc_messages_row; +} locale_entry; + +/* Need to include this before locale.h and xlocale.h! */ +#include + +#undef CODESET_LIST +#define CODESET_LIST (__locale_mmap->codeset_list) +#include +#define LOCALE_NAMES (__locale_mmap->locale_names5) +#define LOCALES (__locale_mmap->locales) +#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers) +#define CATEGORY_NAMES (__locale_mmap->lc_names) + +#define GET_CODESET_NAME(N) (CODESET_LIST + *(CODESET_LIST + N - 3)) +#define GET_LOCALE_ENTRY(R) (locale_entry *)(LOCALES + (__LOCALE_DATA_WIDTH_LOCALES * R)) +#define GET_CATEGORY_NAME(X) (CATEGORY_NAMES + *(CATEGORY_NAMES + X)) +#define GET_LOCALE_NAME(I) (const char *)(LOCALE_NAMES + 5 * (I - 1)) + +static const char utf8[] = "UTF-8"; +static const char ascii[] = "ASCII"; + +/* If set print the name of the category. */ +static int show_category_name = 0; + +/* If set print the name of the item. */ +static int show_keyword_name = 0; + +/* If set print the usage command. */ +static int show_usage = 0; + +/* Print names of all available locales. */ +static int do_all = 0; + +/* Print names of all available character maps. */ +static int do_charmaps = 0; + +static int remaining = 0; + +/* We can map the types of the entries into a few categories. */ +enum value_type { + none, + string, + stringarray, + byte, + bytearray, + word, + stringlist, + wordarray, + wstring, + wstringarray, + wstringlist +}; + +/* Definition of the data structure which represents a category and its + items. */ +struct category { + int cat_id; + const char *name; + size_t number; + struct cat_item { + int item_id; + const char *name; + enum { std, opt } status; + enum value_type value_type; + int min; + int max; + } *item_desc; +}; + +/* Simple helper macro. */ +#define NELEMS(arr) ((sizeof (arr)) / (sizeof (arr[0]))) + +/* For some tricky stuff. */ +#define NO_PAREN(Item, More...) Item, ## More + +/* We have all categories defined in `categories.def'. Now construct + the description and data structure used for all categories. */ +#define DEFINE_ELEMENT(Item, More...) { Item, ## More }, +#define DEFINE_CATEGORY(category, name, items, postload) \ + static struct cat_item category##_desc[] = \ + { \ + NO_PAREN items \ + }; + +#include "categories.def" +#undef DEFINE_CATEGORY + +static struct category category[] = { +#define DEFINE_CATEGORY(category, name, items, postload) \ + [category] = { _NL_NUM_##category, name, NELEMS (category##_desc), \ + category##_desc }, +#include "categories.def" +#undef DEFINE_CATEGORY +}; + +#define NCATEGORIES NELEMS (category) + +static void usage(const char *name); +static void usage(const char *name) +{ + const char *s; + + s = basename(name); + fprintf(stderr, + "Usage: %s [-ck] [--category-name] [--keyword-name] [--help] NAME\n" + "or: %s [OPTION...] [-a|-m] [--all-locales] [--charmaps] \n", s, + s); +} + +static int argp_parse(int argc, char *argv[]); +static int argp_parse(int argc, char *argv[]) +{ + static const struct option long_options[] = { + {"all-locales", no_argument, NULL, 'a'}, + {"charmaps", no_argument, NULL, 'm'}, + {"category-name", no_argument, NULL, 'c'}, + {"keyword-name", no_argument, NULL, 'k'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + int c; + char *progname; + + progname = *argv; + while ((c = getopt_long(argc, argv, "amckh", long_options, NULL)) >= 0) + switch (c) { + case 'a': + do_all = 1; + break; + case 'c': + show_category_name = 1; + break; + case 'm': + do_charmaps = 1; + break; + case 'k': + show_keyword_name = 1; + break; + case 'h': + show_usage = 1; + break; + case '?': + fprintf(stderr, "Unknown option.\n"); + usage(progname); + return 1; + + default: + fprintf(stderr, "This should never happen!\n"); + return 1; + } + + remaining = optind; + + return 0; +} + +static unsigned const char *find_at(char c); +static unsigned const char *find_at(char c) +{ + const unsigned char *q; + + q = LOCALE_AT_MODIFIERS; + do { + if (q[1] == c) { + return (unsigned const char *) q + 2; + } + q += 2 + *q; + } while (*q); + + return NULL; +} + +static void find_locale_string(locale_entry * loc_rec, char *loc) +{ + char at = 0; + unsigned char idx; + uint16_t dotcs, cs; + + idx = loc_rec->idx_name; + if (!idx) { + *loc++ = 'C'; /* jump the first locale (C) */ + *loc = '\0'; + } else { + dotcs = (uint16_t) loc_rec->dot_cs; + cs = (uint16_t) loc_rec->cs;; + loc = strncpy(loc, GET_LOCALE_NAME(idx), 5); + + if (loc[2] == '_') { + sprintf(loc, "%5.5s%c%s\0", loc, (dotcs != 0) ? '.' : ' ', + (cs == + 1) ? ascii : ((cs == 2) ? utf8 : GET_CODESET_NAME(cs))); + } else { + at = loc[2]; + loc[2] = '_'; + sprintf(loc, "%5.5s%c%s@%s\0", loc, (dotcs != 0) ? '.' : ' ', + (cs == + 1) ? ascii : ((cs == 2) ? utf8 : GET_CODESET_NAME(cs)), + find_at(at)); + } + } +} + +static void list_locale(void); +static void list_locale() +{ + char loc[40]; + uint16_t n = 0; + locale_entry *locales = (locale_entry *) LOCALES; + + do { + find_locale_string(locales, loc); + printf("%s\n", loc); + ++n; + locales++; + } while (n < __LOCALE_DATA_NUM_LOCALES); +} + +static void list_charmaps(void); +static void list_charmaps() +{ + unsigned const char *cl; + + cl = CODESET_LIST; + do { + printf("%s\n", CODESET_LIST + *cl); + } while (*++cl); + +} + +static void print_item(struct cat_item *item); +static void print_item(struct cat_item *item) +{ + switch (item->value_type) { + case string: + if (show_keyword_name) + printf("%s=\"", item->name); + fputs(nl_langinfo(item->item_id) ? : "", stdout); + if (show_keyword_name) + putchar('"'); + putchar('\n'); + break; + case stringarray: + { + int cnt; + const char *val; + + if (show_keyword_name) + printf("%s=\"", item->name); + + for (cnt = 0; cnt < item->max - 1; ++cnt) { + val = nl_langinfo(item->item_id + cnt); + if (val != NULL) + fputs(val, stdout); + putchar(';'); + } + + val = nl_langinfo(item->item_id + cnt); + if (val != NULL) + fputs(val, stdout); + + if (show_keyword_name) + putchar('"'); + putchar('\n'); + } + break; + case stringlist: + { + int first = 1; + const char *val = nl_langinfo(item->item_id) ? : ""; + int cnt; + + if (show_keyword_name) + printf("%s=", item->name); + + for (cnt = 0; cnt < item->max && *val != '\0'; ++cnt) { + printf("%s%s%s%s", first ? "" : ";", + show_keyword_name ? "\"" : "", val, + show_keyword_name ? "\"" : ""); + val = strchr(val, '\0') + 1; + first = 0; + } + putchar('\n'); + } + break; + case byte: + { + const char *val = nl_langinfo(item->item_id); + + if (show_keyword_name) + printf("%s=", item->name); + + if (val != NULL) + printf("%d", *val == '\177' ? -1 : *val); + putchar('\n'); + } + break; + case bytearray: + { + const char *val = nl_langinfo(item->item_id); + int cnt = val ? strlen(val) : 0; + + if (show_keyword_name) + printf("%s=", item->name); + + while (cnt > 1) { + printf("%d;", *val == '\177' ? -1 : *val); + --cnt; + ++val; + } + + printf("%d\n", cnt == 0 || *val == '\177' ? -1 : *val); + } + break; + case word: + { + union { + unsigned int word; + char *string; + } val; + + val.string = nl_langinfo(item->item_id); + if (show_keyword_name) + printf("%s=", item->name); + + printf("%d\n", val.word); + } + break; + case wstring: + case wstringarray: + case wstringlist: + /* We don't print wide character information since the same + information is available in a multibyte string. */ + default: + break; + + } +} + +/* Show the information request for NAME. */ +static void show_info(const char *name); +static void show_info(const char *name) +{ + size_t cat_no, item_no; + const unsigned char *cat_name; + + /* Now all categories in an unspecified order. */ + for (cat_no = 0; cat_no < __LC_ALL; ++cat_no) { + cat_name = GET_CATEGORY_NAME(cat_no); + if (strcmp(name, (const char *) cat_name) == 0) { + if (show_category_name) + printf("%s\n", name); + + for (item_no = 0; item_no < category[cat_no].number; ++item_no) + print_item(&category[cat_no].item_desc[item_no]); + + return; + } + + for (item_no = 0; item_no < category[cat_no].number; ++item_no) + if (strcmp(name, category[cat_no].item_desc[item_no].name) == 0) { + if (show_category_name != 0) + puts(category[cat_no].name); + + print_item(&category[cat_no].item_desc[item_no]); + return; + } + } +} + +static void show_locale_vars(void); +static void show_locale_vars() +{ + size_t cat_no; + int row; /* locale row */ + const char *lcall = getenv("LC_ALL"); + const char *lang = getenv("LANG") ? : ""; + unsigned char *cur_loc = __global_locale->cur_locale + 1; + char loc_name[40]; + locale_entry *locales; + + /* LANG has to be the first value. */ + printf("LANG=%s\n", lang); + + /* Now all categories in an unspecified order. */ + for (cat_no = 0; cat_no < __LC_ALL; ++cat_no) { + row = (((int) (*cur_loc & 0x7f)) << 7) + (cur_loc[1] & 0x7f); +/* assert(row < __LOCALE_DATA_NUM_LOCALES); */ + + locales = GET_LOCALE_ENTRY(row); + find_locale_string(locales, loc_name); + printf("%s=%s\n", GET_CATEGORY_NAME(cat_no), loc_name); + + cur_loc += 2; + } + + /* The last is the LC_ALL value. */ + printf("LC_ALL=%s\n", lcall ? : ""); +} + +int main(int argc, char *argv[]) +{ + /* Parse and process arguments. */ + if (argp_parse(argc, argv)) + return 1; + + if (do_all) { + list_locale(); + exit(EXIT_SUCCESS); + } + + if (do_charmaps) { + list_charmaps(); + exit(EXIT_SUCCESS); + } + + if (show_usage) { + usage(*argv); + exit(EXIT_SUCCESS); + } + + /* If no real argument is given we have to print the contents of the + current locale definition variables. These are LANG and the LC_*. */ + if (remaining == argc && show_category_name == 0 + && show_keyword_name == 0) { + show_locale_vars(); + exit(EXIT_SUCCESS); + } + + /* Process all given names. */ + while (remaining < argc) + show_info(argv[remaining++]); + + exit(EXIT_SUCCESS); +} diff --git a/extra/locale/tst_nl_langinfo.c b/extra/locale/tst_nl_langinfo.c new file mode 100644 index 0000000..fcf2fe2 --- /dev/null +++ b/extra/locale/tst_nl_langinfo.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include + +#if !defined(__UCLIBC__) && 0 +#define DO_EXTRA +#endif + +int main(int argc, char **argv) +{ + char *l; + const unsigned char *x; +/* const unsigned char *y; */ + const unsigned char *p; + + if (argc > 2) { + printf("invalid args\n"); + return EXIT_FAILURE; + } + if (argc == 1) { + l = ""; + } else { + l = *++argv; + } + + if (!(x = setlocale(LC_ALL,l))) { + printf("couldn't set locale %s\n", l); + return EXIT_FAILURE; + } + +/* printf("\nsetlocale returned:\n "); */ +/* do { */ +/* printf("\\x%02x", *x); */ +/* } while (*x++); */ +/* printf("\n"); */ + +#ifndef __BCC__ +#define STR(X) #X +#else +#define STR(X) __STR(X) +#endif +#define __PASTE2(A,B) A.B + +#define DO_NL_I(X) \ + printf( STR(X) " = %d\n", (int) nl_langinfo(X) ); +#define DO_NL_S(X) \ + printf( STR(X) " = \"%s\"\n", nl_langinfo(X) ); +#define DO_NL_C(X) \ + printf( STR(X) " = \"\\x%02x\"\n", *((unsigned char *) nl_langinfo(X)) ); + + printf("ctype\n"); + + DO_NL_S(CODESET); +#ifdef DO_EXTRA + DO_NL_I(_NL_CTYPE_INDIGITS_MB_LEN); + DO_NL_S(_NL_CTYPE_INDIGITS0_MB); + DO_NL_S(_NL_CTYPE_INDIGITS1_MB); + DO_NL_S(_NL_CTYPE_INDIGITS2_MB); + DO_NL_S(_NL_CTYPE_INDIGITS3_MB); + DO_NL_S(_NL_CTYPE_INDIGITS4_MB); + DO_NL_S(_NL_CTYPE_INDIGITS5_MB); + DO_NL_S(_NL_CTYPE_INDIGITS6_MB); + DO_NL_S(_NL_CTYPE_INDIGITS7_MB); + DO_NL_S(_NL_CTYPE_INDIGITS8_MB); + DO_NL_S(_NL_CTYPE_INDIGITS9_MB); +#endif + DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB); + + + printf("numeric\n"); + + DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */ + DO_NL_S(THOUSEP); /* THOUSANDS_SEP */ +/* DO_NL_S(GROUPING); */ + + printf("GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + printf("monetary\n"); + + DO_NL_S(INT_CURR_SYMBOL); + DO_NL_S(CURRENCY_SYMBOL); + DO_NL_S(MON_DECIMAL_POINT); + DO_NL_S(MON_THOUSANDS_SEP); +/* DO_NL_S(MON_GROUPING); */ + + printf("MON_GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(MON_GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + DO_NL_S(POSITIVE_SIGN); + DO_NL_S(NEGATIVE_SIGN); + DO_NL_C(INT_FRAC_DIGITS); + DO_NL_C(FRAC_DIGITS); + DO_NL_C(P_CS_PRECEDES); + DO_NL_C(P_SEP_BY_SPACE); + DO_NL_C(N_CS_PRECEDES); + DO_NL_C(N_SEP_BY_SPACE); + DO_NL_C(P_SIGN_POSN); + DO_NL_C(N_SIGN_POSN); + DO_NL_C(INT_P_CS_PRECEDES); + DO_NL_C(INT_P_SEP_BY_SPACE); + DO_NL_C(INT_N_CS_PRECEDES); + DO_NL_C(INT_N_SEP_BY_SPACE); + DO_NL_C(INT_P_SIGN_POSN); + DO_NL_C(INT_N_SIGN_POSN); + + DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */ + + + printf("time\n"); + + DO_NL_S(ABDAY_1); + DO_NL_S(ABDAY_2); + DO_NL_S(ABDAY_3); + DO_NL_S(ABDAY_4); + DO_NL_S(ABDAY_5); + DO_NL_S(ABDAY_6); + DO_NL_S(ABDAY_7); + + DO_NL_S(DAY_1); + DO_NL_S(DAY_2); + DO_NL_S(DAY_3); + DO_NL_S(DAY_4); + DO_NL_S(DAY_5); + DO_NL_S(DAY_6); + DO_NL_S(DAY_7); + + DO_NL_S(ABMON_1); + DO_NL_S(ABMON_2); + DO_NL_S(ABMON_3); + DO_NL_S(ABMON_4); + DO_NL_S(ABMON_5); + DO_NL_S(ABMON_6); + DO_NL_S(ABMON_7); + DO_NL_S(ABMON_8); + DO_NL_S(ABMON_9); + DO_NL_S(ABMON_10); + DO_NL_S(ABMON_11); + DO_NL_S(ABMON_12); + + DO_NL_S(MON_1); + DO_NL_S(MON_2); + DO_NL_S(MON_3); + DO_NL_S(MON_4); + DO_NL_S(MON_5); + DO_NL_S(MON_6); + DO_NL_S(MON_7); + DO_NL_S(MON_8); + DO_NL_S(MON_9); + DO_NL_S(MON_10); + DO_NL_S(MON_11); + DO_NL_S(MON_12); + + DO_NL_S(AM_STR); + DO_NL_S(PM_STR); + + DO_NL_S(D_T_FMT); + DO_NL_S(D_FMT); + DO_NL_S(T_FMT); + DO_NL_S(T_FMT_AMPM); +/* DO_NL_S(ERA); */ + { + const char *p = nl_langinfo(ERA); + if (!p || !*p) { + printf("ERA = (none)\n"); + } else { + int i; + printf("ERA:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + if (!*p) break; + } + } + } + + DO_NL_S(ERA_YEAR); /* non SuSv3 */ + DO_NL_S(ERA_D_FMT); +/* DO_NL_S(ALT_DIGITS); */ + { + const char *p = nl_langinfo(ALT_DIGITS); + if (!p || !*p) { + printf("ALT_DIGITS = (none)\n"); + } else { + int i; + printf("ALT_DIGITS:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + } + } + } + DO_NL_S(ERA_D_T_FMT); + DO_NL_S(ERA_T_FMT); + +#ifdef DO_EXTRA + DO_NL_C(_NL_TIME_WEEK_NDAYS); + DO_NL_I(_NL_TIME_WEEK_1STDAY); /* grr... this won't work with 16bit ptrs */ + DO_NL_C(_NL_TIME_WEEK_1STWEEK); + DO_NL_C(_NL_TIME_FIRST_WEEKDAY); + DO_NL_C(_NL_TIME_FIRST_WORKDAY); + DO_NL_C(_NL_TIME_CAL_DIRECTION); + DO_NL_S(_NL_TIME_TIMEZONE); + DO_NL_S(_DATE_FMT); +#endif + + printf("messages\n"); + + DO_NL_S(YESEXPR); + DO_NL_S(NOEXPR); + DO_NL_S(YESSTR); + DO_NL_S(NOSTR); + +#ifdef DO_EXTRA + + printf("paper\n"); + + DO_NL_I(_NL_PAPER_HEIGHT); + DO_NL_I(_NL_PAPER_WIDTH); + + printf("name\n"); + + DO_NL_S(_NL_NAME_NAME_FMT); + DO_NL_S(_NL_NAME_NAME_GEN); + DO_NL_S(_NL_NAME_NAME_MR); + DO_NL_S(_NL_NAME_NAME_MRS); + DO_NL_S(_NL_NAME_NAME_MISS); + DO_NL_S(_NL_NAME_NAME_MS); + + printf("address\n"); + + DO_NL_S(_NL_ADDRESS_POSTAL_FMT); + DO_NL_S(_NL_ADDRESS_COUNTRY_NAME); + DO_NL_S(_NL_ADDRESS_COUNTRY_POST); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB2); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB3); + DO_NL_S(_NL_ADDRESS_COUNTRY_CAR); + DO_NL_I(_NL_ADDRESS_COUNTRY_NUM); + DO_NL_S(_NL_ADDRESS_COUNTRY_ISBN); + DO_NL_S(_NL_ADDRESS_LANG_NAME); + DO_NL_S(_NL_ADDRESS_LANG_AB); + DO_NL_S(_NL_ADDRESS_LANG_TERM); + DO_NL_S(_NL_ADDRESS_LANG_LIB); + + printf("telephone\n"); + + DO_NL_S(_NL_TELEPHONE_TEL_INT_FMT); + DO_NL_S(_NL_TELEPHONE_TEL_DOM_FMT); + DO_NL_S(_NL_TELEPHONE_INT_SELECT); + DO_NL_S(_NL_TELEPHONE_INT_PREFIX); + + printf("measurement\n"); + + DO_NL_C(_NL_MEASUREMENT_MEASUREMENT); /* 1 is metric, 2 is US */ + + printf("identification\n"); + + DO_NL_S(_NL_IDENTIFICATION_TITLE); + DO_NL_S(_NL_IDENTIFICATION_SOURCE); + DO_NL_S(_NL_IDENTIFICATION_ADDRESS); + DO_NL_S(_NL_IDENTIFICATION_CONTACT); + DO_NL_S(_NL_IDENTIFICATION_EMAIL); + DO_NL_S(_NL_IDENTIFICATION_TEL); + DO_NL_S(_NL_IDENTIFICATION_FAX); + DO_NL_S(_NL_IDENTIFICATION_LANGUAGE); + DO_NL_S(_NL_IDENTIFICATION_TERRITORY); + DO_NL_S(_NL_IDENTIFICATION_AUDIENCE); + DO_NL_S(_NL_IDENTIFICATION_APPLICATION); + DO_NL_S(_NL_IDENTIFICATION_ABBREVIATION); + DO_NL_S(_NL_IDENTIFICATION_REVISION); + DO_NL_S(_NL_IDENTIFICATION_DATE); + DO_NL_S(_NL_IDENTIFICATION_CATEGORY); + +#endif + + return EXIT_SUCCESS; +} diff --git a/extra/scripts/Makefile.arch.lvl3 b/extra/scripts/Makefile.arch.lvl3 new file mode 100644 index 0000000..ac00637 --- /dev/null +++ b/extra/scripts/Makefile.arch.lvl3 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.arch.lvl4 b/extra/scripts/Makefile.arch.lvl4 new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/extra/scripts/Makefile.arch.lvl4 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.libs.lvl0 b/extra/scripts/Makefile.libs.lvl0 new file mode 100644 index 0000000..4709fc2 --- /dev/null +++ b/extra/scripts/Makefile.libs.lvl0 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=./ +top_builddir=./ +#include $(top_builddir)Rules.mak +#all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.libs.lvl1 b/extra/scripts/Makefile.libs.lvl1 new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/extra/scripts/Makefile.libs.lvl1 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.libs.lvl2 b/extra/scripts/Makefile.libs.lvl2 new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/extra/scripts/Makefile.libs.lvl2 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.objs.lvl2 b/extra/scripts/Makefile.objs.lvl2 new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/extra/scripts/Makefile.objs.lvl2 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.objs.lvl3 b/extra/scripts/Makefile.objs.lvl3 new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/extra/scripts/Makefile.objs.lvl3 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.objs.lvl4 b/extra/scripts/Makefile.objs.lvl4 new file mode 100644 index 0000000..3ed177a --- /dev/null +++ b/extra/scripts/Makefile.objs.lvl4 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/Makefile.utils.lvl1 b/extra/scripts/Makefile.utils.lvl1 new file mode 100644 index 0000000..bdaea9f --- /dev/null +++ b/extra/scripts/Makefile.utils.lvl1 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: utils +include Makefile.in +include $(top_srcdir)Makerules diff --git a/extra/scripts/conf-header.sh b/extra/scripts/conf-header.sh new file mode 100755 index 0000000..90dfa99 --- /dev/null +++ b/extra/scripts/conf-header.sh @@ -0,0 +1,27 @@ +#!/bin/sh -e + +# Turn .config into a header file + +if [ -z "$1" ] ; then + echo "Usage: conf-header.sh <.config>" + exit 1 +fi + +cat < directly; use instead +#endif + +#define __UCLIBC_MAJOR__ ${MAJOR_VERSION} +#define __UCLIBC_MINOR__ ${MINOR_VERSION} +#define __UCLIBC_SUBLEVEL__ ${SUBLEVEL} +EOF + +exec \ +sed \ + -e '/^#$/d' \ + -e '/^[^#]/s:^\([^=]*\)=\(.*\):#define __\1__ \2:' \ + -e '/^#define /s: y$: 1:' \ + -e '/^# .* is not set$/s:^# \(.*\) is not set$:#undef __\1__:' \ + -e 's:^# \(.*\)$:/* \1 */:' \ + $1 diff --git a/extra/scripts/create_makefiles.sh b/extra/scripts/create_makefiles.sh new file mode 100755 index 0000000..1d94b0d --- /dev/null +++ b/extra/scripts/create_makefiles.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# Creates the necessary Makefiles to build w/ the Makefile.{arch,in} files + +DIRS="ldso libc libcrypt libintl libm libnsl libpthread libresolv librt libutil" + +if [ ! -f Makerules ] ; then + echo "Run this command in top_srcdir" + exit 1 +fi + +if [ -z "${USE_CMD}" ] ; then +USE_CMD="cp" +fi + +RM="rm -f" +${RM} Makefile +${USE_CMD} extra/scripts/Makefile.libs.lvl0 Makefile + +#for x in ${DIRS} ; do +# find ./${x} -name Makefile -exec rm -f {} \; +#done + +for x in */Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.libs.lvl1 `dirname ${x}`/Makefile +done + +for x in utils/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.utils.lvl1 `dirname ${x}`/Makefile +done + +for x in */*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl2 `dirname ${x}`/Makefile +done + +# overwrites the earlier ones, we do not add arch specific to libm/arch +for x in ldso/*/Makefile.in libpthread/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.libs.lvl2 `dirname ${x}`/Makefile +done + +for x in */*/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl3 `dirname ${x}`/Makefile +done + +for x in libc/*/*/Makefile.arch ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.arch.lvl3 `dirname ${x}`/Makefile +done + +for x in */*/*/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl4 `dirname ${x}`/Makefile +done + +# we do not add these to libpthread/PTNAME/sysdeps/arch +for x in libc/*/*/*/Makefile.arch ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.arch.lvl4 `dirname ${x}`/Makefile +done + +exit 0 diff --git a/extra/scripts/defs.awk b/extra/scripts/defs.awk new file mode 100644 index 0000000..1716fb1 --- /dev/null +++ b/extra/scripts/defs.awk @@ -0,0 +1,27 @@ +/^[ ]*\.endp/ { need_endp = 1 } +/^[ ]*\.end/ { need_end = 1 } +/^[ ]*\.align/ { if($2 > max) max = $2; } + +END { + if(need_endp) + { + print "#define END_INIT .endp _init"; + print "#define END_FINI .endp _fini"; + } else if(need_end) + { + print "#define END_INIT .end _init"; + print "#define END_FINI .end _fini"; + } + else + { + print "#define END_INIT"; + print "#define END_FINI"; + } + if(max) + print "#define ALIGN .align", max; + else + print "#define ALIGN"; + + print "#include "; + #print "weak_extern (__gmon_start__)"; +} diff --git a/extra/scripts/format.lds b/extra/scripts/format.lds new file mode 100644 index 0000000..c20212e --- /dev/null +++ b/extra/scripts/format.lds @@ -0,0 +1,3 @@ +/* GNU ld script + * Use the shared library, but some functions are only in + * the static library, so try that secondarily. */ diff --git a/extra/scripts/gen_bits_syscall_h.sh b/extra/scripts/gen_bits_syscall_h.sh new file mode 100755 index 0000000..f6353ba --- /dev/null +++ b/extra/scripts/gen_bits_syscall_h.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Copyright (C) 2001 Manuel Novoa III +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# June 27, 2001 Manuel Novoa III +# +# This script expects top_builddir and CC (as used in the Makefiles) to be set +# in the environment, and outputs the appropriate +# $top_builddir/include/bits/sysnum.h # corresponding to +# $top_builddir/include/asm/unistd.h to stdout. +# +# Warning!!! This does _no_ error checking!!! + +INCLUDE_OPTS="-nostdinc -I${KERNEL_HEADERS}" + +case $CC in +*icc*) CC_SYSNUM_ARGS="-dM" ;; +*) CC_SYSNUM_ARGS="-dN" ;; +esac + +( echo "#include "; + echo "#include " | + $CC -E $CC_SYSNUM_ARGS $INCLUDE_OPTS - | + sed -ne 's/^[ ]*#define[ ]*\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/UCLIBC\1\2 \1\2/gp' \ + -e 's/^[ ]*#undef[ ]*\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/UNDEFUCLIBC\1\2 \1\2/gp' # needed to strip out any kernel-internal defines +) | +$CC -E $INCLUDE_OPTS - | +( echo "/* WARNING!!! AUTO-GENERATED FILE!!! DO NOT EDIT!!! */" ; + echo ; + echo "#ifndef _BITS_SYSNUM_H" ; + echo "#define _BITS_SYSNUM_H" ; + echo ; + echo "#ifndef _SYSCALL_H" ; + echo "# error \"Never use directly; include instead.\"" ; + echo "#endif" ; echo ; + sed -ne 's/^UCLIBC\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\) *\(.*\)/#undef \1\2\ +#define \1\2 \3\ +#define SYS_\2 \1\2/gp' \ + -e 's/^UNDEFUCLIBC\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/#undef \1\2/gp' + echo ; + echo "#endif" ; +) diff --git a/extra/scripts/getent b/extra/scripts/getent new file mode 100755 index 0000000..30d515b --- /dev/null +++ b/extra/scripts/getent @@ -0,0 +1,43 @@ +#!/bin/sh +# $Header: /var/cvs/uClibc/extra/scripts/getent,v 1.2 2005/02/02 14:18:01 solar Exp $ +# +# Closely (not perfectly) emulate the behavior of glibc's getent utility +# +#passwd|shadow|group|aliases|hosts|networks|ethers|netgroup|protocols|services|rpc +# only returns the first match (by design) +# dns based search is not supported (hosts,networks) +# case-insensitive matches not supported (ethers; others?) +# may return false-positives (hosts,protocols,rpc,services,ethers) + +export PATH="${PATH}:/bin:/usr/bin" + +file="/etc/$1" +case $1 in + passwd|group) + match="^$2:\|^[^:]*:[^:]*:$2:" ;; + shadow) + match="^$2:" ;; + networks|netgroup) + match="^[[:space:]]*$2\>" ;; + hosts|protocols|rpc|services|ethers) + match="\<$2\>" ;; + aliases) + match="^[[:space:]]*$2[[:space:]]*:" ;; + ""|-h|--help) + echo "USAGE: $0 database [key]" + exit 0 ;; + *) + echo "$0: Unknown database: $1" 1>&2 + exit 1 ;; +esac + +if [ ! -f "$file" ] ; then + echo "$0: Could not find database file for $1" 1>&2 + exit 1 +fi + +if [ $# -eq 1 ] ; then + exec cat "$file" +else + sed "s/#.*//; /$match/q; d" "$file" | grep . || exit 2 +fi diff --git a/extra/scripts/install_headers.sh b/extra/scripts/install_headers.sh new file mode 100755 index 0000000..d38d853 --- /dev/null +++ b/extra/scripts/install_headers.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# Parameters: +# $1 = source dir +# $2 = dst dir +# $top_builddir = well you guessed it + +die_if_not_dir() +{ + for dir in "$@"; do + test -d "$dir" && continue + echo "Error: '$dir' is not a directory" + exit 1 + done +} + + +# Ensure that created dirs/files have 755/644 perms +umask 022 + + +# Sanity tests +die_if_not_dir "$1" +mkdir -p "$2" 2>/dev/null +die_if_not_dir "$2" +die_if_not_dir "$top_builddir" +if ! test -x "$top_builddir/extra/scripts/unifdef"; then + echo "Error: need '$top_builddir/extra/scripts/unifdef' executable" + exit 1 +fi + + +# Sanitize and copy uclibc headers +( +# We must cd, or else we'll prepend "$1" to filenames! +cd "$1" || exit 1 +find ! -name '.' -a ! -path '*/.*' | sed -e 's/^\.\///' -e '/^config\//d' \ + -e '/^config$/d' +) | \ +( +IFS='' +while read -r filename; do + if test -d "$1/$filename"; then + mkdir -p "$2/$filename" 2>/dev/null + else + # NB: unifdef exits with 1 if output is not + # exactly the same as input. That's ok. + # Do not abort the script if unifdef "fails"! + "$top_builddir/extra/scripts/unifdef" -UUCLIBC_INTERNAL "$1/$filename" \ + | sed -e '/^\(rtld\|lib\(c\|m\|resolv\|dl\|intl\|rt\|nsl\|util\|crypt\|pthread\)\)_hidden_proto[ ]*([a-zA-Z0-9_]*)$/d' >"$2/$filename" + fi +done +) + + +# Fix mode/owner bits +cd "$2" || exit 1 +chmod -R u=rwX,go=rX . >/dev/null 2>&1 +chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1 diff --git a/extra/scripts/install_kernel_headers.sh b/extra/scripts/install_kernel_headers.sh new file mode 100755 index 0000000..7e86eb8 --- /dev/null +++ b/extra/scripts/install_kernel_headers.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# Parameters: +# $1 = source dir +# $2 = dst dir +# $top_builddir = well you guessed it + +die_if_not_dir() +{ + for dir in "$@"; do + test -d "$dir" && continue + echo "Error: '$dir' is not a directory" + exit 1 + done +} + + +# Ensure that created dirs/files have 755/644 perms +umask 022 + + +# Sanity tests +die_if_not_dir "$1" +mkdir -p "$2" 2>/dev/null +die_if_not_dir "$2" +die_if_not_dir "$top_builddir" + + +# Just copy (no sanitization) some kernel headers. +eval `grep ^KERNEL_HEADERS "$top_builddir/.config"` +if ! test "$KERNEL_HEADERS" \ +|| ! test -d "$KERNEL_HEADERS/asm" \ +|| ! test -d "$KERNEL_HEADERS/asm-generic" \ +|| ! test -d "$KERNEL_HEADERS/linux" \ +; then + echo "Error: '$KERNEL_HEADERS' is not a directory containing kernel headers." + echo "Check KERNEL_HEADERS= in your .config file." + exit 1 +fi +# Do the copying only if src and dst dirs are not the same. +# Be thorough: do not settle just for textual compare, +# and guard against "pwd" being handled as shell builtin. +# Double quoting looks weird, but it works (even bbox ash too). +if test "`(cd "$KERNEL_HEADERS"; env pwd)`" != "`(cd "$2"; env pwd)`"; then + # NB: source or target files and directories may be symlinks, + # and for all we know, good reasons. + # We must work correctly in these cases. This includes "do not replace + # target symlink with real directory" rule. So, no rm -rf here please. + mkdir -p "$2/asm" 2>/dev/null + mkdir -p "$2/linux" 2>/dev/null + # Exists, but is not a dir? That's bad, bail out + die_if_not_dir "$2/asm" "$2/linux" + # cp -HL creates regular destination files even if sources are symlinks. + # This is intended. + # (NB: you need busybox 1.11.x for this. earlier ones are slightly buggy) + cp -RHL "$KERNEL_HEADERS/asm"/* "$2/asm" || exit 1 + cp -RHL "$KERNEL_HEADERS/linux"/* "$2/linux" || exit 1 + # Linux 2.4 doesn't have it + if test -d "$KERNEL_HEADERS/asm-generic"; then + mkdir -p "$2/asm-generic" 2>/dev/null + die_if_not_dir "$2/asm-generic" + cp -RHL "$KERNEL_HEADERS/asm-generic"/* "$2/asm-generic" || exit 1 + fi + if ! test -f "$2/linux/version.h"; then + echo "Warning: '$KERNEL_HEADERS/linux/version.h' is not found" + echo "in kernel headers directory specified in .config." + echo "Some programs won't like that. Consider fixing it by hand." + fi +fi + + +# Fix mode/owner bits +cd "$2" || exit 1 +chmod -R u=rwX,go=rX . >/dev/null 2>&1 +chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1 diff --git a/extra/scripts/randconfig.sh b/extra/scripts/randconfig.sh new file mode 100755 index 0000000..5986a9b --- /dev/null +++ b/extra/scripts/randconfig.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# build random configurations +# Usage: +# ARCH=i386 nohup ./extra/scripts/randconfig.sh & sleep 1800 && touch STOP +# +# The above builds random i386 configs and automatically stops after 30 minutes + +test "x$ARCH" = "x" && ARCH=`uname -m` +KCONFIG_ALLCONFIG=.config.allconfig +(echo TARGET_$ARCH=y + echo '# UCLIBC_PREGENERATED_LOCALE_DATA is not set' + echo '# DOMULTI is not set' + echo '# UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA is not set' +) > $KCONFIG_ALLCONFIG +export KCONFIG_ALLCONFIG + +i=0 +while test ! -f STOP +do + make $* randconfig > /dev/null + make $* silentoldconfig > /dev/null + if (make $*) 2>&1 >& mk.log + then + : + else + i=`expr $i + 1` + num=`printf "%.5d" $i` + mv .config FAILED.$num.config + mv mk.log FAILED.$num.log + fi + make distclean > /dev/null || true +done +rm -f STOP diff --git a/extra/scripts/relative_path.sh b/extra/scripts/relative_path.sh new file mode 100755 index 0000000..c859646 --- /dev/null +++ b/extra/scripts/relative_path.sh @@ -0,0 +1,44 @@ +#! /bin/sh +# +# Copyright 2003 Alexandre Oliva +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# This script computes a relative pathname from $1 to $2 +# They are assumed to not contain . or .. pathname components, +# but if both directories exist and cd/pwd canonicalizes pathnames, +# this shouldn't matter. PWD_CMD may be set to some pwd command that does. + +from=`(cd $1 > /dev/null && ${PWD_CMD-pwd} || echo $1) 2>/dev/null | sed 's,//*,/,g;s,/*$,,'` +target=`(cd $2 > /dev/null && ${PWD_CMD-pwd} || echo $2) 2>/dev/null | sed 's,//*,/,g;s,/*$,,'` + +case $from in /* | "") ;; *) from=`${PWD_CMD-pwd}`/$from ;; esac +case $target in /* | "") ;; *) target=`${PWD_CMD-pwd}`/$target ;; esac + +case $target in +"$from" | "$from/"*) + dots=`echo $from | sed s,.,.,g` + echo $target | sed "s,^$dots/*,,;s,[^/]$,&/," + exit 0 + ;; +esac + +case $from in +"$target/"*) + dots=`echo $target | sed s,.,.,g` + echo $from/ | sed "s,^$dots/*,,;s,[^/]$,&/,;s,[^/]*/*,../,g;s,[^/]$,&/," + exit 0 + ;; +esac + +prefix=`echo $from///$target | sed 's,\(\(/[^/]*\)*\).*///\1.*,\1,'` +dots=`echo $prefix | sed s,.,.,g` +from=`echo $from | sed "s,^$dots,,"` +target=`echo $target | sed "s,^$dots,,"` + +from=`echo $from | sed 's,[^/][^/]*,..,g;s,.$,&/,'` +echo ${from}$target/ + +exit 0 diff --git a/extra/scripts/relinfo.pl b/extra/scripts/relinfo.pl new file mode 100755 index 0000000..ec4a5df --- /dev/null +++ b/extra/scripts/relinfo.pl @@ -0,0 +1,78 @@ +#! /usr/bin/perl +eval "exec /usr/bin/perl -S $0 $*" + if 0; +# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. +# Written by Ulrich Drepper , 2000. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +for ($cnt = 0; $cnt <= $#ARGV; ++$cnt) { + $relent = 0; + $relsz = 0; + $relcount = 0; + $pltrelsz = 0; + $extplt = 0; + $users = 0; + + open (READLINK, "readlink -f $ARGV[$cnt] |") || die "cannot open readlink"; + while () { + chop; + $fullpath = $_; + } + close (READLINK); + + open (READELF, "eu-readelf -d $ARGV[$cnt] |") || die "cannot open $ARGV[$cnt]"; + while () { + chop; + if (/.* RELA?ENT *([0-9]*).*/) { + $relent = $1 + 0; + } elsif (/.* RELA?SZ *([0-9]*).*/) { + $relsz = $1 + 0; + } elsif (/.* RELA?COUNT *([0-9]*).*/) { + $relcount = $1 + 0; + } elsif (/.* PLTRELSZ *([0-9]*).*/) { + $pltrelsz = $1 + 0; + } + } + close (READELF); + + open (READELF, "eu-readelf -r $ARGV[$cnt] | sed '/'.gnu.conflict'/,/^\$/d' |") || die "cannot open $ARGV[$cnt]"; + while () { + chop; + if (/.*JU?MP_SLOT *0+ .*/) { + ++$extplt; + } + } + close (READELF); + + if (open (PRELINK, "/usr/sbin/prelink -p 2>/dev/null | fgrep \"$fullpath\" |")) { + while () { + ++$users; + } + close(PRELINK); + } else { + $users = -1; + } + + printf ("%s: %d relocations, %d relative (%d%%), %d PLT entries, %d for local syms (%d%%)", + $ARGV[$cnt], $relent == 0 ? 0 : $relsz / $relent, $relcount, + $relent == 0 ? 0 : ($relcount * 100) / ($relsz / $relent), + $relent == 0 ? 0 : $pltrelsz / $relent, + $relent == 0 ? 0 : $pltrelsz / $relent - $extplt, + $relent == 0 ? 0 : (($pltrelsz / $relent - $extplt) * 100) / ($pltrelsz / $relent)); + if ($users >= 0) { + printf(", %d users", $users); + } + printf("\n"); +} diff --git a/extra/scripts/unifdef.c b/extra/scripts/unifdef.c new file mode 100644 index 0000000..552025e --- /dev/null +++ b/extra/scripts/unifdef.c @@ -0,0 +1,1005 @@ +/* + * Copyright (c) 2002 - 2005 Tony Finch . All rights reserved. + * + * This code is derived from software contributed to Berkeley by Dave Yost. + * It was rewritten to support ANSI C by Tony Finch. The original version of + * unifdef carried the following copyright notice. None of its code remains + * in this version (though some of the names remain). + * + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#ifndef lint +#if 0 +static const char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif +#ifdef __IDSTRING +__IDSTRING(Berkeley, "@(#)unifdef.c 8.1 (Berkeley) 6/6/93"); +__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $"); +__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $"); +#endif +#endif /* not lint */ +#ifdef __FBSDID +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $"); +#endif + +/* + * unifdef - remove ifdef'ed lines + * + * Wishlist: + * provide an option which will append the name of the + * appropriate symbol after #else's and #endif's + * provide an option which will check symbols after + * #else's and #endif's to see that they match their + * corresponding #ifdef or #ifndef + * + * The first two items above require better buffer handling, which would + * also make it possible to handle all "dodgy" directives correctly. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +size_t strlcpy(char *dst, const char *src, size_t siz); + +/* types of input lines: */ +typedef enum { + LT_TRUEI, /* a true #if with ignore flag */ + LT_FALSEI, /* a false #if with ignore flag */ + LT_IF, /* an unknown #if */ + LT_TRUE, /* a true #if */ + LT_FALSE, /* a false #if */ + LT_ELIF, /* an unknown #elif */ + LT_ELTRUE, /* a true #elif */ + LT_ELFALSE, /* a false #elif */ + LT_ELSE, /* #else */ + LT_ENDIF, /* #endif */ + LT_DODGY, /* flag: directive is not on one line */ + LT_DODGY_LAST = LT_DODGY + LT_ENDIF, + LT_PLAIN, /* ordinary line */ + LT_EOF, /* end of file */ + LT_COUNT +} Linetype; + +static char const * const linetype_name[] = { + "TRUEI", "FALSEI", "IF", "TRUE", "FALSE", + "ELIF", "ELTRUE", "ELFALSE", "ELSE", "ENDIF", + "DODGY TRUEI", "DODGY FALSEI", + "DODGY IF", "DODGY TRUE", "DODGY FALSE", + "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE", + "DODGY ELSE", "DODGY ENDIF", + "PLAIN", "EOF" +}; + +/* state of #if processing */ +typedef enum { + IS_OUTSIDE, + IS_FALSE_PREFIX, /* false #if followed by false #elifs */ + IS_TRUE_PREFIX, /* first non-false #(el)if is true */ + IS_PASS_MIDDLE, /* first non-false #(el)if is unknown */ + IS_FALSE_MIDDLE, /* a false #elif after a pass state */ + IS_TRUE_MIDDLE, /* a true #elif after a pass state */ + IS_PASS_ELSE, /* an else after a pass state */ + IS_FALSE_ELSE, /* an else after a true state */ + IS_TRUE_ELSE, /* an else after only false states */ + IS_FALSE_TRAILER, /* #elifs after a true are false */ + IS_COUNT +} Ifstate; + +static char const * const ifstate_name[] = { + "OUTSIDE", "FALSE_PREFIX", "TRUE_PREFIX", + "PASS_MIDDLE", "FALSE_MIDDLE", "TRUE_MIDDLE", + "PASS_ELSE", "FALSE_ELSE", "TRUE_ELSE", + "FALSE_TRAILER" +}; + +/* state of comment parser */ +typedef enum { + NO_COMMENT = false, /* outside a comment */ + C_COMMENT, /* in a comment like this one */ + CXX_COMMENT, /* between // and end of line */ + STARTING_COMMENT, /* just after slash-backslash-newline */ + FINISHING_COMMENT, /* star-backslash-newline in a C comment */ + CHAR_LITERAL, /* inside '' */ + STRING_LITERAL /* inside "" */ +} Comment_state; + +static char const * const comment_name[] = { + "NO", "C", "CXX", "STARTING", "FINISHING", "CHAR", "STRING" +}; + +/* state of preprocessor line parser */ +typedef enum { + LS_START, /* only space and comments on this line */ + LS_HASH, /* only space, comments, and a hash */ + LS_DIRTY /* this line can't be a preprocessor line */ +} Line_state; + +static char const * const linestate_name[] = { + "START", "HASH", "DIRTY" +}; + +/* + * Minimum translation limits from ISO/IEC 9899:1999 5.2.4.1 + */ +#define MAXDEPTH 64 /* maximum #if nesting */ +#define MAXLINE 4096 /* maximum length of line */ +#define MAXSYMS 4096 /* maximum number of symbols */ + +/* + * Sometimes when editing a keyword the replacement text is longer, so + * we leave some space at the end of the tline buffer to accommodate this. + */ +#define EDITSLOP 10 + +/* + * Globals. + */ + +static bool complement; /* -c: do the complement */ +static bool debugging; /* -d: debugging reports */ +static bool iocccok; /* -e: fewer IOCCC errors */ +static bool killconsts; /* -k: eval constant #ifs */ +static bool lnblank; /* -l: blank deleted lines */ +static bool lnnum; /* -n: add #line directives */ +static bool symlist; /* -s: output symbol list */ +static bool text; /* -t: this is a text file */ + +static const char *symname[MAXSYMS]; /* symbol name */ +static const char *value[MAXSYMS]; /* -Dsym=value */ +static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */ +static int nsyms; /* number of symbols */ + +static FILE *input; /* input file pointer */ +static const char *filename; /* input file name */ +static int linenum; /* current line number */ + +static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ +static char *keyword; /* used for editing #elif's */ + +static Comment_state incomment; /* comment parser state */ +static Line_state linestate; /* #if line parser state */ +static Ifstate ifstate[MAXDEPTH]; /* #if processor state */ +static bool ignoring[MAXDEPTH]; /* ignore comments state */ +static int stifline[MAXDEPTH]; /* start of current #if */ +static int depth; /* current #if nesting */ +static int delcount; /* count of deleted lines */ +static bool keepthis; /* don't delete constant #if */ + +static int exitstat; /* program exit status */ + +static void addsym(bool, bool, char *); +static void debug(const char *, ...); +static void done(void); +static void error(const char *); +static int findsym(const char *); +static void flushline(bool); +static Linetype getline(void); +static Linetype ifeval(const char **); +static void ignoreoff(void); +static void ignoreon(void); +static void keywordedit(const char *); +static void nest(void); +static void process(void); +static const char *skipcomment(const char *); +static const char *skipsym(const char *); +static void state(Ifstate); +static int strlcmp(const char *, const char *, size_t); +static void unnest(void); +static void usage(void); + +#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_') + +/* + * The main program. + */ +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1) + switch (opt) { + case 'i': /* treat stuff controlled by these symbols as text */ + /* + * For strict backwards-compatibility the U or D + * should be immediately after the -i but it doesn't + * matter much if we relax that requirement. + */ + opt = *optarg++; + if (opt == 'D') + addsym(true, true, optarg); + else if (opt == 'U') + addsym(true, false, optarg); + else + usage(); + break; + case 'D': /* define a symbol */ + addsym(false, true, optarg); + break; + case 'U': /* undef a symbol */ + addsym(false, false, optarg); + break; + case 'I': + /* no-op for compatibility with cpp */ + break; + case 'c': /* treat -D as -U and vice versa */ + complement = true; + break; + case 'd': + debugging = true; + break; + case 'e': /* fewer errors from dodgy lines */ + iocccok = true; + break; + case 'k': /* process constant #ifs */ + killconsts = true; + break; + case 'l': /* blank deleted lines instead of omitting them */ + lnblank = true; + break; + case 'n': /* add #line directive after deleted lines */ + lnnum = true; + break; + case 's': /* only output list of symbols that control #ifs */ + symlist = true; + break; + case 't': /* don't parse C comments */ + text = true; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + if (argc > 1) { + errx(2, "can only do one file"); + } else if (argc == 1 && strcmp(*argv, "-") != 0) { + filename = *argv; + input = fopen(filename, "r"); + if (input == NULL) + err(2, "can't open %s", filename); + } else { + filename = "[stdin]"; + input = stdin; + } + process(); + abort(); /* bug */ +} + +static void +usage(void) +{ + fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]" + " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); + exit(2); +} + +/* + * A state transition function alters the global #if processing state + * in a particular way. The table below is indexed by the current + * processing state and the type of the current line. + * + * Nesting is handled by keeping a stack of states; some transition + * functions increase or decrease the depth. They also maintain the + * ignore state on a stack. In some complicated cases they have to + * alter the preprocessor directive, as follows. + * + * When we have processed a group that starts off with a known-false + * #if/#elif sequence (which has therefore been deleted) followed by a + * #elif that we don't understand and therefore must keep, we edit the + * latter into a #if to keep the nesting correct. + * + * When we find a true #elif in a group, the following block will + * always be kept and the rest of the sequence after the next #elif or + * #else will be discarded. We edit the #elif into a #else and the + * following directive to #endif since this has the desired behaviour. + * + * "Dodgy" directives are split across multiple lines, the most common + * example being a multi-line comment hanging off the right of the + * directive. We can handle them correctly only if there is no change + * from printing to dropping (or vice versa) caused by that directive. + * If the directive is the first of a group we have a choice between + * failing with an error, or passing it through unchanged instead of + * evaluating it. The latter is not the default to avoid questions from + * users about unifdef unexpectedly leaving behind preprocessor directives. + */ +typedef void state_fn(void); + +/* report an error */ +static void Eelif (void) { error("Inappropriate #elif"); } +static void Eelse (void) { error("Inappropriate #else"); } +static void Eendif(void) { error("Inappropriate #endif"); } +static void Eeof (void) { error("Premature EOF"); } +static void Eioccc(void) { error("Obfuscated preprocessor control line"); } +/* plain line handling */ +static void print (void) { flushline(true); } +static void drop (void) { flushline(false); } +/* output lacks group's start line */ +static void Strue (void) { drop(); ignoreoff(); state(IS_TRUE_PREFIX); } +static void Sfalse(void) { drop(); ignoreoff(); state(IS_FALSE_PREFIX); } +static void Selse (void) { drop(); state(IS_TRUE_ELSE); } +/* print/pass this block */ +static void Pelif (void) { print(); ignoreoff(); state(IS_PASS_MIDDLE); } +static void Pelse (void) { print(); state(IS_PASS_ELSE); } +static void Pendif(void) { print(); unnest(); } +/* discard this block */ +static void Dfalse(void) { drop(); ignoreoff(); state(IS_FALSE_TRAILER); } +static void Delif (void) { drop(); ignoreoff(); state(IS_FALSE_MIDDLE); } +static void Delse (void) { drop(); state(IS_FALSE_ELSE); } +static void Dendif(void) { drop(); unnest(); } +/* first line of group */ +static void Fdrop (void) { nest(); Dfalse(); } +static void Fpass (void) { nest(); Pelif(); } +static void Ftrue (void) { nest(); Strue(); } +static void Ffalse(void) { nest(); Sfalse(); } +/* variable pedantry for obfuscated lines */ +static void Oiffy (void) { if (!iocccok) Eioccc(); Fpass(); ignoreon(); } +static void Oif (void) { if (!iocccok) Eioccc(); Fpass(); } +static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); } +/* ignore comments in this block */ +static void Idrop (void) { Fdrop(); ignoreon(); } +static void Itrue (void) { Ftrue(); ignoreon(); } +static void Ifalse(void) { Ffalse(); ignoreon(); } +/* edit this line */ +static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } +static void Mtrue (void) { keywordedit("else\n"); state(IS_TRUE_MIDDLE); } +static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); } +static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); } + +static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { +/* IS_OUTSIDE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif, + print, done }, +/* IS_FALSE_PREFIX */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof }, +/* IS_TRUE_PREFIX */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + print, Eeof }, +/* IS_PASS_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif, + print, Eeof }, +/* IS_FALSE_MIDDLE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof }, +/* IS_TRUE_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif, + print, Eeof }, +/* IS_PASS_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif, + print, Eeof }, +/* IS_FALSE_ELSE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc, + drop, Eeof }, +/* IS_TRUE_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc, + print, Eeof }, +/* IS_FALSE_TRAILER */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc, + drop, Eeof } +/*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF + TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY) + PLAIN EOF */ +}; + +/* + * State machine utility functions + */ +static void +done(void) +{ + if (incomment) + error("EOF in comment"); + exit(exitstat); +} +static void +ignoreoff(void) +{ + if (depth == 0) + abort(); /* bug */ + ignoring[depth] = ignoring[depth-1]; +} +static void +ignoreon(void) +{ + ignoring[depth] = true; +} +static void +keywordedit(const char *replacement) +{ + size_t size = tline + sizeof(tline) - keyword; + char *dst = keyword; + const char *src = replacement; + if (size != 0) { + while ((--size != 0) && (*src != '\0')) + *dst++ = *src++; + *dst = '\0'; + } + print(); +} +static void +nest(void) +{ + depth += 1; + if (depth >= MAXDEPTH) + error("Too many levels of nesting"); + stifline[depth] = linenum; +} +static void +unnest(void) +{ + if (depth == 0) + abort(); /* bug */ + depth -= 1; +} +static void +state(Ifstate is) +{ + ifstate[depth] = is; +} + +/* + * Write a line to the output or not, according to command line options. + */ +static void +flushline(bool keep) +{ + if (symlist) + return; + if (keep ^ complement) { + if (lnnum && delcount > 0) + printf("#line %d\n", linenum); + fputs(tline, stdout); + delcount = 0; + } else { + if (lnblank) + putc('\n', stdout); + exitstat = 1; + delcount += 1; + } +} + +/* + * The driver for the state machine. + */ +static void +process(void) +{ + Linetype lineval; + + for (;;) { + linenum++; + lineval = getline(); + trans_table[ifstate[depth]][lineval](); + debug("process %s -> %s depth %d", + linetype_name[lineval], + ifstate_name[ifstate[depth]], depth); + } +} + +/* + * Parse a line and determine its type. We keep the preprocessor line + * parser state between calls in the global variable linestate, with + * help from skipcomment(). + */ +static Linetype +getline(void) +{ + const char *cp; + int cursym; + int kwlen; + Linetype retval; + Comment_state wascomment; + + if (fgets(tline, MAXLINE, input) == NULL) + return (LT_EOF); + retval = LT_PLAIN; + wascomment = incomment; + cp = skipcomment(tline); + if (linestate == LS_START) { + if (*cp == '#') { + linestate = LS_HASH; + cp = skipcomment(cp + 1); + } else if (*cp != '\0') + linestate = LS_DIRTY; + } + if (!incomment && linestate == LS_HASH) { + keyword = tline + (cp - tline); + cp = skipsym(cp); + kwlen = cp - keyword; + /* no way can we deal with a continuation inside a keyword */ + if (strncmp(cp, "\\\n", 2) == 0) + Eioccc(); + if (strlcmp("ifdef", keyword, kwlen) == 0 || + strlcmp("ifndef", keyword, kwlen) == 0) { + cp = skipcomment(cp); + if ((cursym = findsym(cp)) < 0) + retval = LT_IF; + else { + retval = (keyword[2] == 'n') + ? LT_FALSE : LT_TRUE; + if (value[cursym] == NULL) + retval = (retval == LT_TRUE) + ? LT_FALSE : LT_TRUE; + if (ignore[cursym]) + retval = (retval == LT_TRUE) + ? LT_TRUEI : LT_FALSEI; + } + cp = skipsym(cp); + } else if (strlcmp("if", keyword, kwlen) == 0) + retval = ifeval(&cp); + else if (strlcmp("elif", keyword, kwlen) == 0) + retval = ifeval(&cp) - LT_IF + LT_ELIF; + else if (strlcmp("else", keyword, kwlen) == 0) + retval = LT_ELSE; + else if (strlcmp("endif", keyword, kwlen) == 0) + retval = LT_ENDIF; + else { + linestate = LS_DIRTY; + retval = LT_PLAIN; + } + cp = skipcomment(cp); + if (*cp != '\0') { + linestate = LS_DIRTY; + if (retval == LT_TRUE || retval == LT_FALSE || + retval == LT_TRUEI || retval == LT_FALSEI) + retval = LT_IF; + if (retval == LT_ELTRUE || retval == LT_ELFALSE) + retval = LT_ELIF; + } + if (retval != LT_PLAIN && (wascomment || incomment)) { + retval += LT_DODGY; + if (incomment) + linestate = LS_DIRTY; + } + /* skipcomment should have changed the state */ + if (linestate == LS_HASH) + abort(); /* bug */ + } + if (linestate == LS_DIRTY) { + while (*cp != '\0') + cp = skipcomment(cp + 1); + } + debug("parser %s comment %s line", + comment_name[incomment], linestate_name[linestate]); + return (retval); +} + +/* + * These are the binary operators that are supported by the expression + * evaluator. Note that if support for division is added then we also + * need short-circuiting booleans because of divide-by-zero. + */ +static int op_lt(int a, int b) { return (a < b); } +static int op_gt(int a, int b) { return (a > b); } +static int op_le(int a, int b) { return (a <= b); } +static int op_ge(int a, int b) { return (a >= b); } +static int op_eq(int a, int b) { return (a == b); } +static int op_ne(int a, int b) { return (a != b); } +static int op_or(int a, int b) { return (a || b); } +static int op_and(int a, int b) { return (a && b); } + +/* + * An evaluation function takes three arguments, as follows: (1) a pointer to + * an element of the precedence table which lists the operators at the current + * level of precedence; (2) a pointer to an integer which will receive the + * value of the expression; and (3) a pointer to a char* that points to the + * expression to be evaluated and that is updated to the end of the expression + * when evaluation is complete. The function returns LT_FALSE if the value of + * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the + * expression could not be evaluated. + */ +struct ops; + +typedef Linetype eval_fn(const struct ops *, int *, const char **); + +static eval_fn eval_table, eval_unary; + +/* + * The precedence table. Expressions involving binary operators are evaluated + * in a table-driven way by eval_table. When it evaluates a subexpression it + * calls the inner function with its first argument pointing to the next + * element of the table. Innermost expressions have special non-table-driven + * handling. + */ +static const struct ops { + eval_fn *inner; + struct op { + const char *str; + int (*fn)(int, int); + } op[5]; +} eval_ops[] = { + { eval_table, { { "||", op_or } } }, + { eval_table, { { "&&", op_and } } }, + { eval_table, { { "==", op_eq }, + { "!=", op_ne } } }, + { eval_unary, { { "<=", op_le }, + { ">=", op_ge }, + { "<", op_lt }, + { ">", op_gt } } } +}; + +/* + * Function for evaluating the innermost parts of expressions, + * viz. !expr (expr) defined(symbol) symbol number + * We reset the keepthis flag when we find a non-constant subexpression. + */ +static Linetype +eval_unary(const struct ops *ops, int *valp, const char **cpp) +{ + const char *cp; + char *ep; + int sym; + + cp = skipcomment(*cpp); + if (*cp == '!') { + debug("eval%d !", ops - eval_ops); + cp++; + if (eval_unary(ops, valp, &cp) == LT_IF) + return (LT_IF); + *valp = !*valp; + } else if (*cp == '(') { + cp++; + debug("eval%d (", ops - eval_ops); + if (eval_table(eval_ops, valp, &cp) == LT_IF) + return (LT_IF); + cp = skipcomment(cp); + if (*cp++ != ')') + return (LT_IF); + } else if (isdigit((unsigned char)*cp)) { + debug("eval%d number", ops - eval_ops); + *valp = strtol(cp, &ep, 0); + cp = skipsym(cp); + } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { + cp = skipcomment(cp+7); + debug("eval%d defined", ops - eval_ops); + if (*cp++ != '(') + return (LT_IF); + cp = skipcomment(cp); + sym = findsym(cp); + if (sym < 0) + return (LT_IF); + *valp = (value[sym] != NULL); + cp = skipsym(cp); + cp = skipcomment(cp); + if (*cp++ != ')') + return (LT_IF); + keepthis = false; + } else if (!endsym(*cp)) { + debug("eval%d symbol", ops - eval_ops); + sym = findsym(cp); + if (sym < 0) + return (LT_IF); + if (value[sym] == NULL) + *valp = 0; + else { + *valp = strtol(value[sym], &ep, 0); + if (*ep != '\0' || ep == value[sym]) + return (LT_IF); + } + cp = skipsym(cp); + keepthis = false; + } else { + debug("eval%d bad expr", ops - eval_ops); + return (LT_IF); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + return (*valp ? LT_TRUE : LT_FALSE); +} + +/* + * Table-driven evaluation of binary operators. + */ +static Linetype +eval_table(const struct ops *ops, int *valp, const char **cpp) +{ + const struct op *op; + const char *cp; + int val; + + debug("eval%d", ops - eval_ops); + cp = *cpp; + if (ops->inner(ops+1, valp, &cp) == LT_IF) + return (LT_IF); + for (;;) { + cp = skipcomment(cp); + for (op = ops->op; op->str != NULL; op++) + if (strncmp(cp, op->str, strlen(op->str)) == 0) + break; + if (op->str == NULL) + break; + cp += strlen(op->str); + debug("eval%d %s", ops - eval_ops, op->str); + if (ops->inner(ops+1, &val, &cp) == LT_IF) + return (LT_IF); + *valp = op->fn(*valp, val); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + return (*valp ? LT_TRUE : LT_FALSE); +} + +/* + * Evaluate the expression on a #if or #elif line. If we can work out + * the result we return LT_TRUE or LT_FALSE accordingly, otherwise we + * return just a generic LT_IF. + */ +static Linetype +ifeval(const char **cpp) +{ + int ret; + int val; + + debug("eval %s", *cpp); + keepthis = killconsts ? false : true; + ret = eval_table(eval_ops, &val, cpp); + debug("eval = %d", val); + return (keepthis ? LT_IF : ret); +} + +/* + * Skip over comments, strings, and character literals and stop at the + * next character position that is not whitespace. Between calls we keep + * the comment state in the global variable incomment, and we also adjust + * the global variable linestate when we see a newline. + * XXX: doesn't cope with the buffer splitting inside a state transition. + */ +static const char * +skipcomment(const char *cp) +{ + if (text || ignoring[depth]) { + for (; isspace((unsigned char)*cp); cp++) + if (*cp == '\n') + linestate = LS_START; + return (cp); + } + while (*cp != '\0') + /* don't reset to LS_START after a line continuation */ + if (strncmp(cp, "\\\n", 2) == 0) + cp += 2; + else switch (incomment) { + case NO_COMMENT: + if (strncmp(cp, "/\\\n", 3) == 0) { + incomment = STARTING_COMMENT; + cp += 3; + } else if (strncmp(cp, "/*", 2) == 0) { + incomment = C_COMMENT; + cp += 2; + } else if (strncmp(cp, "//", 2) == 0) { + incomment = CXX_COMMENT; + cp += 2; + } else if (strncmp(cp, "\'", 1) == 0) { + incomment = CHAR_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\"", 1) == 0) { + incomment = STRING_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\n", 1) == 0) { + linestate = LS_START; + cp += 1; + } else if (strchr(" \t", *cp) != NULL) { + cp += 1; + } else + return (cp); + continue; + case CXX_COMMENT: + if (strncmp(cp, "\n", 1) == 0) { + incomment = NO_COMMENT; + linestate = LS_START; + } + cp += 1; + continue; + case CHAR_LITERAL: + case STRING_LITERAL: + if ((incomment == CHAR_LITERAL && cp[0] == '\'') || + (incomment == STRING_LITERAL && cp[0] == '\"')) { + incomment = NO_COMMENT; + cp += 1; + } else if (cp[0] == '\\') { + if (cp[1] == '\0') + cp += 1; + else + cp += 2; + } else if (strncmp(cp, "\n", 1) == 0) { + if (incomment == CHAR_LITERAL) + error("unterminated char literal"); + else + error("unterminated string literal"); + } else + cp += 1; + continue; + case C_COMMENT: + if (strncmp(cp, "*\\\n", 3) == 0) { + incomment = FINISHING_COMMENT; + cp += 3; + } else if (strncmp(cp, "*/", 2) == 0) { + incomment = NO_COMMENT; + cp += 2; + } else + cp += 1; + continue; + case STARTING_COMMENT: + if (*cp == '*') { + incomment = C_COMMENT; + cp += 1; + } else if (*cp == '/') { + incomment = CXX_COMMENT; + cp += 1; + } else { + incomment = NO_COMMENT; + linestate = LS_DIRTY; + } + continue; + case FINISHING_COMMENT: + if (*cp == '/') { + incomment = NO_COMMENT; + cp += 1; + } else + incomment = C_COMMENT; + continue; + default: + abort(); /* bug */ + } + return (cp); +} + +/* + * Skip over an identifier. + */ +static const char * +skipsym(const char *cp) +{ + while (!endsym(*cp)) + ++cp; + return (cp); +} + +/* + * Look for the symbol in the symbol table. If is is found, we return + * the symbol table index, else we return -1. + */ +static int +findsym(const char *str) +{ + const char *cp; + int symind; + + cp = skipsym(str); + if (cp == str) + return (-1); + if (symlist) { + printf("%.*s\n", (int)(cp-str), str); + /* we don't care about the value of the symbol */ + return (0); + } + for (symind = 0; symind < nsyms; ++symind) { + if (strlcmp(symname[symind], str, cp-str) == 0) { + debug("findsym %s %s", symname[symind], + value[symind] ? value[symind] : ""); + return (symind); + } + } + return (-1); +} + +/* + * Add a symbol to the symbol table. + */ +static void +addsym(bool ignorethis, bool definethis, char *sym) +{ + int symind; + char *val; + + symind = findsym(sym); + if (symind < 0) { + if (nsyms >= MAXSYMS) + errx(2, "too many symbols"); + symind = nsyms++; + } + symname[symind] = sym; + ignore[symind] = ignorethis; + val = sym + (skipsym(sym) - sym); + if (definethis) { + if (*val == '=') { + value[symind] = val+1; + *val = '\0'; + } else if (*val == '\0') + value[symind] = ""; + else + usage(); + } else { + if (*val != '\0') + usage(); + value[symind] = NULL; + } +} + +/* + * Compare s with n characters of t. + * The same as strncmp() except that it checks that s[n] == '\0'. + */ +static int +strlcmp(const char *s, const char *t, size_t n) +{ + while (n-- && *t != '\0') + if (*s != *t) + return ((unsigned char)*s - (unsigned char)*t); + else + ++s, ++t; + return ((unsigned char)*s); +} + +/* + * Diagnostics. + */ +static void +debug(const char *msg, ...) +{ + va_list ap; + + if (debugging) { + va_start(ap, msg); + vwarnx(msg, ap); + va_end(ap); + } +} + +static void +error(const char *msg) +{ + if (depth == 0) + warnx("%s: %d: %s", filename, linenum, msg); + else + warnx("%s: %d: %s (#if line %d depth %d)", + filename, linenum, msg, stifline[depth], depth); + errx(2, "output may be truncated"); +} diff --git a/include/_lfs_64.h b/include/_lfs_64.h new file mode 100644 index 0000000..deee98a --- /dev/null +++ b/include/_lfs_64.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS != 64 +#undef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 1 +#endif + +/* We absolutely do _NOT_ want interfaces silently + * renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif + +#else + +# error Do not include this header in files not built when LFS is disabled + +#endif diff --git a/include/a.out.h b/include/a.out.h new file mode 100644 index 0000000..d963de7 --- /dev/null +++ b/include/a.out.h @@ -0,0 +1,5 @@ +#ifdef _LIBC +# include_next +#else +# include +#endif diff --git a/include/alloca.h b/include/alloca.h new file mode 100644 index 0000000..b4fc317 --- /dev/null +++ b/include/alloca.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1992, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +/* Remove any previous definitions. */ +#undef alloca + +/* Allocate a block that will be freed when the calling function exits. */ +extern void *alloca (size_t __size) __THROW; + +#ifdef __GNUC__ +# define alloca(size) __builtin_alloca (size) +#endif /* GCC. */ + +#define __MAX_ALLOCA_CUTOFF 65536 + +__END_DECLS + +#endif /* alloca.h */ diff --git a/include/ar.h b/include/ar.h new file mode 100644 index 0000000..5d157ec --- /dev/null +++ b/include/ar.h @@ -0,0 +1,48 @@ +/* Header describing `ar' archive file format. + Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _AR_H +#define _AR_H 1 + +#include + +/* Archive files start with the ARMAG identifying string. Then follows a + `struct ar_hdr', and as many bytes of member file data as its `ar_size' + member indicates, for each member file. */ + +#define ARMAG "!\n" /* String that begins an archive file. */ +#define SARMAG 8 /* Size of that string. */ + +#define ARFMAG "`\n" /* String in ar_fmag at end of each header. */ + +__BEGIN_DECLS + +struct ar_hdr + { + char ar_name[16]; /* Member file name, sometimes / terminated. */ + char ar_date[12]; /* File date, decimal seconds since Epoch. */ + char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ + char ar_mode[8]; /* File mode, in ASCII octal. */ + char ar_size[10]; /* File size, in ASCII decimal. */ + char ar_fmag[2]; /* Always contains ARFMAG. */ + }; + +__END_DECLS + +#endif /* ar.h */ diff --git a/include/arpa/ftp.h b/include/arpa/ftp.h new file mode 100644 index 0000000..e5b340d --- /dev/null +++ b/include/arpa/ftp.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftp.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ARPA_FTP_H +#define _ARPA_FTP_H 1 + +/* Definitions for FTP; see RFC-765. */ + +/* + * Reply codes. + */ +#define PRELIM 1 /* positive preliminary */ +#define COMPLETE 2 /* positive completion */ +#define CONTINUE 3 /* positive intermediate */ +#define TRANSIENT 4 /* transient negative completion */ +#define ERROR 5 /* permanent negative completion */ + +/* + * Type codes + */ +#define TYPE_A 1 /* ASCII */ +#define TYPE_E 2 /* EBCDIC */ +#define TYPE_I 3 /* image */ +#define TYPE_L 4 /* local byte size */ + +#ifdef FTP_NAMES +char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; +#endif + +/* + * Form codes + */ +#define FORM_N 1 /* non-print */ +#define FORM_T 2 /* telnet format effectors */ +#define FORM_C 3 /* carriage control (ASA) */ +#ifdef FTP_NAMES +char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" }; +#endif + +/* + * Structure codes + */ +#define STRU_F 1 /* file (no record structure) */ +#define STRU_R 2 /* record structure */ +#define STRU_P 3 /* page structure */ +#ifdef FTP_NAMES +char *strunames[] = {"0", "File", "Record", "Page" }; +#endif + +/* + * Mode types + */ +#define MODE_S 1 /* stream */ +#define MODE_B 2 /* block */ +#define MODE_C 3 /* compressed */ +#ifdef FTP_NAMES +char *modenames[] = {"0", "Stream", "Block", "Compressed" }; +#endif + +/* + * Record Tokens + */ +#define REC_ESC '\377' /* Record-mode Escape */ +#define REC_EOR '\001' /* Record-mode End-of-Record */ +#define REC_EOF '\002' /* Record-mode End-of-File */ + +/* + * Block Header + */ +#define BLK_EOR 0x80 /* Block is End-of-Record */ +#define BLK_EOF 0x40 /* Block is End-of-File */ +#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */ +#define BLK_RESTART 0x10 /* Block is Restart Marker */ + +#define BLK_BYTECOUNT 2 /* Bytes in this block */ + +#endif /* arpa/ftp.h */ diff --git a/include/arpa/inet.h b/include/arpa/inet.h new file mode 100644 index 0000000..02233d4 --- /dev/null +++ b/include/arpa/inet.h @@ -0,0 +1,108 @@ +/* Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H 1 + +#include +#include /* To define `struct in_addr'. */ + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +__BEGIN_DECLS + +/* Convert Internet host address from numbers-and-dots notation in CP + into binary data in network byte order. */ +extern in_addr_t inet_addr (__const char *__cp) __THROW; + +/* Return the local host address part of the Internet address in IN. */ +extern in_addr_t inet_lnaof (struct in_addr __in) __THROW; + +/* Make Internet host address in network byte order by combining the + network number NET with the local address HOST. */ +extern struct in_addr inet_makeaddr (in_addr_t __net, in_addr_t __host) + __THROW; + +/* Return network number part of the Internet address IN. */ +extern in_addr_t inet_netof (struct in_addr __in) __THROW; + +/* Extract the network number in network byte order from the address + in numbers-and-dots natation starting at CP. */ +extern in_addr_t inet_network (__const char *__cp) __THROW; + +/* Convert Internet number in IN to ASCII representation. The return value + is a pointer to an internal array containing the string. */ +extern char *inet_ntoa (struct in_addr __in) __THROW; +/* Recursion-safe flavor */ +extern char *inet_ntoa_r (struct in_addr __in, char *__buf) __THROW; + +/* Convert from presentation format of an Internet number in buffer + starting at CP to the binary network format and store result for + interface type AF in buffer starting at BUF. */ +extern int inet_pton (int __af, __const char *__restrict __cp, + void *__restrict __buf) __THROW; + +/* Convert a Internet address in binary network format for interface + type AF in buffer starting at CP to presentation form and place + result in buffer of length LEN astarting at BUF. */ +extern __const char *inet_ntop (int __af, __const void *__restrict __cp, + char *__restrict __buf, socklen_t __len) + __THROW; + + +/* The following functions are not part of XNS 5.2. */ +#ifdef __USE_MISC +/* Convert Internet host address from numbers-and-dots notation in CP + into binary data and store the result in the structure INP. */ +extern int inet_aton (__const char *__cp, struct in_addr *__inp) __THROW; + +/* Format a network number NET into presentation format and place result + in buffer starting at BUF with length of LEN bytes. */ +extern char *inet_neta (in_addr_t __net, char *__buf, size_t __len) __THROW; + +/* Convert network number for interface type AF in buffer starting at + CP to presentation format. The result will specifiy BITS bits of + the number. */ +extern char *inet_net_ntop (int __af, __const void *__cp, int __bits, + char *__buf, size_t __len) __THROW; + +/* Convert network number for interface type AF from presentation in + buffer starting at CP to network format and store result int + buffer starting at BUF of size LEN. */ +extern int inet_net_pton (int __af, __const char *__cp, + void *__buf, size_t __len) __THROW; + +/* Convert ASCII representation in hexadecimal form of the Internet + address to binary form and place result in buffer of length LEN + starting at BUF. */ +extern unsigned int inet_nsap_addr (__const char *__cp, + unsigned char *__buf, int __len) __THROW; + +/* Convert internet address in binary form in LEN bytes starting at CP + a presentation form and place result in BUF. */ +extern char *inet_nsap_ntoa (int __len, __const unsigned char *__cp, + char *__buf) __THROW; +#endif + +__END_DECLS + +#endif /* arpa/inet.h */ diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h new file mode 100644 index 0000000..496c8db --- /dev/null +++ b/include/arpa/nameser.h @@ -0,0 +1,557 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#define BIND_4_COMPAT + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not + * compare for equality; rather, use it to determine whether your libbind.a + * contains a new enough lib/nameser/ to support the feature you need. + */ + +#define __NAMESER 19991006 /* New interface version stamp. */ + +/* + * Define constants based on RFC 883, RFC 1034, RFC 1035 + */ +#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#define NS_MAXLABEL 63 /* maximum length of domain label */ +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */ +#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */ +#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */ +#define NS_INADDRSZ 4 /* IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ + +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /* Query: Question. */ + ns_s_zn = 0, /* Update: Zone. */ + ns_s_an = 1, /* Query: Answer. */ + ns_s_pr = 1, /* Update: Prerequisites. */ + ns_s_ns = 2, /* Query: Name servers. */ + ns_s_ud = 2, /* Update: Update. */ + ns_s_ar = 3, /* Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/* + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + const u_char *_msg, *_eom; + u_int16_t _id, _flags, _counts[ns_s_max]; + const u_char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const u_char *_ptr; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ +#define ns_msg_getflag(handle, flag) ( \ + ((handle)._flags & _ns_flagdata[flag].mask) \ + >> _ns_flagdata[flag].shift \ + ) +#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) + +/* + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char * rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#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) + +/* + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /* Question/Response. */ + ns_f_opcode, /* Operation code. */ + ns_f_aa, /* Authoritative Answer. */ + ns_f_tc, /* Truncation occurred. */ + ns_f_rd, /* Recursion Desired. */ + ns_f_ra, /* Recursion Available. */ + ns_f_z, /* MBZ. */ + ns_f_ad, /* Authentic Data (DNSSEC). */ + ns_f_cd, /* Checking Disabled (DNSSEC). */ + ns_f_rcode, /* Response code. */ + ns_f_max +} ns_flag; + +/* + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/* + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11, + /* The following are TSIG extended errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/* + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/* + * This structure is used for TSIG authenticated TCP messages + */ +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 + +/* + * Currently defined type values for resources and queries. + */ +typedef enum __ns_type { + ns_t_invalid = 0, /* Cookie. */ + ns_t_a = 1, /* Host address. */ + ns_t_ns = 2, /* Authoritative server. */ + ns_t_md = 3, /* Mail destination. */ + ns_t_mf = 4, /* Mail forwarder. */ + ns_t_cname = 5, /* Canonical name. */ + ns_t_soa = 6, /* Start of authority zone. */ + ns_t_mb = 7, /* Mailbox domain name. */ + ns_t_mg = 8, /* Mail group member. */ + ns_t_mr = 9, /* Mail rename name. */ + ns_t_null = 10, /* Null resource record. */ + ns_t_wks = 11, /* Well known service. */ + ns_t_ptr = 12, /* Domain name pointer. */ + ns_t_hinfo = 13, /* Host information. */ + ns_t_minfo = 14, /* Mailbox information. */ + ns_t_mx = 15, /* Mail routing information. */ + ns_t_txt = 16, /* Text strings. */ + ns_t_rp = 17, /* Responsible person. */ + ns_t_afsdb = 18, /* AFS cell database. */ + ns_t_x25 = 19, /* X_25 calling address. */ + ns_t_isdn = 20, /* ISDN calling address. */ + ns_t_rt = 21, /* Router. */ + ns_t_nsap = 22, /* NSAP address. */ + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /* Security signature. */ + ns_t_key = 25, /* Security key. */ + ns_t_px = 26, /* X.400 mail mapping. */ + ns_t_gpos = 27, /* Geographical position (withdrawn). */ + ns_t_aaaa = 28, /* Ip6 Address. */ + ns_t_loc = 29, /* Location Information. */ + ns_t_nxt = 30, /* Next domain (security). */ + ns_t_eid = 31, /* Endpoint identifier. */ + ns_t_nimloc = 32, /* Nimrod Locator. */ + ns_t_srv = 33, /* Server Selection. */ + ns_t_atma = 34, /* ATM Address */ + ns_t_naptr = 35, /* Naming Authority PoinTeR */ + ns_t_kx = 36, /* Key Exchange */ + ns_t_cert = 37, /* Certification record */ + ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_opt = 41, /* EDNS0 option (meta-RR) */ + ns_t_tsig = 250, /* Transaction signature. */ + ns_t_ixfr = 251, /* Incremental zone transfer. */ + ns_t_axfr = 252, /* Transfer zone of authority. */ + ns_t_mailb = 253, /* Transfer mailbox records. */ + ns_t_maila = 254, /* Transfer mail agent records. */ + ns_t_any = 255, /* Wildcard match. */ + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_max = 65536 +} ns_type; + +/* Exclusively a QTYPE? (not also an RTYPE) */ +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ +#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) + +/* + * Values for class field + */ +typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ + ns_c_in = 1, /* Internet. */ + ns_c_2 = 2, /* unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* DNSSEC constants. */ + +typedef enum __ns_key_types { + ns_kt_rsa = 1, /* key type RSA/MD5 */ + ns_kt_dh = 2, /* Diffie Hellman */ + ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ + ns_kt_private = 254 /* Private key type starts with OID */ +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /* PKIX (X.509v3) */ + cert_t_spki = 2, /* SPKI */ + cert_t_pgp = 3, /* PGP */ + cert_t_url = 253, /* URL private type */ + cert_t_oid = 254 /* OID private type */ +} ns_cert_types; + +/* Flags field of the KEY RR rdata. */ +#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ +#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ +#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ +#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ +#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ +#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ +#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ +#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ +#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ +#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ +#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ +#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ +#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ +#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ +#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ +#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ +#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ +#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 /* no bits defined here */ + +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define NS_ALG_MD5RSA 1 /* MD5 with RSA */ +#define NS_ALG_DH 2 /* Diffie Hellman KEY */ +#define NS_ALG_DSA 3 /* DSA KEY */ +#define NS_ALG_DSS NS_ALG_DSA +#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ +#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ + +/* Protocol values */ +/* value 0 is reserved */ +#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 + +/* Signatures */ +#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ +#define NS_MD5RSA_MAX_BITS 2552 + /* Total of binary mod and exp */ +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) + /* Max length of text sig block */ +#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 + +/* Offsets into SIG record rdata to find various values */ +#define NS_SIG_TYPE 0 /* Type flags */ +#define NS_SIG_ALG 2 /* Algorithm */ +#define NS_SIG_LABELS 3 /* How many labels in name */ +#define NS_SIG_OTTL 4 /* Original TTL */ +#define NS_SIG_EXPIR 8 /* Expiration time */ +#define NS_SIG_SIGNED 12 /* Signature time */ +#define NS_SIG_FOOT 16 /* Key footprint */ +#define NS_SIG_SIGNER 18 /* Domain name of who signed it */ + +/* How RR types are represented as bit-flags in NXT records */ +#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 + +/* + * Inline versions of get/put short/long. Pointer is advanced. + */ +#define NS_GET16(s, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_GET32(l, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_PUT16(s, cp) do { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_PUT32(l, cp) do { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_char *t_cp = (u_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) + +/* + * ANSI C identifier hiding for bind's lib/nameser. + */ +#define ns_get16 __ns_get16 +#define ns_get32 __ns_get32 +#define ns_put16 __ns_put16 +#define ns_put32 __ns_put32 +#define ns_initparse __ns_initparse +#define ns_skiprr __ns_skiprr +#define ns_parserr __ns_parserr +#define ns_sprintrr __ns_sprintrr +#define ns_sprintrrf __ns_sprintrrf +#define ns_format_ttl __ns_format_ttl +#define ns_parse_ttl __ns_parse_ttl +#define ns_datetosecs __ns_datetosecs +#define ns_name_ntol __ns_name_ntol +#define ns_name_ntop __ns_name_ntop +#define ns_name_pton __ns_name_pton +#define ns_name_unpack __ns_name_unpack +#define ns_name_pack __ns_name_pack +#define ns_name_compress __ns_name_compress +#define ns_name_uncompress __ns_name_uncompress +#define ns_name_skip __ns_name_skip +#define ns_name_rollback __ns_name_rollback +#define ns_sign __ns_sign +#define ns_sign_tcp __ns_sign_tcp +#define ns_sign_tcp_init __ns_sign_tcp_init +#define ns_find_tsig __ns_find_tsig +#define ns_verify __ns_verify +#define ns_verify_tcp __ns_verify_tcp +#define ns_verify_tcp_init __ns_verify_tcp_init +#define ns_samedomain __ns_samedomain +#define ns_subdomain __ns_subdomain +#define ns_makecanon __ns_makecanon +#define ns_samename __ns_samename + +__BEGIN_DECLS +u_int ns_get16 (const u_char *) __THROW; +u_long ns_get32 (const u_char *) __THROW; +void ns_put16 (u_int, u_char *) __THROW; +void ns_put32 (u_long, u_char *) __THROW; +int ns_initparse (const u_char *, int, ns_msg *) __THROW; +int ns_skiprr (const u_char *, const u_char *, ns_sect, int) + __THROW; +int ns_parserr (ns_msg *, ns_sect, int, ns_rr *) __THROW; +int ns_sprintrr (const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t) + __THROW; +int ns_sprintrrf (const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t) __THROW; +int ns_format_ttl (u_long, char *, size_t) __THROW; +int ns_parse_ttl (const char *, u_long *) __THROW; +u_int32_t ns_datetosecs (const char *cp, int *errp) __THROW; +int ns_name_ntol (const u_char *, u_char *, size_t) __THROW; +int ns_name_ntop (const u_char *, char *, size_t) __THROW; +int ns_name_pton (const char *, u_char *, size_t) __THROW; +int ns_name_unpack (const u_char *, const u_char *, + const u_char *, u_char *, size_t) __THROW; +int ns_name_pack (const u_char *, u_char *, int, + const u_char **, const u_char **) __THROW; +int ns_name_uncompress (const u_char *, const u_char *, + const u_char *, char *, size_t) __THROW; +int ns_name_compress (const char *, u_char *, size_t, + const u_char **, const u_char **) __THROW; +int ns_name_skip (const u_char **, const u_char *) __THROW; +void ns_name_rollback (const u_char *, const u_char **, + const u_char **) __THROW; +int ns_sign (u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t) __THROW; +int ns_sign_tcp (u_char *, int *, int, int, + ns_tcp_tsig_state *, int) __THROW; +int ns_sign_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +u_char *ns_find_tsig (u_char *, u_char *) __THROW; +int ns_verify (u_char *, int *, void *, const u_char *, int, + u_char *, int *, time_t *, int) __THROW; +int ns_verify_tcp (u_char *, int *, ns_tcp_tsig_state *, int) + __THROW; +int ns_verify_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +int ns_samedomain (const char *, const char *) __THROW; +int ns_subdomain (const char *, const char *) __THROW; +int ns_makecanon (const char *, char *, size_t) __THROW; +int ns_samename (const char *, const char *) __THROW; +__END_DECLS + +#ifdef BIND_4_COMPAT +#include +#endif + +#endif /* !_ARPA_NAMESER_H_ */ diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h new file mode 100644 index 0000000..e3ef864 --- /dev/null +++ b/include/arpa/nameser_compat.h @@ -0,0 +1,183 @@ +/* Copyright (c) 1983, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /* (DEAD) interface version stamp. */ + +#include + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} 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 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 BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#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_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 +/* BIND_UPDATE */ +#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 /* _ARPA_NAMESER_COMPAT_ */ diff --git a/include/arpa/telnet.h b/include/arpa/telnet.h new file mode 100644 index 0000000..3774c89 --- /dev/null +++ b/include/arpa/telnet.h @@ -0,0 +1,316 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnet.h 8.2 (Berkeley) 12/15/93 + */ + +#ifndef _ARPA_TELNET_H +#define _ARPA_TELNET_H 1 + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, +}; +#else +extern char *telcmds[]; +#endif + +#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] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascii character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 /* X Display Location */ +#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 /* Encryption option */ +#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + + +#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 + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ +#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ +#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ +#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ + +#define LFLOW_OFF 0 /* Disable remote flow control */ +#define LFLOW_ON 1 /* Enable remote flow control */ +#define LFLOW_RESTART_ANY 2 /* Restart output on any char */ +#define LFLOW_RESTART_XON 3 /* Restart output only on XON */ + +/* + * LINEMODE suboptions + */ + +#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 + +/* Not part of protocol, but needed to simplify things... */ +#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 + +/* + * For backwards compatibility, we define SLC_NAMES to be the + * list of names if SLC_NAMES is not defined. + */ +#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 + +/* + * AUTHENTICATION suboptions + */ + +/* + * Who is authenticating who ... + */ +#define AUTH_WHO_CLIENT 0 /* Client authenticating server */ +#define AUTH_WHO_SERVER 1 /* Server authenticating client */ +#define AUTH_WHO_MASK 1 + +/* + * amount of authentication done + */ +#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] + +/* + * ENCRYPTion suboptions + */ +#define ENCRYPT_IS 0 /* I pick encryption type ... */ +#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ +#define ENCRYPT_REPLY 2 /* Initial setup response */ +#define ENCRYPT_START 3 /* Am starting to send encrypted */ +#define ENCRYPT_END 4 /* Am ending encrypted */ +#define ENCRYPT_REQSTART 5 /* Request you start encrypting */ +#define ENCRYPT_REQEND 6 /* Request you send encrypting */ +#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 /* arpa/telnet.h */ diff --git a/include/arpa/tftp.h b/include/arpa/tftp.h new file mode 100644 index 0000000..21b0559 --- /dev/null +++ b/include/arpa/tftp.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tftp.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ARPA_TFTP_H +#define _ARPA_TFTP_H 1 + +/* + * Trivial File Transfer Protocol (IEN-133) + */ +#define SEGSIZE 512 /* data segment size */ + +/* + * Packet types. + */ +#define RRQ 01 /* read request */ +#define WRQ 02 /* write request */ +#define DATA 03 /* data packet */ +#define ACK 04 /* acknowledgement */ +#define ERROR 05 /* error code */ + +struct tftphdr { + short th_opcode; /* packet type */ + union { + unsigned short tu_block; /* block # */ + short tu_code; /* error code */ + char tu_stuff[1]; /* request packet stuff */ + } __attribute__ ((__packed__)) th_u; + char th_data[1]; /* data or error string */ +} __attribute__ ((__packed__)); + +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data + +/* + * Error codes. + */ +#define EUNDEF 0 /* not defined */ +#define ENOTFOUND 1 /* file not found */ +#define EACCESS 2 /* access violation */ +#define ENOSPACE 3 /* disk full or allocation exceeded */ +#define EBADOP 4 /* illegal TFTP operation */ +#define EBADID 5 /* unknown transfer ID */ +#define EEXISTS 6 /* file already exists */ +#define ENOUSER 7 /* no such user */ + +#endif /* arpa/tftp.h */ diff --git a/include/assert.h b/include/assert.h new file mode 100644 index 0000000..9b9d1b7 --- /dev/null +++ b/include/assert.h @@ -0,0 +1,78 @@ +/* Copyright (C) 1991,1992,1994-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.2 Diagnostics + */ + +#ifdef _ASSERT_H + +# undef _ASSERT_H +# undef assert +# undef __ASSERT_VOID_CAST + +#endif /* assert.h */ + +#define _ASSERT_H 1 +#include + +#if defined __cplusplus && __GNUC_PREREQ (2,95) +# define __ASSERT_VOID_CAST static_cast +#else +# define __ASSERT_VOID_CAST (void) +#endif + +/* void assert (int expression); + + If NDEBUG is defined, do nothing. + If not, and EXPRESSION is zero, print an error message and abort. */ + +#ifdef NDEBUG + +# define assert(expr) (__ASSERT_VOID_CAST (0)) + +#else /* Not NDEBUG. */ + +__BEGIN_DECLS + +/* This prints an "Assertion failed" message and aborts. */ +extern void __assert __P((const char *, const char *, int, const char *)); + +__END_DECLS + +# define assert(expr) \ + (__ASSERT_VOID_CAST ((expr) ? 0 : \ + (__assert (__STRING(expr), __FILE__, __LINE__, \ + __ASSERT_FUNCTION), 0))) + +/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__' + which contains the name of the function currently being defined. + This is broken in G++ before version 2.6. + C9x has a similar variable called __func__, but prefer the GCC one since + it demangles C++ function names. */ +# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4) +# define __ASSERT_FUNCTION __PRETTY_FUNCTION__ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __ASSERT_FUNCTION __func__ +# else +# define __ASSERT_FUNCTION ((__const char *) 0) +# endif +# endif + +#endif /* NDEBUG. */ diff --git a/include/atomic.h b/include/atomic.h new file mode 100644 index 0000000..aff4120 --- /dev/null +++ b/include/atomic.h @@ -0,0 +1,261 @@ +/* Internal macros for atomic operations for GNU C Library. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ATOMIC_H +#define _ATOMIC_H 1 + +#include + +#include + +/* Wrapper macros to call pre_NN_post (mem, ...) where NN is the + bit width of *MEM. The calling macro puts parens around MEM + and following args. */ +#define __atomic_val_bysize(pre, post, mem, ...) \ + ({ \ + __typeof (*mem) __result; \ + if (sizeof (*mem) == 1) \ + __result = pre##_8_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 2) \ + __result = pre##_16_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 4) \ + __result = pre##_32_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 8) \ + __result = pre##_64_##post (mem, __VA_ARGS__); \ + else \ + abort (); \ + __result; \ + }) +#define __atomic_bool_bysize(pre, post, mem, ...) \ + ({ \ + int __result; \ + if (sizeof (*mem) == 1) \ + __result = pre##_8_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 2) \ + __result = pre##_16_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 4) \ + __result = pre##_32_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 8) \ + __result = pre##_64_##post (mem, __VA_ARGS__); \ + else \ + abort (); \ + __result; \ + }) + + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return the old *MEM value. */ +#if !defined atomic_compare_and_exchange_val_acq \ + && defined __arch_compare_and_exchange_val_32_acq +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \ + mem, newval, oldval) +#endif + + +#ifndef atomic_compare_and_exchange_val_rel +# define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_val_acq (mem, newval, oldval) +#endif + + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return zero if *MEM was changed or non-zero if no exchange happened. */ +#ifndef atomic_compare_and_exchange_bool_acq +# ifdef __arch_compare_and_exchange_bool_32_acq +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \ + mem, newval, oldval) +# else +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ /* Cannot use __oldval here, because macros later in this file might \ + call this macro with __oldval argument. */ \ + __typeof (oldval) __old = (oldval); \ + atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \ + }) +# endif +#endif + + +#ifndef atomic_compare_and_exchange_bool_rel +# define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_bool_acq (mem, newval, oldval) +#endif + + +/* Store NEWVALUE in *MEM and return the old value. */ +#ifndef atomic_exchange_acq +# define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*(mem)) __oldval; \ + __typeof (mem) __memp = (mem); \ + __typeof (*(mem)) __value = (newvalue); \ + \ + do \ + __oldval = (*__memp); \ + while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ + __value, \ + __oldval),\ + 0)); \ + \ + __oldval; }) +#endif + +#ifndef atomic_exchange_rel +# define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue) +#endif + + +/* Add VALUE to *MEM and return the old value of *MEM. */ +#ifndef atomic_exchange_and_add +# define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*(mem)) __oldval; \ + __typeof (mem) __memp = (mem); \ + __typeof (*(mem)) __value = (value); \ + \ + do \ + __oldval = (*__memp); \ + while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ + __oldval \ + + __value,\ + __oldval),\ + 0)); \ + \ + __oldval; }) +#endif + + +#ifndef atomic_add +# define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value)) +#endif + + +#ifndef atomic_increment +# define atomic_increment(mem) atomic_add ((mem), 1) +#endif + + +#ifndef atomic_increment_val +# define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1) +#endif + + +/* Add one to *MEM and return true iff it's now zero. */ +#ifndef atomic_increment_and_test +# define atomic_increment_and_test(mem) \ + (atomic_exchange_and_add ((mem), 1) + 1 == 0) +#endif + + +#ifndef atomic_decrement +# define atomic_decrement(mem) atomic_add ((mem), -1) +#endif + + +#ifndef atomic_decrement_val +# define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1) +#endif + + +/* Subtract 1 from *MEM and return true iff it's now zero. */ +#ifndef atomic_decrement_and_test +# define atomic_decrement_and_test(mem) \ + (atomic_exchange_and_add ((mem), -1) == 1) +#endif + + +/* Decrement *MEM if it is > 0, and return the old value. */ +#ifndef atomic_decrement_if_positive +# define atomic_decrement_if_positive(mem) \ + ({ __typeof (*(mem)) __oldval; \ + __typeof (mem) __memp = (mem); \ + \ + do \ + { \ + __oldval = *__memp; \ + if (__builtin_expect (__oldval <= 0, 0)) \ + break; \ + } \ + while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ + __oldval \ + - 1, \ + __oldval),\ + 0));\ + __oldval; }) +#endif + + +#ifndef atomic_add_negative +# define atomic_add_negative(mem, value) \ + ({ __typeof (value) __aan_value = (value); \ + atomic_exchange_and_add (mem, __aan_value) < -__aan_value; }) +#endif + + +#ifndef atomic_add_zero +# define atomic_add_zero(mem, value) \ + ({ __typeof (value) __aaz_value = (value); \ + atomic_exchange_and_add (mem, __aaz_value) == -__aaz_value; }) +#endif + + +#ifndef atomic_bit_set +# define atomic_bit_set(mem, bit) \ + (void) atomic_bit_test_set(mem, bit) +#endif + + +#ifndef atomic_bit_test_set +# define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*(mem)) __oldval; \ + __typeof (mem) __memp = (mem); \ + __typeof (*(mem)) __mask = ((__typeof (*(mem))) 1 << (bit)); \ + \ + do \ + __oldval = (*__memp); \ + while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \ + __oldval \ + | __mask, \ + __oldval),\ + 0)); \ + \ + __oldval & __mask; }) +#endif + + +#ifndef atomic_full_barrier +# define atomic_full_barrier() __asm__ ("" ::: "memory") +#endif + + +#ifndef atomic_read_barrier +# define atomic_read_barrier() atomic_full_barrier () +#endif + + +#ifndef atomic_write_barrier +# define atomic_write_barrier() atomic_full_barrier () +#endif + + +#ifndef atomic_delay +# define atomic_delay() do { /* nothing */ } while (0) +#endif + +#endif /* atomic.h */ diff --git a/include/byteswap.h b/include/byteswap.h new file mode 100644 index 0000000..b61d4dd --- /dev/null +++ b/include/byteswap.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H 1 + +/* Get the machine specific, optimized definitions. */ +#include + + +/* The following definitions must all be macros since otherwise some + of the possible optimizations are not possible. */ + +/* Return a value with all bytes in the 16 bit argument swapped. */ +#define bswap_16(x) __bswap_16 (x) + +/* Return a value with all bytes in the 32 bit argument swapped. */ +#define bswap_32(x) __bswap_32 (x) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Return a value with all bytes in the 64 bit argument swapped. */ +# define bswap_64(x) __bswap_64 (x) +#endif + +#endif /* byteswap.h */ diff --git a/include/complex.h b/include/complex.h new file mode 100644 index 0000000..94fb6ea --- /dev/null +++ b/include/complex.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.3 Complex arithmetic + */ + +#ifndef _COMPLEX_H +#define _COMPLEX_H 1 + +#include + +/* Get general and ISO C99 specific information. */ +#include + +__BEGIN_DECLS + +/* We might need to add support for more compilers here. But since ISO + C99 is out hopefully all maintained compilers will soon provide the data + types `float complex' and `double complex'. */ +#if __GNUC_PREREQ (2, 7) && !__GNUC_PREREQ (2, 97) +# define _Complex __complex__ +#endif + +#define complex _Complex + +/* Narrowest imaginary unit. This depends on the floating-point + evaluation method. + XXX This probably has to go into a gcc related file. */ +#define _Complex_I (__extension__ 1.0iF) + +/* Another more descriptive name is `I'. + XXX Once we have the imaginary support switch this to _Imaginary_I. */ +#undef I +#define I _Complex_I + +/* The file contains the prototypes for all the + actual math functions. These macros are used for those prototypes, + so we can easily declare each function as both `name' and `__name', + and can declare the float versions `namef' and `__namef'. */ + +#define __MATHCALL(function, args) \ + __MATHDECL (_Mdouble_complex_,function, args) +#define __MATHDECL(type, function, args) \ + __MATHDECL_1(type, function, args); \ + __MATHDECL_1(type, __CONCAT(__,function), args) +#define __MATHDECL_1(type, function, args) \ + extern type __MATH_PRECNAME(function) args __THROW + +#define _Mdouble_ double +#define __MATH_PRECNAME(name) name +#include +#undef _Mdouble_ +#undef __MATH_PRECNAME + +/* Now the float versions. */ +#ifndef _Mfloat_ +# define _Mfloat_ float +#endif +#define _Mdouble_ _Mfloat_ +#ifdef __STDC__ +# define __MATH_PRECNAME(name) name##f +#else +# define __MATH_PRECNAME(name) name/**/f +#endif +#include +#undef _Mdouble_ +#undef __MATH_PRECNAME + +/* And the long double versions. It is non-critical to define them + here unconditionally since `long double' is required in ISO C99. */ +#if __STDC__ - 0 || __GNUC__ - 0 && defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# ifndef _Mlong_double_ +# define _Mlong_double_ long double +# endif +# define _Mdouble_ _Mlong_double_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name) name##l +# else +# define __MATH_PRECNAME(name) name/**/l +# endif +# include +#endif +#undef _Mdouble_ +#undef __MATH_PRECNAME +#undef __MATHDECL_1 +#undef __MATHDECL +#undef __MATHCALL + +__END_DECLS + +#endif /* complex.h */ diff --git a/include/cpio.h b/include/cpio.h new file mode 100644 index 0000000..fae3275 --- /dev/null +++ b/include/cpio.h @@ -0,0 +1,74 @@ +/* Extended cpio format from POSIX.1. + This file is part of the GNU C Library. + Copyright (C) 1992, 1998 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU cpio. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _CPIO_H +#define _CPIO_H 1 + +/* A cpio archive consists of a sequence of files. + Each file has a 76 byte header, + a variable length, NUL terminated filename, + and variable length file data. + A header for a filename "TRAILER!!!" indicates the end of the archive. */ + +/* All the fields in the header are ISO 646 (approximately ASCII) strings + of octal numbers, left padded, not NUL terminated. + + Field Name Length in Bytes Notes + c_magic 6 must be "070707" + c_dev 6 + c_ino 6 + c_mode 6 see below for value + c_uid 6 + c_gid 6 + c_nlink 6 + c_rdev 6 only valid for chr and blk special files + c_mtime 11 + c_namesize 6 count includes terminating NUL in pathname + c_filesize 11 must be 0 for FIFOs and directories */ + +/* Value for the field `c_magic'. */ +#define MAGIC "070707" + +/* Values for c_mode, OR'd together: */ + +#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 /* cpio.h */ diff --git a/include/crypt.h b/include/crypt.h new file mode 100644 index 0000000..f62a030 --- /dev/null +++ b/include/crypt.h @@ -0,0 +1,42 @@ +/* + * crypt(3) implementation for uClibc + * + * The uClibc 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _CRYPT_H +#define _CRYPT_H 1 + +#include + +__BEGIN_DECLS + +/* Encrypt characters from KEY using salt to perturb the encryption method. + * If salt begins with "$1$", MD5 hashing is used instead of DES. */ +extern char *crypt (const char *__key, const char *__salt) + __THROW __nonnull ((1, 2)); + +/* Setup DES tables according KEY. */ +extern void setkey (const char *__key) __THROW __nonnull ((1)); + +/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt + block in place. */ +extern void encrypt (char *__block, int __edflag) __THROW __nonnull ((1)); + +__END_DECLS + +#endif /* crypt.h */ diff --git a/include/ctype.h b/include/ctype.h new file mode 100644 index 0000000..184b47b --- /dev/null +++ b/include/ctype.h @@ -0,0 +1,383 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2001,02 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard 7.4: Character handling + */ + +#ifndef _CTYPE_H +#define _CTYPE_H 1 + +#include +#include + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +__BEGIN_DECLS + +#ifndef _ISbit +/* These are all the characteristics of characters. + If there get to be more than 16 distinct characteristics, + __ctype_mask_t will need to be adjusted. */ + +# define _ISbit(bit) (1 << (bit)) + +enum +{ + _ISupper = _ISbit (0), /* UPPERCASE. */ + _ISlower = _ISbit (1), /* lowercase. */ + _ISalpha = _ISbit (2), /* Alphabetic. */ + _ISdigit = _ISbit (3), /* Numeric. */ + _ISxdigit = _ISbit (4), /* Hexadecimal numeric. */ + _ISspace = _ISbit (5), /* Whitespace. */ + _ISprint = _ISbit (6), /* Printing. */ + _ISgraph = _ISbit (7), /* Graphical. */ + _ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */ + _IScntrl = _ISbit (9), /* Control character. */ + _ISpunct = _ISbit (10), /* Punctuation. */ + _ISalnum = _ISbit (11) /* Alphanumeric. */ +}; +#else +#error _ISbit already defined! +#endif /* ! _ISbit */ + +#include + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ +# define __UCLIBC_CTYPE_IN_TO_DOMAIN(c) (((unsigned int)((c) + 128)) < 384) + +#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */ +# define __UCLIBC_CTYPE_IN_TO_DOMAIN(c) (((unsigned int)(c)) < 256) + +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +/* In the thread-specific locale model (see `uselocale' in ) + we cannot use global variables for these as was done in the past. + Instead, the following accessor functions return the address of + each variable, which is local to the current thread if multithreaded. + + These point into arrays of 384, so they can be indexed by any `unsigned + char' value [0,255]; by EOF (-1); or by any `signed char' value + [-128,-1). ISO C requires that the ctype functions work for `unsigned + char' values and for EOF; we also support negative `signed char' values + for broken old programs. The case conversion arrays are of `int's + rather than `unsigned char's because tolower (EOF) must be EOF, which + doesn't fit into an `unsigned char'. But today more important is that + the arrays are also used for multi-byte character sets. */ + +/* uClibc differences: + * + * When __UCLIBC_HAS_CTYPE_SIGNED is defined, + * + * The upper and lower mapping arrays are type int16_t, so that + * they may store all char values plus EOF. The glibc reasoning + * given above for these being type int is questionable, as the + * ctype mapping functions map from the set of (unsigned) char + * and EOF back into the set. They have no awareness of multi-byte + * or wide characters. + * + * Otherwise, + * + * The ctype array is defined for -1..255. + * The upper and lower mapping arrays are defined for 0..255. + * The upper and lower mapping arrays are type unsigned char. + */ + +/* Pointers to the default C-locale data. */ +extern const __ctype_mask_t *__C_ctype_b; +extern const __ctype_touplow_t *__C_ctype_toupper; +extern const __ctype_touplow_t *__C_ctype_tolower; + +#ifdef __UCLIBC_HAS_XLOCALE__ + +extern __const __ctype_mask_t **__ctype_b_loc (void) + __attribute__ ((__const)); +extern __const __ctype_touplow_t **__ctype_tolower_loc (void) + __attribute__ ((__const)); +extern __const __ctype_touplow_t **__ctype_toupper_loc (void) + __attribute__ ((__const)); + +#define __UCLIBC_CTYPE_B (*__ctype_b_loc()) +#define __UCLIBC_CTYPE_TOLOWER (*__ctype_tolower_loc()) +#define __UCLIBC_CTYPE_TOUPPER (*__ctype_toupper_loc()) + +#else /* __UCLIBC_HAS_XLOCALE__ */ + +/* Pointers to the current global locale data in use. */ +extern const __ctype_mask_t *__ctype_b; +extern const __ctype_touplow_t *__ctype_toupper; +extern const __ctype_touplow_t *__ctype_tolower; + +#define __UCLIBC_CTYPE_B (__ctype_b) +#define __UCLIBC_CTYPE_TOLOWER (__ctype_tolower) +#define __UCLIBC_CTYPE_TOUPPER (__ctype_toupper) + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#define __isctype(c, type) \ + ((__UCLIBC_CTYPE_B)[(int) (c)] & (__ctype_mask_t) type) + +#define __isascii(c) (((c) & ~0x7f) == 0) /* If C is a 7 bit value. */ +#define __toascii(c) ((c) & 0x7f) /* Mask off high bits. */ + +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) +/* isdigit() is really locale-invariant, so provide some small fast macros. + * These are uClibc-specific. */ +#define __isdigit_char(C) (((unsigned char)((C) - '0')) <= 9) +#define __isdigit_int(C) (((unsigned int)((C) - '0')) <= 9) +#endif + +#define __exctype(name) extern int name (int) __THROW + +__BEGIN_NAMESPACE_STD + +/* The following names are all functions: + int isCHARACTERISTIC(int c); + which return nonzero iff C has CHARACTERISTIC. + For the meaning of the characteristic names, see the `enum' above. */ +__exctype (isalnum); +__exctype (isalpha); +__exctype (iscntrl); +__exctype (isdigit); +__exctype (islower); +__exctype (isgraph); +__exctype (isprint); +__exctype (ispunct); +__exctype (isspace); +__exctype (isupper); +__exctype (isxdigit); + + +/* Return the lowercase version of C. */ +extern int tolower (int __c) __THROW; + +/* Return the uppercase version of C. */ +extern int toupper (int __c) __THROW; + +__END_NAMESPACE_STD + + +/* ISO C99 introduced one new function. */ +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +__exctype (isblank); + +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_GNU +/* Test C for a set of character classes according to MASK. */ +extern int isctype (int __c, int __mask) __THROW; +#endif + +#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN + +/* Return nonzero iff C is in the ASCII set + (i.e., is no more than 7 bits wide). */ +extern int isascii (int __c) __THROW; + +/* Return the part of C that is in the ASCII set + (i.e., the low-order 7 bits of C). */ +extern int toascii (int __c) __THROW; + +/* These are the same as `toupper' and `tolower' except that they do not + check the argument for being in the range of a `char'. */ +__exctype (_toupper); +__exctype (_tolower); +#endif /* Use SVID or use misc. */ + +/* This code is needed for the optimized mapping functions. */ +#define __tobody(c, f, a, args) \ + (__extension__ \ + ({ int __res; \ + if (sizeof (c) > 1) \ + { \ + if (__builtin_constant_p (c)) \ + { \ + int __c = (c); \ + __res = __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (a)[__c] : __c; \ + } \ + else \ + __res = f args; \ + } \ + else \ + __res = (a)[(int) (c)]; \ + __res; })) + +#if !defined __NO_CTYPE && !defined __cplusplus +# define isalnum(c) __isctype((c), _ISalnum) +# define isalpha(c) __isctype((c), _ISalpha) +# define iscntrl(c) __isctype((c), _IScntrl) +# define isdigit(c) __isctype((c), _ISdigit) +# define islower(c) __isctype((c), _ISlower) +# define isgraph(c) __isctype((c), _ISgraph) +# define isprint(c) __isctype((c), _ISprint) +# define ispunct(c) __isctype((c), _ISpunct) +# define isspace(c) __isctype((c), _ISspace) +# define isupper(c) __isctype((c), _ISupper) +# define isxdigit(c) __isctype((c), _ISxdigit) + +# ifdef __USE_ISOC99 +# define isblank(c) __isctype((c), _ISblank) +# endif + +# ifdef __USE_EXTERN_INLINES +__extern_inline int +__NTH (tolower (int __c)) +{ + return __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (__UCLIBC_CTYPE_TOLOWER)[__c] : __c; +} + +__extern_inline int +__NTH (toupper (int __c)) +{ + return __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (__UCLIBC_CTYPE_TOUPPER)[__c] : __c; +} +# endif + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define tolower(c) __tobody (c, tolower, __UCLIBC_CTYPE_TOLOWER, (c)) +# define toupper(c) __tobody (c, toupper, __UCLIBC_CTYPE_TOUPPER, (c)) +# endif /* Optimizing gcc */ + +# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +# define isascii(c) __isascii (c) +# define toascii(c) __toascii (c) + +# define _tolower(c) ((int) (__UCLIBC_CTYPE_TOLOWER)[(int) (c)]) +# define _toupper(c) ((int) (__UCLIBC_CTYPE_TOUPPER)[(int) (c)]) +# endif + +#endif /* Not __NO_CTYPE. */ + + +#if defined(__USE_GNU) && defined(__UCLIBC_HAS_XLOCALE__) +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* These definitions are similar to the ones above but all functions + take as an argument a handle for the locale which shall be used. */ +# define __isctype_l(c, type, locale) \ + ((locale)->__ctype_b[(int) (c)] & (__ctype_mask_t) type) + +# define __exctype_l(name) \ + extern int name (int, __locale_t) __THROW + +/* The following names are all functions: + int isCHARACTERISTIC(int c, locale_t *locale); + which return nonzero iff C has CHARACTERISTIC. + For the meaning of the characteristic names, see the `enum' above. */ +__exctype_l (isalnum_l); +__exctype_l (isalpha_l); +__exctype_l (iscntrl_l); +__exctype_l (isdigit_l); +__exctype_l (islower_l); +__exctype_l (isgraph_l); +__exctype_l (isprint_l); +__exctype_l (ispunct_l); +__exctype_l (isspace_l); +__exctype_l (isupper_l); +__exctype_l (isxdigit_l); + +__exctype_l (isblank_l); + + +/* Return the lowercase version of C in locale L. */ +extern int __tolower_l (int __c, __locale_t __l) __THROW; +extern int tolower_l (int __c, __locale_t __l) __THROW; + +/* Return the uppercase version of C. */ +extern int __toupper_l (int __c, __locale_t __l) __THROW; +extern int toupper_l (int __c, __locale_t __l) __THROW; + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define __tolower_l(c, locale) \ + __tobody (c, __tolower_l, (locale)->__ctype_tolower, (c, locale)) +# define __toupper_l(c, locale) \ + __tobody (c, __toupper_l, (locale)->__ctype_toupper, (c, locale)) +# define tolower_l(c, locale) __tolower_l ((c), (locale)) +# define toupper_l(c, locale) __toupper_l ((c), (locale)) +# endif /* Optimizing gcc */ + + +# ifndef __NO_CTYPE +# define __isalnum_l(c,l) __isctype_l((c), _ISalnum, (l)) +# define __isalpha_l(c,l) __isctype_l((c), _ISalpha, (l)) +# define __iscntrl_l(c,l) __isctype_l((c), _IScntrl, (l)) +# define __isdigit_l(c,l) __isctype_l((c), _ISdigit, (l)) +# define __islower_l(c,l) __isctype_l((c), _ISlower, (l)) +# define __isgraph_l(c,l) __isctype_l((c), _ISgraph, (l)) +# define __isprint_l(c,l) __isctype_l((c), _ISprint, (l)) +# define __ispunct_l(c,l) __isctype_l((c), _ISpunct, (l)) +# define __isspace_l(c,l) __isctype_l((c), _ISspace, (l)) +# define __isupper_l(c,l) __isctype_l((c), _ISupper, (l)) +# define __isxdigit_l(c,l) __isctype_l((c), _ISxdigit, (l)) + +# define __isblank_l(c,l) __isctype_l((c), _ISblank, (l)) + +# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +# define __isascii_l(c,l) ((l), __isascii (c)) +# define __toascii_l(c,l) ((l), __toascii (c)) +# endif + +# define isalnum_l(c,l) __isalnum_l ((c), (l)) +# define isalpha_l(c,l) __isalpha_l ((c), (l)) +# define iscntrl_l(c,l) __iscntrl_l ((c), (l)) +# define isdigit_l(c,l) __isdigit_l ((c), (l)) +# define islower_l(c,l) __islower_l ((c), (l)) +# define isgraph_l(c,l) __isgraph_l ((c), (l)) +# define isprint_l(c,l) __isprint_l ((c), (l)) +# define ispunct_l(c,l) __ispunct_l ((c), (l)) +# define isspace_l(c,l) __isspace_l ((c), (l)) +# define isupper_l(c,l) __isupper_l ((c), (l)) +# define isxdigit_l(c,l) __isxdigit_l ((c), (l)) + +# define isblank_l(c,l) __isblank_l ((c), (l)) + +# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +# define isascii_l(c,l) __isascii_l ((c), (l)) +# define toascii_l(c,l) __toascii_l ((c), (l)) +# endif + +# endif /* Not __NO_CTYPE. */ + +#endif /* Use GNU. */ + +__END_DECLS + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#include + +#endif + +#endif /* ctype.h */ diff --git a/include/dirent.h b/include/dirent.h new file mode 100644 index 0000000..565a94d --- /dev/null +++ b/include/dirent.h @@ -0,0 +1,293 @@ +/* Copyright (C) 1991-2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.1.2 Directory Operations + */ + +#ifndef _DIRENT_H +#define _DIRENT_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifdef __USE_XOPEN +# ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +# endif +# if defined __USE_LARGEFILE64 && !defined __ino64_t_defined +typedef __ino64_t ino64_t; +# define __ino64_t_defined +# endif +#endif + +/* This file defines `struct dirent'. + + It defines the macro `_DIRENT_HAVE_D_NAMLEN' iff there is a `d_namlen' + member that gives the length of `d_name'. + + It defines the macro `_DIRENT_HAVE_D_RECLEN' iff there is a `d_reclen' + member that gives the size of the entire directory entry. + + It defines the macro `_DIRENT_HAVE_D_OFF' iff there is a `d_off' + member that gives the file offset of the next directory entry. + + It defines the macro `_DIRENT_HAVE_D_TYPE' iff there is a `d_type' + member that gives the type of the file. + */ + +#include + +#if (defined __USE_BSD || defined __USE_MISC) && !defined d_fileno +# define d_ino d_fileno /* Backward compatibility. */ +#endif + +/* These macros extract size information from a `struct dirent *'. + They may evaluate their argument multiple times, so it must not + have side effects. Each of these may involve a relatively costly + call to `strlen' on some systems, so these values should be cached. + + _D_EXACT_NAMLEN (DP) returns the length of DP->d_name, not including + its terminating null character. + + _D_ALLOC_NAMLEN (DP) returns a size at least (_D_EXACT_NAMLEN (DP) + 1); + that is, the allocation size needed to hold the DP->d_name string. + Use this macro when you don't need the exact length, just an upper bound. + This macro is less likely to require calling `strlen' than _D_EXACT_NAMLEN. + */ + +#ifdef _DIRENT_HAVE_D_NAMLEN +# define _D_EXACT_NAMLEN(d) ((d)->d_namlen) +# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1) +#else +# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name)) +# ifdef _DIRENT_HAVE_D_RECLEN +# define _D_ALLOC_NAMLEN(d) (((char *) (d) + (d)->d_reclen) - &(d)->d_name[0]) +# else +# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \ + _D_EXACT_NAMLEN (d) + 1) +# endif +#endif + + +#ifdef __USE_BSD +/* File types for `d_type'. */ +enum + { + DT_UNKNOWN = 0, +# define DT_UNKNOWN DT_UNKNOWN + DT_FIFO = 1, +# define DT_FIFO DT_FIFO + DT_CHR = 2, +# define DT_CHR DT_CHR + DT_DIR = 4, +# define DT_DIR DT_DIR + DT_BLK = 6, +# define DT_BLK DT_BLK + DT_REG = 8, +# define DT_REG DT_REG + DT_LNK = 10, +# define DT_LNK DT_LNK + DT_SOCK = 12, +# define DT_SOCK DT_SOCK + DT_WHT = 14 +# define DT_WHT DT_WHT + }; + +/* Convert between stat structure types and directory types. */ +# define IFTODT(mode) (((mode) & 0170000) >> 12) +# define DTTOIF(dirtype) ((dirtype) << 12) +#endif + + +/* This is the data type of directory stream objects. + The actual structure is opaque to users. */ +typedef struct __dirstream DIR; + +/* Open a directory stream on NAME. + Return a DIR stream on the directory, or NULL if it could not be opened. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern DIR *opendir (__const char *__name) __nonnull ((1)); + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int closedir (DIR *__dirp) __nonnull ((1)); + +/* Read a directory entry from DIRP. Return a pointer to a `struct + dirent' describing the entry, or NULL for EOF or error. The + storage returned may be overwritten by a later readdir call on the + same DIR stream. + + If the Large File Support API is selected we have to use the + appropriate interface. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern struct dirent *readdir (DIR *__dirp) __nonnull ((1)); +#else +# ifdef __REDIRECT +extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64) + __nonnull ((1)); +# else +# define readdir readdir64 +# endif +#endif + +#ifdef __USE_LARGEFILE64 +extern struct dirent64 *readdir64 (DIR *__dirp) __nonnull ((1)); +#endif + +#if defined __USE_POSIX || defined __USE_MISC +/* Reentrant version of `readdir'. Return in RESULT a pointer to the + next entry. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int readdir_r (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result) + __nonnull ((1, 2, 3)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (readdir_r, + (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result), + readdir64_r) __nonnull ((1, 2, 3)); +# else +# define readdir_r readdir64_r +# endif +# endif + +# ifdef __USE_LARGEFILE64 +extern int readdir64_r (DIR *__restrict __dirp, + struct dirent64 *__restrict __entry, + struct dirent64 **__restrict __result) + __nonnull ((1, 2, 3)); +# endif +#endif /* POSIX or misc */ + +/* Rewind DIRP to the beginning of the directory. */ +extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1)); + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +# include + +/* Seek to position POS on DIRP. */ +extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull ((1)); + +/* Return the current position of DIRP. */ +extern long int telldir (DIR *__dirp) __THROW __nonnull ((1)); +#endif + +#if defined __USE_BSD || defined __USE_MISC + +/* Return the file descriptor used by DIRP. */ +extern int dirfd (DIR *__dirp) __THROW __nonnull ((1)); + +# if 0 /* defined __OPTIMIZE__ && defined _DIR_dirfd */ +# define dirfd(dirp) _DIR_dirfd (dirp) +# endif + +# ifndef MAXNAMLEN +/* Get the definitions of the POSIX.1 limits. */ +# include + +/* `MAXNAMLEN' is the BSD name for what POSIX calls `NAME_MAX'. */ +# ifdef NAME_MAX +# define MAXNAMLEN NAME_MAX +# else +# define MAXNAMLEN 255 +# endif +# endif + +# define __need_size_t +# include + +/* Scan the directory DIR, calling SELECTOR on each directory entry. + Entries for which SELECT returns nonzero are individually malloc'd, + sorted using qsort with CMP, and collected in a malloc'd array in + *NAMELIST. Returns the number of entries selected, or -1 on error. */ +# ifndef __USE_FILE_OFFSET64 +extern int scandir (__const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const void *, __const void *)) + __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (scandir, + (__const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const void *, __const void *)), + scandir64) __nonnull ((1, 2)); +# else +# define scandir scandir64 +# endif +# endif + +# if defined __USE_GNU && defined __USE_LARGEFILE64 +/* This function is like `scandir' but it uses the 64bit dirent structure. + Please note that the CMP function must now work with struct dirent64 **. */ +extern int scandir64 (__const char *__restrict __dir, + struct dirent64 ***__restrict __namelist, + int (*__selector) (__const struct dirent64 *), + int (*__cmp) (__const void *, __const void *)) + __nonnull ((1, 2)); +# endif + +/* Function to compare two `struct dirent's alphabetically. */ +# ifndef __USE_FILE_OFFSET64 +extern int alphasort (__const void *__e1, __const void *__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (alphasort, + (__const void *__e1, __const void *__e2), + alphasort64) __attribute_pure__ __nonnull ((1, 2)); +# else +# define alphasort alphasort64 +# endif +# endif + +# if defined __USE_GNU && defined __USE_LARGEFILE64 +extern int alphasort64 (__const void *__e1, __const void *__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# endif + +#endif /* Use BSD or misc. */ + +__END_DECLS + +#endif /* dirent.h */ diff --git a/include/dlfcn.h b/include/dlfcn.h new file mode 100644 index 0000000..2348e43 --- /dev/null +++ b/include/dlfcn.h @@ -0,0 +1,201 @@ +/* User functions for run-time dynamic loading. + Copyright (C) 1995-1999,2000,2001,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include +#define __need_size_t +#include + +/* Collect various system dependent definitions and declarations. */ +#include + + +#ifdef __USE_GNU +/* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT + the run-time address of the symbol called NAME in the next shared + object is returned. The "next" relation is defined by the order + the shared objects were loaded. */ +# define RTLD_NEXT ((void *) -1l) + +/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT + the run-time address of the symbol called NAME in the global scope + is returned. */ +# define RTLD_DEFAULT ((void *) 0) + + +# if 0 /* uClibc doesnt support this */ +/* Type for namespace indeces. */ +typedef long int Lmid_t; + +/* Special namespace ID values. */ +# define LM_ID_BASE 0 /* Initial namespace. */ +# define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */ +# endif +#endif + +__BEGIN_DECLS + +/* Open the shared object FILE and map it in; return a handle that can be + passed to `dlsym' to get symbol values from it. */ +extern void *dlopen (__const char *__file, int __mode) __THROW; + +/* Unmap and close a shared object opened by `dlopen'. + The handle cannot be used again after calling `dlclose'. */ +extern int dlclose (void *__handle) __THROW __nonnull ((1)); + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME. */ +extern void *dlsym (void *__restrict __handle, + __const char *__restrict __name) __THROW __nonnull ((2)); + +#if 0 /*def __USE_GNU*/ +/* Like `dlopen', but request object to be allocated in a new namespace. */ +extern void *dlmopen (Lmid_t __nsid, __const char *__file, int __mode) __THROW; + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME with VERSION. */ +extern void *dlvsym (void *__restrict __handle, + __const char *__restrict __name, + __const char *__restrict __version) + __THROW __nonnull ((2, 3)); +#endif + +/* When any of the above functions fails, call this function + to return a string describing the error. Each call resets + the error string so that a following call returns null. */ +extern char *dlerror (void) __THROW; + + +#ifdef __USE_GNU +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + +/* Fill in *INFO with the following information about ADDRESS. + Returns 0 iff no shared object's segments contain that address. */ +extern int dladdr (__const void *__address, Dl_info *__info) + __THROW __nonnull ((2)); + +#if 0 /* not supported by uClibc */ +/* Same as `dladdr', but additionally sets *EXTRA_INFO according to FLAGS. */ +extern int dladdr1 (__const void *__address, Dl_info *__info, + void **__extra_info, int __flags) __THROW __nonnull ((2)); + +/* These are the possible values for the FLAGS argument to `dladdr1'. + This indicates what extra information is stored at *EXTRA_INFO. + It may also be zero, in which case the EXTRA_INFO argument is not used. */ +enum + { + /* Matching symbol table entry (const ElfNN_Sym *). */ + RTLD_DL_SYMENT = 1, + + /* The object containing the address (struct link_map *). */ + RTLD_DL_LINKMAP = 2 + }; + + +/* Get information about the shared object HANDLE refers to. + REQUEST is from among the values below, and determines the use of ARG. + + On success, returns zero. On failure, returns -1 and records an error + message to be fetched with `dlerror'. */ +extern int dlinfo (void *__restrict __handle, + int __request, void *__restrict __arg) + __THROW __nonnull ((1, 3)); + +/* These are the possible values for the REQUEST argument to `dlinfo'. */ +enum + { + /* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */ + RTLD_DI_LMID = 1, + + /* Treat ARG as `struct link_map **'; + store the `struct link_map *' for HANDLE there. */ + RTLD_DI_LINKMAP = 2, + + RTLD_DI_CONFIGADDR = 3, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the + directories that will be searched for dependencies of this object. + RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size' + entries to indicate the size of the buffer that must be passed to + RTLD_DI_SERINFO to fill in the full information. */ + RTLD_DI_SERINFO = 4, + RTLD_DI_SERINFOSIZE = 5, + + /* Treat ARG as `char *', and store there the directory name used to + expand $ORIGIN in this shared object's dependency file names. */ + RTLD_DI_ORIGIN = 6, + + RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */ + RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `size_t *', and store there the TLS module ID + of this object's PT_TLS segment, as used in TLS relocations; + store zero if this object does not define a PT_TLS segment. */ + RTLD_DI_TLS_MODID = 9, + + /* Treat ARG as `void **', and store there a pointer to the calling + thread's TLS block corresponding to this object's PT_TLS segment. + Store a null pointer if this object does not define a PT_TLS + segment, or if the calling thread has not allocated a block for it. */ + RTLD_DI_TLS_DATA = 10, + + RTLD_DI_MAX = 10, + }; + + +/* This is the type of elements in `Dl_serinfo', below. + The `dls_name' member points to space in the buffer passed to `dlinfo'. */ +typedef struct +{ + char *dls_name; /* Name of library search path directory. */ + unsigned int dls_flags; /* Indicates where this directory came from. */ +} Dl_serpath; + +/* This is the structure that must be passed (by reference) to `dlinfo' for + the RTLD_DI_SERINFO and RTLD_DI_SERINFOSIZE requests. */ +typedef struct +{ + size_t dls_size; /* Size in bytes of the whole buffer. */ + unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ + Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ +} Dl_serinfo; + +#else + +/* Get information about the shared objects currently loaded */ +extern int dlinfo (void); + +#endif +#endif /* __USE_GNU */ + + +__END_DECLS + +#endif /* dlfcn.h */ diff --git a/include/elf.h b/include/elf.h new file mode 100644 index 0000000..4c6d090 --- /dev/null +++ b/include/elf.h @@ -0,0 +1,3040 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ELF_H +#define _ELF_H 1 + +#include + +__BEGIN_DECLS + +/* Standard ELF types. */ + +#include + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_OPENVMS 13 /* OpenVMS */ +#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Intel 80486 *//* Reserved for future use */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ +#define EM_RCE 39 /* Old name for MCore */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Renesas SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Renesas H8/300 */ +#define EM_H8_300H 47 /* Renesas H8/300H */ +#define EM_H8S 48 /* Renesas H8S */ +#define EM_H8_500 49 /* Renesas H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Renesas M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_IP2K 101 /* Ubicom IP2022 micro controller */ +#define EM_CR 103 /* National Semiconductor CompactRISC */ +#define EM_MSP430 105 /* TI msp430 micro controller */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CRX */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please pick large + random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision + with official or non-GNU unofficial values. + + NOTE: Do not just increment the most recent number by one. + Somebody else somewhere will do exactly the same thing, and you + will have a collision. Instead, pick a random number. + + Normally, each entity or maintainer responsible for a machine with an + unofficial e_machine number should eventually ask registry@caldera.com for + an officially blessed number to be added to the list above. */ + +/* picoJava */ +#define EM_PJ_OLD 99 + +/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_POWERPC 0x9025 + +/* Old version of Sparc v9, from before the ABI; this should be + removed shortly. */ +#define EM_OLD_SPARCV9 11 + +/* Old version of PowerPC, this should be removed shortly. */ +#define EM_PPC_OLD 17 + +/* (Deprecated) Temporary number for the OpenRISC processor. */ +#define EM_OR32 0x8472 + +/* Renesas M32C and M16C. */ +#define EM_M32C 0xFEB0 + +/* Cygnus M32R ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_M32R 0x9041 + +/* old S/390 backend magic number. Written in the absence of an ABI. */ +#define EM_S390_OLD 0xa390 + +/* D10V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D10V 0x7650 + +/* D30V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D30V 0x7676 + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* mn10200 and mn10300 backend magic numbers. + Written in the absense of an ABI. */ +#define EM_CYGNUS_MN10200 0xdead +#define EM_CYGNUS_MN10300 0xbeef + +/* FR30 magic number - no EABI available. */ +#define EM_CYGNUS_FR30 0x3330 + +/* AVR magic number + Written in the absense of an ABI. */ +#define EM_AVR_OLD 0x1057 + +/* OpenRISC magic number + Written in the absense of an ABI. */ +#define EM_OPENRISC_OLD 0x3426 + +/* DLX magic number + Written in the absense of an ABI. */ +#define EM_DLX 0x5aa5 + +#define EM_XSTORMY16 0xad45 + +/* FRV magic number - no EABI available??. */ +#define EM_CYGNUS_FRV 0x5441 + +/* Ubicom IP2xxx; no ABI */ +#define EM_IP2K_OLD 0x8217 + +#define EM_MT 0x2530 /* Morpho MT; no ABI */ + +/* MSP430 magic number + Written in the absense everything. */ +#define EM_MSP430_OLD 0x1059 + +/* Vitesse IQ2000. */ +#define EM_IQ2000 0xFEBA + +/* Old, unofficial value for Xtensa. */ +#define EM_XTENSA_OLD 0xabc7 + +/* Alpha backend magic number. Written in the absence of an ABI. */ +#define EM_ALPHA 0x9026 + +/* NIOS magic number - no EABI available. */ +#define EM_NIOS32 0xFEBB + +/* AVR32 magic number from ATMEL */ +#define EM_AVR32 0x18ad + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#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)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#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)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#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)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_PAX_FLAGS 0x65041580 /* Indicates PaX flag markings */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_PAGEEXEC (1 << 4) /* Enable PAGEEXEC */ +#define PF_NOPAGEEXEC (1 << 5) /* Disable PAGEEXEC */ +#define PF_SEGMEXEC (1 << 6) /* Enable SEGMEXEC */ +#define PF_NOSEGMEXEC (1 << 7) /* Disable SEGMEXEC */ +#define PF_MPROTECT (1 << 8) /* Enable MPROTECT */ +#define PF_NOMPROTECT (1 << 9) /* Disable MPROTECT */ +#define PF_RANDEXEC (1 << 10) /* Enable RANDEXEC */ +#define PF_NORANDEXEC (1 << 11) /* Disable RANDEXEC */ +#define PF_EMUTRAMP (1 << 12) /* Enable EMUTRAMP */ +#define PF_NOEMUTRAMP (1 << 13) /* Disable EMUTRAMP */ +#define PF_RANDMMAP (1 << 14) /* Enable RANDMMAP */ +#define PF_NORANDMMAP (1 << 15) /* Disable RANDMMAP */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + uint32_t a_type; /* Entry type */ + union + { + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + uint64_t a_type; /* Entry type */ + union + { + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#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) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#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 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* Blackfin specific definitions. */ +#define R_BFIN_unused0 0x00 +#define R_BFIN_pcrel5m2 0x01 +#define R_BFIN_unused1 0x02 +#define R_BFIN_pcrel10 0x03 +#define R_BFIN_pcrel12_jump 0x04 +#define R_BFIN_rimm16 0x05 +#define R_BFIN_luimm16 0x06 +#define R_BFIN_huimm16 0x07 +#define R_BFIN_pcrel12_jump_s 0x08 +#define R_BFIN_pcrel24_jump_x 0x09 +#define R_BFIN_pcrel24 0x0a +#define R_BFIN_unusedb 0x0b +#define R_BFIN_unusedc 0x0c +#define R_BFIN_pcrel24_jump_l 0x0d +#define R_BFIN_pcrel24_call_x 0x0e +#define R_BFIN_var_eq_symb 0x0f +#define R_BFIN_byte_data 0x10 +#define R_BFIN_byte2_data 0x11 +#define R_BFIN_byte4_data 0x12 +#define R_BFIN_pcrel11 0x13 + +#define R_BFIN_GOT17M4 0x14 +#define R_BFIN_GOTHI 0x15 +#define R_BFIN_GOTLO 0x16 +#define R_BFIN_FUNCDESC 0x17 +#define R_BFIN_FUNCDESC_GOT17M4 0x18 +#define R_BFIN_FUNCDESC_GOTHI 0x19 +#define R_BFIN_FUNCDESC_GOTLO 0x1a +#define R_BFIN_FUNCDESC_VALUE 0x1b +#define R_BFIN_FUNCDESC_GOTOFF17M4 0x1c +#define R_BFIN_FUNCDESC_GOTOFFHI 0x1d +#define R_BFIN_FUNCDESC_GOTOFFLO 0x1e +#define R_BFIN_GOTOFF17M4 0x1f +#define R_BFIN_GOTOFFHI 0x20 +#define R_BFIN_GOTOFFLO 0x21 + +#define EF_BFIN_PIC 0x00000001 /* -fpic */ +#define EF_BFIN_FDPIC 0x00000002 /* -mfdpic */ +#define EF_BFIN_CODE_IN_L1 0x00000010 /* --code-in-l1 */ +#define EF_BFIN_DATA_IN_L1 0x00000020 /* --data-in-l1 */ + +/* FR-V specific definitions. */ +#define R_FRV_NONE 0 /* No reloc. */ +#define R_FRV_32 1 /* Direct 32 bit. */ +/* Canonical function descriptor address. */ +#define R_FRV_FUNCDESC 14 +/* Private function descriptor initialization. */ +#define R_FRV_FUNCDESC_VALUE 18 + + /* gpr support */ +#define EF_FRV_GPR_MASK 0x00000003 /* mask for # of gprs */ +#define EF_FRV_GPR_32 0x00000001 /* -mgpr-32 */ +#define EF_FRV_GPR_64 0x00000002 /* -mgpr-64 */ + + /* fpr support */ +#define EF_FRV_FPR_MASK 0x0000000c /* mask for # of fprs */ +#define EF_FRV_FPR_32 0x00000004 /* -mfpr-32 */ +#define EF_FRV_FPR_64 0x00000008 /* -mfpr-64 */ +#define EF_FRV_FPR_NONE 0x0000000c /* -msoft-float */ + +#define EF_FRV_PIC 0x00000100 +#define EF_FRV_FDPIC 0x00008000 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#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 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#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 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#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 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#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 /* Miscellaneous options. */ +#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 /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#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 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#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 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#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 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#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 /* Module number 32 bit */ +#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ +/* Keep this the last entry. */ +#define R_MIPS_NUM 51 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#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 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +#define DT_MIPS_NUM 0x32 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#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) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#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 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#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 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#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 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#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 + +/* Legal values for d_tag of Elf64_Dyn. */ +#define DT_ALPHA_PLTRO (DT_LOPROC + 0) +#define DT_ALPHA_NUM 1 + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#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 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#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 /* 16 bit offset in SDA */ +#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 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* GNU relocs used in PIC code sequences. */ +#define R_PPC_REL16 249 /* word32 (sym-.) */ +#define R_PPC_REL16_LO 250 /* half16 (sym-.)@l */ +#define R_PPC_REL16_HI 251 /* half16 (sym-.)@h */ +#define R_PPC_REL16_HA 252 /* half16 (sym-.)@ha */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +/* PowerPC specific values for the Dyn d_tag field. */ +#define DT_PPC_GOT (DT_LOPROC + 0) +#define DT_PPC_NUM 1 + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#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 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#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 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#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 + + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#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 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#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 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ + +/* ARM relocs. */ + +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#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_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#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 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#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 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#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) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH specific values for `st_other'. */ + +/* If set, this is a symbol pointing to SHmedia code, which will be branched + to, so need to add 1 to the symbol value. */ +#define STO_SH5_ISA32 (1 << 2) + +/* SH relocs. */ +#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_RELATIVE_LOW16 197 +#define R_SH_RELATIVE_MEDLOW16 198 +#define R_SH_IMM_LOW16 246 +#define R_SH_IMM_LOW16_PCREL 247 +#define R_SH_IMM_MEDLOW16 248 +#define R_SH_IMM_MEDLOW16_PCREL 249 + +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + + +/* CRIS flags. */ +#define EF_CRIS_VARIANT_MASK 0x0000000e +#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000 +#define EF_CRIS_VARIANT_V32 0x00000002 +#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004 + +/* CRIS relocations. */ +#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 + +/* Keep this the last entry. */ +#define R_CRIS_NUM 20 + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ + +#define R_MN10300_NUM 24 + + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned + low */ +#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to + GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to + GOT with signed low */ +#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to + GOT */ +#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT + with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + +/* i960 Relocations */ +#define R_960_NONE 0 +#define R_960_12 1 +#define R_960_32 2 +#define R_960_IP24 3 +#define R_960_SUB 4 +#define R_960_OPTCALL 5 +#define R_960_OPTCALLX 6 +#define R_960_OPTCALLXA 7 +/* Keep this the last entry. */ +#define R_960_NUM 8 + + +/* v850 relocations. */ +#define R_V850_NONE 0 +#define R_V850_9_PCREL 1 +#define R_V850_22_PCREL 2 +#define R_V850_HI16_S 3 +#define R_V850_HI16 4 +#define R_V850_LO16 5 +#define R_V850_32 6 +#define R_V850_16 7 +#define R_V850_8 8 +#define R_V850_SDA_16_16_OFFSET 9 /* For ld.b, st.b, set1, clr1, + not1, tst1, movea, movhi */ +#define R_V850_SDA_15_16_OFFSET 10 /* For ld.w, ld.h, ld.hu, st.w, st.h */ +#define R_V850_ZDA_16_16_OFFSET 11 /* For ld.b, st.b, set1, clr1, + not1, tst1, movea, movhi */ +#define R_V850_ZDA_15_16_OFFSET 12 /* For ld.w, ld.h, ld.hu, st.w, st.h */ +#define R_V850_TDA_6_8_OFFSET 13 /* For sst.w, sld.w */ +#define R_V850_TDA_7_8_OFFSET 14 /* For sst.h, sld.h */ +#define R_V850_TDA_7_7_OFFSET 15 /* For sst.b, sld.b */ +#define R_V850_TDA_16_16_OFFSET 16 /* For set1, clr1, not1, tst1, + movea, movhi */ +/* CYGNUS LOCAL v850e */ +#define R_V850_TDA_4_5_OFFSET 17 /* For sld.hu */ +#define R_V850_TDA_4_4_OFFSET 18 /* For sld.bu */ +#define R_V850_SDA_16_16_SPLIT_OFFSET 19 /* For ld.bu */ +#define R_V850_ZDA_16_16_SPLIT_OFFSET 20 /* For ld.bu */ +#define R_V850_CALLT_6_7_OFFSET 21 /* For callt */ +#define R_V850_CALLT_16_16_OFFSET 22 /* For callt */ +/* END CYGNUS LOCAL */ +#define R_V850_GNU_VTINHERIT 23 +#define R_V850_GNU_VTENTRY 24 +/* Keep this the last entry. */ +#define R_V850_NUM 25 + +/* Atmel AVR32 relocations. */ +#define R_AVR32_NONE 0 +#define R_AVR32_32 1 +#define R_AVR32_16 2 +#define R_AVR32_8 3 +#define R_AVR32_32_PCREL 4 +#define R_AVR32_16_PCREL 5 +#define R_AVR32_8_PCREL 6 +#define R_AVR32_DIFF32 7 +#define R_AVR32_DIFF16 8 +#define R_AVR32_DIFF8 9 +#define R_AVR32_GOT32 10 +#define R_AVR32_GOT16 11 +#define R_AVR32_GOT8 12 +#define R_AVR32_21S 13 +#define R_AVR32_16U 14 +#define R_AVR32_16S 15 +#define R_AVR32_8S 16 +#define R_AVR32_8S_EXT 17 +#define R_AVR32_22H_PCREL 18 +#define R_AVR32_18W_PCREL 19 +#define R_AVR32_16B_PCREL 20 +#define R_AVR32_16N_PCREL 21 +#define R_AVR32_14UW_PCREL 22 +#define R_AVR32_11H_PCREL 23 +#define R_AVR32_10UW_PCREL 24 +#define R_AVR32_9H_PCREL 25 +#define R_AVR32_9UW_PCREL 26 +#define R_AVR32_HI16 27 +#define R_AVR32_LO16 28 +#define R_AVR32_GOTPC 29 +#define R_AVR32_GOTCALL 30 +#define R_AVR32_LDA_GOT 31 +#define R_AVR32_GOT21S 32 +#define R_AVR32_GOT18SW 33 +#define R_AVR32_GOT16S 34 +#define R_AVR32_GOT7UW 35 +#define R_AVR32_32_CPENT 36 +#define R_AVR32_CPCALL 37 +#define R_AVR32_16_CP 38 +#define R_AVR32_9W_CP 39 +#define R_AVR32_RELATIVE 40 +#define R_AVR32_GLOB_DAT 41 +#define R_AVR32_JMP_SLOT 42 +#define R_AVR32_ALIGN 43 +#define R_AVR32_NUM 44 + +/* AVR32 dynamic tags */ +#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */ + +/* Renesas H8/300 Relocations */ +#define R_H8_NONE 0 +#define R_H8_DIR32 1 +#define R_H8_DIR32_28 2 +#define R_H8_DIR32_24 3 +#define R_H8_DIR32_16 4 +#define R_H8_DIR32U 6 +#define R_H8_DIR32U_28 7 +#define R_H8_DIR32U_24 8 +#define R_H8_DIR32U_20 9 +#define R_H8_DIR32U_16 10 +#define R_H8_DIR24 11 +#define R_H8_DIR24_20 12 +#define R_H8_DIR24_16 13 +#define R_H8_DIR24U 14 +#define R_H8_DIR24U_20 15 +#define R_H8_DIR24U_16 16 +#define R_H8_DIR16 17 +#define R_H8_DIR16U 18 +#define R_H8_DIR16S_32 19 +#define R_H8_DIR16S_28 20 +#define R_H8_DIR16S_24 21 +#define R_H8_DIR16S_20 22 +#define R_H8_DIR16S 23 +#define R_H8_DIR8 24 +#define R_H8_DIR8U 25 +#define R_H8_DIR8Z_32 26 +#define R_H8_DIR8Z_28 27 +#define R_H8_DIR8Z_24 28 +#define R_H8_DIR8Z_20 29 +#define R_H8_DIR8Z_16 30 +#define R_H8_PCREL16 31 +#define R_H8_PCREL8 32 +#define R_H8_BPOS 33 +#define R_H8_PCREL32 34 +#define R_H8_GOT32O 35 +#define R_H8_GOT16O 36 +#define R_H8_DIR16A8 59 +#define R_H8_DIR16R8 60 +#define R_H8_DIR24A8 61 +#define R_H8_DIR24R8 62 +#define R_H8_DIR32A16 63 +#define R_H8_ABS32 65 +#define R_H8_ABS32A16 127 +#define R_H8_NUM 128 + +/* NIOS relocations. */ +#define R_NIOS_NONE 0 +#define R_NIOS_32 1 /* A 32 bit absolute relocation.*/ +#define R_NIOS_LO16_LO5 2 /* A LO-16 5 bit absolute relocation. */ +#define R_NIOS_LO16_HI11 3 /* A LO-16 top 11 bit absolute relocation. */ +#define R_NIOS_HI16_LO5 4 /* A HI-16 5 bit absolute relocation. */ +#define R_NIOS_HI16_HI11 5 /* A HI-16 top 11 bit absolute relocation. */ +#define R_NIOS_PCREL6 6 /* A 6 bit relative relocation. */ +#define R_NIOS_PCREL8 7 /* An 8 bit relative relocation. */ +#define R_NIOS_PCREL11 8 /* An 11 bit relative relocation. */ +#define R_NIOS_16 9 /* A 16 bit absolute relocation. */ +#define R_NIOS_H_LO5 10 /* Low 5-bits of absolute relocation in halfwords. */ +#define R_NIOS_H_HI11 11 /* Top 11 bits of 16-bit absolute relocation in halfwords. */ +#define R_NIOS_H_XLO5 12 /* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords. */ +#define R_NIOS_H_XHI11 13 /* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords. */ +#define R_NIOS_H_16 14 /* Half-word @h value */ +#define R_NIOS_H_32 15 /* Word @h value */ +#define R_NIOS_GNU_VTINHERIT 200 /* GNU extension to record C++ vtable hierarchy */ +#define R_NIOS_GNU_VTENTRY 201 /* GNU extension to record C++ vtable member usage */ +/* Keep this the last entry. */ +#define R_NIOS_NUM 202 + +/* NIOS II relocations */ +#define R_NIOS2_NONE 0 +#define R_NIOS2_S16 1 +#define R_NIOS2_U16 2 +#define R_NIOS2_PCREL16 3 +#define R_NIOS2_CALL26 4 +#define R_NIOS2_IMM5 5 +#define R_NIOS2_CACHE_OPX 6 +#define R_NIOS2_IMM6 7 +#define R_NIOS2_IMM8 8 +#define R_NIOS2_HI16 9 +#define R_NIOS2_LO16 10 +#define R_NIOS2_HIADJ16 11 +#define R_NIOS2_BFD_RELOC_32 12 +#define R_NIOS2_BFD_RELOC_16 13 +#define R_NIOS2_BFD_RELOC_8 14 +#define R_NIOS2_GPREL 15 +#define R_NIOS2_GNU_VTINHERIT 16 +#define R_NIOS2_GNU_VTENTRY 17 +#define R_NIOS2_UJMP 18 +#define R_NIOS2_CJMP 19 +#define R_NIOS2_CALLR 20 +#define R_NIOS2_ALIGN 21 +/* Keep this the last entry. */ +#define R_NIOS2_NUM 22 + +/* Xtensa-specific declarations */ + +/* Xtensa values for the Dyn d_tag field. */ +#define DT_XTENSA_GOT_LOC_OFF (DT_LOPROC + 0) +#define DT_XTENSA_GOT_LOC_SZ (DT_LOPROC + 1) +#define DT_XTENSA_NUM 2 + +/* Xtensa relocations. */ +#define R_XTENSA_NONE 0 +#define R_XTENSA_32 1 +#define R_XTENSA_RTLD 2 +#define R_XTENSA_GLOB_DAT 3 +#define R_XTENSA_JMP_SLOT 4 +#define R_XTENSA_RELATIVE 5 +#define R_XTENSA_PLT 6 +#define R_XTENSA_OP0 8 +#define R_XTENSA_OP1 9 +#define R_XTENSA_OP2 10 +#define R_XTENSA_ASM_EXPAND 11 +#define R_XTENSA_ASM_SIMPLIFY 12 +#define R_XTENSA_GNU_VTINHERIT 15 +#define R_XTENSA_GNU_VTENTRY 16 +#define R_XTENSA_DIFF8 17 +#define R_XTENSA_DIFF16 18 +#define R_XTENSA_DIFF32 19 +#define R_XTENSA_SLOT0_OP 20 +#define R_XTENSA_SLOT1_OP 21 +#define R_XTENSA_SLOT2_OP 22 +#define R_XTENSA_SLOT3_OP 23 +#define R_XTENSA_SLOT4_OP 24 +#define R_XTENSA_SLOT5_OP 25 +#define R_XTENSA_SLOT6_OP 26 +#define R_XTENSA_SLOT7_OP 27 +#define R_XTENSA_SLOT8_OP 28 +#define R_XTENSA_SLOT9_OP 29 +#define R_XTENSA_SLOT10_OP 30 +#define R_XTENSA_SLOT11_OP 31 +#define R_XTENSA_SLOT12_OP 32 +#define R_XTENSA_SLOT13_OP 33 +#define R_XTENSA_SLOT14_OP 34 +#define R_XTENSA_SLOT0_ALT 35 +#define R_XTENSA_SLOT1_ALT 36 +#define R_XTENSA_SLOT2_ALT 37 +#define R_XTENSA_SLOT3_ALT 38 +#define R_XTENSA_SLOT4_ALT 39 +#define R_XTENSA_SLOT5_ALT 40 +#define R_XTENSA_SLOT6_ALT 41 +#define R_XTENSA_SLOT7_ALT 42 +#define R_XTENSA_SLOT8_ALT 43 +#define R_XTENSA_SLOT9_ALT 44 +#define R_XTENSA_SLOT10_ALT 45 +#define R_XTENSA_SLOT11_ALT 46 +#define R_XTENSA_SLOT12_ALT 47 +#define R_XTENSA_SLOT13_ALT 48 +#define R_XTENSA_SLOT14_ALT 49 +/* Keep this the last entry. */ +#define R_XTENSA_NUM 50 + +__END_DECLS + +#endif /* elf.h */ diff --git a/include/endian.h b/include/endian.h new file mode 100644 index 0000000..2f7bce1 --- /dev/null +++ b/include/endian.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1992, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H 1 + +#include + +/* Definitions for byte order, according to significance of bytes, + from low addresses to high addresses. The value is what you get by + putting '4' in the most significant byte, '3' in the second most + significant byte, '2' in the second least significant byte, and '1' + in the least significant byte, and then writing down one digit for + each byte, starting with the byte at the lowest address at the left, + and proceeding to the byte with the highest address at the right. */ + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __PDP_ENDIAN 3412 + +/* This file defines `__BYTE_ORDER' for the particular machine. */ +#include + +/* Some machines may need to use a different endianness for floating point + values. */ +#ifndef __FLOAT_WORD_ORDER +# define __FLOAT_WORD_ORDER __BYTE_ORDER +#endif + +#ifdef __USE_BSD +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# define PDP_ENDIAN __PDP_ENDIAN +# define BYTE_ORDER __BYTE_ORDER +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) LO, HI +#elif __BYTE_ORDER == __BIG_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) HI, LO +#endif + +#endif /* endian.h */ diff --git a/include/err.h b/include/err.h new file mode 100644 index 0000000..7ff3553 --- /dev/null +++ b/include/err.h @@ -0,0 +1,58 @@ +/* 4.4BSD utility functions for error messages. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ERR_H +#define _ERR_H 1 + +#include + +#define __need___va_list +#include +#ifndef __GNUC_VA_LIST +# define __gnuc_va_list __ptr_t +#endif + +__BEGIN_DECLS + +/* Print "program: ", FORMAT, ": ", the standard error string for errno, + and a newline, on stderr. */ +extern void warn (__const char *__format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +extern void vwarn (__const char *__format, __gnuc_va_list) + __attribute__ ((__format__ (__printf__, 1, 0))); + +/* Likewise, but without ": " and the standard error string. */ +extern void warnx (__const char *__format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +extern void vwarnx (__const char *__format, __gnuc_va_list) + __attribute__ ((__format__ (__printf__, 1, 0))); + +/* Likewise, and then exit with STATUS. */ +extern void err (int __status, __const char *__format, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); +extern void verr (int __status, __const char *__format, __gnuc_va_list) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); +extern void errx (int __status, __const char *__format, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); +extern void verrx (int __status, __const char *, __gnuc_va_list) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); + +__END_DECLS + +#endif /* err.h */ diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000..b2315b9 --- /dev/null +++ b/include/errno.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.5 Errors + */ + +#ifndef _ERRNO_H + +/* The includer defined __need_Emath if he wants only the definitions + of EDOM and ERANGE, and not everything else. */ +#ifndef __need_Emath +# define _ERRNO_H 1 +# include +#endif + +__BEGIN_DECLS + +/* Get the error number constants from the system-specific file. + This file will test __need_Emath and _ERRNO_H. */ +#include +#undef __need_Emath + +#ifdef _ERRNO_H + +/* Declare the `errno' variable, unless it's defined as a macro by + bits/errno.h. This is the case in GNU, where it is a per-thread + variable. This redeclaration using the macro still works, but it + will be a function declaration without a prototype and may trigger + a -Wstrict-prototypes warning. */ +#ifndef errno +extern int errno; +#endif + +#if defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ + +/* The full and simple forms of the name with which the program was + invoked. These variables are set up automatically at startup based on + the value of ARGV[0] (this works only if you use GNU ld). */ +extern const char *program_invocation_name, *program_invocation_short_name; +#endif /* __USE_GNU */ +#endif /* _ERRNO_H */ + +__END_DECLS + +#if defined _LIBC && ( defined IS_IN_libc || defined NOT_IN_libc ) +#include +#endif + +#endif /* _ERRNO_H */ + +/* The Hurd defines `error_t' as an enumerated type so + that printing `error_t' values in the debugger shows the names. We + might need this definition sometimes even if this file was included + before. */ +#if defined __USE_GNU || defined __need_error_t +# ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined 1 +# endif +# undef __need_error_t +#endif diff --git a/include/error.h b/include/error.h new file mode 100644 index 0000000..b553cae --- /dev/null +++ b/include/error.h @@ -0,0 +1,52 @@ +/* Declaration for error-reporting function + Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ERROR_H +#define _ERROR_H 1 + +#include + +__BEGIN_DECLS + +/* Print a message with `fprintf (stderr, FORMAT, ...)'; + if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). + If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ + +extern void error (int __status, int __errnum, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + +extern void error_at_line (int __status, int __errnum, const char *__fname, + unsigned int __lineno, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 5, 6))); + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +extern void (*error_print_progname) (void); + +/* This variable is incremented each time `error' is called. */ +extern unsigned int error_message_count; + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +extern int error_one_per_line; + +__END_DECLS + +#endif /* error.h */ diff --git a/include/fcntl.h b/include/fcntl.h new file mode 100644 index 0000000..3e0aab5 --- /dev/null +++ b/include/fcntl.h @@ -0,0 +1,228 @@ +/* Copyright (C) 1991,1992,1994-2001,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 6.5 File Control Operations + */ + +#ifndef _FCNTL_H +#define _FCNTL_H 1 + +#include + +/* This must be early so can define types winningly. */ +__BEGIN_DECLS + +/* Get the definitions of O_*, F_*, FD_*: all the + numbers and flag bits for `open', `fcntl', et al. */ +#include + +/* For XPG all symbols from should also be available. */ +#ifdef __USE_XOPEN +# include +#endif + +#ifdef __USE_MISC +# ifndef R_OK /* Verbatim from . Ugh. */ +/* Values for the second argument to access. + These may be OR'd together. */ +# define R_OK 4 /* Test for read permission. */ +# define W_OK 2 /* Test for write permission. */ +# define X_OK 1 /* Test for execute permission. */ +# define F_OK 0 /* Test for existence. */ +# endif +#endif /* Use misc. */ + +/* XPG wants the following symbols. */ +#ifdef __USE_XOPEN /* has the same definitions. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Seek from end of file. */ +#endif /* XPG */ + +#if 0 /*def __USE_GNU*/ +# define AT_FDCWD -100 /* Special value used to indicate + openat should use the current + working directory. */ +# define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */ +# define AT_REMOVEDIR 0x200 /* Remove directory instead of + unlinking file. */ +#endif + +/* Do the file control operation described by CMD on FD. + The remaining arguments are interpreted depending on CMD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int fcntl (int __fd, int __cmd, ...); +#else +# ifdef __REDIRECT +extern int __REDIRECT (fcntl, (int __fd, int __cmd, ...), fcntl64); +# else +# define fcntl fcntl64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int fcntl64 (int __fd, int __cmd, ...); +#endif + +/* Open FILE and return a new file descriptor for it, or -1 on error. + OFLAG determines the type of access used. If O_CREAT is on OFLAG, + the third argument is taken as a `mode_t', the mode of the created file. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int open (__const char *__file, int __oflag, ...) __nonnull ((1)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (open, (__const char *__file, int __oflag, ...), open64) + __nonnull ((1)); +# else +# define open open64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int open64 (__const char *__file, int __oflag, ...) __nonnull ((1)); +#endif + +#if 0 /*def __USE_GNU*/ +/* Similar to OPEN but a relative path name is interpreted relative to + the directory for which FD is a descriptor. + + NOTE: some other OPENAT implementation support additional functionality + through this interface, especially using the O_XATTR flag. This is not + yet supported here. + + This function is a cancellation point and therefore not marked with + __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int openat (int __fd, __const char *__file, int __oflag, ...) + __nonnull ((2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (openat, (int __fd, __const char *__file, int __oflag, + ...), openat64) __nonnull ((2)); +# else +# define openat openat64 +# endif +# endif + +extern int openat64 (int __fd, __const char *__file, int __oflag, ...) + __nonnull ((2)); +#endif + +/* Create and open FILE, with mode MODE. This takes an `int' MODE + argument because that is what `mode_t' will be widened to. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int creat (__const char *__file, __mode_t __mode) __nonnull ((1)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (creat, (__const char *__file, __mode_t __mode), + creat64) __nonnull ((1)); +# else +# define creat creat64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int creat64 (__const char *__file, __mode_t __mode) __nonnull ((1)); +#endif + +#if !defined F_LOCK && (defined __USE_MISC || (defined __USE_XOPEN_EXTENDED \ + && !defined __USE_POSIX)) +/* NOTE: These declarations also appear in ; be sure to keep both + files consistent. Some systems have them there and some here, and some + software depends on the macros being defined without including both. */ + +/* `lockf' is a simpler interface to the locking facilities of `fcntl'. + LEN is always relative to the current file position. + The CMD argument is one of the following. */ + +# define F_ULOCK 0 /* Unlock a previously locked region. */ +# define F_LOCK 1 /* Lock a region for exclusive use. */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ +# define F_TEST 3 /* Test a region for other processes locks. */ + +# ifndef __USE_FILE_OFFSET64 +extern int lockf (int __fd, int __cmd, __off_t __len); +# else +# ifdef __REDIRECT +extern int __REDIRECT (lockf, (int __fd, int __cmd, __off64_t __len), lockf64); +# else +# define lockf lockf64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lockf64 (int __fd, int __cmd, __off64_t __len); +# endif +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Advice the system about the expected behaviour of the application with + respect to the file associated with FD. */ +# ifndef __USE_FILE_OFFSET64 +extern int posix_fadvise (int __fd, __off_t __offset, __off_t __len, + int __advise) __THROW; +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (posix_fadvise, (int __fd, __off64_t __offset, + __off64_t __len, int __advise), + posix_fadvise64); +# else +# define posix_fadvise posix_fadvise64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int posix_fadvise64 (int __fd, __off64_t __offset, __off64_t __len, + int __advise) __THROW; +# endif + +#endif + +#if 0 /* && defined __UCLIBC_HAS_ADVANCED_REALTIME__ */ + +/* FIXME -- uClibc should probably implement these... */ + +/* Reserve storage for the data of the file associated with FD. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int posix_fallocate (int __fd, __off_t __offset, __off_t __len); +# else +# ifdef __REDIRECT +extern int __REDIRECT (posix_fallocate, (int __fd, __off64_t __offset, + __off64_t __len), + posix_fallocate64); +# else +# define posix_fallocate posix_fallocate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int posix_fallocate64 (int __fd, __off64_t __offset, __off64_t __len); +# endif +#endif + +__END_DECLS + +#endif /* fcntl.h */ diff --git a/include/features.h b/include/features.h new file mode 100644 index 0000000..defdd04 --- /dev/null +++ b/include/features.h @@ -0,0 +1,425 @@ +/* Copyright (C) 1991-1993,1995-2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FEATURES_H +#define _FEATURES_H 1 + +/* This macro indicates that the installed library is uClibc. Use + * __UCLIBC_MAJOR__ and __UCLIBC_MINOR__ to test for the features in + * specific releases. */ +#define __UCLIBC__ 1 + +/* Load up the current set of uClibc supported features along + * with the current uClibc major and minor version numbers. + * For uClibc release 0.9.26, these numbers would be: + * #define __UCLIBC_MAJOR__ 0 + * #define __UCLIBC_MINOR__ 9 + * #define __UCLIBC_SUBLEVEL__ 26 + */ +#define __need_uClibc_config_h +#include +#undef __need_uClibc_config_h +#include + +/* For uClibc, always optimize for size -- this should disable + * a lot of expensive inlining... */ +#define __OPTIMIZE_SIZE__ 1 + +/* These are defined by the user (or the compiler) + to specify the desired environment: + + __STRICT_ANSI__ ISO Standard C. + _ISOC99_SOURCE Extensions to ISO C89 from ISO C99. + _POSIX_SOURCE IEEE Std 1003.1. + _POSIX_C_SOURCE If ==1, like _POSIX_SOURCE; if >=2 add IEEE Std 1003.2; + if >=199309L, add IEEE Std 1003.1b-1993; + if >=199506L, add IEEE Std 1003.1c-1995; + if >=200112L, all of IEEE 1003.1-2004 + _XOPEN_SOURCE Includes POSIX and XPG things. Set to 500 if + Single Unix conformance is wanted, to 600 for the + upcoming sixth revision. + _XOPEN_SOURCE_EXTENDED XPG things and X/Open Unix extensions. + _LARGEFILE_SOURCE Some more functions for correct standard I/O. + _LARGEFILE64_SOURCE Additional functionality from LFS for large files. + _FILE_OFFSET_BITS=N Select default filesystem interface. + _BSD_SOURCE ISO C, POSIX, and 4.3BSD things. + _SVID_SOURCE ISO C, POSIX, and SVID things. + _ATFILE_SOURCE Additional *at interfaces. + _GNU_SOURCE All of the above, plus GNU extensions. + _REENTRANT Select additionally reentrant object. + _THREAD_SAFE Same as _REENTRANT, often used by other systems. + _FORTIFY_SOURCE If set to numeric value > 0 additional security + measures are defined, according to level. + + The `-ansi' switch to the GNU C compiler defines __STRICT_ANSI__. + If none of these are defined, the default is to have _SVID_SOURCE, + _BSD_SOURCE, and _POSIX_SOURCE set to one and _POSIX_C_SOURCE set to + 199506L. If more than one of these are defined, they accumulate. + For example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE + together give you ISO C, 1003.1, and 1003.2, but nothing else. + + These are defined by this file and are used by the + header files to decide what to declare or define: + + __USE_ISOC99 Define ISO C99 things. + __USE_POSIX Define IEEE Std 1003.1 things. + __USE_POSIX2 Define IEEE Std 1003.2 things. + __USE_POSIX199309 Define IEEE Std 1003.1, and .1b things. + __USE_POSIX199506 Define IEEE Std 1003.1, .1b, .1c and .1i things. + __USE_XOPEN Define XPG things. + __USE_XOPEN_EXTENDED Define X/Open Unix things. + __USE_UNIX98 Define Single Unix V2 things. + __USE_XOPEN2K Define XPG6 things. + __USE_LARGEFILE Define correct standard I/O things. + __USE_LARGEFILE64 Define LFS things with separate names. + __USE_FILE_OFFSET64 Define 64bit interface as default. + __USE_BSD Define 4.3BSD things. + __USE_SVID Define SVID things. + __USE_MISC Define things common to BSD and System V Unix. + __USE_ATFILE Define *at interfaces and AT_* constants for them. + __USE_GNU Define GNU extensions. + __USE_REENTRANT Define reentrant/thread-safe *_r functions. + __USE_FORTIFY_LEVEL Additional security measures used, according to level. + __FAVOR_BSD Favor 4.3BSD things in cases of conflict. + + The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are + defined by this file unconditionally. `__GNU_LIBRARY__' is provided + only for compatibility. All new code should use the other symbols + to test for features. + + All macros listed above as possibly being defined by this file are + explicitly undefined if they are not explicitly defined. + Feature-test macros that are not defined by the user or compiler + but are implied by the other feature-test macros defined (or by the + lack of any definitions) are defined by the file. */ + + +/* Undefine everything, so we get a clean slate. */ +#undef __USE_ISOC99 +#undef __USE_POSIX +#undef __USE_POSIX2 +#undef __USE_POSIX199309 +#undef __USE_POSIX199506 +#undef __USE_XOPEN +#undef __USE_XOPEN_EXTENDED +#undef __USE_UNIX98 +#undef __USE_XOPEN2K +#undef __USE_LARGEFILE +#undef __USE_LARGEFILE64 +#undef __USE_FILE_OFFSET64 +#undef __USE_BSD +#undef __USE_SVID +#undef __USE_MISC +#undef __USE_ATFILE +#undef __USE_GNU +#undef __USE_REENTRANT +#undef __USE_FORTIFY_LEVEL +#undef __FAVOR_BSD +#undef __KERNEL_STRICT_NAMES + +/* Suppress kernel-name space pollution unless user expressedly asks + for it. */ +#ifndef _LOOSE_KERNEL_NAMES +# define __KERNEL_STRICT_NAMES +#endif + +/* Always use ISO C things. */ +#define __USE_ANSI 1 + +/* Convenience macros to test the versions of glibc and gcc. + Use them like this: + #if __GNUC_PREREQ (2,8) + ... code requiring gcc 2.8 or later ... + #endif + Note - they won't work for gcc1 or glibc1, since the _MINOR macros + were not defined then. */ +#if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +# define __GNUC_PREREQ(maj, min) 0 +#endif + + +/* If _BSD_SOURCE was defined by the user, favor BSD over POSIX. */ +#if defined _BSD_SOURCE && \ + !(defined _POSIX_SOURCE || defined _POSIX_C_SOURCE || \ + defined _XOPEN_SOURCE || defined _XOPEN_SOURCE_EXTENDED || \ + defined _GNU_SOURCE || defined _SVID_SOURCE) +# define __FAVOR_BSD 1 +#endif + +/* If _GNU_SOURCE was defined by the user, turn on all the other features. */ +#ifdef _GNU_SOURCE +# undef _ISOC99_SOURCE +# define _ISOC99_SOURCE 1 +# undef _POSIX_SOURCE +# define _POSIX_SOURCE 1 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 199506L +# undef _XOPEN_SOURCE +# define _XOPEN_SOURCE 600 +# undef _XOPEN_SOURCE_EXTENDED +# define _XOPEN_SOURCE_EXTENDED 1 +# ifdef __UCLIBC_HAS_LFS__ +# undef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE 1 +# endif /* __UCLIBC_HAS_LFS__ */ +# undef _BSD_SOURCE +# define _BSD_SOURCE 1 +# undef _SVID_SOURCE +# define _SVID_SOURCE 1 +# undef _ATFILE_SOURCE +# define _ATFILE_SOURCE 1 +#endif + +/* If nothing (other than _GNU_SOURCE) is defined, + define _BSD_SOURCE and _SVID_SOURCE. */ +#if (!defined __STRICT_ANSI__ && !defined _ISOC99_SOURCE && \ + !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE && \ + !defined _XOPEN_SOURCE && !defined _XOPEN_SOURCE_EXTENDED && \ + !defined _BSD_SOURCE && !defined _SVID_SOURCE) +# define _BSD_SOURCE 1 +# define _SVID_SOURCE 1 +#endif + +/* This is to enable the ISO C99 extension. Also recognize the old macro + which was used prior to the standard acceptance. This macro will + eventually go away and the features enabled by default once the ISO C99 + standard is widely adopted. */ +#if (defined _ISOC99_SOURCE || defined _ISOC9X_SOURCE \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) +# define __USE_ISOC99 1 +#endif + +/* If none of the ANSI/POSIX macros are defined, use POSIX.1 and POSIX.2 + (and IEEE Std 1003.1b-1993 unless _XOPEN_SOURCE is defined). */ +#if ((!defined __STRICT_ANSI__ || (_XOPEN_SOURCE - 0) >= 500) && \ + !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE) +# define _POSIX_SOURCE 1 +# if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) < 500 +# define _POSIX_C_SOURCE 2 +# else +# define _POSIX_C_SOURCE 199506L +# endif +#endif + +#if defined _POSIX_SOURCE || _POSIX_C_SOURCE >= 1 || defined _XOPEN_SOURCE +# define __USE_POSIX 1 +#endif + +#if defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 2 || defined _XOPEN_SOURCE +# define __USE_POSIX2 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 199309L +# define __USE_POSIX199309 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 199506L +# define __USE_POSIX199506 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 200112L +# define __USE_XOPEN2K 1 +#endif + +#ifdef _XOPEN_SOURCE +# define __USE_XOPEN 1 +# if (_XOPEN_SOURCE - 0) >= 500 +# define __USE_XOPEN_EXTENDED 1 +# define __USE_UNIX98 1 +# undef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# if (_XOPEN_SOURCE - 0) >= 600 +# define __USE_XOPEN2K 1 +# undef __USE_ISOC99 +# define __USE_ISOC99 1 +# endif +# else +# ifdef _XOPEN_SOURCE_EXTENDED +# define __USE_XOPEN_EXTENDED 1 +# endif +# endif +#endif + +#ifdef _LARGEFILE_SOURCE +# define __USE_LARGEFILE 1 +#endif + +#ifdef _LARGEFILE64_SOURCE +# define __USE_LARGEFILE64 1 +#endif + +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +# define __USE_FILE_OFFSET64 1 +#endif + +#if defined _BSD_SOURCE || defined _SVID_SOURCE +# define __USE_MISC 1 +#endif + +#ifdef _BSD_SOURCE +# define __USE_BSD 1 +#endif + +#ifdef _SVID_SOURCE +# define __USE_SVID 1 +#endif + +#ifdef _ATFILE_SOURCE +# define __USE_ATFILE 1 +#endif + +#ifdef _GNU_SOURCE +# define __USE_GNU 1 +#endif + +#if defined _REENTRANT || defined _THREAD_SAFE +# define __USE_REENTRANT 1 +#endif + +/* uClibc does not support _FORTIFY_SOURCE */ +#undef _FORTIFY_SOURCE +#if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 \ + && __GNUC_PREREQ (4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0 +# if _FORTIFY_SOURCE > 1 +# define __USE_FORTIFY_LEVEL 2 +# else +# define __USE_FORTIFY_LEVEL 1 +# endif +#else +# define __USE_FORTIFY_LEVEL 0 +#endif + +/* We do support the IEC 559 math functionality, real and complex. */ +#define __STDC_IEC_559__ 1 +#define __STDC_IEC_559_COMPLEX__ 1 + +#ifdef __UCLIBC_HAS_WCHAR__ +/* wchar_t uses ISO 10646-1 (2nd ed., published 2000-09-15) / Unicode 3.1. */ +# define __STDC_ISO_10646__ 200009L +#endif + +/* There is an unwholesomely huge amount of code out there that depends on the + * presence of GNU libc header files. We have GNU libc header files. So here + * we commit a horrible sin. At this point, we _lie_ and claim to be GNU libc + * to make things like /usr/include/linux/socket.h and lots of apps work as + * their developers intended. This is IMHO, pardonable, since these defines + * are not really intended to check for the presence of a particular library, + * but rather are used to define an _interface_. */ +#if !defined __FORCE_NOGLIBC && (!defined _LIBC || defined __FORCE_GLIBC) +/* This macro indicates that the installed library is the GNU C Library. + For historic reasons the value now is 6 and this will stay from now + on. The use of this variable is deprecated. */ +# undef __GNU_LIBRARY__ +# define __GNU_LIBRARY__ 6 + +/* Major and minor version number of the GNU C library package. Use + these macros to test for features in specific releases. */ +/* Don't do it, if you want to keep uClibc happy. */ +# define __GLIBC__ 2 +# define __GLIBC_MINOR__ 2 +#endif + +#define __GLIBC_PREREQ(maj, min) \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) + +#ifndef __UCLIBC__ +/* Decide whether a compiler supports the long long datatypes. */ +#if defined __GNUC__ \ + || (defined __PGI && defined __i386__ ) \ + || (defined __INTEL_COMPILER && (defined __i386__ || defined __ia64__)) \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) +# define __GLIBC_HAVE_LONG_LONG 1 +#endif +#endif + +/* This is here only because every header file already includes this one. */ +#ifndef __ASSEMBLER__ +# ifndef _SYS_CDEFS_H +# include +# endif + +/* If we don't have __REDIRECT, prototypes will be missing if + __USE_FILE_OFFSET64 but not __USE_LARGEFILE[64]. */ +# if defined __USE_FILE_OFFSET64 && !defined __REDIRECT +# define __USE_LARGEFILE 1 +# define __USE_LARGEFILE64 1 +# endif + +#endif /* !ASSEMBLER */ + +/* Decide whether we can define 'extern inline' functions in headers. */ +#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \ + && !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ \ + && (defined __extern_inline || defined __GNUC_GNU_INLINE__) +# define __USE_EXTERN_INLINES 1 +#endif + + +/* Make sure users large file options agree with uClibc's configuration. */ +#ifndef __UCLIBC_HAS_LFS__ + +/* If uClibc was built without large file support, output an error if + * 64-bit file offsets were requested. + * NOTE: This is probably incorrect on a 64-bit arch... */ +# ifdef __USE_FILE_OFFSET64 +# error It appears you have defined _FILE_OFFSET_BITS=64. Unfortunately, \ +uClibc was built without large file support enabled. +# endif + +/* If uClibc was built without large file support and _LARGEFILE64_SOURCE + * is defined, undefine it. */ +# ifdef _LARGEFILE64_SOURCE +# undef _LARGEFILE64_SOURCE +# undef __USE_LARGEFILE64 +# endif + +/* If we're actually building uClibc with large file support, + * define __USE_LARGEFILE64 and __USE_LARGEFILE. */ +#elif defined _LIBC +# undef _LARGEFILE_SOURCE +# undef _LARGEFILE64_SOURCE +# undef _FILE_OFFSET_BITS +# undef __USE_LARGEFILE +# undef __USE_LARGEFILE64 +# undef __USE_FILE_OFFSET64 +# define _LARGEFILE_SOURCE 1 +# define _LARGEFILE64_SOURCE 1 +# define __USE_LARGEFILE 1 +# define __USE_LARGEFILE64 1 +#endif + +/* uClibc does not support *at interfaces. */ +#undef _ATFILE_SOURCE +#undef __USE_ATFILE + +#ifdef _LIBC +# include +#endif + +/* Some people like to build up uClibc with *-elf toolchains, so + * a little grease here until we drop '#ifdef __linux__' checks + * from our source code. + */ +#ifndef __linux__ +# define __linux__ 1 +#endif + +#endif /* features.h */ diff --git a/include/fenv.h b/include/fenv.h new file mode 100644 index 0000000..8a06f02 --- /dev/null +++ b/include/fenv.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 7.6: Floating-point environment + */ + +#ifndef _FENV_H +#define _FENV_H 1 + +#include + +/* Get the architecture dependend definitions. The following definitions + are expected to be done: + + fenv_t type for object representing an entire floating-point + environment + + FE_DFL_ENV macro of type pointer to fenv_t to be used as the argument + to functions taking an argument of type fenv_t; in this + case the default environment will be used + + fexcept_t type for object representing the floating-point exception + flags including status associated with the flags + + The following macros are defined iff the implementation supports this + kind of exception. + FE_INEXACT inexact result + FE_DIVBYZERO division by zero + FE_UNDERFLOW result not representable due to underflow + FE_OVERFLOW result not representable due to overflow + FE_INVALID invalid operation + + FE_ALL_EXCEPT bitwise OR of all supported exceptions + + The next macros are defined iff the appropriate rounding mode is + supported by the implementation. + FE_TONEAREST round to nearest + FE_UPWARD round toward +Inf + FE_DOWNWARD round toward -Inf + FE_TOWARDZERO round toward 0 +*/ +#include + +__BEGIN_DECLS + +/* Floating-point exception handling. */ + +/* Clear the supported exceptions represented by EXCEPTS. */ +extern int feclearexcept (int __excepts) __THROW; + +/* Store implementation-defined representation of the exception flags + indicated by EXCEPTS in the object pointed to by FLAGP. */ +extern int fegetexceptflag (fexcept_t *__flagp, int __excepts) __THROW; + +/* Raise the supported exceptions represented by EXCEPTS. */ +extern int feraiseexcept (int __excepts) __THROW; + +/* Set complete status for exceptions indicated by EXCEPTS according to + the representation in the object pointed to by FLAGP. */ +extern int fesetexceptflag (__const fexcept_t *__flagp, int __excepts) __THROW; + +/* Determine which of subset of the exceptions specified by EXCEPTS are + currently set. */ +extern int fetestexcept (int __excepts) __THROW; + + +/* Rounding control. */ + +/* Get current rounding direction. */ +extern int fegetround (void) __THROW; + +/* Establish the rounding direction represented by ROUND. */ +extern int fesetround (int __rounding_direction) __THROW; + + +/* Floating-point environment. */ + +/* Store the current floating-point environment in the object pointed + to by ENVP. */ +extern int fegetenv (fenv_t *__envp) __THROW; + +/* Save the current environment in the object pointed to by ENVP, clear + exception flags and install a non-stop mode (if available) for all + exceptions. */ +extern int feholdexcept (fenv_t *__envp) __THROW; + +/* Establish the floating-point environment represented by the object + pointed to by ENVP. */ +extern int fesetenv (__const fenv_t *__envp) __THROW; + +/* Save current exceptions in temporary storage, install environment + represented by object pointed to by ENVP and raise exceptions + according to saved exceptions. */ +extern int feupdateenv (__const fenv_t *__envp) __THROW; + + +/* Include optimization. */ +#ifdef __OPTIMIZE__ +# include +#endif + +#ifdef __USE_GNU + +/* Enable individual exceptions. Will not enable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully set, otherwise returns -1. */ +extern int feenableexcept (int __excepts) __THROW; + +/* Disable individual exceptions. Will not disable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully disabled, otherwise returns -1. */ +extern int fedisableexcept (int __excepts) __THROW; + +/* Return enabled exceptions. */ +extern int fegetexcept (void) __THROW; +#endif + +__END_DECLS + +#endif /* fenv.h */ diff --git a/include/fnmatch.h b/include/fnmatch.h new file mode 100644 index 0000000..aefb007 --- /dev/null +++ b/include/fnmatch.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1991-93,96,97,98,99,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef const +# if (defined __STDC__ && __STDC__) || defined __cplusplus +# define __const const +# else +# define __const +# endif +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch (__const char *__pattern, __const char *__name, + int __flags); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/include/ftw.h b/include/ftw.h new file mode 100644 index 0000000..4bdff88 --- /dev/null +++ b/include/ftw.h @@ -0,0 +1,178 @@ +/* Copyright (C) 1992,1996-1999,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * X/Open Portability Guide 4.2: ftw.h + */ + +#ifndef _FTW_H +#define _FTW_H 1 + +#include + +#include +#include + + +__BEGIN_DECLS + +/* Values for the FLAG argument to the user function passed to `ftw' + and 'nftw'. */ +enum +{ + FTW_F, /* Regular file. */ +#define FTW_F FTW_F + FTW_D, /* Directory. */ +#define FTW_D FTW_D + FTW_DNR, /* Unreadable directory. */ +#define FTW_DNR FTW_DNR + FTW_NS, /* Unstatable file. */ +#define FTW_NS FTW_NS + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + + FTW_SL, /* Symbolic link. */ +# define FTW_SL FTW_SL +#endif + +#ifdef __USE_XOPEN_EXTENDED +/* These flags are only passed from the `nftw' function. */ + FTW_DP, /* Directory, all subdirs have been visited. */ +# define FTW_DP FTW_DP + FTW_SLN /* Symbolic link naming non-existing file. */ +# define FTW_SLN FTW_SLN + +#endif /* extended X/Open */ +}; + + +#ifdef __USE_XOPEN_EXTENDED +/* Flags for fourth argument of `nftw'. */ +enum +{ + FTW_PHYS = 1, /* Perform physical walk, ignore symlinks. */ +# define FTW_PHYS FTW_PHYS + FTW_MOUNT = 2, /* Report only files on same file system as the + argument. */ +# define FTW_MOUNT FTW_MOUNT + FTW_CHDIR = 4, /* Change to current directory while processing it. */ +# define FTW_CHDIR FTW_CHDIR + FTW_DEPTH = 8 /* Report files in directory before directory itself.*/ +# define FTW_DEPTH FTW_DEPTH +# ifdef __USE_GNU + , + FTW_ACTIONRETVAL = 16 /* Assume callback to return FTW_* values instead of + zero to continue and non-zero to terminate. */ +# define FTW_ACTIONRETVAL FTW_ACTIONRETVAL +# endif +}; + +#ifdef __USE_GNU +/* Return values from callback functions. */ +enum +{ + FTW_CONTINUE = 0, /* Continue with next sibling or for FTW_D with the + first child. */ +# define FTW_CONTINUE FTW_CONTINUE + FTW_STOP = 1, /* Return from `ftw' or `nftw' with FTW_STOP as return + value. */ +# define FTW_STOP FTW_STOP + FTW_SKIP_SUBTREE = 2, /* Only meaningful for FTW_D: Don't walk through the + subtree, instead just continue with its next + sibling. */ +# define FTW_SKIP_SUBTREE FTW_SKIP_SUBTREE + FTW_SKIP_SIBLINGS = 3,/* Continue with FTW_DP callback for current directory + (if FTW_DEPTH) and then its siblings. */ +# define FTW_SKIP_SIBLINGS FTW_SKIP_SIBLINGS +}; +#endif + +/* Structure used for fourth argument to callback function for `nftw'. */ +struct FTW + { + int base; + int level; + }; +#endif /* extended X/Open */ + + +/* Convenient types for callback functions. */ +typedef int (*__ftw_func_t) (__const char *__filename, + __const struct stat *__status, int __flag); +#ifdef __USE_LARGEFILE64 +typedef int (*__ftw64_func_t) (__const char *__filename, + __const struct stat64 *__status, int __flag); +#endif +#ifdef __USE_XOPEN_EXTENDED +typedef int (*__nftw_func_t) (__const char *__filename, + __const struct stat *__status, int __flag, + struct FTW *__info); +# ifdef __USE_LARGEFILE64 +typedef int (*__nftw64_func_t) (__const char *__filename, + __const struct stat64 *__status, + int __flag, struct FTW *__info); +# endif +#endif + +/* Call a function on every element in a directory tree. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int ftw (__const char *__dir, __ftw_func_t __func, int __descriptors) + __nonnull ((1, 2)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (ftw, (__const char *__dir, __ftw_func_t __func, + int __descriptors), ftw64) __nonnull ((1, 2)); +# else +# define ftw ftw64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int ftw64 (__const char *__dir, __ftw64_func_t __func, + int __descriptors) __nonnull ((1, 2)); +#endif + +#ifdef __USE_XOPEN_EXTENDED +/* Call a function on every element in a directory tree. FLAG allows + to specify the behaviour more detailed. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int nftw (__const char *__dir, __nftw_func_t __func, int __descriptors, + int __flag) __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (nftw, (__const char *__dir, __nftw_func_t __func, + int __descriptors, int __flag), nftw64) + __nonnull ((1, 2)); +# else +# define nftw nftw64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int nftw64 (__const char *__dir, __nftw64_func_t __func, + int __descriptors, int __flag) __nonnull ((1, 2)); +# endif +#endif + +__END_DECLS + +#endif /* ftw.h */ diff --git a/include/getopt.h b/include/getopt.h new file mode 100644 index 0000000..a682f9c --- /dev/null +++ b/include/getopt.h @@ -0,0 +1,4 @@ +/* This file will not be installed if not using gnu getopt. */ + +#include + diff --git a/include/glob.h b/include/glob.h new file mode 100644 index 0000000..68ea2cb --- /dev/null +++ b/include/glob.h @@ -0,0 +1,208 @@ +/* Copyright (C) 1991,92,95-98,2000,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GLOB_H +#define _GLOB_H 1 + +#include + +__BEGIN_DECLS + +/* We need `size_t' for the following definitions. */ +#ifndef __size_t +# if defined __GNUC__ && __GNUC__ >= 2 +typedef __SIZE_TYPE__ __size_t; +# ifdef __USE_XOPEN +typedef __SIZE_TYPE__ size_t; +# endif +# else +# include +# ifndef __size_t +# define __size_t size_t +# endif +# endif +#else +/* The GNU CC stddef.h version defines __size_t as empty. We need a real + definition. */ +# undef __size_t +# define __size_t size_t +#endif + +/* Bits set in the FLAGS argument to `glob'. */ +#define GLOB_ERR (1 << 0)/* Return on read errors. */ +#define GLOB_MARK (1 << 1)/* Append a slash to each name. */ +#define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ +#define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ +#define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ +#define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ +#define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ +#define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ + +#if ( !defined __USE_POSIX2 || defined __USE_BSD || defined __USE_GNU ) && defined __UCLIBC_HAS_GNU_GLOB__ +# define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ +#if 1 /* uClibc gnu glob does not support these */ +# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ +# define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ +# define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ +# define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ +# define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ +# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error + if the user name is not available. */ +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ + GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) +#else +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD) +#endif +#else +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD) +#endif + +/* Error returns from `glob'. */ +#define GLOB_NOSPACE 1 /* Ran out of memory. */ +#define GLOB_ABORTED 2 /* Read error. */ +#define GLOB_NOMATCH 3 /* No matches found. */ +#define GLOB_NOSYS 4 /* Not implemented. */ +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +/* Previous versions of this file defined GLOB_ABEND instead of + GLOB_ABORTED. Provide a compatibility definition here. */ +# define GLOB_ABEND GLOB_ABORTED +#endif + +/* Structure describing a globbing run. */ +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +struct stat; +#endif +typedef struct + { + __size_t gl_pathc; /* Count of paths matched by the pattern. */ + char **gl_pathv; /* List of matched pathnames. */ + __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ +#ifdef __UCLIBC_HAS_GNU_GLOB__ + int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ + +#if 1 /* uClibc gnu glob does not support these */ + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +#ifdef __USE_GNU + struct dirent *(*gl_readdir) (void *); +#else + void *(*gl_readdir) (void *); +#endif + void *(*gl_opendir) (__const char *); +#ifdef __USE_GNU + int (*gl_lstat) (__const char *__restrict, struct stat *__restrict); + int (*gl_stat) (__const char *__restrict, struct stat *__restrict); +#else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +#endif +#endif +#endif /* __UCLIBC_HAS_GNU_GLOB__ */ + } glob_t; + +#ifdef __USE_LARGEFILE64 +# if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +struct stat64; +# endif +typedef struct + { + __size_t gl_pathc; + char **gl_pathv; + __size_t gl_offs; +#ifdef __UCLIBC_HAS_GNU_GLOB__ + int gl_flags; + +#if 1 /* uClibc gnu glob does not support these */ + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +# ifdef __USE_GNU + struct dirent64 *(*gl_readdir) (void *); +# else + void *(*gl_readdir) (void *); +# endif + void *(*gl_opendir) (__const char *); +# ifdef __USE_GNU + int (*gl_lstat) (__const char *__restrict, struct stat64 *__restrict); + int (*gl_stat) (__const char *__restrict, struct stat64 *__restrict); +# else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +# endif +#endif +#endif /* __UCLIBC_HAS_GNU_GLOB__ */ + } glob64_t; +#endif + +#if defined(__USE_FILE_OFFSET64) && __GNUC__ < 2 +# define glob glob64 +# define globfree globfree64 +#endif + +/* Do glob searching for PATTERN, placing results in PGLOB. + The bits defined above may be set in FLAGS. + If a directory cannot be opened or read and ERRFUNC is not nil, + it is called with the pathname that caused the error, and the + `errno' value from the failing call; if it returns non-zero + `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +#if !defined __USE_FILE_OFFSET64 || __GNUC__ < 2 +extern int glob (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__restrict __pglob) __THROW; + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +extern void globfree (glob_t *__pglob) __THROW; +#else +extern int __REDIRECT_NTH (glob, (__const char *__restrict __pattern, + int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__restrict __pglob), glob64); + +extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); +#endif + +#ifdef __USE_LARGEFILE64 +extern int glob64 (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob64_t *__restrict __pglob) __THROW; + +extern void globfree64 (glob64_t *__pglob) __THROW; +#endif + + +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. + + This function is not part of the interface specified by POSIX.2 + but several programs want to use it. */ +extern int glob_pattern_p (__const char *__pattern, int __quote) __THROW; +#endif + +__END_DECLS + +#endif /* glob.h */ diff --git a/include/gnu-versions.h b/include/gnu-versions.h new file mode 100644 index 0000000..59e617c --- /dev/null +++ b/include/gnu-versions.h @@ -0,0 +1,53 @@ +/* Header with interface version macros for library pieces copied elsewhere. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_VERSIONS_H +#define _GNU_VERSIONS_H 1 + +/* This file exists to define these few macros. Each specifies a version + number associated with the library interface of a piece of the C library + which is also distributed with other GNU packages. These pieces are + both part of the GNU C library and also distributed with other GNU + packages so those packages may use their facilities on systems lacking + the GNU C library. The source files for each piece surround all their + code with `#ifndef ELIDE_CODE' after defining it with this: + + #define OBSTACK_INTERFACE_VERSION 1 + #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 + #include + #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION + #define ELIDE_CODE + #endif + #endif + + This allows those one to avoid compiling those files when part of a GNU + package not libc, on a system using a GNU C library that supports the + same interface. + + Please preserve the format of the comments after each macro. And + remember, if any of these versions change, the libc.so major version + number must change too (so avoid it)! */ + +#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */ +#define _GNU_REGEX_INTERFACE_VERSION 1 /* vs posix/regex.c */ +#define _GNU_GLOB_INTERFACE_VERSION 1 /* vs posix/glob.c */ +#define _GNU_GETOPT_INTERFACE_VERSION 2 /* vs posix/getopt.c and + posix/getopt1.c */ + +#endif /* gnu-versions.h */ diff --git a/include/grp.h b/include/grp.h new file mode 100644 index 0000000..fa381d2 --- /dev/null +++ b/include/grp.h @@ -0,0 +1,210 @@ +/* Copyright (C) 1991,1992,1995-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 9.2.1 Group Database Access + */ + +#ifndef _GRP_H +#define _GRP_H 1 + +#include + +__BEGIN_DECLS + +#include + +#define __need_size_t +#include + + +/* For the Single Unix specification we must define this type here. */ +#if (defined __USE_XOPEN || defined __USE_XOPEN2K) && !defined __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +/* The group structure. */ +struct group + { + char *gr_name; /* Group name. */ + char *gr_passwd; /* Password. */ + __gid_t gr_gid; /* Group ID. */ + char **gr_mem; /* Member list. */ + }; + + +#if defined __USE_SVID || defined __USE_GNU +# define __need_FILE +# include +#endif + + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Rewind the group-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setgrent (void); + +/* Close the group-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endgrent (void); + +/* Read an entry from the group-file stream, opening it if necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrent (void); +#endif + +#ifdef __USE_SVID +/* Read a group entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct group *fgetgrent (FILE *__stream); +#endif + +#ifdef __USE_GNU +/* Write the given entry onto the given stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putgrent (__const struct group *__restrict __p, + FILE *__restrict __f); +#endif + +/* Search for an entry with a matching group ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrgid (__gid_t __gid); + +/* Search for an entry with a matching group name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrnam (__const char *__name); + +#if defined __USE_POSIX || defined __USE_MISC + +# ifdef __USE_MISC +/* Reasonable value for the buffer sized used in the reentrant + functions below. But better use `sysconf'. */ +# define NSS_BUFLEN_GROUP 1024 +# endif + +/* Reentrant versions of some of the functions above. + + PLEASE NOTE: the `getgrent_r' function is not (yet) standardized. + The interface may change in later versions of this library. But + the interface is designed following the principals used for the + other reentrant functions so the chances are good this is what the + POSIX people would choose. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ + +# ifdef __USE_GNU +extern int getgrent_r (struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +# endif + +/* Search for an entry with a matching group ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getgrgid_r (__gid_t __gid, struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); + +/* Search for an entry with a matching group name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getgrnam_r (__const char *__restrict __name, + struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); + +# ifdef __USE_SVID +/* Read a group entry from STREAM. This function is not standardized + an probably never will. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetgrent_r (FILE *__restrict __stream, + struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +# endif + +#endif /* POSIX or reentrant */ + + +#if defined __USE_BSD || defined __USE_GNU + +# define __need_size_t +# include + +/* Store at most *NGROUPS members of the group set for USER into + *GROUPS. Also include GROUP. The actual number of groups found is + returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. + In all cases the actual number of groups is stored in *NGROUPS. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getgrouplist (__const char *__user, __gid_t __group, + __gid_t *__groups, int *__ngroups); + +#endif + +#if defined __USE_BSD + +/* Set the group set for the current user to GROUPS (N of them). */ +extern int setgroups (size_t __n, __const __gid_t *__groups) __THROW; + +/* Initialize the group set for the current user + by reading the group database and using all groups + of which USER is a member. Also include GROUP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int initgroups (__const char *__user, __gid_t __group); + +#endif /* Use BSD. */ + +__END_DECLS + +#endif /* grp.h */ diff --git a/include/iconv.h b/include/iconv.h new file mode 100644 index 0000000..0a19c04 --- /dev/null +++ b/include/iconv.h @@ -0,0 +1,60 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ICONV_H +#define _ICONV_H 1 + +#include +#define __need_size_t +#include + +#ifndef __UCLIBC_HAS_LOCALE__ +#error Attempted to include iconv.h when uClibc was built without locale support. +#endif + + +__BEGIN_DECLS + +/* Identifier for conversion method from one codeset to another. */ +typedef void *iconv_t; + + +/* Allocate descriptor for code conversion from codeset FROMCODE to + codeset TOCODE. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode); + +/* Convert at most *INBYTESLEFT bytes from *INBUF according to the + code conversion algorithm specified by CD and place up to + *OUTBYTESLEFT bytes in buffer at *OUTBUF. */ +extern size_t iconv (iconv_t __cd, char **__restrict __inbuf, + size_t *__restrict __inbytesleft, + char **__restrict __outbuf, + size_t *__restrict __outbytesleft); + +/* Free resources allocated for descriptor CD for code conversion. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int iconv_close (iconv_t __cd); + +__END_DECLS + +#endif /* iconv.h */ diff --git a/include/ieee754.h b/include/ieee754.h new file mode 100644 index 0000000..7131e5d --- /dev/null +++ b/include/ieee754.h @@ -0,0 +1,199 @@ +/* Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _IEEE754_H + +#define _IEEE754_H 1 +#include + +#include + +__BEGIN_DECLS + +union ieee754_float + { + float f; + + /* This is the IEEE 754 single-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee_nan; + }; + +#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ + + +union ieee754_double + { + double d; + + /* This is the IEEE 754 double-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == BIG_ENDIAN + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else +# if __FLOAT_WORD_ORDER == BIG_ENDIAN + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif + } ieee_nan; + }; + +#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ + + +union ieee854_long_double + { + long double d; + + /* This is the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:32; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee; + + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int one:1; + unsigned int quiet_nan:1; + unsigned int mantissa0:30; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee_nan; + }; + +#define IEEE854_LONG_DOUBLE_BIAS 0x3fff + +__END_DECLS + +#endif /* ieee754.h */ diff --git a/include/ifaddrs.h b/include/ifaddrs.h new file mode 100644 index 0000000..ba6a155 --- /dev/null +++ b/include/ifaddrs.h @@ -0,0 +1,74 @@ +/* ifaddrs.h -- declarations for getting network interface addresses + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _IFADDRS_H +#define _IFADDRS_H 1 + +#include +#include + +__BEGIN_DECLS + +/* The `getifaddrs' function generates a linked list of these structures. + Each element of the list describes one network interface. */ +struct ifaddrs +{ + struct ifaddrs *ifa_next; /* Pointer to the next structure. */ + + char *ifa_name; /* Name of this network interface. */ + unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */ + + struct sockaddr *ifa_addr; /* Network address of this interface. */ + struct sockaddr *ifa_netmask; /* Netmask of this interface. */ + union + { + /* At most one of the following two is valid. If the IFF_BROADCAST + bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the + IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid. + It is never the case that both these bits are set at once. */ + struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */ + struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */ + } ifa_ifu; + /* These very same macros are defined by for `struct ifaddr'. + So if they are defined already, the existing definitions will be fine. */ +# ifndef ifa_broadaddr +# define ifa_broadaddr ifa_ifu.ifu_broadaddr +# endif +# ifndef ifa_dstaddr +# define ifa_dstaddr ifa_ifu.ifu_dstaddr +# endif + + void *ifa_data; /* Address-specific data (may be unused). */ +}; + + +/* Create a linked list of `struct ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. + + The storage returned in *IFAP is allocated dynamically and can + only be properly freed by passing it to `freeifaddrs'. */ +extern int getifaddrs (struct ifaddrs **__ifap) __THROW; + +/* Reclaim the storage allocated by a previous `getifaddrs' call. */ +extern void freeifaddrs (struct ifaddrs *__ifa) __THROW; + +__END_DECLS + +#endif /* ifaddrs.h */ diff --git a/include/inttypes.h b/include/inttypes.h new file mode 100644 index 0000000..b1d4302 --- /dev/null +++ b/include/inttypes.h @@ -0,0 +1,328 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.8 Format conversion of integer types + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H 1 + +#include +/* Get the type definitions. */ +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +/* Get a definition for wchar_t. But we must not define wchar_t itself. */ +#ifndef ____gwchar_t_defined +# ifdef __cplusplus +# define __gwchar_t wchar_t +# elif defined __WCHAR_TYPE__ +typedef __WCHAR_TYPE__ __gwchar_t; +# else +# define __need_wchar_t +# include +typedef wchar_t __gwchar_t; +# endif +# define ____gwchar_t_defined 1 +#endif +#endif + + +/* The ISO C99 standard specifies that these macros must only be + defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_FORMAT_MACROS + +# if __WORDSIZE == 64 +# define __PRI64_PREFIX "l" +# define __PRIPTR_PREFIX "l" +# else +# define __PRI64_PREFIX "ll" +# define __PRIPTR_PREFIX +# endif + +/* Macros for printing format specifiers. */ + +/* Decimal notation. */ +# define PRId8 "d" +# define PRId16 "d" +# define PRId32 "d" +# define PRId64 __PRI64_PREFIX "d" + +# define PRIdLEAST8 "d" +# define PRIdLEAST16 "d" +# define PRIdLEAST32 "d" +# define PRIdLEAST64 __PRI64_PREFIX "d" + +# define PRIdFAST8 "d" +# define PRIdFAST16 "d" +# define PRIdFAST32 "d" +# define PRIdFAST64 __PRI64_PREFIX "d" + + +# define PRIi8 "i" +# define PRIi16 "i" +# define PRIi32 "i" +# define PRIi64 __PRI64_PREFIX "i" + +# define PRIiLEAST8 "i" +# define PRIiLEAST16 "i" +# define PRIiLEAST32 "i" +# define PRIiLEAST64 __PRI64_PREFIX "i" + +# define PRIiFAST8 "i" +# define PRIiFAST16 "i" +# define PRIiFAST32 "i" +# define PRIiFAST64 __PRI64_PREFIX "i" + +/* Octal notation. */ +# define PRIo8 "o" +# define PRIo16 "o" +# define PRIo32 "o" +# define PRIo64 __PRI64_PREFIX "o" + +# define PRIoLEAST8 "o" +# define PRIoLEAST16 "o" +# define PRIoLEAST32 "o" +# define PRIoLEAST64 __PRI64_PREFIX "o" + +# define PRIoFAST8 "o" +# define PRIoFAST16 "o" +# define PRIoFAST32 "o" +# define PRIoFAST64 __PRI64_PREFIX "o" + +/* Unsigned integers. */ +# define PRIu8 "u" +# define PRIu16 "u" +# define PRIu32 "u" +# define PRIu64 __PRI64_PREFIX "u" + +# define PRIuLEAST8 "u" +# define PRIuLEAST16 "u" +# define PRIuLEAST32 "u" +# define PRIuLEAST64 __PRI64_PREFIX "u" + +# define PRIuFAST8 "u" +# define PRIuFAST16 "u" +# define PRIuFAST32 "u" +# define PRIuFAST64 __PRI64_PREFIX "u" + +/* lowercase hexadecimal notation. */ +# define PRIx8 "x" +# define PRIx16 "x" +# define PRIx32 "x" +# define PRIx64 __PRI64_PREFIX "x" + +# define PRIxLEAST8 "x" +# define PRIxLEAST16 "x" +# define PRIxLEAST32 "x" +# define PRIxLEAST64 __PRI64_PREFIX "x" + +# define PRIxFAST8 "x" +# define PRIxFAST16 "x" +# define PRIxFAST32 "x" +# define PRIxFAST64 __PRI64_PREFIX "x" + +/* UPPERCASE hexadecimal notation. */ +# define PRIX8 "X" +# define PRIX16 "X" +# define PRIX32 "X" +# define PRIX64 __PRI64_PREFIX "X" + +# define PRIXLEAST8 "X" +# define PRIXLEAST16 "X" +# define PRIXLEAST32 "X" +# define PRIXLEAST64 __PRI64_PREFIX "X" + +# define PRIXFAST8 "X" +# define PRIXFAST16 "X" +# define PRIXFAST32 "X" +# define PRIXFAST64 __PRI64_PREFIX "X" + + +/* Macros for printing `intmax_t' and `uintmax_t'. */ +# define PRIdMAX __PRI64_PREFIX "d" +# define PRIiMAX __PRI64_PREFIX "i" +# define PRIoMAX __PRI64_PREFIX "o" +# define PRIuMAX __PRI64_PREFIX "u" +# define PRIxMAX __PRI64_PREFIX "x" +# define PRIXMAX __PRI64_PREFIX "X" + + +/* Macros for printing `intptr_t' and `uintptr_t'. */ +# define PRIdPTR __PRIPTR_PREFIX "d" +# define PRIiPTR __PRIPTR_PREFIX "i" +# define PRIoPTR __PRIPTR_PREFIX "o" +# define PRIuPTR __PRIPTR_PREFIX "u" +# define PRIxPTR __PRIPTR_PREFIX "x" +# define PRIXPTR __PRIPTR_PREFIX "X" + + +/* Macros for scanning format specifiers. */ + +/* Signed decimal notation. */ +# define SCNd8 "hhd" +# define SCNd16 "hd" +# define SCNd32 "d" +# define SCNd64 __PRI64_PREFIX "d" + +# define SCNdLEAST8 "hhd" +# define SCNdLEAST16 "hd" +# define SCNdLEAST32 "d" +# define SCNdLEAST64 __PRI64_PREFIX "d" + +# define SCNdFAST8 "hhd" +# define SCNdFAST16 __PRIPTR_PREFIX "d" +# define SCNdFAST32 __PRIPTR_PREFIX "d" +# define SCNdFAST64 __PRI64_PREFIX "d" + +/* Signed decimal notation. */ +# define SCNi8 "hhi" +# define SCNi16 "hi" +# define SCNi32 "i" +# define SCNi64 __PRI64_PREFIX "i" + +# define SCNiLEAST8 "hhi" +# define SCNiLEAST16 "hi" +# define SCNiLEAST32 "i" +# define SCNiLEAST64 __PRI64_PREFIX "i" + +# define SCNiFAST8 "hhi" +# define SCNiFAST16 __PRIPTR_PREFIX "i" +# define SCNiFAST32 __PRIPTR_PREFIX "i" +# define SCNiFAST64 __PRI64_PREFIX "i" + +/* Unsigned decimal notation. */ +# define SCNu8 "hhu" +# define SCNu16 "hu" +# define SCNu32 "u" +# define SCNu64 __PRI64_PREFIX "u" + +# define SCNuLEAST8 "hhu" +# define SCNuLEAST16 "hu" +# define SCNuLEAST32 "u" +# define SCNuLEAST64 __PRI64_PREFIX "u" + +# define SCNuFAST8 "hhu" +# define SCNuFAST16 __PRIPTR_PREFIX "u" +# define SCNuFAST32 __PRIPTR_PREFIX "u" +# define SCNuFAST64 __PRI64_PREFIX "u" + +/* Octal notation. */ +# define SCNo8 "hho" +# define SCNo16 "ho" +# define SCNo32 "o" +# define SCNo64 __PRI64_PREFIX "o" + +# define SCNoLEAST8 "hho" +# define SCNoLEAST16 "ho" +# define SCNoLEAST32 "o" +# define SCNoLEAST64 __PRI64_PREFIX "o" + +# define SCNoFAST8 "hho" +# define SCNoFAST16 __PRIPTR_PREFIX "o" +# define SCNoFAST32 __PRIPTR_PREFIX "o" +# define SCNoFAST64 __PRI64_PREFIX "o" + +/* Hexadecimal notation. */ +# define SCNx8 "hhx" +# define SCNx16 "hx" +# define SCNx32 "x" +# define SCNx64 __PRI64_PREFIX "x" + +# define SCNxLEAST8 "hhx" +# define SCNxLEAST16 "hx" +# define SCNxLEAST32 "x" +# define SCNxLEAST64 __PRI64_PREFIX "x" + +# define SCNxFAST8 "hhx" +# define SCNxFAST16 __PRIPTR_PREFIX "x" +# define SCNxFAST32 __PRIPTR_PREFIX "x" +# define SCNxFAST64 __PRI64_PREFIX "x" + + +/* Macros for scanning `intmax_t' and `uintmax_t'. */ +# define SCNdMAX __PRI64_PREFIX "d" +# define SCNiMAX __PRI64_PREFIX "i" +# define SCNoMAX __PRI64_PREFIX "o" +# define SCNuMAX __PRI64_PREFIX "u" +# define SCNxMAX __PRI64_PREFIX "x" + +/* Macros for scaning `intptr_t' and `uintptr_t'. */ +# define SCNdPTR __PRIPTR_PREFIX "d" +# define SCNiPTR __PRIPTR_PREFIX "i" +# define SCNoPTR __PRIPTR_PREFIX "o" +# define SCNuPTR __PRIPTR_PREFIX "u" +# define SCNxPTR __PRIPTR_PREFIX "x" + +#endif /* C++ && format macros */ + + +__BEGIN_DECLS + +#if __WORDSIZE == 64 + +/* We have to define the `uintmax_t' type using `ldiv_t'. */ +typedef struct + { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ + } imaxdiv_t; + +#else + +/* We have to define the `uintmax_t' type using `lldiv_t'. */ +typedef struct + { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ + } imaxdiv_t; + +#endif + + +/* Compute absolute value of N. */ +extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__)); + +/* Return the `imaxdiv_t' representation of the value of NUMER over DENOM. */ +extern imaxdiv_t imaxdiv (intmax_t __numer, intmax_t __denom) + __THROW __attribute__ ((__const__)); + +/* Like `strtol' but convert to `intmax_t'. */ +extern intmax_t strtoimax (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) __THROW; + +/* Like `strtoul' but convert to `uintmax_t'. */ +extern uintmax_t strtoumax (__const char *__restrict __nptr, + char ** __restrict __endptr, int __base) __THROW; + +#if defined __UCLIBC_HAS_WCHAR__ && __UCLIBC_HAS_WCHAR__ +/* Like `wcstol' but convert to `intmax_t'. */ +extern intmax_t wcstoimax (__const __gwchar_t *__restrict __nptr, + __gwchar_t **__restrict __endptr, int __base) + __THROW; + +/* Like `wcstoul' but convert to `uintmax_t'. */ +extern uintmax_t wcstoumax (__const __gwchar_t *__restrict __nptr, + __gwchar_t ** __restrict __endptr, int __base) + __THROW; +#endif + +__END_DECLS + +#endif /* inttypes.h */ diff --git a/include/langinfo.h b/include/langinfo.h new file mode 100644 index 0000000..12f0080 --- /dev/null +++ b/include/langinfo.h @@ -0,0 +1,623 @@ +/* Access to locale-dependent parameters. + Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LANGINFO_H +#define _LANGINFO_H 1 + +/* Get the type definition. */ +#include + +#include /* Define the __LC_* category names. */ + + +__BEGIN_DECLS + +/* Construct an `nl_item' value for `nl_langinfo' from a locale category + (LC_*) and an item index within the category. Some code may depend on + the item values within a category increasing monotonically with the + indices. */ +#define _NL_ITEM(category, index) \ + (((category) << __NL_ITEM_CATEGORY_SHIFT) | (index)) + +/* Extract the category and item index from a constructed `nl_item' value. */ +#define _NL_ITEM_CATEGORY(item) ((int) (item) >> __NL_ITEM_CATEGORY_SHIFT) +#define _NL_ITEM_INDEX(item) ((int) (item) & __NL_ITEM_INDEX_MASK) + + +/* Enumeration of locale items that can be queried with `nl_langinfo'. */ +enum +{ + /* LC_TIME category: date and time formatting. */ + + /* Abbreviated days of the week. */ + ABDAY_1 = _NL_ITEM (__LC_TIME, 0), /* Sun */ +#define ABDAY_1 ABDAY_1 + ABDAY_2, +#define ABDAY_2 ABDAY_2 + ABDAY_3, +#define ABDAY_3 ABDAY_3 + ABDAY_4, +#define ABDAY_4 ABDAY_4 + ABDAY_5, +#define ABDAY_5 ABDAY_5 + ABDAY_6, +#define ABDAY_6 ABDAY_6 + ABDAY_7, +#define ABDAY_7 ABDAY_7 + + /* Long-named days of the week. */ + DAY_1, /* Sunday */ +#define DAY_1 DAY_1 + DAY_2, /* Monday */ +#define DAY_2 DAY_2 + DAY_3, /* Tuesday */ +#define DAY_3 DAY_3 + DAY_4, /* Wednesday */ +#define DAY_4 DAY_4 + DAY_5, /* Thursday */ +#define DAY_5 DAY_5 + DAY_6, /* Friday */ +#define DAY_6 DAY_6 + DAY_7, /* Saturday */ +#define DAY_7 DAY_7 + + /* Abbreviated month names. */ + ABMON_1, /* Jan */ +#define ABMON_1 ABMON_1 + ABMON_2, +#define ABMON_2 ABMON_2 + ABMON_3, +#define ABMON_3 ABMON_3 + ABMON_4, +#define ABMON_4 ABMON_4 + ABMON_5, +#define ABMON_5 ABMON_5 + ABMON_6, +#define ABMON_6 ABMON_6 + ABMON_7, +#define ABMON_7 ABMON_7 + ABMON_8, +#define ABMON_8 ABMON_8 + ABMON_9, +#define ABMON_9 ABMON_9 + ABMON_10, +#define ABMON_10 ABMON_10 + ABMON_11, +#define ABMON_11 ABMON_11 + ABMON_12, +#define ABMON_12 ABMON_12 + + /* Long month names. */ + MON_1, /* January */ +#define MON_1 MON_1 + MON_2, +#define MON_2 MON_2 + MON_3, +#define MON_3 MON_3 + MON_4, +#define MON_4 MON_4 + MON_5, +#define MON_5 MON_5 + MON_6, +#define MON_6 MON_6 + MON_7, +#define MON_7 MON_7 + MON_8, +#define MON_8 MON_8 + MON_9, +#define MON_9 MON_9 + MON_10, +#define MON_10 MON_10 + MON_11, +#define MON_11 MON_11 + MON_12, +#define MON_12 MON_12 + + AM_STR, /* Ante meridian string. */ +#define AM_STR AM_STR + PM_STR, /* Post meridian string. */ +#define PM_STR PM_STR + + D_T_FMT, /* Date and time format for strftime. */ +#define D_T_FMT D_T_FMT + D_FMT, /* Date format for strftime. */ +#define D_FMT D_FMT + T_FMT, /* Time format for strftime. */ +#define T_FMT T_FMT + T_FMT_AMPM, /* 12-hour time format for strftime. */ +#define T_FMT_AMPM T_FMT_AMPM + + ERA, /* Alternate era. */ +#define ERA ERA + __ERA_YEAR, /* Year in alternate era format. */ +#ifdef __USE_GNU +# define ERA_YEAR __ERA_YEAR +#endif + ERA_D_FMT, /* Date in alternate era format. */ +#define ERA_D_FMT ERA_D_FMT + ALT_DIGITS, /* Alternate symbols for digits. */ +#define ALT_DIGITS ALT_DIGITS + ERA_D_T_FMT, /* Date and time in alternate era format. */ +#define ERA_D_T_FMT ERA_D_T_FMT + ERA_T_FMT, /* Time in alternate era format. */ +#define ERA_T_FMT ERA_T_FMT + +#if 0 + _NL_TIME_ERA_NUM_ENTRIES, /* Number entries in the era arrays. */ + _NL_TIME_ERA_ENTRIES, /* Structure with era entries in usable form.*/ + + _NL_WABDAY_1, /* Sun */ + _NL_WABDAY_2, + _NL_WABDAY_3, + _NL_WABDAY_4, + _NL_WABDAY_5, + _NL_WABDAY_6, + _NL_WABDAY_7, + + /* Long-named days of the week. */ + _NL_WDAY_1, /* Sunday */ + _NL_WDAY_2, /* Monday */ + _NL_WDAY_3, /* Tuesday */ + _NL_WDAY_4, /* Wednesday */ + _NL_WDAY_5, /* Thursday */ + _NL_WDAY_6, /* Friday */ + _NL_WDAY_7, /* Saturday */ + + /* Abbreviated month names. */ + _NL_WABMON_1, /* Jan */ + _NL_WABMON_2, + _NL_WABMON_3, + _NL_WABMON_4, + _NL_WABMON_5, + _NL_WABMON_6, + _NL_WABMON_7, + _NL_WABMON_8, + _NL_WABMON_9, + _NL_WABMON_10, + _NL_WABMON_11, + _NL_WABMON_12, + + /* Long month names. */ + _NL_WMON_1, /* January */ + _NL_WMON_2, + _NL_WMON_3, + _NL_WMON_4, + _NL_WMON_5, + _NL_WMON_6, + _NL_WMON_7, + _NL_WMON_8, + _NL_WMON_9, + _NL_WMON_10, + _NL_WMON_11, + _NL_WMON_12, + + _NL_WAM_STR, /* Ante meridian string. */ + _NL_WPM_STR, /* Post meridian string. */ + + _NL_WD_T_FMT, /* Date and time format for strftime. */ + _NL_WD_FMT, /* Date format for strftime. */ + _NL_WT_FMT, /* Time format for strftime. */ + _NL_WT_FMT_AMPM, /* 12-hour time format for strftime. */ + + _NL_WERA_YEAR, /* Year in alternate era format. */ + _NL_WERA_D_FMT, /* Date in alternate era format. */ + _NL_WALT_DIGITS, /* Alternate symbols for digits. */ + _NL_WERA_D_T_FMT, /* Date and time in alternate era format. */ + _NL_WERA_T_FMT, /* Time in alternate era format. */ + + _NL_TIME_WEEK_NDAYS, + _NL_TIME_WEEK_1STDAY, + _NL_TIME_WEEK_1STWEEK, + _NL_TIME_FIRST_WEEKDAY, + _NL_TIME_FIRST_WORKDAY, + _NL_TIME_CAL_DIRECTION, + _NL_TIME_TIMEZONE, + + _DATE_FMT, /* strftime format for date. */ +#define _DATE_FMT _DATE_FMT + _NL_W_DATE_FMT, + + _NL_TIME_CODESET, +#endif /* 0 */ + + _NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */ + + /* LC_COLLATE category: text sorting. + This information is accessed by the strcoll and strxfrm functions. + These `nl_langinfo' names are used only internally. */ +#if 0 + _NL_COLLATE_NRULES = _NL_ITEM (__LC_COLLATE, 0), + _NL_COLLATE_RULESETS, + _NL_COLLATE_TABLEMB, + _NL_COLLATE_WEIGHTMB, + _NL_COLLATE_EXTRAMB, + _NL_COLLATE_INDIRECTMB, + _NL_COLLATE_GAP1, + _NL_COLLATE_GAP2, + _NL_COLLATE_GAP3, + _NL_COLLATE_TABLEWC, + _NL_COLLATE_WEIGHTWC, + _NL_COLLATE_EXTRAWC, + _NL_COLLATE_INDIRECTWC, + _NL_COLLATE_SYMB_HASH_SIZEMB, + _NL_COLLATE_SYMB_TABLEMB, + _NL_COLLATE_SYMB_EXTRAMB, + _NL_COLLATE_COLLSEQMB, + _NL_COLLATE_COLLSEQWC, + _NL_COLLATE_CODESET, + _NL_NUM_LC_COLLATE, +#endif + + /* LC_CTYPE category: character classification. + This information is accessed by the functions in . + These `nl_langinfo' names are used only internally. */ +#if 0 + _NL_CTYPE_CLASS = _NL_ITEM (__LC_CTYPE, 0), + _NL_CTYPE_TOUPPER, + _NL_CTYPE_GAP1, + _NL_CTYPE_TOLOWER, + _NL_CTYPE_GAP2, + _NL_CTYPE_CLASS32, + _NL_CTYPE_GAP3, + _NL_CTYPE_GAP4, + _NL_CTYPE_GAP5, + _NL_CTYPE_GAP6, + _NL_CTYPE_CLASS_NAMES, + _NL_CTYPE_MAP_NAMES, + _NL_CTYPE_WIDTH, + _NL_CTYPE_MB_CUR_MAX, + _NL_CTYPE_CODESET_NAME, + CODESET = _NL_CTYPE_CODESET_NAME, +#define CODESET CODESET + _NL_CTYPE_TOUPPER32, + _NL_CTYPE_TOLOWER32, + _NL_CTYPE_CLASS_OFFSET, + _NL_CTYPE_MAP_OFFSET, + _NL_CTYPE_INDIGITS_MB_LEN, + _NL_CTYPE_INDIGITS0_MB, + _NL_CTYPE_INDIGITS1_MB, + _NL_CTYPE_INDIGITS2_MB, + _NL_CTYPE_INDIGITS3_MB, + _NL_CTYPE_INDIGITS4_MB, + _NL_CTYPE_INDIGITS5_MB, + _NL_CTYPE_INDIGITS6_MB, + _NL_CTYPE_INDIGITS7_MB, + _NL_CTYPE_INDIGITS8_MB, + _NL_CTYPE_INDIGITS9_MB, + _NL_CTYPE_INDIGITS_WC_LEN, + _NL_CTYPE_INDIGITS0_WC, + _NL_CTYPE_INDIGITS1_WC, + _NL_CTYPE_INDIGITS2_WC, + _NL_CTYPE_INDIGITS3_WC, + _NL_CTYPE_INDIGITS4_WC, + _NL_CTYPE_INDIGITS5_WC, + _NL_CTYPE_INDIGITS6_WC, + _NL_CTYPE_INDIGITS7_WC, + _NL_CTYPE_INDIGITS8_WC, + _NL_CTYPE_INDIGITS9_WC, + _NL_CTYPE_OUTDIGIT0_MB, + _NL_CTYPE_OUTDIGIT1_MB, + _NL_CTYPE_OUTDIGIT2_MB, + _NL_CTYPE_OUTDIGIT3_MB, + _NL_CTYPE_OUTDIGIT4_MB, + _NL_CTYPE_OUTDIGIT5_MB, + _NL_CTYPE_OUTDIGIT6_MB, + _NL_CTYPE_OUTDIGIT7_MB, + _NL_CTYPE_OUTDIGIT8_MB, + _NL_CTYPE_OUTDIGIT9_MB, + _NL_CTYPE_OUTDIGIT0_WC, + _NL_CTYPE_OUTDIGIT1_WC, + _NL_CTYPE_OUTDIGIT2_WC, + _NL_CTYPE_OUTDIGIT3_WC, + _NL_CTYPE_OUTDIGIT4_WC, + _NL_CTYPE_OUTDIGIT5_WC, + _NL_CTYPE_OUTDIGIT6_WC, + _NL_CTYPE_OUTDIGIT7_WC, + _NL_CTYPE_OUTDIGIT8_WC, + _NL_CTYPE_OUTDIGIT9_WC, + _NL_CTYPE_TRANSLIT_TAB_SIZE, + _NL_CTYPE_TRANSLIT_FROM_IDX, + _NL_CTYPE_TRANSLIT_FROM_TBL, + _NL_CTYPE_TRANSLIT_TO_IDX, + _NL_CTYPE_TRANSLIT_TO_TBL, + _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN, + _NL_CTYPE_TRANSLIT_DEFAULT_MISSING, + _NL_CTYPE_TRANSLIT_IGNORE_LEN, + _NL_CTYPE_TRANSLIT_IGNORE, + _NL_CTYPE_EXTRA_MAP_1, + _NL_CTYPE_EXTRA_MAP_2, + _NL_CTYPE_EXTRA_MAP_3, + _NL_CTYPE_EXTRA_MAP_4, + _NL_CTYPE_EXTRA_MAP_5, + _NL_CTYPE_EXTRA_MAP_6, + _NL_CTYPE_EXTRA_MAP_7, + _NL_CTYPE_EXTRA_MAP_8, + _NL_CTYPE_EXTRA_MAP_9, + _NL_CTYPE_EXTRA_MAP_10, + _NL_CTYPE_EXTRA_MAP_11, + _NL_CTYPE_EXTRA_MAP_12, + _NL_CTYPE_EXTRA_MAP_13, + _NL_CTYPE_EXTRA_MAP_14, +#else /* 0 */ + _NL_CTYPE_OUTDIGIT0_MB = _NL_ITEM (__LC_CTYPE, 0), + _NL_CTYPE_OUTDIGIT1_MB, + _NL_CTYPE_OUTDIGIT2_MB, + _NL_CTYPE_OUTDIGIT3_MB, + _NL_CTYPE_OUTDIGIT4_MB, + _NL_CTYPE_OUTDIGIT5_MB, + _NL_CTYPE_OUTDIGIT6_MB, + _NL_CTYPE_OUTDIGIT7_MB, + _NL_CTYPE_OUTDIGIT8_MB, + _NL_CTYPE_OUTDIGIT9_MB, + _NL_CTYPE_CODESET_NAME, /* uClibc note: MUST BE LAST ENTRY!!! */ + CODESET = _NL_CTYPE_CODESET_NAME, +#define CODESET CODESET +#endif /* 0 */ + _NL_NUM_LC_CTYPE, + + /* LC_MONETARY category: formatting of monetary quantities. + These items each correspond to a member of `struct lconv', + defined in . */ + __INT_CURR_SYMBOL = _NL_ITEM (__LC_MONETARY, 0), +#ifdef __USE_GNU +# define INT_CURR_SYMBOL __INT_CURR_SYMBOL +#endif + __CURRENCY_SYMBOL, +#ifdef __USE_GNU +# define CURRENCY_SYMBOL __CURRENCY_SYMBOL +#endif + __MON_DECIMAL_POINT, +#ifdef __USE_GNU +# define MON_DECIMAL_POINT __MON_DECIMAL_POINT +#endif + __MON_THOUSANDS_SEP, +#ifdef __USE_GNU +# define MON_THOUSANDS_SEP __MON_THOUSANDS_SEP +#endif + __MON_GROUPING, +#ifdef __USE_GNU +# define MON_GROUPING __MON_GROUPING +#endif + __POSITIVE_SIGN, +#ifdef __USE_GNU +# define POSITIVE_SIGN __POSITIVE_SIGN +#endif + __NEGATIVE_SIGN, +#ifdef __USE_GNU +# define NEGATIVE_SIGN __NEGATIVE_SIGN +#endif + __INT_FRAC_DIGITS, +#ifdef __USE_GNU +# define INT_FRAC_DIGITS __INT_FRAC_DIGITS +#endif + __FRAC_DIGITS, +#ifdef __USE_GNU +# define FRAC_DIGITS __FRAC_DIGITS +#endif + __P_CS_PRECEDES, +#ifdef __USE_GNU +# define P_CS_PRECEDES __P_CS_PRECEDES +#endif + __P_SEP_BY_SPACE, +#ifdef __USE_GNU +# define P_SEP_BY_SPACE __P_SEP_BY_SPACE +#endif + __N_CS_PRECEDES, +#ifdef __USE_GNU +# define N_CS_PRECEDES __N_CS_PRECEDES +#endif + __N_SEP_BY_SPACE, +#ifdef __USE_GNU +# define N_SEP_BY_SPACE __N_SEP_BY_SPACE +#endif + __P_SIGN_POSN, +#ifdef __USE_GNU +# define P_SIGN_POSN __P_SIGN_POSN +#endif + __N_SIGN_POSN, +#ifdef __USE_GNU +# define N_SIGN_POSN __N_SIGN_POSN +#endif + __INT_P_CS_PRECEDES, +#ifdef __USE_GNU +# define INT_P_CS_PRECEDES __INT_P_CS_PRECEDES +#endif + __INT_P_SEP_BY_SPACE, +#ifdef __USE_GNU +# define INT_P_SEP_BY_SPACE __INT_P_SEP_BY_SPACE +#endif + __INT_N_CS_PRECEDES, +#ifdef __USE_GNU +# define INT_N_CS_PRECEDES __INT_N_CS_PRECEDES +#endif + __INT_N_SEP_BY_SPACE, +#ifdef __USE_GNU +# define INT_N_SEP_BY_SPACE __INT_N_SEP_BY_SPACE +#endif + __INT_P_SIGN_POSN, +#ifdef __USE_GNU +# define INT_P_SIGN_POSN __INT_P_SIGN_POSN +#endif + __INT_N_SIGN_POSN, +#ifdef __USE_GNU +# define INT_N_SIGN_POSN __INT_N_SIGN_POSN +#endif + + _NL_MONETARY_CRNCYSTR, +#define CRNCYSTR _NL_MONETARY_CRNCYSTR + +#if 0 + _NL_MONETARY_DUO_INT_CURR_SYMBOL, + _NL_MONETARY_DUO_CURRENCY_SYMBOL, + _NL_MONETARY_DUO_INT_FRAC_DIGITS, + _NL_MONETARY_DUO_FRAC_DIGITS, + _NL_MONETARY_DUO_P_CS_PRECEDES, + _NL_MONETARY_DUO_P_SEP_BY_SPACE, + _NL_MONETARY_DUO_N_CS_PRECEDES, + _NL_MONETARY_DUO_N_SEP_BY_SPACE, + _NL_MONETARY_DUO_INT_P_CS_PRECEDES, + _NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, + _NL_MONETARY_DUO_INT_N_CS_PRECEDES, + _NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, + _NL_MONETARY_DUO_P_SIGN_POSN, + _NL_MONETARY_DUO_N_SIGN_POSN, + _NL_MONETARY_DUO_INT_P_SIGN_POSN, + _NL_MONETARY_DUO_INT_N_SIGN_POSN, + _NL_MONETARY_UNO_VALID_FROM, + _NL_MONETARY_UNO_VALID_TO, + _NL_MONETARY_DUO_VALID_FROM, + _NL_MONETARY_DUO_VALID_TO, + _NL_MONETARY_CONVERSION_RATE, + _NL_MONETARY_DECIMAL_POINT_WC, + _NL_MONETARY_THOUSANDS_SEP_WC, + _NL_MONETARY_CODESET, +#endif /* 0 */ + _NL_NUM_LC_MONETARY, + + /* LC_NUMERIC category: formatting of numbers. + These also correspond to members of `struct lconv'; see . */ + __DECIMAL_POINT = _NL_ITEM (__LC_NUMERIC, 0), +#ifdef __USE_GNU +# define DECIMAL_POINT __DECIMAL_POINT +#endif + RADIXCHAR = __DECIMAL_POINT, +#define RADIXCHAR RADIXCHAR + __THOUSANDS_SEP, +#ifdef __USE_GNU +# define THOUSANDS_SEP __THOUSANDS_SEP +#endif + THOUSEP = __THOUSANDS_SEP, +#define THOUSEP THOUSEP + __GROUPING, +#ifdef __USE_GNU +# define GROUPING __GROUPING +#endif +#if 0 + _NL_NUMERIC_DECIMAL_POINT_WC, + _NL_NUMERIC_THOUSANDS_SEP_WC, + _NL_NUMERIC_CODESET, +#endif + _NL_NUM_LC_NUMERIC, + + __YESEXPR = _NL_ITEM (__LC_MESSAGES, 0), /* Regex matching ``yes'' input. */ +#define YESEXPR __YESEXPR + __NOEXPR, /* Regex matching ``no'' input. */ +#define NOEXPR __NOEXPR + __YESSTR, /* Output string for ``yes''. */ +#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +# define YESSTR __YESSTR +#endif + __NOSTR, /* Output string for ``no''. */ +#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +# define NOSTR __NOSTR +#endif +#if 0 + _NL_MESSAGES_CODESET, +#endif + _NL_NUM_LC_MESSAGES, + +#if 0 + _NL_PAPER_HEIGHT = _NL_ITEM (__LC_PAPER, 0), + _NL_PAPER_WIDTH, + _NL_PAPER_CODESET, + _NL_NUM_LC_PAPER, + + _NL_NAME_NAME_FMT = _NL_ITEM (__LC_NAME, 0), + _NL_NAME_NAME_GEN, + _NL_NAME_NAME_MR, + _NL_NAME_NAME_MRS, + _NL_NAME_NAME_MISS, + _NL_NAME_NAME_MS, + _NL_NAME_CODESET, + _NL_NUM_LC_NAME, + + _NL_ADDRESS_POSTAL_FMT = _NL_ITEM (__LC_ADDRESS, 0), + _NL_ADDRESS_COUNTRY_NAME, + _NL_ADDRESS_COUNTRY_POST, + _NL_ADDRESS_COUNTRY_AB2, + _NL_ADDRESS_COUNTRY_AB3, + _NL_ADDRESS_COUNTRY_CAR, + _NL_ADDRESS_COUNTRY_NUM, + _NL_ADDRESS_COUNTRY_ISBN, + _NL_ADDRESS_LANG_NAME, + _NL_ADDRESS_LANG_AB, + _NL_ADDRESS_LANG_TERM, + _NL_ADDRESS_LANG_LIB, + _NL_ADDRESS_CODESET, + _NL_NUM_LC_ADDRESS, + + _NL_TELEPHONE_TEL_INT_FMT = _NL_ITEM (__LC_TELEPHONE, 0), + _NL_TELEPHONE_TEL_DOM_FMT, + _NL_TELEPHONE_INT_SELECT, + _NL_TELEPHONE_INT_PREFIX, + _NL_TELEPHONE_CODESET, + _NL_NUM_LC_TELEPHONE, + + _NL_MEASUREMENT_MEASUREMENT = _NL_ITEM (__LC_MEASUREMENT, 0), + _NL_MEASUREMENT_CODESET, + _NL_NUM_LC_MEASUREMENT, + + _NL_IDENTIFICATION_TITLE = _NL_ITEM (__LC_IDENTIFICATION, 0), + _NL_IDENTIFICATION_SOURCE, + _NL_IDENTIFICATION_ADDRESS, + _NL_IDENTIFICATION_CONTACT, + _NL_IDENTIFICATION_EMAIL, + _NL_IDENTIFICATION_TEL, + _NL_IDENTIFICATION_FAX, + _NL_IDENTIFICATION_LANGUAGE, + _NL_IDENTIFICATION_TERRITORY, + _NL_IDENTIFICATION_AUDIENCE, + _NL_IDENTIFICATION_APPLICATION, + _NL_IDENTIFICATION_ABBREVIATION, + _NL_IDENTIFICATION_REVISION, + _NL_IDENTIFICATION_DATE, + _NL_IDENTIFICATION_CATEGORY, + _NL_IDENTIFICATION_CODESET, + _NL_NUM_LC_IDENTIFICATION, +#endif + /* This marks the highest value used. */ + _NL_NUM +}; + + +/* Return the current locale's value for ITEM. + If ITEM is invalid, an empty string is returned. + + The string returned will not change until `setlocale' is called; + it is usually in read-only memory and cannot be modified. */ + +extern char *nl_langinfo (nl_item __item) __THROW; + + +#ifdef __UCLIBC_HAS_XLOCALE__ +#ifdef __USE_GNU +/* This interface is for the extended locale model. See for + more information. */ + +/* Get locale datatype definition. */ +# include + +/* Just like nl_langinfo but get the information from the locale object L. */ +extern char *nl_langinfo_l (nl_item __item, __locale_t l); +#endif +#endif + +__END_DECLS + +#endif /* langinfo.h */ diff --git a/include/lastlog.h b/include/lastlog.h new file mode 100644 index 0000000..8cc4254 --- /dev/null +++ b/include/lastlog.h @@ -0,0 +1,4 @@ +/* This header file is used in 4.3BSD to define `struct lastlog', + which we define in . */ + +#include diff --git a/include/libc-internal.h b/include/libc-internal.h new file mode 100644 index 0000000..7b2566f --- /dev/null +++ b/include/libc-internal.h @@ -0,0 +1,100 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBC_INTERNAL_H +#define _LIBC_INTERNAL_H 1 + +#include + +#ifdef __UCLIBC_BUILD_RELRO__ +# define attribute_relro __attribute__ ((section (".data.rel.ro"))) +#else +# define attribute_relro +#endif + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# define attribute_tls_model_ie __attribute__ ((tls_model ("initial-exec"))) +#endif + +/* Pull in things like __attribute_used__ */ +#include + +/* --- this is added to integrate linuxthreads */ +/*#define __USE_UNIX98 1*/ + +#ifndef __ASSEMBLER__ +# ifdef IS_IN_libc + +# define __need_size_t +# include + +/* sources are built w/ _GNU_SOURCE, this gets undefined */ +#ifdef __USE_GNU +extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen); +#else +extern char *__glibc_strerror_r (int __errnum, char *__buf, size_t __buflen); +#endif + +/* #include */ +# ifndef __UCLIBC_HAS_THREADS__ +# define __pthread_mutex_init(mutex, mutexattr) ((void)0) +# define __pthread_mutex_lock(mutex) ((void)0) +# define __pthread_mutex_trylock(mutex) ((void)0) +# define __pthread_mutex_unlock(mutex) ((void)0) +# define _pthread_cleanup_push_defer(mutex) ((void)0) +# define _pthread_cleanup_pop_restore(mutex) ((void)0) +# endif + +/* internal access to program name */ +extern const char *__uclibc_progname attribute_hidden; + +# endif /* IS_IN_libc */ + +/* #include */ +#include +#if defined(_STACK_GROWS_DOWN) +# define extend_alloca(buf, len, newlen) \ + (__typeof (buf)) ({ size_t __newlen = (newlen); \ + char *__newbuf = alloca (__newlen); \ + if (__newbuf + __newlen == (char *) buf) \ + len += __newlen; \ + else \ + len = __newlen; \ + __newbuf; }) +#elif defined(_STACK_GROWS_UP) +# define extend_alloca(buf, len, newlen) \ + (__typeof (buf)) ({ size_t __newlen = (newlen); \ + char *__newbuf = alloca (__newlen); \ + char *__buf = (buf); \ + if (__buf + __newlen == __newbuf) \ + { \ + len += __newlen; \ + __newbuf = __buf; \ + } \ + else \ + len = __newlen; \ + __newbuf; }) +#else +# warning unknown stack +# define extend_alloca(buf, len, newlen) \ + alloca (((len) = (newlen))) +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* _LIBC_INTERNAL_H */ diff --git a/include/libc-symbols.h b/include/libc-symbols.h new file mode 100644 index 0000000..dacc03c --- /dev/null +++ b/include/libc-symbols.h @@ -0,0 +1,726 @@ +/* Support macros for making weak and strong aliases for symbols, + and for using symbol sets and linker warnings with GNU ld. + Copyright (C) 1995-1998,2000-2003,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBC_SYMBOLS_H +#define _LIBC_SYMBOLS_H 1 + +/* This is defined for the compilation of all C library code. features.h + tests this to avoid inclusion of stubs.h while compiling the library, + before stubs.h has been generated. Some library code that is shared + with other packages also tests this symbol to see if it is being + compiled as part of the C library. We must define this before including + config.h, because it makes some definitions conditional on whether libc + itself is being compiled, or just some generator program. */ +#define _LIBC 1 + + +/* This file's macros are included implicitly in the compilation of every + file in the C library by -imacros. + + We include uClibc_arch_features.h which is defined by arch devs. + It should define for us the following symbols: + + * HAVE_ASM_SET_DIRECTIVE if we have `.set B, A' instead of `A = B'. + * ASM_GLOBAL_DIRECTIVE with `.globl' or `.global'. + * ASM_TYPE_DIRECTIVE_PREFIX with `@' or `#' or whatever for .type, + or leave it undefined if there is no .type directive. + * HAVE_ELF if using ELF, which supports weak symbols using `.weak'. + * HAVE_ASM_WEAK_DIRECTIVE if we have weak symbols using `.weak'. + * HAVE_ASM_WEAKEXT_DIRECTIVE if we have weak symbols using `.weakext'. + + */ + +#include + +/* Enable declarations of GNU extensions, since we are compiling them. */ +#define _GNU_SOURCE 1 + +/* Prepare for the case that `__builtin_expect' is not available. */ +#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 +# define __builtin_expect(x, expected_value) (x) +#endif +#ifndef likely +# define likely(x) __builtin_expect((!!(x)),1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect((!!(x)),0) +#endif +#ifndef __LINUX_COMPILER_H +# define __LINUX_COMPILER_H +#endif +#ifndef __cast__ +# define __cast__(_to) +#endif + +#define attribute_unused __attribute__ ((unused)) + +#if defined __GNUC__ || defined __ICC +# define attribute_noreturn __attribute__ ((__noreturn__)) +#else +# define attribute_noreturn +#endif + +#ifndef NOT_IN_libc +# define IS_IN_libc 1 +#endif + +/* Indirect stringification. Doing two levels allows + * the parameter to be a macro itself. + */ +#define __stringify_1(x) #x +#define __stringify(x) __stringify_1(x) + +#ifdef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ +# define HAVE_ASM_SET_DIRECTIVE +#else +# undef HAVE_ASM_SET_DIRECTIVE +#endif + +#ifdef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ +# define ASM_GLOBAL_DIRECTIVE __UCLIBC_ASM_GLOBAL_DIRECTIVE__ +#else +# define ASM_GLOBAL_DIRECTIVE .global +#endif + +#ifdef __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ +# define HAVE_ASM_WEAK_DIRECTIVE +#else +# undef HAVE_ASM_WEAK_DIRECTIVE +#endif + +#ifdef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ +# define HAVE_ASM_WEAKEXT_DIRECTIVE +#else +# undef HAVE_ASM_WEAKEXT_DIRECTIVE +#endif + +#ifdef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ +# define HAVE_ASM_GLOBAL_DOT_NAME +#else +# undef HAVE_ASM_GLOBAL_DOT_NAME +#endif + +#if defined HAVE_ASM_WEAK_DIRECTIVE || defined HAVE_ASM_WEAKEXT_DIRECTIVE +# define HAVE_WEAK_SYMBOLS +#endif + +#undef C_SYMBOL_NAME +#ifndef C_SYMBOL_NAME +# ifndef __UCLIBC_UNDERSCORES__ +# define C_SYMBOL_NAME(name) name +# else +# define C_SYMBOL_NAME(name) _##name +# endif +#endif + +#ifdef __UCLIBC_ASM_LINE_SEP__ +# define ASM_LINE_SEP __UCLIBC_ASM_LINE_SEP__ +#else +# define ASM_LINE_SEP ; +#endif + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# ifndef C_SYMBOL_DOT_NAME +# if defined __GNUC__ && defined __GNUC_MINOR__ \ + && (__GNUC__ << 16) + __GNUC_MINOR__ >= (3 << 16) + 1 +# define C_SYMBOL_DOT_NAME(name) .name +# else +# define C_SYMBOL_DOT_NAME(name) .##name +# endif +# endif +#endif + +#ifndef __ASSEMBLER__ +/* GCC understands weak symbols and aliases; use its interface where + possible, instead of embedded assembly language. */ + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +/* This comes between the return type and function name in + a function definition to make that definition weak. */ +# define weak_function __attribute__ ((weak)) +# define weak_const_function __attribute__ ((weak, __const__)) + +# ifdef HAVE_WEAK_SYMBOLS + +/* Define ALIASNAME as a weak alias for NAME. + If weak aliases are not available, this defines a strong alias. */ +# define weak_alias(name, aliasname) _weak_alias (name, aliasname) +# define _weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); + +/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ +# define weak_extern(symbol) _weak_extern (weak symbol) +# define _weak_extern(expr) _Pragma (#expr) + +# else + +# define weak_alias(name, aliasname) strong_alias(name, aliasname) +# define weak_extern(symbol) /* Nothing. */ + +# endif + +#else /* __ASSEMBLER__ */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME (alias),C_SYMBOL_DOT_NAME (original) +# define strong_data_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) +# define strong_data_alias(original, alias) strong_alias(original, alias) +# endif +# else +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# define strong_data_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# define strong_data_alias(original, alias) strong_alias(original, alias) +# endif +# endif + +# ifdef HAVE_WEAK_SYMBOLS +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) ASM_LINE_SEP \ + .weakext C_SYMBOL_DOT_NAME (alias), C_SYMBOL_DOT_NAME (original) +# else +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) +# endif +# define weak_extern(symbol) \ + .weakext C_SYMBOL_NAME (symbol) + +# else /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) ASM_LINE_SEP \ + .weak C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME (alias), C_SYMBOL_DOT_NAME (original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original) +# endif +# else /* ! HAVE_ASM_SET_DIRECTIVE */ +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + .weak C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif +# endif +# define weak_extern(symbol) \ + .weak C_SYMBOL_NAME (symbol) + +# endif /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# else /* ! HAVE_WEAK_SYMBOLS */ + +# define weak_alias(original, alias) strong_alias(original, alias) +# define weak_extern(symbol) /* Nothing */ +# endif /* ! HAVE_WEAK_SYMBOLS */ + +#endif /* __ASSEMBLER__ */ + +/* On some platforms we can make internal function calls (i.e., calls of + functions not exported) a bit faster by using a different calling + convention. */ +#ifndef internal_function +# define internal_function /* empty */ +#endif + +/* We want the .gnu.warning.SYMBOL section to be unallocated. */ +#define __make_section_unallocated(section_string) \ + __asm__ (".section " section_string "\n\t.previous"); + +/* Tacking on "\n#APP\n\t#" to the section name makes gcc put it's bogus + section attributes on what looks like a comment to the assembler. */ +#ifdef __sparc__ /* HAVE_SECTION_QUOTES */ +# define __sec_comment "\"\n#APP\n\t#\"" +#else +# define __sec_comment "\n#APP\n\t#" +#endif + +/* When a reference to SYMBOL is encountered, the linker will emit a + warning message MSG. */ +#define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \ + = msg; + +/* Handling on non-exported internal names. We have to do this only + for shared code. */ +#ifdef SHARED +# define INTUSE(name) name##_internal +# define INTDEF(name) strong_alias (name, name##_internal) +# define INTVARDEF(name) \ + _INTVARDEF (name, name##_internal) +# if defined HAVE_VISIBILITY_ATTRIBUTE +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name), \ + visibility ("hidden"))); +# else +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +# endif +# define INTDEF2(name, newname) strong_alias (name, newname##_internal) +# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal) +#else +# define INTUSE(name) name +# define INTDEF(name) +# define INTVARDEF(name) +# define INTDEF2(name, newname) +# define INTVARDEF2(name, newname) +#endif + +/* The following macros are used for PLT bypassing within libc.so + (and if needed other libraries similarly). + First of all, you need to have the function prototyped somewhere, + say in foo/foo.h: + + int foo (int __bar); + + If calls to foo within libc.so should always go to foo defined in libc.so, + then in include/foo.h you add: + + libc_hidden_proto (foo) + + line and after the foo function definition: + + int foo (int __bar) + { + return __bar; + } + libc_hidden_def (foo) + + or + + int foo (int __bar) + { + return __bar; + } + libc_hidden_weak (foo) + + Similarly for global data. If references to foo within libc.so should + always go to foo defined in libc.so, then in include/foo.h you add: + + libc_hidden_proto (foo) + + line and after foo's definition: + + int foo = INITIAL_FOO_VALUE; + libc_hidden_data_def (foo) + + or + + int foo = INITIAL_FOO_VALUE; + libc_hidden_data_weak (foo) + + If foo is normally just an alias (strong or weak) to some other function, + you should use the normal strong_alias first, then add libc_hidden_def + or libc_hidden_weak: + + int baz (int __bar) + { + return __bar; + } + strong_alias (baz, foo) + libc_hidden_weak (foo) + + If the function should be internal to multiple objects, say ld.so and + libc.so, the best way is to use: + + #if !defined NOT_IN_libc || defined IS_IN_rtld + hidden_proto (foo) + #endif + + in include/foo.h and the normal macros at all function definitions + depending on what DSO they belong to. + + If versioned_symbol macro is used to define foo, + libc_hidden_ver macro should be used, as in: + + int __real_foo (int __bar) + { + return __bar; + } + versioned_symbol (libc, __real_foo, foo, GLIBC_2_1); + libc_hidden_ver (__real_foo, foo) */ + +/* uClibc specific (the above comment was copied from glibc): + * a. when ppc64 will be supported, we need changes to support: + * strong_data_alias (used by asm hidden_data_def) + * b. libc_hidden_proto(foo) should be added after the header having foo's prototype + * or after extern foo... to all source files that should use the internal version + * of foo within libc, even to the file defining foo itself, libc_hidden_def does + * not hide __GI_foo itself, although the name suggests it (hiding is done exclusively + * by libc_hidden_proto). The reasoning to have it after the header w/ foo's prototype is + * to get first the __REDIRECT from original header and then create the __GI_foo alias + * c. no versioning support, hidden[_data]_ver are noop + * d. hidden_def() in asm is _hidden_strong_alias (not strong_alias) */ + +/* Arrange to hide uClibc internals */ +#if (defined __GNUC__ && \ + (defined __GNUC_MINOR__ && ( __GNUC__ >= 3 && __GNUC_MINOR__ >= 3 ) \ + || __GNUC__ >= 4)) || defined __ICC +# define attribute_hidden __attribute__ ((visibility ("hidden"))) +# define __hidden_proto_hiddenattr(attrs...) __attribute__ ((visibility ("hidden"), ##attrs)) +#else +# define attribute_hidden +# define __hidden_proto_hiddenattr(attrs...) +#endif + +#if /*!defined STATIC &&*/ !defined __BCC__ +# ifndef __ASSEMBLER__ +# define hidden_proto(name, attrs...) __hidden_proto (name, __GI_##name, ##attrs) +# define __hidden_proto(name, internal, attrs...) \ + extern __typeof (name) name __asm__ (__hidden_asmname (#internal)) \ + __hidden_proto_hiddenattr (attrs); +# define __hidden_asmname(name) __hidden_asmname1 (__USER_LABEL_PREFIX__, name) +# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name) +# define __hidden_asmname2(prefix, name) #prefix name +# define __hidden_ver1(local, internal, name) \ + extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \ + extern __typeof (name) __EI_##name __attribute__((alias (__hidden_asmname1 (,#local)))) +# define hidden_ver(local, name) __hidden_ver1(local, __GI_##name, name); +# define hidden_data_ver(local, name) hidden_ver(local, name) +# define hidden_def(name) __hidden_ver1(__GI_##name, name, name); +# define hidden_data_def(name) hidden_def(name) +# define hidden_weak(name) \ + __hidden_ver1(__GI_##name, name, name) __attribute__((weak)); +# define hidden_data_weak(name) hidden_weak(name) + +# else /* __ASSEMBLER__ */ +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME (alias),C_SYMBOL_DOT_NAME (original) +# else +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME (alias),C_SYMBOL_NAME (original) +# endif +# else +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original) +# else +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) +# endif +# endif + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_weak_alias(original, alias) \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \ + weak_alias(original, alias) +# else +# define _hidden_weak_alias(original, alias) \ + .hidden C_SYMBOL_NAME (alias) ASM_LINE_SEP \ + weak_alias(original, alias) +# endif + +/* For assembly, we need to do the opposite of what we do in C: + in assembly gcc __REDIRECT stuff is not in place, so functions + are defined by its normal name and we need to create the + __GI_* alias to it, in C __REDIRECT causes the function definition + to use __GI_* name and we need to add alias to the real name. + There is no reason to use hidden_weak over hidden_def in assembly, + but we provide it for consistency with the C usage. + hidden_proto doesn't make sense for assembly but the equivalent + is to call via the HIDDEN_JUMPTARGET macro instead of JUMPTARGET. */ +# define hidden_def(name) _hidden_strong_alias (name, __GI_##name) +# define hidden_weak(name) _hidden_weak_alias (name, __GI_##name) +# define hidden_ver(local, name) strong_alias (local, __GI_##name) +# define hidden_data_def(name) _hidden_strong_alias (name, __GI_##name) +# define hidden_data_weak(name) _hidden_weak_alias (name, __GI_##name) +# define hidden_data_ver(local, name) strong_data_alias (local, __GI_##name) +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define HIDDEN_JUMPTARGET(name) .__GI_##name +# else +# define HIDDEN_JUMPTARGET(name) __GI_##name +# endif +# endif /* __ASSEMBLER__ */ +#else /* SHARED */ +# ifndef __ASSEMBLER__ +# define hidden_proto(name, attrs...) +# else +# define HIDDEN_JUMPTARGET(name) name +# endif /* Not __ASSEMBLER__ */ +# define hidden_weak(name) +# define hidden_def(name) +# define hidden_ver(local, name) +# define hidden_data_weak(name) +# define hidden_data_def(name) +# define hidden_data_ver(local, name) +#endif /* SHARED */ + +/* uClibc does not support versioning yet. */ +#define versioned_symbol(lib, local, symbol, version) /* weak_alias(local, symbol) */ +#undef hidden_ver +#define hidden_ver(local, name) /* strong_alias(local, __GI_##name) */ +#undef hidden_data_ver +#define hidden_data_ver(local, name) /* strong_alias(local,__GI_##name) */ + +#if !defined NOT_IN_libc +# define libc_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libc_hidden_def(name) hidden_def (name) +# define libc_hidden_weak(name) hidden_weak (name) +# define libc_hidden_ver(local, name) hidden_ver (local, name) +# define libc_hidden_data_def(name) hidden_data_def (name) +# define libc_hidden_data_weak(name) hidden_data_weak (name) +# define libc_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libc_hidden_proto(name, attrs...) +# define libc_hidden_def(name) +# define libc_hidden_weak(name) +# define libc_hidden_ver(local, name) +# define libc_hidden_data_def(name) +# define libc_hidden_data_weak(name) +# define libc_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_rtld +# define rtld_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define rtld_hidden_def(name) hidden_def (name) +# define rtld_hidden_weak(name) hidden_weak (name) +# define rtld_hidden_ver(local, name) hidden_ver (local, name) +# define rtld_hidden_data_def(name) hidden_data_def (name) +# define rtld_hidden_data_weak(name) hidden_data_weak (name) +# define rtld_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define rtld_hidden_proto(name, attrs...) +# define rtld_hidden_def(name) +# define rtld_hidden_weak(name) +# define rtld_hidden_ver(local, name) +# define rtld_hidden_data_def(name) +# define rtld_hidden_data_weak(name) +# define rtld_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libm +# define libm_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libm_hidden_def(name) hidden_def (name) +# define libm_hidden_weak(name) hidden_weak (name) +# define libm_hidden_ver(local, name) hidden_ver (local, name) +# define libm_hidden_data_def(name) hidden_data_def (name) +# define libm_hidden_data_weak(name) hidden_data_weak (name) +# define libm_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libm_hidden_proto(name, attrs...) +# define libm_hidden_def(name) +# define libm_hidden_weak(name) +# define libm_hidden_ver(local, name) +# define libm_hidden_data_def(name) +# define libm_hidden_data_weak(name) +# define libm_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libresolv +# define libresolv_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libresolv_hidden_def(name) hidden_def (name) +# define libresolv_hidden_weak(name) hidden_weak (name) +# define libresolv_hidden_ver(local, name) hidden_ver (local, name) +# define libresolv_hidden_data_def(name) hidden_data_def (name) +# define libresolv_hidden_data_weak(name) hidden_data_weak (name) +# define libresolv_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libresolv_hidden_proto(name, attrs...) +# define libresolv_hidden_def(name) +# define libresolv_hidden_weak(name) +# define libresolv_hidden_ver(local, name) +# define libresolv_hidden_data_def(name) +# define libresolv_hidden_data_weak(name) +# define libresolv_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_librt +# define librt_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define librt_hidden_def(name) hidden_def (name) +# define librt_hidden_weak(name) hidden_weak (name) +# define librt_hidden_ver(local, name) hidden_ver (local, name) +# define librt_hidden_data_def(name) hidden_data_def (name) +# define librt_hidden_data_weak(name) hidden_data_weak (name) +# define librt_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define librt_hidden_proto(name, attrs...) +# define librt_hidden_def(name) +# define librt_hidden_weak(name) +# define librt_hidden_ver(local, name) +# define librt_hidden_data_def(name) +# define librt_hidden_data_weak(name) +# define librt_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libdl +# define libdl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libdl_hidden_def(name) hidden_def (name) +# define libdl_hidden_weak(name) hidden_weak (name) +# define libdl_hidden_ver(local, name) hidden_ver (local, name) +# define libdl_hidden_data_def(name) hidden_data_def (name) +# define libdl_hidden_data_weak(name) hidden_data_weak (name) +# define libdl_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libdl_hidden_proto(name, attrs...) +# define libdl_hidden_def(name) +# define libdl_hidden_weak(name) +# define libdl_hidden_ver(local, name) +# define libdl_hidden_data_def(name) +# define libdl_hidden_data_weak(name) +# define libdl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libintl +# define libintl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libintl_hidden_def(name) hidden_def (name) +# define libintl_hidden_weak(name) hidden_weak (name) +# define libintl_hidden_ver(local, name) hidden_ver (local, name) +# define libintl_hidden_data_def(name) hidden_data_def (name) +# define libintl_hidden_data_weak(name) hidden_data_weak (name) +# define libintl_hidden_data_ver(local, name) hidden_data_ver(local, name) +#else +# define libintl_hidden_proto(name, attrs...) +# define libintl_hidden_def(name) +# define libintl_hidden_weak(name) +# define libintl_hidden_ver(local, name) +# define libintl_hidden_data_def(name) +# define libintl_hidden_data_weak(name) +# define libintl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libnsl +# define libnsl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libnsl_hidden_def(name) hidden_def (name) +# define libnsl_hidden_weak(name) hidden_weak (name) +# define libnsl_hidden_ver(local, name) hidden_ver (local, name) +# define libnsl_hidden_data_def(name) hidden_data_def (name) +# define libnsl_hidden_data_weak(name) hidden_data_weak (name) +# define libnsl_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libnsl_hidden_proto(name, attrs...) +# define libnsl_hidden_def(name) +# define libnsl_hidden_weak(name) +# define libnsl_hidden_ver(local, name) +# define libnsl_hidden_data_def(name) +# define libnsl_hidden_data_weak(name) +# define libnsl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libutil +# define libutil_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libutil_hidden_def(name) hidden_def (name) +# define libutil_hidden_weak(name) hidden_weak (name) +# define libutil_hidden_ver(local, name) hidden_ver (local, name) +# define libutil_hidden_data_def(name) hidden_data_def (name) +# define libutil_hidden_data_weak(name) hidden_data_weak (name) +# define libutil_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libutil_hidden_proto(name, attrs...) +# define libutil_hidden_def(name) +# define libutil_hidden_weak(name) +# define libutil_hidden_ver(local, name) +# define libutil_hidden_data_def(name) +# define libutil_hidden_data_weak(name) +# define libutil_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libcrypt +# define libcrypt_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libcrypt_hidden_def(name) hidden_def (name) +# define libcrypt_hidden_weak(name) hidden_weak (name) +# define libcrypt_hidden_ver(local, name) hidden_ver (local, name) +# define libcrypt_hidden_data_def(name) hidden_data_def (name) +# define libcrypt_hidden_data_weak(name) hidden_data_weak (name) +# define libcrypt_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libcrypt_hidden_proto(name, attrs...) +# define libcrypt_hidden_def(name) +# define libcrypt_hidden_weak(name) +# define libcrypt_hidden_ver(local, name) +# define libcrypt_hidden_data_def(name) +# define libcrypt_hidden_data_weak(name) +# define libcrypt_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libpthread +# define libpthread_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libpthread_hidden_def(name) hidden_def (name) +# define libpthread_hidden_weak(name) hidden_weak (name) +# define libpthread_hidden_ver(local, name) hidden_ver (local, name) +# define libpthread_hidden_data_def(name) hidden_data_def (name) +# define libpthread_hidden_data_weak(name) hidden_data_weak (name) +# define libpthread_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libpthread_hidden_proto(name, attrs...) +# define libpthread_hidden_def(name) +# define libpthread_hidden_weak(name) +# define libpthread_hidden_ver(local, name) +# define libpthread_hidden_data_def(name) +# define libpthread_hidden_data_weak(name) +# define libpthread_hidden_data_ver(local, name) +#endif + +#endif /* libc-symbols.h */ diff --git a/include/libgen.h b/include/libgen.h new file mode 100644 index 0000000..b252543 --- /dev/null +++ b/include/libgen.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBGEN_H +#define _LIBGEN_H 1 + +#include + +__BEGIN_DECLS + +/* Return directory part of PATH or "." if none is available. */ +extern char *dirname (char *__path) __THROW; + +/* Return final component of PATH. + + This is the weird XPG version of this function. It sometimes will + modify its argument. Therefore we normally use the GNU version (in + ) and only if this header is included make the XPG + version available under the real name. */ +extern char *__xpg_basename (char *__path) __THROW; +#define basename __xpg_basename + +__END_DECLS + +#endif /* libgen.h */ diff --git a/include/libintl.h b/include/libintl.h new file mode 100644 index 0000000..ba57f16 --- /dev/null +++ b/include/libintl.h @@ -0,0 +1,133 @@ +/* Message catalogs for internationalization. + Copyright (C) 1995-2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + This file is derived from the file libgettext.h in the GNU gettext package. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBINTL_H +#define _LIBINTL_H 1 + +#include + +/* We define an additional symbol to signal that we use the GNU + implementation of gettext. */ +#define __USE_GNU_GETTEXT 1 + +/* Provide information about the supported file formats. Returns the + maximum minor revision number supported for a given major revision. */ +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \ + ((major) == 0 ? 1 : -1) + +__BEGIN_DECLS + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: gettext has a prototype but isn't defined." +#warning "mjn3 FIXME: __OPTIMIZE__ is never defined." +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +extern char *gettext (__const char *__msgid) + __THROW __attribute_format_arg__ (1); + +/* Look up MSGID in the DOMAINNAME message catalog for the current + LC_MESSAGES locale. */ +extern char *dgettext (__const char *__domainname, __const char *__msgid) + __THROW __attribute_format_arg__ (2); +#if 0 /* uClibc: disabled */ +extern char *__dgettext (__const char *__domainname, __const char *__msgid) + __THROW __attribute_format_arg__ (2); +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +extern char *dcgettext (__const char *__domainname, + __const char *__msgid, int __category) + __THROW __attribute_format_arg__ (2); +#if 0 /* uClibc: disabled */ +extern char *__dcgettext (__const char *__domainname, + __const char *__msgid, int __category) + __THROW __attribute_format_arg__ (2); +#endif + + +/* Similar to `gettext' but select the plural form corresponding to the + number N. */ +extern char *ngettext (__const char *__msgid1, __const char *__msgid2, + unsigned long int __n) + __THROW __attribute_format_arg__ (1) __attribute_format_arg__ (2); + +/* Similar to `dgettext' but select the plural form corresponding to the + number N. */ +extern char *dngettext (__const char *__domainname, __const char *__msgid1, + __const char *__msgid2, unsigned long int __n) + __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3); + +/* Similar to `dcgettext' but select the plural form corresponding to the + number N. */ +extern char *dcngettext (__const char *__domainname, __const char *__msgid1, + __const char *__msgid2, unsigned long int __n, + int __category) + __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3); + + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +extern char *textdomain (__const char *__domainname) __THROW; + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +extern char *bindtextdomain (__const char *__domainname, + __const char *__dirname) __THROW; + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +extern char *bind_textdomain_codeset (__const char *__domainname, + __const char *__codeset) __THROW; + + +/* Optimized version of the function above. */ +#if defined __OPTIMIZE__ && !defined __cplusplus + +/* We need NULL for `gettext'. */ +# define __need_NULL +# include + +/* We need LC_MESSAGES for `dgettext'. */ +# include + +/* These must be macros. Inlined functions are useless because the + `__builtin_constant_p' predicate in dcgettext would always return + false. */ + +# define gettext(msgid) dgettext (NULL, msgid) + +# define dgettext(domainname, msgid) \ + dcgettext (domainname, msgid, LC_MESSAGES) + +# define ngettext(msgid1, msgid2, n) dngettext (NULL, msgid1, msgid2, n) + +# define dngettext(domainname, msgid1, msgid2, n) \ + dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES) + +#endif /* Optimizing. */ + +__END_DECLS + +#endif /* libintl.h */ diff --git a/include/limits.h b/include/limits.h new file mode 100644 index 0000000..45cd6f2 --- /dev/null +++ b/include/limits.h @@ -0,0 +1,153 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types + */ + +#ifndef _LIBC_LIMITS_H_ +#define _LIBC_LIMITS_H_ 1 + +#include + + +/* Maximum length of any multibyte character in any locale. + We define this value here since the gcc header does not define + the correct value. */ +#define MB_LEN_MAX 16 + + +/* If we are not using GNU CC we have to define all the symbols ourself. + Otherwise use gcc's definitions (see below). */ +#if !defined __GNUC__ || __GNUC__ < 2 + +/* We only protect from multiple inclusion here, because all the other + #include's protect themselves, and in GCC 2 we may #include_next through + multiple copies of this file before we get to GCC's. */ +# ifndef _LIMITS_H +# define _LIMITS_H 1 + +#include + +/* We don't have #include_next. + Define ANSI for standard 32-bit words. */ + +/* These assume 8-bit `char's, 16-bit `short int's, + and 32-bit `int's and `long int's. */ + +/* Number of bits in a `char'. */ +# define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold. */ +# define SCHAR_MIN (-128) +# define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ +# define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold. */ +# ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +# else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +# endif + +/* Minimum and maximum values a `signed short int' can hold. */ +# define SHRT_MIN (-32768) +# define SHRT_MAX 32767 + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */ +# define USHRT_MAX 65535 + +/* Minimum and maximum values a `signed int' can hold. */ +# define INT_MIN (-INT_MAX - 1) +# define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +# define UINT_MAX 4294967295U + +/* Minimum and maximum values a `signed long int' can hold. */ +# if __WORDSIZE == 64 +# define LONG_MAX 9223372036854775807L +# else +# define LONG_MAX 2147483647L +# endif +# define LONG_MIN (-LONG_MAX - 1L) + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */ +# if __WORDSIZE == 64 +# define ULONG_MAX 18446744073709551615UL +# else +# define ULONG_MAX 4294967295UL +# endif + +# ifdef __USE_ISOC99 + +/* Minimum and maximum values a `signed long long int' can hold. */ +# define LLONG_MAX 9223372036854775807LL +# define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +# define ULLONG_MAX 18446744073709551615ULL + +# endif /* ISO C99 */ + +# endif /* limits.h */ +#endif /* GCC 2. */ + +#endif /* !_LIBC_LIMITS_H_ */ + + /* Get the compiler's limits.h, which defines almost all the ISO constants. + + We put this #include_next outside the double inclusion check because + it should be possible to include this file more than once and still get + the definitions from gcc's header. */ +#if defined __GNUC__ && !defined _GCC_LIMITS_H_ +/* `_GCC_LIMITS_H_' is what GCC's file defines. */ +# include_next + +/* The files in some gcc versions don't define LLONG_MIN, + LLONG_MAX, and ULLONG_MAX. Instead only the values gcc defined for + ages are available. */ +# ifdef __USE_ISOC99 +# ifndef LLONG_MIN +# define LLONG_MIN LONG_LONG_MIN +# endif +# ifndef LLONG_MAX +# define LLONG_MAX LONG_LONG_MAX +# endif +# ifndef ULLONG_MAX +# define ULLONG_MAX ULONG_LONG_MAX +# endif +# endif +#endif + +#ifdef __USE_POSIX +/* POSIX adds things to . */ +# include +#endif + +#ifdef __USE_POSIX2 +# include +#endif + +#ifdef __USE_XOPEN +# include +#endif diff --git a/include/link.h b/include/link.h new file mode 100644 index 0000000..6ce15df --- /dev/null +++ b/include/link.h @@ -0,0 +1,240 @@ +/* Data structure for communication from the run-time dynamic linker for + loaded ELF shared objects. + Copyright (C) 1995-2001, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINK_H +#define _LINK_H 1 + +#include +#include +#ifdef __HAVE_SHARED__ +#include +#endif +#include +#if defined _LIBC && defined __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +/* We use this macro to refer to ELF types independent of the native wordsize. + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ +#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) +#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) +#define _ElfW_1(e,w,t) e##w##t + +#include /* Defines __ELF_NATIVE_CLASS. */ + +/* Rendezvous structure used by the run-time dynamic linker to communicate + details of shared object loading to the debugger. If the executable's + dynamic section has a DT_DEBUG element, the run-time linker sets that + element's value to the address where this structure can be found. */ + +struct r_debug + { + int r_version; /* Version number for this protocol. */ + + struct link_map *r_map; /* Head of the chain of loaded objects. */ + + /* This is the address of a function internal to the run-time linker, + that will always be called when the linker begins to map in a + library or unmap it, and again when the mapping change is complete. + The debugger can set a breakpoint at this address if it wants to + notice shared object mapping changes. */ + ElfW(Addr) r_brk; + enum + { + /* This state value describes the mapping change taking place when + the `r_brk' address is called. */ + RT_CONSISTENT, /* Mapping change is complete. */ + RT_ADD, /* Beginning to add a new object. */ + RT_DELETE /* Beginning to remove an object mapping. */ + } r_state; + + ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ + }; + +/* This is the instance of that structure used by the dynamic linker. */ +extern struct r_debug _r_debug; + +/* This symbol refers to the "dynamic structure" in the `.dynamic' section + of whatever module refers to `_DYNAMIC'. So, to find its own + `struct r_debug', a program could do: + for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_DEBUG) + r_debug = (struct r_debug *) dyn->d_un.d_ptr; + */ +extern ElfW(Dyn) _DYNAMIC[]; + +#ifdef __FDPIC__ +# include +#endif + +/* Structure describing a loaded shared object. The `l_next' and `l_prev' + members form a chain of all the shared objects loaded at startup. + + These data structures exist in space used by the run-time dynamic linker; + modifying them may have disastrous results. */ + +struct link_map + { + /* These first few members are part of the protocol with the debugger. + This is the same format used in SVR4. */ + +#ifdef __FDPIC__ + struct elf32_fdpic_loadaddr l_addr; +#else + ElfW(Addr) l_addr; /* Base address shared object is loaded at. */ +#endif + char *l_name; /* Absolute file name object was found in. */ + ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */ + struct link_map *l_next, *l_prev; /* Chain of loaded objects. */ + +#ifdef USE_TLS + /* Thread-local storage related info. */ + + /* Start of the initialization image. */ + void *l_tls_initimage; + /* Size of the initialization image. */ + size_t l_tls_initimage_size; + /* Size of the TLS block. */ + size_t l_tls_blocksize; + /* Alignment requirement of the TLS block. */ + size_t l_tls_align; + /* Offset of first byte module alignment. */ + size_t l_tls_firstbyte_offset; +# ifndef NO_TLS_OFFSET +# define NO_TLS_OFFSET 0 +# endif + /* For objects present at startup time: offset in the static TLS block. */ + ptrdiff_t l_tls_offset; + /* Index of the module in the dtv array. */ + size_t l_tls_modid; + /* Nonzero if _dl_init_static_tls should be called for this module */ + unsigned int l_need_tls_init:1; +#endif + }; + +#ifdef __USE_GNU + +#if 0 +/* Version numbers for la_version handshake interface. */ +#define LAV_CURRENT 1 + +/* Activity types signaled through la_activity. */ +enum + { + LA_ACT_CONSISTENT, /* Link map consistent again. */ + LA_ACT_ADD, /* New object will be added. */ + LA_ACT_DELETE /* Objects will be removed. */ + }; + +/* Values representing origin of name for dynamic loading. */ +enum + { + LA_SER_ORIG = 0x01, /* Original name. */ + LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */ + LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */ + LA_SER_CONFIG = 0x08, /* Found through ldconfig. */ + LA_SER_DEFAULT = 0x40, /* Default directory. */ + LA_SER_SECURE = 0x80 /* Unused. */ + }; + +/* Values for la_objopen return value. */ +enum + { + LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */ + LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */ + }; + +/* Values for la_symbind flags parameter. */ +enum + { + LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */ + LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */ + LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */ + LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */ + LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous + la_symbind call. */ + }; +#endif + +struct dl_phdr_info + { +#ifdef __FDPIC__ + struct elf32_fdpic_loadaddr dlpi_addr; +#else + ElfW(Addr) dlpi_addr; +#endif + const char *dlpi_name; + const ElfW(Phdr) *dlpi_phdr; + ElfW(Half) dlpi_phnum; + +#if 0 + /* Note: Following members were introduced after the first + version of this structure was available. Check the SIZE + argument passed to the dl_iterate_phdr callback to determine + whether or not each later member is available. */ + + /* Incremented when a new object may have been added. */ + unsigned long long int dlpi_adds; + /* Incremented when an object may have been removed. */ + unsigned long long int dlpi_subs; + + /* If there is a PT_TLS segment, its module ID as used in + TLS relocations, else zero. */ + size_t dlpi_tls_modid; + + /* The address of the calling thread's instance of this module's + PT_TLS segment, if it has one and it has been allocated + in the calling thread, otherwise a null pointer. */ + void *dlpi_tls_data; +#endif + }; + +__BEGIN_DECLS + +extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *, + size_t, void *), + void *__data); + + +#if 0 +/* Prototypes for the ld.so auditing interfaces. These are not + defined anywhere in ld.so but instead have to be provided by the + auditing DSO. */ +extern unsigned int la_version (unsigned int __version); +extern void la_activity (uintptr_t *__cookie, unsigned int __flag); +extern char *la_objsearch (const char *__name, uintptr_t *__cookie, + unsigned int __flag); +extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid, + uintptr_t *__cookie); +extern void la_preinit (uintptr_t *__cookie); +extern uintptr_t la_symbind32 (Elf32_Sym *__sym, unsigned int __ndx, + uintptr_t *__refcook, uintptr_t *__defcook, + unsigned int *__flags, const char *__symname); +extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx, + uintptr_t *__refcook, uintptr_t *__defcook, + unsigned int *__flags, const char *__symname); +extern unsigned int la_objclose (uintptr_t *__cookie); +#endif + +__END_DECLS + +#endif + +#endif /* link.h */ diff --git a/include/locale.h b/include/locale.h new file mode 100644 index 0000000..c708d44 --- /dev/null +++ b/include/locale.h @@ -0,0 +1,227 @@ +/* Copyright (C) 1991,92,95-99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.11 Localization + */ + +#ifndef _LOCALE_H +#define _LOCALE_H 1 + +#include + +#define __need_NULL +#include +#include + +__BEGIN_DECLS + +/* These are the possibilities for the first argument to setlocale. + The code assumes that the lowest LC_* symbol has the value zero. */ +#define LC_CTYPE __LC_CTYPE +#define LC_NUMERIC __LC_NUMERIC +#define LC_TIME __LC_TIME +#define LC_COLLATE __LC_COLLATE +#define LC_MONETARY __LC_MONETARY +#define LC_MESSAGES __LC_MESSAGES +#if 0 +#define LC_PAPER __LC_PAPER +#define LC_NAME __LC_NAME +#define LC_ADDRESS __LC_ADDRESS +#define LC_TELEPHONE __LC_TELEPHONE +#define LC_MEASUREMENT __LC_MEASUREMENT +#define LC_IDENTIFICATION __LC_IDENTIFICATION +#endif +#define LC_ALL __LC_ALL + + +/* Structure giving information about numeric and monetary notation. */ +struct lconv +{ + /* Numeric (non-monetary) information. */ + + char *decimal_point; /* Decimal point character. */ + char *thousands_sep; /* Thousands separator. */ + /* Each element is the number of digits in each group; + elements with higher indices are farther left. + An element with value CHAR_MAX means that no further grouping is done. + An element with value 0 means that the previous element is used + for all groups farther left. */ + char *grouping; + + /* Monetary information. */ + + /* First three chars are a currency symbol from ISO 4217. + Fourth char is the separator. Fifth char is '\0'. */ + char *int_curr_symbol; + char *currency_symbol; /* Local currency symbol. */ + char *mon_decimal_point; /* Decimal point character. */ + char *mon_thousands_sep; /* Thousands separator. */ + char *mon_grouping; /* Like `grouping' element (above). */ + char *positive_sign; /* Sign for positive values. */ + char *negative_sign; /* Sign for negative values. */ + char int_frac_digits; /* Int'l fractional digits. */ + char frac_digits; /* Local fractional digits. */ + /* 1 if currency_symbol precedes a positive value, 0 if succeeds. */ + char p_cs_precedes; + /* 1 iff a space separates currency_symbol from a positive value. */ + char p_sep_by_space; + /* 1 if currency_symbol precedes a negative value, 0 if succeeds. */ + char n_cs_precedes; + /* 1 iff a space separates currency_symbol from a negative value. */ + char n_sep_by_space; + /* Positive and negative sign positions: + 0 Parentheses surround the quantity and currency_symbol. + 1 The sign string precedes the quantity and currency_symbol. + 2 The sign string follows the quantity and currency_symbol. + 3 The sign string immediately precedes the currency_symbol. + 4 The sign string immediately follows the currency_symbol. */ + char p_sign_posn; + char n_sign_posn; +#ifdef __USE_ISOC99 + /* 1 if int_curr_symbol precedes a positive value, 0 if succeeds. */ + char int_p_cs_precedes; + /* 1 iff a space separates int_curr_symbol from a positive value. */ + char int_p_sep_by_space; + /* 1 if int_curr_symbol precedes a negative value, 0 if succeeds. */ + char int_n_cs_precedes; + /* 1 iff a space separates int_curr_symbol from a negative value. */ + char int_n_sep_by_space; + /* Positive and negative sign positions: + 0 Parentheses surround the quantity and int_curr_symbol. + 1 The sign string precedes the quantity and int_curr_symbol. + 2 The sign string follows the quantity and int_curr_symbol. + 3 The sign string immediately precedes the int_curr_symbol. + 4 The sign string immediately follows the int_curr_symbol. */ + char int_p_sign_posn; + char int_n_sign_posn; +#else + 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; +#endif +}; + + +__BEGIN_NAMESPACE_STD + +/* Set and/or return the current locale. */ +extern char *setlocale (int __category, __const char *__locale) __THROW; + +/* Return the numeric/monetary information for the current locale. */ +extern struct lconv *localeconv (void) __THROW; + +__END_NAMESPACE_STD + + +#if defined(__USE_GNU) && defined(__UCLIBC_HAS_LOCALE__) +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +#if defined(__UCLIBC_HAS_XLOCALE__) +/* Get locale datatype definition. */ +# include +#endif + +typedef __locale_t locale_t; + +/* Return a reference to a data structure representing a set of locale + datasets. Unlike for the CATEGORY parameter for `setlocale' the + CATEGORY_MASK parameter here uses a single bit for each category, + made by OR'ing together LC_*_MASK bits above. */ +extern __locale_t newlocale (int __category_mask, __const char *__locale, + __locale_t __base) __THROW; + +/* These are the bits that can be set in the CATEGORY_MASK argument to + `newlocale'. In the GNU implementation, LC_FOO_MASK has the value + of (1 << LC_FOO), but this is not a part of the interface that + callers can assume will be true. */ +# 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) +#ifdef L_newlocale +#warning mask defines for extra locale categories +#endif /* L_newlocale - uClibc note */ +#ifdef LC_PAPER +# define LC_PAPER_MASK (1 << __LC_PAPER) +# define LC_NAME_MASK (1 << __LC_NAME) +# define LC_ADDRESS_MASK (1 << __LC_ADDRESS) +# define LC_TELEPHONE_MASK (1 << __LC_TELEPHONE) +# define LC_MEASUREMENT_MASK (1 << __LC_MEASUREMENT) +# define LC_IDENTIFICATION_MASK (1 << __LC_IDENTIFICATION) +# define LC_ALL_MASK (LC_CTYPE_MASK \ + | LC_NUMERIC_MASK \ + | LC_TIME_MASK \ + | LC_COLLATE_MASK \ + | LC_MONETARY_MASK \ + | LC_MESSAGES_MASK \ + | LC_PAPER_MASK \ + | LC_NAME_MASK \ + | LC_ADDRESS_MASK \ + | LC_TELEPHONE_MASK \ + | LC_MEASUREMENT_MASK \ + | LC_IDENTIFICATION_MASK \ + ) +#else /* LC_PAPER */ +# define LC_ALL_MASK (LC_CTYPE_MASK \ + | LC_NUMERIC_MASK \ + | LC_TIME_MASK \ + | LC_COLLATE_MASK \ + | LC_MONETARY_MASK \ + | LC_MESSAGES_MASK \ + ) +#endif /* LC_PAPER */ + +/* Return a duplicate of the set of locale in DATASET. All usage + counters are increased if necessary. */ +extern __locale_t duplocale (__locale_t __dataset) __THROW; + +/* Free the data associated with a locale dataset previously returned + by a call to `setlocale_r'. */ +extern void freelocale (__locale_t __dataset) __THROW; + +/* Switch the current thread's locale to DATASET. + If DATASET is null, instead just return the current setting. + The special value LC_GLOBAL_LOCALE is the initial setting + for all threads and can also be installed any time, meaning + the thread uses the global settings controlled by `setlocale'. */ +extern __locale_t uselocale (__locale_t __dataset) __THROW; + +/* This value can be passed to `uselocale' and may be returned by it. + Passing this value to any other function has undefined behavior. */ +# define LC_GLOBAL_LOCALE ((__locale_t) -1L) + +#endif + +__END_DECLS + +#endif /* locale.h */ diff --git a/include/malloc.h b/include/malloc.h new file mode 100644 index 0000000..12834a5 --- /dev/null +++ b/include/malloc.h @@ -0,0 +1,198 @@ +/* Prototypes and definition for malloc implementation. + Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_H +#define _MALLOC_H 1 + +#include + +/* + `ptmalloc', a malloc implementation for multiple threads without + lock contention, by Wolfram Gloger . + See the files `ptmalloc.c' or `COPYRIGHT' for copying conditions. + + VERSION 2.6.4-pt Wed Dec 4 00:35:54 MET 1996 + + This work is mainly derived from malloc-2.6.4 by Doug Lea + , which is available from: + + ftp://g.oswego.edu/pub/misc/malloc.c + + This trimmed-down header file only provides function prototypes and + the exported data structures. For more detailed function + descriptions and compile-time options, see the source file + `ptmalloc.c'. +*/ + +#if defined(__STDC__) || defined (__cplusplus) +# include +# define __malloc_ptr_t void * +#else +# undef size_t +# define size_t unsigned int +# undef ptrdiff_t +# define ptrdiff_t int +# define __malloc_ptr_t char * +#endif + +#ifdef _LIBC +/* Used by GNU libc internals. */ +# define __malloc_size_t size_t +# define __malloc_ptrdiff_t ptrdiff_t +#elif !defined __attribute_malloc__ +# define __attribute_malloc__ +#endif + +#ifdef __GNUC__ + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. */ +#ifndef __THROW +# if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif +# define __MALLOC_P(args) args __THROW +/* This macro will be used for functions which might take C++ callback + functions. */ +# define __MALLOC_PMT(args) args + +#else /* Not GCC. */ + +# define __THROW + +# if (defined __STDC__ && __STDC__) || defined __cplusplus + +# define __MALLOC_P(args) args +# define __MALLOC_PMT(args) args + +# else /* Not ANSI C or C++. */ + +# define __MALLOC_P(args) () /* No prototypes. */ +# define __MALLOC_PMT(args) () + +# endif /* ANSI C or C++. */ + +#endif /* GCC. */ + +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((__malloc_ptr_t) 0) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Allocate SIZE bytes of memory. */ +extern __malloc_ptr_t malloc __MALLOC_P ((size_t __size)) __attribute_malloc__; + +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern __malloc_ptr_t calloc __MALLOC_P ((size_t __nmemb, size_t __size)) + __attribute_malloc__; + +/* Re-allocate the previously allocated block in __ptr, making the new + block SIZE bytes long. */ +extern __malloc_ptr_t realloc __MALLOC_P ((__malloc_ptr_t __ptr, + size_t __size)) + __attribute_malloc__; + +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free __MALLOC_P ((__malloc_ptr_t __ptr)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ +extern __malloc_ptr_t memalign __MALLOC_P ((size_t __alignment, size_t __size)); + +/* Allocate SIZE bytes on a page boundary. */ +extern __malloc_ptr_t valloc __MALLOC_P ((size_t __size)) __attribute_malloc__; + +#ifdef __MALLOC_STANDARD__ + +/* SVID2/XPG mallinfo structure */ +struct mallinfo { + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ +}; + +/* Returns a copy of the updated current mallinfo. */ +extern struct mallinfo mallinfo __MALLOC_P ((void)); + +/* Release all but __pad bytes of freed top-most memory back to the + system. Return 1 if successful, else 0. */ +extern int malloc_trim(size_t pad); + +#include +/* Prints brief summary statistics to the specified file. + * Writes to stderr if file is NULL. */ +extern void malloc_stats(FILE *file); + +/* SVID2/XPG mallopt options */ +#ifndef M_MXFAST +# define M_MXFAST 1 /* UNUSED in this malloc */ +#endif +#ifndef M_NLBLKS +# define M_NLBLKS 2 /* UNUSED in this malloc */ +#endif +#ifndef M_GRAIN +# define M_GRAIN 3 /* UNUSED in this malloc */ +#endif +#ifndef M_KEEP +# define M_KEEP 4 /* UNUSED in this malloc */ +#endif + +/* mallopt options that actually do something */ +#define M_TRIM_THRESHOLD -1 +#define M_TOP_PAD -2 +#define M_MMAP_THRESHOLD -3 +#define M_MMAP_MAX -4 +#define M_CHECK_ACTION -5 +#define M_PERTURB -6 + +/* General SVID/XPG interface to tunable parameters. */ +extern int mallopt __MALLOC_P ((int __param, int __val)); + +#endif /* __MALLOC_STANDARD__ */ + +/* uClibc may use malloc internally in situations where user can not be + * notified about out-of-memory condition. In this situation uClibc will + * call __uc_malloc_failed if it is non-NULL, and retry allocation + * if it returns. If __uc_malloc_failed is NULL, uclibc will _exit(1). + * NB: do not use stdio in __uc_malloc_failed handler! */ +extern void *__uc_malloc(size_t size); +extern void (*__uc_malloc_failed)(size_t size); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* malloc.h */ diff --git a/include/math.h b/include/math.h new file mode 100644 index 0000000..ae5d6ec --- /dev/null +++ b/include/math.h @@ -0,0 +1,468 @@ +/* Declarations for math functions. + Copyright (C) 1991-1993, 1995-1999, 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.12 Mathematics + */ + +#ifndef _MATH_H +#define _MATH_H 1 + +#include + +__BEGIN_DECLS + +/* Get machine-dependent HUGE_VAL value (returned on overflow). + On all IEEE754 machines, this is +Infinity. */ +#include +#ifdef __USE_ISOC99 +# include +# include + +/* Get machine-dependent INFINITY value. */ +# include + +/* Get machine-dependent NAN value (returned for some domain errors). */ +# include +#endif /* __USE_ISOC99 */ + +/* Get general and ISO C99 specific information. */ +#include + +/* The file contains the prototypes for all the + actual math functions. These macros are used for those prototypes, + so we can easily declare each function as both `name' and `__name', + and can declare the float versions `namef' and `__namef'. */ + +#define __MATHCALL(function,suffix, args) \ + __MATHDECL (_Mdouble_,function,suffix, args) +#define __MATHDECL(type, function,suffix, args) \ + __MATHDECL_1(type, function,suffix, args); \ + __MATHDECL_1(type, __CONCAT(__,function),suffix, args) +#define __MATHCALLX(function,suffix, args, attrib) \ + __MATHDECLX (_Mdouble_,function,suffix, args, attrib) +#define __MATHDECLX(type, function,suffix, args, attrib) \ + __MATHDECL_1(type, function,suffix, args) __attribute__ (attrib); \ + __MATHDECL_1(type, __CONCAT(__,function),suffix, args) __attribute__ (attrib) +#define __MATHDECL_1(type, function,suffix, args) \ + extern type __MATH_PRECNAME(function,suffix) args __THROW + +#define _Mdouble_ double +#define __MATH_PRECNAME(name,r) __CONCAT(name,r) +# define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_STD +# define _Mdouble_END_NAMESPACE __END_NAMESPACE_STD +#include +#undef _Mdouble_ +#undef _Mdouble_BEGIN_NAMESPACE +#undef _Mdouble_END_NAMESPACE +#undef __MATH_PRECNAME + +#if defined __USE_MISC || defined __USE_ISOC99 + + +/* Include the file of declarations again, this time using `float' + instead of `double' and appending f to each function name. */ + +# ifndef _Mfloat_ +# define _Mfloat_ float +# endif +# define _Mdouble_ _Mfloat_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name,r) name##f##r +# else +# define __MATH_PRECNAME(name,r) name/**/f/**/r +# endif +# define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99 +# define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99 +# include +# undef _Mdouble_ +# undef _Mdouble_BEGIN_NAMESPACE +# undef _Mdouble_END_NAMESPACE +# undef __MATH_PRECNAME + +# if (__STDC__ - 0 || __GNUC__ - 0) \ + && (defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ || defined __LDBL_COMPAT) +# ifdef __LDBL_COMPAT + +# ifdef __USE_ISOC99 +extern float __nldbl_nexttowardf (float __x, long double __y) + __THROW __attribute__ ((__const__)); +# ifdef __REDIRECT_NTH +extern float __REDIRECT_NTH (nexttowardf, (float __x, long double __y), + __nldbl_nexttowardf) + __attribute__ ((__const__)); +extern double __REDIRECT_NTH (nexttoward, (double __x, long double __y), + nextafter) __attribute__ ((__const__)); +extern long double __REDIRECT_NTH (nexttowardl, + (long double __x, long double __y), + nextafter) __attribute__ ((__const__)); +# endif +# endif + +/* Include the file of declarations again, this time using `long double' + instead of `double' and appending l to each function name. */ + +# undef __MATHDECL_1 +# define __MATHDECL_2(type, function,suffix, args, alias) \ + extern type __REDIRECT_NTH(__MATH_PRECNAME(function,suffix), \ + args, alias) +# define __MATHDECL_1(type, function,suffix, args) \ + __MATHDECL_2(type, function,suffix, args, __CONCAT(function,suffix)) +# endif + +# ifndef _Mlong_double_ +# define _Mlong_double_ long double +# endif +# define _Mdouble_ _Mlong_double_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name,r) name##l##r +# else +# define __MATH_PRECNAME(name,r) name/**/l/**/r +# endif +# define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99 +# define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99 +# include +# undef _Mdouble_ +# undef _Mdouble_BEGIN_NAMESPACE +# undef _Mdouble_END_NAMESPACE +# undef __MATH_PRECNAME + +# endif /* __STDC__ || __GNUC__ */ + +#endif /* Use misc or ISO C99. */ +#undef __MATHDECL_1 +#undef __MATHDECL +#undef __MATHCALL + + +#if defined __USE_MISC || defined __USE_XOPEN +/* This variable is used by `gamma' and `lgamma'. */ +extern int signgam; +#endif + + +/* ISO C99 defines some generic macros which work on any data type. */ +#ifdef __USE_ISOC99 + +/* Get the architecture specific values describing the floating-point + evaluation. The following symbols will get defined: + + float_t floating-point type at least as wide as `float' used + to evaluate `float' expressions + double_t floating-point type at least as wide as `double' used + to evaluate `double' expressions + + FLT_EVAL_METHOD + Defined to + 0 if `float_t' is `float' and `double_t' is `double' + 1 if `float_t' and `double_t' are `double' + 2 if `float_t' and `double_t' are `long double' + else `float_t' and `double_t' are unspecified + + INFINITY representation of the infinity value of type `float' + + FP_FAST_FMA + FP_FAST_FMAF + FP_FAST_FMAL + If defined it indicates that the `fma' function + generally executes about as fast as a multiply and an add. + This macro is defined only iff the `fma' function is + implemented directly with a hardware multiply-add instructions. + + FP_ILOGB0 Expands to a value returned by `ilogb (0.0)'. + FP_ILOGBNAN Expands to a value returned by `ilogb (NAN)'. + + DECIMAL_DIG Number of decimal digits supported by conversion between + decimal and all internal floating-point formats. + +*/ + +/* All floating-point numbers can be put in one of these categories. */ +enum + { + FP_NAN, +# define FP_NAN FP_NAN + FP_INFINITE, +# define FP_INFINITE FP_INFINITE + FP_ZERO, +# define FP_ZERO FP_ZERO + FP_SUBNORMAL, +# define FP_SUBNORMAL FP_SUBNORMAL + FP_NORMAL +# define FP_NORMAL FP_NORMAL + }; + +/* Return number of classification appropriate for X. */ +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define fpclassify(x) \ + (sizeof (x) == sizeof (float) ? __fpclassifyf (x) : __fpclassify (x)) +# else +# define fpclassify(x) \ + (sizeof (x) == sizeof (float) \ + ? __fpclassifyf (x) \ + : sizeof (x) == sizeof (double) \ + ? __fpclassify (x) : __fpclassifyl (x)) +# endif + +/* Return nonzero value if sign of X is negative. */ +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define signbit(x) \ + (sizeof (x) == sizeof (float) ? __signbitf (x) : __signbit (x)) +# else +# define signbit(x) \ + (sizeof (x) == sizeof (float) \ + ? __signbitf (x) \ + : sizeof (x) == sizeof (double) \ + ? __signbit (x) : __signbitl (x)) +# endif + +/* Return nonzero value if X is not +-Inf or NaN. */ +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define isfinite(x) \ + (sizeof (x) == sizeof (float) ? __finitef (x) : __finite (x)) +# else +# define isfinite(x) \ + (sizeof (x) == sizeof (float) \ + ? __finitef (x) \ + : sizeof (x) == sizeof (double) \ + ? __finite (x) : __finitel (x)) +# endif + +/* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */ +# define isnormal(x) (fpclassify (x) == FP_NORMAL) + +/* Return nonzero value if X is a NaN. We could use `fpclassify' but + we already have this functions `__isnan' and it is faster. */ +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define isnan(x) \ + (sizeof (x) == sizeof (float) ? __isnanf (x) : __isnan (x)) +# else +# define isnan(x) \ + (sizeof (x) == sizeof (float) \ + ? __isnanf (x) \ + : sizeof (x) == sizeof (double) \ + ? __isnan (x) : __isnanl (x)) +# endif + +/* Return nonzero value is X is positive or negative infinity. */ +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define isinf(x) \ + (sizeof (x) == sizeof (float) ? __isinff (x) : __isinf (x)) +# else +# define isinf(x) \ + (sizeof (x) == sizeof (float) \ + ? __isinff (x) \ + : sizeof (x) == sizeof (double) \ + ? __isinf (x) : __isinfl (x)) +# endif + +/* Bitmasks for the math_errhandling macro. */ +# define MATH_ERRNO 1 /* errno set by math functions. */ +# define MATH_ERREXCEPT 2 /* Exceptions raised by math functions. */ + +#endif /* Use ISO C99. */ + +#ifdef __USE_MISC +/* Support for various different standard error handling behaviors. */ +typedef enum +{ + _IEEE_ = -1, /* According to IEEE 754/IEEE 854. */ + _SVID_, /* According to System V, release 4. */ + _XOPEN_, /* Nowadays also Unix98. */ + _POSIX_, + _ISOC_ /* Actually this is ISO C99. */ +} _LIB_VERSION_TYPE; + +/* This variable can be changed at run-time to any of the values above to + affect floating point error handling behavior (it may also be necessary + to change the hardware FPU exception settings). */ +extern _LIB_VERSION_TYPE _LIB_VERSION; +#endif + + +#ifdef __USE_SVID +/* In SVID error handling, `matherr' is called with this description + of the exceptional condition. + + We have a problem when using C++ since `exception' is a reserved + name in C++. */ +# ifdef __cplusplus +struct __exception +# else +struct exception +# endif + { + int type; + char *name; + double arg1; + double arg2; + double retval; + }; + +# ifdef __cplusplus +extern int matherr (struct __exception *__exc) throw (); +# else +extern int matherr (struct exception *__exc); +# endif + +# define X_TLOSS 1.41484755040568800000e+16 + +/* Types of exceptions in the `type' field. */ +# define DOMAIN 1 +# define SING 2 +# define OVERFLOW 3 +# define UNDERFLOW 4 +# define TLOSS 5 +# define PLOSS 6 + +/* SVID mode specifies returning this large value instead of infinity. */ +# define HUGE 3.40282347e+38F + +#else /* !SVID */ + +# ifdef __USE_XOPEN +/* X/Open wants another strange constant. */ +# define MAXFLOAT 3.40282347e+38F +# endif + +#endif /* SVID */ + + +/* Some useful constants. */ +#if defined __USE_BSD || defined __USE_XOPEN +# 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) */ +#endif + +/* The above constants are not adequate for computation using `long double's. + Therefore we provide as an extension constants with similar names as a + GNU extension. Provide enough digits for the 128-bit IEEE quad. */ +#ifdef __USE_GNU +# define M_El 2.7182818284590452353602874713526625L /* e */ +# define M_LOG2El 1.4426950408889634073599246810018921L /* log_2 e */ +# define M_LOG10El 0.4342944819032518276511289189166051L /* log_10 e */ +# define M_LN2l 0.6931471805599453094172321214581766L /* log_e 2 */ +# define M_LN10l 2.3025850929940456840179914546843642L /* log_e 10 */ +# define M_PIl 3.1415926535897932384626433832795029L /* pi */ +# define M_PI_2l 1.5707963267948966192313216916397514L /* pi/2 */ +# define M_PI_4l 0.7853981633974483096156608458198757L /* pi/4 */ +# define M_1_PIl 0.3183098861837906715377675267450287L /* 1/pi */ +# define M_2_PIl 0.6366197723675813430755350534900574L /* 2/pi */ +# define M_2_SQRTPIl 1.1283791670955125738961589031215452L /* 2/sqrt(pi) */ +# define M_SQRT2l 1.4142135623730950488016887242096981L /* sqrt(2) */ +# define M_SQRT1_2l 0.7071067811865475244008443621048490L /* 1/sqrt(2) */ +#endif + + +/* When compiling in strict ISO C compatible mode we must not use the + inline functions since they, among other things, do not set the + `errno' variable correctly. */ +#if defined __STRICT_ANSI__ && !defined __NO_MATH_INLINES +# define __NO_MATH_INLINES 1 +#endif + +#if defined __USE_ISOC99 && __GNUC_PREREQ(2,97) +/* ISO C99 defines some macros to compare number while taking care for + unordered numbers. Many FPUs provide special instructions to support + these operations. Generic support in GCC for these as builtins went + in before 3.0.0, but not all cpus added their patterns. We define + versions that use the builtins here, and will + undef/redefine as appropriate for the specific GCC version in use. */ +# define isgreater(x, y) __builtin_isgreater(x, y) +# define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) +# define isless(x, y) __builtin_isless(x, y) +# define islessequal(x, y) __builtin_islessequal(x, y) +# define islessgreater(x, y) __builtin_islessgreater(x, y) +# define isunordered(u, v) __builtin_isunordered(u, v) +#endif + +/* Get machine-dependent inline versions (if there are any). */ +#ifdef __USE_EXTERN_INLINES +# include +#endif + +#ifdef __USE_ISOC99 +/* If we've still got undefined comparison macros, provide defaults. */ + +/* Return nonzero value if X is greater than Y. */ +# ifndef isgreater +# define isgreater(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x > __y; })) +# endif + +/* Return nonzero value if X is greater than or equal to Y. */ +# ifndef isgreaterequal +# define isgreaterequal(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x >= __y; })) +# endif + +/* Return nonzero value if X is less than Y. */ +# ifndef isless +# define isless(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x < __y; })) +# endif + +/* Return nonzero value if X is less than or equal to Y. */ +# ifndef islessequal +# define islessequal(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x <= __y; })) +# endif + +/* Return nonzero value if either X is less than Y or Y is less than X. */ +# ifndef islessgreater +# define islessgreater(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && (__x < __y || __y < __x); })) +# endif + +/* Return nonzero value if arguments are unordered. */ +# ifndef isunordered +# define isunordered(u, v) \ + (__extension__ \ + ({ __typeof__(u) __u = (u); __typeof__(v) __v = (v); \ + fpclassify (__u) == FP_NAN || fpclassify (__v) == FP_NAN; })) +# endif + +#endif + +__END_DECLS + + +#endif /* math.h */ diff --git a/include/memory.h b/include/memory.h new file mode 100644 index 0000000..743fa6a --- /dev/null +++ b/include/memory.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * SVID + */ + +#ifndef _MEMORY_H +#define _MEMORY_H 1 + +#include + + +#ifndef _STRING_H +# include +#endif /* string.h */ + + +#endif /* memory.h */ diff --git a/include/mntent.h b/include/mntent.h new file mode 100644 index 0000000..a82e953 --- /dev/null +++ b/include/mntent.h @@ -0,0 +1,98 @@ +/* Utilities for reading/writing fstab, mtab, etc. + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MNTENT_H +#define _MNTENT_H 1 + +#include +#define __need_FILE +#include +#include + + +/* File listing canonical interesting mount points. */ +#define MNTTAB _PATH_MNTTAB /* Deprecated alias. */ + +/* File listing currently active mount points. */ +#define MOUNTED _PATH_MOUNTED /* Deprecated alias. */ + + +/* General filesystem types. */ +#define MNTTYPE_IGNORE "ignore" /* Ignore this entry. */ +#define MNTTYPE_NFS "nfs" /* Network file system. */ +#define MNTTYPE_SWAP "swap" /* Swap device. */ + + +/* Generic mount options. */ +#define MNTOPT_DEFAULTS "defaults" /* Use all default options. */ +#define MNTOPT_RO "ro" /* Read only. */ +#define MNTOPT_RW "rw" /* Read/write. */ +#define MNTOPT_SUID "suid" /* Set uid allowed. */ +#define MNTOPT_NOSUID "nosuid" /* No set uid allowed. */ +#define MNTOPT_NOAUTO "noauto" /* Do not auto mount. */ + + +__BEGIN_DECLS + +/* Structure describing a mount table entry. */ +struct mntent + { + char *mnt_fsname; /* Device or server for filesystem. */ + char *mnt_dir; /* Directory mounted on. */ + char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */ + char *mnt_opts; /* Comma-separated options for fs. */ + int mnt_freq; /* Dump frequency (in days). */ + int mnt_passno; /* Pass number for `fsck'. */ + }; + + +/* Prepare to begin reading and/or writing mount table entries from the + beginning of FILE. MODE is as for `fopen'. */ +extern FILE *setmntent (__const char *__file, __const char *__mode) __THROW; + +/* Read one mount table entry from STREAM. Returns a pointer to storage + reused on the next call, or null for EOF or error (use feof/ferror to + check). */ +extern struct mntent *getmntent (FILE *__stream) __THROW; + +#ifdef __USE_MISC +/* Reentrant version of the above function. */ +extern struct mntent *getmntent_r (FILE *__restrict __stream, + struct mntent *__restrict __result, + char *__restrict __buffer, + int __bufsize) __THROW; +#endif + +/* Write the mount table entry described by MNT to STREAM. + Return zero on success, nonzero on failure. */ +extern int addmntent (FILE *__restrict __stream, + __const struct mntent *__restrict __mnt) __THROW; + +/* Close a stream opened with `setmntent'. */ +extern int endmntent (FILE *__stream) __THROW; + +/* Search MNT->mnt_opts for an option matching OPT. + Returns the address of the substring, or null if none found. */ +extern char *hasmntopt (__const struct mntent *__mnt, + __const char *__opt) __THROW; + + +__END_DECLS + +#endif /* mntent.h */ diff --git a/include/mqueue.h b/include/mqueue.h new file mode 100644 index 0000000..f75b506 --- /dev/null +++ b/include/mqueue.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MQUEUE_H +#define _MQUEUE_H 1 + +#include +#if defined __UCLIBC_HAS_REALTIME__ || \ + defined __UCLIBC_HAS_ADVANCED_REALTIME__ +#include +#include +#define __need_sigevent_t +#include +#define __need_timespec +#include +/* Get the definition of mqd_t and struct mq_attr. */ +#include +#endif + +__BEGIN_DECLS +#if defined __UCLIBC_HAS_REALTIME__ +/* Establish connection between a process and a message queue NAME and + return message queue descriptor or (mqd_t) -1 on error. OFLAG determines + the type of access used. If O_CREAT is on OFLAG, the third argument is + taken as a `mode_t', the mode of the created message queue, and the fourth + argument is taken as `struct mq_attr *', pointer to message queue + attributes. If the fourth argument is NULL, default attributes are + used. */ +extern mqd_t mq_open (const char *__name, int __oflag, ...) __THROW; + +/* Removes the association between message queue descriptor MQDES and its + message queue. */ +extern int mq_close (mqd_t __mqdes) __THROW; + +/* Query status and attributes of message queue MQDES. */ +extern int mq_getattr (mqd_t __mqdes, struct mq_attr *__mqstat) __THROW; + +/* Set attributes associated with message queue MQDES and if OMQSTAT is + not NULL also query its old attributes. */ +extern int mq_setattr (mqd_t __mqdes, + const struct mq_attr *__restrict __mqstat, + struct mq_attr *__restrict __omqstat) __THROW; + +/* Remove message queue named NAME. */ +extern int mq_unlink (const char *__name) __THROW; + +/* Register notification issued upon message arrival to an empty + message queue MQDES. */ +extern int mq_notify (mqd_t __mqdes, const struct sigevent *__notification) + __THROW; + +/* Receive the oldest from highest priority messages in message queue + MQDES. */ +extern ssize_t mq_receive (mqd_t __mqdes, char *__msg_ptr, size_t __msg_len, + unsigned int *__msg_prio); + +/* Add message pointed by MSG_PTR to message queue MQDES. */ +extern int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len, + unsigned int __msg_prio); +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Receive the oldest from highest priority messages in message queue + MQDES, stop waiting if ABS_TIMEOUT expires. */ +extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr, + size_t __msg_len, + unsigned int *__restrict __msg_prio, + const struct timespec *__restrict __abs_timeout); + +/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking + on full message queue if ABS_TIMEOUT expires. */ +extern int mq_timedsend (mqd_t __mqdes, const char *__msg_ptr, + size_t __msg_len, unsigned int __msg_prio, + const struct timespec *__abs_timeout); +#endif + +__END_DECLS + +#endif /* mqueue.h */ diff --git a/include/net/ethernet.h b/include/net/ethernet.h new file mode 100644 index 0000000..7ca8e83 --- /dev/null +++ b/include/net/ethernet.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the FreeBSD version of this file. Curiously, that file + lacks a copyright in the header. */ + +#ifndef __NET_ETHERNET_H +#define __NET_ETHERNET_H 1 + +#include +#include +#include /* IEEE 802.3 Ethernet constants */ + +__BEGIN_DECLS + +/* This is a name for the 48 bit ethernet address available on many + systems. */ +struct ether_addr +{ + u_int8_t ether_addr_octet[ETH_ALEN]; +} __attribute__ ((__packed__)); + +/* 10Mb/s ethernet header */ +struct ether_header +{ + u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ + u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ + u_int16_t ether_type; /* packet type ID field */ +} __attribute__ ((__packed__)); + +/* Ethernet protocol ID's */ +#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */ +#define ETHERTYPE_IP 0x0800 /* IP */ +#define ETHERTYPE_ARP 0x0806 /* Address resolution */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ + +#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ +#define ETHER_TYPE_LEN 2 /* bytes in type field */ +#define ETHER_CRC_LEN 4 /* bytes in CRC field */ +#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ +#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) /* min packet length */ +#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */ + +/* make sure ethenet length is valid */ +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHERMTU ETH_DATA_LEN +#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +__END_DECLS + +#endif /* net/ethernet.h */ diff --git a/include/net/if.h b/include/net/if.h new file mode 100644 index 0000000..ebb3e9f --- /dev/null +++ b/include/net/if.h @@ -0,0 +1,205 @@ +/* net/if.h -- declarations for inquiring about network interfaces + Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_H +#define _NET_IF_H 1 + +#include + +#ifdef __USE_MISC +# include +# include +#endif + + +/* Length of interface name. */ +#define IF_NAMESIZE 16 + +struct if_nameindex + { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "eth0", ... */ + }; + + +#ifdef __USE_MISC +/* Standard interface flags. */ +enum + { + IFF_UP = 0x1, /* Interface is up. */ +# define IFF_UP IFF_UP + IFF_BROADCAST = 0x2, /* Broadcast address valid. */ +# define IFF_BROADCAST IFF_BROADCAST + IFF_DEBUG = 0x4, /* Turn on debugging. */ +# define IFF_DEBUG IFF_DEBUG + IFF_LOOPBACK = 0x8, /* Is a loopback net. */ +# define IFF_LOOPBACK IFF_LOOPBACK + IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link. */ +# define IFF_POINTOPOINT IFF_POINTOPOINT + IFF_NOTRAILERS = 0x20, /* Avoid use of trailers. */ +# define IFF_NOTRAILERS IFF_NOTRAILERS + IFF_RUNNING = 0x40, /* Resources allocated. */ +# define IFF_RUNNING IFF_RUNNING + IFF_NOARP = 0x80, /* No address resolution protocol. */ +# define IFF_NOARP IFF_NOARP + IFF_PROMISC = 0x100, /* Receive all packets. */ +# define IFF_PROMISC IFF_PROMISC + + /* Not supported */ + IFF_ALLMULTI = 0x200, /* Receive all multicast packets. */ +# define IFF_ALLMULTI IFF_ALLMULTI + + IFF_MASTER = 0x400, /* Master of a load balancer. */ +# define IFF_MASTER IFF_MASTER + IFF_SLAVE = 0x800, /* Slave of a load balancer. */ +# define IFF_SLAVE IFF_SLAVE + + IFF_MULTICAST = 0x1000, /* Supports multicast. */ +# define IFF_MULTICAST IFF_MULTICAST + + IFF_PORTSEL = 0x2000, /* Can set media type. */ +# define IFF_PORTSEL IFF_PORTSEL + IFF_AUTOMEDIA = 0x4000, /* Auto media select active. */ +# define IFF_AUTOMEDIA IFF_AUTOMEDIA + IFF_DYNAMIC = 0x8000 /* Dialup device with changing addresses. */ +# define IFF_DYNAMIC IFF_DYNAMIC + }; + +/* The ifaddr structure contains information about one address of an + interface. They are maintained by the different address families, + are allocated and attached when an address is set, and are linked + together so all addresses for an interface can be located. */ + +struct ifaddr + { + struct sockaddr ifa_addr; /* Address of interface. */ + union + { + struct sockaddr ifu_broadaddr; + struct sockaddr ifu_dstaddr; + } ifa_ifu; + struct iface *ifa_ifp; /* Back-pointer to interface. */ + struct ifaddr *ifa_next; /* Next address for interface. */ + }; + +# define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ +# define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ + +/* Device mapping structure. I'd just gone off and designed a + beautiful scheme using only loadable modules with arguments for + driver options and along come the PCMCIA people 8) + + Ah well. The get() side of this is good for WDSETUP, and it'll be + handy for debugging things. The set side is fine for now and being + very small might be worth keeping for clean configuration. */ + +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; + /* 3 bytes spare */ + }; + +/* Interface request structure used for socket ioctl's. All interface + ioctl's must have parameter definitions which begin with ifr_name. + The remainder may be interface specific. */ + +struct ifreq + { +# define IFHWADDRLEN 6 +# define IFNAMSIZ IF_NAMESIZE + union + { + char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ + } 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]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + __caddr_t ifru_data; + } ifr_ifru; + }; +# define ifr_name ifr_ifrn.ifrn_name /* interface name */ +# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +# define ifr_addr ifr_ifru.ifru_addr /* address */ +# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +# define ifr_flags ifr_ifru.ifru_flags /* flags */ +# define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +# define ifr_map ifr_ifru.ifru_map /* device map */ +# define ifr_slave ifr_ifru.ifru_slave /* slave device */ +# define ifr_data ifr_ifru.ifru_data /* for use by interface */ +# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */ +# define ifr_newname ifr_ifru.ifru_newname /* New name */ +# 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) + + +/* Structure used in SIOCGIFCONF request. Used to retrieve interface + configuration for machine (useful for programs which must know all + networks accessible). */ + +struct ifconf + { + int ifc_len; /* Size of buffer. */ + union + { + __caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; + }; +# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */ +# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */ +# define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */ +#endif /* Misc. */ + +__BEGIN_DECLS + +/* Convert an interface name to an index, and vice versa. */ +extern unsigned int if_nametoindex (__const char *__ifname) __THROW; +extern char *if_indextoname (unsigned int __ifindex, char *__ifname) __THROW; + +/* Return a list of all interfaces and their indices. */ +extern struct if_nameindex *if_nameindex (void) __THROW; + +/* Free the data returned from if_nameindex. */ +extern void if_freenameindex (struct if_nameindex *__ptr) __THROW; + +__END_DECLS + +#endif /* net/if.h */ diff --git a/include/net/if_arp.h b/include/net/if_arp.h new file mode 100644 index 0000000..46f035b --- /dev/null +++ b/include/net/if_arp.h @@ -0,0 +1,176 @@ +/* Definitions for Address Resolution Protocol. + Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_IF_ARP_H + +#define _NET_IF_ARP_H 1 +#include + +#include +#include + +__BEGIN_DECLS + +/* Some internals from deep down in the kernel. */ +#define MAX_ADDR_LEN 7 + + +/* This structure defines an ethernet arp header. */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request. */ +#define ARPOP_REPLY 2 /* ARP reply. */ +#define ARPOP_RREQUEST 3 /* RARP request. */ +#define ARPOP_RREPLY 4 /* RARP reply. */ +#define ARPOP_InREQUEST 8 /* InARP request. */ +#define ARPOP_InREPLY 9 /* InARP reply. */ +#define ARPOP_NAK 10 /* (ATM)ARP NAK. */ + +/* See RFC 826 for protocol description. ARP packets are variable + in size; the arphdr structure defines the fixed-length portion. + Protocol type values are the same as those for 10 Mb/s Ethernet. + It is followed by the variable-sized fields ar_sha, arp_spa, + arp_tha and arp_tpa in that order, according to the lengths + specified. Field names used correspond to RFC 826. */ + +struct arphdr + { + unsigned short int ar_hrd; /* Format of hardware address. */ + unsigned short int ar_pro; /* Format of protocol address. */ + unsigned char ar_hln; /* Length of hardware address. */ + unsigned char ar_pln; /* Length of protocol address. */ + unsigned short int ar_op; /* ARP opcode (command). */ +#if 0 + /* Ethernet looks like this : This bit is variable sized + however... */ + unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */ + unsigned char __ar_sip[4]; /* Sender IP address. */ + unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */ + unsigned char __ar_tip[4]; /* Target IP address. */ +#endif + }; + + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* From KA9Q: NET/ROM pseudo. */ +#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet. */ +#define ARPHRD_AX25 3 /* AX.25 Level 2. */ +#define ARPHRD_PRONET 4 /* PROnet token ring. */ +#define ARPHRD_CHAOS 5 /* Chaosnet. */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB. */ +#define ARPHRD_ARCNET 7 /* ARCnet. */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk. */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI. */ +#define ARPHRD_ATM 19 /* ATM. */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id). */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734. */ +#define ARPHRD_EUI64 27 /* EUI-64. */ +#define ARPHRD_INFINIBAND 32 /* InfiniBand. */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type. */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25. */ +#define ARPHDR_HWX25 272 /* Boards with X.25 in firmware. */ +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 /* Cisco HDLC. */ +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 /* LAPB. */ +#define ARPHRD_DDCMP 517 /* Digital's DDCMP. */ +#define ARPHRD_RAWHDLC 518 /* Raw HDLC. */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel. */ +#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel. */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device. */ +#define ARPHRD_SKIP 771 /* SKIP vif. */ +#define ARPHRD_LOOPBACK 772 /* Loopback device. */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device. */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface. */ +#define ARPHRD_BIF 775 /* AP1000 BIF. */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4. */ +#define ARPHRD_IPDDP 777 /* IP-in-DDP tunnel. */ +#define ARPHRD_IPGRE 778 /* GRE over IP. */ +#define ARPHRD_PIMREG 779 /* PIMSM register interface. */ +#define ARPHRD_HIPPI 780 /* High Performance Parallel I'face. */ +#define ARPHRD_ASH 781 /* (Nexus Electronics) Ash. */ +#define ARPHRD_ECONET 782 /* Acorn Econet. */ +#define ARPHRD_IRDA 783 /* Linux-IrDA. */ +#define ARPHRD_FCPP 784 /* Point to point fibrechanel. */ +#define ARPHRD_FCAL 785 /* Fibrechanel arbitrated loop. */ +#define ARPHRD_FCPL 786 /* Fibrechanel public loop. */ +#define ARPHRD_FCFABRIC 787 /* Fibrechanel fabric. */ +#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR. */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11. */ + +/* ARP ioctl request. */ +struct arpreq + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + char arp_dev[16]; + }; + +struct arpreq_old + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + }; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* Completed entry (ha valid). */ +#define ATF_PERM 0x04 /* Permanent entry. */ +#define ATF_PUBL 0x08 /* Publish entry. */ +#define ATF_USETRAILERS 0x10 /* Has requested trailers. */ +#define ATF_NETMASK 0x20 /* Want to use a netmask (only + for proxy entries). */ +#define ATF_DONTPUB 0x40 /* Don't answer this addresses. */ +#define ATF_MAGIC 0x80 /* Automatically added entry. */ + + +/* Support for the user space arp daemon, arpd. */ +#define ARPD_UPDATE 0x01 +#define ARPD_LOOKUP 0x02 +#define ARPD_FLUSH 0x03 + +struct arpd_request + { + unsigned short int req; /* Request type. */ + u_int32_t ip; /* IP address of entry. */ + unsigned long int dev; /* Device entry is tied to. */ + unsigned long int stamp; + unsigned long int updated; + unsigned char ha[MAX_ADDR_LEN]; /* Hardware address. */ + }; + +__END_DECLS + +#endif /* net/if_arp.h */ diff --git a/include/net/if_packet.h b/include/net/if_packet.h new file mode 100644 index 0000000..e5184e7 --- /dev/null +++ b/include/net/if_packet.h @@ -0,0 +1,37 @@ +/* Definitions for use with Linux SOCK_PACKET sockets. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __IF_PACKET_H +#define __IF_PACKET_H + +#include +#include + +/* This is the SOCK_PACKET address structure as used in Linux 2.0. + From Linux 2.1 the AF_PACKET interface is preferred and you should + consider using it in place of this one. */ + +struct sockaddr_pkt + { + __SOCKADDR_COMMON (spkt_); + unsigned char spkt_device[14]; + unsigned short spkt_protocol; + }; + +#endif diff --git a/include/net/if_ppp.h b/include/net/if_ppp.h new file mode 100644 index 0000000..1b1c3ea --- /dev/null +++ b/include/net/if_ppp.h @@ -0,0 +1,169 @@ +/* From: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY 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 UNIVERSITY 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. + * + */ + +/* + * ==FILEVERSION 960926== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, please set the above date. + * if_ppp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_ppp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + + +#ifndef __NET_IF_PPP_H +#define __NET_IF_PPP_H 1 + +#include +#include + +#include +#include +#include + +__BEGIN_DECLS + +/* + * Packet sizes + */ + +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ +#define PPP_VERSION "2.2.0" +#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ +#define PROTO_IPX 0x002b /* protocol numbers */ +#define PROTO_DNA_RT 0x0027 /* DNA Routing */ + + +/* + * Bit definitions for flags. + */ + +#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ +#define SC_COMP_AC 0x00000002 /* header compression (output) */ +#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ +#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ +#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ +#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ +#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ +#define SC_DEBUG 0x00010000 /* enable debug messages */ +#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ +#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ +#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ +#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_MASK 0x0fE0ffff /* bits that user can change */ + +/* state bits */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_VJ_RESET 0x20000000 /* Need to reset the VJ decompressor */ +#define SC_XMIT_BUSY 0x10000000 /* ppp_write_wakeup is active */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */ +#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */ + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP protocol, e.g. PPP_IP */ + enum NPmode mode; +}; + +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_int8_t *ptr; + u_int32_t length; + int transmit; +}; + +struct ifpppstatsreq { + struct ifreq b; + struct ppp_stats stats; /* statistic information */ +}; + +struct ifpppcstatsreq { + struct ifreq b; + struct ppp_comp_stats stats; +}; + +#define ifr__name b.ifr_ifrn.ifrn_name +#define stats_ptr b.ifr_ifru.ifru_data + +/* + * Ioctl definitions. + */ + +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ +#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ +#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + +#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) +#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */ +#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2) + +#if !defined(ifr_mtu) +#define ifr_mtu ifr_ifru.ifru_metric +#endif + +__END_DECLS + +#endif /* net/if_ppp.h */ diff --git a/include/net/if_shaper.h b/include/net/if_shaper.h new file mode 100644 index 0000000..7060af3 --- /dev/null +++ b/include/net/if_shaper.h @@ -0,0 +1,59 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SHAPER_H +#define _NET_IF_SHAPER_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +#define SHAPER_QLEN 10 +/* + * This is a bit speed dependant (read it shouldnt be a constant!) + * + * 5 is about right for 28.8 upwards. Below that double for every + * halving of speed or so. - ie about 20 for 9600 baud. + */ +#define SHAPER_LATENCY (5 * HZ) +#define SHAPER_MAXSLIP 2 +#define SHAPER_BURST (HZ / 50) /* Good for >128K then */ + +#define SHAPER_SET_DEV 0x0001 +#define SHAPER_SET_SPEED 0x0002 +#define SHAPER_GET_DEV 0x0003 +#define SHAPER_GET_SPEED 0x0004 + +struct shaperconf +{ + u_int16_t ss_cmd; + union + { + char ssu_name[14]; + u_int32_t ssu_speed; + } ss_u; +#define ss_speed ss_u.ssu_speed +#define ss_name ss_u.ssu_name +}; + +__END_DECLS + +#endif /* net/if_shaper.h */ diff --git a/include/net/if_slip.h b/include/net/if_slip.h new file mode 100644 index 0000000..66bd7f3 --- /dev/null +++ b/include/net/if_slip.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SLIP_H +#define _NET_IF_SLIP_H 1 + +/* We can use the kernel header. */ +#include + +#endif /* net/if_slip.h. */ diff --git a/include/net/ppp-comp.h b/include/net/ppp-comp.h new file mode 100644 index 0000000..4a992d5 --- /dev/null +++ b/include/net/ppp-comp.h @@ -0,0 +1 @@ +#include diff --git a/include/net/ppp_defs.h b/include/net/ppp_defs.h new file mode 100644 index 0000000..f8924c4 --- /dev/null +++ b/include/net/ppp_defs.h @@ -0,0 +1,10 @@ +#ifndef _NET_PPP_DEFS_H +#define _NET_PPP_DEFS_H 1 + +#define __need_time_t +#include + +#include +#include + +#endif /* net/ppp_defs.h */ diff --git a/include/net/route.h b/include/net/route.h new file mode 100644 index 0000000..da5c810 --- /dev/null +++ b/include/net/route.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_ROUTE_H +#define _NET_ROUTE_H 1 + +#include +#include +#include +#include +#include + + +/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ +struct rtentry + { + unsigned long int rt_pad1; + struct sockaddr rt_dst; /* Target address. */ + struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ + struct sockaddr rt_genmask; /* Target network mask (IP). */ + unsigned short int rt_flags; + short int rt_pad2; + unsigned long int rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; +#if __WORDSIZE == 64 + short int rt_pad4[3]; +#else + short int rt_pad4; +#endif + short int rt_metric; /* +1 for binary compatibility! */ + char *rt_dev; /* Forcing the device at add. */ + unsigned long int rt_mtu; /* Per route MTU/Window. */ + unsigned long int rt_window; /* Window clamping. */ + unsigned short int rt_irtt; /* Initial RTT. */ + }; +/* Compatibility hack. */ +#define rt_mss rt_mtu + + +struct in6_rtmsg + { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + u_int32_t rtmsg_type; + u_int16_t rtmsg_dst_len; + u_int16_t rtmsg_src_len; + u_int32_t rtmsg_metric; + unsigned long int rtmsg_info; + u_int32_t rtmsg_flags; + int rtmsg_ifindex; + }; + + +#define RTF_UP 0x0001 /* Route usable. */ +#define RTF_GATEWAY 0x0002 /* Destination is a gateway. */ + +#define RTF_HOST 0x0004 /* Host entry (net otherwise). */ +#define RTF_REINSTATE 0x0008 /* Reinstate route after timeout. */ +#define RTF_DYNAMIC 0x0010 /* Created dyn. (by redirect). */ +#define RTF_MODIFIED 0x0020 /* Modified dyn. (by redirect). */ +#define RTF_MTU 0x0040 /* Specific MTU for this route. */ +#define RTF_MSS RTF_MTU /* Compatibility. */ +#define RTF_WINDOW 0x0080 /* Per route window clamping. */ +#define RTF_IRTT 0x0100 /* Initial round trip time. */ +#define RTF_REJECT 0x0200 /* Reject route. */ +#define RTF_STATIC 0x0400 /* Manually injected route. */ +#define RTF_XRESOLVE 0x0800 /* External resolver. */ +#define RTF_NOFORWARD 0x1000 /* Forwarding inhibited. */ +#define RTF_THROW 0x2000 /* Go to next class. */ +#define RTF_NOPMTUDISC 0x4000 /* Do not send packets with DF. */ + +/* for IPv6 */ +#define RTF_DEFAULT 0x00010000 /* default - learned via ND */ +#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ +#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ + +#define RTF_LINKRT 0x00100000 /* link specific - device match */ +#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ + +#define RTF_CACHE 0x01000000 /* cache entry */ +#define RTF_FLOW 0x02000000 /* flow significant route */ +#define RTF_POLICY 0x04000000 /* policy route */ + +#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) ((__u_int32_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 /* Address Resolution failed. */ + +#endif /* net/route.h */ diff --git a/include/netax25/ax25.h b/include/netax25/ax25.h new file mode 100644 index 0000000..ce3c7ab --- /dev/null +++ b/include/netax25/ax25.h @@ -0,0 +1,171 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETAX25_AX25_H +#define _NETAX25_AX25_H 1 + +#include +#include + +/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx. */ +#define SOL_AX25 257 + +/* AX.25 flags: */ +#define AX25_WINDOW 1 +#define AX25_T1 2 +#define AX25_T2 5 +#define AX25_T3 4 +#define AX25_N2 3 +#define AX25_BACKOFF 6 +#define AX25_EXTSEQ 7 +#define AX25_PIDINCL 8 +#define AX25_IDLE 9 +#define AX25_PACLEN 10 +#define AX25_IPMAXQUEUE 11 +#define AX25_IAMDIGI 12 +#define AX25_KILL 99 + +/* AX.25 socket ioctls: */ +#define SIOCAX25GETUID (SIOCPROTOPRIVATE) +#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1) +#define SIOCAX25DELUID (SIOCPROTOPRIVATE+2) +#define SIOCAX25NOUID (SIOCPROTOPRIVATE+3) +#define SIOCAX25BPQADDR (SIOCPROTOPRIVATE+4) +#define SIOCAX25GETPARMS (SIOCPROTOPRIVATE+5) +#define SIOCAX25SETPARMS (SIOCPROTOPRIVATE+6) +#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) +#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) +#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9) +#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) +#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) + +/* unknown: */ +#define AX25_NOUID_DEFAULT 0 +#define AX25_NOUID_BLOCK 1 +#define AX25_SET_RT_IPMODE 2 + +/* Digipeating flags: */ +#define AX25_DIGI_INBAND 0x01 /* Allow digipeating within port */ +#define AX25_DIGI_XBAND 0x02 /* Allow digipeating across ports */ + +/* Maximim number of digipeaters: */ +#define AX25_MAX_DIGIS 8 + + +typedef struct + { + char ax25_call[7]; /* 6 call + SSID (shifted ascii) */ + } +ax25_address; + +struct sockaddr_ax25 + { + sa_family_t sax25_family; + ax25_address sax25_call; + int sax25_ndigis; + }; + +/* + * The sockaddr struct with the digipeater adresses: + */ +struct full_sockaddr_ax25 + { + struct sockaddr_ax25 fsa_ax25; + ax25_address fsa_digipeater[AX25_MAX_DIGIS]; + }; +#define sax25_uid sax25_ndigis + +struct ax25_routes_struct + { + ax25_address port_addr; + ax25_address dest_addr; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; + }; + +/* The AX.25 ioctl structure: */ +struct ax25_ctl_struct + { + ax25_address port_addr; + ax25_address source_addr; + ax25_address dest_addr; + unsigned int cmd; + unsigned long arg; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; + }; + +struct ax25_info_struct + { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; + }; + +struct ax25_fwd_struct + { + ax25_address port_from; + ax25_address port_to; + }; + +/* AX.25 route structure: */ +struct ax25_route_opt_struct + { + ax25_address port_addr; + ax25_address dest_addr; + int cmd; + int arg; + }; + +/* AX.25 BPQ stuff: */ +struct ax25_bpqaddr_struct + { + char dev[16]; + ax25_address addr; + }; + +/* Definitions for the AX.25 `values' fields: */ +#define AX25_VALUES_IPDEFMODE 0 /* 'D'=DG 'V'=VC */ +#define AX25_VALUES_AXDEFMODE 1 /* 8=Normal 128=Extended Seq Nos */ +#define AX25_VALUES_NETROM 2 /* Allow NET/ROM - 0=No 1=Yes */ +#define AX25_VALUES_TEXT 3 /* Allow PID=Text - 0=No 1=Yes */ +#define AX25_VALUES_BACKOFF 4 /* 'E'=Exponential 'L'=Linear */ +#define AX25_VALUES_CONMODE 5 /* Allow connected modes - 0=No 1=Yes */ +#define AX25_VALUES_WINDOW 6 /* Default window size for standard AX.25 */ +#define AX25_VALUES_EWINDOW 7 /* Default window size for extended AX.25 */ +#define AX25_VALUES_T1 8 /* Default T1 timeout value */ +#define AX25_VALUES_T2 9 /* Default T2 timeout value */ +#define AX25_VALUES_T3 10 /* Default T3 timeout value */ +#define AX25_VALUES_N2 11 /* Default N2 value */ +#define AX25_VALUES_DIGI 12 /* Digipeat mode */ +#define AX25_VALUES_IDLE 13 /* mode vc idle timer */ +#define AX25_VALUES_PACLEN 14 /* AX.25 MTU */ +#define AX25_VALUES_IPMAXQUEUE 15 /* Maximum number of buffers enqueued */ +#define AX25_MAX_VALUES 20 + +struct ax25_parms_struct + { + ax25_address port_addr; + unsigned short values[AX25_MAX_VALUES]; + }; + +#endif /* netax25/ax25.h */ diff --git a/include/netdb.h b/include/netdb.h new file mode 100644 index 0000000..df90601 --- /dev/null +++ b/include/netdb.h @@ -0,0 +1,663 @@ +/* Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* All data returned by the network data base library are supplied in + host order and returned in network order (suitable for use in + system calls). */ + +#ifndef _NETDB_H +#define _NETDB_H 1 + +#include + +#include +#include +#ifdef __USE_MISC +/* This is necessary to make this include file properly replace the + Sun version. */ +# include +#endif + +#ifdef __USE_GNU +# define __need_sigevent_t +# include +# define __need_timespec +# include +#endif + +#include + +/* Absolute file name for network data base files. */ +#define _PATH_HEQUIV "/etc/hosts.equiv" +#define _PATH_HOSTS "/etc/hosts" +#define _PATH_NETWORKS "/etc/networks" +#define _PATH_NSSWITCH_CONF "/etc/nsswitch.conf" +#define _PATH_PROTOCOLS "/etc/protocols" +#define _PATH_SERVICES "/etc/services" + + +__BEGIN_DECLS + +/* Error status for non-reentrant lookup functions. + We use a macro to access always the thread-specific `h_errno' variable. + We always need the extern int here in case internal libc code undefines + the macro because it needs access to the underlying storage. */ +extern int h_errno; +#ifdef __UCLIBC_HAS_THREADS__ +# define h_errno (*__h_errno_location ()) +#endif + +/* Function to get address of global `h_errno' variable. */ +extern int *__h_errno_location (void) __THROW __attribute__ ((__const__)); + +#ifdef _LIBC +# define __set_h_errno(x) (h_errno = (x)) +#endif + +/* Possible values left in `h_errno'. */ +#define NETDB_INTERNAL -1 /* See errno. */ +#define NETDB_SUCCESS 0 /* No problem. */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +#define TRY_AGAIN 2 /* Non-Authoritative Host not found, + or SERVERFAIL. */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, + NOTIMP. */ +#define NO_DATA 4 /* Valid name, no data record of requested + type. */ +#define NO_ADDRESS NO_DATA /* No address, look for MX record. */ + +#ifdef __USE_XOPEN2K +/* Highest reserved Internet port number. */ +# define IPPORT_RESERVED 1024 +#endif + +#ifdef __USE_GNU +/* Scope delimiter for getaddrinfo(), getnameinfo(). */ +# define SCOPE_DELIMITER '%' +#endif + +/* Print error indicated by `h_errno' variable on standard error. STR + if non-null is printed before the error string. */ +extern void herror (__const char *__str) __THROW; + +/* Return string associated with error ERR_NUM. */ +extern __const char *hstrerror (int __err_num) __THROW; + + + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +#define h_addr h_addr_list[0] /* Address, for backward compatibility. */ +}; + +/* Open host data base files and mark them as staying open even after + a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void sethostent (int __stay_open); + +/* Close host data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endhostent (void); + +/* Get next entry from host data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostent (void); + +/* Return entry from host data base which address match ADDR with + length LEN and type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyaddr (__const void *__addr, __socklen_t __len, + int __type); + +/* Return entry from host data base for host with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyname (__const char *__name); + +#ifdef __USE_MISC +/* Return entry from host data base for host with NAME. AF must be + set to the address type which is `AF_INET' for IPv4 or `AF_INET6' + for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct hostent *gethostbyname2 (__const char *__name, int __af); + +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int gethostent_r (struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyaddr_r (__const void *__restrict __addr, __socklen_t __len, + int __type, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyname_r (__const char *__restrict __name, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyname2_r (__const char *__restrict __name, int __af, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +#endif /* misc */ + + +/* Open network data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setnetent (int __stay_open); + +/* Close network data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endnetent (void); + +/* Get next entry from network data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetent (void); + +/* Return entry from network data base which address match NET and + type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyaddr (uint32_t __net, int __type); + +/* Return entry from network data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyname (__const char *__name); + +#if 0 +/* FIXME */ +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getnetent_r (struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); + +extern int getnetbyaddr_r (uint32_t __net, int __type, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); + +extern int getnetbyname_r (__const char *__restrict __name, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); +#endif /* misc */ +#endif + + +/* Description of data base entry for a single service. */ +struct servent +{ + char *s_name; /* Official service name. */ + char **s_aliases; /* Alias list. */ + int s_port; /* Port number. */ + char *s_proto; /* Protocol to use. */ +}; + +/* Open service data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setservent (int __stay_open); + +/* Close service data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endservent (void); + +/* Get next entry from service data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservent (void); + +/* Return entry from network data base for network with NAME and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyname (__const char *__name, + __const char *__proto); + +/* Return entry from service data base which matches port PORT and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyport (int __port, __const char *__proto); + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getservent_r (struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); + +extern int getservbyname_r (__const char *__restrict __name, + __const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); + +extern int getservbyport_r (int __port, __const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); +#endif /* misc */ + + +/* Description of data base entry for a single service. */ +struct protoent +{ + char *p_name; /* Official protocol name. */ + char **p_aliases; /* Alias list. */ + int p_proto; /* Protocol number. */ +}; + +/* Open protocol data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setprotoent (int __stay_open); + +/* Close protocol data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endprotoent (void); + +/* Get next entry from protocol data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotoent (void); + +/* Return entry from protocol data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobyname (__const char *__name); + +/* Return entry from protocol data base which number is PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobynumber (int __proto); + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getprotoent_r (struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + +extern int getprotobyname_r (__const char *__restrict __name, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + +extern int getprotobynumber_r (int __proto, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + + +#ifdef __UCLIBC_HAS_NETGROUP__ +/* Establish network group NETGROUP for enumeration. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int setnetgrent (__const char *__netgroup); + +/* Free all space allocated by previous `setnetgrent' call. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endnetgrent (void); + +/* Get next member of netgroup established by last `setnetgrent' call + and return pointers to elements in HOSTP, USERP, and DOMAINP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp); + + +/* Test whether NETGROUP contains the triple (HOST,USER,DOMAIN). + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int innetgr (__const char *__netgroup, __const char *__host, + __const char *__user, __const char *domain); + +/* Reentrant version of `getnetgrent' where result is placed in BUFFER. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent_r (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp, + char *__restrict __buffer, size_t __buflen); +#endif /* UCLIBC_HAS_NETGROUP */ +#endif /* misc */ + + +/* ruserpass - remote password check. + This function also exists in glibc but is undocumented */ +extern int ruserpass(const char *host, const char **aname, const char **apass); + + +#ifdef __USE_BSD +/* Call `rshd' at port RPORT on remote machine *AHOST to execute CMD. + The local user is LOCUSER, on the remote machine the command is + executed as REMUSER. In *FD2P the descriptor to the socket for the + connection is returned. The caller must have the right to use a + reserved port. When the function returns *AHOST contains the + official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd (char **__restrict __ahost, unsigned short int __rport, + __const char *__restrict __locuser, + __const char *__restrict __remuser, + __const char *__restrict __cmd, int *__restrict __fd2p); + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd_af (char **__restrict __ahost, unsigned short int __rport, + __const char *__restrict __locuser, + __const char *__restrict __remuser, + __const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); +#endif + +/* Call `rexecd' at port RPORT on remote machine *AHOST to execute + CMD. The process runs at the remote machine using the ID of user + NAME whose cleartext password is PASSWD. In *FD2P the descriptor + to the socket for the connection is returned. When the function + returns *AHOST contains the official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec (char **__restrict __ahost, int __rport, + __const char *__restrict __name, + __const char *__restrict __pass, + __const char *__restrict __cmd, int *__restrict __fd2p); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec_af (char **__restrict __ahost, int __rport, + __const char *__restrict __name, + __const char *__restrict __pass, + __const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); + +/* Check whether user REMUSER on system RHOST is allowed to login as LOCUSER. + If SUSER is not zero the user tries to become superuser. Return 0 if + it is possible. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok (__const char *__rhost, int __suser, + __const char *__remuser, __const char *__locuser); + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok_af (__const char *__rhost, int __suser, + __const char *__remuser, __const char *__locuser, + sa_family_t __af); +#endif + +/* Try to allocate reserved port, returning a descriptor for a socket opened + at this port or -1 if unsuccessful. The search for an available port + will start at ALPORT and continues with lower numbers. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport (int *__alport); + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport_af (int *__alport, sa_family_t __af); +#endif +#endif + + +/* Extension from POSIX.1g. */ +#ifdef __USE_POSIX +/* Structure to contain information about address of a service provider. */ +struct addrinfo +{ + int ai_flags; /* Input flags. */ + int ai_family; /* Protocol family for socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol for socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address for socket. */ + char *ai_canonname; /* Canonical name for service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; + +/* Possible values for `ai_flags' field in `addrinfo' structure. */ +# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ +# define AI_CANONNAME 0x0002 /* Request for canonical name. */ +# define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ +# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ +# define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */ +# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose + returned address type.. */ +# ifdef __USE_GNU +# define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded + in the current locale's character set) + before looking it up. */ +# define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */ +# define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode + code points. */ +# define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to + STD3 rules. */ +# endif +# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ + +/* Error values for `getaddrinfo' function. */ +# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +# define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +# define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +# define EAI_NODATA -5 /* No address associated with NAME. */ +# define EAI_FAMILY -6 /* `ai_family' not supported. */ +# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +# define EAI_MEMORY -10 /* Memory allocation failure. */ +# define EAI_SYSTEM -11 /* System error returned in `errno'. */ +# define EAI_OVERFLOW -12 /* Argument buffer overflow. */ +# ifdef __USE_GNU +# define EAI_INPROGRESS -100 /* Processing request in progress. */ +# define EAI_CANCELED -101 /* Request canceled. */ +# define EAI_NOTCANCELED -102 /* Request not canceled. */ +# define EAI_ALLDONE -103 /* All requests done. */ +# define EAI_INTR -104 /* Interrupted by a signal. */ +# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */ +# endif + +# define NI_MAXHOST 1025 +# define NI_MAXSERV 32 + +# define NI_NUMERICHOST 1 /* Don't try to look up hostname. */ +# define NI_NUMERICSERV 2 /* Don't convert port number to name. */ +# define NI_NOFQDN 4 /* Only return nodename portion. */ +# define NI_NAMEREQD 8 /* Don't return numeric addresses. */ +# define NI_DGRAM 16 /* Look up UDP service rather than TCP. */ +# ifdef __USE_GNU +# define NI_IDN 32 /* Convert name from IDN format. */ +# define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode + code points. */ +# define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to + STD3 rules. */ +# endif + +/* Translate name of a service location and/or a service name to set of + socket addresses. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getaddrinfo (__const char *__restrict __name, + __const char *__restrict __service, + __const struct addrinfo *__restrict __req, + struct addrinfo **__restrict __pai); + +/* Free `addrinfo' structure AI including associated storage. */ +extern void freeaddrinfo (struct addrinfo *__ai) __THROW; + +/* Convert error return from getaddrinfo() to a string. */ +extern __const char *gai_strerror (int __ecode) __THROW; + +/* Translate a socket address to a location and service name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getnameinfo (__const struct sockaddr *__restrict __sa, + socklen_t __salen, char *__restrict __host, + socklen_t __hostlen, char *__restrict __serv, + socklen_t __servlen, unsigned int __flags); +#endif /* POSIX */ + +__END_DECLS + +#endif /* netdb.h */ diff --git a/include/neteconet/ec.h b/include/neteconet/ec.h new file mode 100644 index 0000000..f21601c --- /dev/null +++ b/include/neteconet/ec.h @@ -0,0 +1,52 @@ +/* Definitions for use with Linux AF_ECONET sockets. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETECONET_EC_H +#define _NETECONET_EC_H 1 + +#include +#include + +struct ec_addr + { + unsigned char station; /* Station number. */ + unsigned char net; /* Network number. */ + }; + +struct sockaddr_ec + { + __SOCKADDR_COMMON (sec_); + unsigned char port; /* Port number. */ + unsigned char cb; /* Control/flag byte. */ + unsigned char type; /* Type of message. */ + struct ec_addr addr; + unsigned long cookie; + }; + +#define ECTYPE_PACKET_RECEIVED 0 /* Packet received */ +#define ECTYPE_TRANSMIT_STATUS 0x10 /* Transmit completed */ + +#define ECTYPE_TRANSMIT_OK 1 +#define ECTYPE_TRANSMIT_NOT_LISTENING 2 +#define ECTYPE_TRANSMIT_NET_ERROR 3 +#define ECTYPE_TRANSMIT_NO_CLOCK 4 +#define ECTYPE_TRANSMIT_LINE_JAMMED 5 +#define ECTYPE_TRANSMIT_NOT_PRESENT 6 + +#endif diff --git a/include/netinet/ether.h b/include/netinet/ether.h new file mode 100644 index 0000000..0f7029f --- /dev/null +++ b/include/netinet/ether.h @@ -0,0 +1,57 @@ +/* Functions for storing Ethernet addresses in ASCII and mapping to hostnames. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_ETHER_H +#define _NETINET_ETHER_H 1 + +#include + +/* Get definition of `struct ether_addr'. */ +#include + +#define ETHER_FILE_NAME "/etc/ethers" + +__BEGIN_DECLS + +/* Convert 48 bit Ethernet ADDRess to ASCII. */ +extern char *ether_ntoa (__const struct ether_addr *__addr) __THROW; +extern char *ether_ntoa_r (__const struct ether_addr *__addr, char *__buf) + __THROW; + +/* Convert ASCII string S to 48 bit Ethernet address. */ +extern struct ether_addr *ether_aton (__const char *__asc) __THROW; +extern struct ether_addr *ether_aton_r (__const char *__asc, + struct ether_addr *__addr) __THROW; +libc_hidden_proto(ether_aton_r) + +/* Map 48 bit Ethernet number ADDR to HOSTNAME. */ +extern int ether_ntohost (char *__hostname, __const struct ether_addr *__addr) + __THROW; + +/* Map HOSTNAME to 48 bit Ethernet address. */ +extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr) + __THROW; + +/* Scan LINE and set ADDR and HOSTNAME. */ +extern int ether_line (__const char *__line, struct ether_addr *__addr, + char *__hostname) __THROW; + +__END_DECLS + +#endif /* netinet/ether.h */ diff --git a/include/netinet/icmp6.h b/include/netinet/icmp6.h new file mode 100644 index 0000000..0cb1aa6 --- /dev/null +++ b/include/netinet/icmp6.h @@ -0,0 +1,346 @@ +/* Copyright (C) 1991-1997,2000,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_ICMP6_H +#define _NETINET_ICMP6_H 1 + +#include +#include +#include +#include + +#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; /* type field */ + uint8_t icmp6_code; /* code field */ + uint16_t icmp6_cksum; /* checksum field */ + union + { + uint32_t icmp6_un_data32[1]; /* type-specific field */ + uint16_t icmp6_un_data16[2]; /* type-specific field */ + uint8_t icmp6_un_data8[4]; /* type-specific field */ + } 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] /* parameter prob */ +#define icmp6_mtu icmp6_data32[0] /* packet too big */ +#define icmp6_id icmp6_data16[0] /* echo request/reply */ +#define icmp6_seq icmp6_data16[1] /* echo request/reply */ +#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ + +#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 /* all informational messages */ + +#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 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */ + /* administratively prohibited */ +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */ + +#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */ +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */ + +#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ +#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */ +#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */ + +#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 /* router solicitation */ + { + struct icmp6_hdr nd_rs_hdr; + /* could be followed by options */ + }; + +#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 /* router advertisement */ + { + struct icmp6_hdr nd_ra_hdr; + uint32_t nd_ra_reachable; /* reachable time */ + uint32_t nd_ra_retransmit; /* retransmit timer */ + /* could be followed by options */ + }; + +#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 /* neighbor solicitation */ + { + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; /* target address */ + /* could be followed by options */ + }; + +#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 /* neighbor advertisement */ + { + struct icmp6_hdr nd_na_hdr; + struct in6_addr nd_na_target; /* target address */ + /* could be followed by options */ + }; + +#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 /* BYTE_ORDER == LITTLE_ENDIAN */ +#define ND_NA_FLAG_ROUTER 0x00000080 +#define ND_NA_FLAG_SOLICITED 0x00000040 +#define ND_NA_FLAG_OVERRIDE 0x00000020 +#endif + +struct nd_redirect /* redirect */ + { + struct icmp6_hdr nd_rd_hdr; + struct in6_addr nd_rd_target; /* target address */ + struct in6_addr nd_rd_dst; /* destination address */ + /* could be followed by options */ + }; + +#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 /* Neighbor discovery option header */ + { + uint8_t nd_opt_type; + uint8_t nd_opt_len; /* in units of 8 octets */ + /* followed by option specific data */ + }; + +#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 /* prefix information */ + { + 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 /* redirected header */ + { + uint8_t nd_opt_rh_type; + uint8_t nd_opt_rh_len; + uint16_t nd_opt_rh_reserved1; + uint32_t nd_opt_rh_reserved2; + /* followed by IP header and data */ + }; + +struct nd_opt_mtu /* MTU option */ + { + 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; /* multicast address */ + }; + +#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 /* router renumbering header */ + { + 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] + +/* Router renumbering flags */ +#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 /* match prefix part */ + { + 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; + }; + +/* PCO code values */ +#define RPM_PCO_ADD 1 +#define RPM_PCO_CHANGE 2 +#define RPM_PCO_SETGLOBAL 3 + +struct rr_pco_use /* use prefix part */ + { + 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 +#elif BYTE_ORDER == LITTLE_ENDIAN +# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80 +# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40 +#endif + +struct rr_result /* router renumbering result message */ + { + 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 +#elif BYTE_ORDER == LITTLE_ENDIAN +# define ICMP6_RR_RESULT_FLAGS_OOB 0x0200 +# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100 +#endif + +/* Mobile IPv6 extension: Advertisement Interval. */ +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; + }; + +/* Mobile IPv6 extension: Home Agent Info. */ +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; + int16_t nd_opt_home_agent_info_preference; + uint16_t nd_opt_home_agent_info_lifetime; + }; + +#endif /* netinet/icmpv6.h */ diff --git a/include/netinet/if_ether.h b/include/netinet/if_ether.h new file mode 100644 index 0000000..aadb59b --- /dev/null +++ b/include/netinet/if_ether.h @@ -0,0 +1,105 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IF_ETHER_H + +#define __NETINET_IF_ETHER_H 1 +#include +#include + +/* Get definitions from kernel header file. */ +#include + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 + * $FreeBSD$ + */ + +#include +#include + +__BEGIN_DECLS +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#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 + +/* + * Macro to map an IP multicast address to an Ethernet multicast address. + * The high-order 25 bits of the Ethernet address are statically assigned, + * and the low-order 23 bits are taken from the low end of the IP address. + */ +#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ + /* struct in_addr *ipaddr; */ \ + /* u_char enaddr[ETH_ALEN]; */ \ +{ \ + (enaddr)[0] = 0x01; \ + (enaddr)[1] = 0x00; \ + (enaddr)[2] = 0x5e; \ + (enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \ + (enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \ + (enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \ +} + +__END_DECLS +#endif /* __USE_BSD */ + +#endif /* netinet/if_ether.h */ diff --git a/include/netinet/if_fddi.h b/include/netinet/if_fddi.h new file mode 100644 index 0000000..1a0ec92 --- /dev/null +++ b/include/netinet/if_fddi.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IF_FDDI_H +#define _NETINET_IF_FDDI_H 1 + +#include +#include +#include + +#include + +#ifdef __USE_BSD + +struct fddi_header { + u_int8_t fddi_fc; /* Frame Control (FC) value */ + u_int8_t fddi_dhost[FDDI_K_ALEN]; /* Destination host */ + u_int8_t fddi_shost[FDDI_K_ALEN]; /* Source host */ +}; +#endif + +#endif /* netinet/if_fddi.h */ diff --git a/include/netinet/if_tr.h b/include/netinet/if_tr.h new file mode 100644 index 0000000..45c3911 --- /dev/null +++ b/include/netinet/if_tr.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IF_TR_H +#define _NETINET_IF_TR_H 1 + +#include +#include + +/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble + and FCS/CRC (frame check sequence). */ +#define TR_ALEN 6 /* Octets in one token-ring addr */ +#define TR_HLEN (sizeof (struct trh_hdr) + sizeof (struct trllc)) +#define AC 0x10 +#define LLC_FRAME 0x40 + +/* LLC and SNAP constants */ +#define EXTENDED_SAP 0xAA +#define UI_CMD 0x03 + +/* This is an Token-Ring frame header. */ +struct trh_hdr +{ + u_int8_t ac; /* access control field */ + u_int8_t fc; /* frame control field */ + u_int8_t daddr[TR_ALEN]; /* destination address */ + u_int8_t saddr[TR_ALEN]; /* source address */ + u_int16_t rcf; /* route control field */ + u_int16_t rseg[8]; /* routing registers */ +}; + +/* This is an Token-Ring LLC structure */ +struct trllc +{ + u_int8_t dsap; /* destination SAP */ + u_int8_t ssap; /* source SAP */ + u_int8_t llc; /* LLC control field */ + u_int8_t protid[3]; /* protocol id */ + u_int16_t ethertype; /* ether type field */ +}; + +/* Token-Ring statistics collection data. */ +struct tr_statistics +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long transmit_collision; + + /* detailed Token-Ring errors. See IBM Token-Ring Network + Architecture for more info */ + + unsigned long line_errors; + unsigned long internal_errors; + unsigned long burst_errors; + unsigned long A_C_errors; + unsigned long abort_delimiters; + unsigned long lost_frames; + unsigned long recv_congest_count; + unsigned long frame_copied_errors; + unsigned long frequency_errors; + unsigned long token_errors; + unsigned long dummy1; +}; + +/* source routing stuff */ +#define TR_RII 0x80 +#define TR_RCF_DIR_BIT 0x80 +#define TR_RCF_LEN_MASK 0x1f00 +#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ +#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ +#define TR_RCF_FRAME2K 0x20 +#define TR_RCF_BROADCAST_MASK 0xC000 +#define TR_MAXRIFLEN 18 + +#ifdef __USE_BSD + +struct trn_hdr +{ + u_int8_t trn_ac; /* access control field */ + u_int8_t trn_fc; /* field control field */ + u_int8_t trn_dhost[TR_ALEN]; /* destination host */ + u_int8_t trn_shost[TR_ALEN]; /* source host */ + u_int16_t trn_rcf; /* route control field */ + u_int16_t trn_rseg[8]; /* routing registers */ +}; + +#endif + +#endif /* netinet/if_tr.h */ diff --git a/include/netinet/igmp.h b/include/netinet/igmp.h new file mode 100644 index 0000000..67396ba --- /dev/null +++ b/include/netinet/igmp.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1997, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IGMP_H +#define _NETINET_IGMP_H 1 + +#include +#include + +#ifdef __USE_BSD + +#include + +__BEGIN_DECLS + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD$ + */ + +struct igmp { + u_int8_t igmp_type; /* IGMP type */ + u_int8_t igmp_code; /* routing code */ + u_int16_t igmp_cksum; /* checksum */ + struct in_addr igmp_group; /* group address */ +}; + +#define IGMP_MINLEN 8 + +/* + * Message types, including version number. + */ +#define IGMP_MEMBERSHIP_QUERY 0x11 /* membership query */ +#define IGMP_V1_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_V2_LEAVE_GROUP 0x17 /* Leave-group message */ + +#define IGMP_DVMRP 0x13 /* DVMRP routing message */ +#define IGMP_PIM 0x14 /* PIM routing message */ +#define IGMP_TRACE 0x15 + +#define IGMP_MTRACE_RESP 0x1e /* traceroute resp.(to sender)*/ +#define IGMP_MTRACE 0x1f /* mcast traceroute messages */ + +#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ + /* query (in seconds) according */ + /* to RFC1112 */ +#define IGMP_TIMER_SCALE 10 /* denotes that the igmp code field */ + /* specifies time in 10th of seconds*/ + +/* + * States for the IGMP v2 state table. + */ +#define IGMP_DELAYING_MEMBER 1 +#define IGMP_IDLE_MEMBER 2 +#define IGMP_LAZY_MEMBER 3 +#define IGMP_SLEEPING_MEMBER 4 +#define IGMP_AWAKENING_MEMBER 5 + +/* + * States for IGMP router version cache. + */ +#define IGMP_v1_ROUTER 1 +#define IGMP_v2_ROUTER 2 + +/* + * The following four defininitions are for backwards compatibility. + * They should be removed as soon as all applications are updated to + * use the new constant names. + */ +#define IGMP_HOST_MEMBERSHIP_QUERY IGMP_MEMBERSHIP_QUERY +#define IGMP_HOST_MEMBERSHIP_REPORT IGMP_V1_MEMBERSHIP_REPORT +#define IGMP_HOST_NEW_MEMBERSHIP_REPORT IGMP_V2_MEMBERSHIP_REPORT +#define IGMP_HOST_LEAVE_MESSAGE IGMP_V2_LEAVE_GROUP + +__END_DECLS + +#endif + +#endif /* netinet/igmp.h */ diff --git a/include/netinet/in.h b/include/netinet/in.h new file mode 100644 index 0000000..6bfc5e7 --- /dev/null +++ b/include/netinet/in.h @@ -0,0 +1,556 @@ +/* Copyright (C) 1991-2001, 2003, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H 1 + +#include +#include +#include +#include + + +__BEGIN_DECLS + +/* Standard well-defined IP protocols. */ +enum + { + IPPROTO_IP = 0, /* Dummy protocol for TCP. */ +#define IPPROTO_IP IPPROTO_IP + IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ +#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS + IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */ +#define IPPROTO_ICMP IPPROTO_ICMP + IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */ +#define IPPROTO_IGMP IPPROTO_IGMP + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */ +#define IPPROTO_IPIP IPPROTO_IPIP + IPPROTO_TCP = 6, /* Transmission Control Protocol. */ +#define IPPROTO_TCP IPPROTO_TCP + IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */ +#define IPPROTO_EGP IPPROTO_EGP + IPPROTO_PUP = 12, /* PUP protocol. */ +#define IPPROTO_PUP IPPROTO_PUP + IPPROTO_UDP = 17, /* User Datagram Protocol. */ +#define IPPROTO_UDP IPPROTO_UDP + IPPROTO_IDP = 22, /* XNS IDP protocol. */ +#define IPPROTO_IDP IPPROTO_IDP + IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */ +#define IPPROTO_TP IPPROTO_TP + IPPROTO_IPV6 = 41, /* IPv6 header. */ +#define IPPROTO_IPV6 IPPROTO_IPV6 + IPPROTO_ROUTING = 43, /* IPv6 routing header. */ +#define IPPROTO_ROUTING IPPROTO_ROUTING + IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ +#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT + IPPROTO_RSVP = 46, /* Reservation Protocol. */ +#define IPPROTO_RSVP IPPROTO_RSVP + IPPROTO_GRE = 47, /* General Routing Encapsulation. */ +#define IPPROTO_GRE IPPROTO_GRE + IPPROTO_ESP = 50, /* encapsulating security payload. */ +#define IPPROTO_ESP IPPROTO_ESP + IPPROTO_AH = 51, /* authentication header. */ +#define IPPROTO_AH IPPROTO_AH + IPPROTO_ICMPV6 = 58, /* ICMPv6. */ +#define IPPROTO_ICMPV6 IPPROTO_ICMPV6 + IPPROTO_NONE = 59, /* IPv6 no next header. */ +#define IPPROTO_NONE IPPROTO_NONE + IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */ +#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS + IPPROTO_MTP = 92, /* Multicast Transport Protocol. */ +#define IPPROTO_MTP IPPROTO_MTP + IPPROTO_ENCAP = 98, /* Encapsulation Header. */ +#define IPPROTO_ENCAP IPPROTO_ENCAP + IPPROTO_PIM = 103, /* Protocol Independent Multicast. */ +#define IPPROTO_PIM IPPROTO_PIM + IPPROTO_COMP = 108, /* Compression Header Protocol. */ +#define IPPROTO_COMP IPPROTO_COMP + IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */ +#define IPPROTO_SCTP IPPROTO_SCTP + IPPROTO_RAW = 255, /* Raw IP packets. */ +#define IPPROTO_RAW IPPROTO_RAW + IPPROTO_MAX + }; + + +/* Type to represent a port. */ +typedef uint16_t in_port_t; + +/* Standard well-known ports. */ +enum + { + IPPORT_ECHO = 7, /* Echo service. */ + IPPORT_DISCARD = 9, /* Discard transmissions service. */ + IPPORT_SYSTAT = 11, /* System status service. */ + IPPORT_DAYTIME = 13, /* Time of day service. */ + IPPORT_NETSTAT = 15, /* Network status service. */ + IPPORT_FTP = 21, /* File Transfer Protocol. */ + IPPORT_TELNET = 23, /* Telnet protocol. */ + IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */ + IPPORT_TIMESERVER = 37, /* Timeserver service. */ + IPPORT_NAMESERVER = 42, /* Domain Name Service. */ + IPPORT_WHOIS = 43, /* Internet Whois service. */ + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */ + IPPORT_RJE = 77, + IPPORT_FINGER = 79, /* Finger service. */ + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, /* SUPDUP protocol. */ + + + IPPORT_EXECSERVER = 512, /* execd service. */ + IPPORT_LOGINSERVER = 513, /* rlogind service. */ + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + /* UDP ports. */ + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + /* Ports less than this value are reserved for privileged processes. */ + IPPORT_RESERVED = 1024, + + /* Ports greater this value are reserved for (non-privileged) servers. */ + IPPORT_USERRESERVED = 5000 + }; + + +/* Internet address. */ +typedef uint32_t in_addr_t; +struct in_addr + { + in_addr_t s_addr; + }; + + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ + +#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) + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((in_addr_t) 0x00000000) +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((in_addr_t) 0xffffffff) +/* Address indicating an error return. */ +#define INADDR_NONE ((in_addr_t) 0xffffffff) + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 +/* Address to loopback in software to local host. */ +#ifndef INADDR_LOOPBACK +# define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) /* Inet 127.0.0.1. */ +#endif + +/* Defines for Multicast INADDR. */ +#define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */ +#define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */ + + +/* IPv6 address */ +struct in6_addr + { + union + { + uint8_t u6_addr8[16]; + uint16_t u6_addr16[8]; + uint32_t u6_addr32[4]; + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 + }; + +extern const struct in6_addr in6addr_any; /* :: */ +extern const struct in6_addr in6addr_loopback; /* ::1 */ +#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 } } } + +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + + +#if 1 /* defined __UCLIBC_HAS_IPV4__ */ +/* Structure describing an Internet socket address. */ +struct sockaddr_in + { + __SOCKADDR_COMMON (sin_); + in_port_t sin_port; /* Port number. */ + struct in_addr sin_addr; /* Internet address. */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char sin_zero[sizeof (struct sockaddr) - + __SOCKADDR_COMMON_SIZE - + sizeof (in_port_t) - + sizeof (struct in_addr)]; + }; +#endif + +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + in_port_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* IPv6 scope-id */ + }; + + +/* IPv4 multicast request. */ +struct ip_mreq + { + /* IP multicast address of group. */ + struct in_addr imr_multiaddr; + + /* Local IP address of interface. */ + struct in_addr imr_interface; + }; + +struct ip_mreq_source + { + /* IP multicast address of group. */ + struct in_addr imr_multiaddr; + + /* IP address of source. */ + struct in_addr imr_interface; + + /* IP address of interface. */ + struct in_addr imr_sourceaddr; + }; + +/* Likewise, for IPv6. */ +struct ipv6_mreq + { + /* IPv6 multicast address of group */ + struct in6_addr ipv6mr_multiaddr; + + /* local interface */ + unsigned int ipv6mr_interface; + }; + + +/* Multicast group request. */ +struct group_req + { + /* Interface index. */ + uint32_t gr_interface; + + /* Group address. */ + struct sockaddr_storage gr_group; + }; + +struct group_source_req + { + /* Interface index. */ + uint32_t gsr_interface; + + /* Group address. */ + struct sockaddr_storage gsr_group; + + /* Source address. */ + struct sockaddr_storage gsr_source; + }; + + +/* Full-state filter operations. */ +struct ip_msfilter + { + /* IP multicast address of group. */ + struct in_addr imsf_multiaddr; + + /* Local IP address of interface. */ + struct in_addr imsf_interface; + + /* Filter mode. */ + uint32_t imsf_fmode; + + /* Number of source addresses. */ + uint32_t imsf_numsrc; + /* Source addresses. */ + struct in_addr imsf_slist[1]; + }; + +#define IP_MSFILTER_SIZE(numsrc) (sizeof (struct ip_msfilter) \ + - sizeof (struct in_addr) \ + + (numsrc) * sizeof (struct in_addr)) + +struct group_filter + { + /* Interface index. */ + uint32_t gf_interface; + + /* Group address. */ + struct sockaddr_storage gf_group; + + /* Filter mode. */ + uint32_t gf_fmode; + + /* Number of source addresses. */ + uint32_t gf_numsrc; + /* Source addresses. */ + struct sockaddr_storage gf_slist[1]; +}; + +#define GROUP_FILTER_SIZE(numsrc) (sizeof (struct group_filter) \ + - sizeof (struct sockaddr_storage) \ + + ((numsrc) \ + * sizeof (struct sockaddr_storage))) + + +/* Get system-specific definitions. */ +#include + +/* Functions to convert between host and network byte order. + + Please note that these functions normally take `unsigned long int' or + `unsigned short int' values as arguments and also return them. But + this was a short-sighted decision since on different systems the types + may have different representations but the values are always the same. */ + +extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__)); +extern uint16_t ntohs (uint16_t __netshort) + __THROW __attribute__ ((__const__)); +extern uint32_t htonl (uint32_t __hostlong) + __THROW __attribute__ ((__const__)); +extern uint16_t htons (uint16_t __hostshort) + __THROW __attribute__ ((__const__)); + +#include + +/* Get machine dependent optimized versions of byte swapping functions. */ +#include + +#ifdef __OPTIMIZE__ +/* We can optimize calls to the conversion functions. Either nothing has + to be done or we are using directly the byte-swapping functions which + often can be inlined. */ +# if __BYTE_ORDER == __BIG_ENDIAN +/* The host byte order is the same as network byte order, + so these functions are all just identity. */ +# define ntohl(x) (x) +# define ntohs(x) (x) +# define htonl(x) (x) +# define htons(x) (x) +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define ntohl(x) __bswap_32 (x) +# define ntohs(x) __bswap_16 (x) +# define htonl(x) __bswap_32 (x) +# define htons(x) __bswap_16 (x) +# endif +# endif +#endif + +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + (((__const uint32_t *) (a))[0] == 0 \ + && ((__const uint32_t *) (a))[1] == 0 \ + && ((__const uint32_t *) (a))[2] == 0 \ + && ((__const uint32_t *) (a))[3] == 0) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((__const uint32_t *) (a))[0] == 0 \ + && ((__const uint32_t *) (a))[1] == 0 \ + && ((__const uint32_t *) (a))[2] == 0 \ + && ((__const uint32_t *) (a))[3] == htonl (1)) + +#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((__const uint32_t *) (a))[0] & htonl (0xffc00000)) \ + == htonl (0xfe800000)) + +#define IN6_IS_ADDR_SITELOCAL(a) \ + ((((__const uint32_t *) (a))[0] & htonl (0xffc00000)) \ + == htonl (0xfec00000)) + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) + +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == 0) \ + && (ntohl (((__const uint32_t *) (a))[3]) > 1)) + +#define IN6_ARE_ADDR_EQUAL(a,b) \ + ((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0]) \ + && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1]) \ + && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2]) \ + && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3])) + +/* Bind socket to a privileged IP port. */ +extern int bindresvport (int __sockfd, struct sockaddr_in *__sock_in) __THROW; + +/* The IPv6 version of this function. */ +extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in) + __THROW; + + +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) + +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x2)) + +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x5)) + +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x8)) + +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) + +/* IPv6 packet information. */ +struct in6_pktinfo + { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ + }; + +/* IPv6 MTU information. */ +struct ip6_mtuinfo + { + struct sockaddr_in6 ip6m_addr; /* dst address including zone ID */ + uint32_t ip6m_mtu; /* path MTU in host byte order */ + }; + + +#if 0 /*def __USE_GNU*/ +/* Obsolete hop-by-hop and Destination Options Processing (RFC 2292). */ +extern int inet6_option_space (int __nbytes) + __THROW __attribute_deprecated__; +extern int inet6_option_init (void *__bp, struct cmsghdr **__cmsgp, + int __type) __THROW __attribute_deprecated__; +extern int inet6_option_append (struct cmsghdr *__cmsg, + __const uint8_t *__typep, int __multx, + int __plusy) __THROW __attribute_deprecated__; +extern uint8_t *inet6_option_alloc (struct cmsghdr *__cmsg, int __datalen, + int __multx, int __plusy) + __THROW __attribute_deprecated__; +extern int inet6_option_next (__const struct cmsghdr *__cmsg, + uint8_t **__tptrp) + __THROW __attribute_deprecated__; +extern int inet6_option_find (__const struct cmsghdr *__cmsg, + uint8_t **__tptrp, int __type) + __THROW __attribute_deprecated__; + + +/* Hop-by-Hop and Destination Options Processing (RFC 3542). */ +extern int inet6_opt_init (void *__extbuf, socklen_t __extlen) __THROW; +extern int inet6_opt_append (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t __len, uint8_t __align, + void **__databufp) __THROW; +extern int inet6_opt_finish (void *__extbuf, socklen_t __extlen, int __offset) + __THROW; +extern int inet6_opt_set_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; +extern int inet6_opt_next (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t *__typep, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_find (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_get_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; + + +/* Routing Header Option (RFC 3542). */ +extern socklen_t inet6_rth_space (int __type, int __segments) __THROW; +extern void *inet6_rth_init (void *__bp, socklen_t __bp_len, int __type, + int __segments) __THROW; +extern int inet6_rth_add (void *__bp, __const struct in6_addr *__addr) __THROW; +extern int inet6_rth_reverse (__const void *__in, void *__out) __THROW; +extern int inet6_rth_segments (__const void *__bp) __THROW; +extern struct in6_addr *inet6_rth_getaddr (__const void *__bp, int __index) + __THROW; + + +/* Multicast source filter support. */ + +/* Get IPv4 source filter. */ +extern int getipv4sourcefilter (int __s, struct in_addr __interface_addr, + struct in_addr __group, uint32_t *__fmode, + uint32_t *__numsrc, struct in_addr *__slist) + __THROW; + +/* Set IPv4 source filter. */ +extern int setipv4sourcefilter (int __s, struct in_addr __interface_addr, + struct in_addr __group, uint32_t __fmode, + uint32_t __numsrc, + __const struct in_addr *__slist) + __THROW; + + +/* Get source filter. */ +extern int getsourcefilter (int __s, uint32_t __interface_addr, + __const struct sockaddr *__group, + socklen_t __grouplen, uint32_t *__fmode, + uint32_t *__numsrc, + struct sockaddr_storage *__slist) __THROW; + +/* Set source filter. */ +extern int setsourcefilter (int __s, uint32_t __interface_addr, + __const struct sockaddr *__group, + socklen_t __grouplen, uint32_t __fmode, + uint32_t __numsrc, + __const struct sockaddr_storage *__slist) __THROW; +#endif /* use GNU */ + +__END_DECLS + +#endif /* netinet/in.h */ diff --git a/include/netinet/in_systm.h b/include/netinet/in_systm.h new file mode 100644 index 0000000..51a08e1 --- /dev/null +++ b/include/netinet/in_systm.h @@ -0,0 +1,41 @@ +/* System specific type definitions for networking code. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IN_SYSTM_H +#define _NETINET_IN_SYSTM_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * Network order versions of various data types. Unfortunately, BSD + * assumes specific sizes for shorts (16 bit) and longs (32 bit) which + * don't hold in general. As a consequence, the network order versions + * may not reflect the actual size of the native data types. + */ + +typedef u_int16_t n_short; /* short as received from the net */ +typedef u_int32_t n_long; /* long as received from the net */ +typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */ + +__END_DECLS + +#endif /* netinet/in_systm.h */ diff --git a/include/netinet/ip.h b/include/netinet/ip.h new file mode 100644 index 0000000..fc91440 --- /dev/null +++ b/include/netinet/ip.h @@ -0,0 +1,249 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IP_H +#define __NETINET_IP_H 1 + +#include +#include + +#include + +__BEGIN_DECLS + +struct timestamp + { + u_int8_t len; + u_int8_t ptr; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int flags:4; + unsigned int overflow:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int overflow:4; + unsigned int flags:4; +#else +# error "Please fix " +#endif + u_int32_t data[9]; + }; + +struct iphdr + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ihl:4; + unsigned int version:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int version:4; + unsigned int ihl:4; +#else +# error "Please fix " +#endif + u_int8_t tos; + u_int16_t tot_len; + u_int16_t id; + u_int16_t frag_off; + u_int8_t ttl; + u_int8_t protocol; + u_int16_t check; + u_int32_t saddr; + u_int32_t daddr; + /*The options start here. */ + }; + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Definitions for internet protocol version 4. + * Per RFC 791, September 1981. + */ + +/* + * Structure of an internet header, naked of options. + */ +struct ip + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; /* header length */ + unsigned int ip_v:4; /* version */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ip_v:4; /* version */ + unsigned int ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ + }; + +/* + * Time stamp option structure. + */ +struct ip_timestamp + { + u_int8_t ipt_code; /* IPOPT_TS */ + u_int8_t ipt_len; /* size of structure (variable) */ + u_int8_t ipt_ptr; /* index of current entry */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ipt_flg:4; /* flags, see below */ + unsigned int ipt_oflw:4; /* overflow counter */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ipt_oflw:4; /* overflow counter */ + unsigned int ipt_flg:4; /* flags, see below */ +#endif + u_int32_t data[9]; + }; +#endif /* __USE_BSD */ + +#define IPVERSION 4 /* IP version number */ +#define IP_MAXPACKET 65535 /* maximum packet size */ + +/* + * Definitions for IP type of service (ip_tos) + */ +#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 + +/* + * Definitions for IP precedence (also in ip_tos) (hopefully unused) + */ +#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 + +/* + * Definitions for options. + */ +#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 /* end of option list */ +#define IPOPT_END IPOPT_EOL +#define IPOPT_NOP 1 /* no operation */ +#define IPOPT_NOOP IPOPT_NOP + +#define IPOPT_RR 7 /* record packet route */ +#define IPOPT_TS 68 /* timestamp */ +#define IPOPT_TIMESTAMP IPOPT_TS +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ +#define IPOPT_SEC IPOPT_SECURITY +#define IPOPT_LSRR 131 /* loose source route */ +#define IPOPT_SATID 136 /* satnet id */ +#define IPOPT_SID IPOPT_SATID +#define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_RA 148 /* router alert */ + +/* + * Offsets to fields in options other than EOL and NOP. + */ +#define IPOPT_OPTVAL 0 /* option ID */ +#define IPOPT_OLEN 1 /* option length */ +#define IPOPT_OFFSET 2 /* offset within option */ +#define IPOPT_MINOFF 4 /* min value of above */ + +#define MAX_IPOPTLEN 40 + +/* flag bits for ipt_flg */ +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +/* bits for security (not byte swapped) */ +#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 + +/* + * Internet implementation parameters. + */ +#define MAXTTL 255 /* maximum time to live (seconds) */ +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ +#define IPTTLDEC 1 /* subtracted when forwarding */ + +#define IP_MSS 576 /* default maximum segment size */ + +__END_DECLS + +#endif /* netinet/ip.h */ diff --git a/include/netinet/ip6.h b/include/netinet/ip6.h new file mode 100644 index 0000000..bef2af2 --- /dev/null +++ b/include/netinet/ip6.h @@ -0,0 +1,189 @@ +/* Copyright (C) 1991-1997, 2001, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IP6_H +#define _NETINET_IP6_H 1 + +#include +#include + +struct ip6_hdr + { + union + { + struct ip6_hdrctl + { + uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, + 20 bits flow-ID */ + uint16_t ip6_un1_plen; /* payload length */ + uint8_t ip6_un1_nxt; /* next header */ + uint8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + }; + +#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 + +/* Generic extension header. */ +struct ip6_ext + { + uint8_t ip6e_nxt; /* next header. */ + uint8_t ip6e_len; /* length in units of 8 octets. */ + }; + +/* Hop-by-Hop options header. */ +struct ip6_hbh + { + uint8_t ip6h_nxt; /* next header. */ + uint8_t ip6h_len; /* length in units of 8 octets. */ + /* followed by options */ + }; + +/* Destination options header */ +struct ip6_dest + { + uint8_t ip6d_nxt; /* next header */ + uint8_t ip6d_len; /* length in units of 8 octets */ + /* followed by options */ + }; + +/* Routing header */ +struct ip6_rthdr + { + uint8_t ip6r_nxt; /* next header */ + uint8_t ip6r_len; /* length in units of 8 octets */ + uint8_t ip6r_type; /* routing type */ + uint8_t ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ + }; + +/* Type 0 Routing header */ +struct ip6_rthdr0 + { + uint8_t ip6r0_nxt; /* next header */ + uint8_t ip6r0_len; /* length in units of 8 octets */ + uint8_t ip6r0_type; /* always zero */ + uint8_t ip6r0_segleft; /* segments left */ + uint8_t ip6r0_reserved; /* reserved field */ + uint8_t ip6r0_slmap[3]; /* strict/loose bit map */ + /* followed by up to 127 struct in6_addr */ + struct in6_addr ip6r0_addr[0]; + }; + +/* Fragment header */ +struct ip6_frag + { + uint8_t ip6f_nxt; /* next header */ + uint8_t ip6f_reserved; /* reserved field */ + uint16_t ip6f_offlg; /* offset, reserved, and flag */ + uint32_t ip6f_ident; /* identification */ + }; + +#if BYTE_ORDER == BIG_ENDIAN +# define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +# define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ +#endif + +/* IPv6 options */ +struct ip6_opt + { + uint8_t ip6o_type; + uint8_t ip6o_len; + }; + +/* The high-order 3 bits of the option type define the behavior + * when processing an unknown option and whether or not the option + * content changes in flight. + */ +#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 + +/* Special option types for padding. */ +#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 + +/* Jumbo Payload Option */ +struct ip6_opt_jumbo + { + uint8_t ip6oj_type; + uint8_t ip6oj_len; + uint8_t ip6oj_jumbo_len[4]; + }; +#define IP6OPT_JUMBO_LEN 6 + +/* NSAP Address Option */ +struct ip6_opt_nsap + { + uint8_t ip6on_type; + uint8_t ip6on_len; + uint8_t ip6on_src_nsap_len; + uint8_t ip6on_dst_nsap_len; + /* followed by source NSAP */ + /* followed by destination NSAP */ + }; + +/* Tunnel Limit Option */ +struct ip6_opt_tunnel + { + uint8_t ip6ot_type; + uint8_t ip6ot_len; + uint8_t ip6ot_encap_limit; + }; + +/* Router Alert Option */ +struct ip6_opt_router + { + uint8_t ip6or_type; + uint8_t ip6or_len; + uint8_t ip6or_value[2]; + }; + +/* Router alert values (in network byte order) */ +#if BYTE_ORDER == BIG_ENDIAN +# define IP6_ALERT_MLD 0x0000 +# define IP6_ALERT_RSVP 0x0001 +# define IP6_ALERT_AN 0x0002 +#else /* BYTE_ORDER == LITTLE_ENDING */ +# define IP6_ALERT_MLD 0x0000 +# define IP6_ALERT_RSVP 0x0100 +# define IP6_ALERT_AN 0x0200 +#endif + +#endif /* netinet/ip6.h */ diff --git a/include/netinet/ip_icmp.h b/include/netinet/ip_icmp.h new file mode 100644 index 0000000..2fc8e9c --- /dev/null +++ b/include/netinet/ip_icmp.h @@ -0,0 +1,283 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IP_ICMP_H +#define __NETINET_IP_ICMP_H 1 + +#include +#include + +__BEGIN_DECLS + +struct icmphdr +{ + u_int8_t type; /* message type */ + u_int8_t code; /* type sub-code */ + u_int16_t checksum; + union + { + struct + { + u_int16_t id; + u_int16_t sequence; + } echo; /* echo datagram */ + u_int32_t gateway; /* gateway address */ + struct + { + u_int16_t __unused; + u_int16_t mtu; + } frag; /* path mtu discovery */ + } un; +}; + +#define ICMP_ECHOREPLY 0 /* Echo Reply */ +#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ +#define ICMP_SOURCE_QUENCH 4 /* Source Quench */ +#define ICMP_REDIRECT 5 /* Redirect (change route) */ +#define ICMP_ECHO 8 /* Echo Request */ +#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ +#define ICMP_PARAMETERPROB 12 /* Parameter Problem */ +#define ICMP_TIMESTAMP 13 /* Timestamp Request */ +#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ +#define ICMP_INFO_REQUEST 15 /* Information Request */ +#define ICMP_INFO_REPLY 16 /* Information Reply */ +#define ICMP_ADDRESS 17 /* Address Mask Request */ +#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ +#define NR_ICMP_TYPES 18 + + +/* Codes for UNREACH. */ +#define ICMP_NET_UNREACH 0 /* Network Unreachable */ +#define ICMP_HOST_UNREACH 1 /* Host Unreachable */ +#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */ +#define ICMP_PORT_UNREACH 3 /* Port Unreachable */ +#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */ +#define ICMP_SR_FAILED 5 /* Source Route failed */ +#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 /* Packet filtered */ +#define ICMP_PREC_VIOLATION 14 /* Precedence violation */ +#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */ +#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */ + +/* Codes for REDIRECT. */ +#define ICMP_REDIR_NET 0 /* Redirect Net */ +#define ICMP_REDIR_HOST 1 /* Redirect Host */ +#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */ +#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */ + +/* Codes for TIME_EXCEEDED. */ +#define ICMP_EXC_TTL 0 /* TTL count exceeded */ +#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */ + + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#include +#include + +/* + * Internal of an ICMP Router Advertisement + */ +struct icmp_ra_addr +{ + u_int32_t ira_addr; + u_int32_t ira_preference; +}; + +struct icmp +{ + u_int8_t icmp_type; /* type of message, see below */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement checksum of struct */ + union + { + u_char ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* gateway address */ + struct ih_idseq /* echo datagram */ + { + u_int16_t icd_id; + u_int16_t icd_seq; + } ih_idseq; + u_int32_t ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu + { + u_int16_t ipm_void; + u_int16_t ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv + { + u_int8_t irt_num_addrs; + u_int8_t irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#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 + union + { + struct + { + u_int32_t its_otime; + u_int32_t its_rtime; + u_int32_t its_ttime; + } id_ts; + struct + { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + struct icmp_ra_addr id_radv; + u_int32_t id_mask; + u_int8_t id_data[1]; + } icmp_dun; +#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 +}; + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enough to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#ifndef _IP_VHL +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ +#else +#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8) + /* N.B.: must separately check that header length >= 5 */ +#endif + +/* Definition of type and code fields. */ +/* defined above: ICMP_ECHOREPLY, ICMP_REDIRECT, ICMP_ECHO */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ + +#define ICMP_MAXTYPE 18 + +/* UNREACH codes */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* net denied */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* host denied */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ + +/* REDIRECT codes */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ + +/* TIMEXCEED codes */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ + +/* PARAMPROB code */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ + +#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) + +#endif /* __USE_BSD */ + +__END_DECLS + +#endif /* netinet/ip_icmp.h */ diff --git a/include/netinet/protocols.h b/include/netinet/protocols.h new file mode 100644 index 0000000..1a619c4 --- /dev/null +++ b/include/netinet/protocols.h @@ -0,0 +1,62 @@ +/* protocols.h */ +#ifndef _NETINET_PROTOCOLS_H +#define _NETINET_PROTOCOLS_H + +#define IP_ICMP 1 +#define IP_IGMP 2 +#define IP_GGP 3 +#define IP_ST 5 +#define IP_TCP 6 +#define IP_UCL 7 +#define IP_EGP 8 +#define IP_IGP 9 +#define IP_BBN_RCC_MON 10 +#define IP_NVP_II 11 +#define IP_PUP 12 +#define IP_ARGUS 13 +#define IP_EMCON 14 +#define IP_XNET 15 +#define IP_CHAOS 16 +#define IP_UDP 17 +#define IP_MUX 18 +#define IP_DCN_MEAS 19 +#define IP_HMP 20 +#define IP_PRM 21 +#define IP_XNS_IDP 22 +#define IP_TRUNK1 23 +#define IP_TRUNK2 24 +#define IP_LEAF1 25 +#define IP_LEAF2 26 +#define IP_RDP 27 +#define IP_IRTP 28 +#define IP_ISO_TP4 29 +#define IP_NETBLT 30 +#define IP_MFE_NSP 31 +#define IP_MERIT_INP 32 +#define IP_SEP 33 +#define IP_3PC 34 +#define IP_CFTP 62 +#define SAT_EXPAK 64 +#define IP_RVD 66 +#define IP_IPPC 67 +#define IP_SAT_MON 69 +#define IP_VISA 70 +#define IP_IPCV 71 +#define IP_BR_SAT_MON 76 +#define IP_SUN_ND 77 +#define IP_WB_MON 78 +#define IP_WB_EXPAK 79 +#define IP_ISO_IP 80 +#define IP_VMTP 81 +#define IP_SECURE_VMTP 82 +#define IP_VINES 83 +#define IP_TTP 84 +#define NSFNET_IGP 85 +#define IP_DGP 86 +#define IP_TCF 87 +#define IP_IGRP 88 +#define IP_OSPFIGP 89 +#define IP_SPRITE_RPG 90 +#define IP_LARP 91 + +#endif /* _NETINET_PROTOCOLS_H*/ diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h new file mode 100644 index 0000000..06e8414 --- /dev/null +++ b/include/netinet/tcp.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H 1 + +#include + +/* + * User-settable options (used with setsockopt). + */ +#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */ +#define TCP_MAXSEG 2 /* Set maximum segment size */ +#define TCP_CORK 3 /* Control sending of partial frames */ +#define TCP_KEEPIDLE 4 /* Start keeplives after this period */ +#define TCP_KEEPINTVL 5 /* Interval between keepalives */ +#define TCP_KEEPCNT 6 /* Number of keepalives before death */ +#define TCP_SYNCNT 7 /* Number of SYN retransmits */ +#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ +#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ +#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */ +#define TCP_INFO 11 /* Information about this connection. */ +#define TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ +#define TCP_CONGESTION 13 /* Congestion control algorithm. */ +#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ + +#ifdef __USE_MISC +# include +# include + +# ifdef __FAVOR_BSD +typedef u_int32_t tcp_seq; +/* + * TCP header. + * Per RFC 793, September, 1981. + */ +struct tcphdr + { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t th_x2:4; /* (unused) */ + u_int8_t th_off:4; /* data offset */ +# endif +# if __BYTE_ORDER == __BIG_ENDIAN + u_int8_t th_off:4; /* data offset */ + u_int8_t th_x2:4; /* (unused) */ +# endif + u_int8_t th_flags; +# define TH_FIN 0x01 +# define TH_SYN 0x02 +# define TH_RST 0x04 +# define TH_PUSH 0x08 +# define TH_ACK 0x10 +# define TH_URG 0x20 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}; + +# else /* !__FAVOR_BSD */ +struct tcphdr + { + u_int16_t source; + u_int16_t dest; + u_int32_t seq; + u_int32_t ack_seq; +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int16_t res1:4; + u_int16_t doff:4; + u_int16_t fin:1; + u_int16_t syn:1; + u_int16_t rst:1; + u_int16_t psh:1; + u_int16_t ack:1; + u_int16_t urg:1; + u_int16_t res2:2; +# elif __BYTE_ORDER == __BIG_ENDIAN + u_int16_t doff:4; + u_int16_t res1:4; + u_int16_t res2:2; + u_int16_t urg:1; + u_int16_t ack:1; + u_int16_t psh:1; + u_int16_t rst:1; + u_int16_t syn:1; + u_int16_t fin:1; +# else +# error "Adjust your defines" +# endif + u_int16_t window; + u_int16_t check; + u_int16_t urg_ptr; +}; +# endif /* __FAVOR_BSD */ + +enum +{ + TCP_ESTABLISHED = 1, + TCP_SYN_SENT, + TCP_SYN_RECV, + TCP_FIN_WAIT1, + TCP_FIN_WAIT2, + TCP_TIME_WAIT, + TCP_CLOSE, + TCP_CLOSE_WAIT, + TCP_LAST_ACK, + TCP_LISTEN, + TCP_CLOSING /* now a valid state */ +}; + +# define TCPOPT_EOL 0 +# define TCPOPT_NOP 1 +# define TCPOPT_MAXSEG 2 +# define TCPOLEN_MAXSEG 4 +# define TCPOPT_WINDOW 3 +# define TCPOLEN_WINDOW 3 +# define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +# define TCPOLEN_SACK_PERMITTED 2 +# define TCPOPT_SACK 5 /* Experimental */ +# define TCPOPT_TIMESTAMP 8 +# define TCPOLEN_TIMESTAMP 10 +# define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ + +# define TCPOPT_TSTAMP_HDR \ + (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) + +/* + * Default maximum segment size for TCP. + * With an IP MSS of 576, this is 536, + * but 512 is probably more convenient. + * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). + */ +# define TCP_MSS 512 + +# define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ + +# define TCP_MAX_WINSHIFT 14 /* maximum window shift */ + +# define SOL_TCP 6 /* TCP level */ + + +# define TCPI_OPT_TIMESTAMPS 1 +# define TCPI_OPT_SACK 2 +# define TCPI_OPT_WSCALE 4 +# define TCPI_OPT_ECN 8 + +/* Values for tcpi_state. */ +enum tcp_ca_state +{ + TCP_CA_Open = 0, + TCP_CA_Disorder = 1, + TCP_CA_CWR = 2, + TCP_CA_Recovery = 3, + TCP_CA_Loss = 4 +}; + +struct tcp_info +{ + u_int8_t tcpi_state; + u_int8_t tcpi_ca_state; + u_int8_t tcpi_retransmits; + u_int8_t tcpi_probes; + u_int8_t tcpi_backoff; + u_int8_t tcpi_options; + u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + + u_int32_t tcpi_rto; + u_int32_t tcpi_ato; + u_int32_t tcpi_snd_mss; + u_int32_t tcpi_rcv_mss; + + u_int32_t tcpi_unacked; + u_int32_t tcpi_sacked; + u_int32_t tcpi_lost; + u_int32_t tcpi_retrans; + u_int32_t tcpi_fackets; + + /* Times. */ + u_int32_t tcpi_last_data_sent; + u_int32_t tcpi_last_ack_sent; /* Not remembered, sorry. */ + u_int32_t tcpi_last_data_recv; + u_int32_t tcpi_last_ack_recv; + + /* Metrics. */ + u_int32_t tcpi_pmtu; + u_int32_t tcpi_rcv_ssthresh; + u_int32_t tcpi_rtt; + u_int32_t tcpi_rttvar; + u_int32_t tcpi_snd_ssthresh; + u_int32_t tcpi_snd_cwnd; + u_int32_t tcpi_advmss; + u_int32_t tcpi_reordering; + + u_int32_t tcpi_rcv_rtt; + u_int32_t tcpi_rcv_space; + + u_int32_t tcpi_total_retrans; +}; + + +/* For TCP_MD5SIG socket option. */ +#define TCP_MD5SIG_MAXKEYLEN 80 + +struct tcp_md5sig +{ + struct sockaddr_storage tcpm_addr; /* Address associated. */ + u_int16_t __tcpm_pad1; /* Zero. */ + u_int16_t tcpm_keylen; /* Key length. */ + u_int32_t __tcpm_pad2; /* Zero. */ + u_int8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary). */ +}; + +#endif /* Misc. */ + +#endif /* netinet/tcp.h */ diff --git a/include/netinet/udp.h b/include/netinet/udp.h new file mode 100644 index 0000000..45b69f7 --- /dev/null +++ b/include/netinet/udp.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Copyright (C) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __NETINET_UDP_H +#define __NETINET_UDP_H 1 + +#include +#include + + +/* UDP header as specified by RFC 768, August 1980. */ +#ifdef __FAVOR_BSD + +struct udphdr +{ + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +}; + +#else + +struct udphdr +{ + u_int16_t source; + u_int16_t dest; + u_int16_t len; + u_int16_t check; +}; +#endif + +#define SOL_UDP 17 /* sockopt level for UDP */ + +#endif /* netinet/udp.h */ diff --git a/include/netipx/ipx.h b/include/netipx/ipx.h new file mode 100644 index 0000000..7eb42ef --- /dev/null +++ b/include/netipx/ipx.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETIPX_IPX_H +#define __NETIPX_IPX_H 1 + +#include + +#include +#include + +__BEGIN_DECLS + +#define SOL_IPX 256 /* sockopt level */ + +#define IPX_TYPE 1 +#define IPX_NODE_LEN 6 +#define IPX_MTU 576 + +struct sockaddr_ipx + { + sa_family_t sipx_family; + u_int16_t sipx_port; + u_int32_t sipx_network; + unsigned char sipx_node[IPX_NODE_LEN]; + u_int8_t sipx_type; + unsigned char sipx_zero; /* 16 byte fill */ + }; + +/* + * So we can fit the extra info for SIOCSIFADDR into the address nicely + */ + +#define sipx_special sipx_port +#define sipx_action sipx_zero +#define IPX_DLTITF 0 +#define IPX_CRTITF 1 + +typedef struct ipx_route_definition + { + unsigned long ipx_network; + unsigned long ipx_router_network; + unsigned char ipx_router_node[IPX_NODE_LEN]; + } +ipx_route_definition; + +typedef struct ipx_interface_definition + { + unsigned long ipx_network; + unsigned char ipx_device[16]; + unsigned char ipx_dlink_type; +#define IPX_FRAME_NONE 0 +#define IPX_FRAME_SNAP 1 +#define IPX_FRAME_8022 2 +#define IPX_FRAME_ETHERII 3 +#define IPX_FRAME_8023 4 +#define IPX_FRAME_TR_8022 5 + unsigned char ipx_special; +#define IPX_SPECIAL_NONE 0 +#define IPX_PRIMARY 1 +#define IPX_INTERNAL 2 + unsigned char ipx_node[IPX_NODE_LEN]; + } +ipx_interface_definition; + +typedef struct ipx_config_data + { + unsigned char ipxcfg_auto_select_primary; + unsigned char ipxcfg_auto_create_interfaces; + } +ipx_config_data; + +/* + * OLD Route Definition for backward compatibility. + */ + +struct ipx_route_def + { + unsigned long ipx_network; + unsigned long ipx_router_network; +#define IPX_ROUTE_NO_ROUTER 0 + unsigned char ipx_router_node[IPX_NODE_LEN]; + unsigned char ipx_device[16]; + unsigned short ipx_flags; +#define IPX_RT_SNAP 8 +#define IPX_RT_8022 4 +#define IPX_RT_BLUEBOOK 2 +#define IPX_RT_ROUTED 1 + }; + +#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE) +#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE + 1) +#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE + 2) +#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE + 3) + +__END_DECLS + +#endif /* netipx/ipx.h */ diff --git a/include/netpacket/packet.h b/include/netpacket/packet.h new file mode 100644 index 0000000..6c63428 --- /dev/null +++ b/include/netpacket/packet.h @@ -0,0 +1,64 @@ +/* Definitions for use with Linux AF_PACKET sockets. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETPACKET_PACKET_H +#define __NETPACKET_PACKET_H 1 + +struct sockaddr_ll + { + unsigned short int sll_family; + unsigned short int sll_protocol; + int sll_ifindex; + unsigned short int sll_hatype; + unsigned char sll_pkttype; + unsigned char sll_halen; + unsigned char sll_addr[8]; + }; + +/* Packet types. */ + +#define PACKET_HOST 0 /* To us. */ +#define PACKET_BROADCAST 1 /* To all. */ +#define PACKET_MULTICAST 2 /* To group. */ +#define PACKET_OTHERHOST 3 /* To someone else. */ +#define PACKET_OUTGOING 4 /* Originated by us . */ +#define PACKET_LOOPBACK 5 +#define PACKET_FASTROUTE 6 + +/* Packet socket options. */ + +#define PACKET_ADD_MEMBERSHIP 1 +#define PACKET_DROP_MEMBERSHIP 2 +#define PACKET_RECV_OUTPUT 3 +#define PACKET_RX_RING 5 +#define PACKET_STATISTICS 6 + +struct packet_mreq + { + int mr_ifindex; + unsigned short int mr_type; + unsigned short int mr_alen; + unsigned char mr_address[8]; + }; + +#define PACKET_MR_MULTICAST 0 +#define PACKET_MR_PROMISC 1 +#define PACKET_MR_ALLMULTI 2 + +#endif /* netpacket/packet.h */ diff --git a/include/nl_types.h b/include/nl_types.h new file mode 100644 index 0000000..74e7621 --- /dev/null +++ b/include/nl_types.h @@ -0,0 +1,59 @@ +/* Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NL_TYPES_H +#define _NL_TYPES_H 1 + +#include + +/* The default message set used by the gencat program. */ +#define NL_SETD 1 + +/* Value for FLAG parameter of `catgets' to say we want XPG4 compliance. */ +#define NL_CAT_LOCALE 1 + + +__BEGIN_DECLS + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: None of these prototypes have implementations." +#endif + +/* Message catalog descriptor type. */ +typedef void *nl_catd; + +/* Type used by `nl_langinfo'. */ +typedef int nl_item; + +/* Open message catalog for later use, returning descriptor. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern nl_catd catopen (__const char *__cat_name, int __flag) __nonnull ((1)); + +/* Return translation with NUMBER in SET of CATALOG; if not found + return STRING. */ +extern char *catgets (nl_catd __catalog, int __set, int __number, + __const char *__string) __THROW __nonnull ((1)); + +/* Close message CATALOG. */ +extern int catclose (nl_catd __catalog) __THROW __nonnull ((1)); + +__END_DECLS + +#endif /* nl_types.h */ diff --git a/include/obstack.h b/include/obstack.h new file mode 100644 index 0000000..65eb2ba --- /dev/null +++ b/include/obstack.h @@ -0,0 +1,509 @@ +/* obstack.h - object stack macros + Copyright (C) 1988-1994,1996-1999,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Summary: + +All the apparent functions defined here are macros. The idea +is that you would use these pre-tested macros to solve a +very specific set of problems, and they would run fast. +Caution: no side-effects in arguments please!! They may be +evaluated MANY times!! + +These macros operate a stack of objects. Each object starts life +small, and may grow to maturity. (Consider building a word syllable +by syllable.) An object can move while it is growing. Once it has +been "finished" it never changes address again. So the "top of the +stack" is typically an immature growing object, while the rest of the +stack is of mature, fixed size and fixed address objects. + +These routines grab large chunks of memory, using a function you +supply, called `obstack_chunk_alloc'. On occasion, they free chunks, +by calling `obstack_chunk_free'. You must define them and declare +them before using any obstack macros. + +Each independent stack is represented by a `struct obstack'. +Each of the obstack macros expects a pointer to such a structure +as the first argument. + +One motivation for this package is the problem of growing char strings +in symbol tables. Unless you are "fascist pig with a read-only mind" +--Gosper's immortal quote from HAKMEM item 154, out of context--you +would not like to put any arbitrary upper limit on the length of your +symbols. + +In practice this often means you will build many short symbols and a +few long symbols. At the time you are reading a symbol you don't know +how long it is. One traditional method is to read a symbol into a +buffer, realloc()ating the buffer every time you try to read a symbol +that is longer than the buffer. This is beaut, but you still will +want to copy the symbol from the buffer to a more permanent +symbol-table entry say about half the time. + +With obstacks, you can work differently. Use one obstack for all symbol +names. As you read a symbol, grow the name in the obstack gradually. +When the name is complete, finalize it. Then, if the symbol exists already, +free the newly read name. + +The way we do this is to take a large chunk, allocating memory from +low addresses. When you want to build a symbol in the chunk you just +add chars above the current "high water mark" in the chunk. When you +have finished adding chars, because you got to the end of the symbol, +you know how long the chars are, and you can create a new object. +Mostly the chars will not burst over the highest address of the chunk, +because you would typically expect a chunk to be (say) 100 times as +long as an average object. + +In case that isn't clear, when we have enough chars to make up +the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) +so we just point to it where it lies. No moving of chars is +needed and this is the second win: potentially long strings need +never be explicitly shuffled. Once an object is formed, it does not +change its address during its lifetime. + +When the chars burst over a chunk boundary, we allocate a larger +chunk, and then copy the partly formed object from the end of the old +chunk to the beginning of the new larger chunk. We then carry on +accreting characters to the end of the object as we normally would. + +A special macro is provided to add a single char at a time to a +growing object. This allows the use of register variables, which +break the ordinary 'growth' macro. + +Summary: + We allocate large chunks. + We carve out one object at a time from the current chunk. + Once carved, an object never moves. + We are free to append data of any size to the currently + growing object. + Exactly one object is growing in an obstack at any one time. + You can run one obstack per control block. + You may have as many control blocks as you dare. + Because of the way we do it, you can `unwind' an obstack + back to a previous state. (You may remove objects much + as you would with a stack.) +*/ + + +/* Don't do the contents of this file more than once. */ + +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is + defined, as with GNU C, use that; that way we don't pollute the + namespace with 's symbols. Otherwise, include + and use ptrdiff_t. */ + +#ifdef __PTRDIFF_TYPE__ +# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#else +# include +# define PTR_INT_TYPE ptrdiff_t +#endif + +/* If B is the base of an object addressed by P, return the result of + aligning P to the next multiple of A + 1. B and P must be of type + char *. A + 1 must be a power of 2. */ + +#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) + +/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case + where pointers can be converted to integers, aligned as integers, + and converted back again. If PTR_INT_TYPE is narrower than a + pointer (e.g., the AS/400), play it safe and compute the alignment + relative to B. Otherwise, use the faster strategy of computing the + alignment relative to 0. */ + +#define __PTR_ALIGN(B, P, A) \ + __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ + P, A) + +#include + +struct _obstack_chunk /* Lives at front of each chunk. */ +{ + char *limit; /* 1 past end of this chunk */ + struct _obstack_chunk *prev; /* address of prior chunk or NULL */ + char contents[4]; /* objects begin here */ +}; + +struct obstack /* control current object in current chunk */ +{ + long chunk_size; /* preferred size to allocate chunks in */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ + char *object_base; /* address of object we are building */ + char *next_free; /* where to add next char to current object */ + char *chunk_limit; /* address of char after current chunk */ + union + { + PTR_INT_TYPE tempint; + void *tempptr; + } temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ + /* These prototypes vary based on `use_extra_arg', and we use + casts to the prototypeless function type in all assignments, + but having prototypes here quiets -Wstrict-prototypes. */ + struct _obstack_chunk *(*chunkfun) (void *, long); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ + unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ + unsigned maybe_empty_object:1;/* There is a possibility that the current + chunk contains a zero-length object. This + prevents freeing the chunk if we allocate + a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ +}; + +/* Declare the external functions we use; they are in obstack.c. */ + +extern void _obstack_newchunk (struct obstack *, int); +extern int _obstack_begin (struct obstack *, int, int, + void *(*) (long), void (*) (void *)); +extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (void *, long), + void (*) (void *, void *), void *); +extern int _obstack_memory_used (struct obstack *); + +void obstack_free (struct obstack *obstack, void *block); + + +/* Error handler called when `obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function which + should either abort gracefully or use longjump - but shouldn't + return. The default action is to print a message and abort. */ +extern void (*obstack_alloc_failed_handler) (void); + +/* Exit value used when `print_and_abort' is used. */ +extern int obstack_exit_failure; + +/* Pointer to beginning of object being allocated or to be allocated next. + Note that this might not be the final address of the object + because a new chunk might be needed to hold the final size. */ + +#define obstack_base(h) ((void *) (h)->object_base) + +/* Size for allocating ordinary chunks. */ + +#define obstack_chunk_size(h) ((h)->chunk_size) + +/* Pointer to next byte not yet allocated in current chunk. */ + +#define obstack_next_free(h) ((h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +/* To prevent prototype warnings provide complete argument list. */ +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), \ + (void (*) (void *)) (freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg)) + +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) + +#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) + +#define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used (h) + +#if defined __GNUC__ && defined __STDC__ && __STDC__ +/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ +# if __GNUC__ < 2 || (defined __NeXT__ && __NeXT__ && !__GNUC_MINOR__) +# define __extension__ +# endif + +/* For GNU C, if not -traditional, + we can define these macros to compute all args only once + without using a global variable. + Also, we can avoid using the `temp' slot, to make faster code. */ + +# define obstack_object_size(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->next_free - __o->object_base); }) + +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->chunk_limit - __o->next_free); }) + +# define obstack_make_room(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + +# define obstack_empty_p(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (__o->chunk->prev == 0 \ + && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ + __o->chunk->contents, \ + __o->alignment_mask)); }) + +# define obstack_grow(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_grow0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + (void) 0; }) + +# define obstack_1grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ + obstack_1grow_fast (__o, datum); \ + (void) 0; }) + +/* These assume that the obstack alignment is good enough for pointers + or ints, and that the data added so far to the current object + shares that much alignment. */ + +# define obstack_ptr_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ + obstack_ptr_grow_fast (__o, datum); }) \ + +# define obstack_int_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ + obstack_int_grow_fast (__o, datum); }) + +# define obstack_ptr_grow_fast(OBSTACK,aptr) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(const void **) __o1->next_free = (aptr); \ + __o1->next_free += sizeof (const void *); \ + (void) 0; }) + +# define obstack_int_grow_fast(OBSTACK,aint) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(int *) __o1->next_free = (aint); \ + __o1->next_free += sizeof (int); \ + (void) 0; }) + +# define obstack_blank(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + obstack_blank_fast (__o, __len); \ + (void) 0; }) + +# define obstack_alloc(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_blank (__h, (length)); \ + obstack_finish (__h); }) + +# define obstack_copy(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow (__h, (where), (length)); \ + obstack_finish (__h); }) + +# define obstack_copy0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow0 (__h, (where), (length)); \ + obstack_finish (__h); }) + +/* The local variable is named __o1 to avoid a name conflict + when obstack_blank is called. */ +# define obstack_finish(OBSTACK) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + void *__value = (void *) __o1->object_base; \ + if (__o1->next_free == __value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ + __o1->alignment_mask); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + __value; }) + +# define obstack_free(OBSTACK, OBJ) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + void *__obj = (OBJ); \ + if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ + __o->next_free = __o->object_base = (char *)__obj; \ + else (obstack_free) (__o, __obj); }) + +#else /* not __GNUC__ or not __STDC__ */ + +# define obstack_object_size(h) \ + (unsigned) ((h)->next_free - (h)->object_base) + +# define obstack_room(h) \ + (unsigned) ((h)->chunk_limit - (h)->next_free) + +# define obstack_empty_p(h) \ + ((h)->chunk->prev == 0 \ + && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ + (h)->chunk->contents, \ + (h)->alignment_mask)) + +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +# define obstack_make_room(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) + +# define obstack_grow(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint) + +# define obstack_grow0(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint, \ + *((h)->next_free)++ = 0) + +# define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + obstack_1grow_fast (h, datum)) + +# define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + obstack_ptr_grow_fast (h, datum)) + +# define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + obstack_int_grow_fast (h, datum)) + +# define obstack_ptr_grow_fast(h,aptr) \ + (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) + +# define obstack_int_grow_fast(h,aint) \ + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) + +# define obstack_blank(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + obstack_blank_fast (h, (h)->temp.tempint)) + +# define obstack_alloc(h,length) \ + (obstack_blank ((h), (length)), obstack_finish ((h))) + +# define obstack_copy(h,where,length) \ + (obstack_grow ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_copy0(h,where,length) \ + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_finish(h) \ +( ((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp.tempptr = (h)->object_base, \ + (h)->next_free \ + = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ + (h)->alignment_mask), \ + (((h)->next_free - (char *) (h)->chunk \ + > (h)->chunk_limit - (char *) (h)->chunk) \ + ? ((h)->next_free = (h)->chunk_limit) : 0), \ + (h)->object_base = (h)->next_free, \ + (h)->temp.tempptr) + +# define obstack_free(h,obj) \ +( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ + ((((h)->temp.tempint > 0 \ + && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp.tempint + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) + +#endif /* not __GNUC__ or not __STDC__ */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/include/paths.h b/include/paths.h new file mode 100644 index 0000000..ae892c4 --- /dev/null +++ b/include/paths.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)paths.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +/* Default search path. */ +#define _PATH_DEFPATH "/usr/bin:/bin" +/* All standard utilities path. */ +#define _PATH_STDPATH \ + "/usr/bin:/bin:/usr/sbin:/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_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" + +/* uClibc */ +#ifdef _LIBC +#define _PATH_PASSWD "/etc/passwd" +#define _PATH_GROUP "/etc/group" +#endif + +/* Provide trailing slash, since mostly used for building pathnames. */ +#define _PATH_DEV "/dev/" +#define _PATH_TMP "/tmp/" +#define _PATH_VARDB "/var/db/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif /* !_PATHS_H_ */ diff --git a/include/poll.h b/include/poll.h new file mode 100644 index 0000000..06fb41a --- /dev/null +++ b/include/poll.h @@ -0,0 +1 @@ +#include diff --git a/include/printf.h b/include/printf.h new file mode 100644 index 0000000..72dffaa --- /dev/null +++ b/include/printf.h @@ -0,0 +1,237 @@ +/* Copyright (C) 1991-1993,1995-1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* March 11, 2001 Manuel Novoa III + * + * Modified as appropriate for my new stdio lib. + */ + +#ifndef _PRINTF_H + +#define _PRINTF_H 1 +#include + +__BEGIN_DECLS + +#define __need_FILE +#include +#define __need_size_t +#define __need_wchar_t +#include + +/* WARNING -- This is definitely nonportable... but it seems to work + * with gcc, which is currently the only "supported" compiler. + * The library code uses bitmasks for space-efficiency (you can't + * set/test multiple bitfields in one operation). Unfortunatly, we + * need to support bitfields since that's what glibc made visible to users. + * So, we take + * advantage of how gcc lays out bitfields to create an appropriate + * mapping. Inside uclibc (UCLIBC_INTERNAL is defined) we access the + * bitfields using bitmasks in a single flag variable. + * + * WARNING -- This may very well fail if built with -fpack-struct!!! + * + * TODO -- Add a validation test. + * TODO -- Add an option to build in a shim translation function if + * the bitfield<->bitmask mapping fails. + */ +#include + +struct printf_info { + int prec; /* Precision. */ + int width; /* Width. */ +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t spec; /* Format letter. */ +#else + int spec; +#endif + +#ifndef UCLIBC_INTERNAL + +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int space:1; /* Space flag. */ + unsigned int showsign:1; /* + flag. */ + unsigned int extra:1; /* For special use. */ + unsigned int left:1; /* - flag. */ + unsigned int alt:1; /* # flag. */ + unsigned int group:1; /* ' flag. */ + unsigned int i18n:1; /* I flag. */ + unsigned int wide:1; /* Nonzero for wide character streams. */ + unsigned int is_char:1; /* hh flag. */ + unsigned int is_short:1; /* h flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_long_double:1;/* L flag. */ + unsigned int __padding:20; /* non-gnu: match _flags width of 32 bits */ +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int __padding:20; /* non-gnu: match _flags width of 32 bits */ + unsigned int is_long_double:1;/* L flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_short:1; /* h flag. */ + unsigned int is_char:1; /* hh flag. */ + unsigned int wide:1; /* Nonzero for wide character streams. */ + unsigned int i18n:1; /* I flag. */ + unsigned int group:1; /* ' flag. */ + unsigned int alt:1; /* # flag. */ + unsigned int left:1; /* - flag. */ + unsigned int extra:1; /* For special use. */ + unsigned int showsign:1; /* + flag. */ + unsigned int space:1; /* Space flag. */ +#else +#error unsupported byte order! +#endif + +#else /* UCLIBC_INTERNAL */ + + uint32_t _flags; /* non-gnu */ +#define __PRINT_INFO_FLAG_space (1<<0) +#define __PRINT_INFO_FLAG_showsign (1<<1) +#define __PRINT_INFO_FLAG_extra (1<<2) +#define __PRINT_INFO_FLAG_left (1<<3) +#define __PRINT_INFO_FLAG_alt (1<<4) +#define __PRINT_INFO_FLAG_group (1<<5) +#define __PRINT_INFO_FLAG_i18n (1<<6) +#define __PRINT_INFO_FLAG_wide (1<<7) + +#define __PRINT_INFO_FLAG_is_char (1<<8) +#define __PRINT_INFO_FLAG_is_short (1<<9) +#define __PRINT_INFO_FLAG_is_long (1<<10) +#define __PRINT_INFO_FLAG_is_long_double (1<<11) + +#define PRINT_INFO_FLAG_VAL(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags & __PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_SET_FLAG(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags |= __PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_CLR_FLAG(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags &= ~__PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_SET_extra(INFO_PTR,VAL) \ + ((INFO_PTR)->_flags |= (((INFO_PTR)->_flags & ~1) | ((VAL) & 1))) + +#endif /* UCLIBC_INTERNAL */ + +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t pad; /* Padding character. */ +#else + int pad; +#endif +}; + + +/* Type of a printf specifier-handler function. + STREAM is the FILE on which to write output. + INFO gives information about the format specification. + ARGS is a vector of pointers to the argument data; + the number of pointers will be the number returned + by the associated arginfo function for the same INFO. + + The function should return the number of characters written, + or -1 for errors. */ + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +typedef int (*printf_function) (FILE *__stream, + __const struct printf_info *__info, + __const void *__const *__args); + +/* Type of a printf specifier-arginfo function. + INFO gives information about the format specification. + N, ARGTYPES, and return value are as for parse_printf_format. */ + +typedef int printf_arginfo_function (__const struct printf_info *__info, + size_t __n, int *__argtypes); + + +/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be + specified to determine how many arguments a SPEC conversion requires and + what their types are. */ + +extern int register_printf_function (int __spec, printf_function __func, + printf_arginfo_function __arginfo); +#endif + + +/* Parse FMT, and fill in N elements of ARGTYPES with the + types needed for the conversions FMT specifies. Returns + the number of arguments required by FMT. + + The ARGINFO function registered with a user-defined format is passed a + `struct printf_info' describing the format spec being parsed. A width + or precision of INT_MIN means a `*' was used to indicate that the + width/precision will come from an arg. The function should fill in the + array it is passed with the types of the arguments it wants, and return + the number of arguments it wants. */ + +extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n, + int *__restrict __argtypes) __THROW; + + +/* Codes returned by `parse_printf_format' for basic types. + + These values cover all the standard format specifications. + Users can add new values after PA_LAST for their own types. */ + +/* WARNING -- The above is not entirely true, even for glibc. + * As far as the library code is concerned, such args are treated + * as 'your type' pointers if qualified by PA_FLAG_PTR. If they + * aren't qualified as pointers, I _think_ glibc just ignores them + * and carries on. I think it should be treated as an error. */ + +enum { /* C type: */ + PA_INT, /* int */ + PA_CHAR, /* int, cast to char */ + PA_WCHAR, /* wide char */ + PA_STRING, /* const char *, a '\0'-terminated string */ + PA_WSTRING, /* const wchar_t *, wide character string */ + PA_POINTER, /* void * */ + PA_FLOAT, /* float */ + PA_DOUBLE, /* double */ + __PA_NOARG, /* non-glibc -- signals non-arg width or prec */ + PA_LAST +}; + +/* Flag bits that can be set in a type returned by `parse_printf_format'. */ +/* WARNING -- These differ in value from what glibc uses. */ +#define PA_FLAG_MASK (0xff00) +#define __PA_FLAG_CHAR (0x0100) /* non-gnu -- to deal with hh */ +#define PA_FLAG_SHORT (0x0200) +#define PA_FLAG_LONG (0x0400) +#define PA_FLAG_LONG_LONG (0x0800) +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG +#define PA_FLAG_PTR (0x1000) /* TODO -- make dynamic??? */ + +#define __PA_INTMASK (0x0f00) /* non-gnu -- all int flags */ + +#if 0 +/* Function which can be registered as `printf'-handlers. */ + +/* Print floating point value using using abbreviations for the orders + of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If + the format specifier is a uppercase character powers of 1000 are + used. Otherwise powers of 1024. */ +extern int printf_size (FILE *__restrict __fp, + __const struct printf_info *__info, + __const void *__const *__restrict __args) __THROW; + +/* This is the appropriate argument information function for `printf_size'. */ +extern int printf_size_info (__const struct printf_info *__restrict + __info, size_t __n, int *__restrict __argtypes) + __THROW; + +#endif + +__END_DECLS + +#endif /* printf.h */ diff --git a/include/protocols/routed.h b/include/protocols/routed.h new file mode 100644 index 0000000..befd865 --- /dev/null +++ b/include/protocols/routed.h @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)routed.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_ROUTED_H +#define _PROTOCOLS_ROUTED_H 1 + +#include +/* + * Routing Information Protocol + * + * Derived from Xerox NS Routing Information Protocol + * by changing 32-bit net numbers to sockaddr's and + * padding stuff to 32-bit boundaries. + */ +#define RIPVERSION 1 + +struct netinfo { + struct sockaddr rip_dst; /* destination net/host */ + int rip_metric; /* cost of route */ +}; + +struct rip { + u_char rip_cmd; /* request/response */ + u_char rip_vers; /* protocol version # */ + u_char rip_res1[2]; /* pad to 32-bit boundary */ + union { + struct netinfo ru_nets[1]; /* variable length... */ + char ru_tracefile[1]; /* ditto ... */ + } ripun; +#define rip_nets ripun.ru_nets +#define rip_tracefile ripun.ru_tracefile +}; + +/* + * Packet types. + */ +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ +#define RIPCMD_TRACEON 3 /* turn tracing on */ +#define RIPCMD_TRACEOFF 4 /* turn it off */ + +#define RIPCMD_MAX 5 +#ifdef RIPCMDS +char *ripcmds[RIPCMD_MAX] = + { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; +#endif + +#define HOPCNT_INFINITY 16 /* per Xerox NS */ +#define MAXPACKETSIZE 512 /* max broadcast size */ + +/* + * Timer values used in managing the routing table. + * Complete tables are broadcast every SUPPLY_INTERVAL seconds. + * If changes occur between updates, dynamic updates containing only changes + * may be sent. When these are sent, a timer is set for a random value + * between MIN_WAITTIME and MAX_WAITTIME, and no additional dynamic updates + * are sent until the timer expires. + * + * Every update of a routing entry forces an entry's timer to be reset. + * After EXPIRE_TIME without updates, the entry is marked invalid, + * but held onto until GARBAGE_TIME so that others may + * see it "be deleted". + */ +#define TIMER_RATE 30 /* alarm clocks every 30 seconds */ + +#define SUPPLY_INTERVAL 30 /* time to supply tables */ +#define MIN_WAITTIME 2 /* min. interval to broadcast changes */ +#define MAX_WAITTIME 5 /* max. time to delay changes */ + +#define EXPIRE_TIME 180 /* time to mark entry invalid */ +#define GARBAGE_TIME 240 /* time to garbage collect */ + +#endif /* protocols/routed.h */ diff --git a/include/protocols/rwhod.h b/include/protocols/rwhod.h new file mode 100644 index 0000000..446d6f9 --- /dev/null +++ b/include/protocols/rwhod.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rwhod.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_RWHOD_H +#define _PROTOCOLS_RWHOD_H 1 + +#include + +/* + * rwho protocol packet format. + */ +struct outmp { + char out_line[8]; /* tty name */ + char out_name[8]; /* user id */ + int32_t out_time; /* time on */ +}; + +struct whod { + char wd_vers; /* protocol version # */ + char wd_type; /* packet type, see below */ + char wd_pad[2]; + int wd_sendtime; /* time stamp by sender */ + int wd_recvtime; /* time stamp applied by receiver */ + char wd_hostname[32]; /* hosts's name */ + int wd_loadav[3]; /* load average as in uptime */ + int wd_boottime; /* time system booted */ + struct whoent { + struct outmp we_utmp; /* active tty info */ + int we_idle; /* tty idle time */ + } wd_we[1024 / sizeof (struct whoent)]; +}; + +#define WHODVERSION 1 +#define WHODTYPE_STATUS 1 /* host status */ + +/* We used to define _PATH_RWHODIR here but it's now in . */ +#include + +#endif /* protocols/rwhod.h */ diff --git a/include/protocols/talkd.h b/include/protocols/talkd.h new file mode 100644 index 0000000..a8f33b1 --- /dev/null +++ b/include/protocols/talkd.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)talkd.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_TALKD_H +#define _PROTOCOLS_TALKD_H 1 + +/* + * This describes the protocol used by the talk server and clients. + * + * The talk server acts a repository of invitations, responding to + * requests by clients wishing to rendezvous for the purpose of + * holding a conversation. In normal operation, a client, the caller, + * initiates a rendezvous by sending a CTL_MSG to the server of + * type LOOK_UP. This causes the server to search its invitation + * tables to check if an invitation currently exists for the caller + * (to speak to the callee specified in the message). If the lookup + * fails, the caller then sends an ANNOUNCE message causing the server + * to broadcast an announcement on the callee's login ports requesting + * contact. When the callee responds, the local server uses the + * recorded invitation to respond with the appropriate rendezvous + * address and the caller and callee client programs establish a + * stream connection through which the conversation takes place. + */ + +#include +#include + +/* + * Client->server request message format. + */ +typedef struct { + u_char vers; /* protocol version */ + u_char type; /* request type, see below */ + u_char answer; /* not used */ + u_char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* old (4.3) style */ + struct osockaddr ctl_addr; /* old (4.3) style */ + int32_t pid; /* caller's process id */ +#define NAME_SIZE 12 + char l_name[NAME_SIZE];/* caller's name */ + char r_name[NAME_SIZE];/* callee's name */ +#define TTY_SIZE 16 + char r_tty[TTY_SIZE];/* callee's tty name */ +} CTL_MSG; + +/* + * Server->client response message format. + */ +typedef struct { + u_char vers; /* protocol version */ + u_char type; /* type of request message, see below */ + u_char answer; /* response to request message, see below */ + u_char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* address for establishing conversation */ +} CTL_RESPONSE; + +#define TALK_VERSION 1 /* protocol version */ + +/* message type values */ +#define LEAVE_INVITE 0 /* leave invitation with server */ +#define LOOK_UP 1 /* check for invitation by callee */ +#define DELETE 2 /* delete invitation by caller */ +#define ANNOUNCE 3 /* announce invitation by caller */ + +/* answer values */ +#define SUCCESS 0 /* operation completed properly */ +#define NOT_HERE 1 /* callee not logged in */ +#define FAILED 2 /* operation failed for unexplained reason */ +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */ +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */ +#define UNKNOWN_REQUEST 5 /* request has invalid type value */ +#define BADVERSION 6 /* request has invalid protocol version */ +#define BADADDR 7 /* request has invalid addr value */ +#define BADCTLADDR 8 /* request has invalid ctl_addr value */ + +/* + * Operational parameters. + */ +#define MAX_LIFE 60 /* max time daemon saves invitations */ +/* RING_WAIT should be 10's of seconds less than MAX_LIFE */ +#define RING_WAIT 30 /* time to wait before resending invitation */ + +#endif /* protocols/talkd.h */ diff --git a/include/protocols/timed.h b/include/protocols/timed.h new file mode 100644 index 0000000..4345bed --- /dev/null +++ b/include/protocols/timed.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)timed.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_TIMED_H +#define _PROTOCOLS_TIMED_H 1 + +#include + +/* + * Time Synchronization Protocol + */ + +#define TSPVERSION 1 +#define ANYADDR NULL + +struct tsp { + u_char tsp_type; + u_char tsp_vers; + u_short tsp_seq; + union { + struct timeval tspu_time; + char tspu_hopcnt; + } tsp_u; + char tsp_name[MAXHOSTNAMELEN]; +}; + +#define tsp_time tsp_u.tspu_time +#define tsp_hopcnt tsp_u.tspu_hopcnt + +/* + * Command types. + */ +#define TSP_ANY 0 /* match any types */ +#define TSP_ADJTIME 1 /* send adjtime */ +#define TSP_ACK 2 /* generic acknowledgement */ +#define TSP_MASTERREQ 3 /* ask for master's name */ +#define TSP_MASTERACK 4 /* acknowledge master request */ +#define TSP_SETTIME 5 /* send network time */ +#define TSP_MASTERUP 6 /* inform slaves that master is up */ +#define TSP_SLAVEUP 7 /* slave is up but not polled */ +#define TSP_ELECTION 8 /* advance candidature for master */ +#define TSP_ACCEPT 9 /* support candidature of master */ +#define TSP_REFUSE 10 /* reject candidature of master */ +#define TSP_CONFLICT 11 /* two or more masters present */ +#define TSP_RESOLVE 12 /* masters' conflict resolution */ +#define TSP_QUIT 13 /* reject candidature if master is up */ +#define TSP_DATE 14 /* reset the time (date command) */ +#define TSP_DATEREQ 15 /* remote request to reset the time */ +#define TSP_DATEACK 16 /* acknowledge time setting */ +#define TSP_TRACEON 17 /* turn tracing on */ +#define TSP_TRACEOFF 18 /* turn tracing off */ +#define TSP_MSITE 19 /* find out master's site */ +#define TSP_MSITEREQ 20 /* remote master's site request */ +#define TSP_TEST 21 /* for testing election algo */ +#define TSP_SETDATE 22 /* New from date command */ +#define TSP_SETDATEREQ 23 /* New remote for above */ +#define TSP_LOOP 24 /* loop detection packet */ + +#define TSPTYPENUMBER 25 + +#ifdef TSPTYPES +char *tsptype[TSPTYPENUMBER] = + { "ANY", "ADJTIME", "ACK", "MASTERREQ", "MASTERACK", "SETTIME", "MASTERUP", + "SLAVEUP", "ELECTION", "ACCEPT", "REFUSE", "CONFLICT", "RESOLVE", "QUIT", + "DATE", "DATEREQ", "DATEACK", "TRACEON", "TRACEOFF", "MSITE", "MSITEREQ", + "TEST", "SETDATE", "SETDATEREQ", "LOOP" }; +#endif + +#endif /* protocols/timed.h */ diff --git a/include/pty.h b/include/pty.h new file mode 100644 index 0000000..2d4b5e2 --- /dev/null +++ b/include/pty.h @@ -0,0 +1,44 @@ +/* Functions for pseudo TTY handling. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTY_H +#define _PTY_H 1 + +#include + +#include +#include + + +__BEGIN_DECLS + +/* Create pseudo tty master slave pair with NAME and set terminal + attributes according to TERMP and WINP and return handles for both + ends in AMASTER and ASLAVE. */ +extern int openpty (int *__amaster, int *__aslave, char *__name, + struct termios *__termp, struct winsize *__winp) __THROW; + +/* Create child process and establish the slave pseudo terminal as the + child's controlling terminal. */ +extern int forkpty (int *__amaster, char *__name, + struct termios *__termp, struct winsize *__winp) __THROW; + +__END_DECLS + +#endif /* pty.h */ diff --git a/include/pwd.h b/include/pwd.h new file mode 100644 index 0000000..e874133 --- /dev/null +++ b/include/pwd.h @@ -0,0 +1,186 @@ +/* Copyright (C) 1991,1992,1995-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 9.2.2 User Database Access + */ + +#ifndef _PWD_H +#define _PWD_H 1 + +#include + +__BEGIN_DECLS + +#include + +#define __need_size_t +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif + +/* The passwd structure. */ +struct passwd +{ + char *pw_name; /* Username. */ + char *pw_passwd; /* Password. */ + __uid_t pw_uid; /* User ID. */ + __gid_t pw_gid; /* Group ID. */ + char *pw_gecos; /* Real name. */ + char *pw_dir; /* Home directory. */ + char *pw_shell; /* Shell program. */ +}; + + +#if defined __USE_SVID || defined __USE_GNU +# define __need_FILE +# include +#endif + + +#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN_EXTENDED +/* Rewind the password-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setpwent (void); + +/* Close the password-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endpwent (void); + +/* Read an entry from the password-file stream, opening it if necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwent (void); +#endif + +#ifdef __USE_SVID +/* Read an entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct passwd *fgetpwent (FILE *__stream); + +/* Write the given entry onto the given stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putpwent (__const struct passwd *__restrict __p, + FILE *__restrict __f); +#endif + +/* Search for an entry with a matching user ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwuid (__uid_t __uid); + +/* Search for an entry with a matching username. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwnam (__const char *__name); + +#if defined __USE_POSIX || defined __USE_MISC + +# ifdef __USE_MISC +/* Reasonable value for the buffer sized used in the reentrant + functions below. But better use `sysconf'. */ +# define NSS_BUFLEN_PASSWD 1024 +# endif + +/* Reentrant versions of some of the functions above. + + PLEASE NOTE: the `getpwent_r' function is not (yet) standardized. + The interface may change in later versions of this library. But + the interface is designed following the principals used for the + other reentrant functions so the chances are good this is what the + POSIX people would choose. */ + +# if defined __USE_SVID || defined __USE_MISC +/* This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getpwent_r (struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +# endif + +extern int getpwuid_r (__uid_t __uid, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); + +extern int getpwnam_r (__const char *__restrict __name, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); + + +# ifdef __USE_SVID +/* Read an entry from STREAM. This function is not standardized and + probably never will. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetpwent_r (FILE *__restrict __stream, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +# endif + +#endif /* POSIX or reentrant */ + +#ifdef __USE_GNU +/* Re-construct the password-file line for the given uid + in the given buffer. This knows the format that the caller + will expect, but this need not be the format of the password file. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getpw (__uid_t __uid, char *__buffer); +#endif + +__END_DECLS + +#endif /* pwd.h */ diff --git a/include/regex.h b/include/regex.h new file mode 100644 index 0000000..5bd3088 --- /dev/null +++ b/include/regex.h @@ -0,0 +1,565 @@ +/* Definitions for data structures and routines for the regular + expression library. + Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +#include + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* POSIX says that must be included (by the caller) before + . */ + +#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS +/* VMS doesn't have `size_t' in , even though POSIX says it + should be there. */ +# include +#endif + +/* The following two types have to be signed and unsigned integer type + wide enough to hold a value of a pointer. For most ANSI compilers + ptrdiff_t and size_t should be likely OK. Still size of these two + types is 2 for Microsoft C. Ugh... */ +typedef long int s_reg_t; +typedef unsigned long int active_reg_t; + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned long int reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \ matches . + If not set, then \ is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* If this bit is set, succeed as soon as we match the whole pattern, + without further backtracking. */ +#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) + +/* If this bit is set, do not process the GNU regex operators. + If not set, then the GNU regex operators are recognized. */ +#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) + +/* If this bit is set, turn on internal regex debugging. + If not set, and debugging was on, turn it off. + This only works if regex.c is compiled -DDEBUG. + We define this bit always, so that all that's needed to turn on + debugging is to recompile regex.c; the calling code can always have + this bit set, and it won't affect anything in the normal case. */ +#define RE_DEBUG (RE_NO_GNU_OPS << 1) + +/* If this bit is set, a syntactically invalid interval is treated as + a string of ordinary characters. For example, the ERE 'a{1' is + treated as 'a\{1'. */ +#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) + +/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only + for ^, because it is difficult to scan the regex backwards to find + whether ^ should be special. */ +#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) + +/* If this bit is set, then \{ cannot be first in an bre or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) + +/* If this bit is set, then no_sub will be set to 1 during + re_compile_pattern. */ +#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GNU_AWK \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ + & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INTERVALS | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ + | RE_INVALID_INTERVAL_ORD) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is + removed and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +# undef RE_DUP_MAX +#endif +/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ +#define RE_DUP_MAX (0x7fff) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + +/* Use PMATCH[0] to delimit the start and end of the search in the + buffer. */ +#define REG_STARTEND (1 << 2) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ +#ifdef _XOPEN_SOURCE + REG_ENOSYS = -1, /* This will never happen for this implementation. */ +#endif + + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Invalid collating element. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define RE_TRANSLATE_TYPE unsigned char * +#endif + +struct re_pattern_buffer +{ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are sometimes used as + array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long int allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long int used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses the + fastmap, if there is one, to skip over impossible starting points + for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation is + applied to a pattern when it is compiled and to a string when it + is matched. */ + RE_TRANSLATE_TYPE translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see whether or + not we should use the fastmap, so we don't set this absolutely + perfectly; see `re_compile_fastmap' (the `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the beginning + of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +# define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern (const char *__pattern, size_t __length, + struct re_pattern_buffer *__buffer); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search (struct re_pattern_buffer *__buffer, const char *__string, + int __length, int __start, int __range, + struct re_registers *__regs); + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 (struct re_pattern_buffer *__buffer, + const char *__string1, int __length1, + const char *__string2, int __length2, int __start, + int __range, struct re_registers *__regs, int __stop); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match (struct re_pattern_buffer *__buffer, const char *__string, + int __length, int __start, struct re_registers *__regs); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 (struct re_pattern_buffer *__buffer, + const char *__string1, int __length1, + const char *__string2, int __length2, int __start, + struct re_registers *__regs, int __stop); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers (struct re_pattern_buffer *__buffer, + struct re_registers *__regs, + unsigned int __num_regs, + regoff_t *__starts, regoff_t *__ends); + +#if defined _REGEX_RE_COMP || defined _LIBC +# ifndef _CRAY +/* 4.2 bsd compatibility. */ +extern char *re_comp (const char *); +extern int re_exec (const char *); +# endif +#endif + +/* GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". */ +#ifndef __restrict +# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) +# if defined restrict || 199901L <= __STDC_VERSION__ +# define __restrict restrict +# else +# define __restrict +# endif +# endif +#endif +/* gcc 3.1 and up support the [restrict] syntax. */ +#ifndef __restrict_arr +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define __restrict_arr __restrict +# else +# define __restrict_arr +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp (regex_t *__restrict __preg, + const char *__restrict __pattern, + int __cflags); + +extern int regexec (const regex_t *__restrict __preg, + const char *__restrict __string, size_t __nmatch, + regmatch_t __pmatch[__restrict_arr], + int __eflags); + +extern size_t regerror (int __errcode, const regex_t *__restrict __preg, + char *__restrict __errbuf, size_t __errbuf_size); + +extern void regfree (regex_t *__preg); + + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* regex.h */ diff --git a/include/regexp.h b/include/regexp.h new file mode 100644 index 0000000..b7b50b7 --- /dev/null +++ b/include/regexp.h @@ -0,0 +1,222 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEXP_H +#define _REGEXP_H 1 + +/* The contents of this header file was first standardized in X/Open + System Interface and Headers Issue 2, originally coming from SysV. + In issue 4, version 2, it is marked as TO BE WITDRAWN, and it has + been withdrawn in SUSv3. + + This code shouldn't be used in any newly written code. It is + included only for compatibility reasons. Use the POSIX definition + in for portable applications and a reasonable interface. */ + +#include +#include +#include +#include +#include + +/* The implementation provided here emulates the needed functionality + by mapping to the POSIX regular expression matcher. The interface + for the here included function is weird (this really is a harmless + word). + + The user has to provide six macros before this header file can be + included: + + INIT Declarations vor variables which can be used by the + other macros. + + GETC() Return the value of the next character in the regular + expression pattern. Successive calls should return + successive characters. + + PEEKC() Return the value of the next character in the regular + expression pattern. Immediately successive calls to + PEEKC() should return the same character which should + also be the next character returned by GETC(). + + UNGETC(c) Cause `c' to be returned by the next call to GETC() and + PEEKC(). + + RETURN(ptr) Used for normal exit of the `compile' function. `ptr' + is a pointer to the character after the last character of + the compiled regular expression. + + ERROR(val) Used for abnormal return from `compile'. `val' is the + error number. The error codes are: + 11 Range endpoint too large. + 16 Bad number. + 25 \digit out of range. + 36 Illegal or missing delimiter. + 41 No remembered search string. + 42 \( \) imbalance. + 43 Too many \(. + 44 More tan two numbers given in \{ \}. + 45 } expected after \. + 46 First number exceeds second in \{ \}. + 49 [ ] imbalance. + 50 Regular expression overflow. + + */ + +__BEGIN_DECLS + +/* Interface variables. They contain the results of the successful + calls to `setp' and `advance'. */ +extern char *loc1; +extern char *loc2; + +/* The use of this variable in the `advance' function is not + supported. */ +extern char *locs; + + +#ifndef __DO_NOT_DEFINE_COMPILE +/* Get and compile the user supplied pattern up to end of line or + string or until EOF is seen, whatever happens first. The result is + placed in the buffer starting at EXPBUF and delimited by ENDBUF. + + This function cannot be defined in the libc itself since it depends + on the macros. */ +char * +compile (char *__restrict instring, char *__restrict expbuf, + __const char *__restrict endbuf, int eof) +{ + char *__input_buffer = NULL; + size_t __input_size = 0; + size_t __current_size = 0; + int __ch; + int __error; + INIT + + /* Align the expression buffer according to the needs for an object + of type `regex_t'. Then check for minimum size of the buffer for + the compiled regular expression. */ + regex_t *__expr_ptr; +# if defined __GNUC__ && __GNUC__ >= 2 + const size_t __req = __alignof__ (regex_t *); +# else + /* How shall we find out? We simply guess it and can change it is + this really proofs to be wrong. */ + const size_t __req = 8; +# endif + expbuf += __req; + expbuf -= (expbuf - ((char *) 0)) % __req; + if (endbuf < expbuf + sizeof (regex_t)) + { + ERROR (50); + } + __expr_ptr = (regex_t *) expbuf; + /* The remaining space in the buffer can be used for the compiled + pattern. */ + __expr_ptr->buffer = expbuf + sizeof (regex_t); + __expr_ptr->allocated = endbuf - (char *) __expr_ptr->buffer; + + while ((__ch = (GETC ())) != eof) + { + if (__ch == '\0' || __ch == '\n') + { + UNGETC (__ch); + break; + } + + if (__current_size + 1 >= __input_size) + { + size_t __new_size = __input_size ? 2 * __input_size : 128; + char *__new_room = (char *) alloca (__new_size); + /* See whether we can use the old buffer. */ + if (__new_room + __new_size == __input_buffer) + { + __input_size += __new_size; + __input_buffer = (char *) memcpy (__new_room, __input_buffer, + __current_size); + } + else if (__input_buffer + __input_size == __new_room) + __input_size += __new_size; + else + { + __input_size = __new_size; + __input_buffer = (char *) memcpy (__new_room, __input_buffer, + __current_size); + } + } + __input_buffer[__current_size++] = __ch; + } + __input_buffer[__current_size++] = '\0'; + + /* Now compile the pattern. */ + __error = regcomp (__expr_ptr, __input_buffer, REG_NEWLINE); + if (__error != 0) + /* Oh well, we have to translate POSIX error codes. */ + switch (__error) + { + case REG_BADPAT: + case REG_ECOLLATE: + case REG_ECTYPE: + case REG_EESCAPE: + case REG_BADRPT: + case REG_EEND: + case REG_ERPAREN: + default: + /* There is no matching error code. */ + RETURN (36); + case REG_ESUBREG: + RETURN (25); + case REG_EBRACK: + RETURN (49); + case REG_EPAREN: + RETURN (42); + case REG_EBRACE: + RETURN (44); + case REG_BADBR: + RETURN (46); + case REG_ERANGE: + RETURN (11); + case REG_ESPACE: + case REG_ESIZE: + ERROR (50); + } + + /* Everything is ok. */ + RETURN ((char *) (__expr_ptr->buffer + __expr_ptr->used)); +} +#endif + + +/* Find the next match in STRING. The compiled regular expression is + found in the buffer starting at EXPBUF. `loc1' will return the + first character matched and `loc2' points to the next unmatched + character. */ +extern int step (__const char *__restrict __string, + __const char *__restrict __expbuf) __THROW; + +/* Match the beginning of STRING with the compiled regular expression + in EXPBUF. If the match is successful `loc2' will contain the + position of the first unmatched character. */ +extern int advance (__const char *__restrict __string, + __const char *__restrict __expbuf) __THROW; + + +__END_DECLS + +#endif /* regexp.h */ diff --git a/include/resolv.h b/include/resolv.h new file mode 100644 index 0000000..3434f5d --- /dev/null +++ b/include/resolv.h @@ -0,0 +1,395 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $BINDId: resolv.h,v 8.31 2000/03/30 20:16:50 vixie Exp $ + */ + +#ifndef _RESOLV_H_ + +/* These headers are needed for types used in the `struct res_state' + declaration. */ +#include +#include + +#ifndef __need_res_state +# define _RESOLV_H_ + +# include +# include +# include +# include +#endif + +#ifndef __res_state_defined +# define __res_state_defined + +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *ns, + const u_char **query, + int *querylen, + u_char *ans, + int anssiz, + int *resplen); + +typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns, + const u_char *query, + int querylen, + u_char *ans, + int anssiz, + int *resplen); + +/* + * Global defines and variables for resolver stub. + */ +# define MAXNS 3 /* max # name servers we'll track */ +# define MAXDFLSRCH 3 /* # default domain levels to try */ +# define MAXDNSRCH 6 /* max # domains in search path */ +# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +# define RES_TIMEOUT 5 /* min. seconds between retries */ +# define MAXRESOLVSORT 10 /* number of net to sort on */ +# define RES_MAXNDOTS 15 /* should reflect bit field size */ +# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +# define RES_DFLRETRY 2 /* Default #/tries. */ +# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + u_long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ +# define nsaddr nsaddr_list[0] /* for backward compatibility */ + u_short id; /* current message id */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + char unused[3]; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + u_int _flags; /* PRIVATE: see below */ + union { + char pad[52]; /* On an i386 this means 512b total. */ + struct { + u_int16_t nscount; +#if 0 + u_int16_t nsmap[MAXNS]; +#else + u_int16_t nstimes[MAXNS]; /* ms. */ +#endif + int nssocks[MAXNS]; + u_int16_t nscount6; + u_int16_t nsinit; + struct sockaddr_in6 *nsaddrs[MAXNS]; +#if 0 +#ifdef _LIBC + unsigned long long int initstamp + __attribute__((packed)); +#else + unsigned int _initstamp[2]; +#endif +#endif + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; +# undef __need_res_state +#endif + +#ifdef _RESOLV_H_ +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#if 0 +#define __RES 19991006 +#else +#define __RES 19960801 +#endif + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +struct res_sym { + int number; /* Identifying number, like T_MX */ + char * name; /* Its symbolic name, like "MX" */ + char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * Resolver flags (used to be discrete per-module statics ints). + */ +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ + +/* res_findzonecut() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ + +/* + * Resolver options (keep these in synch with res_debug.c, please) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +#if 0 +#define RES_USEBSTRING 0x00040000 /* IPv6 reverse lookup with byte + strings */ +#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6 + reverse lookup */ + +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) +#else +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) +#endif + +/* + * Resolver "pfcode" values. Used by dig. + */ +#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 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +#if 0 +__BEGIN_DECLS +extern struct __res_state *__res_state(void) __attribute__ ((__const__)); +__END_DECLS +#define _res (*__res_state()) +#else +extern struct __res_state _res; +#endif + +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send + +__BEGIN_DECLS +void fp_nquery (const u_char *, int, FILE *) __THROW; +void fp_query (const u_char *, FILE *) __THROW; +const char * hostalias (const char *) __THROW; +void p_query (const u_char *) __THROW; +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close (void) __THROW; +#endif +int res_init (void) __THROW; +int res_isourserver (const struct sockaddr_in *) __THROW; +int res_mkquery (int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int) __THROW; +int res_query (const char *, int, int, u_char *, int) __THROW; +int res_querydomain (const char *, const char *, int, int, + u_char *, int) __THROW; +int res_search (const char *, int, int, u_char *, int) __THROW; +int res_send (const u_char *, int, u_char *, int) __THROW; +__END_DECLS + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_npquery __res_npquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +__BEGIN_DECLS +int res_hnok (const char *) __THROW; +int res_ownok (const char *) __THROW; +int res_mailok (const char *) __THROW; +int res_dnok (const char *) __THROW; +int sym_ston (const struct res_sym *, const char *, int *) __THROW; +const char * sym_ntos (const struct res_sym *, int, int *) __THROW; +const char * sym_ntop (const struct res_sym *, int, int *) __THROW; +int b64_ntop (u_char const *, size_t, char *, size_t) __THROW; +int b64_pton (char const *, u_char *, size_t) __THROW; +int loc_aton (const char *ascii, u_char *binary) __THROW; +const char * loc_ntoa (const u_char *binary, char *ascii) __THROW; +int dn_skipname (const u_char *, const u_char *) __THROW; +void putlong (u_int32_t, u_char *) __THROW; +void putshort (u_int16_t, u_char *) __THROW; +const char * p_class (int) __THROW; +const char * p_time (u_int32_t) __THROW; +const char * p_type (int) __THROW; +const char * p_rcode (int) __THROW; +const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *) + __THROW; +const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW; +const u_char * p_fqnname (const u_char *cp, const u_char *msg, + int, char *, int) __THROW; +const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW; +const char * p_option (u_long option) __THROW; +char * p_secstodate (u_long) __THROW; +int dn_count_labels (const char *) __THROW; +int dn_comp (const char *, u_char *, int, u_char **, u_char **) + __THROW; +int dn_expand (const u_char *, const u_char *, const u_char *, + char *, int) __THROW; +u_int res_randomid (void) __THROW; +int res_nameinquery (const char *, int, int, + const u_char *, const u_char *) __THROW; +int res_queriesmatch (const u_char *, const u_char *, + const u_char *, const u_char *) __THROW; +const char * p_section (int section, int opcode) __THROW; +/* Things involving a resolver context. */ +int res_ninit (res_state) __THROW; +int res_nisourserver (const res_state, + const struct sockaddr_in *) __THROW; +void fp_resstat (const res_state, FILE *) __THROW; +void res_npquery (const res_state, const u_char *, int, FILE *) + __THROW; +const char * res_hostalias (const res_state, const char *, char *, size_t) + __THROW; +int res_nquery (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nsearch (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nquerydomain (res_state, const char *, const char *, int, + int, u_char *, int) __THROW; +int res_nmkquery (res_state, int, const char *, int, int, + const u_char *, int, const u_char *, u_char *, + int) __THROW; +int res_nsend (res_state, const u_char *, int, u_char *, int) + __THROW; +void res_nclose (res_state) __THROW; +__END_DECLS +#endif + +#endif /* !_RESOLV_H_ */ diff --git a/include/rpc/auth.h b/include/rpc/auth.h new file mode 100644 index 0000000..17eb59f --- /dev/null +++ b/include/rpc/auth.h @@ -0,0 +1,224 @@ +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + +#ifndef _RPC_AUTH_H + +#define _RPC_AUTH_H 1 +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOUCE +#define _GNU_SOUCE +#endif +#define _(X) X +#endif +#include +#include + +__BEGIN_DECLS + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32_t high; + u_int32_t low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block (XDR *__xdrs, des_block *__blkp) __THROW; + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct AUTH AUTH; +struct AUTH { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf) (AUTH *); + int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */ + int (*ah_validate) (AUTH *, struct opaque_auth *); + /* validate verifier */ + int (*ah_refresh) (AUTH *); /* refresh credentials */ + void (*ah_destroy) (AUTH *); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +}; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create (char *__machname, __uid_t __uid, __gid_t __gid, + int __len, __gid_t *__aup_gids); +extern AUTH *authunix_create_default (void); +extern AUTH *authnone_create (void) __THROW; +extern AUTH *authdes_create (const char *__servername, u_int __window, + struct sockaddr *__syncaddr, des_block *__ckey) + __THROW; +extern AUTH *authdes_pk_create (const char *, netobj *, u_int, + struct sockaddr *, des_block *) __THROW; + + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_SYS 1 /* unix style (uid, gids) */ +#define AUTH_UNIX AUTH_SYS +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ +#define AUTH_DH AUTH_DES /* Diffie-Hellman (this is DES) */ +#define AUTH_KERB 4 /* kerberos style */ + +/* + * Netname manipulating functions + * + */ +extern int getnetname (char *) __THROW; +extern int host2netname (char *, __const char *, __const char *) __THROW; +extern int user2netname (char *, __const uid_t, __const char *) __THROW; +extern int netname2user (__const char *, uid_t *, gid_t *, int *, gid_t *) + __THROW; +extern int netname2host (__const char *, char *, __const int) __THROW; + +/* + * + * These routines interface to the keyserv daemon + * + */ +extern int key_decryptsession (char *, des_block *); +extern int key_decryptsession_pk (char *, netobj *, des_block *); +extern int key_encryptsession (char *, des_block *); +extern int key_encryptsession_pk (char *, netobj *, des_block *); +extern int key_gendes (des_block *); +extern int key_setsecret (char *); +extern int key_secretkey_is_set (void); +extern int key_get_conv (char *, des_block *); + +/* + * XDR an opaque authentication struct. + */ +extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *) __THROW; + +__END_DECLS + +#endif /* rpc/auth.h */ diff --git a/include/rpc/auth_des.h b/include/rpc/auth_des.h new file mode 100644 index 0000000..12ada84 --- /dev/null +++ b/include/rpc/auth_des.h @@ -0,0 +1,112 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _RPC_AUTH_DES_H +#define _RPC_AUTH_DES_H 1 + +#include +#include + +__BEGIN_DECLS + +/* There are two kinds of "names": fullnames and nicknames */ +enum authdes_namekind + { + ADN_FULLNAME, + ADN_NICKNAME + }; + +/* A fullname contains the network name of the client, + a conversation key and the window */ +struct authdes_fullname + { + char *name; /* network name of client, up to MAXNETNAMELEN */ + des_block key; /* conversation key */ + uint32_t window; /* associated window */ + }; + +/* A credential */ +struct authdes_cred + { + enum authdes_namekind adc_namekind; + struct authdes_fullname adc_fullname; + uint32_t adc_nickname; + }; + +/* A timeval replacement for !32bit platforms */ +struct rpc_timeval + { + uint32_t tv_sec; /* Seconds. */ + uint32_t tv_usec; /* Microseconds. */ + }; + +/* A des authentication verifier */ +struct authdes_verf + { + union + { + struct rpc_timeval adv_ctime; /* clear time */ + des_block adv_xtime; /* crypt time */ + } + adv_time_u; + uint32_t adv_int_u; + }; + +/* des authentication verifier: client variety + + adv_timestamp is the current time. + adv_winverf is the credential window + 1. + Both are encrypted using the conversation key. */ +#define adv_timestamp adv_time_u.adv_ctime +#define adv_xtimestamp adv_time_u.adv_xtime +#define adv_winverf adv_int_u + +/* des authentication verifier: server variety + + adv_timeverf is the client's timestamp + client's window + adv_nickname is the server's nickname for the client. + adv_timeverf is encrypted using the conversation key. */ +#define adv_timeverf adv_time_u.adv_ctime +#define adv_xtimeverf adv_time_u.adv_xtime +#define adv_nickname adv_int_u + +/* Map a des credential into a unix cred. */ +extern int authdes_getucred (__const struct authdes_cred * __adc, + uid_t * __uid, gid_t * __gid, + short *__grouplen, gid_t * __groups) __THROW; + +/* Get the public key for NAME and place it in KEY. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY should + have HEXKEYBYTES + 1 bytes long to fit all characters from the key. */ +extern int getpublickey (__const char *__name, char *__key) __THROW; + +/* Get the secret key for NAME and place it in KEY. PASSWD is used to + decrypt the encrypted key stored in the database. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY + should have HEXKEYBYTES + 1 bytes long to fit all characters from + the key. */ +extern int getsecretkey (__const char *__name, char *__key, + __const char *__passwd) __THROW; + +extern int rtime (struct sockaddr_in *__addrp, struct rpc_timeval *__timep, + struct rpc_timeval *__timeout) __THROW; + +__END_DECLS + + +#endif /* rpc/auth_des.h */ diff --git a/include/rpc/auth_unix.h b/include/rpc/auth_unix.h new file mode 100644 index 0000000..424661d --- /dev/null +++ b/include/rpc/auth_unix.h @@ -0,0 +1,90 @@ +/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)auth_unix.h 1.5 86/07/16 SMI */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H 1 + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms + { + u_long aup_time; + char *aup_machname; + __uid_t aup_uid; + __gid_t aup_gid; + u_int aup_len; + __gid_t *aup_gids; + }; + +extern bool_t xdr_authunix_parms (XDR *__xdrs, struct authunix_parms *__p) + __THROW; + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf + { + struct opaque_auth new_cred; + }; + +__END_DECLS + +#endif /* rpc/auth_unix.h */ diff --git a/include/rpc/clnt.h b/include/rpc/clnt.h new file mode 100644 index 0000000..cf271c5 --- /dev/null +++ b/include/rpc/clnt.h @@ -0,0 +1,421 @@ +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_CLNT_H +#define _RPC_CLNT_H 1 + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + RPC_NOBROADCAST = 21, /* Broadcasting not supported */ + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unknown protocol */ + RPC_UNKNOWNADDR = 19, /* Remote address unknown */ + + /* + * rpcbind errors + */ + RPC_RPCBFAILURE=14, /* portmapper failed in its call */ +#define RPC_PMAPFAILURE RPC_RPCBFAILURE + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + RPC_N2AXLATEFAILURE = 22, /* Name to addr translation failed */ + /* + * unspecified error + */ + RPC_FAILED=16, + RPC_INTR=18, + RPC_TLIERROR=20, + RPC_UDERROR=23, + /* + * asynchronous errors + */ + RPC_INPROGRESS = 24, + RPC_STALERACHANDLE = 25 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* related system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct CLIENT CLIENT; +struct CLIENT { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call) (CLIENT *, u_long, xdrproc_t, caddr_t, xdrproc_t, + caddr_t, struct timeval); + /* call remote procedure */ + void (*cl_abort) (void); /* abort a call */ + void (*cl_geterr) (CLIENT *, struct rpc_err *); + /* get specific error code */ + bool_t (*cl_freeres) (CLIENT *, xdrproc_t, caddr_t); + /* frees results */ + void (*cl_destroy) (CLIENT *); /* destroy this structure */ + bool_t (*cl_control) (CLIENT *, int, char *); + /* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +}; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to all transports + * + * Note: options marked XXX are no-ops in this implementation of RPC. + * The are present in TI-RPC but can't be implemented here since they + * depend on the presence of STREAMS/TLI, which we don't have. + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +#define CLGET_FD 6 /* get connections file descriptor */ +#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */ +#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */ +#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy*/ +#define CLGET_XID 10 /* Get xid */ +#define CLSET_XID 11 /* Set xid */ +#define CLGET_VERS 12 /* Get version number */ +#define CLSET_VERS 13 /* Set version number */ +#define CLGET_PROG 14 /* Get program number */ +#define CLSET_PROG 15 /* Set program number */ +#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */ +#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */ +#define CLSET_POP_TIMOD 18 /* pop timod XXX */ +/* + * Connectionless only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessible on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create (__const u_long __prog, __const u_long __vers) + __THROW; + + +/* + * Generic client creation routine. Supported protocols are "udp", "tcp" and + * "unix" + * CLIENT * + * clnt_create(host, prog, vers, prot) + * char *host; -- hostname + * u_long prog; -- program number + * u_ong vers; -- version number + * char *prot; -- protocol + */ +extern CLIENT *clnt_create (__const char *__host, __const u_long __prog, + __const u_long __vers, __const char *__prot) + __THROW; + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog, + u_long __version, int *__sockp, u_int __sendsz, + u_int __recvsz) __THROW; + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program, + u_long __version, struct timeval __wait_resend, + int *__sockp) __THROW; +extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr, + u_long __program, u_long __version, + struct timeval __wait_resend, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; + + + + +/* + * AF_UNIX based rpc + * CLIENT * + * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_un *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntunix_create (struct sockaddr_un *__raddr, u_long __program, + u_long __version, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; + + +extern int callrpc (__const char *__host, __const u_long __prognum, + __const u_long __versnum, __const u_long __procnum, + __const xdrproc_t __inproc, __const char *__in, + __const xdrproc_t __outproc, char *__out) __THROW; +extern int _rpc_dtablesize (void) __THROW; + +/* + * Print why creation failed + */ +extern void clnt_pcreateerror (__const char *__msg); /* stderr */ +extern char *clnt_spcreateerror(__const char *__msg) __THROW; /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +extern void clnt_perrno (enum clnt_stat __num); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +extern void clnt_perror (CLIENT *__clnt, __const char *__msg); + /* stderr */ +extern char *clnt_sperror (CLIENT *__clnt, __const char *__msg) __THROW; + /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +extern char *clnt_sperrno (enum clnt_stat __num) __THROW; /* string */ + +/* + * get the port number on the host for the rpc program,version and proto + */ +extern int getrpcport (__const char * __host, u_long __prognum, + u_long __versnum, u_int proto) __THROW; + +/* + * get the local host's IP address without consulting + * name service library functions + */ +extern void get_myaddress (struct sockaddr_in *) __THROW; + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +__END_DECLS + +#endif /* rpc/clnt.h */ diff --git a/include/rpc/des_crypt.h b/include/rpc/des_crypt.h new file mode 100644 index 0000000..6a65887 --- /dev/null +++ b/include/rpc/des_crypt.h @@ -0,0 +1,97 @@ +/* + * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI + * + * des_crypt.h, des library routine interface + * Copyright (C) 1986, Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ifndef __DES_CRYPT_H__ +#define __DES_CRYPT_H__ 1 + +#include + +__BEGIN_DECLS + +#define DES_MAXDATA 8192 /* max bytes encrypted in one call */ +#define DES_DIRMASK (1 << 0) +#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ +#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ + + +#define DES_DEVMASK (1 << 1) +#define DES_HW (0*DES_DEVMASK) /* Use hardware device */ +#define DES_SW (1*DES_DEVMASK) /* Use software device */ + + +#define DESERR_NONE 0 /* succeeded */ +#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ +#define DESERR_HWERROR 2 /* failed, hardware/driver error */ +#define DESERR_BADPARAM 3 /* failed, bad parameter to call */ + +#define DES_FAILED(err) \ + ((err) > DESERR_NOHWDEVICE) + +/* + * cbc_crypt() + * ecb_crypt() + * + * Encrypt (or decrypt) len bytes of a buffer buf. + * The length must be a multiple of eight. + * The key should have odd parity in the low bit of each byte. + * ivec is the input vector, and is updated to the new one (cbc only). + * The mode is created by oring together the appropriate parameters. + * DESERR_NOHWDEVICE is returned if DES_HW was specified but + * there was no hardware to do it on (the data will still be + * encrypted though, in software). + */ + + +/* + * Cipher Block Chaining mode + */ +extern int cbc_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode, char *__ivec) __THROW; + +/* + * Electronic Code Book mode + */ +extern int ecb_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode) __THROW; + +/* + * Set des parity for a key. + * DES parity is odd and in the low bit of each byte + */ +extern void des_setparity (char *__key) __THROW; + +__END_DECLS + +#endif diff --git a/include/rpc/key_prot.h b/include/rpc/key_prot.h new file mode 100644 index 0000000..629e249 --- /dev/null +++ b/include/rpc/key_prot.h @@ -0,0 +1,346 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _KEY_PROT_H_RPCGEN +#define _KEY_PROT_H_RPCGEN + +#include + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" +#endif +/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ +#define PROOT 3 +#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" +#define HEXKEYBYTES 48 +#define KEYSIZE 192 +#define KEYBYTES 24 +#define KEYCHECKSUMSIZE 16 + +enum keystatus { + KEY_SUCCESS = 0, + KEY_NOSECRET = 1, + KEY_UNKNOWN = 2, + KEY_SYSTEMERR = 3, +}; +typedef enum keystatus keystatus; +#ifdef __cplusplus +extern "C" bool_t xdr_keystatus(XDR *, keystatus*); +#elif __STDC__ +extern bool_t xdr_keystatus(XDR *, keystatus*); +#else /* Old Style C */ +bool_t xdr_keystatus(); +#endif /* Old Style C */ + + +typedef char keybuf[HEXKEYBYTES]; +#ifdef __cplusplus +extern "C" bool_t xdr_keybuf(XDR *, keybuf); +#elif __STDC__ +extern bool_t xdr_keybuf(XDR *, keybuf); +#else /* Old Style C */ +bool_t xdr_keybuf(); +#endif /* Old Style C */ + + +typedef char *netnamestr; +#ifdef __cplusplus +extern "C" bool_t xdr_netnamestr(XDR *, netnamestr*); +#elif __STDC__ +extern bool_t xdr_netnamestr(XDR *, netnamestr*); +#else /* Old Style C */ +bool_t xdr_netnamestr(); +#endif /* Old Style C */ + + +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; +typedef struct cryptkeyarg cryptkeyarg; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg(); +#endif /* Old Style C */ + + +struct cryptkeyarg2 { + netnamestr remotename; + netobj remotekey; + des_block deskey; +}; +typedef struct cryptkeyarg2 cryptkeyarg2; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg2(); +#endif /* Old Style C */ + + +struct cryptkeyres { + keystatus status; + union { + des_block deskey; + } cryptkeyres_u; +}; +typedef struct cryptkeyres cryptkeyres; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#elif __STDC__ +extern bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#else /* Old Style C */ +bool_t xdr_cryptkeyres(); +#endif /* Old Style C */ + +#define MAXGIDS 16 + +struct unixcred { + u_int uid; + u_int gid; + struct { + u_int gids_len; + u_int *gids_val; + } gids; +}; +typedef struct unixcred unixcred; +#ifdef __cplusplus +extern "C" bool_t xdr_unixcred(XDR *, unixcred*); +#elif __STDC__ +extern bool_t xdr_unixcred(XDR *, unixcred*); +#else /* Old Style C */ +bool_t xdr_unixcred(); +#endif /* Old Style C */ + + +struct getcredres { + keystatus status; + union { + unixcred cred; + } getcredres_u; +}; +typedef struct getcredres getcredres; +#ifdef __cplusplus +extern "C" bool_t xdr_getcredres(XDR *, getcredres*); +#elif __STDC__ +extern bool_t xdr_getcredres(XDR *, getcredres*); +#else /* Old Style C */ +bool_t xdr_getcredres(); +#endif /* Old Style C */ + + +struct key_netstarg { + keybuf st_priv_key; + keybuf st_pub_key; + netnamestr st_netname; +}; +typedef struct key_netstarg key_netstarg; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#elif __STDC__ +extern bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#else /* Old Style C */ +bool_t xdr_key_netstarg(); +#endif /* Old Style C */ + + +struct key_netstres { + keystatus status; + union { + key_netstarg knet; + } key_netstres_u; +}; +typedef struct key_netstres key_netstres; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstres(XDR *, key_netstres*); +#elif __STDC__ +extern bool_t xdr_key_netstres(XDR *, key_netstres*); +#else /* Old Style C */ +bool_t xdr_key_netstres(); +#endif /* Old Style C */ + + +#ifndef opaque +#define opaque char +#endif + + +#define KEY_PROG ((u_long)100029) +#define KEY_VERS ((u_long)1) + +#ifdef __cplusplus +#define KEY_SET ((u_long)1) +extern "C" keystatus * key_set_1(opaque *, CLIENT *); +extern "C" keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern "C" cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern "C" cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern "C" des_block * key_gen_1(void *, CLIENT *); +extern "C" des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern "C" getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#elif __STDC__ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(opaque *, CLIENT *); +extern keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(void *, CLIENT *); +extern des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#else /* Old Style C */ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(); +extern keystatus * key_set_1_svc(); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(); +extern cryptkeyres * key_encrypt_1_svc(); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(); +extern cryptkeyres * key_decrypt_1_svc(); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(); +extern des_block * key_gen_1_svc(); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(); +extern getcredres * key_getcred_1_svc(); +#endif /* Old Style C */ +#define KEY_VERS2 ((u_long)2) + +#ifdef __cplusplus +extern "C" keystatus * key_set_2(opaque *, CLIENT *); +extern "C" keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern "C" cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" des_block * key_gen_2(void *, CLIENT *); +extern "C" des_block * key_gen_2_svc(void *, struct svc_req *); +extern "C" getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern "C" cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern "C" cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern "C" keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern "C" keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern "C" key_netstres * key_net_get_2(void *, CLIENT *); +extern "C" key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern "C" cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern "C" cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#elif __STDC__ +extern keystatus * key_set_2(opaque *, CLIENT *); +extern keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern des_block * key_gen_2(void *, CLIENT *); +extern des_block * key_gen_2_svc(void *, struct svc_req *); +extern getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(void *, CLIENT *); +extern key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#else /* Old Style C */ +extern keystatus * key_set_2(); +extern keystatus * key_set_2_svc(); +extern cryptkeyres * key_encrypt_2(); +extern cryptkeyres * key_encrypt_2_svc(); +extern cryptkeyres * key_decrypt_2(); +extern cryptkeyres * key_decrypt_2_svc(); +extern des_block * key_gen_2(); +extern des_block * key_gen_2_svc(); +extern getcredres * key_getcred_2(); +extern getcredres * key_getcred_2_svc(); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(); +extern cryptkeyres * key_encrypt_pk_2_svc(); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(); +extern cryptkeyres * key_decrypt_pk_2_svc(); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(); +extern keystatus * key_net_put_2_svc(); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(); +extern key_netstres * key_net_get_2_svc(); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(); +extern cryptkeyres * key_get_conv_2_svc(); +#endif /* Old Style C */ + +#endif /* !_KEY_PROT_H_RPCGEN */ diff --git a/include/rpc/netdb.h b/include/rpc/netdb.h new file mode 100644 index 0000000..8671737 --- /dev/null +++ b/include/rpc/netdb.h @@ -0,0 +1,74 @@ +/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc.h 1.8 87/07/24 SMI */ + +/* Cleaned up for GNU C library roland@gnu.ai.mit.edu: + added multiple inclusion protection and use of . + In GNU this file is #include'd by . */ + +#ifndef _RPC_NETDB_H +#define _RPC_NETDB_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +struct rpcent +{ + char *r_name; /* Name of server for this rpc program. */ + char **r_aliases; /* Alias list. */ + int r_number; /* RPC program number. */ +}; + +extern void setrpcent (int __stayopen) __THROW; +extern void endrpcent (void) __THROW; +extern struct rpcent *getrpcbyname (__const char *__name) __THROW; +extern struct rpcent *getrpcbynumber (int __number) __THROW; +extern struct rpcent *getrpcent (void) __THROW; + +#if defined __USE_MISC && defined __UCLIBC_HAS_REENTRANT_RPC__ +extern int getrpcbyname_r (__const char *__name, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcbynumber_r (int __number, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcent_r (struct rpcent *__result_buf, char *__buffer, + size_t __buflen, struct rpcent **__result) __THROW; +#endif + +__END_DECLS + +#endif /* rpc/netdb.h */ diff --git a/include/rpc/pmap_clnt.h b/include/rpc/pmap_clnt.h new file mode 100644 index 0000000..1b1c452 --- /dev/null +++ b/include/rpc/pmap_clnt.h @@ -0,0 +1,98 @@ +/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_CLNT_H +#define _RPC_PMAP_CLNT_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef bool_t (*resultproc_t) (caddr_t resp, struct sockaddr_in *raddr); + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +extern bool_t pmap_set (__const u_long __program, __const u_long __vers, + int __protocol, u_short __port) __THROW; +extern bool_t pmap_unset (__const u_long __program, __const u_long __vers) + __THROW; +extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW; +extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr, + __const u_long __prog, + __const u_long __vers, + __const u_long __proc, + xdrproc_t __xdrargs, + caddr_t __argsp, xdrproc_t __xdrres, + caddr_t __resp, struct timeval __tout, + u_long *__port_ptr) __THROW; +extern enum clnt_stat clnt_broadcast (__const u_long __prog, + __const u_long __vers, + __const u_long __proc, xdrproc_t __xargs, + caddr_t __argsp, xdrproc_t __xresults, + caddr_t __resultsp, + resultproc_t __eachresult) __THROW; +extern u_short pmap_getport (struct sockaddr_in *__address, + __const u_long __program, + __const u_long __version, u_int __protocol) + __THROW; + +__END_DECLS + +#endif /* rpc/pmap_clnt.h */ diff --git a/include/rpc/pmap_prot.h b/include/rpc/pmap_prot.h new file mode 100644 index 0000000..cd64e36 --- /dev/null +++ b/include/rpc/pmap_prot.h @@ -0,0 +1,108 @@ +/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_PROT_H +#define _RPC_PMAP_PROT_H 1 + +#include + +#include + +__BEGIN_DECLS + +/* The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#define PMAPPORT ((u_short)111) +#define PMAPPROG ((u_long)100000) +#define PMAPVERS ((u_long)2) +#define PMAPVERS_PROTO ((u_long)2) +#define PMAPVERS_ORIG ((u_long)1) +#define PMAPPROC_NULL ((u_long)0) +#define PMAPPROC_SET ((u_long)1) +#define PMAPPROC_UNSET ((u_long)2) +#define PMAPPROC_GETPORT ((u_long)3) +#define PMAPPROC_DUMP ((u_long)4) +#define PMAPPROC_CALLIT ((u_long)5) + +struct pmap { + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +}; + +extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs) __THROW; + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +extern bool_t xdr_pmaplist (XDR *__xdrs, struct pmaplist **__rp) __THROW; + +__END_DECLS + +#endif /* rpc/pmap_prot.h */ diff --git a/include/rpc/pmap_rmt.h b/include/rpc/pmap_rmt.h new file mode 100644 index 0000000..7a38b5f --- /dev/null +++ b/include/rpc/pmap_rmt.h @@ -0,0 +1,68 @@ +/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_RMT_H +#define _RPC_PMAP_RMT_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +struct rmtcallargs { + u_long prog, vers, proc, arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +extern bool_t xdr_rmtcall_args (XDR *__xdrs, struct rmtcallargs *__crp) + __THROW; + +struct rmtcallres { + u_long *port_ptr; + u_long resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +extern bool_t xdr_rmtcallres (XDR *__xdrs, struct rmtcallres *__crp) __THROW; + +__END_DECLS + +#endif /* rpc/pmap_rmt.h */ diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h new file mode 100644 index 0000000..8194ffe --- /dev/null +++ b/include/rpc/rpc.h @@ -0,0 +1,113 @@ +/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_RPC_H +#define _RPC_RPC_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOUCE +#define _GNU_SOUCE +#endif +#define _(X) X +#include +#endif + +#include /* some typedefs */ +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +#include /* protocol for unix style cred */ +#include /* protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION + * OF UNIX BASED ON NFSSRC. These systems will already have the structures + * defined by included in . + */ +/* routines for parsing /etc/rpc */ +#include /* structures and routines to parse /etc/rpc */ + +__BEGIN_DECLS + +/* Global variables, protected for multi-threaded applications. */ +extern fd_set *__rpc_thread_svc_fdset (void) __attribute__ ((__const__)); +#define svc_fdset (*__rpc_thread_svc_fdset ()) + +extern struct rpc_createerr *__rpc_thread_createerr (void) + __attribute__ ((__const__)); +#define get_rpc_createerr() (*__rpc_thread_createerr ()) +/* The people who "engineered" RPC should bee punished for naming the + data structure and the variable the same. We cannot always define the + macro 'rpc_createerr' because this would prevent people from defining + object of type 'struct rpc_createerr'. So we leave it up to the user + to select transparent replacement also of this variable. */ +#ifdef _RPC_MT_VARS +# define rpc_createerr (*__rpc_thread_createerr ()) +#endif + +extern struct pollfd **__rpc_thread_svc_pollfd (void) + __attribute__ ((__const__)); +#define svc_pollfd (*__rpc_thread_svc_pollfd ()) + +extern int *__rpc_thread_svc_max_pollfd (void) __attribute__ ((__const__)); +#define svc_max_pollfd (*__rpc_thread_svc_max_pollfd ()) + +extern bool_t xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar); +extern bool_t xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr); + +__END_DECLS + +#endif /* rpc/rpc.h */ diff --git a/include/rpc/rpc_des.h b/include/rpc/rpc_des.h new file mode 100644 index 0000000..96e5369 --- /dev/null +++ b/include/rpc/rpc_des.h @@ -0,0 +1,72 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Generic DES driver interface + * Keep this file hardware independent! + * Copyright (c) 1986 by Sun Microsystems, Inc. + */ + +#ifndef _DES_H +#define _DES_H + +#include + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +enum desdir + { + ENCRYPT, DECRYPT + }; +enum desmode + { + CBC, ECB + }; + +/* + * parameters to ioctl call + */ +struct desparams + { + u_char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + u_char des_ivec[8]; /* input vector */ + unsigned des_len; /* number of bytes to crypt */ + union + { + u_char UDES_data[DES_QUICKLEN]; + u_char *UDES_buf; + } + UDES; +#define des_data UDES.UDES_data /* direct data here if quick */ +#define des_buf UDES.UDES_buf /* otherwise, pointer to data */ + }; + +#endif diff --git a/include/rpc/rpc_msg.h b/include/rpc/rpc_msg.h new file mode 100644 index 0000000..636d60e --- /dev/null +++ b/include/rpc/rpc_msg.h @@ -0,0 +1,202 @@ +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +#ifndef _RPC_MSG_H +#define _RPC_MSG_H 1 + +#include + +#include +#include + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +__BEGIN_DECLS + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall struct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg (XDR *__xdrs, struct rpc_msg *__cmsg) __THROW; + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr (XDR *__xdrs, struct rpc_msg *__cmsg) __THROW; + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg (XDR *__xdrs, struct rpc_msg *__rmsg) __THROW; + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply (struct rpc_msg *__msg, struct rpc_err *__error) + __THROW; + +__END_DECLS + +#endif /* rpc/rpc_msg.h */ diff --git a/include/rpc/svc.h b/include/rpc/svc.h new file mode 100644 index 0000000..3ffca50 --- /dev/null +++ b/include/rpc/svc.h @@ -0,0 +1,316 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVC_H +#define _RPC_SVC_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct SVCXPRT SVCXPRT; +struct SVCXPRT { + int xp_sock; + u_short xp_port; /* associated port number */ + const struct xp_ops { + bool_t (*xp_recv) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* receive incoming requests */ + enum xprt_stat (*xp_stat) (SVCXPRT *__xprt); + /* get transport status */ + bool_t (*xp_getargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t args_ptr); /* get arguments */ + bool_t (*xp_reply) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* send reply */ + bool_t (*xp_freeargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t args_ptr); + /* free mem allocated for args */ + void (*xp_destroy) (SVCXPRT *__xprt); + /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ + char xp_pad [256]; /* padding, internal use */ +}; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + rpcprog_t rq_prog; /* service program number */ + rpcvers_t rq_vers; /* service protocol version */ + rpcproc_t rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + +#ifndef __DISPATCH_FN_T +#define __DISPATCH_FN_T +typedef void (*__dispatch_fn_t) (struct svc_req*, SVCXPRT*); +#endif + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * rpcprog_t prog; + * rpcvers_t vers; + * void (*dispatch)(struct svc_req*, SVCXPRT*); + * rpcprot_t protocol; like TCP or UDP, zero means do not register + */ +extern bool_t svc_register (SVCXPRT *__xprt, rpcprog_t __prog, + rpcvers_t __vers, __dispatch_fn_t __dispatch, + rpcprot_t __protocol) __THROW; + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * rpcprog_t prog; + * rpcvers_t vers; + */ +extern void svc_unregister (rpcprog_t __prog, rpcvers_t __vers) __THROW; + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register (SVCXPRT *__xprt) __THROW; + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister (SVCXPRT *__xprt) __THROW; + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply (SVCXPRT *xprt, xdrproc_t __xdr_results, + caddr_t __xdr_location) __THROW; + +extern void svcerr_decode (SVCXPRT *__xprt) __THROW; + +extern void svcerr_weakauth (SVCXPRT *__xprt) __THROW; + +extern void svcerr_noproc (SVCXPRT *__xprt) __THROW; + +extern void svcerr_progvers (SVCXPRT *__xprt, rpcvers_t __low_vers, + rpcvers_t __high_vers) __THROW; + +extern void svcerr_auth (SVCXPRT *__xprt, enum auth_stat __why) __THROW; + +extern void svcerr_noprog (SVCXPRT *__xprt) __THROW; + +extern void svcerr_systemerr (SVCXPRT *__xprt) __THROW; + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (coexistent) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ + +extern struct pollfd *svc_pollfd; +extern int svc_max_pollfd; +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void svc_getreq (int __rdfds) __THROW; +extern void svc_getreq_common (const int __fd) __THROW; +extern void svc_getreqset (fd_set *__readfds) __THROW; +extern void svc_getreq_poll (struct pollfd *, const int) __THROW; +extern void svc_exit (void) __THROW; +extern void svc_run (void) __THROW; + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create (void) __THROW; + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create (int __sock) __THROW; +extern SVCXPRT *svcudp_bufcreate (int __sock, u_int __sendsz, u_int __recvsz) + __THROW; + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create (int __sock, u_int __sendsize, u_int __recvsize) + __THROW; + + +/* + * Unix based rpc. + */ +extern SVCXPRT *svcunix_create (int __sock, u_int __sendsize, u_int __recvsize, + char *__path) __THROW; + + +__END_DECLS + +#endif /* rpc/svc.h */ diff --git a/include/rpc/svc_auth.h b/include/rpc/svc_auth.h new file mode 100644 index 0000000..1c1a715 --- /dev/null +++ b/include/rpc/svc_auth.h @@ -0,0 +1,54 @@ +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVC_AUTH_H +#define _RPC_SVC_AUTH_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate (struct svc_req *__rqst, + struct rpc_msg *__msg) __THROW; + +__END_DECLS + +#endif /* rpc/svc_auth.h */ diff --git a/include/rpc/types.h b/include/rpc/types.h new file mode 100644 index 0000000..469576e --- /dev/null +++ b/include/rpc/types.h @@ -0,0 +1,108 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* fixincludes should not add extern "C" to this file */ +/* + * Rpc additions to + */ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOUCE +#define _GNU_SOUCE +#endif +#define _(X) X +#endif +#include + +typedef int bool_t; +typedef int enum_t; +/* This needs to be changed to uint32_t in the future */ +typedef unsigned long rpcprog_t; +typedef unsigned long rpcvers_t; +typedef unsigned long rpcproc_t; +typedef unsigned long rpcprot_t; +typedef unsigned long rpcport_t; + +#define __dontcare__ -1 + +#ifndef FALSE +# define FALSE (0) +#endif + +#ifndef TRUE +# define TRUE (1) +#endif + +#ifndef NULL +# define NULL 0 +#endif + +#include /* For malloc decl. */ +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif + +#ifndef __u_char_defined +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +# define __u_char_defined +#endif +#ifndef __daddr_t_defined +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +# define __daddr_t_defined +#endif + +#include +#include + +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* rpc/types.h */ diff --git a/include/rpc/xdr.h b/include/rpc/xdr.h new file mode 100644 index 0000000..25dd214 --- /dev/null +++ b/include/rpc/xdr.h @@ -0,0 +1,385 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_XDR_H +#define _RPC_XDR_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +# ifndef __FORCE_GLIBC +# define __FORCE_GLIBC +# endif +# define _(X) X +#endif +#include +#include +#include + +/* We need FILE. */ +#include + +__BEGIN_DECLS + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE = 0, + XDR_DECODE = 1, + XDR_FREE = 2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +/* + * This only works if the above is a power of 2. But it's defined to be + * 4 by the appropriate RFCs. So it will work. And it's normally quicker + * than the old routine. + */ +#if 1 +#define RNDUP(x) (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1)) +#else /* this is the old routine */ +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) +#endif + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct XDR XDR; +struct XDR + { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops + { + bool_t (*x_getlong) (XDR *__xdrs, long *__lp); + /* get a long from underlying stream */ + bool_t (*x_putlong) (XDR *__xdrs, __const long *__lp); + /* put a long to " */ + bool_t (*x_getbytes) (XDR *__xdrs, caddr_t __addr, u_int __len); + /* get some bytes from " */ + bool_t (*x_putbytes) (XDR *__xdrs, __const char *__addr, u_int __len); + /* put some bytes to " */ + u_int (*x_getpostn) (__const XDR *__xdrs); + /* returns bytes off from beginning */ + bool_t (*x_setpostn) (XDR *__xdrs, u_int __pos); + /* lets you reposition the stream */ + int32_t *(*x_inline) (XDR *__xdrs, u_int __len); + /* buf quick ptr to buffered data */ + void (*x_destroy) (XDR *__xdrs); + /* free privates of this xdr_stream */ + bool_t (*x_getint32) (XDR *__xdrs, int32_t *__ip); + /* get a int from underlying stream */ + bool_t (*x_putint32) (XDR *__xdrs, __const int32_t *__ip); + /* put a int to " */ + } + *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + u_int x_handy; /* extra private word */ + }; + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t) (XDR *, void *,...); + + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * int32_t *int32p; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) +#define xdr_getint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) + +#define XDR_PUTINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) +#define xdr_putint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) + +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) +#define xdr_destroy(xdrs) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim +{ + int value; + xdrproc_t proc; +}; + +/* + * Inline routines for fast encode/decode of primitive data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ + +#define IXDR_GET_INT32(buf) ((int32_t)ntohl((uint32_t)*(buf)++)) +#define IXDR_PUT_INT32(buf, v) (*(buf)++ = (int32_t)htonl((uint32_t)(v))) +#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) +#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32(buf, (int32_t)(v)) + +/* WARNING: The IXDR_*_LONG defines are removed by Sun for new platforms + * and shouldn't be used any longer. Code which use this defines or longs + * in the RPC code will not work on 64bit Solaris platforms ! + */ +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf)) +#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v))) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + +/* + * These are the "generic" xdr routines. + * None of these can have const applied because it's not possible to + * know whether the call is a read or a write to the passed parameter + * also, the XDR structure is always updated by some of these calls. + */ +extern bool_t xdr_void (void) __THROW; +extern bool_t xdr_short (XDR *__xdrs, short *__sp) __THROW; +extern bool_t xdr_u_short (XDR *__xdrs, u_short *__usp) __THROW; +extern bool_t xdr_int (XDR *__xdrs, int *__ip) __THROW; +extern bool_t xdr_u_int (XDR *__xdrs, u_int *__up) __THROW; +extern bool_t xdr_long (XDR *__xdrs, long *__lp) __THROW; +extern bool_t xdr_u_long (XDR *__xdrs, u_long *__ulp) __THROW; +extern bool_t xdr_hyper (XDR *__xdrs, quad_t *__llp) __THROW; +extern bool_t xdr_u_hyper (XDR *__xdrs, u_quad_t *__ullp) __THROW; +extern bool_t xdr_longlong_t (XDR *__xdrs, quad_t *__llp) __THROW; +extern bool_t xdr_u_longlong_t (XDR *__xdrs, u_quad_t *__ullp) __THROW; +extern bool_t xdr_int8_t (XDR *__xdrs, int8_t *__ip) __THROW; +extern bool_t xdr_uint8_t (XDR *__xdrs, uint8_t *__up) __THROW; +extern bool_t xdr_int16_t (XDR *__xdrs, int16_t *__ip) __THROW; +extern bool_t xdr_uint16_t (XDR *__xdrs, uint16_t *__up) __THROW; +extern bool_t xdr_int32_t (XDR *__xdrs, int32_t *__ip) __THROW; +extern bool_t xdr_uint32_t (XDR *__xdrs, uint32_t *__up) __THROW; +extern bool_t xdr_int64_t (XDR *__xdrs, int64_t *__ip) __THROW; +extern bool_t xdr_uint64_t (XDR *__xdrs, uint64_t *__up) __THROW; +extern bool_t xdr_bool (XDR *__xdrs, bool_t *__bp) __THROW; +extern bool_t xdr_enum (XDR *__xdrs, enum_t *__ep) __THROW; +extern bool_t xdr_array (XDR * _xdrs, caddr_t *__addrp, u_int *__sizep, + u_int __maxsize, u_int __elsize, xdrproc_t __elproc) + __THROW; +extern bool_t xdr_bytes (XDR *__xdrs, char **__cpp, u_int *__sizep, + u_int __maxsize) __THROW; +extern bool_t xdr_opaque (XDR *__xdrs, caddr_t __cp, u_int __cnt) __THROW; +extern bool_t xdr_string (XDR *__xdrs, char **__cpp, u_int __maxsize) __THROW; +extern bool_t xdr_union (XDR *__xdrs, enum_t *__dscmp, char *__unp, + __const struct xdr_discrim *__choices, + xdrproc_t dfault) __THROW; +extern bool_t xdr_char (XDR *__xdrs, char *__cp) __THROW; +extern bool_t xdr_u_char (XDR *__xdrs, u_char *__cp) __THROW; +extern bool_t xdr_vector (XDR *__xdrs, char *__basep, u_int __nelem, + u_int __elemsize, xdrproc_t __xdr_elem) __THROW; +extern bool_t xdr_float (XDR *__xdrs, float *__fp) __THROW; +extern bool_t xdr_double (XDR *__xdrs, double *__dp) __THROW; +extern bool_t xdr_reference (XDR *__xdrs, caddr_t *__xpp, u_int __size, + xdrproc_t __proc) __THROW; +extern bool_t xdr_pointer (XDR *__xdrs, char **__objpp, + u_int __obj_size, xdrproc_t __xdr_obj) __THROW; +extern bool_t xdr_wrapstring (XDR *__xdrs, char **__cpp) __THROW; +extern u_long xdr_sizeof (xdrproc_t, void *) __THROW; + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj +{ + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj (XDR *__xdrs, struct netobj *__np) __THROW; + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ + +/* XDR using memory buffers */ +extern void xdrmem_create (XDR *__xdrs, __const caddr_t __addr, + u_int __size, enum xdr_op __xop) __THROW; + +/* XDR using stdio library */ +extern void xdrstdio_create (XDR *__xdrs, FILE *__file, enum xdr_op __xop) + __THROW; + +/* XDR pseudo records for tcp */ +extern void xdrrec_create (XDR *__xdrs, u_int __sendsize, + u_int __recvsize, caddr_t __tcp_handle, + int (*__readit) (char *, char *, int), + int (*__writeit) (char *, char *, int)) __THROW; + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord (XDR *__xdrs, bool_t __sendnow) __THROW; + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord (XDR *__xdrs) __THROW; + +/* true if no more input */ +extern bool_t xdrrec_eof (XDR *__xdrs) __THROW; + +/* free memory buffers for xdr */ +extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW; + +__END_DECLS + +#endif /* rpc/xdr.h */ diff --git a/include/sched.h b/include/sched.h new file mode 100644 index 0000000..7cfdbf1 --- /dev/null +++ b/include/sched.h @@ -0,0 +1,86 @@ +/* Definitions for POSIX 1003.1b-1993 (aka POSIX.4) scheduling interface. + Copyright (C) 1996,1997,1999,2001-2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SCHED_H +#define _SCHED_H 1 + +#include + +/* Get type definitions. */ +#include + +#define __need_timespec +#include + +/* Get system specific constant and data structure definitions. */ +#include +/* Define the real names for the elements of `struct sched_param'. */ +#define sched_priority __sched_priority + + +__BEGIN_DECLS + +/* Set scheduling parameters for a process. */ +extern int sched_setparam (__pid_t __pid, __const struct sched_param *__param) + __THROW; + +/* Retrieve scheduling parameters for a particular process. */ +extern int sched_getparam (__pid_t __pid, struct sched_param *__param) __THROW; + +/* Set scheduling algorithm and/or parameters for a process. */ +extern int sched_setscheduler (__pid_t __pid, int __policy, + __const struct sched_param *__param) __THROW; + +/* Retrieve scheduling algorithm for a particular purpose. */ +extern int sched_getscheduler (__pid_t __pid) __THROW; + +/* Yield the processor. */ +extern int sched_yield (void) __THROW; + +/* Get maximum priority value for a scheduler. */ +extern int sched_get_priority_max (int __algorithm) __THROW; + +/* Get minimum priority value for a scheduler. */ +extern int sched_get_priority_min (int __algorithm) __THROW; + +/* Get the SCHED_RR interval for the named process. */ +extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW; + + +#ifdef __USE_GNU +/* Access macros for `cpu_set'. */ +#define CPU_SETSIZE __CPU_SETSIZE +#define CPU_SET(cpu, cpusetp) __CPU_SET (cpu, cpusetp) +#define CPU_CLR(cpu, cpusetp) __CPU_CLR (cpu, cpusetp) +#define CPU_ISSET(cpu, cpusetp) __CPU_ISSET (cpu, cpusetp) +#define CPU_ZERO(cpusetp) __CPU_ZERO (cpusetp) + + +/* Set the CPU affinity for a task */ +extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize, + __const cpu_set_t *__cpuset) __THROW; + +/* Get the CPU affinity for a task */ +extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize, + cpu_set_t *__cpuset) __THROW; +#endif + +__END_DECLS + +#endif /* sched.h */ diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h new file mode 100644 index 0000000..49ab758 --- /dev/null +++ b/include/scsi/scsi.h @@ -0,0 +1,226 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * This header file contains public constants and structures used by + * the scsi code for linux. + */ + +#ifndef _SCSI_SCSI_H +#define _SCSI_SCSI_H 1 + +#include + +/* + * SCSI opcodes + */ + +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define READ_TOC 0x43 +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define MOVE_MEDIUM 0xa5 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define WRITE_VERIFY_12 0xae +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea + +/* + * Status codes + */ + +#define GOOD 0x00 +#define CHECK_CONDITION 0x01 +#define CONDITION_GOOD 0x02 +#define BUSY 0x04 +#define INTERMEDIATE_GOOD 0x08 +#define INTERMEDIATE_C_GOOD 0x0a +#define RESERVATION_CONFLICT 0x0c +#define COMMAND_TERMINATED 0x11 +#define QUEUE_FULL 0x14 + +#define STATUS_MASK 0x3e + +/* + * SENSE KEYS + */ + +#define NO_SENSE 0x00 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define MEDIUM_ERROR 0x03 +#define HARDWARE_ERROR 0x04 +#define ILLEGAL_REQUEST 0x05 +#define UNIT_ATTENTION 0x06 +#define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 +#define COPY_ABORTED 0x0a +#define ABORTED_COMMAND 0x0b +#define VOLUME_OVERFLOW 0x0d +#define MISCOMPARE 0x0e + + +/* + * DEVICE TYPES + */ + +#define TYPE_DISK 0x00 +#define TYPE_TAPE 0x01 +#define TYPE_PROCESSOR 0x03 /* HP scanners use this */ +#define TYPE_WORM 0x04 /* Treated as ROM by our system */ +#define TYPE_ROM 0x05 +#define TYPE_SCANNER 0x06 +#define TYPE_MOD 0x07 /* Magneto-optical disk - + * - treated as TYPE_DISK */ +#define TYPE_MEDIUM_CHANGER 0x08 +#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ +#define TYPE_NO_LUN 0x7f + +/* + * standard mode-select header prepended to all mode-select commands + * + * moved here from cdrom.h -- kraxel + */ + +struct ccs_modesel_head + { + unsigned char _r1; /* reserved. */ + unsigned char medium; /* device-specific medium type. */ + unsigned char _r2; /* reserved. */ + unsigned char block_desc_length; /* block descriptor length. */ + unsigned char density; /* device-specific density code. */ + unsigned char number_blocks_hi; /* number of blocks in this block + desc. */ + unsigned char number_blocks_med; + unsigned char number_blocks_lo; + unsigned char _r3; + unsigned char block_length_hi; /* block length for blocks in this + desc. */ + unsigned char block_length_med; + unsigned char block_length_lo; + }; + +/* + * MESSAGE CODES + */ + +#define COMMAND_COMPLETE 0x00 +#define EXTENDED_MESSAGE 0x01 +#define EXTENDED_MODIFY_DATA_POINTER 0x00 +#define EXTENDED_SDTR 0x01 +#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */ +#define EXTENDED_WDTR 0x03 +#define SAVE_POINTERS 0x02 +#define RESTORE_POINTERS 0x03 +#define DISCONNECT 0x04 +#define INITIATOR_ERROR 0x05 +#define ABORT 0x06 +#define MESSAGE_REJECT 0x07 +#define NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define LINKED_CMD_COMPLETE 0x0a +#define LINKED_FLG_CMD_COMPLETE 0x0b +#define BUS_DEVICE_RESET 0x0c + +#define INITIATE_RECOVERY 0x0f /* SCSI-II only */ +#define RELEASE_RECOVERY 0x10 /* SCSI-II only */ + +#define SIMPLE_QUEUE_TAG 0x20 +#define HEAD_OF_QUEUE_TAG 0x21 +#define ORDERED_QUEUE_TAG 0x22 + +/* + * Here are some scsi specific ioctl commands which are sometimes useful. + */ +/* These are a few other constants only used by scsi devices. */ + +#define SCSI_IOCTL_GET_IDLUN 0x5382 + +/* Used to turn on and off tagged queuing for scsi devices. */ + +#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 +#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 + +/* Used to obtain the host number of a device. */ +#define SCSI_IOCTL_PROBE_HOST 0x5385 + +/* Used to get the bus number for a device. */ +#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 + +#endif /* scsi/scsi.h */ diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h new file mode 100644 index 0000000..ba8c84f --- /dev/null +++ b/include/scsi/scsi_ioctl.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SCSI_IOCTL_H +#define _SCSI_IOCTL_H + +/* IOCTLs for SCSI. */ +#define SCSI_IOCTL_SEND_COMMAND 1 /* Send a command to the SCSI host. */ +#define SCSI_IOCTL_TEST_UNIT_READY 2 /* Test if unit is ready. */ +#define SCSI_IOCTL_BENCHMARK_COMMAND 3 +#define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters. */ +#define SCSI_IOCTL_START_UNIT 5 +#define SCSI_IOCTL_STOP_UNIT 6 +#define SCSI_IOCTL_DOORLOCK 0x5380 /* Lock the eject mechanism. */ +#define SCSI_IOCTL_DOORUNLOCK 0x5381 /* Unlock the mechanism. */ + +#endif + + diff --git a/include/scsi/sg.h b/include/scsi/sg.h new file mode 100644 index 0000000..b0dc0ad --- /dev/null +++ b/include/scsi/sg.h @@ -0,0 +1,275 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + History: + Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user + process control of SCSI devices. + Development Sponsored by Killy Corp. NY NY +*/ + +#ifndef _SCSI_SG_H +#define _SCSI_SG_H 1 + +#include + + +/* New interface introduced in the 3.x SG drivers follows */ + +/* Same structure as used by readv() Linux system call. It defines one + scatter-gather element. */ +typedef struct sg_iovec +{ + void * iov_base; /* Starting address */ + size_t iov_len; /* Length in bytes */ +} sg_iovec_t; + + +typedef struct sg_io_hdr +{ + int interface_id; /* [i] 'S' for SCSI generic (required) */ + int dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short int iovec_count; /* [i] 0 implies no scatter gather */ + unsigned int dxfer_len; /* [i] byte count of data transfer */ + void * dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + unsigned char * cmdp; /* [i], [*i] points to command to perform */ + unsigned char * sbp; /* [i], [*o] points to sense_buffer memory */ + unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */ + int pack_id; /* [i->o] unused internally (normally) */ + void * usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status;/* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short int host_status; /* [o] errors from host adapter */ + unsigned short int driver_status;/* [o] errors from software driver */ + int resid; /* [o] dxfer_len - actual_transferred */ + unsigned int duration; /* [o] time taken by cmd (unit: millisec) */ + unsigned int info; /* [o] auxiliary information */ +} sg_io_hdr_t; + + +/* Use negative values to flag difference from original sg_header structure. */ +#define SG_DXFER_NONE -1 /* e.g. a SCSI Test Unit Ready command */ +#define SG_DXFER_TO_DEV -2 /* e.g. a SCSI WRITE command */ +#define SG_DXFER_FROM_DEV -3 /* e.g. a SCSI READ command */ +#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the + additional property than during indirect + IO the user buffer is copied into the + kernel buffers before the transfer */ + + +/* following flag values can be "or"-ed together */ +#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */ +#define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */ + /* the 2nd byte of SCSI command */ +#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */ + /* user space (debug indirect IO) */ + +/* The following 'info' values are "or"-ed together. */ +#define SG_INFO_OK_MASK 0x1 +#define SG_INFO_OK 0x0 /* no sense, host nor driver "noise" */ +#define SG_INFO_CHECK 0x1 /* something abnormal happened */ + +#define SG_INFO_DIRECT_IO_MASK 0x6 +#define SG_INFO_INDIRECT_IO 0x0 /* data xfer via kernel buffers (or no xfer) */ +#define SG_INFO_DIRECT_IO 0x2 /* direct IO requested and performed */ +#define SG_INFO_MIXED_IO 0x4 /* part direct, part indirect IO */ + + +/* Request information about a specific SG device, used by + SG_GET_SCSI_ID ioctl (). */ +struct sg_scsi_id { + /* Host number as in "scsi" where 'n' is one of 0, 1, 2 etc. */ + int host_no; + int channel; + /* SCSI id of target device. */ + int scsi_id; + int lun; + /* TYPE_... defined in . */ + int scsi_type; + /* Host (adapter) maximum commands per lun. */ + short int h_cmd_per_lun; + /* Device (or adapter) maximum queue length. */ + short int d_queue_depth; + /* Unused, set to 0 for now. */ + int unused[2]; +}; + +/* Used by SG_GET_REQUEST_TABLE ioctl(). */ +typedef struct sg_req_info { + char req_state; /* 0 -> not used, 1 -> written, 2 -> ready to read */ + char orphan; /* 0 -> normal request, 1 -> from interruped SG_IO */ + char sg_io_owned; /* 0 -> complete with read(), 1 -> owned by SG_IO */ + char problem; /* 0 -> no problem detected, 1 -> error to report */ + int pack_id; /* pack_id associated with request */ + void * usr_ptr; /* user provided pointer (in new interface) */ + unsigned int duration; /* millisecs elapsed since written (req_state==1) + or request duration (req_state==2) */ + int unused; +} sg_req_info_t; + + +/* IOCTLs: Those ioctls that are relevant to the SG 3.x drivers follow. + [Those that only apply to the SG 2.x drivers are at the end of the file.] + (_GET_s yield result via 'int *' 3rd argument unless otherwise indicated) */ + +#define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */ + +/* Used to configure SCSI command transformation layer for ATAPI devices */ +/* Only supported by the ide-scsi driver */ +#define SG_SET_TRANSFORM 0x2204 /* N.B. 3rd arg is not pointer but value: */ + /* 3rd arg = 0 to disable transform, 1 to enable it */ +#define SG_GET_TRANSFORM 0x2205 + +#define SG_SET_RESERVED_SIZE 0x2275 /* request a new reserved buffer size */ +#define SG_GET_RESERVED_SIZE 0x2272 /* actual size of reserved buffer */ + +/* The following ioctl has a 'sg_scsi_id_t *' object as its 3rd argument. */ +#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus, chan, dev, lun + type */ +/* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */ + +/* Override host setting and always DMA using low memory ( <16MB on i386) */ +#define SG_SET_FORCE_LOW_DMA 0x2279 /* 0-> use adapter setting, 1-> force */ +#define SG_GET_LOW_DMA 0x227a /* 0-> use all ram for dma; 1-> low dma ram */ + +/* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which + tries to fetch a packet with a matching pack_id, waits, or returns EAGAIN. + If pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0 + then pack_id ignored by read() and oldest readable fetched. */ +#define SG_SET_FORCE_PACK_ID 0x227b +#define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */ + +#define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */ + +/* Yields max scatter gather tablesize allowed by current host adapter */ +#define SG_GET_SG_TABLESIZE 0x227F /* 0 implies can't do scatter gather */ + +#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */ + +/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */ +#define SG_SCSI_RESET 0x2284 +/* Associated values that can be given to SG_SCSI_RESET follow */ +#define SG_SCSI_RESET_NOTHING 0 +#define SG_SCSI_RESET_DEVICE 1 +#define SG_SCSI_RESET_BUS 2 +#define SG_SCSI_RESET_HOST 3 + +/* synchronous SCSI command ioctl, (only in version 3 interface) */ +#define SG_IO 0x2285 /* similar effect as write() followed by read() */ + +#define SG_GET_REQUEST_TABLE 0x2286 /* yields table of active requests */ + +/* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */ +#define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */ +#define SG_GET_KEEP_ORPHAN 0x2288 + + +#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */ +/* Largest size (in bytes) a single scatter-gather list element can have. + The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on + i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported + by adapter then this value is the largest data block that can be + read/written by a single scsi command. The user can find the value of + PAGE_SIZE by calling getpagesize() defined in unistd.h . */ + +#define SG_DEFAULT_RETRIES 1 + +/* Defaults, commented if they differ from original sg driver */ +#define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */ +#define SG_DEF_FORCE_PACK_ID 0 +#define SG_DEF_KEEP_ORPHAN 0 +#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */ + +/* maximum outstanding requests, write() yields EDOM if exceeded */ +#define SG_MAX_QUEUE 16 + +#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE /* for backward compatibility */ + +/* Alternate style type names, "..._t" variants preferred */ +typedef struct sg_io_hdr Sg_io_hdr; +typedef struct sg_io_vec Sg_io_vec; +typedef struct sg_scsi_id Sg_scsi_id; +typedef struct sg_req_info Sg_req_info; + + +/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ +/* The older SG interface based on the 'sg_header' structure follows. */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ + +#define SG_MAX_SENSE 16 /* this only applies to the sg_header interface */ + +struct sg_header + { + /* Length of incoming packet (including header). */ + int pack_len; + /* Maximal length of expected reply. */ + int reply_len; + /* Id number of packet. */ + int pack_id; + /* 0==ok, otherwise error number. */ + int result; + /* Force 12 byte command length for group 6 & 7 commands. */ + unsigned int twelve_byte:1; + /* SCSI status from target. */ + unsigned int target_status:5; + /* Host status (see "DID" codes). */ + unsigned int host_status:8; + /* Driver status+suggestion. */ + unsigned int driver_status:8; + /* Unused. */ + unsigned int other_flags:10; + /* Output in 3 cases: + when target_status is CHECK_CONDITION or + when target_status is COMMAND_TERMINATED or + when (driver_status & DRIVER_SENSE) is true. */ + unsigned char sense_buffer[SG_MAX_SENSE]; + }; + + +/* IOCTLs: The following are not required (or ignored) when the sg_io_hdr_t + interface is used. They are kept for backward compatibility with + the original and version 2 drivers. */ + +#define SG_SET_TIMEOUT 0x2201 /* Set timeout; *(int *)arg==timeout. */ +#define SG_GET_TIMEOUT 0x2202 /* Get timeout; return timeout. */ + +/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q). */ +#define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on). */ +#define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1. */ + +/* Turn on error sense trace (1..8), dump this device to log/console (9) + or dump all sg device states ( >9 ) to log/console. */ +#define SG_SET_DEBUG 0x227e /* 0 -> turn off debug */ + +#define SG_NEXT_CMD_LEN 0x2283 /* Override SCSI command length with given + number on the next write() on this file + descriptor. */ + +/* Defaults, commented if they differ from original sg driver */ +#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */ +#define SG_DEF_COMMAND_Q 0 /* command queuing is always on when + the new interface is used */ +#define SG_DEF_UNDERRUN_FLAG 0 + + +#endif /* scsi/sg.h */ diff --git a/include/search.h b/include/search.h new file mode 100644 index 0000000..2ffba69 --- /dev/null +++ b/include/search.h @@ -0,0 +1,175 @@ +/* Declarations for System V style searching functions. + Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEARCH_H +#define _SEARCH_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Prototype structure for a linked-list data structure. + This is the type used by the `insque' and `remque' functions. */ + +# ifdef __USE_GNU +struct qelem + { + struct qelem *q_forw; + struct qelem *q_back; + char q_data[1]; + }; +# endif + + +/* Insert ELEM into a doubly-linked list, after PREV. */ +extern void insque (void *__elem, void *__prev) __THROW; + +/* Unlink ELEM from the doubly-linked list that it is in. */ +extern void remque (void *__elem) __THROW; +#endif + + +/* For use with hsearch(3). */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +/* Action which shall be performed in the call the hsearch. */ +typedef enum + { + FIND, + ENTER + } +ACTION; + +typedef struct entry + { + char *key; + void *data; + } +ENTRY; + +/* Opaque type for internal use. */ +struct _ENTRY; + +/* Family of hash table handling functions. The functions also + have reentrant counterparts ending with _r. The non-reentrant + functions all work on a signle internal hashing table. */ + +/* Search for entry matching ITEM.key in internal hash table. If + ACTION is `FIND' return found entry or signal error by returning + NULL. If ACTION is `ENTER' replace existing data (if any) with + ITEM.data. */ +extern ENTRY *hsearch (ENTRY __item, ACTION __action) __THROW; + +/* Create a new hashing table which will at most contain NEL elements. */ +extern int hcreate (size_t __nel) __THROW; + +/* Destroy current internal hashing table. */ +extern void hdestroy (void) __THROW; + +#ifdef __USE_GNU +/* Data type for reentrant functions. */ +struct hsearch_data + { + struct _ENTRY *table; + unsigned int size; + unsigned int filled; + }; + +/* Reentrant versions which can handle multiple hashing tables at the + same time. */ +extern int hsearch_r (ENTRY __item, ACTION __action, ENTRY **__retval, + struct hsearch_data *__htab) __THROW; +extern int hcreate_r (size_t __nel, struct hsearch_data *__htab) __THROW; +extern void hdestroy_r (struct hsearch_data *__htab) __THROW; +#endif + + +/* The tsearch routines are very interesting. They make many + assumptions about the compiler. It assumes that the first field + in node must be the "key" field, which points to the datum. + Everything depends on that. */ +/* For tsearch */ +typedef enum +{ + preorder, + postorder, + endorder, + leaf +} +VISIT; + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP and insert a new element if not found. */ +extern void *tsearch (__const void *__key, void **__rootp, + __compar_fn_t __compar); + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP. If no matching entry is available return NULL. */ +extern void *tfind (__const void *__key, void *__const *__rootp, + __compar_fn_t __compar); + +/* Remove the element matching KEY from the tree pointed to by *ROOTP. */ +extern void *tdelete (__const void *__restrict __key, + void **__restrict __rootp, + __compar_fn_t __compar); + +#ifndef __ACTION_FN_T +# define __ACTION_FN_T +typedef void (*__action_fn_t) (__const void *__nodep, VISIT __value, + int __level); +#endif + +/* Walk through the whole tree and call the ACTION callback for every node + or leaf. */ +extern void twalk (__const void *__root, __action_fn_t __action); + +#ifdef __USE_GNU +/* Callback type for function to free a tree node. If the keys are atomic + data this function should do nothing. */ +typedef void (*__free_fn_t) (void *__nodep); + +/* Destroy the whole tree, call FREEFCT for each node or leaf. */ +extern void tdestroy (void *__root, __free_fn_t __freefct); +#endif + + +/* Perform linear search for KEY by comparing by COMPAR in an array + [BASE,BASE+NMEMB*SIZE). */ +extern void *lfind (__const void *__key, __const void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); + +/* Perform linear search for KEY by comparing by COMPAR function in + array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */ +extern void *lsearch (__const void *__key, void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); + +__END_DECLS + +#endif /* search.h */ diff --git a/include/setjmp.h b/include/setjmp.h new file mode 100644 index 0000000..99e3dc8 --- /dev/null +++ b/include/setjmp.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1991-1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.13 Nonlocal jumps + */ + +#ifndef _SETJMP_H +#define _SETJMP_H 1 + +#include + +__BEGIN_DECLS + +#include /* Get `__jmp_buf'. */ +#include /* Get `__sigset_t'. */ + +/* Calling environment, plus possibly a saved signal mask. */ +typedef struct __jmp_buf_tag /* C++ doesn't like tagless structs. */ + { + /* NOTE: The machine-dependent definitions of `__sigsetjmp' + assume that a `jmp_buf' begins with a `__jmp_buf' and that + `__mask_was_saved' follows it. Do not move these members + or add others before it. */ + __jmp_buf __jmpbuf; /* Calling environment. */ + int __mask_was_saved; /* Saved the signal mask? */ + __sigset_t __saved_mask; /* Saved signal mask. */ + } jmp_buf[1]; + + +/* Store the calling environment in ENV, also saving the signal mask. + Return 0. */ +extern int setjmp (jmp_buf __env) __THROW; + +/* Store the calling environment in ENV, not saving the signal mask. + Return 0. */ +extern int _setjmp (jmp_buf __env) __THROW; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. + This is the internal name for `sigsetjmp'. */ +extern int __sigsetjmp (jmp_buf __env, int __savemask) __THROW; + +#ifndef __FAVOR_BSD +/* Do not save the signal mask. This is equivalent to the `_setjmp' + BSD function. */ +# define setjmp(env) _setjmp (env) +#else +/* We are in 4.3 BSD-compatibility mode in which `setjmp' + saves the signal mask like `sigsetjmp (ENV, 1)'. We have to + define a macro since ISO C says `setjmp' is one. */ +# define setjmp(env) setjmp (env) +#endif /* Favor BSD. */ + + +/* Jump to the environment saved in ENV, making the + `setjmp' call there return VAL, or 1 if VAL is 0. */ +extern void longjmp (jmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#if defined __USE_BSD || defined __USE_XOPEN +/* Same. Usually `_longjmp' is used with `_setjmp', which does not save + the signal mask. But it is how ENV was saved that determines whether + `longjmp' restores the mask; `_longjmp' is just an alias. */ +extern void _longjmp (jmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#endif + + +#ifdef __USE_POSIX +/* Use the same type for `jmp_buf' and `sigjmp_buf'. + The `__mask_was_saved' flag determines whether + or not `longjmp' will restore the signal mask. */ +typedef jmp_buf sigjmp_buf; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. */ +# define sigsetjmp(env, savemask) __sigsetjmp (env, savemask) + +/* Jump to the environment saved in ENV, making the + sigsetjmp call there return VAL, or 1 if VAL is 0. + Restore the signal mask if that sigsetjmp call saved it. + This is just an alias `longjmp'. */ +extern void siglongjmp (sigjmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#endif /* Use POSIX. */ + +__END_DECLS + +#endif /* setjmp.h */ diff --git a/include/sgtty.h b/include/sgtty.h new file mode 100644 index 0000000..5b2bc41 --- /dev/null +++ b/include/sgtty.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SGTTY_H +#define _SGTTY_H 1 + +#include + +#include + +/* On some systems this type is not defined by ; + in that case, the functions are just stubs that return ENOSYS. */ +struct sgttyb; + +__BEGIN_DECLS + +/* Fill in *PARAMS with terminal parameters associated with FD. */ +extern int gtty (int __fd, struct sgttyb *__params) __THROW; + +/* Set the terminal parameters associated with FD to *PARAMS. */ +extern int stty (int __fd, __const struct sgttyb *__params) __THROW; + + +__END_DECLS + +#endif /* sgtty.h */ diff --git a/include/shadow.h b/include/shadow.h new file mode 100644 index 0000000..778df52 --- /dev/null +++ b/include/shadow.h @@ -0,0 +1,149 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Declaration of types and functions for shadow password suite. */ + +#ifndef _SHADOW_H +#define _SHADOW_H 1 + +#include + +#include + +#define __need_FILE +#include +#define __need_size_t +#include + +/* Paths to the user database files. */ +#define SHADOW _PATH_SHADOW + + +__BEGIN_DECLS + +/* Structure of the password file. */ +struct spwd + { + char *sp_namp; /* Login name. */ + char *sp_pwdp; /* Encrypted password. */ + long int sp_lstchg; /* Date of last change. */ + long int sp_min; /* Minimum number of days between changes. */ + long int sp_max; /* Maximum number of days between changes. */ + long int sp_warn; /* Number of days to warn user to change + the password. */ + long int sp_inact; /* Number of days the account may be + inactive. */ + long int sp_expire; /* Number of days since 1970-01-01 until + account expires. */ + unsigned long int sp_flag; /* Reserved. */ + }; + + +/* Open database for reading. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void setspent (void); + +/* Close database. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endspent (void); + +/* Get next entry from database, perhaps after opening the file. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *getspent (void); + +/* Get shadow entry matching NAME. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *getspnam (__const char *__name); + +/* Read shadow entry from STRING. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *sgetspent (__const char *__string); + +/* Read next shadow entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *fgetspent (FILE *__stream); + +/* Write line containing shadow password entry to stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putspent (__const struct spwd *__p, FILE *__stream); + + +#ifdef __USE_MISC +/* Reentrant versions of some of the functions above. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getspent_r (struct spwd *__result_buf, char *__buffer, + size_t __buflen, struct spwd **__result); + +extern int getspnam_r (__const char *__name, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); + +extern int sgetspent_r (__const char *__string, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); + +extern int fgetspent_r (FILE *__stream, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); +#endif /* misc */ + + +/* The simple locking functionality provided here is not suitable for + multi-threaded applications. */ + +/* Protect password file against multi writers. */ +extern int lckpwdf (void) __THROW; + +/* Unlock password file. */ +extern int ulckpwdf (void) __THROW; + +__END_DECLS + +#endif /* shadow.h */ diff --git a/include/signal.h b/include/signal.h new file mode 100644 index 0000000..610acdc --- /dev/null +++ b/include/signal.h @@ -0,0 +1,402 @@ +/* Copyright (C) 1991-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.14 Signal handling + */ + +#ifndef _SIGNAL_H + +#if !defined __need_sig_atomic_t && !defined __need_sigset_t +# define _SIGNAL_H +#endif + +#include + +__BEGIN_DECLS + +#include /* __sigset_t, __sig_atomic_t. */ + +/* An integral type that can be modified atomically, without the + possibility of a signal arriving in the middle of the operation. */ +#if defined __need_sig_atomic_t || defined _SIGNAL_H +# ifndef __sig_atomic_t_defined +# define __sig_atomic_t_defined +__BEGIN_NAMESPACE_STD +typedef __sig_atomic_t sig_atomic_t; +__END_NAMESPACE_STD +# endif +# undef __need_sig_atomic_t +#endif + +#if defined __need_sigset_t || (defined _SIGNAL_H && defined __USE_POSIX) +# ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +# endif +# undef __need_sigset_t +#endif + +#ifdef _SIGNAL_H + +#include +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif +#ifdef __USE_XOPEN +# endif +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif /* Unix98 */ + + +/* Type of a signal handler. */ +typedef void (*__sighandler_t) (int); +#if defined __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ +/* The X/Open definition of `signal' specifies the SVID semantic. Use + the additional function `sysv_signal' when X/Open compatibility is + requested. */ +extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler) + __THROW; +#ifdef __USE_GNU +extern __sighandler_t sysv_signal (int __sig, __sighandler_t __handler) + __THROW; +#endif +#endif /* __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ */ + +/* Set the handler for the signal SIG to HANDLER, returning the old + handler, or SIG_ERR on error. + By default `signal' has the BSD semantic. */ +__BEGIN_NAMESPACE_STD +#if defined __USE_BSD || !defined __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ +extern __sighandler_t signal (int __sig, __sighandler_t __handler) + __THROW; +#else +/* Make sure the used `signal' implementation is the SVID version. */ +# ifdef __REDIRECT_NTH +extern __sighandler_t __REDIRECT_NTH (signal, + (int __sig, __sighandler_t __handler), + __sysv_signal); +# else +# define signal __sysv_signal +# endif +#endif +__END_NAMESPACE_STD + +#ifdef __USE_XOPEN +/* The X/Open definition of `signal' conflicts with the BSD version. + So they defined another function `bsd_signal'. */ +extern __sighandler_t bsd_signal (int __sig, __sighandler_t __handler) + __THROW; +#endif + +/* Send signal SIG to process number PID. If PID is zero, + send SIG to all processes in the current process's process group. + If PID is < -1, send SIG to all processes in process group - PID. */ +#ifdef __USE_POSIX +extern int kill (__pid_t __pid, int __sig) __THROW; +#endif /* Use POSIX. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ +extern int killpg (__pid_t __pgrp, int __sig) __THROW; +#endif /* Use BSD || X/Open Unix. */ + +__BEGIN_NAMESPACE_STD +/* Raise signal SIG, i.e., send SIG to yourself. */ +extern int raise (int __sig) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_SVID +/* SVID names for the same things. */ +extern __sighandler_t ssignal (int __sig, __sighandler_t __handler) + __THROW; +extern int gsignal (int __sig) __THROW; +#endif /* Use SVID. */ + +#ifdef __USE_MISC +/* Print a message describing the meaning of the given signal number. */ +extern void psignal (int __sig, __const char *__s); +#endif /* Use misc. */ + + +/* The `sigpause' function has two different interfaces. The original + BSD definition defines the argument as a mask of the signal, while + the more modern interface in X/Open defines it as the signal + number. We go with the BSD version unless the user explicitly + selects the X/Open version. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int __sigpause (int __sig_or_mask, int __is_sig); + +#ifdef __FAVOR_BSD +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +extern int sigpause (int __mask) __THROW __attribute_deprecated__; +# define sigpause(mask) __sigpause ((mask), 0) +#else +# ifdef __USE_XOPEN +/* Remove a signal from the signal mask and suspend the process. */ +# define sigpause(sig) __sigpause ((sig), 1) +# endif +#endif + + +#ifdef __USE_BSD +/* None of the following functions should be used anymore. They are here + only for compatibility. A single word (`int') is not guaranteed to be + enough to hold a complete signal mask and therefore these functions + simply do not work in many situations. Use `sigprocmask' instead. */ + +/* Compute mask for signal SIG. */ +# define sigmask(sig) __sigmask(sig) + +/* Block signals in MASK, returning the old mask. */ +extern int sigblock (int __mask) __THROW __attribute_deprecated__; + +/* Set the mask of blocked signals to MASK, returning the old mask. */ +extern int sigsetmask (int __mask) __THROW __attribute_deprecated__; + +/* Return currently selected signal mask. */ +extern int siggetmask (void) __THROW __attribute_deprecated__; +#endif /* Use BSD. */ + + +#ifdef __USE_MISC +# define NSIG _NSIG +#endif + +#ifdef __USE_GNU +typedef __sighandler_t sighandler_t; +#endif + +/* 4.4 BSD uses the name `sig_t' for this. */ +#ifdef __USE_BSD +typedef __sighandler_t sig_t; +#endif + +#ifdef __USE_POSIX + +# ifdef __USE_POSIX199309 +/* We need `struct timespec' later on. */ +# define __need_timespec +# include + +/* Get the `siginfo_t' type plus the needed symbols. */ +# include +# endif + +/* Clear all signals from SET. */ +extern int sigemptyset (sigset_t *__set) __THROW __nonnull ((1)); + +/* Set all signals in SET. */ +extern int sigfillset (sigset_t *__set) __THROW __nonnull ((1)); + +/* Add SIGNO to SET. */ +extern int sigaddset (sigset_t *__set, int __signo) __THROW __nonnull ((1)); + +/* Remove SIGNO from SET. */ +extern int sigdelset (sigset_t *__set, int __signo) __THROW __nonnull ((1)); + +/* Return 1 if SIGNO is in SET, 0 if not. */ +extern int sigismember (__const sigset_t *__set, int __signo) + __THROW __nonnull ((1)); + +# ifdef __USE_GNU +/* Return non-empty value is SET is not empty. */ +extern int sigisemptyset (__const sigset_t *__set) __THROW __nonnull ((1)); + +/* Build new signal set by combining the two inputs set using logical AND. */ +extern int sigandset (sigset_t *__set, __const sigset_t *__left, + __const sigset_t *__right) __THROW __nonnull ((1, 2, 3)); + +/* Build new signal set by combining the two inputs set using logical OR. */ +extern int sigorset (sigset_t *__set, __const sigset_t *__left, + __const sigset_t *__right) __THROW __nonnull ((1, 2, 3)); +# endif /* GNU */ + +/* Get the system-specific definitions of `struct sigaction' + and the `SA_*' and `SIG_*'. constants. */ +# include + +/* Get and/or change the set of blocked signals. */ +extern int sigprocmask (int __how, __const sigset_t *__restrict __set, + sigset_t *__restrict __oset) __THROW; + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigsuspend (__const sigset_t *__set) __nonnull ((1)); + +/* Get and/or set the action for signal SIG. */ +extern int sigaction (int __sig, __const struct sigaction *__restrict __act, + struct sigaction *__restrict __oact) __THROW; + +/* Put in SET all signals that are blocked and waiting to be delivered. */ +extern int sigpending (sigset_t *__set) __THROW __nonnull ((1)); + + +/* Select any of pending signals from SET or wait for any to arrive. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigwait (__const sigset_t *__restrict __set, int *__restrict __sig) + __nonnull ((1, 2)); + +# if defined __USE_POSIX199309 && defined __UCLIBC_HAS_REALTIME__ +/* Select any of pending signals from SET and place information in INFO. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigwaitinfo (__const sigset_t *__restrict __set, + siginfo_t *__restrict __info) __nonnull ((1)); + +/* Select any of pending signals from SET and place information in INFO. + Wait the time specified by TIMEOUT if no signal is pending. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigtimedwait (__const sigset_t *__restrict __set, + siginfo_t *__restrict __info, + __const struct timespec *__restrict __timeout) + __nonnull ((1)); + +/* Send signal SIG to the process PID. Associate data in VAL with the + signal. */ +extern int sigqueue (__pid_t __pid, int __sig, __const union sigval __val) + __THROW; +# endif /* Use POSIX 199306. */ + +#endif /* Use POSIX. */ + +#ifdef __USE_BSD + +#ifdef __UCLIBC_HAS_SYS_SIGLIST__ +/* Names of the signals. This variable exists only for compatibility. + Use `strsignal' instead (see ). */ +#define _sys_siglist sys_siglist +extern __const char *__const sys_siglist[_NSIG]; +#endif /* __UCLIBC_HAS_SYS_SIGLIST__ */ + +/* Structure passed to `sigvec'. */ +struct sigvec + { + __sighandler_t sv_handler; /* Signal handler. */ + int sv_mask; /* Mask of signals to be blocked. */ + + int sv_flags; /* Flags (see below). */ +# define sv_onstack sv_flags /* 4.2 BSD compatibility. */ + }; + +/* Bits in `sv_flags'. */ +# define SV_ONSTACK (1 << 0)/* Take the signal on the signal stack. */ +# define SV_INTERRUPT (1 << 1)/* Do not restart system calls. */ +# define SV_RESETHAND (1 << 2)/* Reset handler to SIG_DFL on receipt. */ + + +/* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member + of VEC. The signals in `sv_mask' will be blocked while the handler runs. + If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be + reset to SIG_DFL before `sv_handler' is entered. If OVEC is non-NULL, + it is filled in with the old information for SIG. */ +extern int sigvec (int __sig, __const struct sigvec *__vec, + struct sigvec *__ovec) __THROW; + + +/* Get machine-dependent `struct sigcontext' and signal subcodes. */ +# include + +/* Restore the state saved in SCP. */ +extern int sigreturn (struct sigcontext *__scp) __THROW; + +#endif /* use BSD. */ + + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + +/* If INTERRUPT is nonzero, make signal SIG interrupt system calls + (causing them to fail with EINTR); if INTERRUPT is zero, make system + calls be restarted after signal SIG. */ +extern int siginterrupt (int __sig, int __interrupt) __THROW; + +# include +# ifdef __USE_XOPEN +/* This will define `ucontext_t' and `mcontext_t'. */ +# include +# endif + +/* Run signals handlers on the stack specified by SS (if not NULL). + If OSS is not NULL, it is filled in with the old signal stack status. + This interface is obsolete and on many platform not implemented. */ +extern int sigstack (struct sigstack *__ss, struct sigstack *__oss) + __THROW __attribute_deprecated__; + +/* Alternate signal handler stack interface. + This interface should always be preferred over `sigstack'. */ +extern int sigaltstack (__const struct sigaltstack *__restrict __ss, + struct sigaltstack *__restrict __oss) __THROW; + +#endif /* use BSD or X/Open Unix. */ + +#if defined __USE_XOPEN_EXTENDED && defined __UCLIBC_HAS_OBSOLETE_BSD_SIGNAL__ +/* Simplified interface for signal management. */ + +/* Add SIG to the calling process' signal mask. */ +extern int sighold (int __sig) __THROW; + +/* Remove SIG from the calling process' signal mask. */ +extern int sigrelse (int __sig) __THROW; + +/* Set the disposition of SIG to SIG_IGN. */ +extern int sigignore (int __sig) __THROW; + +/* Set the disposition of SIG. */ +extern __sighandler_t sigset (int __sig, __sighandler_t __disp) __THROW; +#endif + +#if defined __UCLIBC_HAS_THREADS__ && (defined __USE_POSIX199506 || defined __USE_UNIX98) +/* Some of the functions for handling signals in threaded programs must + be defined here. */ +# include +# include +#endif /* use Unix98 */ + +/* The following functions are used internally in the C library and in + other code which need deep insights. */ + +/* Return number of available real-time signal with highest priority. */ +extern int __libc_current_sigrtmin (void) __THROW; +/* Return number of available real-time signal with lowest priority. */ +extern int __libc_current_sigrtmax (void) __THROW; + +#endif /* signal.h */ + +__END_DECLS + +#endif /* not signal.h */ diff --git a/include/stdint.h b/include/stdint.h new file mode 100644 index 0000000..6d1ecbe --- /dev/null +++ b/include/stdint.h @@ -0,0 +1,332 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.18 Integer types + */ + +#ifndef _STDINT_H +#define _STDINT_H 1 + +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif /* __UCLIBC_HAS_WCHAR__ */ +#include + +/* Exact integral types. */ + +/* Signed. */ + +/* There is some amount of overlap with as known by inet code */ +#ifndef __int8_t_defined +# define __int8_t_defined +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +# if __WORDSIZE == 64 +typedef long int int64_t; +# else +__extension__ +typedef long long int int64_t; +# endif +#endif + +/* Unsigned. */ +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +#ifndef __uint32_t_defined +typedef unsigned int uint32_t; +# define __uint32_t_defined +#endif +#if __WORDSIZE == 64 +typedef unsigned long int uint64_t; +#else +__extension__ +typedef unsigned long long int uint64_t; +#endif + + +/* Small types. */ + +/* Signed. */ +typedef signed char int_least8_t; +typedef short int int_least16_t; +typedef int int_least32_t; +#if __WORDSIZE == 64 +typedef long int int_least64_t; +#else +__extension__ +typedef long long int int_least64_t; +#endif + +/* Unsigned. */ +typedef unsigned char uint_least8_t; +typedef unsigned short int uint_least16_t; +typedef unsigned int uint_least32_t; +#if __WORDSIZE == 64 +typedef unsigned long int uint_least64_t; +#else +__extension__ +typedef unsigned long long int uint_least64_t; +#endif + + +/* Fast types. */ + +/* Signed. */ +typedef signed char int_fast8_t; +#if __WORDSIZE == 64 +typedef long int int_fast16_t; +typedef long int int_fast32_t; +typedef long int int_fast64_t; +#else +typedef int int_fast16_t; +typedef int int_fast32_t; +__extension__ +typedef long long int int_fast64_t; +#endif + +/* Unsigned. */ +typedef unsigned char uint_fast8_t; +#if __WORDSIZE == 64 +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; +typedef unsigned long int uint_fast64_t; +#else +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; +__extension__ +typedef unsigned long long int uint_fast64_t; +#endif + + +/* Types for `void *' pointers. */ +#if __WORDSIZE == 64 +# ifndef __intptr_t_defined +typedef long int intptr_t; +# define __intptr_t_defined +# endif +typedef unsigned long int uintptr_t; +#else +# ifndef __intptr_t_defined +typedef int intptr_t; +# define __intptr_t_defined +# endif +typedef unsigned int uintptr_t; +#endif + + +/* Largest integral types. */ +#if __WORDSIZE == 64 +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +#else +__extension__ +typedef long long int intmax_t; +__extension__ +typedef unsigned long long int uintmax_t; +#endif + + +/* The ISO C99 standard specifies that in C++ implementations these + macros should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_LIMIT_MACROS + +# if __WORDSIZE == 64 +# define __INT64_C(c) c ## L +# define __UINT64_C(c) c ## UL +# else +# define __INT64_C(c) c ## LL +# define __UINT64_C(c) c ## ULL +# endif + +/* Limits of integral types. */ + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + + +/* Minimum of signed integral types having a minimum size. */ +# define INT_LEAST8_MIN (-128) +# define INT_LEAST16_MIN (-32767-1) +# define INT_LEAST32_MIN (-2147483647-1) +# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types having a minimum size. */ +# define INT_LEAST8_MAX (127) +# define INT_LEAST16_MAX (32767) +# define INT_LEAST32_MAX (2147483647) +# define INT_LEAST64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types having a minimum size. */ +# define UINT_LEAST8_MAX (255) +# define UINT_LEAST16_MAX (65535) +# define UINT_LEAST32_MAX (4294967295U) +# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615)) + + +/* Minimum of fast signed integral types having a minimum size. */ +# define INT_FAST8_MIN (-128) +# if __WORDSIZE == 64 +# define INT_FAST16_MIN (-9223372036854775807L-1) +# define INT_FAST32_MIN (-9223372036854775807L-1) +# else +# define INT_FAST16_MIN (-2147483647-1) +# define INT_FAST32_MIN (-2147483647-1) +# endif +# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of fast signed integral types having a minimum size. */ +# define INT_FAST8_MAX (127) +# if __WORDSIZE == 64 +# define INT_FAST16_MAX (9223372036854775807L) +# define INT_FAST32_MAX (9223372036854775807L) +# else +# define INT_FAST16_MAX (2147483647) +# define INT_FAST32_MAX (2147483647) +# endif +# define INT_FAST64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of fast unsigned integral types having a minimum size. */ +# define UINT_FAST8_MAX (255) +# if __WORDSIZE == 64 +# define UINT_FAST16_MAX (18446744073709551615UL) +# define UINT_FAST32_MAX (18446744073709551615UL) +# else +# define UINT_FAST16_MAX (4294967295U) +# define UINT_FAST32_MAX (4294967295U) +# endif +# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615)) + + +/* Values to test for integral types holding `void *' pointer. */ +# if __WORDSIZE == 64 +# define INTPTR_MIN (-9223372036854775807L-1) +# define INTPTR_MAX (9223372036854775807L) +# define UINTPTR_MAX (18446744073709551615UL) +# else +# define INTPTR_MIN (-2147483647-1) +# define INTPTR_MAX (2147483647) +# define UINTPTR_MAX (4294967295U) +# endif + +#if !defined(__H8300H__) && !defined(__H8300S__) +/* Minimum for largest signed integral type. */ +# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum for largest signed integral type. */ +# define INTMAX_MAX (__INT64_C(9223372036854775807)) + +/* Maximum for largest unsigned integral type. */ +# define UINTMAX_MAX (__UINT64_C(18446744073709551615)) +#else +/* Minimum for largest signed integral type. */ +# define INTMAX_MIN (-LONG_LONG_MAX-1) +/* Maximum for largest signed integral type. */ +# define INTMAX_MAX (LONG_LONG_MAX) + +/* Maximum for largest unsigned integral type. */ +# define UINTMAX_MAX (LONG_LONG_MAX<<1+1) +#endif + +/* Limits of other integer types. */ + +/* Limits of `ptrdiff_t' type. */ +# if __WORDSIZE == 64 +# define PTRDIFF_MIN (-9223372036854775807L-1) +# define PTRDIFF_MAX (9223372036854775807L) +# else +# define PTRDIFF_MIN (-2147483647-1) +# define PTRDIFF_MAX (2147483647) +# endif + +/* Limits of `sig_atomic_t'. */ +# define SIG_ATOMIC_MIN (-2147483647-1) +# define SIG_ATOMIC_MAX (2147483647) + +/* Limit of `size_t' type. */ +# if __WORDSIZE == 64 +# define SIZE_MAX (18446744073709551615UL) +# else +# define SIZE_MAX (4294967295U) +# endif + +#ifdef __UCLIBC_HAS_WCHAR__ +/* Limits of `wchar_t'. */ +# ifndef WCHAR_MIN +/* These constants might also be defined in . */ +# define WCHAR_MIN __WCHAR_MIN +# define WCHAR_MAX __WCHAR_MAX +# endif + +/* Limits of `wint_t'. */ +# define WINT_MIN (0u) +# define WINT_MAX (4294967295u) +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#endif /* C++ && limit macros */ + + +/* The ISO C99 standard specifies that in C++ implementations these + should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS + +/* Signed. */ +# define INT8_C(c) c +# define INT16_C(c) c +# define INT32_C(c) c +# if __WORDSIZE == 64 +# define INT64_C(c) c ## L +# else +# define INT64_C(c) c ## LL +# endif + +/* Unsigned. */ +# define UINT8_C(c) c ## U +# define UINT16_C(c) c ## U +# define UINT32_C(c) c ## U +# if __WORDSIZE == 64 +# define UINT64_C(c) c ## UL +# else +# define UINT64_C(c) c ## ULL +# endif + +/* Maximal type. */ +# if __WORDSIZE == 64 +# define INTMAX_C(c) c ## L +# define UINTMAX_C(c) c ## UL +# else +# define INTMAX_C(c) c ## LL +# define UINTMAX_C(c) c ## ULL +# endif + +#endif /* C++ && constant macros */ + +#endif /* stdint.h */ diff --git a/include/stdio.h b/include/stdio.h new file mode 100644 index 0000000..f14016a --- /dev/null +++ b/include/stdio.h @@ -0,0 +1,877 @@ +/* + Copyright (C) 1991,1994-2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.19 Input/output + */ + +#ifndef _STDIO_H + +#if !defined __need_FILE && !defined __need___FILE +# define _STDIO_H 1 +# include + +__BEGIN_DECLS + +# define __need_size_t +# define __need_NULL +# include + +# include +# define __need_FILE +# define __need___FILE +#endif /* Don't need FILE. */ + + +#if !defined __FILE_defined && defined __need_FILE + +__BEGIN_NAMESPACE_STD +/* The opaque type of streams. This is the definition used elsewhere. */ +typedef struct __STDIO_FILE_STRUCT FILE; +__END_NAMESPACE_STD +#if defined __USE_LARGEFILE64 || defined __USE_SVID || defined __USE_POSIX \ + || defined __USE_BSD || defined __USE_ISOC99 || defined __USE_XOPEN \ + || defined __USE_POSIX2 +__USING_NAMESPACE_STD(FILE) +#endif + +# define __FILE_defined 1 +#endif /* FILE not defined. */ +#undef __need_FILE + + +#if !defined ____FILE_defined && defined __need___FILE + +/* The opaque type of streams. This is the definition used elsewhere. */ +typedef struct __STDIO_FILE_STRUCT __FILE; + +# define ____FILE_defined 1 +#endif /* __FILE not defined. */ +#undef __need___FILE + + +#ifdef _STDIO_H +#undef _STDIO_USES_IOSTREAM + +#include + +/* This define avoids name pollution if we're using GNU stdarg.h */ +# define __need___va_list +#include + +/* The type of the second argument to `fgetpos' and `fsetpos'. */ +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +typedef __STDIO_fpos_t fpos_t; +#else +typedef __STDIO_fpos64_t fpos_t; +#endif +__END_NAMESPACE_STD +#ifdef __USE_LARGEFILE64 +typedef __STDIO_fpos64_t fpos64_t; +#endif + +/* The possibilities for the third argument to `setvbuf'. */ +#define _IOFBF __STDIO_IOFBF /* Fully buffered. */ +#define _IOLBF __STDIO_IOLBF /* Line buffered. */ +#define _IONBF __STDIO_IONBF /* No buffering. */ + + +/* Default buffer size. */ +#ifndef BUFSIZ +# define BUFSIZ __STDIO_BUFSIZ +#endif + + +/* End of file character. + Some things throughout the library rely on this being -1. */ +#ifndef EOF +# define EOF (-1) +#endif + + +/* The possibilities for the third argument to `fseek'. + These values should not be changed. */ +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 /* Seek from end of file. */ + + +#if defined __USE_SVID || defined __USE_XOPEN +/* Default path prefix for `tempnam' and `tmpnam'. */ +# define P_tmpdir "/tmp" +#endif + + +/* Get the values: + L_tmpnam How long an array of chars must be to be passed to `tmpnam'. + TMP_MAX The minimum number of unique filenames generated by tmpnam + (and tempnam when it uses tmpnam's name space), + or tempnam (the two are separate). + L_ctermid How long an array to pass to `ctermid'. + L_cuserid How long an array to pass to `cuserid'. + FOPEN_MAX Minimum number of files that can be open at once. + FILENAME_MAX Maximum length of a filename. */ +#include + + +/* Standard streams. */ +extern FILE *stdin; /* Standard input stream. */ +extern FILE *stdout; /* Standard output stream. */ +extern FILE *stderr; /* Standard error output stream. */ +/* C89/C99 say they're macros. Make them happy. */ +#define stdin stdin +#define stdout stdout +#define stderr stderr + +__BEGIN_NAMESPACE_STD +/* Remove file FILENAME. */ +extern int remove (__const char *__filename) __THROW; +/* Rename file OLD to NEW. */ +extern int rename (__const char *__old, __const char *__new) __THROW; +__END_NAMESPACE_STD + + +__BEGIN_NAMESPACE_STD +/* Create a temporary file and open it read/write. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern FILE *tmpfile (void) __wur; +#else +# ifdef __REDIRECT +extern FILE *__REDIRECT (tmpfile, (void), tmpfile64) __wur; +# else +# define tmpfile tmpfile64 +# endif +#endif + +#ifdef __USE_LARGEFILE64 +extern FILE *tmpfile64 (void) __wur; +#endif + +/* Generate a temporary filename. */ +extern char *tmpnam (char *__s) __THROW __wur; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* This is the reentrant variant of `tmpnam'. The only difference is + that it does not allow S to be NULL. */ +extern char *tmpnam_r (char *__s) __THROW __wur; +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN +/* Generate a unique temporary filename using up to five characters of PFX + if it is not NULL. The directory to put this file in is searched for + as follows: First the environment variable "TMPDIR" is checked. + If it contains the name of a writable directory, that directory is used. + If not and if DIR is not NULL, that value is checked. If that fails, + P_tmpdir is tried and finally "/tmp". The storage for the filename + is allocated by `malloc'. */ +extern char *tempnam (__const char *__dir, __const char *__pfx) + __THROW __attribute_malloc__ __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Close STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fclose (FILE *__stream); +/* Flush STREAM, or all streams if STREAM is NULL. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fflush (FILE *__stream); +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Faster versions when locking is not required. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fflush_unlocked (FILE *__stream); +#endif + +#ifdef __USE_GNU +/* Close all streams. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fcloseall (void); +#endif + + +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +/* Open a file and create a new stream for it. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *fopen (__const char *__restrict __filename, + __const char *__restrict __modes) __wur; +/* Open a file, replacing an existing stream with it. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *freopen (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream) __wur; +#else +# ifdef __REDIRECT +extern FILE *__REDIRECT (fopen, (__const char *__restrict __filename, + __const char *__restrict __modes), fopen64) + __wur; +extern FILE *__REDIRECT (freopen, (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream), freopen64) + __wur; +# else +# define fopen fopen64 +# define freopen freopen64 +# endif +#endif +__END_NAMESPACE_STD +#ifdef __USE_LARGEFILE64 +extern FILE *fopen64 (__const char *__restrict __filename, + __const char *__restrict __modes) __wur; +extern FILE *freopen64 (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream) __wur; +#endif + +#ifdef __USE_POSIX +/* Create a new stream that refers to an existing system file descriptor. */ +extern FILE *fdopen (int __fd, __const char *__modes) __THROW __wur; +#endif + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +/* Create a new stream that refers to the given magic cookie, + and uses the given functions for input and output. */ +extern FILE *fopencookie (void *__restrict __magic_cookie, + __const char *__restrict __modes, + _IO_cookie_io_functions_t __io_funcs) __THROW __wur; + +/* Create a new stream that refers to a memory buffer. */ +extern FILE *fmemopen (void *__s, size_t __len, __const char *__modes) + __THROW __wur; + +/* Open a stream that writes into a malloc'd buffer that is expanded as + necessary. *BUFLOC and *SIZELOC are updated with the buffer's location + and the number of characters written on fflush or fclose. */ +extern FILE *open_memstream (char **__restrict __bufloc, + size_t *__restrict __sizeloc) __THROW __wur; +#endif +#endif + + +__BEGIN_NAMESPACE_STD +/* If BUF is NULL, make STREAM unbuffered. + Else make it use buffer BUF, of size BUFSIZ. */ +extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __THROW; +/* Make STREAM use buffering mode MODE. + If BUF is not NULL, use N bytes of it for buffering; + else allocate an internal buffer N bytes long. */ +extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, + int __modes, size_t __n) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_BSD +/* If BUF is NULL, make STREAM unbuffered. + Else make it use SIZE bytes of BUF for buffering. */ +extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, + size_t __size) __THROW; + +/* Make STREAM line-buffered. */ +extern void setlinebuf (FILE *__stream) __THROW; +#endif + + +__BEGIN_NAMESPACE_STD +/* Write formatted output to STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fprintf (FILE *__restrict __stream, + __const char *__restrict __format, ...); +/* Write formatted output to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int printf (__const char *__restrict __format, ...); +/* Write formatted output to S. */ +extern int sprintf (char *__restrict __s, + __const char *__restrict __format, ...) __THROW; + +/* Write formatted output to S from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg); +/* Write formatted output to stdout from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg); +/* Write formatted output to S from argument list ARG. */ +extern int vsprintf (char *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) __THROW; +__END_NAMESPACE_STD + +#if defined __USE_BSD || defined __USE_ISOC99 || defined __USE_UNIX98 +__BEGIN_NAMESPACE_C99 +/* Maximum chars of output to write in MAXLEN. */ +extern int snprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__printf__, 3, 4))); + +extern int vsnprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__printf__, 3, 0))); +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_GNU +/* Write formatted output to a string dynamically allocated with `malloc'. + Store the address of the string in *PTR. */ +extern int vasprintf (char **__restrict __ptr, __const char *__restrict __f, + __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))) __wur; +#if 0 /* uClibc: disabled */ +extern int __asprintf (char **__restrict __ptr, + __const char *__restrict __fmt, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))) __wur; +#endif +extern int asprintf (char **__restrict __ptr, + __const char *__restrict __fmt, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))) __wur; + +/* Write formatted output to a file descriptor. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int vdprintf (int __fd, __const char *__restrict __fmt, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__printf__, 2, 0))); +extern int dprintf (int __fd, __const char *__restrict __fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +#endif + + +__BEGIN_NAMESPACE_STD +/* Read formatted input from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fscanf (FILE *__restrict __stream, + __const char *__restrict __format, ...) __wur; +/* Read formatted input from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int scanf (__const char *__restrict __format, ...) __wur; +/* Read formatted input from S. */ +extern int sscanf (__const char *__restrict __s, + __const char *__restrict __format, ...) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Read formatted input from S into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 2, 0))) __wur; + +/* Read formatted input from stdin into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 1, 0))) __wur; + +/* Read formatted input from S into argument list ARG. */ +extern int vsscanf (__const char *__restrict __s, + __const char *__restrict __format, __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__scanf__, 2, 0))); +__END_NAMESPACE_C99 +#endif /* Use ISO C9x. */ + + +__BEGIN_NAMESPACE_STD +/* Read a character from STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int fgetc (FILE *__stream); +extern int getc (FILE *__stream); + +/* Read a character from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getchar (void); +__END_NAMESPACE_STD + +/* The C standard explicitly says this is a macro, so we always do the + optimization for it. */ +#define getc(_fp) __GETC(_fp) + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int getc_unlocked (FILE *__stream); +extern int getchar_unlocked (void); + +/* SUSv3 allows getc_unlocked to be a macro */ +#define getc_unlocked(_fp) __GETC_UNLOCKED(_fp) +#endif /* Use POSIX or MISC. */ + +#ifdef __USE_MISC +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetc_unlocked (FILE *__stream); +#endif /* Use MISC. */ + + +__BEGIN_NAMESPACE_STD +/* Write a character to STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. + + These functions is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fputc (int __c, FILE *__stream); +extern int putc (int __c, FILE *__stream); + +/* Write a character to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int putchar (int __c); +__END_NAMESPACE_STD + +/* The C standard explicitly says this can be a macro, + so we always do the optimization for it. */ +#define putc(_ch, _fp) __PUTC(_ch, _fp) + +#ifdef __USE_MISC +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputc_unlocked (int __c, FILE *__stream); +#endif /* Use MISC. */ + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int putc_unlocked (int __c, FILE *__stream); +extern int putchar_unlocked (int __c); + +/* SUSv3 allows putc_unlocked to be a macro */ +#define putc_unlocked(_ch, _fp) __PUTC_UNLOCKED(_ch, _fp) +#endif /* Use POSIX or MISC. */ + + +#if defined __USE_SVID || defined __USE_MISC \ + || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +/* Get a word (int) from STREAM. */ +extern int getw (FILE *__stream); + +/* Write a word (int) to STREAM. */ +extern int putw (int __w, FILE *__stream); +#endif + + +__BEGIN_NAMESPACE_STD +/* Get a newline-terminated string of finite length from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + __wur; + +/* Get a newline-terminated string from stdin, removing the newline. + DO NOT USE THIS FUNCTION!! There is no limit on how much it will read. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern char *gets (char *__s) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function does the same as `fgets' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern char *fgets_unlocked (char *__restrict __s, int __n, + FILE *__restrict __stream) __wur; +#endif + + +#ifdef __USE_GNU +/* Read up to (and including) a DELIMITER from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or EOF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +#if 0 /* uClibc: disabled */ +extern __ssize_t __getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) __wur; +#endif +extern __ssize_t getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) __wur; + +/* Like `getdelim', but reads up to a newline. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern __ssize_t getline (char **__restrict __lineptr, + size_t *__restrict __n, + FILE *__restrict __stream) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Write a string to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int fputs (__const char *__restrict __s, FILE *__restrict __stream); + +/* Write a string, followed by a newline, to stdout. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int puts (__const char *__s); + + +/* Push a character back onto the input buffer of STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int ungetc (int __c, FILE *__stream); + + +/* Read chunks of generic data from STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +/* Write chunks of generic data to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern size_t fwrite (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function does the same as `fputs' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputs_unlocked (__const char *__restrict __s, + FILE *__restrict __stream); +#endif + +#ifdef __USE_MISC +/* Faster versions when locking is not necessary. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Seek to a certain position on STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fseek (FILE *__stream, long int __off, int __whence); +/* Return the current position of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern long int ftell (FILE *__stream) __wur; +/* Rewind to the beginning of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void rewind (FILE *__stream); +__END_NAMESPACE_STD + +/* The Single Unix Specification, Version 2, specifies an alternative, + more adequate interface for the two functions above which deal with + file offset. `long int' is not the right type. These definitions + are originally defined in the Large File Support API. */ + +#if defined __USE_LARGEFILE || defined __USE_XOPEN2K +# ifndef __USE_FILE_OFFSET64 +/* Seek to a certain position on STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fseeko (FILE *__stream, __off_t __off, int __whence); +/* Return the current position of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern __off_t ftello (FILE *__stream) __wur; +# else +# ifdef __REDIRECT +extern int __REDIRECT (fseeko, + (FILE *__stream, __off64_t __off, int __whence), + fseeko64); +extern __off64_t __REDIRECT (ftello, (FILE *__stream), ftello64); +# else +# define fseeko fseeko64 +# define ftello ftello64 +# endif +# endif +#endif + +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +/* Get STREAM's position. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); +/* Set STREAM's position. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fsetpos (FILE *__stream, __const fpos_t *__pos); +#else +# ifdef __REDIRECT +extern int __REDIRECT (fgetpos, (FILE *__restrict __stream, + fpos_t *__restrict __pos), fgetpos64); +extern int __REDIRECT (fsetpos, + (FILE *__stream, __const fpos_t *__pos), fsetpos64); +# else +# define fgetpos fgetpos64 +# define fsetpos fsetpos64 +# endif +#endif +__END_NAMESPACE_STD + +#ifdef __USE_LARGEFILE64 +extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence); +extern __off64_t ftello64 (FILE *__stream) __wur; +extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos); +extern int fsetpos64 (FILE *__stream, __const fpos64_t *__pos); +#endif + +__BEGIN_NAMESPACE_STD +/* Clear the error and EOF indicators for STREAM. */ +extern void clearerr (FILE *__stream) __THROW; +/* Return the EOF indicator for STREAM. */ +extern int feof (FILE *__stream) __THROW __wur; +/* Return the error indicator for STREAM. */ +extern int ferror (FILE *__stream) __THROW __wur; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Faster versions when locking is not required. */ +extern void clearerr_unlocked (FILE *__stream) __THROW; +extern int feof_unlocked (FILE *__stream) __THROW __wur; +extern int ferror_unlocked (FILE *__stream) __THROW __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Print a message describing the meaning of the value of errno. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void perror (__const char *__s); +__END_NAMESPACE_STD + +#ifdef __UCLIBC_HAS_SYS_ERRLIST__ +/* These variables normally should not be used directly. The `strerror' + function provides all the needed functionality. */ +#ifdef __USE_BSD +extern int sys_nerr; +extern __const char *__const sys_errlist[]; +#endif +#endif /* __UCLIBC_HAS_SYS_ERRLIST__ */ + + +#ifdef __USE_POSIX +/* Return the system file descriptor for STREAM. */ +extern int fileno (FILE *__stream) __THROW __wur; +#endif /* Use POSIX. */ + +#ifdef __USE_MISC +/* Faster version when locking is not required. */ +extern int fileno_unlocked (FILE *__stream) __THROW __wur; +#endif + + +#if (defined __USE_POSIX2 || defined __USE_SVID || defined __USE_BSD || \ + defined __USE_MISC) +/* Create a new stream connected to a pipe running the given command. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *popen (__const char *__command, __const char *__modes) __wur; + +/* Close a stream opened by popen and return the status of its child. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int pclose (FILE *__stream); +#endif + + +#ifdef __USE_POSIX +/* Return the name of the controlling terminal. */ +extern char *ctermid (char *__s) __THROW; +#endif /* Use POSIX. */ + + +#ifdef __USE_XOPEN +/* Return the name of the current user. */ +extern char *cuserid (char *__s); +#endif /* Use X/Open, but not issue 6. */ + + +#if 0 /* def __USE_GNU uClibc note: not supported */ +struct obstack; /* See . */ + +/* Write formatted output to an obstack. */ +extern int obstack_printf (struct obstack *__restrict __obstack, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))); +extern int obstack_vprintf (struct obstack *__restrict __obstack, + __const char *__restrict __format, + __gnuc_va_list __args) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))); +#endif /* Use GNU. */ + + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. */ + +/* Acquire ownership of STREAM. */ +extern void flockfile (FILE *__stream) __THROW; + +/* Try to acquire ownership of STREAM but do not block if it is not + possible. */ +extern int ftrylockfile (FILE *__stream) __THROW __wur; + +/* Relinquish the ownership granted for STREAM. */ +extern void funlockfile (FILE *__stream) __THROW; +#endif /* POSIX || misc */ + +#if defined __USE_XOPEN && !defined __USE_XOPEN2K && !defined __USE_GNU +/* The X/Open standard requires some functions and variables to be + declared here which do not belong into this header. But we have to + follow. In GNU mode we don't do this nonsense. */ +# define __need_getopt +# include +#endif /* X/Open, but not issue 6 and not for GNU. */ + +/* If we are compiling with optimizing read this file. It contains + several optimizing inline functions and macros. */ +#define fgetc(_fp) __FGETC(_fp) +#define fputc(_ch, _fp) __FPUTC(_ch, _fp) + +#ifdef __USE_MISC +#define fgetc_unlocked(_fp) __FGETC_UNLOCKED(_fp) +#define fputc_unlocked(_ch, _fp) __FPUTC_UNLOCKED(_ch, _fp) +#endif + +#ifndef __STDIO_GETC_MACRO +#define __stdin stdin +#endif +#define getchar() __GETC(__stdin) + +#ifndef __STDIO_PUTC_MACRO +#define __stdout stdout +#endif +#define putchar(_ch) __PUTC((_ch), __stdout) + +#if defined __USE_POSIX || defined __USE_MISC +#define getchar_unlocked() __GETC_UNLOCKED(__stdin) +#define putchar_unlocked(_ch) __PUTC_UNLOCKED((_ch), __stdout) +#endif + +/* Clear the error and EOF indicators for STREAM. */ +#define clearerr(_fp) __CLEARERR(_fp) +#define feof(_fp) __FEOF(_fp) +#define ferror(_fp) __FERROR(_fp) + +#ifdef __USE_MISC +#define clearerr_unlocked(_fp) __CLEARERR_UNLOCKED(_fp) +#define feof_unlocked(_fp) __FEOF_UNLOCKED(_fp) +#define ferror_unlocked(_fp) __FERROR_UNLOCKED(_fp) +#endif + +__END_DECLS + +#endif /* included. */ + +#endif /* !_STDIO_H */ diff --git a/include/stdio_ext.h b/include/stdio_ext.h new file mode 100644 index 0000000..23d12e0 --- /dev/null +++ b/include/stdio_ext.h @@ -0,0 +1,87 @@ +/* Functions to access FILE structure internals. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This header contains the same definitions as the header of the same name + on Sun's Solaris OS. */ + +#ifndef _STDIO_EXT_H +#define _STDIO_EXT_H 1 + +#include + +enum +{ + /* Query current state of the locking status. */ + FSETLOCKING_QUERY = 0, +#define FSETLOCKING_QUERY FSETLOCKING_QUERY + /* The library protects all uses of the stream functions, except for + uses of the *_unlocked functions, by calls equivalent to flockfile(). */ + FSETLOCKING_INTERNAL, +#define FSETLOCKING_INTERNAL FSETLOCKING_INTERNAL + /* The user will take care of locking. */ + FSETLOCKING_BYCALLER +#define FSETLOCKING_BYCALLER FSETLOCKING_BYCALLER +}; + + +__BEGIN_DECLS + +/* Return the size of the buffer of FP in bytes currently in use by + the given stream. */ +extern size_t __fbufsize (FILE *__fp) __THROW; + + +/* Return non-zero value iff the stream FP is opened readonly, or if the + last operation on the stream was a read operation. */ +extern int __freading (FILE *__fp) __THROW; + +/* Return non-zero value iff the stream FP is opened write-only or + append-only, or if the last operation on the stream was a write + operation. */ +extern int __fwriting (FILE *__fp) __THROW; + + +/* Return non-zero value iff stream FP is not opened write-only or + append-only. */ +extern int __freadable (FILE *__fp) __THROW; + +/* Return non-zero value iff stream FP is not opened read-only. */ +extern int __fwritable (FILE *__fp) __THROW; + + +/* Return non-zero value iff the stream FP is line-buffered. */ +extern int __flbf (FILE *__fp) __THROW; + + +/* Discard all pending buffered I/O on the stream FP. */ +extern void __fpurge (FILE *__fp) __THROW; + +/* Return amount of output in bytes pending on a stream FP. */ +extern size_t __fpending (FILE *__fp) __THROW; + +/* Flush all line-buffered files. */ +extern void _flushlbf (void); + + +/* Set locking status of stream FP to TYPE. */ +extern int __fsetlocking (FILE *__fp, int __type) __THROW; + +__END_DECLS + +#endif /* stdio_ext.h */ diff --git a/include/stdlib.h b/include/stdlib.h new file mode 100644 index 0000000..b87dfd9 --- /dev/null +++ b/include/stdlib.h @@ -0,0 +1,872 @@ +/* Copyright (C) 1991-2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.20 General utilities + */ + +#ifndef _STDLIB_H + +#include + +/* Get size_t, wchar_t and NULL from . */ +#define __need_size_t +#ifndef __need_malloc_and_calloc +# ifdef __UCLIBC_HAS_WCHAR__ +# define __need_wchar_t +# endif +# define __need_NULL +#endif +#include + +__BEGIN_DECLS + +#ifndef __need_malloc_and_calloc +#define _STDLIB_H 1 + +#if defined __USE_XOPEN && !defined _SYS_WAIT_H +/* XPG requires a few symbols from being defined. */ +# include +# include + +# ifdef __USE_BSD + +/* Lots of hair to allow traditional BSD use of `union wait' + as well as POSIX.1 use of `int' for the status word. */ + +# if defined __GNUC__ && !defined __cplusplus +# define __WAIT_INT(status) \ + (__extension__ ({ union { __typeof(status) __in; int __i; } __u; \ + __u.__in = (status); __u.__i; })) +# else +# define __WAIT_INT(status) (*(int *) &(status)) +# endif + +/* This is the type of the argument to `wait'. The funky union + causes redeclarations with ether `int *' or `union wait *' to be + allowed without complaint. __WAIT_STATUS_DEFN is the type used in + the actual function definitions. */ + +# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus +# define __WAIT_STATUS void * +# define __WAIT_STATUS_DEFN void * +# else +/* This works in GCC 2.6.1 and later. */ +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# define __WAIT_STATUS_DEFN int * +# endif + +# else /* Don't use BSD. */ + +# define __WAIT_INT(status) (status) +# define __WAIT_STATUS int * +# define __WAIT_STATUS_DEFN int * + +# endif /* Use BSD. */ + +/* Define the macros also would define this way. */ +# define WEXITSTATUS(status) __WEXITSTATUS(__WAIT_INT(status)) +# define WTERMSIG(status) __WTERMSIG(__WAIT_INT(status)) +# define WSTOPSIG(status) __WSTOPSIG(__WAIT_INT(status)) +# define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) +# define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) +# define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +# if 0 /* def __WIFCONTINUED */ +# define WIFCONTINUED(status) __WIFCONTINUED(__WAIT_INT(status)) +# endif +#endif /* X/Open and not included. */ + +__BEGIN_NAMESPACE_STD +/* Returned by `div'. */ +typedef struct + { + int quot; /* Quotient. */ + int rem; /* Remainder. */ + } div_t; + +/* Returned by `ldiv'. */ +#ifndef __ldiv_t_defined +typedef struct + { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ + } ldiv_t; +# define __ldiv_t_defined 1 +#endif +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 && !defined __lldiv_t_defined +__BEGIN_NAMESPACE_C99 +/* Returned by `lldiv'. */ +__extension__ typedef struct + { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ + } lldiv_t; +# define __lldiv_t_defined 1 +__END_NAMESPACE_C99 +#endif + + +/* The largest number rand will return (same as INT_MAX). */ +#define RAND_MAX 2147483647 + + +/* We define these the same for all machines. + Changes from this to the outside world should be done in `_exit'. */ +#define EXIT_FAILURE 1 /* Failing exit status. */ +#define EXIT_SUCCESS 0 /* Successful exit status. */ + + +/* Maximum length of a multibyte character in the current locale. */ +#if 0 +#define MB_CUR_MAX (__ctype_get_mb_cur_max ()) +extern size_t __ctype_get_mb_cur_max (void) __THROW __wur; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ +#define MB_CUR_MAX (_stdlib_mb_cur_max ()) +extern size_t _stdlib_mb_cur_max (void) __THROW __wur; +#endif + + +__BEGIN_NAMESPACE_STD +#ifdef __UCLIBC_HAS_FLOATS__ +/* Convert a string to a floating-point number. */ +extern double atof (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +#endif /* __UCLIBC_HAS_FLOATS__ */ +/* Convert a string to an integer. */ +extern int atoi (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +/* Convert a string to a long integer. */ +extern long int atol (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 || defined __USE_MISC +__BEGIN_NAMESPACE_C99 +/* Convert a string to a long long integer. */ +__extension__ extern long long int atoll (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif + +#ifdef __UCLIBC_HAS_FLOATS__ +__BEGIN_NAMESPACE_STD +/* Convert a string to a floating-point number. */ +extern double strtod (__const char *__restrict __nptr, + char **__restrict __endptr) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float strtof (__const char *__restrict __nptr, + char **__restrict __endptr) __THROW __nonnull ((1)) __wur; + +extern long double strtold (__const char *__restrict __nptr, + char **__restrict __endptr) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif +#endif /* __UCLIBC_HAS_FLOATS__ */ + +__BEGIN_NAMESPACE_STD +/* Convert a string to a long integer. */ +extern long int strtol (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +/* Convert a string to an unsigned long integer. */ +extern unsigned long int strtoul (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_BSD +/* Convert a string to a quadword integer. */ +__extension__ +extern long long int strtoq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern unsigned long long int strtouq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +#endif /* GCC and use BSD. */ + +#if defined __USE_ISOC99 || defined __USE_MISC +__BEGIN_NAMESPACE_C99 +/* Convert a string to a quadword integer. */ +__extension__ +extern long long int strtoll (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern unsigned long long int strtoull (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif /* ISO C99 or GCC and use MISC. */ + + +#ifdef __UCLIBC_HAS_XLOCALE__ +#ifdef __USE_GNU +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int strtol_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) __THROW __nonnull ((1, 4)) __wur; + +extern unsigned long int strtoul_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; + +__extension__ +extern long long int strtoll_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; + +__extension__ +extern unsigned long long int strtoull_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern double strtod_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; + +extern float strtof_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; + +extern long double strtold_l (__const char *__restrict __nptr, + char **__restrict __endptr, + __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#endif /* GNU */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Convert N to base 64 using the digits "./0-9A-Za-z", least-significant + digit first. Returns a pointer to static storage overwritten by the + next call. */ +extern char *l64a (long int __n) __THROW __wur; + +/* Read a number from a string S in base 64 as above. */ +extern long int a64l (__const char *__s) + __THROW __attribute_pure__ __nonnull ((1)) __wur; + +#endif /* Use SVID || extended X/Open. */ + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED || defined __USE_BSD +# include /* we need int32_t... */ + +/* These are the functions that actually do things. The `random', `srandom', + `initstate' and `setstate' functions are those from BSD Unices. + The `rand' and `srand' functions are required by the ANSI standard. + We provide both interfaces to the same random number generator. */ +/* Return a random long integer between 0 and RAND_MAX inclusive. */ +extern long int random (void) __THROW; + +/* Seed the random number generator with the given number. */ +extern void srandom (unsigned int __seed) __THROW; + +/* Initialize the random number generator to use state buffer STATEBUF, + of length STATELEN, and seed it with SEED. Optimal lengths are 8, 16, + 32, 64, 128 and 256, the bigger the better; values less than 8 will + cause an error and values greater than 256 will be rounded down. */ +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __THROW __nonnull ((2)); + +/* Switch the random number generator to state buffer STATEBUF, + which should have been previously initialized by `initstate'. */ +extern char *setstate (char *__statebuf) __THROW __nonnull ((1)); + + +# ifdef __USE_MISC +/* Reentrant versions of the `random' family of functions. + These functions all use the following data structure to contain + state, rather than global state variables. */ + +struct random_data + { + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + int rand_type; /* Type of random number generator. */ + int rand_deg; /* Degree of random number generator. */ + int rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ + }; + +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __THROW __nonnull ((1, 2)); + +extern int srandom_r (unsigned int __seed, struct random_data *__buf) + __THROW __nonnull ((2)); + +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) + __THROW __nonnull ((2, 4)); + +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) + __THROW __nonnull ((1, 2)); +# endif /* Use misc. */ +#endif /* Use SVID || extended X/Open || BSD. */ + + +__BEGIN_NAMESPACE_STD +/* Return a random integer between 0 and RAND_MAX inclusive. */ +extern int rand (void) __THROW; +/* Seed the random number generator with the given number. */ +extern void srand (unsigned int __seed) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_POSIX +/* Reentrant interface according to POSIX.1. */ +extern int rand_r (unsigned int *__seed) __THROW; +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN +/* System V style 48-bit random number generator functions. */ + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern double drand48 (void) __THROW; +extern double erand48 (unsigned short int __xsubi[3]) __THROW __nonnull ((1)); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Return non-negative, long integer in [0,2^31). */ +extern long int lrand48 (void) __THROW; +extern long int nrand48 (unsigned short int __xsubi[3]) + __THROW __nonnull ((1)); + +/* Return signed, long integers in [-2^31,2^31). */ +extern long int mrand48 (void) __THROW; +extern long int jrand48 (unsigned short int __xsubi[3]) + __THROW __nonnull ((1)); + +/* Seed random number generator. */ +extern void srand48 (long int __seedval) __THROW; +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) + __THROW __nonnull ((1)); +extern void lcong48 (unsigned short int __param[7]) __THROW __nonnull ((1)); + +# ifdef __USE_MISC +/* Data structure for communication with thread safe versions. This + type is to be regarded as opaque. It's only exported because users + have to allocate objects of this type. */ +struct drand48_data + { + unsigned short int __x[3]; /* Current state. */ + unsigned short int __old_x[3]; /* Old state. */ + unsigned short int __c; /* Additive const. in congruential formula. */ + unsigned short int __init; /* Flag for initializing. */ + unsigned long long int __a; /* Factor in congruential formula. */ + }; + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW __nonnull ((1, 2)); +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW __nonnull ((1, 2)); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Return non-negative, long integer in [0,2^31). */ +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); + +/* Return signed, long integers in [-2^31,2^31). */ +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); + +/* Seed random number generator. */ +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __THROW __nonnull ((2)); + +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __THROW __nonnull ((1, 2)); + +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) + __THROW __nonnull ((1, 2)); +# endif /* Use misc. */ +#endif /* Use SVID or X/Open. */ + +#endif /* don't just need malloc and calloc */ + +#ifndef __malloc_and_calloc_defined +# define __malloc_and_calloc_defined +__BEGIN_NAMESPACE_STD +/* Allocate SIZE bytes of memory. */ +extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur; +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern void *calloc (size_t __nmemb, size_t __size) + __THROW __attribute_malloc__ __wur; +__END_NAMESPACE_STD +#endif + +#ifndef __need_malloc_and_calloc +__BEGIN_NAMESPACE_STD +/* Re-allocate the previously allocated block + in PTR, making the new block SIZE bytes long. */ +extern void *realloc (void *__ptr, size_t __size) + __THROW __attribute_malloc__ __attribute_warn_unused_result__; +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free (void *__ptr) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Free a block. An alias for `free'. (Sun Unices). */ +extern void cfree (void *__ptr) __THROW; +#endif /* Use misc. */ + +#if defined __USE_GNU || defined __USE_BSD || defined __USE_MISC +# include +#endif /* Use GNU, BSD, or misc. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Allocate SIZE bytes on a page boundary. The storage cannot be freed. */ +extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur; +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Allocate memory of SIZE bytes with an alignment of ALIGNMENT. */ +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __THROW __nonnull ((1)) __wur; +#endif + +__BEGIN_NAMESPACE_STD +/* Abort execution and generate a core-dump. */ +extern void abort (void) __THROW __attribute__ ((__noreturn__)); + + +/* Register a function to be called when `exit' is called. */ +extern int atexit (void (*__func) (void)) __THROW __nonnull ((1)); +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Register a function to be called with the status + given to `exit' and the given argument. */ +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __THROW __nonnull ((1)); +#endif + +__BEGIN_NAMESPACE_STD +/* Call all functions registered with `atexit' and `on_exit', + in the reverse of the order in which they were registered + perform stdio cleanup, and terminate program execution with STATUS. */ +extern void exit (int __status) __THROW __attribute__ ((__noreturn__)); +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Terminate the program with STATUS without calling any of the + functions registered with `atexit' or `on_exit'. */ +extern void _Exit (int __status) __THROW __attribute__ ((__noreturn__)); +__END_NAMESPACE_C99 +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the value of envariable NAME, or NULL if it doesn't exist. */ +extern char *getenv (__const char *__name) __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_STD + +/* This function is similar to the above but returns NULL if the + programs is running with SUID or SGID enabled. */ +extern char *__secure_getenv (__const char *__name) + __THROW __nonnull ((1)) __wur; + +#if defined __USE_SVID || defined __USE_XOPEN +/* The SVID says this is in , but this seems a better place. */ +/* Put STRING, which is of the form "NAME=VALUE", in the environment. + If there is no `=', remove NAME from the environment. */ +extern int putenv (char *__string) __THROW __nonnull ((1)); +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +extern int setenv (__const char *__name, __const char *__value, int __replace) + __THROW __nonnull ((2)); + +/* Remove the variable NAME from the environment. */ +extern int unsetenv (__const char *__name) __THROW; +#endif + +/* The following is used by uClibc in atexit.c and sysconf.c */ +/* We have no limit when __UCLIBC_DYNAMIC_ATEXIT__ is enabled. */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +# define __UCLIBC_MAX_ATEXIT INT_MAX +#else +# define __UCLIBC_MAX_ATEXIT 20 +#endif + + +#ifdef __USE_MISC +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +extern int clearenv (void) __THROW; +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique file name. */ +extern char *mktemp (char *__template) __THROW __nonnull ((1)) __wur; + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Returns a file descriptor open on the file for reading and writing, + or -1 if it cannot create a uniquely-named file. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int mkstemp (char *__template) __nonnull ((1)) __wur; +# else +# ifdef __REDIRECT +extern int __REDIRECT (mkstemp, (char *__template), mkstemp64) + __nonnull ((1)) __wur; +# else +# define mkstemp mkstemp64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int mkstemp64 (char *__template) __nonnull ((1)) __wur; +# endif +#endif + +#ifdef __USE_BSD +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char *mkdtemp (char *__template) __THROW __nonnull ((1)) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Execute the given line as a shell command. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int system (__const char *__command) __wur; +__END_NAMESPACE_STD + + +#if 0 /* def __USE_GNU */ +/* Return a malloc'd string containing the canonical absolute name of the + named file. The last file name component need not exist, and may be a + symlink to a nonexistent file. */ +extern char *canonicalize_file_name (__const char *__name) + __THROW __nonnull ((1)) __wur; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Return the canonical absolute name of file NAME. The last file name + component need not exist, and may be a symlink to a nonexistent file. + If RESOLVED is null, the result is malloc'd; otherwise, if the canonical + name is PATH_MAX chars or more, returns null with `errno' set to + ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the + name in RESOLVED. */ +/* we choose to handle __resolved==NULL as crash :) */ +extern char *realpath (__const char *__restrict __name, + char *__restrict __resolved) __THROW __wur __nonnull((2)); +#endif + + +/* Shorthand for type of comparison functions. */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +__BEGIN_NAMESPACE_STD +/* Do a binary search for KEY in BASE, which consists of NMEMB elements + of SIZE bytes each, using COMPAR to perform the comparisons. */ +extern void *bsearch (__const void *__key, __const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar) + __nonnull ((1, 2, 5)) __wur; + +/* Sort NMEMB elements of BASE, of SIZE bytes each, + using COMPAR to perform the comparisons. */ +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __nonnull ((1, 4)); + + +/* Return the absolute value of X. */ +extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur; +extern long int labs (long int __x) __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__extension__ extern long long int llabs (long long int __x) + __THROW __attribute__ ((__const__)) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the `div_t', `ldiv_t' or `lldiv_t' representation + of the value of NUMER over DENOM. */ +/* GCC may have built-ins for these someday. */ +extern div_t div (int __numer, int __denom) + __THROW __attribute__ ((__const__)) __wur; +extern ldiv_t ldiv (long int __numer, long int __denom) + __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_C99 +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED || defined __USE_BSD +/* Convert floating point numbers to strings. The returned values are + valid only until another call to the same function. */ + +# ifdef __UCLIBC_SUSV3_LEGACY__ + +#if 0 +/* Convert VALUE to a string with NDIGIT digits and return a pointer to + this. Set *DECPT with the position of the decimal character and *SIGN + with the sign of the number. */ +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW __nonnull ((3, 4)) __wur; + +/* Convert VALUE to a string rounded to NDIGIT decimal digits. Set *DECPT + with the position of the decimal character and *SIGN with the sign of + the number. */ +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW __nonnull ((3, 4)) __wur; +#endif + +/* If possible convert VALUE to a string with NDIGIT significant digits. + Otherwise use exponential representation. The resulting string will + be written to BUF. */ +extern char *gcvt (double __value, int __ndigit, char *__buf) + __THROW __nonnull ((3)) __wur; +# endif /* __UCLIBC_SUSV3_LEGACY__ */ + +# if 0 /*def __USE_MISC*/ +/* Long double versions of above functions. */ +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __THROW __nonnull ((3, 4)) __wur; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __THROW __nonnull ((3, 4)) __wur; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) + __THROW __nonnull ((3)) __wur; + + +/* Reentrant version of the functions above which provide their own + buffers. */ +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW __nonnull ((3, 4, 5)); +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW __nonnull ((3, 4, 5)); + +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((3, 4, 5)); +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((3, 4, 5)); +# endif /* misc */ +#endif /* use MISC || use X/Open Unix */ + +#ifdef __UCLIBC_HAS_WCHAR__ +__BEGIN_NAMESPACE_STD +/* Return the length of the multibyte character + in S, which is no longer than N. */ +extern int mblen (__const char *__s, size_t __n) __THROW __wur; +/* Return the length of the given multibyte character, + putting its `wchar_t' representation in *PWC. */ +extern int mbtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n) __THROW __wur; +/* Put the multibyte character represented + by WCHAR in S, returning its length. */ +extern int wctomb (char *__s, wchar_t __wchar) __THROW __wur; + + +/* Convert a multibyte string to a wide char string. */ +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + __const char *__restrict __s, size_t __n) __THROW; +/* Convert a wide char string to multibyte string. */ +extern size_t wcstombs (char *__restrict __s, + __const wchar_t *__restrict __pwcs, size_t __n) + __THROW; +__END_NAMESPACE_STD +#endif /* __UCLIBC_HAS_WCHAR__ */ + + +#ifdef __USE_SVID +/* Determine whether the string value of RESPONSE matches the affirmation + or negative response expression as specified by the LC_MESSAGES category + in the program's current locale. Returns 1 if affirmative, 0 if + negative, and -1 if not matching. */ +extern int rpmatch (__const char *__response) __THROW __nonnull ((1)) __wur; +#endif + + +#ifdef __USE_XOPEN_EXTENDED +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +extern int getsubopt (char **__restrict __optionp, + char *__const *__restrict __tokens, + char **__restrict __valuep) + __THROW __nonnull ((1, 2, 3)) __wur; +#endif + + +#ifdef __USE_XOPEN +# if defined __UCLIBC_HAS_CRYPT__ +/* Setup DES tables according KEY. */ +extern void setkey (__const char *__key) __THROW __nonnull ((1)); +# endif /* __UCLIBC_HAS_CRYPT__ */ +#endif + + +/* X/Open pseudo terminal handling. */ + +#ifdef __USE_XOPEN2K +/* Return a master pseudo-terminal handle. */ +extern int posix_openpt (int __oflag) __wur; +libc_hidden_proto(posix_openpt) +#endif + +#ifdef __USE_XOPEN +/* The next four functions all take a master pseudo-tty fd and + perform an operation on the associated slave: */ +#ifdef __UCLIBC_HAS_PTY__ +/* Chown the slave to the calling user. */ +extern int grantpt (int __fd) __THROW; + +/* Release an internal lock so the slave can be opened. + Call after grantpt(). */ +extern int unlockpt (int __fd) __THROW; + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +extern char *ptsname (int __fd) __THROW __wur; +#endif /* __UCLIBC_HAS_PTY__ */ +#endif + +#ifdef __USE_GNU +# if defined __UCLIBC_HAS_PTY__ +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +extern int ptsname_r (int __fd, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +# endif +# if defined __UCLIBC_HAS_GETPT__ +/* Open a master pseudo terminal and return its file descriptor. */ +extern int getpt (void); +# endif +#endif + +#if 0 /* def __USE_BSD */ +/* Put the 1 minute, 5 minute and 15 minute load averages into the first + NELEM elements of LOADAVG. Return the number written (never more than + three, but may be less than NELEM), or -1 if an error occurred. */ +extern int getloadavg (double __loadavg[], int __nelem) + __THROW __nonnull ((1)); +#endif + +#ifdef __UCLIBC_HAS_ARC4RANDOM__ +#include +extern uint32_t arc4random(void); +extern void arc4random_stir(void); +extern void arc4random_addrandom(unsigned char *, int); +#endif + +#endif /* don't just need malloc and calloc */ +#undef __need_malloc_and_calloc + +__END_DECLS + +#endif /* stdlib.h */ diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..bbca20a --- /dev/null +++ b/include/string.h @@ -0,0 +1,485 @@ +/* Copyright (C) 1991-1993, 1995-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.21 String handling + */ + +#ifndef _STRING_H +#define _STRING_H 1 + +#include + +__BEGIN_DECLS + +/* Get size_t and NULL from . */ +#define __need_size_t +#define __need_NULL +#include + + +__BEGIN_NAMESPACE_STD +/* Copy N bytes of SRC to DEST. */ +extern void *memcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memcpy) +/* Copy N bytes of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +extern void *memmove (void *__dest, __const void *__src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memmove) +__END_NAMESPACE_STD + +/* Copy no more than N bytes of SRC to DEST, stopping when C is found. + Return the position in DEST one byte past where C was copied, + or NULL if C was not found in the first N bytes of SRC. */ +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN +extern void *memccpy (void *__restrict __dest, __const void *__restrict __src, + int __c, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memccpy) +#endif /* SVID. */ + + +__BEGIN_NAMESPACE_STD +/* Set N bytes of S to C. */ +extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1)); +libc_hidden_proto(memset) + +/* Compare N bytes of S1 and S2. */ +extern int memcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(memcmp) + +/* Search N bytes of S for C. */ +extern void *memchr (__const void *__s, int __c, size_t __n) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(memchr) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* Search in S for C. This is similar to `memchr' but there is no + length limit. */ +extern void *rawmemchr (__const void *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(rawmemchr) + +/* Search N bytes of S for the final occurrence of C. */ +extern void *memrchr (__const void *__s, int __c, size_t __n) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(memrchr) +#endif + + +__BEGIN_NAMESPACE_STD +/* Copy SRC to DEST. */ +extern char *strcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strcpy) +/* Copy no more than N characters of SRC to DEST. */ +extern char *strncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strncpy) + +/* Append SRC onto DEST. */ +extern char *strcat (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strcat) +/* Append no more than N characters from SRC onto DEST. */ +extern char *strncat (char *__restrict __dest, __const char *__restrict __src, + size_t __n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strncat) + +/* Compare S1 and S2. */ +extern int strcmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcmp) +/* Compare N characters of S1 and S2. */ +extern int strncmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strncmp) + +/* Compare the collated forms of S1 and S2. */ +extern int strcoll (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcoll) +/* Put a transformation of SRC into no more than N bytes of DEST. */ +extern size_t strxfrm (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((2)); +libc_hidden_proto(strxfrm) +__END_NAMESPACE_STD + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* The following functions are equivalent to the both above but they + take the locale they use for the collation as an extra argument. + This is not standardsized but something like will come. */ +# include + +/* Compare the collated forms of S1 and S2 using rules from L. */ +extern int strcoll_l (__const char *__s1, __const char *__s2, __locale_t __l) + __THROW __attribute_pure__ __nonnull ((1, 2, 3)); +libc_hidden_proto(strcoll_l) +/* Put a transformation of SRC into no more than N bytes of DEST. */ +extern size_t strxfrm_l (char *__dest, __const char *__src, size_t __n, + __locale_t __l) __THROW __nonnull ((2, 4)); +libc_hidden_proto(strxfrm_l) +#endif + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Duplicate S, returning an identical malloc'd string. */ +extern char *strdup (__const char *__s) + __THROW __attribute_malloc__ __nonnull ((1)); +libc_hidden_proto(strdup) +#endif + +/* Return a malloc'd copy of at most N bytes of STRING. The + resultant string is terminated even if no null terminator + appears before STRING[N]. */ +#if defined __USE_GNU +extern char *strndup (__const char *__string, size_t __n) + __THROW __attribute_malloc__ __nonnull ((1)); +libc_hidden_proto(strndup) +#endif + +#if defined __USE_GNU && defined __GNUC__ +/* Duplicate S, returning an identical alloca'd string. */ +# define strdupa(s) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strlen (__old) + 1; \ + char *__new = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__new, __old, __len); \ + })) + +/* Return an alloca'd copy of at most N bytes of string. */ +# define strndupa(s, n) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strnlen (__old, (n)); \ + char *__new = (char *) __builtin_alloca (__len + 1); \ + __new[__len] = '\0'; \ + (char *) memcpy (__new, __old, __len); \ + })) +#endif + +__BEGIN_NAMESPACE_STD +/* Find the first occurrence of C in S. */ +extern char *strchr (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strchr) +/* Find the last occurrence of C in S. */ +extern char *strrchr (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strrchr) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function is similar to `strchr'. But it returns a pointer to + the closing NUL byte in case C is not found in S. */ +extern char *strchrnul (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strchrnul) +#endif + +__BEGIN_NAMESPACE_STD +/* Return the length of the initial segment of S which + consists entirely of characters not in REJECT. */ +extern size_t strcspn (__const char *__s, __const char *__reject) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcspn) +/* Return the length of the initial segment of S which + consists entirely of characters in ACCEPT. */ +extern size_t strspn (__const char *__s, __const char *__accept) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strspn) +/* Find the first occurrence in S of any character in ACCEPT. */ +extern char *strpbrk (__const char *__s, __const char *__accept) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strpbrk) +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +extern char *strstr (__const char *__haystack, __const char *__needle) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strstr) + + +/* Divide S into tokens separated by characters in DELIM. */ +extern char *strtok (char *__restrict __s, __const char *__restrict __delim) + __THROW __nonnull ((2)); +libc_hidden_proto(strtok) +__END_NAMESPACE_STD + +/* Divide S into tokens separated by characters in DELIM. Information + passed between calls are stored in SAVE_PTR. */ +#if 0 /* uClibc: disabled */ +extern char *__strtok_r (char *__restrict __s, + __const char *__restrict __delim, + char **__restrict __save_ptr) + __THROW __nonnull ((2, 3)); +#endif +#if defined __USE_POSIX || defined __USE_MISC +extern char *strtok_r (char *__restrict __s, __const char *__restrict __delim, + char **__restrict __save_ptr) + __THROW __nonnull ((2, 3)); +libc_hidden_proto(strtok_r) +#endif + +#ifdef __USE_GNU +/* Similar to `strstr' but this function ignores the case of both strings. */ +extern char *strcasestr (__const char *__haystack, __const char *__needle) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcasestr) +#endif + +#ifdef __USE_GNU +/* Find the first occurrence of NEEDLE in HAYSTACK. + NEEDLE is NEEDLELEN bytes long; + HAYSTACK is HAYSTACKLEN bytes long. */ +extern void *memmem (__const void *__haystack, size_t __haystacklen, + __const void *__needle, size_t __needlelen) + __THROW __attribute_pure__ __nonnull ((1, 3)); +libc_hidden_proto(memmem) + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +#if 0 /* uClibc: disabled */ +extern void *__mempcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +#endif +extern void *mempcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(mempcpy) +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the length of S. */ +extern size_t strlen (__const char *__s) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strlen) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +extern size_t strnlen (__const char *__string, size_t __maxlen) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strnlen) +#endif + + +__BEGIN_NAMESPACE_STD +/* Return a string describing the meaning of the `errno' code in ERRNUM. */ +extern char *strerror (int __errnum) __THROW; +libc_hidden_proto(strerror) +__END_NAMESPACE_STD +#if defined __USE_XOPEN2K || defined __USE_MISC +/* Reentrant version of `strerror'. + There are 2 flavors of `strerror_r', GNU which returns the string + and may or may not use the supplied temporary buffer and POSIX one + which fills the string into the buffer. + To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L + without -D_GNU_SOURCE is needed, otherwise the GNU version is + preferred. */ +# if defined __USE_XOPEN2K && !defined __USE_GNU +/* Fill BUF with a string describing the meaning of the `errno' code in + ERRNUM. */ +extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (strerror_r, + (int __errnum, char *__buf, size_t __buflen), + __xpg_strerror_r) __nonnull ((2)); +# else +# define strerror_r __xpg_strerror_r +# endif +# else +/* If a temporary buffer is required, at most BUFLEN bytes of BUF will be + used. */ +extern char *__glibc_strerror_r (int __errnum, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +# ifdef __REDIRECT_NTH +extern char * __REDIRECT_NTH (strerror_r, + (int __errnum, char *__buf, size_t __buflen), + __glibc_strerror_r) __nonnull ((2)); +# else +# define strerror_r __glibc_strerror_r +# endif +# endif +#endif + +/* We define this function always since `bzero' is sometimes needed when + the namespace rules does not allow this. */ +#if 0 /* uClibc: disabled */ +extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1)); +#endif + +#ifdef __USE_BSD +# ifdef __UCLIBC_SUSV3_LEGACY__ +/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ +extern void bcopy (__const void *__src, void *__dest, size_t __n) + __THROW __nonnull ((1, 2)); + +/* Set N bytes of S to 0. */ +extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1)); + +/* Compare N bytes of S1 and S2 (same as memcmp). */ +extern int bcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Find the first occurrence of C in S (same as strchr). */ +extern char *index (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); + +/* Find the last occurrence of C in S (same as strrchr). */ +extern char *rindex (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +# else +# ifdef __UCLIBC_SUSV3_LEGACY_MACROS__ +/* bcopy/bzero/bcmp/index/rindex are marked LEGACY in SuSv3. + * They are replaced as proposed by SuSv3. Don't sync this part + * with glibc and keep it in sync with strings.h. */ + +# define bcopy(src,dest,n) (memmove((dest), (src), (n)), (void) 0) +# define bzero(s,n) (memset((s), '\0', (n)), (void) 0) +# define bcmp(s1,s2,n) memcmp((s1), (s2), (size_t)(n)) +# define index(s,c) strchr((s), (c)) +# define rindex(s,c) strrchr((s), (c)) +# endif +# endif + +/* Return the position of the first bit set in I, or 0 if none are set. + The least-significant bit is position 1, the most-significant 32. */ +extern int ffs (int __i) __THROW __attribute__ ((__const__)); +libc_hidden_proto(ffs) + +/* The following two functions are non-standard but necessary for non-32 bit + platforms. */ +#if 0 /*def __USE_GNU*/ +extern int ffsl (long int __l) __THROW __attribute__ ((__const__)); +# ifdef __GNUC__ +__extension__ extern int ffsll (long long int __ll) + __THROW __attribute__ ((__const__)); +# endif +# endif + +/* Compare S1 and S2, ignoring case. */ +extern int strcasecmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcasecmp) + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strncasecmp) +#endif /* Use BSD. */ + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* Again versions of a few functions which use the given locale instead + of the global one. */ +extern int strcasecmp_l (__const char *__s1, __const char *__s2, + __locale_t __loc) + __THROW __attribute_pure__ __nonnull ((1, 2, 3)); +libc_hidden_proto(strcasecmp_l) + +extern int strncasecmp_l (__const char *__s1, __const char *__s2, + size_t __n, __locale_t __loc) + __THROW __attribute_pure__ __nonnull ((1, 2, 4)); +libc_hidden_proto(strncasecmp_l) +#endif + +#ifdef __USE_BSD +/* Return the next DELIM-delimited token from *STRINGP, + terminating it with a '\0', and update *STRINGP to point past it. */ +extern char *strsep (char **__restrict __stringp, + __const char *__restrict __delim) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strsep) +#endif + +#ifdef __USE_GNU +/* Compare S1 and S2 as strings holding name & indices/version numbers. */ +#if 0 +extern int strverscmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strverscmp) +#endif + +/* Return a string describing the meaning of the signal number in SIG. */ +extern char *strsignal (int __sig) __THROW; +libc_hidden_proto(strsignal) + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +#if 0 /* uClibc: disabled */ +extern char *__stpcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +#endif +extern char *stpcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(stpcpy) + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +#if 0 /* uClibc: disabled */ +extern char *__stpncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +#endif +extern char *stpncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(stpncpy) + +#if 0 /* uClibc does not support strfry or memfrob. */ +/* Sautee STRING briskly. */ +extern char *strfry (char *__string) __THROW __nonnull ((1)); + +/* Frobnicate N bytes of S. */ +extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1)); +#endif + +# ifndef basename +/* Return the file name within directory of FILENAME. We don't + declare the function if the `basename' macro is available (defined + in ) which makes the XPG version of this function + available. */ +extern char *basename (__const char *__filename) __THROW __nonnull ((1)); +libc_hidden_proto(basename) +# endif +#endif + + +#ifdef __USE_BSD +/* Two OpenBSD extension functions. */ +extern size_t strlcat(char *__restrict dst, const char *__restrict src, + size_t n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strlcat) +extern size_t strlcpy(char *__restrict dst, const char *__restrict src, + size_t n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strlcpy) +#endif + +__END_DECLS + +#endif /* string.h */ diff --git a/include/strings.h b/include/strings.h new file mode 100644 index 0000000..550f4ab --- /dev/null +++ b/include/strings.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1991,92,96,97,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STRINGS_H +#define _STRINGS_H 1 + +/* We don't need and should not read this file if was already + read. The one exception being that if __USE_BSD isn't defined, then + these aren't defined in string.h, so we need to define them here. */ + +/* keep this file in sync w/ string.h, the glibc version is out of date */ + +#if !defined _STRING_H || !defined __USE_BSD + +# include +# define __need_size_t +# include + +__BEGIN_DECLS + +# ifdef __UCLIBC_SUSV3_LEGACY__ +/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ +extern void bcopy (__const void *__src, void *__dest, size_t __n) + __THROW __nonnull ((1, 2)); + +/* Set N bytes of S to 0. */ +extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1)); + +/* Compare N bytes of S1 and S2 (same as memcmp). */ +extern int bcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Find the first occurrence of C in S (same as strchr). */ +extern char *index (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); + +/* Find the last occurrence of C in S (same as strrchr). */ +extern char *rindex (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +# else +# ifdef __UCLIBC_SUSV3_LEGACY_MACROS__ +/* bcopy/bzero/bcmp/index/rindex are marked LEGACY in SuSv3. + * They are replaced as proposed by SuSv3. Don't sync this part + * with glibc and keep it in sync with string.h. */ + +# define bcopy(src,dest,n) (memmove((dest), (src), (n)), (void) 0) +# define bzero(s,n) (memset((s), '\0', (n)), (void) 0) +# define bcmp(s1,s2,n) memcmp((s1), (s2), (size_t)(n)) +# define index(s,c) strchr((s), (c)) +# define rindex(s,c) strrchr((s), (c)) +# endif +# endif + +/* Return the position of the first bit set in I, or 0 if none are set. + The least-significant bit is position 1, the most-significant 32. */ +extern int ffs (int __i) __THROW __attribute__ ((__const__)); + +/* The following two functions are non-standard but necessary for non-32 bit + platforms. */ +#if 0 /*def __USE_GNU*/ +extern int ffsl (long int __l) __THROW __attribute__ ((__const__)); +# ifdef __GNUC__ +__extension__ extern int ffsll (long long int __ll) + __THROW __attribute__ ((__const__)); +# endif +# endif + +/* Compare S1 and S2, ignoring case. */ +extern int strcasecmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +__END_DECLS + + +#ifdef UCLIBC_INTERNAL +#error " should not be included from libc." +#endif + + +#endif /* string.h */ + +#endif /* strings.h */ diff --git a/include/sys/bitypes.h b/include/sys/bitypes.h new file mode 100644 index 0000000..3a9860f --- /dev/null +++ b/include/sys/bitypes.h @@ -0,0 +1,3 @@ +/* The GNU defines all the necessary types. */ + +#include diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h new file mode 100644 index 0000000..588c1eb --- /dev/null +++ b/include/sys/cdefs.h @@ -0,0 +1,358 @@ +/* Copyright (C) 1992-2001, 2002, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_CDEFS_H +#define _SYS_CDEFS_H 1 + +/* We are almost always included from features.h. */ +#ifndef _FEATURES_H +# include +#endif + +/* The GNU libc does not support any K&R compilers or the traditional mode + of ISO C compilers anymore. Check for some of the combinations not + anymore supported. */ +#if defined __GNUC__ && !defined __STDC__ +# error "You need a ISO C conforming compiler to use the glibc headers" +#endif + +/* Some user header file might have defined this before. */ +#undef __P +#undef __PMT + +#ifdef __GNUC__ + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions + as non-throwing using a function attribute since programs can use + the -fexceptions options for C code as well. */ +# if !defined __cplusplus && __GNUC_PREREQ (3, 3) +# define __THROW __attribute__ ((__nothrow__)) +# define __NTH(fct) __attribute__ ((__nothrow__)) fct +# else +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# define __NTH(fct) fct throw () +# else +# define __THROW +# define __NTH(fct) fct +# endif +# endif + +#else /* Not GCC. */ + +# define __inline /* No inline functions. */ + +# define __THROW +# define __NTH(fct) fct + +# define __const const +# define __signed signed +# define __volatile volatile + +#endif /* GCC. */ + +/* These two macros are not used in glibc anymore. They are kept here + only because some other projects expect the macros to be defined. */ +#define __P(args) args +#define __PMT(args) args + +/* For these things, GCC behaves the ANSI way normally, + and the non-ANSI way under -traditional. */ + +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +/* This is not a typedef so `const __ptr_t' does the right thing. */ +#define __ptr_t void * +#define __long_double_t long double + + +/* C++ needs to know that types and declarations are C, not C++. */ +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + + +/* The standard library needs the functions from the ISO C90 standard + in the std namespace. At the same time we want to be safe for + future changes and we include the ISO C99 code in the non-standard + namespace __c99. The C++ wrapper header take case of adding the + definitions to the global namespace. */ +#if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES +# define __BEGIN_NAMESPACE_STD namespace std { +# define __END_NAMESPACE_STD } +# define __USING_NAMESPACE_STD(name) using std::name; +# define __BEGIN_NAMESPACE_C99 namespace __c99 { +# define __END_NAMESPACE_C99 } +# define __USING_NAMESPACE_C99(name) using __c99::name; +#else +/* For compatibility we do not add the declarations into any + namespace. They will end up in the global namespace which is what + old code expects. */ +# define __BEGIN_NAMESPACE_STD +# define __END_NAMESPACE_STD +# define __USING_NAMESPACE_STD(name) +# define __BEGIN_NAMESPACE_C99 +# define __END_NAMESPACE_C99 +# define __USING_NAMESPACE_C99(name) +#endif + + +/* Support for bounded pointers. */ +#ifndef __BOUNDED_POINTERS__ +# define __bounded /* nothing */ +# define __unbounded /* nothing */ +# define __ptrvalue /* nothing */ +#endif + + +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) + +#if __GNUC_PREREQ (4,3) +# define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) +# define __warnattr(msg) __attribute__((__warning__ (msg))) +# define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) +#else +# define __warndecl(name, msg) extern void name (void) +# define __warnattr(msg) +# define __errordecl(name, msg) extern void name (void) +#endif + +/* Support for flexible arrays. */ +#if __GNUC_PREREQ (2,97) +/* GCC 2.97 supports C99 flexible array members. */ +# define __flexarr [] +#else +# ifdef __GNUC__ +# define __flexarr [0] +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __flexarr [] +# else +/* Some other non-C99 compiler. Approximate with [1]. */ +# define __flexarr [1] +# endif +# endif +#endif + + +/* __asm__ ("xyz") is used throughout the headers to rename functions + at the assembly language level. This is wrapped by the __REDIRECT + macro, in order to support compilers that can do this some other + way. When compilers don't support asm-names at all, we have to do + preprocessor tricks instead (which don't have exactly the right + semantics, but it's the best we can do). + + Example: + int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ + +#if defined __GNUC__ && __GNUC__ >= 2 + +# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) +# ifdef __cplusplus +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __THROW __asm__ (__ASMNAME (#alias)) +# else +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROW +# endif +# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) +# define __ASMNAME2(prefix, cname) __STRING (prefix) cname + +/* +#elif __SOME_OTHER_COMPILER__ + +# define __REDIRECT(name, proto, alias) name proto; \ + _Pragma("let " #name " = " #alias) +*/ +#endif + +/* GCC has various useful declarations that can be made with the + `__attribute__' syntax. All of the ways we use this do fine if + they are omitted for compilers that don't understand it. */ +#if !defined __GNUC__ || __GNUC__ < 2 +# define __attribute__(xyz) /* Ignore */ +#endif + +/* We make this a no-op unless it can be used as both a variable and + a type attribute. gcc 2.8 is known to support both. */ +#if __GNUC_PREREQ (2,8) +# define __attribute_aligned__(size) __attribute__ ((__aligned__ (size))) +#else +# define __attribute_aligned__(size) /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `malloc' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_malloc__ __attribute__ ((__malloc__)) +#else +# define __attribute_malloc__ /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `pure' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_pure__ __attribute__ ((__pure__)) +#else +# define __attribute_pure__ /* Ignore */ +#endif + +/* At some point during the gcc 3.1 development the `used' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (3,1) +# define __attribute_used__ __attribute__ ((__used__)) +# define __attribute_noinline__ __attribute__ ((__noinline__)) +#else +# define __attribute_used__ __attribute__ ((__unused__)) +# define __attribute_noinline__ /* Ignore */ +#endif + +/* gcc allows marking deprecated functions. */ +#if __GNUC_PREREQ (3,2) && !defined(__UCLIBC_HIDE_DEPRECATED__) +# define __attribute_deprecated__ __attribute__ ((__deprecated__)) +#else +# define __attribute_deprecated__ /* Ignore */ +#endif + +/* At some point during the gcc 2.8 development the `format_arg' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. + If several `format_arg' attributes are given for the same function, in + gcc-3.0 and older, all but the last one are ignored. In newer gccs, + all designated arguments are considered. */ +#if __GNUC_PREREQ (2,8) +# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) +#else +# define __attribute_format_arg__(x) /* Ignore */ +#endif + +/* At some point during the gcc 2.97 development the `strfmon' format + attribute for functions was introduced. We don't want to use it + unconditionally (although this would be possible) since it + generates warnings. */ +#if __GNUC_PREREQ (2,97) +# define __attribute_format_strfmon__(a,b) \ + __attribute__ ((__format__ (__strfmon__, a, b))) +#else +# define __attribute_format_strfmon__(a,b) /* Ignore */ +#endif + +/* The nonull function attribute allows to mark pointer parameters which + must not be NULL. */ +#if __GNUC_PREREQ (3,3) +# define __nonnull(params) __attribute__ ((__nonnull__ params)) +#else +# define __nonnull(params) +#endif + +/* If fortification mode, we warn about unused results of certain + function calls which can lead to problems. */ +#if __GNUC_PREREQ (3,4) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# if __USE_FORTIFY_LEVEL > 0 +# define __wur __attribute_warn_unused_result__ +# endif +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif +#ifndef __wur +# define __wur /* Ignore */ +#endif + +/* Forces a function to be always inlined. */ +#if __GNUC_PREREQ (3,2) +# define __always_inline __inline __attribute__ ((__always_inline__)) +#else +# define __always_inline __inline +#endif + +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. + For -std=gnu99, forcing gnu_inline attribute does not change behavior, + but may silence spurious warnings (such as in GCC 4.2). */ +#if !defined __cplusplus || __GNUC_PREREQ (4,3) +# if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# if __GNUC_PREREQ (4,3) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__, __artificial__)) +# else +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# endif +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +#endif + +/* GCC 4.3 and above allow passing all anonymous arguments of an + __extern_always_inline function to some other vararg function. */ +#if __GNUC_PREREQ (4,3) +# define __va_arg_pack() __builtin_va_arg_pack () +# define __va_arg_pack_len() __builtin_va_arg_pack_len () +#endif + +/* It is possible to compile containing GCC extensions even if GCC is + run in pedantic mode if the uses are carefully marked using the + `__extension__' keyword. But this is not generally available before + version 2.8. */ +#if !__GNUC_PREREQ (2,8) +# define __extension__ /* Ignore */ +#endif + +/* __restrict is known in EGCS 1.2 and above. */ +#if !__GNUC_PREREQ (2,92) +# define __restrict /* Ignore */ +#endif + +/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is + array_name[restrict] + GCC 3.1 supports this. */ +#if __GNUC_PREREQ (3,1) && !defined __GNUG__ +# define __restrict_arr __restrict +#else +# ifdef __GNUC__ +# define __restrict_arr /* Not supported in old GCC. */ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict_arr restrict +# else +/* Some other non-C99 compiler. */ +# define __restrict_arr /* Not supported. */ +# endif +# endif +#endif + +#endif /* sys/cdefs.h */ diff --git a/include/sys/dir.h b/include/sys/dir.h new file mode 100644 index 0000000..2611d6c --- /dev/null +++ b/include/sys/dir.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DIR_H +#define _SYS_DIR_H 1 + +#include + +#include + +#define direct dirent + +#endif /* sys/dir.h */ diff --git a/include/sys/errno.h b/include/sys/errno.h new file mode 100644 index 0000000..339f4fc --- /dev/null +++ b/include/sys/errno.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/fcntl.h b/include/sys/fcntl.h new file mode 100644 index 0000000..cd30455 --- /dev/null +++ b/include/sys/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/file.h b/include/sys/file.h new file mode 100644 index 0000000..93b3635 --- /dev/null +++ b/include/sys/file.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FILE_H +#define _SYS_FILE_H 1 + +#include + +#ifndef _FCNTL_H +# include +#endif + +__BEGIN_DECLS + + +/* Alternate names for values for the WHENCE argument to `lseek'. + These are the same as SEEK_SET, SEEK_CUR, and SEEK_END, respectively. */ +#ifndef L_SET +# define L_SET 0 /* Seek from beginning of file. */ +# define L_INCR 1 /* Seek from current position. */ +# define L_XTND 2 /* Seek from end of file. */ +#endif + + +/* Operations for the `flock' call. */ +#define LOCK_SH 1 /* Shared lock. */ +#define LOCK_EX 2 /* Exclusive lock. */ +#define LOCK_UN 8 /* Unlock. */ + +/* Can be OR'd in to one of the above. */ +#define LOCK_NB 4 /* Don't block when locking. */ + + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +extern int flock (int __fd, int __operation) __THROW; + + +__END_DECLS + +#endif /* sys/file.h */ diff --git a/include/sys/fsuid.h b/include/sys/fsuid.h new file mode 100644 index 0000000..4ecb199 --- /dev/null +++ b/include/sys/fsuid.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Change uid used for file access control to UID, without affecting + other privileges (such as who can send signals at the process). */ +extern int setfsuid (__uid_t __uid) __THROW; + +/* Ditto for group id. */ +extern int setfsgid (__gid_t __gid) __THROW; + +__END_DECLS + +#endif /* fsuid.h */ diff --git a/include/sys/ioctl.h b/include/sys/ioctl.h new file mode 100644 index 0000000..6d8a0f4 --- /dev/null +++ b/include/sys/ioctl.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H 1 + +#include + +__BEGIN_DECLS + +/* Get the list of `ioctl' requests and related constants. */ +#include + +/* Define some types used by `ioctl' requests. */ +#include + +/* On a Unix system, the system probably defines some of + the symbols we define in (usually with the same + values). The code to generate has omitted these + symbols to avoid the conflict, but a Unix program expects + to define them, so we must include here. */ +#include + +/* Perform the I/O control operation specified by REQUEST on FD. + One argument may follow; its presence and type depend on REQUEST. + Return value depends on REQUEST. Usually -1 indicates error. */ +extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; + +__END_DECLS + +#endif /* sys/ioctl.h */ diff --git a/include/sys/ipc.h b/include/sys/ipc.h new file mode 100644 index 0000000..42806db --- /dev/null +++ b/include/sys/ipc.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +#define _SYS_IPC_H 1 + +#include + +#if !defined __USE_SVID && !defined __USE_XOPEN && __GNUC__ >= 2 +# warning "Files using this header must be compiled with _SVID_SOURCE or _XOPEN_SOURCE" +#endif + +/* Get system dependent definition of `struct ipc_perm' and more. */ +#include + +#ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +#endif + +#ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#ifndef __key_t_defined +typedef __key_t key_t; +# define __key_t_defined +#endif + +__BEGIN_DECLS + +/* Generates key for System V style IPC. */ +extern key_t ftok (__const char *__pathname, int __proj_id) __THROW; + +__END_DECLS + +#endif /* sys/ipc.h */ diff --git a/include/sys/kd.h b/include/sys/kd.h new file mode 100644 index 0000000..d459c07 --- /dev/null +++ b/include/sys/kd.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_KD_H +#define _SYS_KD_H 1 + +/* Make sure the header is not loaded. */ +#ifndef _LINUX_TYPES_H +# define _LINUX_TYPES_H 1 +# define __undef_LINUX_TYPES_H +#endif + +#include + +#ifdef __undef_LINUX_TYPES_H +# undef _LINUX_TYPES_H +# undef __undef_LINUX_TYPES_H +#endif + +#endif /* sys/kd.h */ diff --git a/include/sys/kdaemon.h b/include/sys/kdaemon.h new file mode 100644 index 0000000..61491f9 --- /dev/null +++ b/include/sys/kdaemon.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Interfaces to control the various kernel daemons. */ + +#ifndef _SYS_KDAEMON_H + +#define _SYS_KDAEMON_H 1 +#include + +__BEGIN_DECLS + +/* Start, flush, or tune the kernel's buffer flushing daemon. */ +extern int bdflush (int __func, long int __data) __THROW; + +__END_DECLS + +#endif /* _SYS_KDAEMON_H */ diff --git a/include/sys/klog.h b/include/sys/klog.h new file mode 100644 index 0000000..35f5fe4 --- /dev/null +++ b/include/sys/klog.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_KLOG_H + +#define _SYS_KLOG_H 1 +#include + +__BEGIN_DECLS + +/* Control the kernel's logging facility. This corresponds exactly to + the kernel's syslog system call, but that name is easily confused + with the user-level syslog facility, which is something completely + different. */ +extern int klogctl (int __type, char *__bufp, int __len) __THROW; + +__END_DECLS + +#endif /* _SYS_KLOG_H */ diff --git a/include/sys/mman.h b/include/sys/mman.h new file mode 100644 index 0000000..10471e6 --- /dev/null +++ b/include/sys/mman.h @@ -0,0 +1,175 @@ +/* Definitions for BSD-style memory management. + Copyright (C) 1994-2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H 1 + +#include +#include +#define __need_size_t +#include + +#ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#include + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((void *) -1) + +__BEGIN_DECLS +/* Map addresses starting near ADDR and extending for LEN bytes. from + OFFSET into the file FD describes according to PROT and FLAGS. If ADDR + is nonzero, it is the desired mapping address. If the MAP_FIXED bit is + set in FLAGS, the mapping will be at ADDR exactly (which must be + page-aligned); otherwise the system chooses a convenient nearby address. + The return value is the actual mapping address chosen or MAP_FAILED + for errors (in which case `errno' is set). A successful `mmap' call + deallocates any previous mapping for the affected region. */ + +#ifndef __USE_FILE_OFFSET64 +extern void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset) __THROW; +#else +# ifdef __REDIRECT +extern void * __REDIRECT (mmap, + (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off64_t __offset), + mmap64); +# else +# define mmap mmap64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern void *mmap64 (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off64_t __offset) __THROW; +#endif + +/* Deallocate any mapping for the region starting at ADDR and extending LEN + bytes. Returns 0 if successful, -1 for errors (and sets errno). */ +extern int munmap (void *__addr, size_t __len) __THROW; + +/* Change the memory protection of the region starting at ADDR and + extending LEN bytes to PROT. Returns 0 if successful, -1 for errors + (and sets errno). */ +extern int mprotect (void *__addr, size_t __len, int __prot) __THROW; + +#ifdef __ARCH_USE_MMU__ + +/* Synchronize the region starting at ADDR and extending LEN bytes with the + file it maps. Filesystem operations on a file being mapped are + unpredictable before this is done. Flags are from the MS_* set. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int msync (void *__addr, size_t __len, int __flags); + +#else + +/* On no-mmu systems you can't have real private mappings. */ +static __inline__ int msync (void *__addr, size_t __len, int __flags) { return 0; } + +#endif + +#if defined __USE_BSD && defined __UCLIBC_LINUX_SPECIFIC__ +/* Advise the system about particular usage patterns the program follows + for the region starting at ADDR and extending LEN bytes. */ +extern int madvise (void *__addr, size_t __len, int __advice) __THROW; +#endif +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* This is the POSIX name for this function. */ +extern int posix_madvise (void *__addr, size_t __len, int __advice) __THROW; +#endif + +#if defined __UCLIBC_HAS_REALTIME__ +# ifdef __ARCH_USE_MMU__ + +/* Guarantee all whole pages mapped by the range [ADDR,ADDR+LEN) to + be memory resident. */ +extern int mlock (__const void *__addr, size_t __len) __THROW; + +/* Unlock whole pages previously mapped by the range [ADDR,ADDR+LEN). */ +extern int munlock (__const void *__addr, size_t __len) __THROW; + +/* Cause all currently mapped pages of the process to be memory resident + until unlocked by a call to the `munlockall', until the process exits, + or until the process calls `execve'. */ +extern int mlockall (int __flags) __THROW; + +/* All currently mapped pages of the process' address space become + unlocked. */ +extern int munlockall (void) __THROW; + +#else + +/* On no-mmu systems, memory cannot be swapped out, so + * these functions will always succeed. */ +static __inline__ int mlock (__const void *__addr, size_t __len) { return 0; } +static __inline__ int munlock (__const void *__addr, size_t __len) { return 0; } +static __inline__ int mlockall (int __flags) { return 0; } +static __inline__ int munlockall (void) { return 0; } +#endif +#endif /* __UCLIBC_HAS_REALTIME__ */ + +#if defined __USE_MISC && defined __UCLIBC_BSD_SPECIFIC__ +/* mincore returns the memory residency status of the pages in the + current process's address space specified by [start, start + len). + The status is returned in a vector of bytes. The least significant + bit of each byte is 1 if the referenced page is in memory, otherwise + it is zero. */ +extern int mincore (void *__start, size_t __len, unsigned char *__vec) + __THROW; +#endif + +#ifdef __USE_GNU +/* Remap pages mapped by the range [ADDR,ADDR+OLD_LEN) to new length + NEW_LEN. If MREMAP_MAYMOVE is set in FLAGS the returned address + may differ from ADDR. If MREMAP_FIXED is set in FLAGS the function + takes another paramter which is a fixed address at which the block + resides after a successful call. */ +extern void *mremap (void *__addr, size_t __old_len, size_t __new_len, + int __flags, ...) __THROW; + +/* Remap arbitrary pages of a shared backing store within an existing + VMA. */ +extern int remap_file_pages (void *__start, size_t __size, int __prot, + size_t __pgoff, int __flags) __THROW; +#endif + + +/* Open shared memory segment. */ +extern int shm_open (__const char *__name, int __oflag, mode_t __mode); + +/* Remove shared memory segment. */ +extern int shm_unlink (__const char *__name); + +__END_DECLS + +#endif /* sys/mman.h */ diff --git a/include/sys/mount.h b/include/sys/mount.h new file mode 100644 index 0000000..b305549 --- /dev/null +++ b/include/sys/mount.h @@ -0,0 +1,119 @@ +/* Header file for mounting/unmount Linux filesystems. + Copyright (C) 1996,1997,1998,1999,2000,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is taken from /usr/include/linux/fs.h. */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H 1 + +#include +#include + +#define BLOCK_SIZE 1024 +#define BLOCK_SIZE_BITS 10 + + +/* These are the fs-independent mount-flags: up to 16 flags are + supported */ +enum +{ + MS_RDONLY = 1, /* Mount read-only. */ +#define MS_RDONLY MS_RDONLY + MS_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define MS_NOSUID MS_NOSUID + MS_NODEV = 4, /* Disallow access to device special files. */ +#define MS_NODEV MS_NODEV + MS_NOEXEC = 8, /* Disallow program execution. */ +#define MS_NOEXEC MS_NOEXEC + MS_SYNCHRONOUS = 16, /* Writes are synced at once. */ +#define MS_SYNCHRONOUS MS_SYNCHRONOUS + MS_REMOUNT = 32, /* Alter flags of a mounted FS. */ +#define MS_REMOUNT MS_REMOUNT + MS_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +#define MS_MANDLOCK MS_MANDLOCK + S_WRITE = 128, /* Write on file/directory/symlink. */ +#define S_WRITE S_WRITE + S_APPEND = 256, /* Append-only file. */ +#define S_APPEND S_APPEND + S_IMMUTABLE = 512, /* Immutable file. */ +#define S_IMMUTABLE S_IMMUTABLE + MS_NOATIME = 1024, /* Do not update access times. */ +#define MS_NOATIME MS_NOATIME + MS_NODIRATIME = 2048, /* Do not update directory access times. */ +#define MS_NODIRATIME MS_NODIRATIME + MS_BIND = 4096, /* Bind directory at different place. */ +#define MS_BIND MS_BIND +}; + +/* Flags that can be altered by MS_REMOUNT */ +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME \ + |MS_NODIRATIME) + + +/* Magic mount flag number. Has to be or-ed to the flag values. */ + +#define MS_MGC_VAL 0xc0ed0000 /* Magic flag number to indicate "new" flags */ +#define MS_MGC_MSK 0xffff0000 /* Magic flag number mask */ + + +/* The read-only stuff doesn't really belong here, but any other place + is probably as bad and I don't want to create yet another include + file. */ + +#define BLKROSET _IO(0x12, 93) /* Set device read-only (0 = read-write). */ +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ +#define BLKRRPART _IO(0x12, 95) /* Re-read partition table. */ +#define BLKGETSIZE _IO(0x12, 96) /* Return device size. */ +#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */ +#define BLKRASET _IO(0x12, 98) /* Set read ahead for block device. */ +#define BLKRAGET _IO(0x12, 99) /* Get current read ahead setting. */ +#define BLKFRASET _IO(0x12,100) /* Set filesystem read-ahead. */ +#define BLKFRAGET _IO(0x12,101) /* Get filesystem read-ahead. */ +#define BLKSECTSET _IO(0x12,102) /* Set max sectors per request. */ +#define BLKSECTGET _IO(0x12,103) /* Get max sectors per request. */ +#define BLKSSZGET _IO(0x12,104) /* Get block device sector size. */ +#define BLKBSZGET _IOR(0x12,112,size_t) +#define BLKBSZSET _IOW(0x12,113,size_t) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size. */ + + +/* Possible value for FLAGS parameter of `umount2'. */ +enum +{ + MNT_FORCE = 1 /* Force unmounting. */ +#define MNT_FORCE MNT_FORCE +}; + + +__BEGIN_DECLS + +/* Mount a filesystem. */ +extern int mount (__const char *__special_file, __const char *__dir, + __const char *__fstype, unsigned long int __rwflag, + __const void *__data) __THROW; + +/* Unmount a filesystem. */ +extern int umount (__const char *__special_file) __THROW; + +/* Unmount a filesystem. Force unmounting if FLAGS is set to MNT_FORCE. */ +extern int umount2 (__const char *__special_file, int __flags) __THROW; + +__END_DECLS + +#endif /* _SYS_MOUNT_H */ diff --git a/include/sys/msg.h b/include/sys/msg.h new file mode 100644 index 0000000..1fd64b2 --- /dev/null +++ b/include/sys/msg.h @@ -0,0 +1,81 @@ +/* Copyright (C) 1995,1996,1997,1999,2000,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +#define _SYS_MSG_H + +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct msqid_ds' and more. */ +#include + +/* Define types required by the standard. */ +#define __need_time_t +#include + +#ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +/* The following System V style IPC functions implement a message queue + system. The definition is found in XPG2. */ + +#ifdef __USE_GNU +/* Template for struct to be used as argument for `msgsnd' and `msgrcv'. */ +struct msgbuf + { + long int mtype; /* type of received/sent message */ + char mtext[1]; /* text of the message */ + }; +#endif + + +__BEGIN_DECLS + +/* Message queue control operation. */ +extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW; + +/* Get messages queue. */ +extern int msgget (key_t __key, int __msgflg) __THROW; + +/* Receive message from message queue. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int msgrcv (int __msqid, void *__msgp, size_t __msgsz, + long int __msgtyp, int __msgflg); + +/* Send message to message queue. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz, + int __msgflg); + +__END_DECLS + +#endif /* sys/msg.h */ diff --git a/include/sys/mtio.h b/include/sys/mtio.h new file mode 100644 index 0000000..51fa550 --- /dev/null +++ b/include/sys/mtio.h @@ -0,0 +1,277 @@ +/* Structures and definitions for magnetic tape I/O control commands. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by H. Bergman . */ + +#ifndef _SYS_MTIO_H +#define _SYS_MTIO_H 1 + +/* Get necessary definitions from system and kernel headers. */ +#include +#include + + +/* Structure for MTIOCTOP - magnetic tape operation command. */ +struct mtop + { + short int mt_op; /* Operations defined below. */ + int mt_count; /* How many of them. */ + }; +#define _IOT_mtop /* Hurd ioctl type field. */ \ + _IOT (_IOTS (short), 1, _IOTS (int), 1, 0, 0) + +/* Magnetic Tape operations [Not all operations supported by all drivers]. */ +#define MTRESET 0 /* +reset drive in case of problems. */ +#define MTFSF 1 /* Forward space over FileMark, + * position at first record of next file. */ +#define MTBSF 2 /* Backward space FileMark (position before FM). */ +#define MTFSR 3 /* Forward space record. */ +#define MTBSR 4 /* Backward space record. */ +#define MTWEOF 5 /* Write an end-of-file record (mark). */ +#define MTREW 6 /* Rewind. */ +#define MTOFFL 7 /* Rewind and put the drive offline (eject?). */ +#define MTNOP 8 /* No op, set status only (read with MTIOCGET). */ +#define MTRETEN 9 /* Retension tape. */ +#define MTBSFM 10 /* +backward space FileMark, position at FM. */ +#define MTFSFM 11 /* +forward space FileMark, position at FM. */ +#define MTEOM 12 /* Goto end of recorded media (for appending files). + MTEOM positions after the last FM, ready for + appending another file. */ +#define MTERASE 13 /* Erase tape -- be careful! */ + +#define MTRAS1 14 /* Run self test 1 (nondestructive). */ +#define MTRAS2 15 /* Run self test 2 (destructive). */ +#define MTRAS3 16 /* Reserved for self test 3. */ + +#define MTSETBLK 20 /* Set block length (SCSI). */ +#define MTSETDENSITY 21 /* Set tape density (SCSI). */ +#define MTSEEK 22 /* Seek to block (Tandberg, etc.). */ +#define MTTELL 23 /* Tell block (Tandberg, etc.). */ +#define MTSETDRVBUFFER 24 /* Set the drive buffering according to SCSI-2. + Ordinary buffered operation with code 1. */ +#define MTFSS 25 /* Space forward over setmarks. */ +#define MTBSS 26 /* Space backward over setmarks. */ +#define MTWSM 27 /* Write setmarks. */ + +#define MTLOCK 28 /* Lock the drive door. */ +#define MTUNLOCK 29 /* Unlock the drive door. */ +#define MTLOAD 30 /* Execute the SCSI load command. */ +#define MTUNLOAD 31 /* Execute the SCSI unload command. */ +#define MTCOMPRESSION 32/* Control compression with SCSI mode page 15. */ +#define MTSETPART 33 /* Change the active tape partition. */ +#define MTMKPART 34 /* Format the tape with one or two partitions. */ + +/* structure for MTIOCGET - mag tape get status command */ + +struct mtget + { + long int mt_type; /* Type of magtape device. */ + long int mt_resid; /* Residual count: (not sure) + number of bytes ignored, or + number of files not skipped, or + number of records not skipped. */ + /* The following registers are device dependent. */ + long int mt_dsreg; /* Status register. */ + long int mt_gstat; /* Generic (device independent) status. */ + long int mt_erreg; /* Error register. */ + /* The next two fields are not always used. */ + __daddr_t mt_fileno; /* Number of current file on tape. */ + __daddr_t mt_blkno; /* Current block number. */ + }; +#define _IOT_mtget /* Hurd ioctl type field. */ \ + _IOT (_IOTS (long), 7, 0, 0, 0, 0) + + +/* Constants for mt_type. Not all of these are supported, and + these are not all of the ones that are supported. */ +#define MT_ISUNKNOWN 0x01 +#define MT_ISQIC02 0x02 /* Generic QIC-02 tape streamer. */ +#define MT_ISWT5150 0x03 /* Wangtek 5150EQ, QIC-150, QIC-02. */ +#define MT_ISARCHIVE_5945L2 0x04 /* Archive 5945L-2, QIC-24, QIC-02?. */ +#define MT_ISCMSJ500 0x05 /* CMS Jumbo 500 (QIC-02?). */ +#define MT_ISTDC3610 0x06 /* Tandberg 6310, QIC-24. */ +#define MT_ISARCHIVE_VP60I 0x07 /* Archive VP60i, QIC-02. */ +#define MT_ISARCHIVE_2150L 0x08 /* Archive Viper 2150L. */ +#define MT_ISARCHIVE_2060L 0x09 /* Archive Viper 2060L. */ +#define MT_ISARCHIVESC499 0x0A /* Archive SC-499 QIC-36 controller. */ +#define MT_ISQIC02_ALL_FEATURES 0x0F /* Generic QIC-02 with all features. */ +#define MT_ISWT5099EEN24 0x11 /* Wangtek 5099-een24, 60MB, QIC-24. */ +#define MT_ISTEAC_MT2ST 0x12 /* Teac MT-2ST 155mb drive, + Teac DC-1 card (Wangtek type). */ +#define MT_ISEVEREX_FT40A 0x32 /* Everex FT40A (QIC-40). */ +#define MT_ISDDS1 0x51 /* DDS device without partitions. */ +#define MT_ISDDS2 0x52 /* DDS device with partitions. */ +#define MT_ISSCSI1 0x71 /* Generic ANSI SCSI-1 tape unit. */ +#define MT_ISSCSI2 0x72 /* Generic ANSI SCSI-2 tape unit. */ + +/* QIC-40/80/3010/3020 ftape supported drives. + 20bit vendor ID + 0x800000 (see vendors.h in ftape distribution). */ +#define MT_ISFTAPE_UNKNOWN 0x800000 /* obsolete */ +#define MT_ISFTAPE_FLAG 0x800000 + +struct mt_tape_info + { + long int t_type; /* Device type id (mt_type). */ + char *t_name; /* Descriptive name. */ + }; + +#define MT_TAPE_INFO \ + { \ + {MT_ISUNKNOWN, "Unknown type of tape device"}, \ + {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \ + {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \ + {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \ + {MT_ISCMSJ500, "CMS Jumbo 500"}, \ + {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \ + {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \ + {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \ + {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \ + {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \ + {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \ + {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \ + {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \ + {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ + {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ + {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ + {0, NULL} \ + } + + +/* Structure for MTIOCPOS - mag tape get position command. */ + +struct mtpos + { + long int mt_blkno; /* Current block number. */ + }; +#define _IOT_mtpos /* Hurd ioctl type field. */ \ + _IOT_SIMPLE (long) + + +/* Structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended + as an interim solution for QIC-02 until DDI is fully implemented. */ +struct mtconfiginfo + { + long int mt_type; /* Drive type. */ + long int ifc_type; /* Interface card type. */ + unsigned short int irqnr; /* IRQ number to use. */ + unsigned short int dmanr; /* DMA channel to use. */ + unsigned short int port; /* IO port base address. */ + + unsigned long int debug; /* Debugging flags. */ + + unsigned have_dens:1; + unsigned have_bsf:1; + unsigned have_fsr:1; + unsigned have_bsr:1; + unsigned have_eod:1; + unsigned have_seek:1; + unsigned have_tell:1; + unsigned have_ras1:1; + unsigned have_ras2:1; + unsigned have_ras3:1; + unsigned have_qfa:1; + + unsigned pad1:5; + char reserved[10]; + }; +#define _IOT_mtconfiginfo /* Hurd ioctl type field. */ \ + _IOT (_IOTS (long), 2, _IOTS (short), 3, _IOTS (long), 1) /* XXX wrong */ + + +/* Magnetic tape I/O control commands. */ +#define MTIOCTOP _IOW('m', 1, struct mtop) /* Do a mag tape op. */ +#define MTIOCGET _IOR('m', 2, struct mtget) /* Get tape status. */ +#define MTIOCPOS _IOR('m', 3, struct mtpos) /* Get tape position.*/ + +/* The next two are used by the QIC-02 driver for runtime reconfiguration. + See tpqic02.h for struct mtconfiginfo. */ +#define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* Get tape config.*/ +#define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* Set tape config.*/ + +/* Generic Mag Tape (device independent) status macros for examining + mt_gstat -- HP-UX compatible. + There is room for more generic status bits here, but I don't + know which of them are reserved. At least three or so should + be added to make this really useful. */ +#define GMT_EOF(x) ((x) & 0x80000000) +#define GMT_BOT(x) ((x) & 0x40000000) +#define GMT_EOT(x) ((x) & 0x20000000) +#define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */ +#define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */ +#define GMT_WR_PROT(x) ((x) & 0x04000000) +/* #define GMT_ ? ((x) & 0x02000000) */ +#define GMT_ONLINE(x) ((x) & 0x01000000) +#define GMT_D_6250(x) ((x) & 0x00800000) +#define GMT_D_1600(x) ((x) & 0x00400000) +#define GMT_D_800(x) ((x) & 0x00200000) +/* #define GMT_ ? ((x) & 0x00100000) */ +/* #define GMT_ ? ((x) & 0x00080000) */ +#define GMT_DR_OPEN(x) ((x) & 0x00040000) /* Door open (no tape). */ +/* #define GMT_ ? ((x) & 0x00020000) */ +#define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* Immediate report mode.*/ +/* 16 generic status bits unused. */ + + +/* SCSI-tape specific definitions. Bitfield shifts in the status */ +#define MT_ST_BLKSIZE_SHIFT 0 +#define MT_ST_BLKSIZE_MASK 0xffffff +#define MT_ST_DENSITY_SHIFT 24 +#define MT_ST_DENSITY_MASK 0xff000000 + +#define MT_ST_SOFTERR_SHIFT 0 +#define MT_ST_SOFTERR_MASK 0xffff + +/* Bitfields for the MTSETDRVBUFFER ioctl. */ +#define MT_ST_OPTIONS 0xf0000000 +#define MT_ST_BOOLEANS 0x10000000 +#define MT_ST_SETBOOLEANS 0x30000000 +#define MT_ST_CLEARBOOLEANS 0x40000000 +#define MT_ST_WRITE_THRESHOLD 0x20000000 +#define MT_ST_DEF_BLKSIZE 0x50000000 +#define MT_ST_DEF_OPTIONS 0x60000000 + +#define MT_ST_BUFFER_WRITES 0x1 +#define MT_ST_ASYNC_WRITES 0x2 +#define MT_ST_READ_AHEAD 0x4 +#define MT_ST_DEBUGGING 0x8 +#define MT_ST_TWO_FM 0x10 +#define MT_ST_FAST_MTEOM 0x20 +#define MT_ST_AUTO_LOCK 0x40 +#define MT_ST_DEF_WRITES 0x80 +#define MT_ST_CAN_BSR 0x100 +#define MT_ST_NO_BLKLIMS 0x200 +#define MT_ST_CAN_PARTITIONS 0x400 +#define MT_ST_SCSI2LOGICAL 0x800 + +/* The mode parameters to be controlled. Parameter chosen with bits 20-28. */ +#define MT_ST_CLEAR_DEFAULT 0xfffff +#define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000) +#define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000) +#define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000) + +/* The offset for the arguments for the special HP changer load command. */ +#define MT_ST_HPLOADER_OFFSET 10000 + + +/* Specify default tape device. */ +#ifndef DEFTAPE +# define DEFTAPE "/dev/tape" +#endif + +#endif /* mtio.h */ diff --git a/include/sys/param.h b/include/sys/param.h new file mode 100644 index 0000000..0b0424e --- /dev/null +++ b/include/sys/param.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1995,1996,1997,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H 1 + +#include +#include +#include + +/* BSD names for some values. */ + +#define NBBY CHAR_BIT +#ifndef NGROUPS +# define NGROUPS NGROUPS_MAX +#endif +#define MAXSYMLINKS 20 +#define CANBSIZ MAX_CANON +#define NCARGS ARG_MAX +#define MAXPATHLEN PATH_MAX +/* The following is not really correct but it is a value we used for a + long time and which seems to be usable. People should not use NOFILE + anyway. */ +#define NOFILE 256 + + +#include + +/* Bit map related macros. */ +#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +# define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif +#ifdef __GNUC__ +# define roundup(x, y) (__builtin_constant_p (y) && powerof2 (y) \ + ? (((x) + (y) - 1) & ~((y) - 1)) \ + : ((((x) + ((y) - 1)) / (y)) * (y))) +#else +# define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +#endif +#define powerof2(x) ((((x) - 1) & (x)) == 0) + +/* Macros for min/max. */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +/* Unit of `st_blocks'. */ +#define DEV_BSIZE 512 + + +#endif /* sys/param.h */ diff --git a/include/sys/personality.h b/include/sys/personality.h new file mode 100644 index 0000000..154b113 --- /dev/null +++ b/include/sys/personality.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Taken verbatim from Linux 2.4 (include/linux/personality.h). */ + +#ifndef _SYS_PERSONALITY_H +#define _SYS_PERSONALITY_H 1 + +#include + +/* Flags for bug emulation. + These occupy the top three bytes. */ +enum + { + MMAP_PAGE_ZERO = 0x0100000, + ADDR_LIMIT_32BIT = 0x0800000, + SHORT_INODE = 0x1000000, + WHOLE_SECONDS = 0x2000000, + STICKY_TIMEOUTS = 0x4000000, + }; + +/* Personality types. + + These go in the low byte. Avoid using the top bit, it will + conflict with error returns. */ +enum + { + PER_LINUX = 0x0000, + PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, + PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, + PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, + PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, + PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, + PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, + PER_BSD = 0x0006, + PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, + PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, + PER_LINUX32 = 0x0008, + PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS, /* IRIX5 32-bit */ + PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS, /* IRIX6 new 32-bit */ + PER_IRIX64 = 0x000b | STICKY_TIMEOUTS, /* IRIX6 64-bit */ + PER_RISCOS = 0x000c, + PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, + PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_HPUX = 0x000f, + PER_OSF4 = 0x0010, + PER_MASK = 0x00ff, + }; + +__BEGIN_DECLS + +/* Set different ABIs (personalities). */ +extern int personality (unsigned long int __persona) __THROW; + +__END_DECLS + +#endif /* sys/personality.h */ diff --git a/include/sys/poll.h b/include/sys/poll.h new file mode 100644 index 0000000..a298dac --- /dev/null +++ b/include/sys/poll.h @@ -0,0 +1,76 @@ +/* Compatibility definitions for System V `poll' interface. + Copyright (C) 1994,1996-2001,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +#define _SYS_POLL_H 1 + +#include + +/* Get the platform dependent bits of `poll'. */ +#include +#ifdef __USE_GNU +/* Get the __sigset_t definition. */ +# include +/* Get the timespec definition. */ +# define __need_timespec +# include +/* get NULL definition. */ +# include +#endif + + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd + { + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ + }; + + +__BEGIN_DECLS + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Like poll, but before waiting the threads signal mask is replaced + with that specified in the fourth parameter. For better usability, + the timeout value is specified using a TIMESPEC object. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int ppoll (struct pollfd *__fds, nfds_t __nfds, + __const struct timespec *__timeout, + __const __sigset_t *__ss); +#endif + +__END_DECLS + +#endif /* sys/poll.h */ diff --git a/include/sys/queue.h b/include/sys/queue.h new file mode 100644 index 0000000..d62afcc --- /dev/null +++ b/include/sys/queue.h @@ -0,0 +1,618 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.68 2006/10/24 11:20:29 ru Exp $ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ + TRASHIT((elm)->field.stqe_next); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT((elm)->field.le_next); \ + TRASHIT((elm)->field.le_prev); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#ifdef __CC_SUPPORTS___INLINE + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !__CC_SUPPORTS___INLINE */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __CC_SUPPORTS___INLINE */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/include/sys/quota.h b/include/sys/quota.h new file mode 100644 index 0000000..a6afdbe --- /dev/null +++ b/include/sys/quota.h @@ -0,0 +1,158 @@ +/* This just represents the non-kernel parts of . + * + * here's the corresponding copyright: + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Version: $Id: quota.h,v 1.1 2002/01/03 04:00:09 andersen Exp $ + */ + +#ifndef _SYS_QUOTA_H +#define _SYS_QUOTA_H 1 + +#include +#include + +/* + * Convert diskblocks to blocks and the other way around. + * currently only to fool the BSD source. :-) + */ +#define dbtob(num) ((num) << 10) +#define btodb(num) ((num) >> 10) + +/* + * Convert count of filesystem blocks to diskquota blocks, meant + * for filesystems where i_blksize != BLOCK_SIZE + */ +#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) + +/* + * Definitions for disk quotas imposed on the average user + * (big brother finally hits Linux). + * + * The following constants define the amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +#define MAXQUOTAS 2 +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +/* + * Definitions for the default names of the quotas files. + */ +#define INITQFNAMES { \ + "user", /* USRQUOTA */ \ + "group", /* GRPQUOTA */ \ + "undefined", \ +}; + +#define QUOTAFILENAME "quota" +#define QUOTAGROUP "staff" + +#define NR_DQHASH 43 /* Just an arbitrary number any suggestions ? */ +#define NR_DQUOTS 256 /* Number of quotas active at one time */ + +/* + * Command definitions for the 'quotactl' system call. + * The commands are broken into a main command defined below + * and a subcommand that is used to convey the type of + * quota that is being manipulated (see above). + */ +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_QUOTAON 0x0100 /* enable quotas */ +#define Q_QUOTAOFF 0x0200 /* disable quotas */ +#define Q_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_SETQUOTA 0x0400 /* set limits and usage */ +#define Q_SETUSE 0x0500 /* set usage */ +#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ +#define Q_SETQLIM 0x0700 /* set limits */ +#define Q_GETSTATS 0x0800 /* get collected stats */ +#define Q_RSQUASH 0x1000 /* set root_squash option */ + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is an array of these structures + * indexed by user or group number. + */ +struct dqblk + { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ + }; + +/* + * Shorthand notation. + */ +#define dq_bhardlimit dq_dqb.dqb_bhardlimit +#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit +#define dq_curblocks dq_dqb.dqb_curblocks +#define dq_ihardlimit dq_dqb.dqb_ihardlimit +#define dq_isoftlimit dq_dqb.dqb_isoftlimit +#define dq_curinodes dq_dqb.dqb_curinodes +#define dq_btime dq_dqb.dqb_btime +#define dq_itime dq_dqb.dqb_itime + +#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) + +struct dqstats + { + u_int32_t lookups; + u_int32_t drops; + u_int32_t reads; + u_int32_t writes; + u_int32_t cache_hits; + u_int32_t pages_allocated; + u_int32_t allocated_dquots; + u_int32_t free_dquots; + u_int32_t syncs; + }; + +__BEGIN_DECLS + +extern int quotactl (int __cmd, const char *__special, int __id, + caddr_t __addr) __THROW; + +__END_DECLS + +#endif /* sys/quota.h */ diff --git a/include/sys/reboot.h b/include/sys/reboot.h new file mode 100644 index 0000000..2a719c7 --- /dev/null +++ b/include/sys/reboot.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file should define RB_* macros to be used as flag + bits in the argument to the `reboot' system call. */ + +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H 1 + +#include + +/* Perform a hard reset now. */ +#define RB_AUTOBOOT 0x01234567 + +/* Halt the system. */ +#define RB_HALT_SYSTEM 0xcdef0123 + +/* Enable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_ENABLE_CAD 0x89abcdef + +/* Disable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_DISABLE_CAD 0 + +/* Stop system and switch power off if possible. */ +#define RB_POWER_OFF 0x4321fedc + +__BEGIN_DECLS + +/* Reboot or halt the system. */ +extern int reboot (int __howto) __THROW; + +__END_DECLS + +#endif /* _SYS_REBOOT_H */ diff --git a/include/sys/resource.h b/include/sys/resource.h new file mode 100644 index 0000000..3912741 --- /dev/null +++ b/include/sys/resource.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1992,94,1996-2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H 1 + +#include + +/* Get the system-dependent definitions of structures and bit values. */ +#include + +#ifndef __id_t_defined +typedef __id_t id_t; +# define __id_t_defined +#endif + +__BEGIN_DECLS + +/* The X/Open standard defines that all the functions below must use + `int' as the type for the first argument. When we are compiling with + GNU extensions we change this slightly to provide better error + checking. */ +#if defined __USE_GNU && !defined __cplusplus +typedef enum __rlimit_resource __rlimit_resource_t; +typedef enum __rusage_who __rusage_who_t; +typedef enum __priority_which __priority_which_t; +#else +typedef int __rlimit_resource_t; +typedef int __rusage_who_t; +typedef int __priority_which_t; +#endif + +/* Put the soft and hard limits for RESOURCE in *RLIMITS. + Returns 0 if successful, -1 if not (and sets errno). */ +#ifndef __USE_FILE_OFFSET64 +extern int getrlimit (__rlimit_resource_t __resource, + struct rlimit *__rlimits) __THROW; +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (getrlimit, (__rlimit_resource_t __resource, + struct rlimit *__rlimits), getrlimit64); +# else +# define getrlimit getrlimit64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int getrlimit64 (__rlimit_resource_t __resource, + struct rlimit64 *__rlimits) __THROW; +#endif + +/* Set the soft and hard limits for RESOURCE to *RLIMITS. + Only the super-user can increase hard limits. + Return 0 if successful, -1 if not (and sets errno). */ +#ifndef __USE_FILE_OFFSET64 +extern int setrlimit (__rlimit_resource_t __resource, + __const struct rlimit *__rlimits) __THROW; +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (setrlimit, (__rlimit_resource_t __resource, + __const struct rlimit *__rlimits), + setrlimit64); +# else +# define setrlimit setrlimit64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int setrlimit64 (__rlimit_resource_t __resource, + __const struct rlimit64 *__rlimits) __THROW; +#endif + +/* Return resource usage information on process indicated by WHO + and put it in *USAGE. Returns 0 for success, -1 for failure. */ +extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __THROW; + +/* Return the highest priority of any process specified by WHICH and WHO + (see above); if WHO is zero, the current process, process group, or user + (as specified by WHO) is used. A lower priority number means higher + priority. Priorities range from PRIO_MIN to PRIO_MAX (above). */ +extern int getpriority (__priority_which_t __which, id_t __who) __THROW; + +/* Set the priority of all processes specified by WHICH and WHO (see above) + to PRIO. Returns 0 on success, -1 on errors. */ +extern int setpriority (__priority_which_t __which, id_t __who, int __prio) + __THROW; + +__END_DECLS + +#endif /* sys/resource.h */ diff --git a/include/sys/select.h b/include/sys/select.h new file mode 100644 index 0000000..2a40843 --- /dev/null +++ b/include/sys/select.h @@ -0,0 +1,130 @@ +/* `fd_set' type and related macros, and `select'/`pselect' declarations. + Copyright (C) 1996,97,98,99,2000,01,02,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* POSIX 1003.1g: 6.2 Select from File Descriptor Sets */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H 1 + +#include + +/* Get definition of needed basic types. */ +#include + +/* Get __FD_* definitions. */ +#include + +/* Get __sigset_t. */ +#include + +#ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +#endif + +/* Get definition of timer specification structures. */ +#define __need_time_t +#define __need_timespec +#include +#define __need_timeval +#include + +#ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +#endif + + +/* The fd_set member is required to be an array of longs. */ +typedef long int __fd_mask; + +/* Some versions of define these macros. */ +#undef __NFDBITS +#undef __FDELT +#undef __FDMASK +/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ +#define __NFDBITS (8 * sizeof (__fd_mask)) +#define __FDELT(d) ((d) / __NFDBITS) +#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) + +/* fd_set for select and pselect. */ +typedef struct + { + /* XPG4.2 requires this member name. Otherwise avoid the name + from the global namespace. */ +#ifdef __USE_XOPEN + __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; +# define __FDS_BITS(set) ((set)->fds_bits) +#else + __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS]; +# define __FDS_BITS(set) ((set)->__fds_bits) +#endif + } fd_set; + +/* Maximum number of file descriptors in `fd_set'. */ +#define FD_SETSIZE __FD_SETSIZE + +#ifdef __USE_MISC +/* Sometimes the fd_set member is assumed to have this type. */ +typedef __fd_mask fd_mask; + +/* Number of bits per word of `fd_set' (some code assumes this is 32). */ +# define NFDBITS __NFDBITS +#endif + + +/* Access macros for `fd_set'. */ +#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) +#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) +#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) +#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) + + +__BEGIN_DECLS + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Returns the number of ready + descriptors, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int select (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + struct timeval *__restrict __timeout); + +#ifdef __USE_XOPEN2K +/* Same as above only that the TIMEOUT value is given with higher + resolution and a sigmask which is been set temporarily. This version + should be used. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pselect (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t *__restrict __sigmask); +#endif + +__END_DECLS + +#endif /* sys/select.h */ diff --git a/include/sys/sem.h b/include/sys/sem.h new file mode 100644 index 0000000..24a57fc --- /dev/null +++ b/include/sys/sem.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1995-1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +#define _SYS_SEM_H 1 + +#include + +#define __need_size_t +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct semid_ds' and more. */ +#include + +#ifdef __USE_GNU +# define __need_timespec +# include +#endif + +/* The following System V style IPC functions implement a semaphore + handling. The definition is found in XPG2. */ + +/* Structure used for argument to `semop' to describe operations. */ +struct sembuf +{ + unsigned short int sem_num; /* semaphore number */ + short int sem_op; /* semaphore operation */ + short int sem_flg; /* operation flag */ +}; + + +__BEGIN_DECLS + +/* Semaphore control operation. */ +extern int semctl (int __semid, int __semnum, int __cmd, ...) __THROW; + +/* Get semaphore. */ +extern int semget (key_t __key, int __nsems, int __semflg) __THROW; + +/* Operate on semaphore. */ +extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __THROW; + +#ifdef __USE_GNU +/* Operate on semaphore with timeout. */ +extern int semtimedop (int __semid, struct sembuf *__sops, size_t __nsops, + __const struct timespec *__timeout) __THROW; +#endif + +__END_DECLS + +#endif /* sys/sem.h */ diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h new file mode 100644 index 0000000..4c1367b --- /dev/null +++ b/include/sys/sendfile.h @@ -0,0 +1,52 @@ +/* sendfile -- copy data directly from one file descriptor to another + Copyright (C) 1998,99,01,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SENDFILE_H +#define _SYS_SENDFILE_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Send up to COUNT bytes from file associated with IN_FD starting at + *OFFSET to descriptor OUT_FD. Set *OFFSET to the IN_FD's file position + following the read bytes. If OFFSET is a null pointer, use the normal + file position instead. Return the number of written bytes, or -1 in + case of error. */ +#ifndef __USE_FILE_OFFSET64 +extern ssize_t sendfile (int __out_fd, int __in_fd, off_t *__offset, + size_t __count) __THROW; +#else +# ifdef __REDIRECT_NTH +extern ssize_t __REDIRECT_NTH (sendfile, + (int __out_fd, int __in_fd, __off64_t *__offset, + size_t __count), sendfile64); +# else +# define sendfile sendfile64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern ssize_t sendfile64 (int __out_fd, int __in_fd, __off64_t *__offset, + size_t __count) __THROW; +#endif + +__END_DECLS + +#endif /* sys/sendfile.h */ diff --git a/include/sys/shm.h b/include/sys/shm.h new file mode 100644 index 0000000..8ec30b4 --- /dev/null +++ b/include/sys/shm.h @@ -0,0 +1,64 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +#define _SYS_SHM_H 1 + +#include + +#define __need_size_t +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct shmid_ds' and more. */ +#include + +/* Define types required by the standard. */ +#define __need_time_t +#include + +#ifdef __USE_XOPEN +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif /* X/Open */ + +__BEGIN_DECLS + +/* The following System V style IPC functions implement a shared memory + facility. The definition is found in XPG4.2. */ + +/* Shared memory control operation. */ +extern int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf) __THROW; + +/* Get shared memory segment. */ +extern int shmget (key_t __key, size_t __size, int __shmflg) __THROW; + +/* Attach shared memory segment. */ +extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg) + __THROW; + +/* Detach shared memory segment. */ +extern int shmdt (__const void *__shmaddr) __THROW; + +__END_DECLS + +#endif /* sys/shm.h */ diff --git a/include/sys/signal.h b/include/sys/signal.h new file mode 100644 index 0000000..2e602da --- /dev/null +++ b/include/sys/signal.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/signalfd.h b/include/sys/signalfd.h new file mode 100644 index 0000000..8cee17c --- /dev/null +++ b/include/sys/signalfd.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SIGNALFD_H +#define _SYS_SIGNALFD_H 1 + +#define __need_sigset_t +#include +#include + + +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; + uint64_t ssi_ptr; + uint64_t ssi_utime; + uint64_t ssi_stime; + uint64_t ssi_addr; + uint8_t __pad[48]; +}; + +/* Flags for signalfd. */ +#if defined __sparc__ || defined __sparc64__ +enum + { + SFD_CLOEXEC = 0x400000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 0x4000 +# define SFD_NONBLOCK SFD_NONBLOCK + }; + +#elif defined __alpha__ +enum + { + SFD_CLOEXEC = 010000000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 04 +# define SFD_NONBLOCK SFD_NONBLOCK + }; + +#else +enum + { + SFD_CLOEXEC = 02000000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 04000 +# define SFD_NONBLOCK SFD_NONBLOCK + }; +#endif + +__BEGIN_DECLS + +/* Request notification for delivery of signals in MASK to be + performed using descriptor FD.*/ +extern int signalfd (int __fd, const sigset_t *__mask, int __flags) + __nonnull ((2)) __THROW; + +__END_DECLS + +#endif /* sys/signalfd.h */ diff --git a/include/sys/socket.h b/include/sys/socket.h new file mode 100644 index 0000000..4ae1ea9 --- /dev/null +++ b/include/sys/socket.h @@ -0,0 +1,236 @@ +/* Declarations of socket constants, types, and functions. + Copyright (C) 1991,92,1994-2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H 1 + +#include + +__BEGIN_DECLS + +#include +#define __need_size_t +#include + + +/* This operating system-specific header file defines the SOCK_*, PF_*, + AF_*, MSG_*, SOL_*, and SO_* constants, and the `struct sockaddr', + `struct msghdr', and `struct linger' types. */ +#include + +#ifdef __USE_BSD +/* This is the 4.3 BSD `struct sockaddr' format, which is used as wire + format in the grotty old 4.3 `talk' protocol. */ +struct osockaddr + { + unsigned short int sa_family; + unsigned char sa_data[14]; + }; +#endif + +/* The following constants should be used for the second parameter of + `shutdown'. */ +enum +{ + SHUT_RD = 0, /* No more receptions. */ +#define SHUT_RD SHUT_RD + SHUT_WR, /* No more transmissions. */ +#define SHUT_WR SHUT_WR + SHUT_RDWR /* No more receptions or transmissions. */ +#define SHUT_RDWR SHUT_RDWR +}; + +/* This is the type we use for generic socket address arguments. + + With GCC 2.7 and later, the funky union causes redeclarations or + uses with any of the listed types to be allowed without complaint. + G++ 2.7 does not support transparent unions so there we want the + old-style declaration, too. */ +#if defined __cplusplus || !__GNUC_PREREQ (2, 7) || !defined __USE_GNU +# define __SOCKADDR_ARG struct sockaddr *__restrict +# define __CONST_SOCKADDR_ARG __const struct sockaddr * +#else +/* Add more `struct sockaddr_AF' types here as necessary. + These are all the ones I found on NetBSD and Linux. */ +# define __SOCKADDR_ALLTYPES \ + __SOCKADDR_ONETYPE (sockaddr) \ + __SOCKADDR_ONETYPE (sockaddr_at) \ + __SOCKADDR_ONETYPE (sockaddr_ax25) \ + __SOCKADDR_ONETYPE (sockaddr_dl) \ + __SOCKADDR_ONETYPE (sockaddr_eon) \ + __SOCKADDR_ONETYPE (sockaddr_in) \ + __SOCKADDR_ONETYPE (sockaddr_in6) \ + __SOCKADDR_ONETYPE (sockaddr_inarp) \ + __SOCKADDR_ONETYPE (sockaddr_ipx) \ + __SOCKADDR_ONETYPE (sockaddr_iso) \ + __SOCKADDR_ONETYPE (sockaddr_ns) \ + __SOCKADDR_ONETYPE (sockaddr_un) \ + __SOCKADDR_ONETYPE (sockaddr_x25) + +# define __SOCKADDR_ONETYPE(type) struct type *__restrict __##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __SOCKADDR_ARG __attribute__ ((__transparent_union__)); +# undef __SOCKADDR_ONETYPE +# define __SOCKADDR_ONETYPE(type) __const struct type *__restrict __##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __CONST_SOCKADDR_ARG __attribute__ ((__transparent_union__)); +# undef __SOCKADDR_ONETYPE +#endif + + +/* Create a new socket of type TYPE in domain DOMAIN, using + protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. + Returns a file descriptor for the new socket, or -1 for errors. */ +extern int socket (int __domain, int __type, int __protocol) __THROW; + +/* Create two new sockets, of type TYPE in domain DOMAIN and using + protocol PROTOCOL, which are connected to each other, and put file + descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + one will be chosen automatically. Returns 0 on success, -1 for errors. */ +extern int socketpair (int __domain, int __type, int __protocol, + int __fds[2]) __THROW; + +/* Give the socket FD the local address ADDR (which is LEN bytes long). */ +extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) + __THROW; + +/* Put the local address of FD into *ADDR and its length in *LEN. */ +extern int getsockname (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __len) __THROW; + +/* Open a connection on socket FD to peer at ADDR (which LEN bytes long). + For connectionless socket types, just set the default address to send to + and the only address from which to accept transmissions. + Return 0 on success, -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); + +/* Put the address of the peer connected to socket FD into *ADDR + (which is *LEN bytes long), and its actual length into *LEN. */ +extern int getpeername (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __len) __THROW; + + +/* Send N bytes of BUF to socket FD. Returns the number sent or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags); + +/* Read N bytes into BUF from socket FD. + Returns the number read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); + +/* Send N bytes of BUF on socket FD to peer at address ADDR (which is + ADDR_LEN bytes long). Returns the number sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t sendto (int __fd, __const void *__buf, size_t __n, + int __flags, __CONST_SOCKADDR_ARG __addr, + socklen_t __addr_len); + +/* Read N bytes into BUF through socket FD. + If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of + the sender, and store the actual size of the address in *ADDR_LEN. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, + int __flags, __SOCKADDR_ARG __addr, + socklen_t *__restrict __addr_len); + + +/* Send a message described MESSAGE on socket FD. + Returns the number of bytes sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t sendmsg (int __fd, __const struct msghdr *__message, + int __flags); + +/* Receive a message as described by MESSAGE from socket FD. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); + + +/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL + into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's + actual length. Returns 0 on success, -1 for errors. */ +extern int getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, + socklen_t *__restrict __optlen) __THROW; + +/* Set socket FD's option OPTNAME at protocol level LEVEL + to *OPTVAL (which is OPTLEN bytes long). + Returns 0 on success, -1 for errors. */ +extern int setsockopt (int __fd, int __level, int __optname, + __const void *__optval, socklen_t __optlen) __THROW; + + +/* Prepare to accept connections on socket FD. + N connection requests will be queued before further requests are refused. + Returns 0 on success, -1 for errors. */ +extern int listen (int __fd, int __n) __THROW; + +/* Await a connection on socket FD. + When a connection arrives, open a new socket to communicate with it, + set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting + peer and *ADDR_LEN to the address's actual length, and return the + new socket's descriptor, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int accept (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __addr_len); + +/* Shut down all or part of the connection open on socket FD. + HOW determines what to shut down: + SHUT_RD = No more receptions; + SHUT_WR = No more transmissions; + SHUT_RDWR = No more receptions or transmissions. + Returns 0 on success, -1 for errors. */ +extern int shutdown (int __fd, int __how) __THROW; + + +#ifdef __USE_XOPEN2K +/* Determine wheter socket is at a out-of-band mark. */ +extern int sockatmark (int __fd) __THROW; +#endif + + +#ifdef __USE_MISC +/* FDTYPE is S_IFSOCK or another S_IF* macro defined in ; + returns 1 if FD is open on an object of the indicated type, 0 if not, + or -1 for errors (setting errno). */ +extern int isfdtype (int __fd, int __fdtype) __THROW; +#endif + +__END_DECLS + +#endif /* sys/socket.h */ diff --git a/include/sys/socketvar.h b/include/sys/socketvar.h new file mode 100644 index 0000000..b177158 --- /dev/null +++ b/include/sys/socketvar.h @@ -0,0 +1,3 @@ +/* This header is used on many systems but for GNU we have everything + already defined in the standard header. */ +#include diff --git a/include/sys/soundcard.h b/include/sys/soundcard.h new file mode 100644 index 0000000..fade986 --- /dev/null +++ b/include/sys/soundcard.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/stat.h b/include/sys/stat.h new file mode 100644 index 0000000..5082390 --- /dev/null +++ b/include/sys/stat.h @@ -0,0 +1,366 @@ +/* Copyright (C) 1991,1992,1995-2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.6 File Characteristics + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H 1 + +#include + +#include /* For __mode_t and __dev_t. */ + +#if defined __USE_XOPEN || defined __USE_MISC +# if defined __USE_XOPEN || defined __USE_XOPEN2K +# define __need_time_t +# endif +# ifdef __USE_MISC +# define __need_timespec +# endif +# include /* For time_t resp. timespec. */ +#endif + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __dev_t_defined +typedef __dev_t dev_t; +# define __dev_t_defined +# endif + +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +# endif + +# ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +# endif + +# ifndef __nlink_t_defined +typedef __nlink_t nlink_t; +# define __nlink_t_defined +# endif + +# ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif /* X/Open */ + +#ifdef __USE_UNIX98 +# ifndef __blkcnt_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __blkcnt_t blkcnt_t; +# else +typedef __blkcnt64_t blkcnt_t; +# endif +# define __blkcnt_t_defined +# endif + +# ifndef __blksize_t_defined +typedef __blksize_t blksize_t; +# define __blksize_t_defined +# endif +#endif /* Unix98 */ + +__BEGIN_DECLS + +#include + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +# define S_IFMT __S_IFMT +# define S_IFDIR __S_IFDIR +# define S_IFCHR __S_IFCHR +# define S_IFBLK __S_IFBLK +# define S_IFREG __S_IFREG +# ifdef __S_IFIFO +# define S_IFIFO __S_IFIFO +# endif +# ifdef __S_IFLNK +# define S_IFLNK __S_IFLNK +# endif +# if (defined __USE_BSD || defined __USE_MISC || defined __USE_UNIX98) \ + && defined __S_IFSOCK +# define S_IFSOCK __S_IFSOCK +# endif +#endif + +/* Test macros for file types. */ + +#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)) + +#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) +#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR) +#define S_ISBLK(mode) __S_ISTYPE((mode), __S_IFBLK) +#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) +#ifdef __S_IFIFO +# define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO) +#endif +#ifdef __S_IFLNK +# define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK) +#endif + +#if defined __USE_BSD && !defined __S_IFLNK +# define S_ISLNK(mode) 0 +#endif + +#if (defined __USE_BSD || defined __USE_UNIX98) \ + && defined __S_IFSOCK +# define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK) +#endif + +/* These are from POSIX.1b. If the objects are not implemented using separate + distinct file types, the macros always will evaluate to zero. Unlike the + other S_* macros the following three take a pointer to a `struct stat' + object as the argument. */ +#ifdef __USE_POSIX199309 +# define S_TYPEISMQ(buf) __S_TYPEISMQ(buf) +# define S_TYPEISSEM(buf) __S_TYPEISSEM(buf) +# define S_TYPEISSHM(buf) __S_TYPEISSHM(buf) +#endif + + +/* Protection bits. */ + +#define S_ISUID __S_ISUID /* Set user ID on execution. */ +#define S_ISGID __S_ISGID /* Set group ID on execution. */ + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +/* Save swapped text after use (sticky bit). This is pretty well obsolete. */ +# define S_ISVTX __S_ISVTX +#endif + +#define S_IRUSR __S_IREAD /* Read by owner. */ +#define S_IWUSR __S_IWRITE /* Write by owner. */ +#define S_IXUSR __S_IEXEC /* Execute by owner. */ +/* Read, write, and execute by owner. */ +#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC) + +#if defined __USE_MISC && defined __USE_BSD +# define S_IREAD S_IRUSR +# define S_IWRITE S_IWUSR +# define S_IEXEC S_IXUSR +#endif + +#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */ +#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */ +#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */ +/* Read, write, and execute by group. */ +#define S_IRWXG (S_IRWXU >> 3) + +#define S_IROTH (S_IRGRP >> 3) /* Read by others. */ +#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */ +#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */ +/* Read, write, and execute by others. */ +#define S_IRWXO (S_IRWXG >> 3) + + +#ifdef __USE_BSD +/* Macros for common mode bit masks. */ +# define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */ +# define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)/* 07777 */ +# define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666*/ + +# define S_BLKSIZE 512 /* Block size for `st_blocks'. */ +#endif + + +#ifndef __USE_FILE_OFFSET64 +/* Get file attributes for FILE and put them in BUF. */ +extern int stat (__const char *__restrict __file, + struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); + +/* Get file attributes for the file, device, pipe, or socket + that file descriptor FD is open on and put them in BUF. */ +extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (stat, (__const char *__restrict __file, + struct stat *__restrict __buf), stat64) + __nonnull ((1, 2)); +extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64) + __nonnull ((2)); +# else +# define stat stat64 +# define fstat fstat64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int stat64 (__const char *__restrict __file, + struct stat64 *__restrict __buf) __THROW __nonnull ((1, 2)); +extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2)); +#endif + +#ifdef __USE_ATFILE +/* Similar to stat, get the attributes for FILE and put them in BUF. + Relative path names are interpreted relative to FD unless FD is + AT_FDCWD. */ +# ifndef __USE_FILE_OFFSET64 +extern int fstatat (int __fd, __const char *__restrict __file, + struct stat *__restrict __buf, int __flag) + __THROW __nonnull ((2, 3)); +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatat, (int __fd, __const char *__restrict __file, + struct stat *__restrict __buf, + int __flag), + fstatat64) __nonnull ((2, 3)); +# else +# define fstatat fstatat64 +# endif +# endif + +extern int fstatat64 (int __fd, __const char *__restrict __file, + struct stat64 *__restrict __buf, int __flag) + __THROW __nonnull ((2, 3)); +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +# ifndef __USE_FILE_OFFSET64 +/* Get file attributes about FILE and put them in BUF. + If FILE is a symbolic link, do not follow it. */ +extern int lstat (__const char *__restrict __file, + struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (lstat, + (__const char *__restrict __file, + struct stat *__restrict __buf), lstat64) + __nonnull ((1, 2)); +# else +# define lstat lstat64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lstat64 (__const char *__restrict __file, + struct stat64 *__restrict __buf) + __THROW __nonnull ((1, 2)); +# endif +#endif + +/* Set file access permissions for FILE to MODE. + If FILE is a symbolic link, this affects its target instead. */ +extern int chmod (__const char *__file, __mode_t __mode) + __THROW __nonnull ((1)); + +#if 0 /*def __USE_BSD*/ +/* Set file access permissions for FILE to MODE. + If FILE is a symbolic link, this affects the link itself + rather than its target. */ +extern int lchmod (__const char *__file, __mode_t __mode) + __THROW __nonnull ((1)); +#endif + +/* Set file access permissions of the file FD is open on to MODE. */ +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +extern int fchmod (int __fd, __mode_t __mode) __THROW; +#endif + +#ifdef __USE_ATFILE +/* Set file access permissions of FILE relative to + the directory FD is open on. */ +extern int fchmodat (int __fd, __const char *__file, __mode_t mode, int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use ATFILE. */ + + + +/* Set the file creation mask of the current process to MASK, + and return the old creation mask. */ +extern __mode_t umask (__mode_t __mask) __THROW; + +#if 0 /*def __USE_GNU*/ +/* Get the current `umask' value without changing it. + This function is only available under the GNU Hurd. */ +extern __mode_t getumask (void) __THROW; +#endif + +/* Create a new directory named PATH, with permission bits MODE. */ +extern int mkdir (__const char *__path, __mode_t __mode) + __THROW __nonnull ((1)); + +#ifdef __USE_ATFILE +/* Like mkdir, create a new directory with permission bits MODE. But + interpret relative PATH names relative to the directory associated + with FD. */ +extern int mkdirat (int __fd, __const char *__path, __mode_t __mode) + __THROW __nonnull ((2)); +#endif + +/* Create a device file named PATH, with permission and special bits MODE + and device number DEV (which can be constructed from major and minor + device numbers with the `makedev' macro above). */ +#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +extern int mknod (__const char *__path, __mode_t __mode, __dev_t __dev) + __THROW __nonnull ((1)); +#endif + +#ifdef __USE_ATFILE +/* Like mknod, create a new device file with permission bits MODE and + device number DEV. But interpret relative PATH names relative to + the directory associated with FD. */ +extern int mknodat (int __fd, __const char *__path, __mode_t __mode, + __dev_t __dev) __THROW __nonnull ((2)); +#endif + + +/* Create a new FIFO named PATH, with permission bits MODE. */ +extern int mkfifo (__const char *__path, __mode_t __mode) + __THROW __nonnull ((1)); + +#ifdef __USE_ATFILE +/* Like mkfifo, create a new FIFO with permission bits MODE. But + interpret relative PATH names relative to the directory associated + with FD. */ +extern int mkfifoat (int __fd, __const char *__path, __mode_t __mode) + __THROW __nonnull ((2)); +#endif + +/* on uClibc we have unversioned struct stat and mknod. + * bits/stat.h is filled with wrong info, so we undo it here. */ +#undef _STAT_VER +#define _STAT_VER 0 +#undef _MKNOD_VER +#define _MKNOD_VER 0 + +__END_DECLS + + +#endif /* sys/stat.h */ diff --git a/include/sys/statfs.h b/include/sys/statfs.h new file mode 100644 index 0000000..f4177d4 --- /dev/null +++ b/include/sys/statfs.h @@ -0,0 +1,70 @@ +/* Definitions for getting information about a filesystem. + Copyright (C) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +#define _SYS_STATFS_H 1 + +#include + +/* Get the system-specific definition of `struct statfs'. */ +#include + +__BEGIN_DECLS + +/* Return information about the filesystem on which FILE resides. */ +#ifndef __USE_FILE_OFFSET64 +extern int statfs (__const char *__file, struct statfs *__buf) + __THROW __nonnull ((1, 2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (statfs, + (__const char *__file, struct statfs *__buf), + statfs64) __nonnull ((1, 2)); +# else +# define statfs statfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int statfs64 (__const char *__file, struct statfs64 *__buf) + __THROW __nonnull ((1, 2)); +#endif + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* Return information about the filesystem containing the file FILDES + refers to. */ +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int fstatfs64 (int __fildes, struct statfs64 *__buf) + __THROW __nonnull ((2)); +#endif +#endif /* __UCLIBC_LINUX_SPECIFIC__ */ + +__END_DECLS + +#endif /* sys/statfs.h */ diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h new file mode 100644 index 0000000..685dd26 --- /dev/null +++ b/include/sys/statvfs.h @@ -0,0 +1,91 @@ +/* Definitions for getting information about a filesystem. + Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +#define _SYS_STATVFS_H 1 + +#include + +/* Get the system-specific definition of `struct statfs'. */ +#include + +#ifndef __USE_FILE_OFFSET64 +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#else +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt64_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt64_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#endif + +__BEGIN_DECLS + +/* Return information about the filesystem on which FILE resides. */ +#ifndef __USE_FILE_OFFSET64 +extern int statvfs (__const char *__restrict __file, + struct statvfs *__restrict __buf) + __THROW __nonnull ((1, 2)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (statvfs, + (__const char *__restrict __file, + struct statvfs *__restrict __buf), statvfs64) + __nonnull ((1, 2)); +# else +# define statvfs statvfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int statvfs64 (__const char *__restrict __file, + struct statvfs64 *__restrict __buf) + __THROW __nonnull ((1, 2)); +#endif + +/* Return information about the filesystem containing the file FILDES + refers to. */ +#ifndef __USE_FILE_OFFSET64 +extern int fstatvfs (int __fildes, struct statvfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (fstatvfs, (int __fildes, struct statvfs *__buf), + fstatvfs64) __nonnull ((2)); +# else +# define fstatvfs fstatvfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int fstatvfs64 (int __fildes, struct statvfs64 *__buf) + __THROW __nonnull ((2)); +#endif + +__END_DECLS + +#endif /* sys/statvfs.h */ diff --git a/include/sys/swap.h b/include/sys/swap.h new file mode 100644 index 0000000..b6e7bef --- /dev/null +++ b/include/sys/swap.h @@ -0,0 +1,43 @@ +/* Calls to enable and disable swapping on specified locations. Linux version. + Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SWAP_H + +#define _SYS_SWAP_H 1 +#include + +/* The swap priority is encoded as: + (prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK +*/ +#define SWAP_FLAG_PREFER 0x8000 /* Set if swap priority is specified. */ +#define SWAP_FLAG_PRIO_MASK 0x7fff +#define SWAP_FLAG_PRIO_SHIFT 0 + +__BEGIN_DECLS + +/* Make the block special device PATH available to the system for swapping. + This call is restricted to the super-user. */ +extern int swapon (__const char *__path, int __flags) __THROW; + +/* Stop using block special device PATH for swapping. */ +extern int swapoff (__const char *__path) __THROW; + +__END_DECLS + +#endif /* _SYS_SWAP_H */ diff --git a/include/sys/syscall.h b/include/sys/syscall.h new file mode 100644 index 0000000..4c8ede8 --- /dev/null +++ b/include/sys/syscall.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYSCALL_H +#define _SYSCALL_H 1 + +/* The _syscall#() macros are for uClibc internal use only. + * User application code should use syscall() instead. + * + * The kernel provided _syscall[0-6] macros from asm/unistd.h are not suitable + * for use in uClibc as they lack PIC support etc, so for uClibc we use our own + * local _syscall# macros to be certain all such variations are handled + * properly. + */ + +#include +#include +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) +# include +#endif + +#endif diff --git a/include/sys/sysctl.h b/include/sys/sysctl.h new file mode 100644 index 0000000..110efaa --- /dev/null +++ b/include/sys/sysctl.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1996, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSCTL_H +#define _SYS_SYSCTL_H 1 + +#include +#define __need_size_t +#include +/* Prevent more kernel headers than necessary to be included. */ +#ifndef _LINUX_KERNEL_H +# define _LINUX_KERNEL_H 1 +# define __undef_LINUX_KERNEL_H +#endif +#ifndef _LINUX_TYPES_H +# define _LINUX_TYPES_H 1 +# define __undef_LINUX_TYPES_H +#endif +#ifndef _LINUX_LIST_H +# define _LINUX_LIST_H 1 +# define __undef_LINUX_LIST_H +#endif +#ifndef __LINUX_COMPILER_H +# define __LINUX_COMPILER_H 1 +# define __user +# define __undef__LINUX_COMPILER_H +#endif + +#include + +#ifdef __undef_LINUX_KERNEL_H +# undef _LINUX_KERNEL_H +# undef __undef_LINUX_KERNEL_H +#endif +#ifdef __undef_LINUX_TYPES_H +# undef _LINUX_TYPES_H +# undef __undef_LINUX_TYPES_H +#endif +#ifdef __undef_LINUX_LIST_H +# undef _LINUX_LIST_H +# undef __undef_LINUX_LIST_H +#endif +#ifdef __undef__LINUX_COMPILER_H +# undef __LINUX_COMPILER_H +# undef __user +# undef __undef__LINUX_COMPILER_H +#endif + +__BEGIN_DECLS + +/* Read or write system parameters. */ +extern int sysctl (int *__name, int __nlen, void *__oldval, + size_t *__oldlenp, void *__newval, size_t __newlen) __THROW; + +__END_DECLS + +#endif /* _SYS_SYSCTL_H */ diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h new file mode 100644 index 0000000..9fd4fa8 --- /dev/null +++ b/include/sys/sysinfo.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1996, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSINFO_H +#define _SYS_SYSINFO_H 1 + +#include + +#ifndef _LINUX_KERNEL_H +/* Include our own copy of struct sysinfo to avoid binary compatability + * problems with Linux 2.4, which changed things. Grumble, grumble. */ +#define SI_LOAD_SHIFT 16 +struct sysinfo { + long uptime; /* Seconds since boot */ + unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ + unsigned long totalram; /* Total usable main memory size */ + unsigned long freeram; /* Available memory size */ + unsigned long sharedram; /* Amount of shared memory */ + unsigned long bufferram; /* Memory used by buffers */ + unsigned long totalswap; /* Total swap space size */ + unsigned long freeswap; /* swap space still available */ + unsigned short procs; /* Number of current processes */ + unsigned short pad; /* Padding needed for m68k */ + unsigned long totalhigh; /* Total high memory size */ + unsigned long freehigh; /* Available high memory size */ + unsigned int mem_unit; /* Memory unit size in bytes */ + char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +}; +#endif + +__BEGIN_DECLS + +/* Returns information on overall system statistics. */ +extern int sysinfo (struct sysinfo *__info) __THROW; + + +/* Return number of configured processors. */ +extern int get_nprocs_conf (void) __THROW; + +/* Return number of available processors. */ +extern int get_nprocs (void) __THROW; + + +/* Return number of physical pages of memory in the system. */ +extern long int get_phys_pages (void) __THROW; + +/* Return number of available physical pages of memory in the system. */ +extern long int get_avphys_pages (void) __THROW; + +__END_DECLS + +#endif /* sys/sysinfo.h */ diff --git a/include/sys/syslog.h b/include/sys/syslog.h new file mode 100644 index 0000000..3f5e6b2 --- /dev/null +++ b/include/sys/syslog.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SYSLOG_H +#define _SYS_SYSLOG_H 1 + +#include +#define __need___va_list +#include + + +#define _PATH_LOG "/dev/log" + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) + +#ifdef SYSLOG_NAMES +#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ + /* mark "facility" */ +#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) +typedef struct _code { + const char *c_name; + int c_val; +} CODE; + +#ifdef SYSLOG_NAMES_CONST +const +#endif +CODE prioritynames[] = + { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "error", LOG_ERR }, /* DEPRECATED */ + { "info", LOG_INFO }, + { "none", INTERNAL_NOPRI }, /* INTERNAL */ + { "notice", LOG_NOTICE }, + { "panic", LOG_EMERG }, /* DEPRECATED */ + { "warn", LOG_WARNING }, /* DEPRECATED */ + { "warning", LOG_WARNING }, + { NULL, -1 } + }; +#endif + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#ifdef SYSLOG_NAMES +#ifdef SYSLOG_NAMES_CONST +const +#endif +CODE facilitynames[] = + { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "mark", INTERNAL_MARK }, /* INTERNAL */ + { "news", LOG_NEWS }, + { "security", LOG_AUTH }, /* DEPRECATED */ + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 } + }; +#endif + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + * + * LOG_ODELAY no longer does anything. + * LOG_NDELAY is the inverse of what it used to be. + */ +#define LOG_PID 0x01 /* log the pid with each message */ +#define LOG_CONS 0x02 /* log on the console if errors in sending */ +#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ +#define LOG_NDELAY 0x08 /* don't delay open */ +#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ +#define LOG_PERROR 0x20 /* log to stderr as well */ + +__BEGIN_DECLS + +/* Close descriptor used to write to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void closelog (void); + +/* Open connection to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void openlog (__const char *__ident, int __option, int __facility); + +/* Set the log mask level. */ +extern int setlogmask (int __mask) __THROW; + +/* Generate a log message using FMT string and option arguments. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void syslog (int __pri, __const char *__fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + +#ifdef __USE_BSD +/* Generate a log message using FMT and using arguments pointed to by AP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void vsyslog (int __pri, __const char *__fmt, __gnuc_va_list __ap) + __attribute__ ((__format__ (__printf__, 2, 0))); +#endif + +__END_DECLS + +#endif /* sys/syslog.h */ diff --git a/include/sys/sysmacros.h b/include/sys/sysmacros.h new file mode 100644 index 0000000..c5efca4 --- /dev/null +++ b/include/sys/sysmacros.h @@ -0,0 +1,69 @@ +/* Definitions of macros to access `dev_t' values. + Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H 1 + +#include + +/* If the compiler does not know long long it is out of luck. We are + not going to hack weird hacks to support the dev_t representation + they need. */ +#if 1 /*def __GLIBC_HAVE_LONG_LONG uClibc note: always enable */ +__extension__ +static __inline unsigned int gnu_dev_major (unsigned long long int __dev) + __THROW; +__extension__ +static __inline unsigned int gnu_dev_minor (unsigned long long int __dev) + __THROW; +__extension__ +static __inline unsigned long long int gnu_dev_makedev (unsigned int __major, + unsigned int __minor) + __THROW; + +# if defined __GNUC__ && __GNUC__ >= 2 +__extension__ static __inline unsigned int +__NTH (gnu_dev_major (unsigned long long int __dev)) +{ + return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff); +} + +__extension__ static __inline unsigned int +__NTH (gnu_dev_minor (unsigned long long int __dev)) +{ + return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); +} + +__extension__ static __inline unsigned long long int +__NTH (gnu_dev_makedev (unsigned int __major, unsigned int __minor)) +{ + return ((__minor & 0xff) | ((__major & 0xfff) << 8) + | (((unsigned long long int) (__minor & ~0xff)) << 12) + | (((unsigned long long int) (__major & ~0xfff)) << 32)); +} +# endif + + +/* Access the functions with their traditional names. */ +# define major(dev) gnu_dev_major (dev) +# define minor(dev) gnu_dev_minor (dev) +# define makedev(maj, min) gnu_dev_makedev (maj, min) +#endif + +#endif /* sys/sysmacros.h */ diff --git a/include/sys/termios.h b/include/sys/termios.h new file mode 100644 index 0000000..3e18805 --- /dev/null +++ b/include/sys/termios.h @@ -0,0 +1,4 @@ +#ifndef _SYS_TERMIOS_H +#define _SYS_TERMIOS_H +#include +#endif diff --git a/include/sys/time.h b/include/sys/time.h new file mode 100644 index 0000000..66fb9e0 --- /dev/null +++ b/include/sys/time.h @@ -0,0 +1,192 @@ +/* Copyright (C) 1991-1994,1996-2002,2003,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H 1 + +#include + +#include +#define __need_time_t +#include +#define __need_timeval +#include + +#include + +#ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +#endif + + +__BEGIN_DECLS + +#ifdef __USE_GNU +/* Macros for converting between `struct timeval' and `struct timespec'. */ +# define TIMEVAL_TO_TIMESPEC(tv, ts) { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} +# define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} +#endif + + +#ifdef __USE_BSD +/* Structure crudely representing a timezone. + This is obsolete and should never be used. */ +struct timezone + { + int tz_minuteswest; /* Minutes west of GMT. */ + int tz_dsttime; /* Nonzero if DST is ever in effect. */ + }; + +typedef struct timezone *__restrict __timezone_ptr_t; +#else +typedef void *__restrict __timezone_ptr_t; +#endif + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. + NOTE: This form of timezone information is obsolete. + Use the functions and variables declared in instead. */ +extern int gettimeofday (struct timeval *__restrict __tv, + __timezone_ptr_t __tz) __THROW __nonnull ((1)); + +#ifdef __USE_BSD +/* Set the current time of day and timezone information. + This call is restricted to the super-user. */ +extern int settimeofday (__const struct timeval *__tv, + __const struct timezone *__tz) + __THROW __nonnull ((1)); + +/* Adjust the current time of day by the amount in DELTA. + If OLDDELTA is not NULL, it is filled in with the amount + of time adjustment remaining to be done from the last `adjtime' call. + This call is restricted to the super-user. */ +extern int adjtime (__const struct timeval *__delta, + struct timeval *__olddelta) __THROW; +#endif + + +/* Values for the first argument to `getitimer' and `setitimer'. */ +enum __itimer_which + { + /* Timers run in real time. */ + ITIMER_REAL = 0, +#define ITIMER_REAL ITIMER_REAL + /* Timers run only when the process is executing. */ + ITIMER_VIRTUAL = 1, +#define ITIMER_VIRTUAL ITIMER_VIRTUAL + /* Timers run when the process is executing and when + the system is executing on behalf of the process. */ + ITIMER_PROF = 2 +#define ITIMER_PROF ITIMER_PROF + }; + +/* Type of the second argument to `getitimer' and + the second and third arguments `setitimer'. */ +struct itimerval + { + /* Value to put into `it_value' when the timer expires. */ + struct timeval it_interval; + /* Time to the next timer expiration. */ + struct timeval it_value; + }; + +#if defined __USE_GNU && !defined __cplusplus +/* Use the nicer parameter type only in GNU mode and not for C++ since the + strict C++ rules prevent the automatic promotion. */ +typedef enum __itimer_which __itimer_which_t; +#else +typedef int __itimer_which_t; +#endif + +/* Set *VALUE to the current setting of timer WHICH. + Return 0 on success, -1 on errors. */ +extern int getitimer (__itimer_which_t __which, + struct itimerval *__value) __THROW; + +/* Set the timer WHICH to *NEW. If OLD is not NULL, + set *OLD to the old value of timer WHICH. + Returns 0 on success, -1 on errors. */ +extern int setitimer (__itimer_which_t __which, + __const struct itimerval *__restrict __new, + struct itimerval *__restrict __old) __THROW; + +/* Change the access time of FILE to TVP[0] and the modification time of + FILE to TVP[1]. If TVP is a null pointer, use the current time instead. + Returns 0 on success, -1 on errors. */ +extern int utimes (__const char *__file, __const struct timeval __tvp[2]) + __THROW __nonnull ((1)); + +#if 0 /*def __USE_BSD*/ +/* Same as `utimes', but does not follow symbolic links. */ +extern int lutimes (__const char *__file, __const struct timeval __tvp[2]) + __THROW __nonnull ((1)); + +/* Same as `utimes', but takes an open file descriptor instead of a name. */ +extern int futimes (int __fd, __const struct timeval __tvp[2]) __THROW; +#endif + +#if 0 /*def __USE_GNU*/ +/* Change the access time of FILE relative to FD to TVP[0] and the + modification time of FILE to TVP[1]. If TVP is a null pointer, use + the current time instead. Returns 0 on success, -1 on errors. */ +extern int futimesat (int __fd, __const char *__file, + __const struct timeval __tvp[2]) __THROW; +#endif + + +#ifdef __USE_BSD +/* Convenience macros for operations on timevals. + NOTE: `timercmp' does not work for >= or <=. */ +# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) +# define timercmp(a, b, CMP) \ + (((a)->tv_sec == (b)->tv_sec) ? \ + ((a)->tv_usec CMP (b)->tv_usec) : \ + ((a)->tv_sec CMP (b)->tv_sec)) +# define timeradd(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ + if ((result)->tv_usec >= 1000000) \ + { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +# define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* BSD */ + +__END_DECLS + +#endif /* sys/time.h */ diff --git a/include/sys/timeb.h b/include/sys/timeb.h new file mode 100644 index 0000000..dbdbf45 --- /dev/null +++ b/include/sys/timeb.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIMEB_H +#define _SYS_TIMEB_H 1 + +#include + +#define __need_time_t +#include + + +__BEGIN_DECLS + +/* Structure returned by the `ftime' function. */ + +struct timeb + { + time_t time; /* Seconds since epoch, as from `time'. */ + unsigned short int millitm; /* Additional milliseconds. */ + short int timezone; /* Minutes west of GMT. */ + short int dstflag; /* Nonzero if Daylight Savings Time used. */ + }; + +/* Fill in TIMEBUF with information about the current time. */ + +extern int ftime (struct timeb *__timebuf); + +__END_DECLS + +#endif /* sys/timeb.h */ diff --git a/include/sys/times.h b/include/sys/times.h new file mode 100644 index 0000000..6022f2f --- /dev/null +++ b/include/sys/times.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 4.5.2 Process Times + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H 1 + +#include + +#define __need_clock_t +#include + + +__BEGIN_DECLS + +/* Structure describing CPU time used by a process and its children. */ +struct tms + { + clock_t tms_utime; /* User CPU time. */ + clock_t tms_stime; /* System CPU time. */ + + clock_t tms_cutime; /* User CPU time of dead children. */ + clock_t tms_cstime; /* System CPU time of dead children. */ + }; + + +/* Store the CPU time used by this process and all its + dead children (and their dead children) in BUFFER. + Return the elapsed real time, or (clock_t) -1 for errors. + All times are in CLK_TCKths of a second. */ +extern clock_t times (struct tms *__buffer) __THROW; + +__END_DECLS + +#endif /* sys/times.h */ diff --git a/include/sys/timex.h b/include/sys/timex.h new file mode 100644 index 0000000..d2020a6 --- /dev/null +++ b/include/sys/timex.h @@ -0,0 +1,129 @@ +/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIMEX_H +#define _SYS_TIMEX_H 1 + +#include +#include + +/* These definitions from linux/timex.h as of 2.2.0. */ + +struct ntptimeval +{ + struct timeval time; /* current time (ro) */ + long int maxerror; /* maximum error (us) (ro) */ + long int esterror; /* estimated error (us) (ro) */ +}; + +struct timex +{ + unsigned int modes; /* mode selector */ + long int offset; /* time offset (usec) */ + long int freq; /* frequency offset (scaled ppm) */ + long int maxerror; /* maximum error (usec) */ + long int esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + long int constant; /* pll time constant */ + long int precision; /* clock precision (usec) (read only) */ + long int tolerance; /* clock frequency tolerance (ppm) (read only) */ + struct timeval time; /* (read only) */ + long int tick; /* (modified) usecs between clock ticks */ + + long int ppsfreq; /* pps frequency (scaled ppm) (ro) */ + long int jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + long int stabil; /* pps stability (scaled ppm) (ro) */ + long int jitcnt; /* jitter limit exceeded (ro) */ + long int calcnt; /* calibration intervals (ro) */ + long int errcnt; /* calibration errors (ro) */ + long int stbcnt; /* stability limit exceeded (ro) */ + + /* ??? */ + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; +}; + +/* Mode codes (timex.mode) */ +#define ADJ_OFFSET 0x0001 /* time offset */ +#define ADJ_FREQUENCY 0x0002 /* frequency offset */ +#define ADJ_MAXERROR 0x0004 /* maximum time error */ +#define ADJ_ESTERROR 0x0008 /* estimated time error */ +#define ADJ_STATUS 0x0010 /* clock status */ +#define ADJ_TIMECONST 0x0020 /* pll time constant */ +#define ADJ_TICK 0x4000 /* tick value */ +#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ + +/* xntp 3.4 compatibility names */ +#define MOD_OFFSET ADJ_OFFSET +#define MOD_FREQUENCY ADJ_FREQUENCY +#define MOD_MAXERROR ADJ_MAXERROR +#define MOD_ESTERROR ADJ_ESTERROR +#define MOD_STATUS ADJ_STATUS +#define MOD_TIMECONST ADJ_TIMECONST +#define MOD_CLKB ADJ_TICK +#define MOD_CLKA ADJ_OFFSET_SINGLESHOT /* 0x8000 in original */ + + +/* Status codes (timex.status) */ +#define STA_PLL 0x0001 /* enable PLL updates (rw) */ +#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */ +#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */ +#define STA_FLL 0x0008 /* select frequency-lock mode (rw) */ + +#define STA_INS 0x0010 /* insert leap (rw) */ +#define STA_DEL 0x0020 /* delete leap (rw) */ +#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */ +#define STA_FREQHOLD 0x0080 /* hold frequency (rw) */ + +#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */ +#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */ +#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */ +#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ + +#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ + +#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ + STA_PPSERROR | STA_CLOCKERR) /* read-only bits */ + +/* Clock states (time_state) */ +#define TIME_OK 0 /* clock synchronized, no leap second */ +#define TIME_INS 1 /* insert leap second */ +#define TIME_DEL 2 /* delete leap second */ +#define TIME_OOP 3 /* leap second in progress */ +#define TIME_WAIT 4 /* leap second has occurred */ +#define TIME_ERROR 5 /* clock not synchronized */ +#define TIME_BAD TIME_ERROR /* bw compat */ + +/* Maximum time constant of the PLL. */ +#define MAXTC 6 + +__BEGIN_DECLS + +extern int __adjtimex (struct timex *__ntx) __THROW; +extern int adjtimex (struct timex *__ntx) __THROW; + +#if defined __UCLIBC_NTP_LEGACY__ +extern int ntp_gettime (struct ntptimeval *__ntv) __THROW; +extern int ntp_adjtime (struct timex *__tntx) __THROW; +#endif + +__END_DECLS + +#endif /* sys/timex.h */ diff --git a/include/sys/ttydefaults.h b/include/sys/ttydefaults.h new file mode 100644 index 0000000..9be168b --- /dev/null +++ b/include/sys/ttydefaults.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttydefaults.h 8.4 (Berkeley) 1/21/94 + */ + +/* + * System wide defaults for terminal state. Linux version. + */ +#ifndef _SYS_TTYDEFAULTS_H_ +#define _SYS_TTYDEFAULTS_H_ + +/* + * Defaults on "first" open. + */ +#define TTYDEF_IFLAG (BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY) +#define TTYDEF_OFLAG (OPOST | ONLCR | XTABS) +#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL) +#define TTYDEF_CFLAG (CREAD | CS7 | PARENB | HUPCL) +#define TTYDEF_SPEED (B9600) + +/* + * Control Character Defaults + */ +#define CTRL(x) (x&037) +#define CEOF CTRL('d') +#ifdef _POSIX_VDISABLE +# define CEOL _POSIX_VDISABLE +#else +# define CEOL '\0' /* XXX avoid _POSIX_VDISABLE */ +#endif +#define CERASE 0177 +#define CINTR CTRL('c') +#ifdef _POSIX_VDISABLE +# define CSTATUS _POSIX_VDISABLE +#else +# define CSTATUS '\0' /* XXX avoid _POSIX_VDISABLE */ +#endif +#define CKILL CTRL('u') +#define CMIN 1 +#define CQUIT 034 /* FS, ^\ */ +#define CSUSP CTRL('z') +#define CTIME 0 +#define CDSUSP CTRL('y') +#define CSTART CTRL('q') +#define CSTOP CTRL('s') +#define CLNEXT CTRL('v') +#define CDISCARD CTRL('o') +#define CWERASE CTRL('w') +#define CREPRINT CTRL('r') +#define CEOT CEOF +/* compat */ +#define CBRK CEOL +#define CRPRNT CREPRINT +#define CFLUSH CDISCARD + +/* PROTECTED INCLUSION ENDS HERE */ +#endif /* !_SYS_TTYDEFAULTS_H_ */ + +/* + * #define TTYDEFCHARS to include an array of default control characters. + */ +#ifdef TTYDEFCHARS +cc_t ttydefchars[NCCS] = { + CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, + _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, + CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE +}; +#undef TTYDEFCHARS +#endif diff --git a/include/sys/types.h b/include/sys/types.h new file mode 100644 index 0000000..8c0b5dc --- /dev/null +++ b/include/sys/types.h @@ -0,0 +1,275 @@ +/* Copyright (C) 1991,1992,1994,1995,1996,1997,1998,1999,2000,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.6 Primitive System Data Types + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifdef __USE_BSD +# ifndef __u_char_defined +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +# define __u_char_defined +# endif +#endif + +typedef __loff_t loff_t; + +#ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +#endif +#if defined __USE_LARGEFILE64 && !defined __ino64_t_defined +typedef __ino64_t ino64_t; +# define __ino64_t_defined +#endif + +#ifndef __dev_t_defined +typedef __dev_t dev_t; +# define __dev_t_defined +#endif + +#ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#ifndef __nlink_t_defined +typedef __nlink_t nlink_t; +# define __nlink_t_defined +#endif + +#ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +#endif + +#ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +#endif +#if defined __USE_LARGEFILE64 && !defined __off64_t_defined +typedef __off64_t off64_t; +# define __off64_t_defined +#endif + +#ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif + +#if (defined __USE_SVID || defined __USE_XOPEN) && !defined __id_t_defined +typedef __id_t id_t; +# define __id_t_defined +#endif + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +#ifdef __USE_BSD +# ifndef __daddr_t_defined +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +# define __daddr_t_defined +# endif +#endif + +#if (defined __USE_SVID || defined __USE_XOPEN) && !defined __key_t_defined +typedef __key_t key_t; +# define __key_t_defined +#endif + +#ifdef __USE_XOPEN +# define __need_clock_t +#endif +#define __need_time_t +#define __need_timer_t +#define __need_clockid_t +#include + +#ifdef __USE_XOPEN +# ifndef __useconds_t_defined +typedef __useconds_t useconds_t; +# define __useconds_t_defined +# endif +# ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +# endif +#endif + +#define __need_size_t +#include + +#ifdef __USE_MISC +/* Old compatibility names for C types. */ +typedef unsigned long int ulong; +typedef unsigned short int ushort; +typedef unsigned int uint; +#endif + +/* These size-specific names are used by some of the inet code. */ + +#if !__GNUC_PREREQ (2, 7) + +/* These types are defined by the ISO C99 header . */ +# ifndef __int8_t_defined +# define __int8_t_defined +typedef char int8_t; +typedef short int int16_t; +typedef int int32_t; +# if __WORDSIZE == 64 +typedef long int int64_t; +# elif defined __GNUC__ || defined __ICC +__extension__ typedef long long int int64_t; +# endif +# endif + +/* But these were defined by ISO C without the first `_'. */ +typedef unsigned char u_int8_t; +typedef unsigned short int u_int16_t; +typedef unsigned int u_int32_t; +# if __WORDSIZE == 64 +typedef unsigned long int u_int64_t; +# elif defined __GNUC__ || defined __ICC +__extension__ typedef unsigned long long int u_int64_t; +# endif + +typedef int register_t; + +#else + +/* For GCC 2.7 and later, we can use specific type-size attributes. */ +# define __intN_t(N, MODE) \ + typedef int int##N##_t __attribute__ ((__mode__ (MODE))) +# define __u_intN_t(N, MODE) \ + typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE))) + +# ifndef __int8_t_defined +# define __int8_t_defined +__intN_t (8, __QI__); +__intN_t (16, __HI__); +__intN_t (32, __SI__); +__intN_t (64, __DI__); +# endif + +__u_intN_t (8, __QI__); +__u_intN_t (16, __HI__); +__u_intN_t (32, __SI__); +__u_intN_t (64, __DI__); + +typedef int register_t __attribute__ ((__mode__ (__word__))); + + +/* Some code from BIND tests this macro to see if the types above are + defined. */ +#endif +#define __BIT_TYPES_DEFINED__ 1 + + +#ifdef __USE_BSD +/* In BSD is expected to define BYTE_ORDER. */ +# include + +/* It also defines `fd_set' and the FD_* macros for `select'. */ +# include + +/* BSD defines these symbols, so we follow. */ +# include +#endif /* Use BSD. */ + + +#if defined __USE_UNIX98 && !defined __blksize_t_defined +typedef __blksize_t blksize_t; +# define __blksize_t_defined +#endif + +/* Types from the Large File Support interface. */ +#ifndef __USE_FILE_OFFSET64 +# ifndef __blkcnt_t_defined +typedef __blkcnt_t blkcnt_t; /* Type to count number of disk blocks. */ +# define __blkcnt_t_defined +# endif +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#else +# ifndef __blkcnt_t_defined +typedef __blkcnt64_t blkcnt_t; /* Type to count number of disk blocks. */ +# define __blkcnt_t_defined +# endif +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt64_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt64_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#endif + +#ifdef __USE_LARGEFILE64 +typedef __blkcnt64_t blkcnt64_t; /* Type to count number of disk blocks. */ +typedef __fsblkcnt64_t fsblkcnt64_t; /* Type to count file system blocks. */ +typedef __fsfilcnt64_t fsfilcnt64_t; /* Type to count file system inodes. */ +#endif + + +/* Now add the thread types. */ +#if (defined __USE_POSIX199506 || defined __USE_UNIX98) && defined __UCLIBC_HAS_THREADS__ +# include +#endif + +__END_DECLS + +#endif /* sys/types.h */ diff --git a/include/sys/uio.h b/include/sys/uio.h new file mode 100644 index 0000000..1b203f7 --- /dev/null +++ b/include/sys/uio.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UIO_H +#define _SYS_UIO_H 1 + +#include + +#include + +__BEGIN_DECLS + +/* This file defines `struct iovec'. */ +#include + + +/* Read data from file descriptor FD, and put the result in the + buffers described by IOVEC, which is a vector of COUNT `struct iovec's. + The buffers are filled in the order specified. + Operates just like `read' (see ) except that data are + put in IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t readv (int __fd, __const struct iovec *__iovec, int __count); + +/* Write data pointed by the buffers described by IOVEC, which + is a vector of COUNT `struct iovec's, to file descriptor FD. + The data is written in the order specified. + Operates just like `write' (see ) except that the data + are taken from IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t writev (int __fd, __const struct iovec *__iovec, int __count); + +__END_DECLS + +#endif /* sys/uio.h */ diff --git a/include/sys/un.h b/include/sys/un.h new file mode 100644 index 0000000..1fa10e4 --- /dev/null +++ b/include/sys/un.h @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1995, 1996, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UN_H +#define _SYS_UN_H 1 + +#include + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +__BEGIN_DECLS + +/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */ +struct sockaddr_un + { + __SOCKADDR_COMMON (sun_); + char sun_path[108]; /* Path name. */ + }; + + +#ifdef __USE_MISC +# include /* For prototype of `strlen'. */ + +/* Evaluate to actual length of the `sockaddr_un' structure. */ +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif + +__END_DECLS + +#endif /* sys/un.h */ diff --git a/include/sys/unistd.h b/include/sys/unistd.h new file mode 100644 index 0000000..1e823fb --- /dev/null +++ b/include/sys/unistd.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/ustat.h b/include/sys/ustat.h new file mode 100644 index 0000000..7a9cdac --- /dev/null +++ b/include/sys/ustat.h @@ -0,0 +1,38 @@ +/* Header describing obsolete `ustat' interface. + Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * This interface is obsolete. Use instead. + */ + +#ifndef _SYS_USTAT_H +#define _SYS_USTAT_H 1 + +#include + +#include +#include + +__BEGIN_DECLS + +extern int ustat (__dev_t __dev, struct ustat *__ubuf) __THROW; + +__END_DECLS + +#endif /* sys/ustat.h */ diff --git a/include/sys/utsname.h b/include/sys/utsname.h new file mode 100644 index 0000000..ca195cb --- /dev/null +++ b/include/sys/utsname.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1991, 92, 94, 96, 97, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 4.4 System Identification + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifndef _UTSNAME_NODENAME_LENGTH +# define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH +#endif + +/* Structure describing the system and machine. */ +struct utsname + { + /* Name of the implementation of the operating system. */ + char sysname[_UTSNAME_LENGTH]; + + /* Name of this node on the network. */ + char nodename[_UTSNAME_NODENAME_LENGTH]; + + /* Current release level of this implementation. */ + char release[_UTSNAME_LENGTH]; + /* Current version level of this release. */ + char version[_UTSNAME_LENGTH]; + + /* Name of the hardware type the system is running on. */ + char machine[_UTSNAME_LENGTH]; + +#if _UTSNAME_DOMAIN_LENGTH - 0 + /* Name of the domain of this node on the network. */ +# ifdef __USE_GNU + char domainname[_UTSNAME_DOMAIN_LENGTH]; +# else + char __domainname[_UTSNAME_DOMAIN_LENGTH]; +# endif +#endif + }; + +#ifdef __USE_SVID +# define SYS_NMLN _UTSNAME_LENGTH +#endif + + +/* Put information about the system in NAME. */ +extern int uname (struct utsname *__name) __THROW; + + +__END_DECLS + +#endif /* sys/utsname.h */ diff --git a/include/sys/vfs.h b/include/sys/vfs.h new file mode 100644 index 0000000..fa22d31 --- /dev/null +++ b/include/sys/vfs.h @@ -0,0 +1,4 @@ +/* Other systems declare `struct statfs' et al in , + so we have this file to be compatible with programs expecting it. */ + +#include diff --git a/include/sys/vt.h b/include/sys/vt.h new file mode 100644 index 0000000..834abfb --- /dev/null +++ b/include/sys/vt.h @@ -0,0 +1 @@ +#include diff --git a/include/sys/wait.h b/include/sys/wait.h new file mode 100644 index 0000000..81a54fc --- /dev/null +++ b/include/sys/wait.h @@ -0,0 +1,186 @@ +/* Copyright (C) 1991-1994,1996-2001,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 3.2.1 Wait for Process Termination + */ + +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H 1 + +#include + +__BEGIN_DECLS + +#include +#include + +/* These macros could also be defined in . */ +#if !defined _STDLIB_H || !defined __USE_XOPEN +/* This will define the `W*' macros for the flag + bits to `waitpid', `wait3', and `wait4'. */ +# include + +# ifdef __USE_BSD + +/* Lots of hair to allow traditional BSD use of `union wait' + as well as POSIX.1 use of `int' for the status word. */ + +# if defined __GNUC__ && !defined __cplusplus +# define __WAIT_INT(status) \ + (__extension__ (((union { __typeof(status) __in; int __i; }) \ + { .__in = (status) }).__i)) +# else +# define __WAIT_INT(status) (*(__const int *) &(status)) +# endif + +/* This is the type of the argument to `wait'. The funky union + causes redeclarations with ether `int *' or `union wait *' to be + allowed without complaint. __WAIT_STATUS_DEFN is the type used in + the actual function definitions. */ + +# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus +# define __WAIT_STATUS void * +# define __WAIT_STATUS_DEFN void * +# else +/* This works in GCC 2.6.1 and later. */ +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# define __WAIT_STATUS_DEFN int * +# endif + +# else /* Don't use BSD. */ + +# define __WAIT_INT(status) (status) +# define __WAIT_STATUS int * +# define __WAIT_STATUS_DEFN int * + +# endif /* Use BSD. */ + +/* This will define all the `__W*' macros. */ +# include + +# define WEXITSTATUS(status) __WEXITSTATUS(__WAIT_INT(status)) +# define WTERMSIG(status) __WTERMSIG(__WAIT_INT(status)) +# define WSTOPSIG(status) __WSTOPSIG(__WAIT_INT(status)) +# define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) +# define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) +# define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +# if 0 /*def __WIFCONTINUED*/ +# define WIFCONTINUED(status) __WIFCONTINUED(__WAIT_INT(status)) +# endif +#endif /* not included. */ + +#ifdef __USE_BSD +# define WCOREFLAG __WCOREFLAG +# define WCOREDUMP(status) __WCOREDUMP(__WAIT_INT(status)) +# define W_EXITCODE(ret, sig) __W_EXITCODE(ret, sig) +# define W_STOPCODE(sig) __W_STOPCODE(sig) +#endif + +/* The following values are used by the `waitid' function. */ +#if defined __USE_SVID || defined __USE_XOPEN +typedef enum +{ + P_ALL, /* Wait for any child. */ + P_PID, /* Wait for specified process. */ + P_PGID /* Wait for members of process group. */ +} idtype_t; +#endif + + +/* Wait for a child to die. When one does, put its status in *STAT_LOC + and return its process ID. For errors, return (pid_t) -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern __pid_t wait (__WAIT_STATUS __stat_loc); + +#ifdef __USE_BSD +/* Special values for the PID argument to `waitpid' and `wait4'. */ +# define WAIT_ANY (-1) /* Any process. */ +# define WAIT_MYPGRP 0 /* Any process in my process group. */ +#endif + +/* Wait for a child matching PID to die. + If PID is greater than 0, match any process whose process ID is PID. + If PID is (pid_t) -1, match any process. + If PID is (pid_t) 0, match any process with the + same process group as the current process. + If PID is less than -1, match any process whose + process group is the absolute value of PID. + If the WNOHANG bit is set in OPTIONS, and that child + is not already dead, return (pid_t) 0. If successful, + return PID and store the dead child's status in STAT_LOC. + Return (pid_t) -1 for errors. If the WUNTRACED bit is + set in OPTIONS, return status for stopped children; otherwise don't. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options); + +#if defined __USE_SVID || defined __USE_XOPEN +# define __need_siginfo_t +# include +/* Wait for a childing matching IDTYPE and ID to change the status and + place appropriate information in *INFOP. + If IDTYPE is P_PID, match any process whose process ID is ID. + If IDTYPE is P_PGID, match any process whose process group is ID. + If IDTYPE is P_ALL, match any process. + If the WNOHANG bit is set in OPTIONS, and that child + is not already dead, clear *INFOP and return 0. If successful, store + exit code and status in *INFOP. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop, + int __options); +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* This being here makes the prototypes valid whether or not + we have already included to define `struct rusage'. */ +struct rusage; + +/* Wait for a child to exit. When one does, put its status in *STAT_LOC and + return its process ID. For errors return (pid_t) -1. If USAGE is not + nil, store information about the child's resource usage there. If the + WUNTRACED bit is set in OPTIONS, return status for stopped children; + otherwise don't. */ +extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options, + struct rusage * __usage) __THROW; +#endif + +#ifdef __USE_BSD +/* This being here makes the prototypes valid whether or not + we have already included to define `struct rusage'. */ +struct rusage; + +/* PID is like waitpid. Other args are like wait3. */ +extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options, + struct rusage *__usage) __THROW; +#endif /* Use BSD. */ + + +__END_DECLS + +#endif /* sys/wait.h */ diff --git a/include/sys/xattr.h b/include/sys/xattr.h new file mode 100644 index 0000000..2737f90 --- /dev/null +++ b/include/sys/xattr.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_XATTR_H +#define _SYS_XATTR_H 1 + +#include +#include + + +__BEGIN_DECLS + +/* The following constants should be used for the fifth parameter of + `*setxattr'. */ +enum +{ + XATTR_CREATE = 1, /* set value, fail if attr already exists. */ +#define XATTR_CREATE XATTR_CREATE + XATTR_REPLACE = 2 /* set value, fail if attr does not exist. */ +#define XATTR_REPLACE XATTR_REPLACE +}; + +/* Set the attribute NAME of the file pointed to by PATH to VALUE (which + is SIZE bytes long). Return 0 on success, -1 for errors. */ +extern int setxattr (__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) + __THROW; + +/* Set the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long), not following symlinks for the last pathname component. + Return 0 on success, -1 for errors. */ +extern int lsetxattr (__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) + __THROW; + +/* Set the attribute NAME of the file descriptor FD to VALUE (which is SIZE + bytes long). Return 0 on success, -1 for errors. */ +extern int fsetxattr (int __fd, __const char *__name, __const void *__value, + size_t __size, int __flags) __THROW; + +/* Get the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long). Return 0 on success, -1 for errors. */ +extern ssize_t getxattr (__const char *__path, __const char *__name, + void *__value, size_t __size) __THROW; + +/* Get the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long), not following symlinks for the last pathname component. + Return 0 on success, -1 for errors. */ +extern ssize_t lgetxattr (__const char *__path, __const char *__name, + void *__value, size_t __size) __THROW; + +/* Get the attribute NAME of the file descriptor FD to VALUE (which is SIZE + bytes long). Return 0 on success, -1 for errors. */ +extern ssize_t fgetxattr (int __fd, __const char *__name, void *__value, + size_t __size) __THROW; + +/* List attributes of the file pointed to by PATH into the user-supplied + buffer LIST (which is SIZE bytes big). Return 0 on success, -1 for + errors. */ +extern ssize_t listxattr (__const char *__path, char *__list, size_t __size) + __THROW; + +/* List attributes of the file pointed to by PATH into the user-supplied + buffer LIST (which is SIZE bytes big), not following symlinks for the + last pathname component. Return 0 on success, -1 for errors. */ +extern ssize_t llistxattr (__const char *__path, char *__list, size_t __size) + __THROW; + +/* List attributes of the file descriptor FD into the user-supplied buffer + LIST (which is SIZE bytes big). Return 0 on success, -1 for errors. */ +extern ssize_t flistxattr (int __fd, char *__list, size_t __size) + __THROW; + +/* Remove the attribute NAME from the file pointed to by PATH. Return 0 + on success, -1 for errors. */ +extern int removexattr (__const char *__path, __const char *__name) __THROW; + +/* Remove the attribute NAME from the file pointed to by PATH, not + following symlinks for the last pathname component. Return 0 on + success, -1 for errors. */ +extern int lremovexattr (__const char *__path, __const char *__name) __THROW; + +/* Remove the attribute NAME from the file descriptor FD. Return 0 on + success, -1 for errors. */ +extern int fremovexattr (int __fd, __const char *__name) __THROW; + +__END_DECLS + +#endif /* sys/xattr.h */ diff --git a/include/syscall.h b/include/syscall.h new file mode 100644 index 0000000..4c30578 --- /dev/null +++ b/include/syscall.h @@ -0,0 +1 @@ +#include diff --git a/include/sysexits.h b/include/sysexits.h new file mode 100644 index 0000000..37246b6 --- /dev/null +++ b/include/sysexits.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYSEXITS_H +#define _SYSEXITS_H 1 + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* sysexits.h */ diff --git a/include/syslog.h b/include/syslog.h new file mode 100644 index 0000000..830b492 --- /dev/null +++ b/include/syslog.h @@ -0,0 +1 @@ +#include diff --git a/include/tar.h b/include/tar.h new file mode 100644 index 0000000..ddfef75 --- /dev/null +++ b/include/tar.h @@ -0,0 +1,108 @@ +/* Extended tar format from POSIX.1. + Copyright (C) 1992, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by David J. MacKenzie. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TAR_H +#define _TAR_H 1 + +/* A tar archive consists of 512-byte blocks. + Each file in the archive has a header block followed by 0+ data blocks. + Two blocks of NUL bytes indicate the end of the archive. */ + +/* The fields of header blocks: + All strings are stored as ISO 646 (approximately ASCII) strings. + + Fields are numeric unless otherwise noted below; numbers are ISO 646 + representations of octal numbers, with leading zeros as needed. + + linkname is only valid when typeflag==LNKTYPE. It doesn't use prefix; + files that are links to pathnames >100 chars long can not be stored + in a tar archive. + + If typeflag=={LNKTYPE,SYMTYPE,DIRTYPE} then size must be 0. + + devmajor and devminor are only valid for typeflag=={BLKTYPE,CHRTYPE}. + + chksum contains the sum of all 512 bytes in the header block, + treating each byte as an 8-bit unsigned value and treating the + 8 bytes of chksum as blank characters. + + uname and gname are used in preference to uid and gid, if those + names exist locally. + + Field Name Byte Offset Length in Bytes Field Type + name 0 100 NUL-terminated if NUL fits + mode 100 8 + uid 108 8 + gid 116 8 + size 124 12 + mtime 136 12 + chksum 148 8 + typeflag 156 1 see below + linkname 157 100 NUL-terminated if NUL fits + magic 257 6 must be TMAGIC (NUL term.) + version 263 2 must be TVERSION + uname 265 32 NUL-terminated + gname 297 32 NUL-terminated + devmajor 329 8 + devminor 337 8 + prefix 345 155 NUL-terminated if NUL fits + + If the first character of prefix is '\0', the file name is name; + otherwise, it is prefix/name. Files whose pathnames don't fit in that + length can not be stored in a tar archive. */ + +/* The bits in mode: */ +#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 + +/* The values for typeflag: + Values 'A'-'Z' are reserved for custom implementations. + All other values are reserved for future POSIX.1 revisions. */ + +#define REGTYPE '0' /* Regular file (preferred code). */ +#define AREGTYPE '\0' /* Regular file (alternate code). */ +#define LNKTYPE '1' /* Hard link. */ +#define SYMTYPE '2' /* Symbolic link (hard if not supported). */ +#define CHRTYPE '3' /* Character special. */ +#define BLKTYPE '4' /* Block special. */ +#define DIRTYPE '5' /* Directory. */ +#define FIFOTYPE '6' /* Named pipe. */ +#define CONTTYPE '7' /* Contiguous file */ + /* (regular file if not supported). */ + +/* Contents of magic field and its length. */ +#define TMAGIC "ustar" +#define TMAGLEN 6 + +/* Contents of the version field and its length. */ +#define TVERSION "00" +#define TVERSLEN 2 + +#endif /* tar.h */ diff --git a/include/termio.h b/include/termio.h new file mode 100644 index 0000000..0e610f0 --- /dev/null +++ b/include/termio.h @@ -0,0 +1,6 @@ +/* Compatible for old `struct termio' ioctl interface. + This is obsolete; use the POSIX.1 `struct termios' interface + defined in instead. */ + +#include +#include diff --git a/include/termios.h b/include/termios.h new file mode 100644 index 0000000..9698b1f --- /dev/null +++ b/include/termios.h @@ -0,0 +1,110 @@ +/* Copyright (C) 1991,92,93,94,96,97,98,99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 7.1-2 General Terminal Interface + */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H 1 + +#include +#ifdef __USE_UNIX98 +/* We need `pid_t'. */ +# include +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif + +__BEGIN_DECLS + +/* Get the system-dependent definitions of `struct termios', `tcflag_t', + `cc_t', `speed_t', and all the macros specifying the flag bits. */ +#include + +#ifdef __USE_BSD +/* Compare a character C to a value VAL from the `c_cc' array in a + `struct termios'. If VAL is _POSIX_VDISABLE, no character can match it. */ +# define CCEQ(val, c) ((c) == (val) && (val) != _POSIX_VDISABLE) +#endif + +/* Return the output baud rate stored in *TERMIOS_P. */ +extern speed_t cfgetospeed (__const struct termios *__termios_p) __THROW; + +/* Return the input baud rate stored in *TERMIOS_P. */ +extern speed_t cfgetispeed (__const struct termios *__termios_p) __THROW; + +/* Set the output baud rate stored in *TERMIOS_P to SPEED. */ +extern int cfsetospeed (struct termios *__termios_p, speed_t __speed) __THROW; + +/* Set the input baud rate stored in *TERMIOS_P to SPEED. */ +extern int cfsetispeed (struct termios *__termios_p, speed_t __speed) __THROW; + +#ifdef __USE_BSD +/* Set both the input and output baud rates in *TERMIOS_OP to SPEED. */ +extern int cfsetspeed (struct termios *__termios_p, speed_t __speed) __THROW; +#endif + + +/* Put the state of FD into *TERMIOS_P. */ +extern int tcgetattr (int __fd, struct termios *__termios_p) __THROW; + +/* Set the state of FD to *TERMIOS_P. + Values for OPTIONAL_ACTIONS (TCSA*) are in . */ +extern int tcsetattr (int __fd, int __optional_actions, + __const struct termios *__termios_p) __THROW; + + +#ifdef __USE_BSD +/* Set *TERMIOS_P to indicate raw mode. */ +extern void cfmakeraw (struct termios *__termios_p) __THROW; +#endif + +/* Send zero bits on FD. */ +extern int tcsendbreak (int __fd, int __duration) __THROW; + +/* Wait for pending output to be written on FD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int tcdrain (int __fd); + +/* Flush pending data on FD. + Values for QUEUE_SELECTOR (TC{I,O,IO}FLUSH) are in . */ +extern int tcflush (int __fd, int __queue_selector) __THROW; + +/* Suspend or restart transmission on FD. + Values for ACTION (TC[IO]{OFF,ON}) are in . */ +extern int tcflow (int __fd, int __action) __THROW; + + +#ifdef __USE_UNIX98 +/* Get process group ID for session leader for controlling terminal FD. */ +extern __pid_t tcgetsid (int __fd) __THROW; +#endif + + +#ifdef __USE_BSD +# include +#endif + +__END_DECLS + +#endif /* termios.h */ diff --git a/include/tgmath.h b/include/tgmath.h new file mode 100644 index 0000000..685a345 --- /dev/null +++ b/include/tgmath.h @@ -0,0 +1,430 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.22 Type-generic math + */ + +#ifndef _TGMATH_H +#define _TGMATH_H 1 + +/* Include the needed headers. */ +#include +#include + + +/* Since `complex' is currently not really implemented in most C compilers + and if it is implemented, the implementations differ. This makes it + quite difficult to write a generic implementation of this header. We + do not try this for now and instead concentrate only on GNU CC. Once + we have more information support for other compilers might follow. */ + +#if __GNUC_PREREQ (2, 7) + +# ifndef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __tgml(fct) fct +# else +# define __tgml(fct) fct ## l +# endif + +/* This is ugly but unless gcc gets appropriate builtins we have to do + something like this. Don't ask how it works. */ + +/* 1 if 'type' is a floating type, 0 if 'type' is an integer type. + Allows for _Bool. Expands to an integer constant expression. */ +# define __floating_type(type) (((type) 0.25) && ((type) 0.25 - 1)) + +/* The tgmath real type for T, where E is 0 if T is an integer type and + 1 for a floating type. */ +# define __tgmath_real_type_sub(T, E) \ + __typeof__(*(0 ? (__typeof__ (0 ? (double *) 0 : (void *) (E))) 0 \ + : (__typeof__ (0 ? (T *) 0 : (void *) (!(E)))) 0)) + +/* The tgmath real type of EXPR. */ +# define __tgmath_real_type(expr) \ + __tgmath_real_type_sub(__typeof__(expr), __floating_type(__typeof__(expr))) + + +/* We have two kinds of generic macros: to support functions which are + only defined on real valued parameters and those which are defined + for complex functions as well. */ +# define __TGMATH_UNARY_REAL_ONLY(Val, Fct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (Val) == sizeof (double) \ + || __builtin_classify_type (Val) != 8) \ + __tgmres = Fct (Val); \ + else if (sizeof (Val) == sizeof (float)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = __tgml(Fct) (Val); \ + __tgmres; })) + +# define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \ + (__extension__ ({ __tgmath_real_type (Val1) __tgmres; \ + if (sizeof (Val1) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8) \ + __tgmres = Fct (Val1, Val2); \ + else if (sizeof (Val1) == sizeof (float)) \ + __tgmres = Fct##f (Val1, Val2); \ + else \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + __tgmres; })) + +# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8) \ + __tgmres = Fct (Val1, Val2); \ + else \ + __tgmres = Fct##f (Val1, Val2); \ + __tgmres; })) + +# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2, Val3); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8) \ + __tgmres = Fct (Val1, Val2, Val3); \ + else \ + __tgmres = Fct##f (Val1, Val2, Val3); \ + __tgmres; })) + +# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2) + (Val3)) __tgmres;\ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double) \ + || sizeof (Val3) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2) \ + + (Val3)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2, Val3); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || sizeof (Val3) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8 \ + || __builtin_classify_type (Val3) != 8) \ + __tgmres = Fct (Val1, Val2, Val3); \ + else \ + __tgmres = Fct##f (Val1, Val2, Val3); \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (__real__ (Val)) > sizeof (double) \ + && __builtin_classify_type (__real__ (Val)) == 8) \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = __tgml(Fct) (Val); \ + else \ + __tgmres = __tgml(Cfct) (Val); \ + } \ + else if (sizeof (__real__ (Val)) == sizeof (double) \ + || __builtin_classify_type (__real__ (Val)) \ + != 8) \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = Fct (Val); \ + else \ + __tgmres = Cfct (Val); \ + } \ + else \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = Cfct##f (Val); \ + } \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_UNARY_IMAG_ONLY(Val, Fct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (Val) == sizeof (__complex__ double) \ + || __builtin_classify_type (__real__ (Val)) != 8) \ + __tgmres = Fct (Val); \ + else if (sizeof (Val) == sizeof (__complex__ float)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = __tgml(Fct) (Val); \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (__real__ (Val1)) > sizeof (double) \ + || sizeof (__real__ (Val2)) > sizeof (double)) \ + && __builtin_classify_type (__real__ (Val1) \ + + __real__ (Val2)) \ + == 8) \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + else \ + __tgmres = __tgml(Cfct) (Val1, Val2); \ + } \ + else if (sizeof (__real__ (Val1)) == sizeof (double) \ + || sizeof (__real__ (Val2)) == sizeof(double) \ + || (__builtin_classify_type (__real__ (Val1)) \ + != 8) \ + || (__builtin_classify_type (__real__ (Val2)) \ + != 8)) \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = Fct (Val1, Val2); \ + else \ + __tgmres = Cfct (Val1, Val2); \ + } \ + else \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = Fct##f (Val1, Val2); \ + else \ + __tgmres = Cfct##f (Val1, Val2); \ + } \ + __tgmres; })) +#else +# error "Unsupported compiler; you cannot use " +#endif + + +/* Unary functions defined for real and complex values. */ + + +/* Trigonometric functions. */ + +/* Arc cosine of X. */ +#define acos(Val) __TGMATH_UNARY_REAL_IMAG (Val, acos, cacos) +/* Arc sine of X. */ +#define asin(Val) __TGMATH_UNARY_REAL_IMAG (Val, asin, casin) +/* Arc tangent of X. */ +#define atan(Val) __TGMATH_UNARY_REAL_IMAG (Val, atan, catan) +/* Arc tangent of Y/X. */ +#define atan2(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, atan2) + +/* Cosine of X. */ +#define cos(Val) __TGMATH_UNARY_REAL_IMAG (Val, cos, ccos) +/* Sine of X. */ +#define sin(Val) __TGMATH_UNARY_REAL_IMAG (Val, sin, csin) +/* Tangent of X. */ +#define tan(Val) __TGMATH_UNARY_REAL_IMAG (Val, tan, ctan) + + +/* Hyperbolic functions. */ + +/* Hyperbolic arc cosine of X. */ +#define acosh(Val) __TGMATH_UNARY_REAL_IMAG (Val, acosh, cacosh) +/* Hyperbolic arc sine of X. */ +#define asinh(Val) __TGMATH_UNARY_REAL_IMAG (Val, asinh, casinh) +/* Hyperbolic arc tangent of X. */ +#define atanh(Val) __TGMATH_UNARY_REAL_IMAG (Val, atanh, catanh) + +/* Hyperbolic cosine of X. */ +#define cosh(Val) __TGMATH_UNARY_REAL_IMAG (Val, cosh, ccosh) +/* Hyperbolic sine of X. */ +#define sinh(Val) __TGMATH_UNARY_REAL_IMAG (Val, sinh, csinh) +/* Hyperbolic tangent of X. */ +#define tanh(Val) __TGMATH_UNARY_REAL_IMAG (Val, tanh, ctanh) + + +/* Exponential and logarithmic functions. */ + +/* Exponential function of X. */ +#define exp(Val) __TGMATH_UNARY_REAL_IMAG (Val, exp, cexp) + +/* Break VALUE into a normalized fraction and an integral power of 2. */ +#define frexp(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, frexp) + +/* X times (two to the EXP power). */ +#define ldexp(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, ldexp) + +/* Natural logarithm of X. */ +#define log(Val) __TGMATH_UNARY_REAL_IMAG (Val, log, clog) + +/* Base-ten logarithm of X. */ +#ifdef __USE_GNU +# define log10(Val) __TGMATH_UNARY_REAL_IMAG (Val, log10, __clog10) +#else +# define log10(Val) __TGMATH_UNARY_REAL_ONLY (Val, log10) +#endif + +/* Return exp(X) - 1. */ +#define expm1(Val) __TGMATH_UNARY_REAL_ONLY (Val, expm1) + +/* Return log(1 + X). */ +#define log1p(Val) __TGMATH_UNARY_REAL_ONLY (Val, log1p) + +/* Return the base 2 signed integral exponent of X. */ +#define logb(Val) __TGMATH_UNARY_REAL_ONLY (Val, logb) + +/* Compute base-2 exponential of X. */ +#define exp2(Val) __TGMATH_UNARY_REAL_ONLY (Val, exp2) + +/* Compute base-2 logarithm of X. */ +#define log2(Val) __TGMATH_UNARY_REAL_ONLY (Val, log2) + + +/* Power functions. */ + +/* Return X to the Y power. */ +#define pow(Val1, Val2) __TGMATH_BINARY_REAL_IMAG (Val1, Val2, pow, cpow) + +/* Return the square root of X. */ +#define sqrt(Val) __TGMATH_UNARY_REAL_IMAG (Val, sqrt, csqrt) + +/* Return `sqrt(X*X + Y*Y)'. */ +#define hypot(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, hypot) + +/* Return the cube root of X. */ +#define cbrt(Val) __TGMATH_UNARY_REAL_ONLY (Val, cbrt) + + +/* Nearest integer, absolute value, and remainder functions. */ + +/* Smallest integral value not less than X. */ +#define ceil(Val) __TGMATH_UNARY_REAL_ONLY (Val, ceil) + +/* Absolute value of X. */ +#define fabs(Val) __TGMATH_UNARY_REAL_IMAG (Val, fabs, cabs) + +/* Largest integer not greater than X. */ +#define floor(Val) __TGMATH_UNARY_REAL_ONLY (Val, floor) + +/* Floating-point modulo remainder of X/Y. */ +#define fmod(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmod) + +/* Round X to integral valuein floating-point format using current + rounding direction, but do not raise inexact exception. */ +#define nearbyint(Val) __TGMATH_UNARY_REAL_ONLY (Val, nearbyint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +#define round(Val) __TGMATH_UNARY_REAL_ONLY (Val, round) + +/* Round X to the integral value in floating-point format nearest but + not larger in magnitude. */ +#define trunc(Val) __TGMATH_UNARY_REAL_ONLY (Val, trunc) + +/* Compute remainder of X and Y and put in *QUO a value with sign of x/y + and magnitude congruent `mod 2^n' to the magnitude of the integral + quotient x/y, with n >= 3. */ +#define remquo(Val1, Val2, Val3) \ + __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY (Val1, Val2, Val3, remquo) + +/* Round X to nearest integral value according to current rounding + direction. */ +#define lrint(Val) __TGMATH_UNARY_REAL_ONLY (Val, lrint) +#define llrint(Val) __TGMATH_UNARY_REAL_ONLY (Val, llrint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +#define lround(Val) __TGMATH_UNARY_REAL_ONLY (Val, lround) +#define llround(Val) __TGMATH_UNARY_REAL_ONLY (Val, llround) + + +/* Return X with its signed changed to Y's. */ +#define copysign(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, copysign) + +/* Error and gamma functions. */ +#define erf(Val) __TGMATH_UNARY_REAL_ONLY (Val, erf) +#define erfc(Val) __TGMATH_UNARY_REAL_ONLY (Val, erfc) +#define tgamma(Val) __TGMATH_UNARY_REAL_ONLY (Val, tgamma) +#define lgamma(Val) __TGMATH_UNARY_REAL_ONLY (Val, lgamma) + + +/* Return the integer nearest X in the direction of the + prevailing rounding mode. */ +#define rint(Val) __TGMATH_UNARY_REAL_ONLY (Val, rint) + +/* Return X + epsilon if X < Y, X - epsilon if X > Y. */ +#define nextafter(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, nextafter) +#define nexttoward(Val1, Val2) \ + __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, nexttoward) + +/* Return the remainder of integer divison X / Y with infinite precision. */ +#define remainder(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, remainder) + +/* Return X times (2 to the Nth power). */ +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +# define scalb(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, scalb) +#endif + +/* Return X times (2 to the Nth power). */ +#define scalbn(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, scalbn) + +/* Return X times (2 to the Nth power). */ +#define scalbln(Val1, Val2) \ + __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, scalbln) + +/* Return the binary exponent of X, which must be nonzero. */ +#define ilogb(Val) __TGMATH_UNARY_REAL_ONLY (Val, ilogb) + + +/* Return positive difference between X and Y. */ +#define fdim(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fdim) + +/* Return maximum numeric value from X and Y. */ +#define fmax(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmax) + +/* Return minimum numeric value from X and Y. */ +#define fmin(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmin) + + +/* Multiply-add function computed as a ternary operation. */ +#define fma(Val1, Val2, Val3) \ + __TGMATH_TERNARY_REAL_ONLY (Val1, Val2, Val3, fma) + + +/* Absolute value, conjugates, and projection. */ + +/* Argument value of Z. */ +#define carg(Val) __TGMATH_UNARY_IMAG_ONLY (Val, carg) + +/* Complex conjugate of Z. */ +#define conj(Val) __TGMATH_UNARY_IMAG_ONLY (Val, conj) + +/* Projection of Z onto the Riemann sphere. */ +#define cproj(Val) __TGMATH_UNARY_IMAG_ONLY (Val, cproj) + + +/* Decomposing complex values. */ + +/* Imaginary part of Z. */ +#define cimag(Val) __TGMATH_UNARY_IMAG_ONLY (Val, cimag) + +/* Real part of Z. */ +#define creal(Val) __TGMATH_UNARY_IMAG_ONLY (Val, creal) + +#endif /* tgmath.h */ diff --git a/include/time.h b/include/time.h new file mode 100644 index 0000000..f6863ed --- /dev/null +++ b/include/time.h @@ -0,0 +1,445 @@ +/* Copyright (C) 1991-1999,2000,2001,2002,2003,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.23 Date and time + */ + +#ifndef _TIME_H + +#if (! defined __need_time_t && !defined __need_clock_t && \ + ! defined __need_timespec) +# define _TIME_H 1 +# include + +__BEGIN_DECLS + +#endif + +#ifdef _TIME_H +/* Get size_t and NULL from . */ +# define __need_size_t +# define __need_NULL +# include + +/* This defines CLOCKS_PER_SEC, which is the number of processor clock + ticks per second. */ +# include + +/* This is the obsolete POSIX.1-1988 name for the same constant. */ +# if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K +# ifndef CLK_TCK +# define CLK_TCK CLOCKS_PER_SEC +# endif +# endif + +#endif /* included. */ + +#if !defined __clock_t_defined && (defined _TIME_H || defined __need_clock_t) +# define __clock_t_defined 1 + +# include + +__BEGIN_NAMESPACE_STD +/* Returned by `clock'. */ +typedef __clock_t clock_t; +__END_NAMESPACE_STD +#if defined __USE_XOPEN || defined __USE_POSIX || defined __USE_MISC +__USING_NAMESPACE_STD(clock_t) +#endif + +#endif /* clock_t not defined and or need clock_t. */ +#undef __need_clock_t + +#if !defined __time_t_defined && (defined _TIME_H || defined __need_time_t) +# define __time_t_defined 1 + +# include + +__BEGIN_NAMESPACE_STD +/* Returned by `time'. */ +typedef __time_t time_t; +__END_NAMESPACE_STD +#if defined __USE_POSIX || defined __USE_MISC || defined __USE_SVID +__USING_NAMESPACE_STD(time_t) +#endif + +#endif /* time_t not defined and or need time_t. */ +#undef __need_time_t + +#if !defined __clockid_t_defined && \ + ((defined _TIME_H && defined __USE_POSIX199309) || defined __need_clockid_t) +# define __clockid_t_defined 1 + +# include + +/* Clock ID used in clock and timer functions. */ +typedef __clockid_t clockid_t; + +#endif /* clockid_t not defined and or need clockid_t. */ +#undef __clockid_time_t + +#if !defined __timer_t_defined && \ + ((defined _TIME_H && defined __USE_POSIX199309) || defined __need_timer_t) +# define __timer_t_defined 1 + +# include + +/* Timer ID returned by `timer_create'. */ +typedef __timer_t timer_t; + +#endif /* timer_t not defined and or need timer_t. */ +#undef __need_timer_t + + +#if !defined __timespec_defined && \ + ((defined _TIME_H && \ + (defined __USE_POSIX199309 || defined __USE_MISC)) || \ + defined __need_timespec) +# define __timespec_defined 1 + +# include /* This defines __time_t for us. */ + +/* POSIX.1b structure for a time value. This is like a `struct timeval' but + has nanoseconds instead of microseconds. */ +struct timespec + { + __time_t tv_sec; /* Seconds. */ + long int tv_nsec; /* Nanoseconds. */ + }; + +#endif /* timespec not defined and or need timespec. */ +#undef __need_timespec + + +#ifdef _TIME_H +__BEGIN_NAMESPACE_STD +/* Used by other time functions. */ +struct tm +{ + int tm_sec; /* Seconds. [0-60] (1 leap second) */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year - 1900. */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* DST. [-1/0/1]*/ + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +#ifdef __USE_BSD + long int tm_gmtoff; /* Seconds east of UTC. */ + __const char *tm_zone; /* Timezone abbreviation. */ +#else + long int __tm_gmtoff; /* Seconds east of UTC. */ + __const char *__tm_zone; /* Timezone abbreviation. */ +#endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ +}; +__END_NAMESPACE_STD +#if defined __USE_XOPEN || defined __USE_POSIX || defined __USE_MISC +__USING_NAMESPACE_STD(tm) +#endif + + +#ifdef __USE_POSIX199309 +/* POSIX.1b structure for timer start values and intervals. */ +struct itimerspec + { + struct timespec it_interval; + struct timespec it_value; + }; + +/* We can use a simple forward declaration. */ +struct sigevent; + +#endif /* POSIX.1b */ + +#ifdef __USE_XOPEN2K +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif + + +__BEGIN_NAMESPACE_STD +/* Time used by the program so far (user time + system time). + The result / CLOCKS_PER_SECOND is program time in seconds. */ +extern clock_t clock (void) __THROW; + +/* Return the current time and put it in *TIMER if TIMER is not NULL. */ +extern time_t time (time_t *__timer) __THROW; + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return the difference between TIME1 and TIME0. */ +extern double difftime (time_t __time1, time_t __time0) + __THROW __attribute__ ((__const__)); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Return the `time_t' representation of TP and normalize TP. */ +extern time_t mktime (struct tm *__tp) __THROW; + + +/* Format TP into S according to FORMAT. + Write no more than MAXSIZE characters and return the number + of characters written, or 0 if it would exceed MAXSIZE. */ +extern size_t strftime (char *__restrict __s, size_t __maxsize, + __const char *__restrict __format, + __const struct tm *__restrict __tp) __THROW; +__END_NAMESPACE_STD + +# ifdef __USE_XOPEN +/* Parse S according to FORMAT and store binary time information in TP. + The return value is a pointer to the first unparsed character in S. */ +extern char *strptime (__const char *__restrict __s, + __const char *__restrict __fmt, struct tm *__tp) + __THROW; +# endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +# ifdef __USE_GNU +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ +# include + +extern size_t strftime_l (char *__restrict __s, size_t __maxsize, + __const char *__restrict __format, + __const struct tm *__restrict __tp, + __locale_t __loc) __THROW; + +extern char *strptime_l (__const char *__restrict __s, + __const char *__restrict __fmt, struct tm *__tp, + __locale_t __loc) __THROW; +# endif +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the `struct tm' representation of *TIMER + in Universal Coordinated Time (aka Greenwich Mean Time). */ +extern struct tm *gmtime (__const time_t *__timer) __THROW; + +/* Return the `struct tm' representation + of *TIMER in the local timezone. */ +extern struct tm *localtime (__const time_t *__timer) __THROW; +__END_NAMESPACE_STD + +# if defined __USE_POSIX || defined __USE_MISC +/* Return the `struct tm' representation of *TIMER in UTC, + using *TP to store the result. */ +extern struct tm *gmtime_r (__const time_t *__restrict __timer, + struct tm *__restrict __tp) __THROW; + +/* Return the `struct tm' representation of *TIMER in local time, + using *TP to store the result. */ +extern struct tm *localtime_r (__const time_t *__restrict __timer, + struct tm *__restrict __tp) __THROW; +# endif /* POSIX or misc */ + +__BEGIN_NAMESPACE_STD +/* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n" + that is the representation of TP in this format. */ +extern char *asctime (__const struct tm *__tp) __THROW; + +/* Equivalent to `asctime (localtime (timer))'. */ +extern char *ctime (__const time_t *__timer) __THROW; +__END_NAMESPACE_STD + +# if defined __USE_POSIX || defined __USE_MISC +/* Reentrant versions of the above functions. */ + +/* Return in BUF a string of the form "Day Mon dd hh:mm:ss yyyy\n" + that is the representation of TP in this format. */ +extern char *asctime_r (__const struct tm *__restrict __tp, + char *__restrict __buf) __THROW; + +/* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'. */ +extern char *ctime_r (__const time_t *__restrict __timer, + char *__restrict __buf) __THROW; +# endif /* POSIX or misc */ + + +/* Defined in localtime.c. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: __tzname, __daylight, and __timezone have a prototype but are not defined." +extern char *__tzname[2]; /* Current timezone names. */ +extern int __daylight; /* If daylight-saving time is ever in use. */ +extern long int __timezone; /* Seconds west of UTC. */ +#endif /* __UCLIBC_MJN3_ONLY__ */ + + +# ifdef __USE_POSIX +/* Same as above. */ +extern char *tzname[2]; + +/* Set time conversion information from the TZ environment variable. + If TZ is not defined, a locale-dependent default is used. */ +extern void tzset (void) __THROW; +# endif + +# if defined __USE_SVID || defined __USE_XOPEN +extern int daylight; +extern long int timezone; +# endif + +# ifdef __USE_SVID +/* Set the system time to *WHEN. + This call is restricted to the superuser. */ +extern int stime (__const time_t *__when) __THROW; +# endif + + +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + + +# ifdef __USE_MISC +/* Miscellaneous functions many Unices inherited from the public domain + localtime package. These are included only for compatibility. */ + +/* Like `mktime', but for TP represents Universal Time, not local time. */ +extern time_t timegm (struct tm *__tp) __THROW; + +/* Another name for `mktime'. */ +extern time_t timelocal (struct tm *__tp) __THROW; + +/* Return the number of days in YEAR. */ +extern int dysize (int __year) __THROW __attribute__ ((__const__)); +# endif + + +# ifdef __USE_POSIX199309 +# if defined __UCLIBC_HAS_REALTIME__ +/* Pause execution for a number of nanoseconds. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int nanosleep (__const struct timespec *__requested_time, + struct timespec *__remaining); + + +/* Get resolution of clock CLOCK_ID. */ +extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW; +libc_hidden_proto(clock_getres) + +/* Get current value of clock CLOCK_ID and store it in TP. */ +extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW; + +/* Set clock CLOCK_ID to value TP. */ +extern int clock_settime (clockid_t __clock_id, __const struct timespec *__tp) + __THROW; +#endif /* __UCLIBC_HAS_REALTIME__ */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: a bunch of unimplemented function prototypes." +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* High-resolution sleep with the specified clock. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int clock_nanosleep (clockid_t __clock_id, int __flags, + __const struct timespec *__req, + struct timespec *__rem); + +/* Return clock ID for CPU-time clock. */ +extern int clock_getcpuclockid (pid_t __pid, clockid_t *__clock_id) __THROW; +# endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +# if defined __UCLIBC_HAS_REALTIME__ +/* Create new per-process timer using CLOCK_ID. */ +extern int timer_create (clockid_t __clock_id, + struct sigevent *__restrict __evp, + timer_t *__restrict __timerid) __THROW; + +/* Delete timer TIMERID. */ +extern int timer_delete (timer_t __timerid) __THROW; + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +extern int timer_settime (timer_t __timerid, int __flags, + __const struct itimerspec *__restrict __value, + struct itimerspec *__restrict __ovalue) __THROW; + +/* Get current value of timer TIMERID and store it in VLAUE. */ +extern int timer_gettime (timer_t __timerid, struct itimerspec *__value) + __THROW; + +/* Get expiration overrun for timer TIMERID. */ +extern int timer_getoverrun (timer_t __timerid) __THROW; +# endif /* __UCLIBC_HAS_REALTIME__ */ +# endif /* __USE_POSIX199309 */ + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: a bunch of unimplemented function prototypes." +# ifdef __USE_XOPEN_EXTENDED +/* Set to one of the following values to indicate an error. + 1 the DATEMSK environment variable is null or undefined, + 2 the template file cannot be opened for reading, + 3 failed to get file status information, + 4 the template file is not a regular file, + 5 an error is encountered while reading the template file, + 6 memory allication failed (not enough memory available), + 7 there is no line in the template that matches the input, + 8 invalid input specification Example: February 31 or a time is + specified that can not be represented in a time_t (representing + the time in seconds since 00:00:00 UTC, January 1, 1970) */ +extern int getdate_err; + +/* Parse the given string as a date specification and return a value + representing the value. The templates from the file identified by + the environment variable DATEMSK are used. In case of an error + `getdate_err' is set. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern struct tm *getdate (__const char *__string); +# endif + +# ifdef __USE_GNU +/* Since `getdate' is not reentrant because of the use of `getdate_err' + and the static buffer to return the result in, we provide a thread-safe + variant. The functionality is the same. The result is returned in + the buffer pointed to by RESBUFP and in case of an error the return + value is != 0 with the same values as given above for `getdate_err'. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getdate_r (__const char *__restrict __string, + struct tm *__restrict __resbufp); +# endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +__END_DECLS + + +#ifdef UCLIBC_INTERNAL +/* Experiment. Grep for 'libc_hidden_proto(time)' if need to revert */ +libc_hidden_proto(time) +#endif + + +#endif /* included. */ + +#endif /* not already included. */ diff --git a/include/ttyent.h b/include/ttyent.h new file mode 100644 index 0000000..0b221bc --- /dev/null +++ b/include/ttyent.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttyent.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _TTYENT_H +#define _TTYENT_H 1 + +#include + +#define _PATH_TTYS "/etc/ttys" + +#define _TTYS_OFF "off" +#define _TTYS_ON "on" +#define _TTYS_SECURE "secure" +#define _TTYS_WINDOW "window" + +struct ttyent { + char *ty_name; /* terminal device name */ + char *ty_getty; /* command to execute, usually getty */ + char *ty_type; /* terminal type for termcap */ +#define TTY_ON 0x01 /* enable logins (start ty_getty program) */ +#define TTY_SECURE 0x02 /* allow uid of 0 to login */ + int ty_status; /* status flags */ + char *ty_window; /* command to start up window manager */ + char *ty_comment; /* comment field */ +}; + + +__BEGIN_DECLS + +extern struct ttyent *getttyent (void) __THROW; +extern struct ttyent *getttynam (__const char *__tty) __THROW; +extern int setttyent (void) __THROW; +extern int endttyent (void) __THROW; + +__END_DECLS + +#endif /* ttyent.h */ diff --git a/include/ucontext.h b/include/ucontext.h new file mode 100644 index 0000000..5bd4645 --- /dev/null +++ b/include/ucontext.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UCONTEXT_H +#define _UCONTEXT_H 1 + +#include + +/* Get machine dependent definition of data structures. */ +#include + +/* The System V ABI user-level context switching support functions + * are marked obsolescent by SuSv3, and are not implemented by + * uClibc. This header is therefore empty. */ + + +#endif /* ucontext.h */ diff --git a/include/ulimit.h b/include/ulimit.h new file mode 100644 index 0000000..93b5f37 --- /dev/null +++ b/include/ulimit.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ULIMIT_H +#define _ULIMIT_H 1 + +#include + +/* Constants used as the first parameter for `ulimit'. They denote limits + which can be set or retrieved using this function. */ +enum +{ + UL_GETFSIZE = 1, /* Return limit on the size of a file, + in units of 512 bytes. */ +#define UL_GETFSIZE UL_GETFSIZE + UL_SETFSIZE, /* Set limit on the size of a file to + second argument. */ +#define UL_SETFSIZE UL_SETFSIZE + __UL_GETMAXBRK, /* Return the maximum possible address + of the data segment. */ + __UL_GETOPENMAX /* Return the maximum number of files + that the calling process can open.*/ +}; + + +__BEGIN_DECLS + +/* Control process limits according to CMD. */ +extern long int ulimit (int __cmd, ...) __THROW; + +__END_DECLS + +#endif /* ulimit.h */ diff --git a/include/unistd.h b/include/unistd.h new file mode 100644 index 0000000..164f289 --- /dev/null +++ b/include/unistd.h @@ -0,0 +1,1125 @@ +/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.10 Symbolic Constants + */ + +#ifndef _UNISTD_H +#define _UNISTD_H 1 + +#include + +__BEGIN_DECLS + +/* These may be used to determine what facilities are present at compile time. + Their values can be obtained at run time from `sysconf'. */ + +/* POSIX Standard approved as ISO/IEC 9945-1 as of December 2001. */ +#define _POSIX_VERSION 200112L + +/* These are not #ifdef __USE_POSIX2 because they are + in the theoretically application-owned namespace. */ + +/* The utilities on GNU systems also correspond to this version. */ +#define _POSIX2_VERSION 200112L + +/* If defined, the implementation supports the + C Language Bindings Option. */ +#define _POSIX2_C_BIND 200112L + +/* If defined, the implementation supports the + C Language Development Utilities Option. */ +#define _POSIX2_C_DEV 200112L + +/* If defined, the implementation supports the + Software Development Utilities Option. */ +#define _POSIX2_SW_DEV 200112L + +/* If defined, the implementation supports the + creation of locales with the localedef utility. */ +#define _POSIX2_LOCALEDEF 200112L + +/* X/Open version number to which the library conforms. It is selectable. */ +#ifdef __USE_UNIX98 +# define _XOPEN_VERSION 500 +#else +# define _XOPEN_VERSION 4 +#endif + +/* Commands and utilities from XPG4 are available. */ +#define _XOPEN_XCU_VERSION 4 + +/* We are compatible with the old published standards as well. */ +#define _XOPEN_XPG2 1 +#define _XOPEN_XPG3 1 +#define _XOPEN_XPG4 1 + +/* The X/Open Unix extensions are available. */ +#define _XOPEN_UNIX 1 + +/* Encryption is present. */ +#define _XOPEN_CRYPT 1 + +/* The enhanced internationalization capabilities according to XPG4.2 + are present. */ +#define _XOPEN_ENH_I18N 1 + +/* The legacy interfaces are also available. */ +#define _XOPEN_LEGACY 1 + + +/* Get values of POSIX options: + + If these symbols are defined, the corresponding features are + always available. If not, they may be available sometimes. + The current values can be obtained with `sysconf'. + + _POSIX_JOB_CONTROL Job control is supported. + _POSIX_SAVED_IDS Processes have a saved set-user-ID + and a saved set-group-ID. + _POSIX_REALTIME_SIGNALS Real-time, queued signals are supported. + _POSIX_PRIORITY_SCHEDULING Priority scheduling is supported. + _POSIX_TIMERS POSIX.4 clocks and timers are supported. + _POSIX_ASYNCHRONOUS_IO Asynchronous I/O is supported. + _POSIX_PRIORITIZED_IO Prioritized asynchronous I/O is supported. + _POSIX_SYNCHRONIZED_IO Synchronizing file data is supported. + _POSIX_FSYNC The fsync function is present. + _POSIX_MAPPED_FILES Mapping of files to memory is supported. + _POSIX_MEMLOCK Locking of all memory is supported. + _POSIX_MEMLOCK_RANGE Locking of ranges of memory is supported. + _POSIX_MEMORY_PROTECTION Setting of memory protections is supported. + _POSIX_MESSAGE_PASSING POSIX.4 message queues are supported. + _POSIX_SEMAPHORES POSIX.4 counting semaphores are supported. + _POSIX_SHARED_MEMORY_OBJECTS POSIX.4 shared memory objects are supported. + _POSIX_THREADS POSIX.1c pthreads are supported. + _POSIX_THREAD_ATTR_STACKADDR Thread stack address attribute option supported. + _POSIX_THREAD_ATTR_STACKSIZE Thread stack size attribute option supported. + _POSIX_THREAD_SAFE_FUNCTIONS Thread-safe functions are supported. + _POSIX_THREAD_PRIORITY_SCHEDULING + POSIX.1c thread execution scheduling supported. + _POSIX_THREAD_PRIO_INHERIT Thread priority inheritance option supported. + _POSIX_THREAD_PRIO_PROTECT Thread priority protection option supported. + _POSIX_THREAD_PROCESS_SHARED Process-shared synchronization supported. + _POSIX_PII Protocol-independent interfaces are supported. + _POSIX_PII_XTI XTI protocol-indep. interfaces are supported. + _POSIX_PII_SOCKET Socket protocol-indep. interfaces are supported. + _POSIX_PII_INTERNET Internet family of protocols supported. + _POSIX_PII_INTERNET_STREAM Connection-mode Internet protocol supported. + _POSIX_PII_INTERNET_DGRAM Connectionless Internet protocol supported. + _POSIX_PII_OSI ISO/OSI family of protocols supported. + _POSIX_PII_OSI_COTS Connection-mode ISO/OSI service supported. + _POSIX_PII_OSI_CLTS Connectionless ISO/OSI service supported. + _POSIX_POLL Implementation supports `poll' function. + _POSIX_SELECT Implementation supports `select' and `pselect'. + + _XOPEN_REALTIME X/Open realtime support is available. + _XOPEN_REALTIME_THREADS X/Open realtime thread support is available. + _XOPEN_SHM Shared memory interface according to XPG4.2. + + _XBS5_ILP32_OFF32 Implementation provides environment with 32-bit + int, long, pointer, and off_t types. + _XBS5_ILP32_OFFBIG Implementation provides environment with 32-bit + int, long, and pointer and off_t with at least + 64 bits. + _XBS5_LP64_OFF64 Implementation provides environment with 32-bit + int, and 64-bit long, pointer, and off_t types. + _XBS5_LPBIG_OFFBIG Implementation provides environment with at + least 32 bits int and long, pointer, and off_t + with at least 64 bits. + + If any of these symbols is defined as -1, the corresponding option is not + true for any file. If any is defined as other than -1, the corresponding + option is true for all files. If a symbol is not defined at all, the value + for a specific file can be obtained from `pathconf' and `fpathconf'. + + _POSIX_CHOWN_RESTRICTED Only the super user can use `chown' to change + the owner of a file. `chown' can only be used + to change the group ID of a file to a group of + which the calling process is a member. + _POSIX_NO_TRUNC Pathname components longer than + NAME_MAX generate an error. + _POSIX_VDISABLE If defined, if the value of an element of the + `c_cc' member of `struct termios' is + _POSIX_VDISABLE, no character will have the + effect associated with that element. + _POSIX_SYNC_IO Synchronous I/O may be performed. + _POSIX_ASYNC_IO Asynchronous I/O may be performed. + _POSIX_PRIO_IO Prioritized Asynchronous I/O may be performed. + + Support for the Large File Support interface is not generally available. + If it is available the following constants are defined to one. + _LFS64_LARGEFILE Low-level I/O supports large files. + _LFS64_STDIO Standard I/O supports large files. + */ + +#include + +/* Get the environment definitions from Unix98. */ +#ifdef __USE_UNIX98 +# include +#endif + +/* Standard file descriptors. */ +#define STDIN_FILENO 0 /* Standard input. */ +#define STDOUT_FILENO 1 /* Standard output. */ +#define STDERR_FILENO 2 /* Standard error output. */ + + +/* All functions that are not declared anywhere else. */ + +#include + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +#define __need_size_t +#define __need_NULL +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif + +# ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +# endif +# if defined __USE_LARGEFILE64 && !defined __off64_t_defined +typedef __off64_t off64_t; +# define __off64_t_defined +# endif + +# ifndef __useconds_t_defined +typedef __useconds_t useconds_t; +# define __useconds_t_defined +# endif + +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif /* X/Open */ + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +# ifndef __intptr_t_defined +typedef __intptr_t intptr_t; +# define __intptr_t_defined +# endif +#endif + +#if defined __USE_BSD || defined __USE_XOPEN +# ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +# endif +#endif + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define X_OK 1 /* Test for execute permission. */ +#define F_OK 0 /* Test for existence. */ + +/* Test for access to NAME using the real UID and real GID. */ +extern int access (__const char *__name, int __type) __THROW __nonnull ((1)); + +#if 0 /*def __USE_GNU*/ +/* Test for access to NAME using the effective UID and GID + (as normal file operations use). */ +extern int euidaccess (__const char *__name, int __type) + __THROW __nonnull ((1)); + +/* An alias for `euidaccess', used by some other systems. */ +extern int eaccess (__const char *__name, int __type) + __THROW __nonnull ((1)); +#endif + +#ifdef __USE_ATFILE +/* Test for access to FILE relative to the directory FD is open on. + If AT_EACCESS is set in FLAG, then use effective IDs like `eaccess', + otherwise use real IDs like `access'. */ +extern int faccessat (int __fd, __const char *__file, int __type, int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use GNU. */ + + +/* Values for the WHENCE argument to lseek. */ +#ifndef _STDIO_H /* has the same definitions. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Seek from end of file. */ +#endif + +#if defined __USE_BSD && !defined L_SET +/* Old BSD names for the same constants; just for compatibility. */ +# define L_SET SEEK_SET +# define L_INCR SEEK_CUR +# define L_XTND SEEK_END +#endif + + +/* Move FD's file position to OFFSET bytes from the + beginning of the file (if WHENCE is SEEK_SET), + the current position (if WHENCE is SEEK_CUR), + or the end of the file (if WHENCE is SEEK_END). + Return the new file position. */ +#ifndef __USE_FILE_OFFSET64 +extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW; +#else +# ifdef __REDIRECT_NTH +extern __off64_t __REDIRECT_NTH (lseek, + (int __fd, __off64_t __offset, int __whence), + lseek64); +# else +# define lseek lseek64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern __off64_t lseek64 (int __fd, __off64_t __offset, int __whence) + __THROW; +#endif + +/* Close the file descriptor FD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int close (int __fd); + +/* Read NBYTES into BUF from FD. Return the + number read, -1 for errors or 0 for EOF. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur; + +/* Write N bytes of BUF to FD. Return the number written, or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t write (int __fd, __const void *__buf, size_t __n) __wur; + +#ifdef __USE_UNIX98 +# ifndef __USE_FILE_OFFSET64 +/* Read NBYTES into BUF from FD at the given position OFFSET without + changing the file pointer. Return the number read, -1 for errors + or 0 for EOF. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, + __off_t __offset) __wur; + +/* Write N bytes of BUF to FD at the given position OFFSET without + changing the file pointer. Return the number written, or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t pwrite (int __fd, __const void *__buf, size_t __n, + __off_t __offset) __wur; +# else +# ifdef __REDIRECT +extern ssize_t __REDIRECT (pread, (int __fd, void *__buf, size_t __nbytes, + __off64_t __offset), + pread64) __wur; +extern ssize_t __REDIRECT (pwrite, (int __fd, __const void *__buf, + size_t __nbytes, __off64_t __offset), + pwrite64) __wur; +# else +# define pread pread64 +# define pwrite pwrite64 +# endif +# endif + +# ifdef __USE_LARGEFILE64 +/* Read NBYTES into BUF from FD at the given position OFFSET without + changing the file pointer. Return the number read, -1 for errors + or 0 for EOF. */ +extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, + __off64_t __offset) __wur; +/* Write N bytes of BUF to FD at the given position OFFSET without + changing the file pointer. Return the number written, or -1. */ +extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n, + __off64_t __offset) __wur; +# endif +#endif + +/* Create a one-way communication channel (pipe). + If successful, two file descriptors are stored in PIPEDES; + bytes written on PIPEDES[1] can be read from PIPEDES[0]. + Returns 0 if successful, -1 if not. */ +extern int pipe (int __pipedes[2]) __THROW __wur; + +/* Schedule an alarm. In SECONDS seconds, the process will get a SIGALRM. + If SECONDS is zero, any currently scheduled alarm will be cancelled. + The function returns the number of seconds remaining until the last + alarm scheduled would have signaled, or zero if there wasn't one. + There is no return value to indicate an error, but you can set `errno' + to 0 and check its value after calling `alarm', and this might tell you. + The signal may come late due to processor scheduling. */ +extern unsigned int alarm (unsigned int __seconds) __THROW; + +/* Make the process sleep for SECONDS seconds, or until a signal arrives + and is not ignored. The function returns the number of seconds less + than SECONDS which it actually slept (thus zero if it slept the full time). + If a signal handler does a `longjmp' or modifies the handling of the + SIGALRM signal while inside `sleep' call, the handling of the SIGALRM + signal afterwards is undefined. There is no return value to indicate + error, but if `sleep' returns SECONDS, it probably didn't work. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern unsigned int sleep (unsigned int __seconds); + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Set an alarm to go off (generating a SIGALRM signal) in VALUE + microseconds. If INTERVAL is nonzero, when the alarm goes off, the + timer is reset to go off every INTERVAL microseconds thereafter. + Returns the number of microseconds remaining before the alarm. */ +extern __useconds_t ualarm (__useconds_t __value, __useconds_t __interval) + __THROW; + +/* Sleep USECONDS microseconds, or until a signal arrives that is not blocked + or ignored. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int usleep (__useconds_t __useconds); +#endif + + +/* Suspend the process until a signal arrives. + This always returns -1 and sets `errno' to EINTR. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pause (void); + + +/* Change the owner and group of FILE. */ +extern int chown (__const char *__file, __uid_t __owner, __gid_t __group) + __THROW __nonnull ((1)) __wur; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Change the owner and group of the file that FD is open on. */ +extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __THROW __wur; + + +/* Change owner and group of FILE, if it is a symbolic + link the ownership of the symbolic link is changed. */ +extern int lchown (__const char *__file, __uid_t __owner, __gid_t __group) + __THROW __nonnull ((1)) __wur; + +#endif /* Use BSD || X/Open Unix. */ + +#ifdef __USE_ATFILE +/* Change the owner and group of FILE relative to the directory FD is open + on. */ +extern int fchownat (int __fd, __const char *__file, __uid_t __owner, + __gid_t __group, int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use GNU. */ + +/* Change the process's working directory to PATH. */ +extern int chdir (__const char *__path) __THROW __nonnull ((1)) __wur; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Change the process's working directory to the one FD is open on. */ +extern int fchdir (int __fd) __THROW __wur; +#endif + +/* Get the pathname of the current working directory, + and put it in SIZE bytes of BUF. Returns NULL if the + directory couldn't be determined or SIZE was too small. + If successful, returns BUF. In GNU, if BUF is NULL, + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE == 0, in which case it is as + big as necessary. */ +extern char *getcwd (char *__buf, size_t __size) __THROW __wur; + +#ifdef __USE_GNU +/* Return a malloc'd string containing the current directory name. + If the environment variable `PWD' is set, and its value is correct, + that value is used. */ +extern char *get_current_dir_name (void) __THROW; +#endif + +#if 0 /*defined __USE_BSD || defined __USE_XOPEN_EXTENDED*/ +/* Put the absolute pathname of the current working directory in BUF. + If successful, return BUF. If not, put an error message in + BUF and return NULL. BUF should be at least PATH_MAX bytes long. */ +extern char *getwd (char *__buf) + __THROW __nonnull ((1)) __attribute_deprecated__ __wur; +#endif + + +/* Duplicate FD, returning a new file descriptor on the same file. */ +extern int dup (int __fd) __THROW __wur; + +/* Duplicate FD to FD2, closing FD2 and making it open on the same file. */ +extern int dup2 (int __fd, int __fd2) __THROW; + +/* NULL-terminated array of "NAME=VALUE" environment variables. */ +extern char **__environ; +#ifdef __USE_GNU +extern char **environ; +#endif + + +/* Replace the current process, executing PATH with arguments ARGV and + environment ENVP. ARGV and ENVP are terminated by NULL pointers. */ +extern int execve (__const char *__path, char *__const __argv[], + char *__const __envp[]) __THROW __nonnull ((1)); + +#if 0 /*def __USE_GNU*/ +/* Execute the file FD refers to, overlaying the running program image. + ARGV and ENVP are passed to the new program, as for `execve'. */ +extern int fexecve (int __fd, char *__const __argv[], char *__const __envp[]) + __THROW; +#endif + + +/* Execute PATH with arguments ARGV and environment from `environ'. */ +extern int execv (__const char *__path, char *__const __argv[]) + __THROW __nonnull ((1)); + +/* Execute PATH with all arguments after PATH until a NULL pointer, + and the argument after that for environment. */ +extern int execle (__const char *__path, __const char *__arg, ...) + __THROW __nonnull ((1)); + +/* Execute PATH with all arguments after PATH until + a NULL pointer and environment from `environ'. */ +extern int execl (__const char *__path, __const char *__arg, ...) + __THROW __nonnull ((1)); + +/* Execute FILE, searching in the `PATH' environment variable if it contains + no slashes, with arguments ARGV and environment from `environ'. */ +extern int execvp (__const char *__file, char *__const __argv[]) + __THROW __nonnull ((1)); + +/* Execute FILE, searching in the `PATH' environment variable if + it contains no slashes, with all arguments after FILE until a + NULL pointer and environment from `environ'. */ +extern int execlp (__const char *__file, __const char *__arg, ...) + __THROW __nonnull ((1)); + + +#if defined __USE_MISC || defined __USE_XOPEN +/* Add INC to priority of the current process. */ +extern int nice (int __inc) __THROW __wur; +#endif + + +/* Terminate program execution with the low-order 8 bits of STATUS. */ +extern void _exit (int __status) __attribute__ ((__noreturn__)); + + +/* Get the `_PC_*' symbols for the NAME argument to `pathconf' and `fpathconf'; + the `_SC_*' symbols for the NAME argument to `sysconf'; + and the `_CS_*' symbols for the NAME argument to `confstr'. */ +#include + +/* Get file-specific configuration information about PATH. */ +extern long int pathconf (__const char *__path, int __name) + __THROW __nonnull ((1)); + +/* Get file-specific configuration about descriptor FD. */ +extern long int fpathconf (int __fd, int __name) __THROW; + +/* Get the value of the system variable NAME. */ +extern long int sysconf (int __name) __THROW; + +#ifdef __USE_POSIX2 +/* Get the value of the string-valued system variable NAME. */ +extern size_t confstr (int __name, char *__buf, size_t __len) __THROW; +#endif + + +/* Get the process ID of the calling process. */ +extern __pid_t getpid (void) __THROW; + +/* Get the process ID of the calling process's parent. */ +extern __pid_t getppid (void) __THROW; + +/* Get the process group ID of the calling process. + This function is different on old BSD. */ +#ifndef __FAVOR_BSD +extern __pid_t getpgrp (void) __THROW; +#else +# ifdef __REDIRECT_NTH +extern __pid_t __REDIRECT_NTH (getpgrp, (__pid_t __pid), __getpgid); +# else +# define getpgrp __getpgid +# endif +#endif + +/* Get the process group ID of process PID. */ +extern __pid_t __getpgid (__pid_t __pid) __THROW; +#ifdef __USE_XOPEN_EXTENDED +extern __pid_t getpgid (__pid_t __pid) __THROW; +#endif + + +/* Set the process group ID of the process matching PID to PGID. + If PID is zero, the current process's process group ID is set. + If PGID is zero, the process ID of the process is used. */ +extern int setpgid (__pid_t __pid, __pid_t __pgid) __THROW; + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Both System V and BSD have `setpgrp' functions, but with different + calling conventions. The BSD function is the same as POSIX.1 `setpgid' + (above). The System V function takes no arguments and puts the calling + process in its on group like `setpgid (0, 0)'. + + New programs should always use `setpgid' instead. + + The default in GNU is to provide the System V function. The BSD + function is available under -D_BSD_SOURCE. */ + +# ifndef __FAVOR_BSD + +/* Set the process group ID of the calling process to its own PID. + This is exactly the same as `setpgid (0, 0)'. */ +extern int setpgrp (void) __THROW; + +# else + +/* Another name for `setpgid' (above). */ +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (setpgrp, (__pid_t __pid, __pid_t __pgrp), setpgid); +# else +# define setpgrp setpgid +# endif + +# endif /* Favor BSD. */ +#endif /* Use SVID or BSD. */ + +/* Create a new session with the calling process as its leader. + The process group IDs of the session and the calling process + are set to the process ID of the calling process, which is returned. */ +extern __pid_t setsid (void) __THROW; + +#ifdef __USE_XOPEN_EXTENDED +/* Return the session ID of the given process. */ +extern __pid_t getsid (__pid_t __pid) __THROW; +#endif + +/* Get the real user ID of the calling process. */ +extern __uid_t getuid (void) __THROW; + +/* Get the effective user ID of the calling process. */ +extern __uid_t geteuid (void) __THROW; + +/* Get the real group ID of the calling process. */ +extern __gid_t getgid (void) __THROW; + +/* Get the effective group ID of the calling process. */ +extern __gid_t getegid (void) __THROW; + +/* If SIZE is zero, return the number of supplementary groups + the calling process is in. Otherwise, fill in the group IDs + of its supplementary groups in LIST and return the number written. */ +extern int getgroups (int __size, __gid_t __list[]) __THROW __wur; + +#if 0 /*def __USE_GNU*/ +/* Return nonzero iff the calling process is in group GID. */ +extern int group_member (__gid_t __gid) __THROW; +#endif + +/* Set the user ID of the calling process to UID. + If the calling process is the super-user, set the real + and effective user IDs, and the saved set-user-ID to UID; + if not, the effective user ID is set to UID. */ +extern int setuid (__uid_t __uid) __THROW; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Set the real user ID of the calling process to RUID, + and the effective user ID of the calling process to EUID. */ +extern int setreuid (__uid_t __ruid, __uid_t __euid) __THROW; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set the effective user ID of the calling process to UID. */ +extern int seteuid (__uid_t __uid) __THROW; +#endif /* Use BSD. */ + +/* Set the group ID of the calling process to GID. + If the calling process is the super-user, set the real + and effective group IDs, and the saved set-group-ID to GID; + if not, the effective group ID is set to GID. */ +extern int setgid (__gid_t __gid) __THROW; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Set the real group ID of the calling process to RGID, + and the effective group ID of the calling process to EGID. */ +extern int setregid (__gid_t __rgid, __gid_t __egid) __THROW; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set the effective group ID of the calling process to GID. */ +extern int setegid (__gid_t __gid) __THROW; +#endif /* Use BSD. */ + +#ifdef __USE_GNU +/* Fetch the real user ID, effective user ID, and saved-set user ID, + of the calling process. */ +extern int getresuid (__uid_t *__ruid, __uid_t *__euid, __uid_t *__suid) + __THROW; + +/* Fetch the real group ID, effective group ID, and saved-set group ID, + of the calling process. */ +extern int getresgid (__gid_t *__rgid, __gid_t *__egid, __gid_t *__sgid) + __THROW; + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* Set the real user ID, effective user ID, and saved-set user ID, + of the calling process to RUID, EUID, and SUID, respectively. */ +extern int setresuid (__uid_t __ruid, __uid_t __euid, __uid_t __suid) + __THROW; +#endif + +/* Set the real group ID, effective group ID, and saved-set group ID, + of the calling process to RGID, EGID, and SGID, respectively. */ +extern int setresgid (__gid_t __rgid, __gid_t __egid, __gid_t __sgid) + __THROW; +#endif + + +#if defined __UCLIBC_HAS_STUBS__ || defined __ARCH_USE_MMU__ +/* Clone the calling process, creating an exact copy. + Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ +extern __pid_t fork (void) __THROW; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ +extern __pid_t vfork (void) __THROW; +#endif /* Use BSD. */ + + +/* Return the pathname of the terminal FD is open on, or NULL on errors. + The returned storage is good only until the next call to this function. */ +extern char *ttyname (int __fd) __THROW; + +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +extern int ttyname_r (int __fd, char *__buf, size_t __buflen) + __THROW __nonnull ((2)) __wur; + +/* Return 1 if FD is a valid descriptor associated + with a terminal, zero if not. */ +extern int isatty (int __fd) __THROW; + +#if 0 /*defined __USE_BSD \ + || (defined __USE_XOPEN_EXTENDED && !defined __USE_UNIX98)*/ +/* Return the index into the active-logins file (utmp) for + the controlling terminal. */ +extern int ttyslot (void) __THROW; +#endif + + +/* Make a link to FROM named TO. */ +extern int link (__const char *__from, __const char *__to) + __THROW __nonnull ((1, 2)) __wur; + +#ifdef __USE_ATFILE +/* Like link but relative paths in TO and FROM are interpreted relative + to FROMFD and TOFD respectively. */ +extern int linkat (int __fromfd, __const char *__from, int __tofd, + __const char *__to, int __flags) + __THROW __nonnull ((2, 4)) __wur; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K +/* Make a symbolic link to FROM named TO. */ +extern int symlink (__const char *__from, __const char *__to) + __THROW __nonnull ((1, 2)) __wur; + +/* Read the contents of the symbolic link PATH into no more than + LEN bytes of BUF. The contents are not null-terminated. + Returns the number of characters read, or -1 for errors. */ +extern ssize_t readlink (__const char *__restrict __path, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((1, 2)) __wur; +#endif /* Use BSD. */ + +#ifdef __USE_ATFILE +/* Like symlink but a relative path in TO is interpreted relative to TOFD. */ +extern int symlinkat (__const char *__from, int __tofd, + __const char *__to) __THROW __nonnull ((1, 3)) __wur; + +/* Like readlink but a relative PATH is interpreted relative to FD. */ +extern ssize_t readlinkat (int __fd, __const char *__restrict __path, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((2, 3)) __wur; +#endif + +/* Remove the link NAME. */ +extern int unlink (__const char *__name) __THROW __nonnull ((1)); + +#ifdef __USE_ATFILE +/* Remove the link NAME relative to FD. */ +extern int unlinkat (int __fd, __const char *__name, int __flag) + __THROW __nonnull ((2)); +#endif + +/* Remove the directory PATH. */ +extern int rmdir (__const char *__path) __THROW __nonnull ((1)); + + +/* Return the foreground process group ID of FD. */ +extern __pid_t tcgetpgrp (int __fd) __THROW; + +/* Set the foreground process group ID of FD set PGRP_ID. */ +extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW; + + +/* Return the login name of the user. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern char *getlogin (void); +#if defined __USE_REENTRANT || defined __USE_POSIX199506 +/* Return at most NAME_LEN characters of the login name of the user in NAME. + If it cannot be determined or some other error occurred, return the error + code. Otherwise return 0. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)); +#endif + +#if 0 /*def __USE_BSD*/ +/* Set the login name returned by `getlogin'. */ +extern int setlogin (__const char *__name) __THROW __nonnull ((1)); +#endif + + +#ifdef __USE_POSIX2 +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. */ +# define __need_getopt +/* keep this for uClibc in bits/, we need it when GNU_GETOPT is disabled */ +# include +#endif + + +#if defined __USE_BSD || defined __USE_UNIX98 +/* Put the name of the current host in no more than LEN bytes of NAME. + The result is null-terminated if LEN is large enough for the full + name and the terminator. */ +extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)); +#endif + + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +/* Set the name of the current host to NAME, which is LEN bytes long. + This call is restricted to the super-user. */ +extern int sethostname (__const char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; + +/* Set the current machine's Internet number to ID. + This call is restricted to the super-user. */ +extern int sethostid (long int __id) __THROW __wur; + +#if defined __UCLIBC_BSD_SPECIFIC__ +/* Get and set the NIS (aka YP) domain name, if any. + Called just like `gethostname' and `sethostname'. + The NIS domain name is usually the empty string when not using NIS. */ +extern int getdomainname (char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; +extern int setdomainname (__const char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; +#endif + +/* Revoke access permissions to all processes currently communicating + with the control terminal, and then send a SIGHUP signal to the process + group of the control terminal. */ +extern int vhangup (void) __THROW; + +#if 0 +/* Revoke the access of all descriptors currently open on FILE. */ +extern int revoke (__const char *__file) __THROW __nonnull ((1)) __wur; + + +/* Enable statistical profiling, writing samples of the PC into at most + SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling + is enabled, the system examines the user PC and increments + SAMPLE_BUFFER[((PC - OFFSET) / 2) * SCALE / 65536]. If SCALE is zero, + disable profiling. Returns zero on success, -1 on error. */ +extern int profil (unsigned short int *__sample_buffer, size_t __size, + size_t __offset, unsigned int __scale) + __THROW __nonnull ((1)); +#endif + + +/* Turn accounting on if NAME is an existing file. The system will then write + a record for each process as it terminates, to this file. If NAME is NULL, + turn accounting off. This call is restricted to the super-user. */ +extern int acct (__const char *__name) __THROW; + + +/* Successive calls return the shells listed in `/etc/shells'. */ +extern char *getusershell (void) __THROW; +extern void endusershell (void) __THROW; /* Discard cached info. */ +extern void setusershell (void) __THROW; /* Rewind and re-read the file. */ + + +#ifdef __ARCH_USE_MMU__ +/* Put the program in the background, and dissociate from the controlling + terminal. If NOCHDIR is zero, do `chdir ("/")'. If NOCLOSE is zero, + redirects stdin, stdout, and stderr to /dev/null. */ +extern int daemon (int __nochdir, int __noclose) __THROW __wur; +#endif +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +/* Make PATH be the root directory (the starting point for absolute paths). + This call is restricted to the super-user. */ +extern int chroot (__const char *__path) __THROW __nonnull ((1)) __wur; + +/* Prompt with PROMPT and read a string from the terminal without echoing. + Uses /dev/tty if possible; otherwise stderr and stdin. */ +extern char *getpass (__const char *__prompt) __nonnull ((1)); +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || defined __USE_XOPEN +/* Make all changes done to FD actually appear on disk. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int fsync (int __fd); +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + +/* Return identifier for the current host. */ +extern long int gethostid (void); + +/* Make all changes done to all files actually appear on disk. */ +extern void sync (void) __THROW; + + +/* Return the number of bytes in a page. This is the system's page size, + which is not necessarily the same as the hardware page size. */ +extern int getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Return the maximum number of file descriptors + the current process could possibly have. */ +extern int getdtablesize (void) __THROW; + + +/* Truncate FILE to LENGTH bytes. */ +# ifndef __USE_FILE_OFFSET64 +extern int truncate (__const char *__file, __off_t __length) + __THROW __nonnull ((1)) __wur; +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (truncate, + (__const char *__file, __off64_t __length), + truncate64) __nonnull ((1)) __wur; +# else +# define truncate truncate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int truncate64 (__const char *__file, __off64_t __length) + __THROW __nonnull ((1)) __wur; +# endif + +#endif /* Use BSD || X/Open Unix. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K + +/* Truncate the file FD is open on to LENGTH bytes. */ +# ifndef __USE_FILE_OFFSET64 +extern int ftruncate (int __fd, __off_t __length) __THROW __wur; +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (ftruncate, (int __fd, __off64_t __length), + ftruncate64) __wur; +# else +# define ftruncate ftruncate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int ftruncate64 (int __fd, __off64_t __length) __THROW __wur; +# endif + +#endif /* Use BSD || X/Open Unix || POSIX 2003. */ + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED + +/* Set the end of accessible data space (aka "the break") to ADDR. + Returns zero on success and -1 for errors (with errno set). */ +extern int brk (void *__addr) __THROW __wur; + +/* Increase or decrease the end of accessible data space by DELTA bytes. + If successful, returns the address the previous end of data space + (i.e. the beginning of the new space, if DELTA > 0); + returns (void *) -1 for errors (with errno set). */ +extern void *sbrk (intptr_t __delta) __THROW; +#endif + + +#ifdef __USE_MISC +/* Invoke `system call' number SYSNO, passing it the remaining arguments. + This is completely system-dependent, and not often useful. + + In Unix, `syscall' sets `errno' for all errors and most calls return -1 + for errors; in many systems you cannot pass arguments or get return + values for all system calls (`pipe', `fork', and `getppid' typically + among them). + + In Mach, all system calls take normal arguments and always return an + error code (zero for success). */ +extern long int syscall (long int __sysno, ...) __THROW; + +#endif /* Use misc. */ + + +#if (defined __USE_MISC || defined __USE_XOPEN_EXTENDED) && !defined F_LOCK +/* NOTE: These declarations also appear in ; be sure to keep both + files consistent. Some systems have them there and some here, and some + software depends on the macros being defined without including both. */ + +/* `lockf' is a simpler interface to the locking facilities of `fcntl'. + LEN is always relative to the current file position. + The CMD argument is one of the following. + + This function is a cancellation point and therefore not marked with + __THROW. */ + +# define F_ULOCK 0 /* Unlock a previously locked region. */ +# define F_LOCK 1 /* Lock a region for exclusive use. */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ +# define F_TEST 3 /* Test a region for other processes locks. */ + +# ifndef __USE_FILE_OFFSET64 +extern int lockf (int __fd, int __cmd, __off_t __len) __wur; +# else +# ifdef __REDIRECT +extern int __REDIRECT (lockf, (int __fd, int __cmd, __off64_t __len), + lockf64) __wur; +# else +# define lockf lockf64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lockf64 (int __fd, int __cmd, __off64_t __len) __wur; +# endif +#endif /* Use misc and F_LOCK not already defined. */ + + +#ifdef __USE_GNU + +/* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno' + set to EINTR. */ + +# define TEMP_FAILURE_RETRY(expression) \ + (__extension__ \ + ({ long int __result; \ + do __result = (long int) (expression); \ + while (__result == -1L && errno == EINTR); \ + __result; })) +#endif + +#if (defined __USE_POSIX199309 || defined __USE_UNIX98) \ + && defined __UCLIBC_HAS_REALTIME__ +/* Synchronize at least the data part of a file with the underlying + media. */ +extern int fdatasync (int __fildes) __THROW; +#endif /* Use POSIX199309 */ + + +/* XPG4.2 specifies that prototypes for the encryption functions must + be defined here. */ +#ifdef __USE_XOPEN +# if defined __UCLIBC_HAS_CRYPT__ +/* Encrypt at most 8 characters from KEY using salt to perturb DES. */ +extern char *crypt (__const char *__key, __const char *__salt) + __THROW __nonnull ((1, 2)); + +/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt + block in place. */ +extern void encrypt (char *__block, int __edflag) __THROW __nonnull ((1)); +# endif /* __UCLIBC_HAS_CRYPT__ */ + + +/* Swab pairs bytes in the first N bytes of the area pointed to by + FROM and copy the result to TO. The value of TO must not be in the + range [FROM - N + 1, FROM - 1]. If N is odd the first byte in FROM + is without partner. */ +extern void swab (__const void *__restrict __from, void *__restrict __to, + ssize_t __n) __THROW __nonnull ((1, 2)); +#endif + + +/* The Single Unix specification demands this prototype to be here. + It is also found in . */ +#ifdef __USE_XOPEN +/* Return the name of the controlling terminal. */ +extern char *ctermid (char *__s) __THROW; +#endif + + +/* Define some macros helping to catch buffer overflows. */ +#if __USE_FORTIFY_LEVEL > 0 && !defined __cplusplus +# include +#endif + +__END_DECLS + + +#ifdef UCLIBC_INTERNAL +#ifndef smallint_type /* if arch didn't override it in bits/wordsize.h */ +#define smallint_type int +#endif +typedef signed smallint_type smallint; +typedef unsigned smallint_type smalluint; +#endif + + +#endif /* unistd.h */ diff --git a/include/ustat.h b/include/ustat.h new file mode 100644 index 0000000..cba150e --- /dev/null +++ b/include/ustat.h @@ -0,0 +1 @@ +#include diff --git a/include/utime.h b/include/utime.h new file mode 100644 index 0000000..dd5d265 --- /dev/null +++ b/include/utime.h @@ -0,0 +1,52 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.6.6 Set File Access and Modification Times + */ + +#ifndef _UTIME_H +#define _UTIME_H 1 + +#include + +__BEGIN_DECLS + +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +# define __need_time_t +# include +#endif + +/* Structure describing file times. */ +struct utimbuf + { + __time_t actime; /* Access time. */ + __time_t modtime; /* Modification time. */ + }; + +/* Set the access and modification times of FILE to those given in + *FILE_TIMES. If FILE_TIMES is NULL, set them to the current time. */ +extern int utime (__const char *__file, + __const struct utimbuf *__file_times) + __THROW __nonnull ((1)); + +__END_DECLS + +#endif /* utime.h */ diff --git a/include/utmp.h b/include/utmp.h new file mode 100644 index 0000000..585aad1 --- /dev/null +++ b/include/utmp.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMP_H +#define _UTMP_H 1 + +#include + +#include + + +__BEGIN_DECLS + +/* Get system dependent values and data structures. */ +#include + +/* Compatibility names for the strings of the canonical file names. */ +#define UTMP_FILE _PATH_UTMP +#define UTMP_FILENAME _PATH_UTMP +#define WTMP_FILE _PATH_WTMP +#define WTMP_FILENAME _PATH_WTMP + + + +/* Make FD be the controlling terminal, stdin, stdout, and stderr; + then close FD. Returns 0 on success, nonzero on error. */ +extern int login_tty (int __fd) __THROW; + + +/* Write the given entry into utmp and wtmp. */ +extern void login (__const struct utmp *__entry) __THROW; + +/* Write the utmp entry to say the user on UT_LINE has logged out. */ +extern int logout (__const char *__ut_line) __THROW; + +/* Append to wtmp an entry for the current time and the given info. */ +extern void logwtmp (__const char *__ut_line, __const char *__ut_name, + __const char *__ut_host) __THROW; + +/* Append entry UTMP to the wtmp-like file WTMP_FILE. */ +extern void updwtmp (__const char *__wtmp_file, __const struct utmp *__utmp) + __THROW; + +/* Change name of the utmp file to be examined. */ +extern int utmpname (__const char *__file) __THROW; + +/* Read next entry from a utmp-like file. */ +extern struct utmp *getutent (void) __THROW; + +/* Reset the input stream to the beginning of the file. */ +extern void setutent (void) __THROW; + +/* Close the current open file. */ +extern void endutent (void) __THROW; + +/* Search forward from the current point in the utmp file until the + next entry with a ut_type matching ID->ut_type. */ +extern struct utmp *getutid (__const struct utmp *__id) __THROW; + +/* Search forward from the current point in the utmp file until the + next entry with a ut_line matching LINE->ut_line. */ +extern struct utmp *getutline (__const struct utmp *__line) __THROW; + +/* Write out entry pointed to by UTMP_PTR into the utmp file. */ +extern struct utmp *pututline (__const struct utmp *__utmp_ptr) __THROW; + + +#if 0 /* def __USE_MISC */ +/* Reentrant versions of the file for handling utmp files. */ +extern int getutent_r (struct utmp *__buffer, struct utmp **__result) __THROW; + +extern int getutid_r (__const struct utmp *__id, struct utmp *__buffer, + struct utmp **__result) __THROW; + +extern int getutline_r (__const struct utmp *__line, + struct utmp *__buffer, struct utmp **__result) __THROW; + +#endif /* Use misc. */ + +__END_DECLS + +#endif /* utmp.h */ diff --git a/include/values.h b/include/values.h new file mode 100644 index 0000000..d8bd8b5 --- /dev/null +++ b/include/values.h @@ -0,0 +1,71 @@ +/* Old compatibility names for and constants. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This interface is obsolete. New programs should use + and/or instead of . */ + +#ifndef _VALUES_H +#define _VALUES_H 1 + +#include + +#include + +#define _TYPEBITS(type) (sizeof (type) * CHAR_BIT) + +#define CHARBITS _TYPEBITS (char) +#define SHORTBITS _TYPEBITS (short int) +#define INTBITS _TYPEBITS (int) +#define LONGBITS _TYPEBITS (long int) +#define PTRBITS _TYPEBITS (char *) +#define DOUBLEBITS _TYPEBITS (double) +#define FLOATBITS _TYPEBITS (float) + +#define MINSHORT SHRT_MIN +#define MININT INT_MIN +#define MINLONG LONG_MIN + +#define MAXSHORT SHRT_MAX +#define MAXINT INT_MAX +#define MAXLONG LONG_MAX + +#define HIBITS MINSHORT +#define HIBITL MINLONG + + +#ifdef __UCLIBC_HAS_FLOATS__ +#include + +#define MAXDOUBLE DBL_MAX +#define MAXFLOAT FLT_MAX +#define MINDOUBLE DBL_MIN +#define MINFLOAT FLT_MIN +#define DMINEXP DBL_MIN_EXP +#define FMINEXP FLT_MIN_EXP +#define DMAXEXP DBL_MAX_EXP +#define FMAXEXP FLT_MAX_EXP +#endif /* __UCLIBC_HAS_FLOATS__ */ + + +#ifdef __USE_MISC +/* Some systems define this name instead of CHAR_BIT or CHARBITS. */ +# define BITSPERBYTE CHAR_BIT +#endif + +#endif /* values.h */ diff --git a/include/wait.h b/include/wait.h new file mode 100644 index 0000000..d01b811 --- /dev/null +++ b/include/wait.h @@ -0,0 +1 @@ +#include diff --git a/include/wchar.h b/include/wchar.h new file mode 100644 index 0000000..e461f71 --- /dev/null +++ b/include/wchar.h @@ -0,0 +1,752 @@ +/* Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.24 + * Extended multibyte and wide character utilities + */ + +#ifndef _WCHAR_H + +#ifndef __need_mbstate_t +# define _WCHAR_H 1 +# include +#endif + +#ifndef __UCLIBC_HAS_WCHAR__ +#error Attempted to include wchar.h when uClibc built without wide char support. +#endif + +#ifdef _WCHAR_H +/* Get FILE definition. */ +# define __need___FILE +# ifdef __USE_UNIX98 +# define __need_FILE +# endif +# include +/* Get va_list definition. */ +# define __need___va_list +# include + +/* Get size_t, wchar_t, wint_t and NULL from . */ +# define __need_size_t +# define __need_wchar_t +# define __need_NULL +#endif +#define __need_wint_t +#include + +#include + +/* We try to get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +#ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +#else +/* Work around problems with the file which doesn't put + wint_t in the std namespace. */ +# if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES \ + && defined __WINT_TYPE__ +__BEGIN_NAMESPACE_STD +typedef __WINT_TYPE__ wint_t; +__END_NAMESPACE_STD +# endif +#endif + + +#ifndef __mbstate_t_defined +# define __mbstate_t_defined 1 +/* Conversion state information. */ +#if 1 +typedef struct +{ + wchar_t __mask; + wchar_t __wc; +} __mbstate_t; +#else +typedef struct +{ + int __count; + union + { + wint_t __wch; + char __wchb[4]; + } __value; /* Value so far. */ +} __mbstate_t; +#endif +#endif +#undef __need_mbstate_t + + +/* The rest of the file is only used if used if __need_mbstate_t is not + defined. */ +#ifdef _WCHAR_H + +__BEGIN_NAMESPACE_C99 +/* Public type. */ +typedef __mbstate_t mbstate_t; +__END_NAMESPACE_C99 +#ifdef __USE_GNU +__USING_NAMESPACE_C99(mbstate_t) +#endif + +#ifndef WCHAR_MIN +/* These constants might also be defined in . */ +# define WCHAR_MIN __WCHAR_MIN +# define WCHAR_MAX __WCHAR_MAX +#endif + +#ifndef WEOF +# define WEOF (0xffffffffu) +#endif + +/* For XPG4 compliance we have to define the stuff from here + as well. */ +#if defined __USE_XOPEN && !defined __USE_UNIX98 +# include +#endif + + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_STD +/* This incomplete type is defined in but needed here because + of `wcsftime'. */ +struct tm; +/* XXX We have to clean this up at some point. Since tm is in the std + namespace but wcsftime is in __c99 the type wouldn't be found + without inserting it in the global namespace. */ +__USING_NAMESPACE_STD(tm) +__END_NAMESPACE_STD + + +__BEGIN_NAMESPACE_C99 +/* Copy SRC to DEST. */ +extern wchar_t *wcscpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +/* Copy no more than N wide-characters of SRC to DEST. */ +extern wchar_t *wcsncpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Append SRC onto DEST. */ +extern wchar_t *wcscat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +/* Append no more than N wide-characters of SRC onto DEST. */ +extern wchar_t *wcsncat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Compare S1 and S2. */ +extern int wcscmp (__const wchar_t *__s1, __const wchar_t *__s2) + __THROW __attribute_pure__; +/* Compare N wide-characters of S1 and S2. */ +extern int wcsncmp (__const wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Compare S1 and S2, ignoring case. */ +extern int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int wcsncasecmp (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n) __THROW; + +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ +# include + +extern int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; + +extern int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; +#endif /* __UCLIBC_HAS_XLOCALE__ */ +#endif + +__BEGIN_NAMESPACE_C99 +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the current locale. */ +extern int wcscoll (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ + +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the given locale. */ +extern int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; + +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Duplicate S, returning an identical malloc'd string. */ +extern wchar_t *wcsdup (__const wchar_t *__s) __THROW __attribute_malloc__; +#endif + +__BEGIN_NAMESPACE_C99 +/* Find the first occurrence of WC in WCS. */ +extern wchar_t *wcschr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +/* Find the last occurrence of WC in WCS. */ +extern wchar_t *wcsrchr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* This function is similar to `wcschr'. But it returns a pointer to + the closing NUL wide character in case C is not found in S. */ +extern wchar_t *wcschrnul (__const wchar_t *__s, wchar_t __wc) + __THROW __attribute_pure__; +#endif + +__BEGIN_NAMESPACE_C99 +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters not in REJECT. */ +extern size_t wcscspn (__const wchar_t *__wcs, __const wchar_t *__reject) + __THROW __attribute_pure__; +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters in ACCEPT. */ +extern size_t wcsspn (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +/* Find the first occurrence in WCS of any character in ACCEPT. */ +extern wchar_t *wcspbrk (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +extern wchar_t *wcsstr (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; + +/* Divide WCS into tokens separated by characters in DELIM. */ +extern wchar_t *wcstok (wchar_t *__restrict __s, + __const wchar_t *__restrict __delim, + wchar_t **__restrict __ptr) __THROW; + +/* Return the number of wide characters in S. */ +extern size_t wcslen (__const wchar_t *__s) __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_XOPEN +/* Another name for `wcsstr' from XPG4. */ +extern wchar_t *wcswcs (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; +#endif + +#ifdef __USE_GNU +/* Return the number of wide characters in S, but at most MAXLEN. */ +extern size_t wcsnlen (__const wchar_t *__s, size_t __maxlen) + __THROW __attribute_pure__; +#endif + + +__BEGIN_NAMESPACE_C99 +/* Search N wide characters of S for C. */ +extern wchar_t *wmemchr (__const wchar_t *__s, wchar_t __c, size_t __n) + __THROW __attribute_pure__; + +/* Compare N wide characters of S1 and S2. */ +extern int wmemcmp (__const wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW __attribute_pure__; + +/* Copy N wide characters of SRC to DEST. */ +extern wchar_t *wmemcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; + +/* Copy N wide characters of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +extern wchar_t *wmemmove (wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW; + +/* Set N wide characters of S to C. */ +extern wchar_t *wmemset (wchar_t *__s, wchar_t __c, size_t __n) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Copy N wide characters of SRC to DEST and return pointer to following + wide character. */ +extern wchar_t *wmempcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW; +#endif + + +__BEGIN_NAMESPACE_C99 +/* Determine whether C constitutes a valid (one-byte) multibyte + character. */ +extern wint_t btowc (int __c) __THROW; + +/* Determine whether C corresponds to a member of the extended + character set whose multibyte representation is a single byte. */ +extern int wctob (wint_t __c) __THROW; + +/* Determine whether PS points to an object representing the initial + state. */ +extern int mbsinit (__const mbstate_t *__ps) __THROW __attribute_pure__; + +/* Write wide character representation of multibyte character pointed + to by S to PWC. */ +extern size_t mbrtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n, + mbstate_t *__p) __THROW; + +/* Write multibyte representation of wide character WC to S. */ +extern size_t wcrtomb (char *__restrict __s, wchar_t __wc, + mbstate_t *__restrict __ps) __THROW; + +/* Return number of bytes in multibyte character pointed to by S. */ +#if 0 /* uClibc: disabled */ +extern size_t __mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; +#endif +extern size_t mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; + +/* Write wide character representation of multibyte character string + SRC to DST. */ +extern size_t mbsrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; + +/* Write multibyte character representation of wide character string + SRC to DST. */ +extern size_t wcsrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* Write wide character representation of at most NMC bytes of the + multibyte character string SRC to DST. */ +extern size_t mbsnrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __nmc, + size_t __len, mbstate_t *__restrict __ps) __THROW; + +/* Write multibyte character representation of at most NWC characters + from the wide character string SRC to DST. */ +extern size_t wcsnrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, + size_t __nwc, size_t __len, + mbstate_t *__restrict __ps) __THROW; +#endif /* use GNU */ + + +/* The following functions are extensions found in X/Open CAE. */ +#ifdef __USE_XOPEN +/* Determine number of column positions required for C. */ +extern int wcwidth (wchar_t __c) __THROW; + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +extern int wcswidth (__const wchar_t *__s, size_t __n) __THROW; +#endif /* Use X/Open. */ + + +__BEGIN_NAMESPACE_C99 +#ifdef __UCLIBC_HAS_FLOATS__ +/* Convert initial portion of the wide string NPTR to `double' + representation. */ +extern double wcstod (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; + +#ifdef __USE_ISOC99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float wcstof (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +extern long double wcstold (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +#endif /* C99 */ +#endif /* __UCLIBC_HAS_FLOATS__ */ + + +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +extern long int wcstol (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long int' + representation. */ +extern unsigned long int wcstoul (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +#if defined __USE_ISOC99 || (defined __GNUC__ && defined __USE_GNU) +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoll (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstoull (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* ISO C99 or GCC and GNU. */ +__END_NAMESPACE_C99 + +#if defined __GNUC__ && defined __USE_GNU +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstouq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* GCC and use GNU. */ + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_XLOCALE__ +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int wcstol_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base, + __locale_t __loc) __THROW; + +extern unsigned long int wcstoul_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern long long int wcstoll_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern unsigned long long int wcstoull_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) + __THROW; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern double wcstod_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern float wcstof_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern long double wcstold_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + __locale_t __loc) __THROW; +#endif /* __UCLIBC_HAS_FLOATS__ */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +#endif /* GNU */ + + +#ifdef __USE_GNU +/* Copy SRC to DEST, returning the address of the terminating L'\0' in + DEST. */ +extern wchar_t *wcpcpy (wchar_t *__dest, __const wchar_t *__src) __THROW; + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +extern wchar_t *wcpncpy (wchar_t *__dest, __const wchar_t *__src, size_t __n) + __THROW; +#endif /* use GNU */ + + +/* Wide character I/O functions. */ +#if defined __USE_ISOC99 || defined __USE_UNIX98 +__BEGIN_NAMESPACE_C99 + +/* Select orientation for stream. */ +extern int fwide (__FILE *__fp, int __mode) __THROW; + + +/* Write formatted output to STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fwprintf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wprintf__, 2, 3))) */; +/* Write formatted output to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int wprintf (__const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wprintf__, 1, 2))) */; +/* Write formatted output of at most N characters to S. */ +extern int swprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */; + +/* Write formatted output to S from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfwprintf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */; +/* Write formatted output to stdout from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vwprintf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wprintf__, 1, 0))) */; +/* Write formatted output of at most N character to S from argument + list ARG. */ +extern int vswprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */; + + +/* Read formatted input from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fwscanf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; +/* Read formatted input from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int wscanf (__const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wscanf__, 1, 2))) */; +/* Read formatted input from S. */ +extern int swscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; + +__END_NAMESPACE_C99 +#endif /* Use ISO C99 and Unix98. */ + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +/* Read formatted input from S into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfwscanf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; +/* Read formatted input from stdin into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vwscanf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wscanf__, 1, 0))) */; +/* Read formatted input from S into argument list ARG. */ +extern int vswscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; + +__END_NAMESPACE_C99 +#endif /* Use ISO C99. */ + + +__BEGIN_NAMESPACE_C99 +/* Read a character from STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t fgetwc (__FILE *__stream); +extern wint_t getwc (__FILE *__stream); + +/* Read a character from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern wint_t getwchar (void); + + +/* Write a character to STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t fputwc (wchar_t __wc, __FILE *__stream); +extern wint_t putwc (wchar_t __wc, __FILE *__stream); + +/* Write a character to stdout. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t putwchar (wchar_t __wc); + + +/* Get a newline-terminated wide character string of finite length + from STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wchar_t *fgetws (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream); + +/* Write a string to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int fputws (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream); + + +/* Push a character back onto the input buffer of STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t ungetwc (wint_t __wc, __FILE *__stream); +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern wint_t getwc_unlocked (__FILE *__stream); +extern wint_t getwchar_unlocked (void); + +/* This is the wide character version of a GNU extension. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wint_t fgetwc_unlocked (__FILE *__stream); + +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wint_t fputwc_unlocked (wchar_t __wc, __FILE *__stream); + +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern wint_t putwc_unlocked (wchar_t __wc, __FILE *__stream); +extern wint_t putwchar_unlocked (wchar_t __wc); + + +/* This function does the same as `fgetws' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wchar_t *fgetws_unlocked (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream); + +/* This function does the same as `fputws' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputws_unlocked (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream); +#endif + + +__BEGIN_NAMESPACE_C99 +/* Format TP into S according to FORMAT. + Write no more than MAXSIZE wide characters and return the number + of wide characters written, or 0 if it would exceed MAXSIZE. */ +extern size_t wcsftime (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp) __THROW; +__END_NAMESPACE_C99 + +# if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +# include + +/* Similar to `wcsftime' but takes the information from + the provided locale and not the global locale. */ +extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp, + __locale_t __loc) __THROW; +# endif + +/* The X/Open standard demands that most of the functions defined in + the header must also appear here. This is probably + because some X/Open members wrote their implementation before the + ISO C standard was published and introduced the better solution. + We have to provide these definitions for compliance reasons but we + do this nonsense only if really necessary. */ +#if defined __USE_UNIX98 && !defined __USE_GNU +# define __need_iswxxx +# include +#endif + +__END_DECLS + +#endif /* _WCHAR_H defined */ + +#endif /* wchar.h */ diff --git a/include/wctype.h b/include/wctype.h new file mode 100644 index 0000000..266ffab --- /dev/null +++ b/include/wctype.h @@ -0,0 +1,330 @@ +/* Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.25 + * Wide character classification and mapping utilities + */ + +#ifndef _WCTYPE_H + +#include +#include + +#ifndef __UCLIBC_HAS_WCHAR__ +#error Attempted to include wctype.h when uClibc built without wide char support. +#endif + +#ifndef __need_iswxxx +# define _WCTYPE_H 1 + +/* We try to get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +# define __need_wint_t +# include +# ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +# else +# ifdef __USE_ISOC99 +__USING_NAMESPACE_C99(wint_t) +# endif +# endif + +/* Constant expression of type `wint_t' whose value does not correspond + to any member of the extended character set. */ +# ifndef WEOF +# define WEOF (0xffffffffu) +# endif +#endif +#undef __need_iswxxx + + +/* The following part is also used in the header when compiled + in the Unix98 compatibility mode. */ +#ifndef __iswxxx_defined +# define __iswxxx_defined 1 + +__BEGIN_NAMESPACE_C99 +/* Scalar type that can hold values which represent locale-specific + character classifications. */ +/* uClibc note: glibc uses - typedef unsigned long int wctype_t; */ +typedef unsigned int wctype_t; +__END_NAMESPACE_C99 + +# ifndef _ISwbit +# define _ISwbit(bit) (1 << (bit)) + +enum +{ + __ISwupper = 0, /* UPPERCASE. */ + __ISwlower = 1, /* lowercase. */ + __ISwalpha = 2, /* Alphabetic. */ + __ISwdigit = 3, /* Numeric. */ + __ISwxdigit = 4, /* Hexadecimal numeric. */ + __ISwspace = 5, /* Whitespace. */ + __ISwprint = 6, /* Printing. */ + __ISwgraph = 7, /* Graphical. */ + __ISwblank = 8, /* Blank (usually SPC and TAB). */ + __ISwcntrl = 9, /* Control character. */ + __ISwpunct = 10, /* Punctuation. */ + __ISwalnum = 11, /* Alphanumeric. */ + + _ISwupper = _ISwbit (__ISwupper), /* UPPERCASE. */ + _ISwlower = _ISwbit (__ISwlower), /* lowercase. */ + _ISwalpha = _ISwbit (__ISwalpha), /* Alphabetic. */ + _ISwdigit = _ISwbit (__ISwdigit), /* Numeric. */ + _ISwxdigit = _ISwbit (__ISwxdigit), /* Hexadecimal numeric. */ + _ISwspace = _ISwbit (__ISwspace), /* Whitespace. */ + _ISwprint = _ISwbit (__ISwprint), /* Printing. */ + _ISwgraph = _ISwbit (__ISwgraph), /* Graphical. */ + _ISwblank = _ISwbit (__ISwblank), /* Blank (usually SPC and TAB). */ + _ISwcntrl = _ISwbit (__ISwcntrl), /* Control character. */ + _ISwpunct = _ISwbit (__ISwpunct), /* Punctuation. */ + _ISwalnum = _ISwbit (__ISwalnum) /* Alphanumeric. */ +}; +# else +# if defined(__UCLIBC_MJN3_ONLY__) && defined(L_iswctype) +#warning remove _ISwbit already defined check? +#error _ISwbit already defined! +# endif +# endif /* Not _ISwbit */ + + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_C99 +/* + * Wide-character classification functions: 7.15.2.1. + */ + +/* Test for any wide character for which `iswalpha' or `iswdigit' is + true. */ +extern int iswalnum (wint_t __wc) __THROW; + +/* Test for any wide character for which `iswupper' or 'iswlower' is + true, or any wide character that is one of a locale-specific set of + wide-characters for which none of `iswcntrl', `iswdigit', + `iswpunct', or `iswspace' is true. */ +extern int iswalpha (wint_t __wc) __THROW; + +/* Test for any control wide character. */ +extern int iswcntrl (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a decimal-digit + character. */ +extern int iswdigit (wint_t __wc) __THROW; + +/* Test for any wide character for which `iswprint' is true and + `iswspace' is false. */ +extern int iswgraph (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a lowercase letter + or is one of a locale-specific set of wide characters for which + none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswlower (wint_t __wc) __THROW; + +/* Test for any printing wide character. */ +extern int iswprint (wint_t __wc) __THROW; + +/* Test for any printing wide character that is one of a + locale-specific et of wide characters for which neither `iswspace' + nor `iswalnum' is true. */ +extern int iswpunct (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a locale-specific + set of wide characters for which none of `iswalnum', `iswgraph', or + `iswpunct' is true. */ +extern int iswspace (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to an uppercase letter + or is one of a locale-specific set of wide character for which none + of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswupper (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a hexadecimal-digit + character equivalent to that performed be the functions described + in the previous subclause. */ +extern int iswxdigit (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a standard blank + wide character or a locale-specific set of wide characters for + which `iswalnum' is false. */ +# ifdef __USE_ISOC99 +extern int iswblank (wint_t __wc) __THROW; +# endif + +/* + * Extensible wide-character classification functions: 7.15.2.2. + */ + +/* Construct value that describes a class of wide characters identified + by the string argument PROPERTY. */ +extern wctype_t wctype (__const char *__property) __THROW; + +/* Determine whether the wide-character WC has the property described by + DESC. */ +extern int iswctype (wint_t __wc, wctype_t __desc) __THROW; +__END_NAMESPACE_C99 + + +/* + * Wide-character case-mapping functions: 7.15.3.1. + */ + +__BEGIN_NAMESPACE_C99 +/* Scalar type that can hold values which represent locale-specific + character mappings. */ +/* uClibc note: glibc uses - typedef __const __int32_t *wctrans_t; */ +typedef unsigned int wctrans_t; +__END_NAMESPACE_C99 +#ifdef __USE_GNU +__USING_NAMESPACE_C99(wctrans_t) +#endif + +__BEGIN_NAMESPACE_C99 +/* Converts an uppercase letter to the corresponding lowercase letter. */ +extern wint_t towlower (wint_t __wc) __THROW; + +/* Converts an lowercase letter to the corresponding uppercase letter. */ +extern wint_t towupper (wint_t __wc) __THROW; +__END_NAMESPACE_C99 + +__END_DECLS + +#endif /* need iswxxx. */ + + +/* The remaining definitions and declarations must not appear in the + header. */ +#ifdef _WCTYPE_H + +/* + * Extensible wide-character mapping functions: 7.15.3.2. + */ + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_C99 +/* Construct value that describes a mapping between wide characters + identified by the string argument PROPERTY. */ +extern wctrans_t wctrans (__const char *__property) __THROW; + +/* Map the wide character WC using the mapping described by DESC. */ +extern wint_t towctrans (wint_t __wc, wctrans_t __desc) __THROW; +__END_NAMESPACE_C99 + +#if defined(__USE_GNU) && defined(__UCLIBC_HAS_XLOCALE__) +/* Declare the interface to extended locale model. */ +# include + +/* Test for any wide character for which `iswalpha' or `iswdigit' is + true. */ +extern int iswalnum_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character for which `iswupper' or 'iswlower' is + true, or any wide character that is one of a locale-specific set of + wide-characters for which none of `iswcntrl', `iswdigit', + `iswpunct', or `iswspace' is true. */ +extern int iswalpha_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any control wide character. */ +extern int iswcntrl_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a decimal-digit + character. */ +extern int iswdigit_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character for which `iswprint' is true and + `iswspace' is false. */ +extern int iswgraph_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a lowercase letter + or is one of a locale-specific set of wide characters for which + none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswlower_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any printing wide character. */ +extern int iswprint_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any printing wide character that is one of a + locale-specific et of wide characters for which neither `iswspace' + nor `iswalnum' is true. */ +extern int iswpunct_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a locale-specific + set of wide characters for which none of `iswalnum', `iswgraph', or + `iswpunct' is true. */ +extern int iswspace_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to an uppercase letter + or is one of a locale-specific set of wide character for which none + of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswupper_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a hexadecimal-digit + character equivalent to that performed be the functions described + in the previous subclause. */ +extern int iswxdigit_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a standard blank + wide character or a locale-specific set of wide characters for + which `iswalnum' is false. */ +extern int iswblank_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Construct value that describes a class of wide characters identified + by the string argument PROPERTY. */ +extern wctype_t wctype_l (__const char *__property, __locale_t __locale) + __THROW; + +/* Determine whether the wide-character WC has the property described by + DESC. */ +extern int iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale) + __THROW; + + +/* + * Wide-character case-mapping functions. + */ + +/* Converts an uppercase letter to the corresponding lowercase letter. */ +extern wint_t towlower_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Converts an lowercase letter to the corresponding uppercase letter. */ +extern wint_t towupper_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Construct value that describes a mapping between wide characters + identified by the string argument PROPERTY. */ +extern wctrans_t wctrans_l (__const char *__property, __locale_t __locale) + __THROW; + +/* Map the wide character WC using the mapping described by DESC. */ +extern wint_t towctrans_l (wint_t __wc, wctrans_t __desc, + __locale_t __locale) __THROW; + +# endif /* Use GNU. */ + +__END_DECLS + +#endif /* __WCTYPE_H defined. */ + +#endif /* wctype.h */ diff --git a/include/wordexp.h b/include/wordexp.h new file mode 100644 index 0000000..1c40e61 --- /dev/null +++ b/include/wordexp.h @@ -0,0 +1,71 @@ +/* Copyright (C) 1991, 92, 1996-1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _WORDEXP_H +#define _WORDEXP_H 1 + +#include +#define __need_size_t +#include + +__BEGIN_DECLS + +/* Bits set in the FLAGS argument to `wordexp'. */ +enum + { + WRDE_DOOFFS = (1 << 0), /* Insert PWORDEXP->we_offs NULLs. */ + WRDE_APPEND = (1 << 1), /* Append to results of a previous call. */ + WRDE_NOCMD = (1 << 2), /* Don't do command substitution. */ + WRDE_REUSE = (1 << 3), /* Reuse storage in PWORDEXP. */ + WRDE_SHOWERR = (1 << 4), /* Don't redirect stderr to /dev/null. */ + WRDE_UNDEF = (1 << 5), /* Error for expanding undefined variables. */ + __WRDE_FLAGS = (WRDE_DOOFFS | WRDE_APPEND | WRDE_NOCMD | + WRDE_REUSE | WRDE_SHOWERR | WRDE_UNDEF) + }; + +/* Structure describing a word-expansion run. */ +typedef struct + { + size_t we_wordc; /* Count of words matched. */ + char **we_wordv; /* List of expanded words. */ + size_t we_offs; /* Slots to reserve in `we_wordv'. */ + } wordexp_t; + +/* Possible nonzero return values from `wordexp'. */ +enum + { +#ifdef __USE_XOPEN + WRDE_NOSYS = -1, /* Never used since we support `wordexp'. */ +#endif + WRDE_NOSPACE = 1, /* Ran out of memory. */ + WRDE_BADCHAR, /* A metachar appears in the wrong place. */ + WRDE_BADVAL, /* Undefined var reference with WRDE_UNDEF. */ + WRDE_CMDSUB, /* Command substitution with WRDE_NOCMD. */ + WRDE_SYNTAX /* Shell syntax error. */ + }; + +/* Do word expansion of WORDS into PWORDEXP. */ +extern int wordexp (__const char *__restrict __words, + wordexp_t *__restrict __pwordexp, int __flags); + +/* Free the storage allocated by a `wordexp' call. */ +extern void wordfree (wordexp_t *__wordexp) __THROW; + +__END_DECLS + +#endif /* wordexp.h */ diff --git a/include/xlocale.h b/include/xlocale.h new file mode 100644 index 0000000..6f726fe --- /dev/null +++ b/include/xlocale.h @@ -0,0 +1,62 @@ +/* Definition of locale datatype. + Copyright (C) 1997,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _XLOCALE_H +#define _XLOCALE_H 1 + +#include + +#ifndef __UCLIBC_HAS_XLOCALE__ +#error Attempted to include xlocale.h when uClibc built without extended locale support. +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#include +/* #include */ + +#if 0 +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. The file and + this data structure is not standardized. Don't rely on it. It can + go away without warning. */ +typedef struct __locale_struct +{ +#if 0 + /* Note: LC_ALL is not a valid index into this array. */ + struct locale_data *__locales[13]; /* 13 = __LC_LAST. */ +#endif + + /* To increase the speed of this solution we add some special members. */ +/* const unsigned short int *__ctype_b; */ +/* const int *__ctype_tolower; */ +/* const int *__ctype_toupper; */ + const __uint16_t *__ctype_b; + const __ctype_touplow_t *__ctype_tolower; + const __ctype_touplow_t *__ctype_toupper; + + __uclibc_locale_t *__locale_ptr; + +#if 0 + /* Note: LC_ALL is not a valid index into this array. */ + const char *__names[13]; +#endif +} *__locale_t; +#endif + +#endif /* xlocale.h */ diff --git a/ldso/COPYRIGHT b/ldso/COPYRIGHT new file mode 100644 index 0000000..fb34248 --- /dev/null +++ b/ldso/COPYRIGHT @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, David Engel, + * Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Notice of general intent: + * + * The linux operating system generally contains large amounts of code + * that fall under the GNU General Public License, or GPL for short. + * This file contains source code that by it's very nature would always + * be linked with an application program, and because of this a GPL + * type of copyright on this file would place restrictions upon the + * distribution of binary-only commercial software. Since the goal of + * the Linux project as a whole is not to discourage the development and + * distribution of commercial software for Linux, this file has been + * placed under a more relaxed BSD-style of copyright. + * + * It is the general understanding of the above contributors that a + * program executable linked to a library containing code that falls + * under the GPL or GLPL style of license is not subject to the terms of + * the GPL or GLPL license if the program executable(s) that are supplied + * are linked to a shared library form of the GPL or GLPL library, and as + * long as the form of the shared library is such that it is possible for + * the end user to modify and rebuild the library and use it in + * conjunction with the program executable. + */ diff --git a/ldso/Makefile b/ldso/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/ldso/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/ldso/Makefile.in b/ldso/Makefile.in new file mode 100644 index 0000000..7bbef23 --- /dev/null +++ b/ldso/Makefile.in @@ -0,0 +1,9 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)ldso/ldso/Makefile.in +include $(top_srcdir)ldso/libdl/Makefile.in diff --git a/ldso/README b/ldso/README new file mode 100644 index 0000000..dc37ea6 --- /dev/null +++ b/ldso/README @@ -0,0 +1,841 @@ + +Apr 20, 2001 -- Manuel Novoa III + +Inital port for uClibc from debian ld.so_1.9.11-9.tar.gz. + +Removed a.out support. + +****************** original ld.so.lsm file ************************** +Begin3 +Title: Linux shared, dynamic linker and utilities. +Version: 1.9.11 +Entered-date: 01MAY99 +Description: This package contains ld.so, ld-linux.so, ldconfig, + ldd and libdl. +Keywords: dynamic linker, shared library, ld.so, ld-linux.so, + ldconfig, ldd, libdl +Author: david@ods.com (David Engel) +Maintained-by: david@ods.com (David Engel) +Primary-site: tsx-11.mit.edu /pub/linux/packages/GCC + ld.so-1.9.11.tar.gz +Alternate-site: sunsite.unc.edu /pub/Linux/GCC + ld.so-1.9.11.tar.gz +Platform: Linux 2.0.0 or later. +Copying-policy: Copyrighted but freely distributable. +End +********************************************************************* + Original README starts here +********************************************************************* + +This package contains my ELF dynamic linkers (ld-linux.so.1), dynamic +linker library (libdl.so.1) and utilities (ldconfig and ldd) for Linux. + +You need Linux kernel 2.0.0 or later with ELF support compiled in +(i.e. not loaded as a module) to use this package. + +The dynamic linker is used to bootstrap programs and load shared +libraries at startup. The dynamic linker library is used to +dynamically load shared libraries after a program is running. +Ldconfig is used to automatically update the symbolic links to shared +libraries and build the cache file used by the dynamic linker. Ldd is +used to list the shared libraries used by a program. + +Please see the included manual pages for further details. + +To install, simply run "sh instldso.sh" as root. Ready-to-go versions +of all end-products are provided so nothing should need to be compiled +or linked. If you are still using libc5 as your primary development +library, you should use the "--devfiles" option when running +instldso.sh to install the file needed to compile with libdl. + +ELF versions of gcc, binutils and libc are now required to compile +everything, including the old, unsupported, a.out dynamic linker. +Finally, an optimization level of O2 or higher must be used to compile +ld-linux.so and libdl.so due the use of inline functions. + +Notable contributors to this package include Eric Youngdale, Peter +MacDonald, Hongjiu Lu, Linus Torvalds, Lars Wirzenius, Mitch D'Souza, +Rik Faith, Andreas Schwab and Adam Richter (not necessarily in that +order). + +###################### IMPORTANT NOTICES ############################# + +A.OUT SUPPORT: + +As of ld.so-1.9.0, the old, a.out dynamic loader is no longer +officially supported. The code is still included and built, but I +make no promises that it will work. I will accept patches for it, +but they will not be tested by me. + +GLIBC (AKA LIBC6) SUPPORT: + +As of ld.so-1.9.0, the main focus of this package is to ease the +transition to libc6. No significant, new features are expected to be +added. If you need new features, switch to libc6. + +Except for libpthread.so, the sonames of the core libraries provided +with libc6 have been chosen so they do not conflict with those +provided by libc5 and ld.so. However, the current plan is not use +new, nonconflicting sonames for other libraries such as ncurses and +X11. This presents two problems. First, libraries using the same +soname for both libc5 and libc6 can not be placed in the same +directory. Second, the dynamic linkers need to make sure not to load +a library for the wrong version of libc. + +The first problem is easy. Just move the old, libc5-based libraries +to new directories (e.g. /lib/libc5-compat, /usr/lib/libc5-compat, +etc.) and add those directories to /etc/ld.so.conf. Then install the +new, libc6-based versions in the standard places. + +The second problem is more difficult. Ideally, the dynamic linkers +would be changed to perform a complete dependency analysis on every +library to be loaded to make sure the wrong versions aren't used. +This approach doesn't seem worth the added complexity, especially +since we now have symbol versioning for ELF libraries. Instead a +simpler approach will be used, at least initially. + +Ldconfig has been modified to perform a (currently simple) dependency +analysis on libraries and to store an indication in /etc/ld.so.cache +of whether a library is for libc5, libc6 or an unknown libc. The +dynamic linkers then only need to make a simple check at run-time to +make sure they don't load the wrong version of a library. + +The dynamic linker for libc5 provided in this package, has already +been modified to use the new information in /etc/ld.so.cache. For +glibc versions 2.0.1 and earlier, the dynamic linker for libc6 needs +the patch contained in glibc.patch. You should apply the patch and +rebuild glibc before using the new ldconfig. + +As stated above, the dependency analysis currently done by ldconfig is +rather simple. Basically, it looks for the sonames used by the +various versions of libc, libm and libdl. For any approach using a +dependency analysis such as this to work, it is very important that +shared libraries be built with complete dependency information. This +can be done by using the appropriate -l options when running 'gcc +-shared'. For example, when building libfoo.so which depends on libc +and libbar, you should add -lbar and -lc gcc command line. + +###################################################################### + +Changes in version 1.9.11: + + Fixed a bug in ld-linux.so where a reference to an + undefined symbol could cause a segfault. + + Added a clarification for LD_PRELOAD to the ld.so manual + page and added a symlink for ld-linux.so (Bug#33123). + + Don't install ldd for Debian except for the m68k arch + because glibc 2.1 now includes it (Bug#35458). + +Changes in version 1.9.10: + + Changed ldconfig to issue a warning and not overwrite a + regular file with a symlink (Bug#30859). + + Changed Debian packaging to conflict with and replace the + ldconfig package (Bug#29398). + +Changes in version 1.9.9: + + Changed ld-linux.so and libdl.so to match glibc by not + allowing user preloads of system libraries into setu/gid + binaries unless the library itself is setuid. + + Fixed problems in ld-linux.so on the sparc architecture + (Juan Cespedes). + +Changes in version 1.9.8: + + Changed ldconfig to allow the expected type for all + libraries in a directory to be optionally specified + (Mark Phillips). See the ldconfig man page. + + Changed ldconfig to use the same type names used in the + change above when the -p option is used. + +Changes in version 1.9.7: + + Changed ldd for m68k to use /lib/ld.so.1 instead of + /lib/ld-linux.so.2. + + Added support for dladdr to libdl.so (Eduard Gode). + + Fixed a small memory leak in libdl.so (Richard Garnish). + + Fixed a bug in ldconfig when the -l option was used on a + filename without a '/' in it. + + Updated the man pages (Bug#6404, Bug#9721, Bug#10652, + Bug#13494 and Bug#14127). They could still use some work. + + No longer install the info page since it's way out of date. + + Fixed minor Debian packaging problems (Bug#13160, + Bug#15577 and Bug#19345). + +Changes in version 1.9.6: + + Changed ldd to not use the glibc dynamic linker when run + on a libc5-based shared library. + + Added a -q option to ldconfig which causes warnings not + to be printed (Bob Tinsley). + + Dropped support for the Debian libdl1-dev package. + + Changed ld-linux.so to be compilable with gcc 2.8.0 (Sven + Verdoolaege) + +Changes in version 1.9.5: + + Fixed a bug in ldd where ld-linux.so.2 was not called + correctly when run on shared libraries. + + Fixed a problem in the previous version where some + Makefiles were not architecture independent. + +Changes in version 1.9.4: + + Fixed a bug in ld.so introduced in the previous version + which broke preloads. + + Turned a.out support back on by default, at least for the + time being. There are no promises to keep it. + +Changes in version 1.9.3: + + Fixed buffer overflow bugs in ld-linux.so and ld.so. + + Changed the README file a little to clarify a couple of + things. + + Changed ldconfig to chroot to the specified directory when + the new -r option is used (Bob Tinsley). + +Changes in version 1.9.2: + + Removed /usr/local/lib from the default /etc/ld.so.conf + for Debian (Bug#8181). + + Changed ldconfig to be 64-bit clean (H.J. Lu). + +Changes in version 1.9.1: + + Changed ldconfig to try to determine which libc a + library is for even if it doesn't have an soname. + + Fixed a bug in ldconfig where an older library using + the glibc naming convention would be used instead of + a newer library. + + Changed to ld-linux.so and libdl.so to not require the + libc5 headers in order to compile. + + Changed ldconfig and ldd to be compilable with either + libc5 or libc6. + +Changes in version 1.9.0: + + Changed to not build the old, a.out dynamic loader by + default. + + Changed instldso.sh to require the --force option to + make sure users read the README file. + + Changed instldso.sh to not install the libdl.so + development files unless the --devfiles option is used. + + Changed instldso.sh to not strip binaries and libraries + if the --no-strip option is used. + + Changed the Debian packaging to put the development files + which conflict with glibc in a new libdl1-dev package. + + Changed ldd to use the glibc dynamic linker, if it is + available, when run on a shared library. + + Changed ld-linux.so to print the load addresses of + libraries, ala glibc, when run by ldd. + + Changed ld-linux.so to allow the libraries listed in + LD_PRELOAD to be separated by white space in addition to + colons. + + Changed ld-linux.so to load the libraries listed in + LD_PRELOAD for setu/gid programs as long as they can be + loaded securely. + + Changed ldconfig to update the symlinks for the dynamic + linkers. + + Changed ldconfig to try to determine if an ELF library is + intended for libc5 or libc6 and save the infomation in the + cache. The mechanism used is rather simplistic and may + need to be enhanced. + + Changed ldconfig to print the type of ELF library when + printing the cache. + + Changed ld-linux.so to only load ELF shared libraries for + use with libc5 or an unknown libc. + +Changes in version 1.8.10: + + Fixed a bug in ldconfig where a symlink could be used + instead of a regular file. + + Fixed a Debian packaging problem for the sparc + architecture. + +Changes in version 1.8.9: + + Changed ldconfig to only cache the symlinks it creates. + This make the behavior of the dynamic linkers consistent + with how they would behave if a cache was not used. + + Changed ldconfig to cache the symlinks that it finds but + use the name of the symlink as the soname instead of the + actual soname. + +Changes in version 1.8.8: + + Minor documentation updates to reflect recent changes. + + Changed ld.so and ld-linux.so to perform more complete + validation on ld.so.cache before using it. + + Changed ldconfig to accept libraries with inconsistent + sonames since glibc is going to use them. A warning is + still printed in debug mode. + + Changed the install script to not strip _dl_debug_state + from ld-linux.so since gdb needs it. + + More sparc fixes (Derrick Brashear). + + Changed ldconfig to not issue a warning when a linker + script disguised as a shared library is found. + + Fixed a bug in ld-linux.so where some registers were + not preserved on the first call to a function causing + problems for non-C-like languages (Tim Renouf). + + Fixed a bug in ld-linux.so where global variables were + not always mapped correctly across dynamically loaded + libraries (Mikihiko Nakao). + + Converted to new Debian source packaging format (Shaya + Potter). + +Changes in version 1.8.6/7: + + Never released as some unofficial patches used these + version numbers. + +Changes in version 1.8.5: + + Fixed a bug in ld.so introduced in the previous changes. + +Changes in version 1.8.4: + + Changed ldconfig to completely ignore symbolic links. + + Changed ldconfig to issue the warning concerning an + inconsistent soname in non-verbose mode. + + Changed ld-linux.so back to not keep ld.so.cache mapped + at all times. + + Changed Debian packaging to compress man pages, strip all + binaries (Bug#5125) and include a shlibs file. + +Changes in version 1.8.3: + + Changed ld-linux.so to process LD_PRELOAD before + /etc/ld.so.preload. + + Fixed a Debian packaging problem where libdl might not + be available if other packages were upgraded at the same + time (Debian Bug#4728). + + Changed ldd to always exit with status 1 if any errors + occur (Debian Bug#4188). + + Fixed some minor problems in instldso.sh (Mike Castle and + Wolfgang Franke). + + Changed ldconfig to issue a warning in verbose mode when + skipping a library because the soname doesn't match. + + More sparc fixes (Miguel de Icaza). + + Don't link with -N when building ld.so (Alan Modra). + + Changed ld-linux.so to better support position-dependant + libraries (NIIBE Yutaka). + +Changes in version 1.8.2: + + Added a texinfo file for ld.so and libdl (Michael + Deutschmann). + + Minor sparc and installation changes (Elliot Lee). + + Added multiple architecture support for Debian (Leland + Lucius). + + Changed libdl to better support RTLD_NEXT (Eric + Youngdale). Note: the exact meaning of ETLD_NEXT is + still not clear in all cases. + + Removed some libc dependencies from libdl. Still need + to remove malloc and free. + +Changes in version 1.8.1: + + Changed ld.so to be compiled as ELF. This also means + that ELF support is now required. A.out support is + still optional. + + Changed ld-linux.so and libdl.so to use the rpath in the + executable instead of in the invoking shared library. + + More m68k fixes (Andreas Schwab). + + Various sparc fixes (Miguel de Icaza). + + Changed ldcnnfig to ignore libraries ending in '~'. + + Changed ldconfig to allow alternative conf and cache + files to be specified on the command-line. + + Changed libdl.so to work when dlsym is passed a NULL + handle pointer. + +Changes in version 1.8.0: + + Changed ld-linux.so to be more liberal when checking to + see if a library is already loaded. This should avoid + the duplicate loading problem for programs linkeed with + the -rpath option. + + Various m68k fixes (Andreas Schwab). + + Changed ld.so to only use LD_AOUT_LIBRARY_PATH and + LD_AOUT_PRELOAD and ld-linux.so to only use + LD_LIBRARY_PATH and LD_PRELOAD. LD_ELF_LIBRARY_PATH + and LD_ELF_PRELOAD are no longer supported. + + Changed ld-linux.so to allow debugging of shared and + dynamically loaded libraries (H.J. Lu, Andreas Schwab). + + Changed ld-linux.so to preload ELF shared libraries + listed in /etc/ld.so.preload. This allows secure + preloads, even for setuid/setgid programs. + + Changed ld-linux.so to keep ld.so.cache mapped at all + times. + + Changed ldconfig to allow #-style comments in ld.so.conf. + + Removed various compiler warnings (Richard Sladkey and + David Engel). + + Changed ldd to work on ELF shared libraries. This may + need a little more work. + +Changes in version 1.7.14: + + Changed ldconfig to recognize ELF shared libraries + generated by post-2.6 versions of ld (Andreas Schwab). + + Changed ldconfig to not remove stale links that do not + have a version number since they may be needed by ld. + +Changes in version 1.7.13: + + Fixed a problem in ld-linux.so where a program linked + with a shared library that was not used could result in + a segmentation fault (H.J. Lu). + +Changes in version 1.7.12: + + Fixed a problem in libdl.so where the wrong library + could be marked as global when RTLD_GLOBAL was used + (Lars Heete). + + Installed dlfcn.h with libdl.so instead of requiring + it to be supplied with libc. + + Removed support for libldso.a since it was nearly + impossible to use anyway. + + Changed ldd to detect when the program being checked + exited abnormally. + +Changes in version 1.7.11: + + Changed ld.so and ld-linux.so to delete all variations + of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs, + This makes it harder for broken set[ug]id programs to be + compromised. + + Fixed a problem in libdl.so where dlsym would not accept + the handle returned from dlopen(0, *). + +Changes in version 1.7.10: + + Changed ld-linux.so and libdl.so to support RTLD_GLOBAL + (Eric Youngdale). + +Changes in version 1.7.9: + + Fixed a problem in ld-linux.so in detecting when the + new user/group information is provided by the kernel. + + Fixed a problem in ld-linux.so where a buffer could be + overflowed if a large number of libraries were loaded + (Thomas Moore). + +Changes in version 1.7.8: + + Changed the Makefiles and install scripts to support + a.out- and ELF-only configurations. + + Changed ld-linux.so to use the user/group information + provided by linux 1.3.23+ instead of making syscalls + to get it. + + Changed libdl.so to support RTLD_NEXT (Glenn Fowler). + + Changed libdl.so to only execute the fini sections + instead of completely closing libraries at exit (Glenn + Fowler). + + Changed ld.so and ld-linux.so to print the required + cache version when a mismatch is detected. + + Changed ld-linux.so to not require on /dev/zero (Ralph + Loader). + + Minor m68k cleanups (Andreas Schwab). + +Changes in version 1.7.7: + + Fixed problems compiling with recent 1.3.x kernels. + + Changed ld-linux.so to not use MAP_DENYWRITE until the + permission issue regarding it is resolved. + +Changes in version 1.7.6: + + Fixed a bug in ld-linux.so dealing with a zero-length + LD_{ELF_}PRELOAD. + + Changed ld.so and ld-linux.so to truncate all variations + of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs. + +Changes in version 1.7.5: + + Changed ldconfig to recognize libraries without any + version number (eg. libXYZ.so). + + Changed ldconfig to not generate a corrupt cache when + the disk is full or other write errors occur. + + Changed ld-linux.so to map files with MAP_DENYWRITE to + keep them from being changed while the file is in use + (Rick Sladkey). + + Changed libdl to not overwrite the scope pointer of a + library if it was already loaded (H.J. Lu). + + Changed ld-linux.so so gdb can be used on constructors + (Eric Youngdale). + + Changed ldconfig to ignore ELF libraries where the soname + does not match the file name on the assumption that it is + a used at compile-time (eg. libcurses.so -> libncruses.so). + +Changes in version 1.7.4: + + Changed ld-linux.so and libdl to use the appropriate + rpaths when searching for shared libraries (Eric + Youngdale). + + Changed ld-linux.so to search rpath before using the + cache. This more closely conforms to the IBCS standard. + +Changes in version 1.7.3: + + Changed ld-linux.so to only print a library name the + first time it is loaded when run from ldd. + + Fixed a bug in ldconfig where an invalid cache could be + generated if a directory was specified multiple times in + ld.so.conf. + + Changed ld-linux.so so it will return the address of a + weak symbol when called from dlsym in libdl (Eric + Youngdale. + +Changes in version 1.7.2: + + Changed libdl.so again to fix the undefined foobar + problem. + +Changes in version 1.7.1: + + Changed libdl so it will compile at optimization level + O3 or higher. + + Changed ldconfig to always create the cache file with + mode 644. + + Changed ldconfig to not ingore valid symlinks. + + Changed ldconfig to use the library name as the soname + for ELF libraries that do not have an soname entry. + + Changed ld-linux.so to print the actual, requested library + name at the time it is loaded instead of trying to figure + it out after the fact. + +Changes in version 1.7.0: + + Changed ldconfig to read the actual soname from the image + for ELF libraries and make it available to ld-linux.so. + The soname for DLL libraries is still determined by + truncating the minor numbers from the image file name. + + Changed ldconfig to no longer support the undocumented + sort options. + + Changed ld.so to require a valid cache to find libraries + in directories specified in ld.so.conf. /usr/lib and /lib + are still searched as a last resort. Ld-linux.so already + operated this way. + + Fixed a bug in libldso.a where the arguments to + shared_loader were not parsed correctly (Wolfram Gloger). + + Added support for RELA-style relocations under Linux/68k + (Andreas Schwab). + + Changed ld-linux.so to only map the cache once for all + libraries instead of individually for each library. + + Changed ld-linux.so continue searching the cache instead of + giving up when failing to load the first entry found. + + Changed ld-linux.so to produce output similar to ld.so when + run from ldd or when errors occur. + +Changes in version 1.6.7: + + Changed the install scripts to make sure that ld.so and + ld-linux.so are always usable. + + Added support for Linux/Sparc (Eric Youngdale). + + Added support for Linux/68k (Andreas Schwab). + + Fixed various bugs in ld-linux.so dealing with closing + files, unmapping memory, dereferencing NULL pointers and + printing library names (David Engel, Eric Youngdale and + Andreas Schwab). + + Replaced the manual page for libdl with a freely + distributable one (Adam Richter). + + Fixed a bug in ld-linux.so where LD_LIBRARY_PATH and + LD_PRELOAD were not cleared for setuid/setgid programs. + + Fixed a bug in libdl where dlsym would not return the + correct address of a symbol if it was redefined in another + library (Oleg Kibirev). + + Changed ld-linux.so to use the following order to search + for libraries: LD_{ELF_}LIBRARY_PATH, ld.so.cache, rpath, + /usr/lib and /lib. + + Changed ld-linux.so to not needlessly allocate memory when + using ld.so.cache. + +Changes in version 1.6.6: + + Changed ldconfig to not warn about removing stale links + unless the -v option is specified. + + Added manual pages for libdl (from FreeBSD/Sun) + + Fixed a bug in ld.so dealing with preloading of objects + generated by recent versions of ld (Mitch D'Souza). + + Fixed bugs in ldd where some errors were either not + detected or not printed. + + Fixed a bug in ld-linux.so where the trailing nul in a + library name was not being copied (Owen Taylor). + +Changes in version 1.6.5: + + Changed ldconfig to remove stale symbolic links. + + Added debug hooks in ld-linux.so and libdl.so to be used + by a future version of gdb (Eric Youngdale). + +Changes in version 1.6.4: + + Change ld-linux.so to print on stdout instead of stderr + when run from ldd. + + Added support for Debian GNU/Linux packaging. + +Changes in version 1.6.3: + + Fixed a bug in libdl when closing a library (H.J. Lu). + +Changes in version 1.6.2: + + Changed the error message printed by ldd when a file is + not a.out or ELF. It used to only list a.out formats. + + Changed ldconfig to no longer cache and set up links for + ld-linux.so. + + Changed ld-linux.so and libdl to not conflict with upcoming + changes in kernel header files. + + Changed ld-linux.so to not print preloaded libraries. + +Changes in version 1.6.1: + + Updated the installation script. + + Changed ld.so and ld-linux.so to look for LD_AOUT_PRELOAD + and LD_ELF_PRELOAD, respectively, before LD_PRELOAD. + + Changed ld.so and ld-linux.so to use LD_AOUT_LIBRARY_PATH + and LD_ELF_LIBRARY_PATH, respectively, instead of + AOUT_LD_LIBRARY_PATH and ELF_LD_LIBRARY_PATH. + +Changes in version 1.6.0: + + Changed ldconfig to process libraries which do not have + a minor version or patch level number. + + Incorporated ld-linux.so and libdl.so. + + Changed ld.so and ld-linux.so to not miss entries in the + cache when the fully qualified library is requested. + + Changed ldconfig to use stdout instead of stderr when + printing the cache. + +Changes in version 1.5.3: + + LD_PRELOAD enhancements (Tristan Gigold). + + LD_PRELOAD patch for linux-68k (Andreas Schwab). + +Changes in version 1.5.2: + + More ELF changes (Mitch D'Souza). + + Changed ldconfig to also update the link for ld-linux.so. + +Changes in version 1.5.1: + + More ELF and LD_PRELOAD changes (Mitch D'Souza). + +Changes in version 1.5.0: + + Chnaged all executables to QMAGIC (Mitch D'Souza and Rick + Sladkey). + + Added preliminary support for ELF to ldd and ldconfig (Eric + Youndale and H.J. Lu). + + Added support for LD_PRELOAD to ld.so (Mitch D'Souza). + + Removed the "advertising" clause from the copyright notices + in all source files. + +Changes in version 1.4.4: + + Changed ldconfig to support QMAGIC libraries. + + Fixed a bug in ld.so where some of the error messages had + transposed arguments. + +Changes in version 1.4.3: + + Fixed an obscure bug in ld.so where an index was not being + incremented when a library was not found using the cache. + +Changes in version 1.4.2: + + Changed ldconfig to issue a warning and continue instead + of an error and exiting when a link can't be updated. + This is useful when some libraries are imported on read- + only file systems, such as an NFS mounted /usr. + + Changed ld.so to be more robust in searching for libraries. + A library is not considered found unless it can actually be + loaded. If a library is not found using the cache, the + standard directories are searched as in pre-cache versions. + +Changes in version 1.4.1: + + Fixed minor Makefile problems. + + Added support for linux-68k. + + Fixed a bug in ld.so where libraries with absolute paths + were not handled correctly. + + Changed ld.so to ignore the directory in the names of + shared libraries by default. This allows older libraries + with absolute paths, such as the XView libraries, to take + advantage of the cache support. + + Added a minimal usage message to ldconfig. + +Changes in version 1.4: + + Fixed bug in ld.so where minor version numbers were not + reported correctly when a minor version incompatibility + was found. + + Fixed bug in ldconfig where libraries with subversion + numbers greater than 9 were not compared correctly. + + Added Mitch D'Souza's support for suppressing warning + messages from ld.so about minor version incompatibilities. + + Added Mitch D'Souza's support for using a cache to speed + up searching for libraries in the standard directories. + + Added Mitch D'Souza's support for a debugging version of + ld.so. Link with -lldso if you think you are experiencing + dynamic linker problems. + +Changes in version 1.3: + + Added support for libraries using absolute pathnames. If I + had known that the XView libraries used them, I would have + added this earlier. + + Fixed a bug handling old libraries using a pathname beginning + with '/' or '/lib/'. + +Changes in version 1.2a: + + Fixed a minor bug in ldd which caused all files, specifically + scripts, to be recognized as binaries. Thanks to Olaf Flebbe + for reporting it. + +David Engel +david@sw.ods.com diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h new file mode 100644 index 0000000..791d068 --- /dev/null +++ b/ldso/include/dl-defs.h @@ -0,0 +1,254 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_DEFS_H +#define _LD_DEFS_H + +#define FLAG_ANY -1 +#define FLAG_TYPE_MASK 0x00ff +#define FLAG_LIBC4 0x0000 +#define FLAG_ELF 0x0001 +#define FLAG_ELF_LIBC5 0x0002 +#define FLAG_ELF_LIBC6 0x0003 +#define FLAG_ELF_UCLIBC 0x0004 +#define FLAG_REQUIRED_MASK 0xff00 +#define FLAG_SPARC_LIB64 0x0100 +#define FLAG_IA64_LIB64 0x0200 +#define FLAG_X8664_LIB64 0x0300 +#define FLAG_S390_LIB64 0x0400 +#define FLAG_POWERPC_LIB64 0x0500 +#define FLAG_MIPS64_LIBN32 0x0600 +#define FLAG_MIPS64_LIBN64 0x0700 + +#define LIB_ANY -1 +#define LIB_DLL 0 +#define LIB_ELF 1 +#define LIB_ELF64 0x80 +#define LIB_ELF_LIBC5 2 +#define LIB_ELF_LIBC6 3 +#define LIB_ELF_LIBC0 4 + +#if defined(__LDSO_PRELOAD_FILE_SUPPORT__) || defined(__LDSO_CACHE_SUPPORT__) +#ifndef __LDSO_BASE_FILENAME__ +#define __LDSO_BASE_FILENAME__ "ld.so" +#endif +#define LDSO_BASE_PATH UCLIBC_RUNTIME_PREFIX "etc/" __LDSO_BASE_FILENAME__ + +#ifdef __LDSO_PRELOAD_FILE_SUPPORT__ +#define LDSO_PRELOAD LDSO_BASE_PATH ".preload" +#endif + +#ifdef __LDSO_CACHE_SUPPORT__ +#define LDSO_CONF LDSO_BASE_PATH ".conf" +#define LDSO_CACHE LDSO_BASE_PATH ".cache" + +#define LDSO_CACHE_MAGIC "ld.so-" +#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) +#define LDSO_CACHE_VER "1.7.0" +#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) + +typedef struct { + char magic [LDSO_CACHE_MAGIC_LEN]; + char version [LDSO_CACHE_VER_LEN]; + int nlibs; +} header_t; + +typedef struct { + int flags; + int sooffset; + int liboffset; +} libentry_t; + +#ifdef __ARCH_USE_MMU__ +#define LDSO_CACHE_MMAP_FLAGS (MAP_SHARED) +#else +#define LDSO_CACHE_MMAP_FLAGS (MAP_PRIVATE) +#endif +#endif /* __LDSO_CACHE_SUPPORT__ */ + +#endif + +/* Provide a means for a port to pass additional arguments to the _dl_start + function. */ +#ifndef DL_START +# define DL_START(X) static void * __attribute_used__ _dl_start(X) +#endif + +/* Machines in which different sections may be relocated by different + * amounts should define this and LD_RELOC_ADDR. If you change this, + * make sure you change struct link_map in include/link.h accordingly + * such that it matches a prefix of struct elf_resolve. + */ +#ifndef DL_LOADADDR_TYPE +# define DL_LOADADDR_TYPE ElfW(Addr) +#endif + +/* When DL_LOADADDR_TYPE is not a scalar value, or some different + * computation is needed to relocate an address, define this. + */ +#ifndef DL_RELOC_ADDR +# define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((LOADADDR) + (ADDR)) +#endif + +/* Initialize the location of the dynamic addr. This is only called + * from DL_START, so additional arguments passed to it may be referenced. */ +#ifndef DL_BOOT_COMPUTE_DYN +#define DL_BOOT_COMPUTE_DYN(DPNT, GOT, LOAD_ADDR) \ + ((DPNT) = ((ElfW(Dyn) *) DL_RELOC_ADDR(load_addr, got))) +#endif + +/* Initialize the location of the global offset table. This is only called + * from DL_START, so additional arguments passed to it may be referenced. */ +#ifndef DL_BOOT_COMPUTE_GOT +#define DL_BOOT_COMPUTE_GOT(GOT) \ + ((GOT) = elf_machine_dynamic()) +#endif + +/* Initialize a LOADADDR representing the loader itself. It's only + * called from DL_START, so additional arguments passed to it may be + * referenced. + */ +#ifndef DL_INIT_LOADADDR_BOOT +# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + ((LOADADDR) = (BASEADDR)) +#endif + +/* Define if any declarations/definitions of local variables are + * needed in a function that calls DT_INIT_LOADADDR or + * DL_INIT_LOADADDR_HDR. Declarations must be properly terminated + * with a semicolon, and non-declaration statements are forbidden. + */ +#ifndef DL_INIT_LOADADDR_EXTRA_DECLS +# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */ +#endif + +/* Prepare a DL_LOADADDR_TYPE data structure for incremental + * initialization with DL_INIT_LOADADDR_HDR, given pointers to a base + * load address and to program headers. + */ +#ifndef DL_INIT_LOADADDR +# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + ((LOADADDR) = (BASEADDR)) +#endif + +/* Initialize a LOADADDR representing the program. It's called from + * DL_BOOT only. + */ +#ifndef DL_INIT_LOADADDR_PROG +# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + ((LOADADDR) = (DL_LOADADDR_TYPE)(BASEADDR)) +#endif + +/* Update LOADADDR with information about PHDR, just mapped to the + given ADDR. */ +#ifndef DL_INIT_LOADADDR_HDR +# define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) /* Do nothing. */ +#endif + +/* Convert a DL_LOADADDR_TYPE to an identifying pointer. Used mostly + * for debugging. + */ +#ifndef DL_LOADADDR_BASE +# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR) +#endif + +/* Test whether a given ADDR is more likely to be within the memory + * region mapped to TPNT (a struct elf_resolve *) than to TFROM. + * Everywhere that this is used, TFROM is initially NULL, and whenever + * a potential match is found, it's updated. One might want to walk + * the chain of elf_resolve to locate the best match and return false + * whenever TFROM is non-NULL, or use an exact-matching algorithm + * using additional information encoded in DL_LOADADDR_TYPE to test + * for exact containment. + */ +#ifndef DL_ADDR_IN_LOADADDR +# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + ((void*)(TPNT)->mapaddr < (void*)(ADDR) \ + && (!(TFROM) || (TFROM)->mapaddr < (TPNT)->mapaddr)) +#endif + +/* This is called from dladdr() to give targets that use function descriptors + * a chance to map a function descriptor's address to the function's entry + * point before trying to find in which library it's defined. */ +#ifndef DL_LOOKUP_ADDRESS +#define DL_LOOKUP_ADDRESS(ADDRESS) (ADDRESS) +#endif + +/* Use this macro to convert a pointer to a function's entry point to + * a pointer to function. The pointer is assumed to have already been + * relocated. LOADADDR is passed because it may contain additional + * information needed to compute the pointer to function. + */ +#ifndef DL_ADDR_TO_FUNC_PTR +# define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) ((void(*)(void))(ADDR)) +#endif + +/* On some platforms, computing a pointer to function is more + expensive than calling a function at a given address, so this + alternative is provided. The function signature must be given + within parentheses, as in a type cast. */ +#ifndef DL_CALL_FUNC_AT_ADDR +# define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ((*SIGNATURE DL_ADDR_TO_FUNC_PTR ((ADDR), (LOADADDR)))(__VA_ARGS__)) +#endif + +/* An alignment value for a memory block returned by _dl_malloc. */ +#ifndef DL_MALLOC_ALIGN +# define DL_MALLOC_ALIGN (__WORDSIZE / 8) +#endif + +#ifdef __UCLIBC_UNDERSCORES__ +# define __C_SYMBOL_PREFIX__ "_" +#else +# define __C_SYMBOL_PREFIX__ "" +#endif + +/* Define this if you want to modify the VALUE returned by + _dl_find_hash for this reloc TYPE. TPNT is the module in which the + matching SYM was found. */ +#ifndef DL_FIND_HASH_VALUE +# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr)) +#endif + +/* Unmap all previously-mapped segments accumulated in LOADADDR. + Generally used when an error occurs during loading. */ +#ifndef DL_LOADADDR_UNMAP +# define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + _dl_munmap((char *) (LOADADDR), (LEN)) +#endif + +/* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been + dlopen()ed successfully, when they're dlclose()d. */ +#ifndef DL_LIB_UNMAP +# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->loadaddr, (LEN))) +#endif + +/* Define this to verify that a library named LIBNAME, whose ELF + headers are pointed to by EPNT, is suitable for dynamic linking. + If it is not, print an error message (optional) and return NULL. + If the library can have its segments relocated independently, + arrange for PICLIB to be set to 2. If all segments have to be + relocated by the same amount, set it to 1. If it has to be loaded + at physical addresses as specified in the program headers, set it + to 0. A reasonable (?) guess for PICLIB will already be in place, + so it is safe to do nothing here. */ +#ifndef DL_CHECK_LIB_TYPE +# define DL_CHECK_LIB_TYPE(EPNT, PICLIB, PROGNAME, LIBNAME) (void)0 +#endif + +/* Define this if you have special segment. */ +#ifndef DL_IS_SPECIAL_SEGMENT +# define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) 0 +#endif + +/* Define this if you want to use special method to map the segment. */ +#ifndef DL_MAP_SEGMENT +# define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0 +#endif + +#endif /* _LD_DEFS_H */ diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h new file mode 100644 index 0000000..076678c --- /dev/null +++ b/ldso/include/dl-elf.h @@ -0,0 +1,199 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef LINUXELF_H +#define LINUXELF_H + +#include /* before elf.h to get ELF_USES_RELOCA right */ +#include +#include + +/* Forward declarations for stuff defined in ld_hash.h */ +struct dyn_elf; +struct elf_resolve; + +#include +#ifdef __LDSO_CACHE_SUPPORT__ +extern int _dl_map_cache(void); +extern int _dl_unmap_cache(void); +#else +static __inline__ void _dl_map_cache(void) { } +static __inline__ void _dl_unmap_cache(void) { } +#endif + + +/* Function prototypes for non-static stuff in readelflib1.c */ +extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size); +extern int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size); +extern struct elf_resolve * _dl_load_shared_library(int secure, + struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, + int trace_loaded_objects); +extern struct elf_resolve * _dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname); +extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, + int trace_loaded_objects); +extern int _dl_linux_resolve(void); +extern int _dl_fixup(struct dyn_elf *rpnt, int flag); +extern void _dl_protect_relro (struct elf_resolve *l); + +/* + * Bitsize related settings for things ElfW() + * does not handle already + */ +#if __WORDSIZE == 64 +# define ELF_ST_BIND(val) ELF64_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val) +# define ELF_R_SYM(i) ELF64_R_SYM(i) +# define ELF_R_TYPE(i) ELF64_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS64 +# endif +#else +# define ELF_ST_BIND(val) ELF32_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val) +# define ELF_R_SYM(i) ELF32_R_SYM(i) +# define ELF_R_TYPE(i) ELF32_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS32 +# endif +#endif + +/* + * Datatype of a relocation on this platform + */ +#ifdef ELF_USES_RELOCA +# define ELF_RELOC ElfW(Rela) +# define DT_RELOC_TABLE_ADDR DT_RELA +# define DT_RELOC_TABLE_SIZE DT_RELASZ +# define DT_RELOCCOUNT DT_RELACOUNT +# define UNSUPPORTED_RELOC_TYPE DT_REL +# define UNSUPPORTED_RELOC_STR "REL" +#else +# define ELF_RELOC ElfW(Rel) +# define DT_RELOC_TABLE_ADDR DT_REL +# define DT_RELOC_TABLE_SIZE DT_RELSZ +# define DT_RELOCCOUNT DT_RELCOUNT +# define UNSUPPORTED_RELOC_TYPE DT_RELA +# define UNSUPPORTED_RELOC_STR "RELA" +#endif + +/* OS and/or GNU dynamic extensions */ +#ifdef __LDSO_GNU_HASH_SUPPORT__ +# define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */ +#else +# define OS_NUM 1 /* for DT_RELOCCOUNT entry */ +#endif + +#ifndef ARCH_DYNAMIC_INFO + /* define in arch specific code, if needed */ +# define ARCH_NUM 0 +#endif + +#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM) +/* Keep ARCH specific entries into dynamic section at the end of the array */ +#define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM) + +#ifdef __LDSO_GNU_HASH_SUPPORT__ +/* GNU hash comes just after the relocation count */ +# define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1) +#endif + +extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off); + +static __always_inline +void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off) +{ + for (; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag < DT_NUM) { + dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; +#ifndef __mips__ + /* we disable for mips because normally this page is readonly + * and modifying the value here needlessly dirties a page. + * see this post for more info: + * http://uclibc.org/lists/uclibc/2006-April/015224.html */ + if (dpnt->d_tag == DT_DEBUG) + dpnt->d_un.d_val = (unsigned long)debug_addr; +#endif + if (dpnt->d_tag == DT_BIND_NOW) + dynamic_info[DT_BIND_NOW] = 1; + if (dpnt->d_tag == DT_FLAGS && + (dpnt->d_un.d_val & DF_BIND_NOW)) + dynamic_info[DT_BIND_NOW] = 1; + if (dpnt->d_tag == DT_TEXTREL) + dynamic_info[DT_TEXTREL] = 1; +#ifdef __LDSO_RUNPATH__ + if (dpnt->d_tag == DT_RUNPATH) + dynamic_info[DT_RPATH] = 0; + if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH]) + dynamic_info[DT_RPATH] = 0; +#endif + } else if (dpnt->d_tag < DT_LOPROC) { + if (dpnt->d_tag == DT_RELOCCOUNT) + dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_FLAGS_1 && + (dpnt->d_un.d_val & DF_1_NOW)) + dynamic_info[DT_BIND_NOW] = 1; +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (dpnt->d_tag == DT_GNU_HASH) + dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr; +#endif + } +#ifdef ARCH_DYNAMIC_INFO + else { + ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr); + } +#endif + } +#define ADJUST_DYN_INFO(tag, load_off) \ + do { \ + if (dynamic_info[tag]) \ + dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \ + } while (0) + ADJUST_DYN_INFO(DT_HASH, load_off); + ADJUST_DYN_INFO(DT_PLTGOT, load_off); + ADJUST_DYN_INFO(DT_STRTAB, load_off); + ADJUST_DYN_INFO(DT_SYMTAB, load_off); + ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off); + ADJUST_DYN_INFO(DT_JMPREL, load_off); +#ifdef __LDSO_GNU_HASH_SUPPORT__ + ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off); +#endif +#undef ADJUST_DYN_INFO +} + +/* Reloc type classes as returned by elf_machine_type_class(). + ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by + some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be + satisfied by any symbol in the executable. Some architectures do + not support copy relocations. In this case we define the macro to + zero so that the code for handling them gets automatically optimized + out. */ +#ifdef DL_NO_COPY_RELOCS +# define ELF_RTYPE_CLASS_COPY (0x0) +#else +# define ELF_RTYPE_CLASS_COPY (0x2) +#endif +#define ELF_RTYPE_CLASS_PLT (0x1) + +/* dlsym() calls _dl_find_hash with this value, that enables + DL_FIND_HASH_VALUE to return something different than the symbol + itself, e.g., a function descriptor. */ +#define ELF_RTYPE_CLASS_DLSYM 0x80000000 + + +/* Convert between the Linux flags for page protections and the + ones specified in the ELF standard. */ +#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \ + (((X) & PF_W) ? PROT_WRITE : 0) | \ + (((X) & PF_X) ? PROT_EXEC : 0)) + + +#endif /* LINUXELF_H */ diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h new file mode 100644 index 0000000..e7ca4ab --- /dev/null +++ b/ldso/include/dl-hash.h @@ -0,0 +1,155 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_HASH_H_ +#define _LD_HASH_H_ + +#ifndef RTLD_NEXT +#define RTLD_NEXT ((void*)-1) +#endif + +struct init_fini { + struct elf_resolve **init_fini; + unsigned long nlist; /* Number of entries in init_fini */ +}; + +struct dyn_elf { + struct elf_resolve * dyn; + struct dyn_elf * next_handle; /* Used by dlopen et al. */ + struct init_fini init_fini; + struct dyn_elf * next; + struct dyn_elf * prev; +}; + +struct elf_resolve { + /* These entries must be in this order to be compatible with the interface used + by gdb to obtain the list of symbols. */ + DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */ + char *libname; /* Absolute file name object was found in. */ + ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */ + struct elf_resolve * next; + struct elf_resolve * prev; + /* Nothing after this address is used by gdb. */ + ElfW(Addr) mapaddr; /* Address at which ELF segments (either main app and DSO) are mapped into */ + enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; + struct dyn_elf * symbol_scope; + unsigned short usage_count; + unsigned short int init_flag; + unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ + Elf_Symndx nbucket; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + /* Data needed to support GNU hash style */ + Elf32_Word l_gnu_bitmask_idxbits; + Elf32_Word l_gnu_shift; + const ElfW(Addr) *l_gnu_bitmask; + + union + { + const Elf32_Word *l_gnu_chain_zero; + const Elf_Symndx *elf_buckets; + }; +#else + Elf_Symndx *elf_buckets; +#endif + + struct init_fini_list *init_fini; + struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ + /* + * These are only used with ELF style shared libraries + */ + Elf_Symndx nchain; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + union + { + const Elf32_Word *l_gnu_buckets; + const Elf_Symndx *chains; + }; +#else + Elf_Symndx *chains; +#endif + unsigned long dynamic_info[DYNAMIC_SIZE]; + + unsigned long n_phent; + ElfW(Phdr) * ppnt; + + ElfW(Addr) relro_addr; + size_t relro_size; + + dev_t st_dev; /* device */ + ino_t st_ino; /* inode */ + +#ifdef __powerpc__ + /* this is used to store the address of relocation data words, so + * we don't have to calculate it every time, which requires a divide */ + unsigned long data_words; +#endif + +#ifdef __FDPIC__ + /* Every loaded module holds a hashtable of function descriptors of + functions defined in it, such that it's easy to release the + memory when the module is dlclose()d. */ + struct funcdesc_ht *funcdesc_ht; +#endif +}; + +#define RELOCS_DONE 0x000001 +#define JMP_RELOCS_DONE 0x000002 +#define INIT_FUNCS_CALLED 0x000004 +#define FINI_FUNCS_CALLED 0x000008 +#define DL_OPENED 0x000010 + +extern struct dyn_elf * _dl_symbol_tables; +extern struct elf_resolve * _dl_loaded_modules; +extern struct dyn_elf * _dl_handles; + +extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, + DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info, + unsigned long dynamic_addr, unsigned long dynamic_size); + +extern char * _dl_lookup_hash(const char * name, struct dyn_elf * rpnt, + struct elf_resolve *mytpnt, int type_class +#ifdef __FDPIC__ + , struct elf_resolve **tpntp +#endif + ); + +static __always_inline char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, + struct elf_resolve *mytpnt, int type_class) +{ +#ifdef __FDPIC__ + return _dl_lookup_hash(name, rpnt, mytpnt, type_class, NULL); +#else + return _dl_lookup_hash(name, rpnt, mytpnt, type_class); +#endif +} + +extern int _dl_linux_dynamic_link(void); + +extern char * _dl_library_path; +extern char * _dl_not_lazy; + +static __inline__ int _dl_symbol(char * name) +{ + if (name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') + return 0; + return 1; +} + +#define LD_ERROR_NOFILE 1 +#define LD_ERROR_NOZERO 2 +#define LD_ERROR_NOTELF 3 +#define LD_ERROR_NOTMAGIC 4 +#define LD_ERROR_NOTDYN 5 +#define LD_ERROR_MMAP_FAILED 6 +#define LD_ERROR_NODYNAMIC 7 +#define LD_WRONG_RELOCS 8 +#define LD_BAD_HANDLE 9 +#define LD_NO_SYMBOL 10 + +#endif /* _LD_HASH_H_ */ diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h new file mode 100644 index 0000000..746bd91 --- /dev/null +++ b/ldso/include/dl-string.h @@ -0,0 +1,365 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LINUX_STRING_H_ +#define _LINUX_STRING_H_ + +#include /* for do_rem */ +#include + +/* provide some sane defaults */ +#ifndef do_rem +# define do_rem(result, n, base) ((result) = (n) % (base)) +#endif +#ifndef do_div_10 +# define do_div_10(result, remain) ((result) /= 10) +#endif + +static size_t _dl_strlen(const char * str); +static char *_dl_strcat(char *dst, const char *src); +static char * _dl_strcpy(char * dst,const char *src); +static int _dl_strcmp(const char * s1,const char * s2); +static int _dl_strncmp(const char * s1,const char * s2,size_t len); +static char * _dl_strchr(const char * str,int c); +static char *_dl_strrchr(const char *str, int c); +static char *_dl_strstr(const char *s1, const char *s2); +static void * _dl_memcpy(void * dst, const void * src, size_t len); +static int _dl_memcmp(const void * s1,const void * s2,size_t len); +static void *_dl_memset(void * str,int c,size_t len); +static char *_dl_get_last_path_component(char *path); +static char *_dl_simple_ltoa(char * local, unsigned long i); +static char *_dl_simple_ltoahex(char * local, unsigned long i); + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +static __always_inline size_t _dl_strlen(const char * str) +{ + register const char *ptr = (char *) str-1; + while (*++ptr) + ;/* empty */ + return (ptr - str); +} + +static __always_inline char * _dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst-1; + + src--; + while (*++ptr) + ;/* empty */ + ptr--; + while ((*++ptr = *++src) != 0) + ;/* empty */ + return dst; +} + +static __always_inline char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + dst--;src--; + while ((*++dst = *++src) != 0) + ;/* empty */ + + return ptr; +} + +static __always_inline int _dl_strcmp(const char * s1,const char * s2) +{ + register unsigned char c1, c2; + s1--;s2--; + do { + c1 = (unsigned char) *++s1; + c2 = (unsigned char) *++s2; + if (c1 == '\0') + return c1 - c2; + } while (c1 == c2); + + return c1 - c2; +} + +static __always_inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + register unsigned char c1 = '\0'; + register unsigned char c2 = '\0'; + + s1--;s2--; + while (len > 0) { + c1 = (unsigned char) *++s1; + c2 = (unsigned char) *++s2; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + return c1 - c2; +} + +static __always_inline char * _dl_strchr(const char * str,int c) +{ + register char ch; + str--; + do { + if ((ch = *++str) == c) + return (char *) str; + } + while (ch); + + return 0; +} + +static __always_inline char * _dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str-1; + + while (*++ptr != '\0') { + if (*ptr == c) + prev = ptr; + } + if (c == '\0') + return(ptr); + return(prev); +} + +static __always_inline char * _dl_strstr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + + do { + if (!*p) + return (char *) s1;; + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) + return NULL; + s = ++s1; + } + } while (1); +} + +static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst-1; + register const char *b = src-1; + + while (len) { + *++a = *++b; + --len; + } + return dst; +} + +static __always_inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +{ + unsigned char *c1 = (unsigned char *)s1-1; + unsigned char *c2 = (unsigned char *)s2-1; + + while (len) { + if (*++c1 != *++c2) + return *c1 - *c2; + len--; + } + return 0; +} + +#if defined(powerpc) +/* Will generate smaller and faster code due to loop unrolling.*/ +static __always_inline void * _dl_memset(void *to, int c, size_t n) +{ + unsigned long chunks; + unsigned long *tmp_to; + unsigned char *tmp_char; + + chunks = n / 4; + tmp_to = to + n; + c = c << 8 | c; + c = c << 16 | c; + if (!chunks) + goto lessthan4; + do { + *--tmp_to = c; + } while (--chunks); +lessthan4: + n = n % 4; + if (!n) + return to; + tmp_char = (unsigned char *)tmp_to; + do { + *--tmp_char = c; + } while (--n); + return to; +} +#else +static __always_inline void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} +#endif + +static __always_inline char * _dl_get_last_path_component(char *path) +{ + register char *ptr = path-1; + + while (*++ptr) + ;/* empty */ + + /* strip trailing slashes */ + while (ptr != path && *--ptr == '/') { + *ptr = '\0'; + } + + /* find last component */ + while (ptr != path && *--ptr != '/') + ;/* empty */ + return ptr == path ? ptr : ptr+1; +} + +/* Early on, we can't call printf, so use this to print out + * numbers using the SEND_STDERR() macro. Avoid using mod + * or using long division */ +static __always_inline char * _dl_simple_ltoa(char * local, unsigned long i) +{ + /* 20 digits plus a null terminator should be good for + * 64-bit or smaller ints (2^64 - 1)*/ + char *p = &local[22]; + *--p = '\0'; + do { + char temp; + do_rem(temp, i, 10); + *--p = '0' + temp; + do_div_10(i, temp); + } while (i > 0); + return p; +} + +static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i) +{ + /* 16 digits plus a leading "0x" plus a null terminator, + * should be good for 64-bit or smaller ints */ + char *p = &local[22]; + *--p = '\0'; + do { + char temp = i & 0xf; + if (temp <= 0x09) + *--p = '0' + temp; + else + *--p = 'a' - 0x0a + temp; + i >>= 4; + } while (i > 0); + *--p = 'x'; + *--p = '0'; + return p; +} + + + + +/* The following macros may be used in dl-startup.c to debug + * ldso before ldso has fixed itself up to make function calls */ + +/* On some (wierd) arches, none of this stuff works at all, so + * disable the whole lot... */ +#if defined(__mips__) + +# define SEND_STDERR(X) +# define SEND_ADDRESS_STDERR(X, add_a_newline) +# define SEND_NUMBER_STDERR(X, add_a_newline) + +#else + +/* On some arches constant strings are referenced through the GOT. + * This requires that load_addr must already be defined... */ +#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \ + defined(__mips__) || defined(__sh__) || defined(__powerpc__) || \ + defined(__avr32__) || defined(__xtensa__) +# define CONSTANT_STRING_GOT_FIXUP(X) \ + if ((X) < (const char *) load_addr) (X) += load_addr +# define NO_EARLY_SEND_STDERR +#else +# define CONSTANT_STRING_GOT_FIXUP(X) +#endif + +#define SEND_STDERR(X) \ +{ \ + const char *tmp1 = (X); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ +} + +#define SEND_ADDRESS_STDERR(ADR, add_a_newline) \ +{ \ + char tmp[26], v, *tmp2, *tmp1 = tmp; \ + unsigned long X = (unsigned long)(ADR); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + tmp2 = tmp1 + sizeof(tmp); \ + *--tmp2 = '\0'; \ + if (add_a_newline) *--tmp2 = '\n'; \ + do { \ + v = (X) & 0xf; \ + if (v <= 0x09) \ + *--tmp2 = '0' + v; \ + else \ + *--tmp2 = 'a' - 0x0a + v; \ + (X) >>= 4; \ + } while ((X) > 0); \ + *--tmp2 = 'x'; \ + *--tmp2 = '0'; \ + _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ +} + +#define SEND_NUMBER_STDERR(NUM, add_a_newline) \ +{ \ + char tmp[26], v, *tmp2, *tmp1 = tmp; \ + unsigned long X = (unsigned long)(NUM); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + tmp2 = tmp1 + sizeof(tmp); \ + *--tmp2 = '\0'; \ + if (add_a_newline) *--tmp2 = '\n'; \ + do { \ + do_rem(v, (X), 10); \ + *--tmp2 = '0' + v; \ + do_div_10((X), v); \ + } while ((X) > 0); \ + _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ +} +#endif + +/* Some targets may have to override this to something that doesn't + * reference constant strings through the GOT. This macro should be + * preferred over SEND_STDERR for constant strings before we complete + * bootstrap. + */ +#ifndef SEND_EARLY_STDERR +# define SEND_EARLY_STDERR(S) SEND_STDERR(S) +#else +# define EARLY_STDERR_SPECIAL +#endif + +#ifdef __SUPPORT_LD_DEBUG_EARLY__ +# define SEND_STDERR_DEBUG(X) SEND_STDERR(X) +# define SEND_EARLY_STDERR_DEBUG(X) SEND_EARLY_STDERR(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) SEND_NUMBER_STDERR(X, add_a_newline) +# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) SEND_ADDRESS_STDERR(X, add_a_newline) +#else +# define SEND_STDERR_DEBUG(X) +# define SEND_EARLY_STDERR_DEBUG(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) +# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) +#endif + +#endif diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h new file mode 100644 index 0000000..1cbbbad --- /dev/null +++ b/ldso/include/dl-syscall.h @@ -0,0 +1,203 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_SYSCALL_H_ +#define _LD_SYSCALL_H_ + +/* Pull in the arch specific syscall implementation */ +#include +/* For MAP_ANONYMOUS -- differs between platforms */ +#define _SYS_MMAN_H 1 +#include +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#if defined(__sparc_v9__) && (__WORDSIZE == 64) +#define kernel_stat64 stat +#else +#define kernel_stat stat +#endif +#include +#include + +/* _dl_open() parameters */ +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 + +/* Encoding of the file mode. */ +#define S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define S_IFDIR 0040000 /* Directory. */ +#define S_IFCHR 0020000 /* Character device. */ +#define S_IFBLK 0060000 /* Block device. */ +#define S_IFREG 0100000 /* Regular file. */ +#define S_IFIFO 0010000 /* FIFO. */ +#define S_IFLNK 0120000 /* Symbolic link. */ +#define S_IFSOCK 0140000 /* Socket. */ + +/* Protection bits. */ +#define S_ISUID 04000 /* Set user ID on execution. */ +#define S_ISGID 02000 /* Set group ID on execution. */ +#define S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define S_IREAD 0400 /* Read by owner. */ +#define S_IWRITE 0200 /* Write by owner. */ +#define S_IEXEC 0100 /* Execute by owner. */ + + + +/* Here are the definitions for some syscalls that are used + by the dynamic linker. The idea is that we want to be able + to call these before the errno symbol is dynamicly linked, so + we use our own version here. Note that we cannot assume any + dynamic linking at all, so we cannot return any error codes. + We just punt if there is an error. */ +#define __NR__dl_exit __NR_exit +static __always_inline _syscall1(void, _dl_exit, int, status); + +#define __NR__dl_close __NR_close +static __always_inline _syscall1(int, _dl_close, int, fd); + +#define __NR__dl_open __NR_open +static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags, + __kernel_mode_t, mode); + +#define __NR__dl_write __NR_write +static __always_inline _syscall3(unsigned long, _dl_write, int, fd, + const void *, buf, unsigned long, count); + +#define __NR__dl_read __NR_read +static __always_inline _syscall3(unsigned long, _dl_read, int, fd, + const void *, buf, unsigned long, count); + +#define __NR__dl_mprotect __NR_mprotect +static __always_inline _syscall3(int, _dl_mprotect, const void *, addr, + unsigned long, len, int, prot); + +#define __NR__dl_stat __NR_stat +static __always_inline _syscall2(int, _dl_stat, const char *, file_name, + struct stat *, buf); + +#define __NR__dl_fstat __NR_fstat +static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf); + +#define __NR__dl_munmap __NR_munmap +static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length); + +#ifdef __NR_getxuid +# define __NR_getuid __NR_getxuid +#endif +#define __NR__dl_getuid __NR_getuid +static __always_inline _syscall0(uid_t, _dl_getuid); + +#ifndef __NR_geteuid +# define __NR_geteuid __NR_getuid +#endif +#define __NR__dl_geteuid __NR_geteuid +static __always_inline _syscall0(uid_t, _dl_geteuid); + +#ifdef __NR_getxgid +# define __NR_getgid __NR_getxgid +#endif +#define __NR__dl_getgid __NR_getgid +static __always_inline _syscall0(gid_t, _dl_getgid); + +#ifndef __NR_getegid +# define __NR_getegid __NR_getgid +#endif +#define __NR__dl_getegid __NR_getegid +static __always_inline _syscall0(gid_t, _dl_getegid); + +#ifdef __NR_getxpid +# define __NR_getpid __NR_getxpid +#endif +#define __NR__dl_getpid __NR_getpid +static __always_inline _syscall0(gid_t, _dl_getpid); + +#define __NR__dl_readlink __NR_readlink +static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, + size_t, bufsiz); + +#ifdef __UCLIBC_HAS_SSP__ +# include +# define __NR__dl_gettimeofday __NR_gettimeofday +static __always_inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv, +# ifdef __USE_BSD + struct timezone *, tz); +# else + void *, tz); +# endif +#endif + + +/* handle all the fun mmap intricacies */ +#if (defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap)) || !defined(__NR_mmap2) +# define _dl_MAX_ERRNO 4096 +# define _dl_mmap_check_error(__res) \ + (((long)__res) < 0 && ((long)__res) >= -_dl_MAX_ERRNO) +#else +# define MAP_FAILED ((void *) -1) +# define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) +#endif + +/* first try mmap(), syscall6() style */ +#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap) + +# define __NR__dl_mmap __NR_mmap +static __always_inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset); + +/* then try mmap2() */ +#elif defined(__NR_mmap2) + +# define __NR___syscall_mmap2 __NR_mmap2 +static __always_inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, off_t, offset); + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +#ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +#endif + +static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) + return MAP_FAILED; + return __syscall_mmap2(addr, size, prot, flags, + fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)); +} + +/* finally, fall back to mmap(), syscall1() style */ +#elif defined(__NR_mmap) + +# define __NR__dl_mmap_real __NR_mmap +static __always_inline _syscall1(void *, _dl_mmap_real, unsigned long *, buffer); +static __always_inline void * _dl_mmap(void * addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) size; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (void *) _dl_mmap_real(buffer); +} + +#else +# error "Your architecture doesn't seem to provide mmap() !?" +#endif + +#endif /* _LD_SYSCALL_H_ */ diff --git a/ldso/include/dlfcn.h b/ldso/include/dlfcn.h new file mode 100644 index 0000000..03afd34 --- /dev/null +++ b/ldso/include/dlfcn.h @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +/* User functions for run-time dynamic loading. libdl version */ +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include +#include + +#define RTLD_NEXT ((void *) -1l) +#define RTLD_DEFAULT ((void *) 0) + +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + +#endif /* _DLFCN_H */ diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h new file mode 100644 index 0000000..35a72fc --- /dev/null +++ b/ldso/include/ldso.h @@ -0,0 +1,124 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LDSO_H_ +#define _LDSO_H_ + +#include + +/* Prepare for the case that `__builtin_expect' is not available. */ +#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 +#define __builtin_expect(x, expected_value) (x) +#endif +#ifndef likely +# define likely(x) __builtin_expect((!!(x)),1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect((!!(x)),0) +#endif +#ifndef __LINUX_COMPILER_H +#define __LINUX_COMPILER_H +#endif + +/* Pull in compiler and arch stuff */ +#include +#include +#include +/* Pull in the arch specific type information */ +#include +/* Pull in the arch specific page size */ +#include +/* Pull in the ldso syscalls and string functions */ +#include +#include +/* Now the ldso specific headers */ +#include +#include + +/* For INIT/FINI dependency sorting. */ +struct init_fini_list { + struct init_fini_list *next; + struct elf_resolve *tpnt; +}; + +/* Global variables used within the shared library loader */ +extern char *_dl_library_path; /* Where we look for libraries */ +extern char *_dl_preload; /* Things to be loaded before the libs */ +extern char *_dl_ldsopath; /* Where the shared lib loader was found */ +extern const char *_dl_progname; /* The name of the executable being run */ +extern int _dl_secure; /* Are we dealing with setuid stuff? */ +extern size_t _dl_pagesize; /* Store the page size for use later */ + +#ifdef __SUPPORT_LD_DEBUG__ +extern char *_dl_debug; +extern char *_dl_debug_symbols; +extern char *_dl_debug_move; +extern char *_dl_debug_reloc; +extern char *_dl_debug_detail; +extern char *_dl_debug_nofixups; +extern char *_dl_debug_bindings; +extern int _dl_debug_file; +# define __dl_debug_dprint(fmt, args...) \ + _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __FUNCTION__, __LINE__, ## args); +# define _dl_if_debug_dprint(fmt, args...) \ + do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0) +#else +# define __dl_debug_dprint(fmt, args...) do {} while (0) +# define _dl_if_debug_dprint(fmt, args...) do {} while (0) +# define _dl_debug_file 2 +#endif /* __SUPPORT_LD_DEBUG__ */ + +#ifdef IS_IN_rtld +# ifdef __SUPPORT_LD_DEBUG__ +# define _dl_assert(expr) \ + do { \ + if (!(expr)) { \ + __dl_debug_dprint("assert(%s)\n", #expr); \ + _dl_exit(45); \ + } \ + } while (0) +# else +# define _dl_assert(expr) ((void)0) +# endif +#else +# include +# define _dl_assert(expr) assert(expr) +#endif + +#ifdef __SUPPORT_LD_DEBUG_EARLY__ +# define _dl_debug_early(fmt, args...) __dl_debug_dprint(fmt, ## args) +#else +# define _dl_debug_early(fmt, args...) do {} while (0) +#endif /* __SUPPORT_LD_DEBUG_EARLY__ */ + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +extern void *_dl_malloc(size_t size); +extern void _dl_free(void *); +extern char *_dl_getenv(const char *symbol, char **envp); +extern void _dl_unsetenv(const char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern void _dl_dprintf(int, const char *, ...); + +#ifndef DL_GET_READY_TO_RUN_EXTRA_PARMS +# define DL_GET_READY_TO_RUN_EXTRA_PARMS +#endif +#ifndef DL_GET_READY_TO_RUN_EXTRA_ARGS +# define DL_GET_READY_TO_RUN_EXTRA_ARGS +#endif + +extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, + ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv + DL_GET_READY_TO_RUN_EXTRA_PARMS); + +#ifdef HAVE_DL_INLINES_H +#include +#endif + +#endif /* _LDSO_H_ */ diff --git a/ldso/include/unsecvars.h b/ldso/include/unsecvars.h new file mode 100644 index 0000000..f1ef381 --- /dev/null +++ b/ldso/include/unsecvars.h @@ -0,0 +1,32 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +/* + * Environment variable to be removed for SUID programs. The names are all + * stuffed in a single string which means they have to be terminated with a + * '\0' explicitly. + */ + +#define UNSECURE_ENVVARS \ + "LD_PRELOAD\0" \ + "LD_LIBRARY_PATH\0" \ + "LD_DEBUG\0" \ + "LD_DEBUG_OUTPUT\0" \ + "LD_TRACE_LOADED_OBJECTS\0" \ + "TMPDIR\0" + +/* + * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h + * though used by ldd + * + * These environment variables are defined by glibc but ignored in + * uClibc, but may very well have an equivalent in uClibc. + * + * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV, + * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE, + * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR + */ diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/ldso/ldso/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in new file mode 100644 index 0000000..b8af95f --- /dev/null +++ b/ldso/ldso/Makefile.in @@ -0,0 +1,61 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-ldso := -DNOT_IN_libc -DIS_IN_rtld $(SSP_DISABLE_FLAGS) + +# This stuff will not work with -fomit-frame-pointer +CFLAGS-ldso += -fno-omit-frame-pointer + +CFLAGS-ldso += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso +CFLAGS-ldso += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" + +CFLAGS-ldso/ldso/$(TARGET_ARCH)/ := $(CFLAGS-ldso) + +CFLAGS-ldso.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" $(CFLAGS-ldso) + +ifneq ($(SUPPORT_LD_DEBUG),y) +LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS) +else +LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +endif +LDFLAGS-$(UCLIBC_LDSO_NAME).so += -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic -Wl,--sort-common -Wl,--discard-locals -Wl,--discard-all -Wl,--no-undefined + +ldso_FULL_NAME := $(UCLIBC_LDSO_NAME)-$(VERSION).so + +$(UCLIBC_LDSO_NAME)_DIR := $(top_srcdir)ldso/ldso +$(UCLIBC_LDSO_NAME)_OUT := $(top_builddir)ldso/ldso + +$(UCLIBC_LDSO_NAME)_CSRC := $($(UCLIBC_LDSO_NAME)_DIR)/ldso.c +# prerequesites +$($(UCLIBC_LDSO_NAME)_OUT)/ldso.o $($(UCLIBC_LDSO_NAME)_OUT)/ldso.oS: \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-debug.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-startup.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-array.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-hash.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-elf.c +$(UCLIBC_LDSO_NAME)_COBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/%.c,$($(UCLIBC_LDSO_NAME)_OUT)/%.o,$($(UCLIBC_LDSO_NAME)_CSRC)) + +$(UCLIBC_LDSO_NAME)_SSRC := $(wildcard $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/*.S) +$(UCLIBC_LDSO_NAME)_SOBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/%.S,$($(UCLIBC_LDSO_NAME)_OUT)/$(TARGET_ARCH)/%.o,$($(UCLIBC_LDSO_NAME)_SSRC)) + +$(UCLIBC_LDSO_NAME)_OBJS := $($(UCLIBC_LDSO_NAME)_COBJ) $($(UCLIBC_LDSO_NAME)_SOBJ) + +ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS) + +lib-so-y += $(ldso) +objclean-y += $(UCLIBC_LDSO_NAME)_clean + +$(ldso): $(ldso:.$(MAJOR_VERSION)=) +$(ldso:.$(MAJOR_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a + $(call link.so,$(ldso_FULL_NAME),$(MAJOR_VERSION)) + +$($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y) + $(Q)$(RM) $@ + $(do_ar) + +$(UCLIBC_LDSO_NAME)_clean: + $(do_rm) $(addprefix $($(UCLIBC_LDSO_NAME)_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*.,$(d)$(e)))) diff --git a/ldso/ldso/arm/dl-debug.h b/ldso/ldso/arm/dl-debug.h new file mode 100644 index 0000000..d510320 --- /dev/null +++ b/ldso/ldso/arm/dl-debug.h @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* ARM ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32", + [4] "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5", + [8] "R_ARM_ABS8", "R_ARM_SBREL32","R_ARM_THM_PC22", "R_ARM_THM_PC8", + [12] "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25", + [16] "R_ARM_THM_XPC22", + [20] "R_ARM_COPY", "R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT", "R_ARM_RELATIVE", + [24] "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32", "R_ARM_PLT32", + [32] "R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0", + [36] "R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20", + [100] "R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9", + [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32", + [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE", +}; diff --git a/ldso/ldso/arm/dl-startup.h b/ldso/ldso/arm/dl-startup.h new file mode 100644 index 0000000..73edbff --- /dev/null +++ b/ldso/ldso/arm/dl-startup.h @@ -0,0 +1,194 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if !defined(__thumb__) +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr sl, .L_GET_GOT\n" + " add sl, pc, sl\n" + ".L_GOT_GOT:\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [sl, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " add sp, sp, r4, lsl #2\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " add r3, r2, r1, lsl #2\n" + " add r3, r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [sl, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#else +__asm__( + " .text\n" + " .arm\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ dumb: can't persuade the linker to make the start address\n" + " @ odd, so use an arm function and change to thumb (_dl_start\n" + " @ is thumb)\n" + " adr r0, __dl_thumb_start+1\n" + " bx r0\n" + "\n\n" + " .thumb\n" + " .globl __dl_thumb_start\n" + " .thumb_func\n" + " .type __dl_thumb_start,%function\n" + "__dl_thumb_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr r7, .L_GET_GOT\n" + ".L_GOT_GOT:\n" + " add r7, pc\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [r7, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " lsl r4, r4, #2\n" + " add sp, r4\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " lsl r3, r1, #2\n" + " add r3, r3, r2\n" + " add r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [r7, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + "\n\n" + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#endif + + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *reloc_addr += symbol_addr; + break; + case R_ARM_PC24: + { + unsigned long addend; + long newvalue, topbits; + + addend = *reloc_addr & 0x00ffffff; + if (addend & 0x00800000) addend |= 0xff000000; + + newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (topbits != 0xfe000000 && topbits != 0x00000000) + { +#if 0 + /* Don't bother with this during ldso initilization... */ + newvalue = fix_bad_pc24(reloc_addr, symbol_addr) + - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000)) + { + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); + } +#else + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); +#endif + } + newvalue >>= 2; + symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); + *reloc_addr = symbol_addr; + break; + } + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARM_RELATIVE: + *reloc_addr += load_addr; + break; + case R_ARM_COPY: + break; + default: + SEND_STDERR("Unsupported relocation type\n"); + _dl_exit(1); + } +} diff --git a/ldso/ldso/arm/dl-syscalls.h b/ldso/ldso/arm/dl-syscalls.h new file mode 100644 index 0000000..1c0e669 --- /dev/null +++ b/ldso/ldso/arm/dl-syscalls.h @@ -0,0 +1,42 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +/* _call_via_rX calls are used in thumb ldso because of calls via + * function pointers, but ldso is not linked with anything which + * provides them, so define them here (only required for thumb). + */ +#if defined(__thumb__) +__asm__( + ".macro call_via register\n" + " .global _call_via_\\register\n" + " .hidden _call_via_\\register\n" + " .type _call_via_\\register, %function\n" + " .thumb_func\n" + "_call_via_\\register:\n" + " bx \\register\n" + " .size _call_via_\\register, . - _call_via_\\register\n" + ".endm\n" + + ".text\n" + ".thumb\n" + ".align 1\n" + " call_via r0\n" + " call_via r1\n" + " call_via r2\n" + " call_via r3\n" + " call_via r4\n" + " call_via r5\n" + " call_via r6\n" + " call_via r7\n" + " call_via r8\n" + " call_via r9\n" + " call_via r10\n" + " call_via r11\n" + " call_via r12\n" + " call_via r13\n" + " call_via r14\n" +); +#endif diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h new file mode 100644 index 0000000..c3fc4e5 --- /dev/null +++ b/ldso/ldso/arm/dl-sysdep.h @@ -0,0 +1,146 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +static __inline__ unsigned long arm_modulus(unsigned long m, unsigned long p) +{ + unsigned long i,t,inc; + i=p; t=0; + while (!(i&(1<<31))) { + i<<=1; + t++; + } + t--; + for (inc=t;inc>2;inc--) { + i=p<=i) { + m-=i; + i<<=1; + if (i&(1<<31)) + break; + if (i=p) { + m-=p; + } + return m; +} +#define do_rem(result, n, base) ((result) = arm_modulus(n, base)) +#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_ARM +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "ARM" + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. We used to use the PIC register to do this + without a constant pool reference, but GCC 4.2 will use a pseudo-register + for the PIC base, so it may not be in r10. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf32_Addr dynamic; +#if !defined __thumb__ + __asm__ ("ldr %0, 2f\n" + "1: ldr %0, [pc, %0]\n" + "b 3f\n" + "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" + "3:" : "=r" (dynamic)); +#else + int tmp; + __asm__ (".align 2\n" + "bx pc\n" + "nop\n" + ".arm\n" + "ldr %0, 2f\n" + "1: ldr %0, [pc, %0]\n" + "b 3f\n" + "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" + "3:" + ".align 2\n" + "orr %1, pc, #1\n" + "bx %1\n" + ".force_thumb\n" + : "=r" (dynamic), "=&r" (tmp)); +#endif + + return dynamic; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + extern void __dl_start __asm__ ("_dl_start"); + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; +#if defined __OPTIMIZE__ && !defined __thumb__ + __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr)); +#else + /* A simple adr does not work in Thumb mode because the offset is + negative, and for debug builds may be too large. */ + int tmp; + __asm__ ("adr %1, 1f\n\t" + "ldr %0, [%1]\n\t" + "add %0, %0, %1\n\t" + "b 2f\n\t" + ".align 2\n\t" + "1: .word _dl_start - 1b\n\t" + "2:" + : "=r" (pcrel_addr), "=r" (tmp)); +#endif + return pcrel_addr - got_addr; +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr += load_off; + } while (--relative_count); +} + +#ifdef __ARM_EABI__ +#define DL_MALLOC_ALIGN 8 /* EABI needs 8 byte alignment for STRD LDRD */ +#endif diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c new file mode 100644 index 0000000..3753112 --- /dev/null +++ b/ldso/ldso/arm/elfinterp.c @@ -0,0 +1,333 @@ +/* vi: set sw=4 ts=4: */ +/* ARM ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + char *symname; + Elf32_Sym *symtab; + ELF_RELOC *rel_addr; + int symtab_index; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + + rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = rel_addr + reloc_entry; + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_ARM_JUMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of jump instruction to fix up */ + instr_addr = ((unsigned long) this_reloc->r_offset + + (unsigned long) tpnt->loadaddr); + got_addr = (char **) instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, + tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } +#if defined (__SUPPORT_LD_DEBUG__) +#if !defined __SUPPORT_LD_DEBUG_EARLY__ + if ((unsigned long) got_addr < 0x40000000) +#endif + { + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + int i; + char *strtab; + int goof = 0; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res <0)) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + if (unlikely(res >0)) + { + _dl_dprintf(2, "can't resolve symbol\n"); + goof += res; + } + } + return goof; +} + +#if 0 +static unsigned long +fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value) +{ + static void *fix_page; + static unsigned int fix_offset; + unsigned int *fix_address; + if (! fix_page) + { + fix_page = _dl_mmap (NULL, PAGE_SIZE , PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fix_offset = 0; + } + + fix_address = (unsigned int *)(fix_page + fix_offset); + fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */ + fix_address[1] = value; + + fix_offset += 8; + if (fix_offset >= PAGE_SIZE) + fix_page = NULL; + + return (unsigned long)fix_address; +} +#endif + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + unsigned long *reloc_addr; + unsigned long symbol_addr; + int goof = 0; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + + if (symtab_index) { + + symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, + scope, tpnt, elf_machine_type_class(reloc_type)); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *reloc_addr += symbol_addr; + break; + case R_ARM_PC24: +#if 0 + { + unsigned long addend; + long newvalue, topbits; + + addend = *reloc_addr & 0x00ffffff; + if (addend & 0x00800000) addend |= 0xff000000; + + newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (topbits != 0xfe000000 && topbits != 0x00000000) + { + newvalue = fix_bad_pc24(reloc_addr, symbol_addr) + - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000)) + { + _dl_dprintf(2,"symbol '%s': R_ARM_PC24 relocation out of range.", + symtab[symtab_index].st_name); + _dl_exit(1); + } + } + newvalue >>= 2; + symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); + *reloc_addr = symbol_addr; + break; + } +#else + _dl_dprintf(2,"R_ARM_PC24: Compile shared libraries with -fPIC!\n"); + _dl_exit(1); +#endif + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARM_RELATIVE: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + case R_ARM_COPY: + _dl_memcpy((void *) reloc_addr, + (void *) symbol_addr, symtab[symtab_index].st_size); + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + + return goof; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_ARM_NONE: + break; + case R_ARM_JUMP_SLOT: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + return 0; + +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + diff --git a/ldso/ldso/arm/resolve.S b/ldso/ldso/arm/resolve.S new file mode 100644 index 0000000..b422c33 --- /dev/null +++ b/ldso/ldso/arm/resolve.S @@ -0,0 +1,169 @@ +/* + * + * add ip, pc, #0xNN00000 + * add ip, ip, #0xNN000 + * ldr pc, [ip, #0xNNN]! + * + * So that, effectively, causes the following to happen: + * + * ip : = pc+0x0NNNNNNN + * pc : = *ip + * + * For thumb the above fragment is preceded by "bx pc, nop" to switch to ARM + * mode and the thumb 'bl' must go to PLT-4 - the PLT entry is expanded by + * four bytes to accomodate the trampoline code. + * + * 0x0NNNNNNN is the offset of the GOT entry for this function relative to + * the PLT entry for this function (where the code is). So the code in the + * PLT causes a branch to whatever is in the GOT, leaving the actual address + * of the GOT entry in ip. (Note that the GOT must follow the PLT - the + * added value is 28 bit unsigned). + * + * ip is a pointer to the GOT entry for this function, the first time round + * *ip points to this code: + * + * str lr, [sp, #-4]! @ save lr + * ldr lr, [pc, #4] @ lr : = *dat (&GOT_TABLE[0]-.) + * add lr, pc, lr @ lr += &dat (so lr == &GOT_TABLE[0]) + * ldr pc, [lr, #8]! @ pc : = GOT_TABLE[2] + *dat: *.long &GOT_TABLE[0] - . + * + * (this code is actually held in the first entry of the PLT). The code + * preserves lr then uses it as a scratch register (this preserves the ip + * value calculated above). GOT_TABLE[2] is initialized by INIT_GOT in + * dl-sysdep.h to point to _dl_linux_resolve - this function. The first + * three entries in the GOT are reserved, then they are followed by the + * entries for the PLT entries, in order. + * + * The linker initialises the following (non-reserved) GOT entries to + * the offset of the PLT with an associated relocation so that on load + * the entry is relocated to point to the PLT - the above code. + * + * The net effect of all this is that on the first call to an external (as + * yet unresolved) function all seven of the above instructions are + * executed in sequence and the program ends up executing _dl_linux_resolve + * with the following important values in registers: + * + * ip - a pointer to the GOT entry for the as yet unresolved function + * lr - &GOT_TABLE[2] + * + * GOT_TABLE[2] has already been initialised to _dl_linux_resolve, and + * GOT_TABLE[1] is a pointer to the (elf_resolve*) from INIT_GOT. + * _dl_linux_resolve unfrobnicates the ip and lr values to obtain arguments + * for a call to _dl_linux_resolver (not the additional 'r' on the end) - + * this is in elfinterp.c in this directory. The call takes arguments: + * + * _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) + * + * And returns the address of the function, it also overwrites the GOT + * table entry so that the next time round only the first code fragment will + * be executed - it will call the function directly. + * + * [[Of course, this simply doesn't work on ARM 4T with a thumb target - because + * 4T did not do the thumb/arm change on ldr pc! It can be made to work by + * changing _dl_linux_resolver to return __%s_from_arm for an STT_TFUNC, but + * this hasn't been done, and there is no guarantee that the linker generated + * that glue anyway.]] + * + * _dl_linux_resolve gets the arguments to call the resolver as follows: + * + * tpnt *GOT_TABLE[1], [lr-4] + * reloc-entry &GOT-&GOT_TABLE[3], (ip - lr - 4)/4 + * + * (I.e. 'GOT' means the table entry for this function, the thing for which + * ip holds the address.) The reloc-entry is passed as an index, since + * since the GOT table has 4 byte entries the code needs to divide this by 4 + * to get the actual index. + * + * John Bowler, August 13, 2005 - determined by experiment and examination + * of generated ARM code (there was no documentation...) + * + * This code is all ARM code - not thumb - _dl_linux_resolver may, itself, + * be thumb, in which case the linker will insert the appropriate glue. A + * call from thumb to the PLT hits the trampoline code described above. + * This code (now) builds a proper stack frame. + * + * The code does *not* set sb (r9,v6) - to do that the basic PLT instructions + * would need to save sb and load the new value and that would require + * support in the linker since it generates those instructions. (Also note + * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see + * dl-startup.c). + */ + +#include +#include + +#include + + .text + .align 4 @ 16 byte boundary and there are 32 bytes below (arm case) + #if !defined(__thumb__) || defined(__thumb2__) + .arm + .globl _dl_linux_resolve + .type _dl_linux_resolve,%function + .align 4; + +_dl_linux_resolve: + @ _dl_linux_resolver is a standard subroutine call, therefore it + @ preserves everything except r0-r3 (a1-a4), ip and lr. This + @ function must branch to the real function, and that expects + @ r0-r3 and lr to be as they were before the whole PLT stuff - + @ ip can be trashed. + @ This routine is called after pushing lr, so we must push an odd + @ number of words to keep the stack correctly aligned. + + stmdb sp!, {r0, r1, r2, r3, r4} + ldr r0, [lr, #-4] @ r0 : = [lr-4] (GOT_TABLE[1]) + sub r1, lr, ip @ r1 : = (lr-ip) (a multple of 4) + mvn r1, r1, ASR #2 @ r1 : = ~((lr-ip)>>2), since -x = (1+~x) + @ ~x = -x-1, therefore ~(r1>>2) = (-((lr-ip)>>2)-1) + @ = - ((lr-ip)/4) - 1 = (ip - lr - 4)/4, as required + + bl _dl_linux_resolver + + mov ip, r0 + ldmia sp!, {r0, r1, r2, r3, r4, lr} + +#if defined(__USE_BX__) + bx ip +#else + mov pc,ip +#endif +#else + @ In the thumb case _dl_linux_resolver is thumb. If a bl is used + @ from arm code the linker will insert a stub call which, with + @ binutils 2.16, is not PIC. Since this code is accessed by an + @ ldr pc the reasonable fix is to make _dl_linux_resolve thumb too. + .thumb + .globl _dl_linux_resolve + .thumb_func + .type _dl_linux_resolve,%function + _dl_linux_resolve: + @ _dl_linux_resolver is a standard subroutine call, therefore it + @ preserves everything except r0-r3 (a1-a4), ip and lr. This + @ function must branch to the real function, and that expects + @ r0-r3 and lr to be as they were before the whole PLT stuff - + @ ip can be trashed. + @ This routine is called after pushing lr, so we must push an odd + @ number of words to keep the stack correctly aligned. + push {r0-r4} + mov r1, lr @ &GOT_TABLE[2] + sub r0, r1, #4 + mov r2, ip @ &GOT[n] + ldr r0, [r0] @ r0 := GOT_TABLE[1] + @ for the function call r1 := n-3 + sub r1, r2 + asr r1, r1, #2 + mvn r1, r1 @ exactly as in the arm code above + bl _dl_linux_resolver + @ r0 contains the branch address, the return address is above + @ the saved r0..r3 + mov ip, r0 + ldr r1, [sp, #20] + mov lr, r1 + pop {r0-r4} + add sp, #4 + bx ip + +#endif +.size _dl_linux_resolve, .-_dl_linux_resolve diff --git a/ldso/ldso/avr32/dl-debug.h b/ldso/ldso/avr32/dl-debug.h new file mode 100644 index 0000000..fe35539 --- /dev/null +++ b/ldso/ldso/avr32/dl-debug.h @@ -0,0 +1,45 @@ +/* + * AVR32 ELF shared libary loader support + * + * Copyright (C) 2005-2007 Atmel Corporation + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + "R_AVR32_NONE", + "R_AVR32_32", "R_AVR32_16", "R_AVR32_8", + "R_AVR32_32_PCREL", "R_AVR32_16_PCREL", "R_AVR32_8_PCREL", + "R_AVR32_DIFF32", "R_AVR32_DIFF16", "R_AVR32_DIFF8", + "R_AVR32_GOT32", "R_AVR32_GOT16", "R_AVR32_GOT8", + "R_AVR32_21S", "R_AVR32_16U", "R_AVR32_16S", "R_AVR32_8S", "R_AVR32_8S_EXT", + "R_AVR32_22H_PCREL", "R_AVR32_18W_PCREL", "R_AVR32_16B_PCREL", + "R_AVR32_16N_PCREL", "R_AVR32_14UW_PCREL", "R_AVR32_11H_PCREL", + "R_AVR32_10UW_PCREL", "R_AVR32_9H_PCREL", "R_AVR32_9UW_PCREL", + "R_AVR32_HI16", "R_AVR32_LO16", + "R_AVR32_GOTPC", "R_AVR32_GOTCALL", "R_AVR32_LDA_GOT", + "R_AVR32_GOT21S", "R_AVR32_GOT18SW", "R_AVR32_GOT16S", "R_AVR32_GOT7UW", + "R_AVR32_32_CPENT", "R_AVR32_CPCALL", "R_AVR32_16_CP", "R_AVR32_9W_CP", + "R_AVR32_RELATIVE", "R_AVR32_GLOB_DAT", "R_AVR32_JMP_SLOT", + "R_AVR32_ALIGN", +}; diff --git a/ldso/ldso/avr32/dl-startup.h b/ldso/ldso/avr32/dl-startup.h new file mode 100644 index 0000000..3b8bf4c --- /dev/null +++ b/ldso/ldso/avr32/dl-startup.h @@ -0,0 +1,112 @@ +/* + * Architecture specific code used by dl-startup.c + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* This is the library loader's main entry point. Let _dl_boot2 do its + * initializations and jump to the application's entry point + * afterwards. */ +__asm__(" .text\n" + " .global _start\n" + " .type _start,@function\n" + "_start:\n" + /* All arguments are on the stack initially */ + " mov r12, sp\n" + " rcall _dl_start\n" + /* Returns user entry point in r12. Save it. */ + " mov r0, r12\n" + /* We're PIC, so get the Global Offset Table */ + " lddpc r6, .L_GOT\n" + ".L_RGOT:\n" + " rsub r6, pc\n" + /* Adjust argc and argv according to _dl_skip_args */ + " ld.w r1, r6[_dl_skip_args@got]\n" + " ld.w r1, r1[0]\n" + " ld.w r2, sp++\n" + " sub r2, r1\n" + " add sp, sp, r1 << 2\n" + " st.w --sp, r2\n" + /* Load the finalizer function */ + " ld.w r12, r6[_dl_fini@got]\n" + /* Jump to the user's entry point */ + " mov pc, r0\n\n" + + " .align 2\n" + ".L_GOT:" + " .long .L_RGOT - _GLOBAL_OFFSET_TABLE_\n" + " .size _start, . - _start\n" + " .previous\n"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1) + + +/* We can't call functions before the GOT has been initialized */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +/* + * Relocate the GOT during dynamic loader bootstrap. This will add + * the load address to all entries in the GOT, which is necessary + * because the linker doesn't generate R_AVR32_RELATIVE relocs for the + * GOT. + */ +static __always_inline +void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt) +{ + Elf32_Addr i, nr_got; + register Elf32_Addr *__r6 __asm__("r6"); + Elf32_Addr *got = __r6; + + nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got); + for (i = 2; i < nr_got; i++) + got[i] += tpnt->loadaddr; +} + +#define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, + unsigned long load_addr, Elf32_Sym *symtab) +{ + switch(ELF32_R_TYPE(rpnt->r_info)) { + case R_AVR32_NONE: + break; + case R_AVR32_GLOB_DAT: + case R_AVR32_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_AVR32_RELATIVE: + SEND_STDERR_DEBUG("Applying RELATIVE relocation: "); + SEND_ADDRESS_STDERR_DEBUG(load_addr, 0); + SEND_STDERR_DEBUG(" + "); + SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1); + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type "); + SEND_NUMBER_STDERR(ELF32_R_TYPE(rpnt->r_info), 1); + SEND_STDERR("REL, SYMBOL, LOAD: "); + SEND_ADDRESS_STDERR(reloc_addr, 0); + SEND_STDERR(", "); + SEND_ADDRESS_STDERR(symbol_addr, 0); + SEND_STDERR(", "); + SEND_ADDRESS_STDERR(load_addr, 1); + _dl_exit(1); + } +} + +/* Transfer control to the user's application, once the dynamic loader + * is done. This routine has to exit the current function, then call + * the _dl_elf_main function. + * + * Since our _dl_boot will simply call whatever is returned by + * _dl_boot2, we can just return the address we're supposed to + * call. */ +#define START() return _dl_elf_main; diff --git a/ldso/ldso/avr32/dl-syscalls.h b/ldso/ldso/avr32/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/avr32/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/avr32/dl-sysdep.h b/ldso/ldso/avr32/dl-sysdep.h new file mode 100644 index 0000000..6696382 --- /dev/null +++ b/ldso/ldso/avr32/dl-sysdep.h @@ -0,0 +1,105 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * + * Copyright (C) 2004-2007 Atmel Corporation + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA + +#include + +#define ARCH_NUM 1 +#define DT_AVR32_GOTSZ_IDX (DT_NUM + OS_NUM) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ + do { \ + if (dpnt->d_tag == DT_AVR32_GOTSZ) \ + dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \ + } while (0) + +/* Initialization sequence for the application/library GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ + do { \ + unsigned long _i, _nr_got; \ + \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ + \ + /* Add load address displacement to all GOT entries */ \ + _nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \ + for (_i = 2; _i < _nr_got; _i++) \ + GOT_BASE[_i] += (unsigned long)MODULE->loadaddr; \ + } while (0) + +#define do_rem(result, n, base) ((result) = (n) % (base)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_AVR32 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "AVR32" + +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +#define elf_machine_type_class(type) \ + ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) + +/* AVR32 doesn't need any COPY relocs */ +#define DL_NO_COPY_RELOCS + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__("r6"); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + extern void __dl_start __asm__("_dl_start"); + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; + + __asm__(" lddpc %0, 2f\n" + "1: add %0, pc\n" + " rjmp 3f\n" + " .align 2\n" + "2: .long _dl_start - 1b\n" + "3:\n" + : "=r"(pcrel_addr) : : "cc"); + + return pcrel_addr - got_addr; +} + +/* + * Perform any RELATIVE relocations specified by DT_RELCOUNT. + * Currently, we don't use that tag, but we might in the future as + * this would reduce the startup time somewhat (although probably not by much). + */ +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (void *)rel_addr; + + do { + Elf32_Addr *reloc_addr; + reloc_addr = (void *)(load_off + (rpnt++)->r_offset); + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c new file mode 100644 index 0000000..813179e --- /dev/null +++ b/ldso/ldso/avr32/elfinterp.c @@ -0,0 +1,193 @@ +/* + * AVR32 ELF shared library loader suppport + * + * Copyright (C) 2004-2006 Atmel Corporation + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got) +{ + /* + * AVR32 currently does not do lazy relocation. + */ +#if 0 + struct elf_resolve *tpnt = (struct elf_resolve *)got[1]; + Elf32_Sym *sym; + unsigned long local_gotno; + unsigned long gotsym; + unsigned long new_addr; + char *strtab, *symname; + unsigned long *entry; + unsigned long sym_index = got_offset / 4; + + local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO]; + gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM]; + + sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + + sym_index; + strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); + symname = strtab + sym->st_name; + + new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name, + tpnt->symbol_scope, tpnt, + resolver); + + entry = (unsigned long *)(got + local_gotno + sym_index - gotsym); + *entry = new_addr; + + return new_addr; +#endif + return 0; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope, + Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + Elf32_Sym *symtab; + Elf32_Rela *rpnt; + char *strtab; + int i; + + rpnt = (Elf32_Rela *)rel_addr; + rel_size /= sizeof(Elf32_Rela); + symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int symtab_index, res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_func(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (res < 0) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined(__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n", + _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); +#endif + _dl_exit(-res); + } else { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined(__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + symbol_addr = (unsigned long) + _dl_find_hash(strtab + symtab[symtab_index].st_name, + tpnt->symbol_scope, tpnt, + elf_machine_type_class(reloc_type)); + + /* Allow undefined references to weak symbols */ + if (!symbol_addr && + ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + return 0; + } + } + +#if defined(__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_AVR32_NONE: + break; + case R_AVR32_GLOB_DAT: + case R_AVR32_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_AVR32_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + + rpnt->r_addend; + break; + default: + return -1; + } + +#if defined(__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr); +#endif + + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + /* TODO: Might want to support this in order to get faster + * startup times... */ +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, + _dl_do_reloc); +} diff --git a/ldso/ldso/avr32/resolve.S b/ldso/ldso/avr32/resolve.S new file mode 100644 index 0000000..e3cb7f4 --- /dev/null +++ b/ldso/ldso/avr32/resolve.S @@ -0,0 +1,28 @@ +/* + * Linux dynamic resolving code for AVR32. Fixes up the GOT entry as + * indicated in register r12 and jumps to the resolved address. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Copyright (C) 2004-2007 Atmel Corporation + */ + +#define ip r5 + + .text + .global _dl_linux_resolve + .type _dl_linux_resolve,@function +_dl_linux_resolve: + /* The PLT code pushed r8 for us. It contains the address of this + function's GOT entry, that is entry 0. ip contains the address + of the GOT entry of the function we wanted to call. */ + stm --sp, r9-r12, lr + mov r11, r8 + sub r12, ip, r8 + rcall _dl_linux_resolver + mov ip, r12 + popm r8-r12,lr + mov pc, ip + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/ldso/ldso/bfin/dl-debug.h b/ldso/ldso/bfin/dl-debug.h new file mode 100644 index 0000000..9dd3162 --- /dev/null +++ b/ldso/ldso/bfin/dl-debug.h @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* Blackfin ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_BFIN_unused0", "R_BFIN_pcrel5m2", + [2] "R_BFIN_unused1", "R_BFIN_pcrel10", + [4] "R_BFIN_pcrel12_jump", "R_BFIN_rimm16", + [6] "R_BFIN_luimm16", "R_BFIN_huimm16", + [8] "R_BFIN_pcrel12_jump_s","R_BFIN_pcrel24_jump_x", + [10] "R_BFIN_pcrel24", "R_BFIN_unusedb", + [12] "R_BFIN_unusedc", "R_BFIN_pcrel24_jump_l", + [14] "R_BFIN_pcrel24_call_x","R_BFIN_var_eq_symb", + [16] "R_BFIN_byte_data", "R_BFIN_byte2_data", "R_BFIN_byte4_data", + [19] "R_BFIN_pcrel11", + + [20] "R_BFIN_GOT17M4", "R_BFIN_GOTHI", "R_BFIN_GOTLO", + [23] "R_BFIN_FUNCDESC", + [24] "R_BFIN_FUNCDESC_GOT17M4", "R_BFIN_FUNCDESC_GOTHI", "R_BFIN_FUNCDESC_GOTLO", + [27] "R_BFIN_FUNCDESC_VALUE", "R_BFIN_FUNCDESC_GOTOFF17M4", + [29] "R_BFIN_FUNCDESC_GOTOFFHI", "R_BFIN_FUNCDESC_GOTOFFLO", + [31] "R_BFIN_GOTOFF17M4", "R_BFIN_GOTOFFHI", "R_BFIN_GOTOFFLO", +#if 0 + [200] "R_BFIN_GNU_VTINHERIT", "R_BFIN_GNU_VTENTRY" +#endif +}; diff --git a/ldso/ldso/bfin/dl-inlines.h b/ldso/ldso/bfin/dl-inlines.h new file mode 100644 index 0000000..6ed1bda --- /dev/null +++ b/ldso/ldso/bfin/dl-inlines.h @@ -0,0 +1,574 @@ + /* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +#include + +#ifndef _dl_assert +# define _dl_assert(expr) +#endif + +/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete + load map. */ +static __always_inline void +__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer, + struct elf32_fdpic_loadmap *map) +{ + if (map->version != 0) + { + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); + _dl_exit(-1); + } + if (map->nsegs == 0) + { + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); + _dl_exit(-1); + } + loadaddr->got_value = dl_boot_got_pointer; + loadaddr->map = map; +} + +/* Figure out how many LOAD segments there are in the given headers, + and allocate a block for the load map big enough for them. + got_value will be properly initialized later on, with INIT_GOT. */ +static __always_inline int +__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt, + int pcnt) +{ + int count = 0, i; + size_t size; + + for (i = 0; i < pcnt; i++) + if (ppnt[i].p_type == PT_LOAD) + count++; + + loadaddr->got_value = 0; + + size = sizeof (struct elf32_fdpic_loadmap) + + sizeof (struct elf32_fdpic_loadseg) * count; + loadaddr->map = _dl_malloc (size); + if (! loadaddr->map) + _dl_exit (-1); + + loadaddr->map->version = 0; + loadaddr->map->nsegs = 0; + + return count; +} + +/* Incrementally initialize a load map. */ +static __always_inline void +__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr, + Elf32_Phdr *phdr, int maxsegs) +{ + struct elf32_fdpic_loadseg *segdata; + + if (loadaddr.map->nsegs == maxsegs) + _dl_exit (-1); + + segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; + segdata->addr = (Elf32_Addr) addr; + segdata->p_vaddr = phdr->p_vaddr; + segdata->p_memsz = phdr->p_memsz; + +#if defined (__SUPPORT_LD_DEBUG__) + { + extern char *_dl_debug; + extern int _dl_debug_file; + if (_dl_debug) + _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", + loadaddr.map->nsegs-1, + segdata->p_vaddr, segdata->addr, segdata->p_memsz); + } +#endif +} + +static __always_inline void __dl_loadaddr_unmap +(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht); + +/* Figure out whether the given address is in one of the mapped + segments. */ +static __always_inline int +__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr) +{ + struct elf32_fdpic_loadmap *map = loadaddr.map; + int c; + + for (c = 0; c < map->nsegs; c++) + if ((void*)map->segs[c].addr <= p + && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) + return 1; + + return 0; +} + +static __always_inline void * _dl_funcdesc_for (void *entry_point, void *got_value); + +/* The hashcode handling code below is heavily inspired in libiberty's + hashtab code, but with most adaptation points and support for + deleting elements removed. + + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). */ + +static __always_inline unsigned long +higher_prime_number (unsigned long n) +{ + /* These are primes that are near, but slightly smaller than, a + power of two. */ + static const unsigned long primes[] = { + (unsigned long) 7, + (unsigned long) 13, + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, + /* 4294967291L */ + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + }; + + const unsigned long *low = &primes[0]; + const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])]; + + while (low != high) + { + const unsigned long *mid = low + (high - low) / 2; + if (n > *mid) + low = mid + 1; + else + high = mid; + } + +#if 0 + /* If we've run out of primes, abort. */ + if (n > *low) + { + fprintf (stderr, "Cannot find prime bigger than %lu\n", n); + abort (); + } +#endif + + return *low; +} + +struct funcdesc_ht +{ + /* Table itself. */ + struct funcdesc_value **entries; + + /* Current size (in entries) of the hash table */ + size_t size; + + /* Current number of elements. */ + size_t n_elements; +}; + +static __always_inline int +hash_pointer (const void *p) +{ + return (int) ((long)p >> 3); +} + +static __always_inline struct funcdesc_ht * +htab_create (void) +{ + struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht)); + + if (! ht) + return NULL; + ht->size = 3; + ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size); + if (! ht->entries) + return NULL; + + ht->n_elements = 0; + + _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size); + + return ht; +} + +/* This is only called from _dl_loadaddr_unmap, so it's safe to call + _dl_free(). See the discussion below. */ +static __always_inline void +htab_delete (struct funcdesc_ht *htab) +{ + int i; + + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i]) + _dl_free (htab->entries[i]); + + _dl_free (htab->entries); + _dl_free (htab); +} + +/* Similar to htab_find_slot, but without several unwanted side effects: + - Does not call htab->eq_f when it finds an existing entry. + - Does not change the count of elements/searches/collisions in the + hash table. + This function also assumes there are no deleted entries in the table. + HASH is the hash value for the element to be inserted. */ + +static __always_inline struct funcdesc_value ** +find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash) +{ + size_t size = htab->size; + unsigned int index = hash % size; + struct funcdesc_value **slot = htab->entries + index; + int hash2; + + if (! *slot) + return slot; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + slot = htab->entries + index; + if (! *slot) + return slot; + } +} + +/* The following function changes size of memory allocated for the + entries and repeatedly inserts the table elements. The occupancy + of the table after the call will be about 50%. Naturally the hash + table must already exist. Remember also that the place of the + table entries is changed. If memory allocation failures are allowed, + this function will return zero, indicating that the table could not be + expanded. If all goes well, it will return a non-zero value. */ + +static __always_inline int +htab_expand (struct funcdesc_ht *htab) +{ + struct funcdesc_value **oentries; + struct funcdesc_value **olimit; + struct funcdesc_value **p; + struct funcdesc_value **nentries; + size_t nsize; + + oentries = htab->entries; + olimit = oentries + htab->size; + + /* Resize only when table after removal of unused elements is either + too full or too empty. */ + if (htab->n_elements * 2 > htab->size) + nsize = higher_prime_number (htab->n_elements * 2); + else + nsize = htab->size; + + nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize); + _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize); + if (nentries == NULL) + return 0; + htab->entries = nentries; + htab->size = nsize; + + p = oentries; + do + { + if (*p) + *find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point)) + = *p; + + p++; + } + while (p < olimit); + +#if 0 /* We can't tell whether this was allocated by the _dl_malloc() + built into ld.so or malloc() in the main executable or libc, + and calling free() for something that wasn't malloc()ed could + do Very Bad Things (TM). Take the conservative approach + here, potentially wasting as much memory as actually used by + the hash table, even if multiple growths occur. That's not + so bad as to require some overengineered solution that would + enable us to keep track of how it was allocated. */ + _dl_free (oentries); +#endif + return 1; +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. + When inserting an entry, NULL may be returned if memory allocation + fails. */ + +static __always_inline struct funcdesc_value ** +htab_find_slot (struct funcdesc_ht *htab, void *ptr, int insert) +{ + unsigned int index; + int hash, hash2; + size_t size; + struct funcdesc_value **entry; + + if (htab->size * 3 <= htab->n_elements * 4 + && htab_expand (htab) == 0) + return NULL; + + hash = hash_pointer (ptr); + + size = htab->size; + index = hash % size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + } + + empty_entry: + if (!insert) + return NULL; + + htab->n_elements++; + return entry; +} + +void * +_dl_funcdesc_for (void *entry_point, void *got_value) +{ + struct elf_resolve *tpnt = ((void**)got_value)[2]; + struct funcdesc_ht *ht = tpnt->funcdesc_ht; + struct funcdesc_value **entry; + + _dl_assert (got_value == tpnt->loadaddr.got_value); + + if (! ht) + { + ht = htab_create (); + if (! ht) + return (void*)-1; + tpnt->funcdesc_ht = ht; + } + + entry = htab_find_slot (ht, entry_point, 1); + if (*entry) + { + _dl_assert ((*entry)->entry_point == entry_point); + return _dl_stabilize_funcdesc (*entry); + } + + *entry = _dl_malloc (sizeof (struct funcdesc_value)); + (*entry)->entry_point = entry_point; + (*entry)->got_value = got_value; + + return _dl_stabilize_funcdesc (*entry); +} + +static __always_inline void const * +_dl_lookup_address (void const *address) +{ + struct elf_resolve *rpnt; + struct funcdesc_value const *fd; + + /* Make sure we don't make assumptions about its alignment. */ + __asm__ ("" : "+r" (address)); + + if ((Elf32_Addr)address & 7) + /* It's not a function descriptor. */ + return address; + + fd = (struct funcdesc_value const *)address; + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) + { + if (! rpnt->funcdesc_ht) + continue; + + if (fd->got_value != rpnt->loadaddr.got_value) + continue; + + address = htab_find_slot (rpnt->funcdesc_ht, (void*)fd->entry_point, 0); + + if (address && *(struct funcdesc_value *const*)address == fd) + { + address = (*(struct funcdesc_value *const*)address)->entry_point; + break; + } + else + address = fd; + } + + return address; +} + +void +__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr, + struct funcdesc_ht *funcdesc_ht) +{ + int i; + + for (i = 0; i < loadaddr.map->nsegs; i++) + { + struct elf32_fdpic_loadseg *segdata; + ssize_t offs; + segdata = loadaddr.map->segs + i; + + /* FIXME: + A more cleaner way is to add type for struct elf32_fdpic_loadseg, + and release the memory according to the type. + Currently, we hardcode the memory address of L1 SRAM. */ + if ((segdata->addr & 0xff800000) == 0xff800000) + { + _dl_sram_free ((void *)segdata->addr); + continue; + } + + offs = (segdata->p_vaddr & ADDR_ALIGN); + _dl_munmap ((void*)segdata->addr - offs, + segdata->p_memsz + offs); + } + /* _dl_unmap is only called for dlopen()ed libraries, for which + calling free() is safe, or before we've completed the initial + relocation, in which case calling free() is probably pointless, + but still safe. */ + _dl_free (loadaddr.map); + if (funcdesc_ht) + htab_delete (funcdesc_ht); +} + +static __always_inline int +__dl_is_special_segment (Elf32_Ehdr *epnt, + Elf32_Phdr *ppnt) +{ + if (ppnt->p_type != PT_LOAD) + return 0; + + if ((epnt->e_flags & EF_BFIN_CODE_IN_L1) + && !(ppnt->p_flags & PF_W) + && (ppnt->p_flags & PF_X)) + return 1; + + if ((epnt->e_flags & EF_BFIN_DATA_IN_L1) + && (ppnt->p_flags & PF_W) + && !(ppnt->p_flags & PF_X)) + return 1; + + /* 0xff700000, 0xff800000, 0xff900000 and 0xffa00000 are also used in + GNU ld and linux kernel. They need to be keep synchronized. */ + if (ppnt->p_vaddr == 0xff700000 + || ppnt->p_vaddr == 0xff800000 + || ppnt->p_vaddr == 0xff900000 + || ppnt->p_vaddr == 0xffa00000) + return 1; + + return 0; +} + +static __always_inline char * +__dl_map_segment (Elf32_Ehdr *epnt, + Elf32_Phdr *ppnt, + int infile, + int flags) +{ + char *status, *tryaddr, *l1addr; + size_t size; + + if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000) + && !(ppnt->p_flags & PF_W) + && (ppnt->p_flags & PF_X)) { + status = (char *) _dl_mmap + (tryaddr = 0, + size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz, + LXFLAGS(ppnt->p_flags), + flags | MAP_EXECUTABLE | MAP_DENYWRITE, + infile, ppnt->p_offset & OFFS_ALIGN); + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) + return NULL; + l1addr = (char *) _dl_sram_alloc (ppnt->p_filesz, L1_INST_SRAM); + if (l1addr != NULL) + _dl_dma_memcpy (l1addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz); + _dl_munmap (status, size); + if (l1addr == NULL) + _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__); + return l1addr; + } + + if (((epnt->e_flags & EF_BFIN_DATA_IN_L1) + || ppnt->p_vaddr == 0xff700000 + || ppnt->p_vaddr == 0xff800000 + || ppnt->p_vaddr == 0xff900000) + && (ppnt->p_flags & PF_W) + && !(ppnt->p_flags & PF_X)) { + if (ppnt->p_vaddr == 0xff800000) + l1addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_A_SRAM); + else if (ppnt->p_vaddr == 0xff900000) + l1addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_B_SRAM); + else + l1addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_SRAM); + if (l1addr == NULL) { + _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__); + } else { + if (_DL_PREAD (infile, l1addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) { + _dl_sram_free (l1addr); + return NULL; + } + if (ppnt->p_filesz < ppnt->p_memsz) + _dl_memset (l1addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz); + } + return l1addr; + } + + return 0; +} diff --git a/ldso/ldso/bfin/dl-startup.h b/ldso/ldso/bfin/dl-startup.h new file mode 100644 index 0000000..a1e150e --- /dev/null +++ b/ldso/ldso/bfin/dl-startup.h @@ -0,0 +1,145 @@ + /* Copyright (C) 2003 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* Any assembly language/system dependent hacks needed to setup + * boot1.c so it will work as expected and cope with whatever platform + * specific wierdness is needed for this architecture. + + * We override the default _dl_boot function, and replace it with a + * bit of asm. Then call the real _dl_boot function, which is now + * named _dl_boot2. */ + +/* At program start-up, p0 contains a pointer to a + elf32_fdpic_loadmap that describes how the executable was loaded + into memory. p1 contains a pointer to the interpreter (our!) + loadmap, if there is an interpreter, or 0 if we're being run as an + executable. p2 holds a pointer to the interpreter's dynamic + section, if there is an interpreter, or to the executable's dynamic + section, otherwise. If the executable is not dynamic, gr18 is 0. + + We rely on the fact that the linker adds a pointer to the + _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that + __self_reloc returns the relocated pointer to us, so that we can + use this value to initialize the PIC register. */ + +__asm__( + " .text\n" \ + " .global __dl_boot\n" \ + " .type __dl_boot,@function\n" \ + "__dl_boot:\n" \ + " call .Lcall\n" \ + ".Lcall:\n" \ + " R4 = RETS;\n" \ + " SP += -32;\n" \ + " R5 = P0;\n" \ + " R6 = P1;\n" \ + " R7 = P2;\n" \ + " R0.L = .Lcall;\n" \ + " R0.H = .Lcall;\n" \ + " R1.L = __ROFIXUP_LIST__;\n" \ + " R1.H = __ROFIXUP_LIST__;\n" \ + " R2.L = __ROFIXUP_END__;\n" \ + " R2.H = __ROFIXUP_END__;\n" \ + " R1 = R1 - R0;\n" \ + " R1 = R1 + R4;\n" \ + " R2 = R2 - R0;\n" \ + " R2 = R2 + R4;\n" \ + " R0 = P1;\n" \ + " CC = R0 == 0;\n" \ + " IF CC R0 = P0;\n" \ + " CALL ___self_reloc;\n" \ + " P3 = R0;\n" \ + " P5 = R0;\n" \ + " R1 = R5;\n" \ + " R2 = R6;\n" \ + " [SP + 12] = R7;\n" \ + " P0 = SP;\n" \ + " P0 += 24;\n" \ + " [SP + 16] = P0;\n" \ + " P0 += 8;\n" \ + " [SP + 20] = P0;\n" \ + " CALL __dl_start;\n" \ + " /* Pass our FINI ptr() to the user in P1 */\n" \ + " R7 = [P5 + __dl_fini@FUNCDESC_GOT17M4];\n" \ + " P4 = [SP + 24];\n" \ + " P3 = [SP + 28];\n" \ + " P0 = R5;\n" \ + " SP += 32;\n" \ + " JUMP (P4);\n" \ + " .size __dl_boot,.-__dl_boot\n" +); + +#undef DL_START +#define DL_START(X) \ +static void __attribute__ ((used)) \ +_dl_start (Elf32_Addr dl_boot_got_pointer, \ + struct elf32_fdpic_loadmap *dl_boot_progmap, \ + struct elf32_fdpic_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + struct funcdesc_value *dl_main_funcdesc, \ + X) + +struct elf32_fdpic_loadmap; + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_BFIN_byte4_data: \ + *(REL) += (SYMBOL); \ + break; \ + case R_BFIN_FUNCDESC_VALUE: \ + { \ + struct funcdesc_value fv = { \ + (void*)((SYMBOL) + *(REL)), \ + (LOAD).got_value \ + }; \ + *(struct funcdesc_value volatile *)(REL) = fv; \ + break; \ + } \ + default: \ + _dl_exit(1); \ + } + +/* + * Transfer control to the user's application, once the dynamic loader + * is done. We return the address of the function's entry point to + * _dl_boot, see boot1_arch.h. + */ +#define START() do { \ + struct elf_resolve *exec_mod = _dl_loaded_modules; \ + dl_main_funcdesc->entry_point = _dl_elf_main; \ + while (exec_mod->libtype != elf_executable) \ + exec_mod = exec_mod->next; \ + dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \ + return; \ +} while (0) diff --git a/ldso/ldso/bfin/dl-syscalls.h b/ldso/ldso/bfin/dl-syscalls.h new file mode 100644 index 0000000..916d0f8 --- /dev/null +++ b/ldso/ldso/bfin/dl-syscalls.h @@ -0,0 +1,208 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +#include + +/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ + +#if DYNAMIC_LOADER_IN_SIMULATOR +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset); + +/* Make sure we don't get another definition of _dl_mmap from the + machine-independent code. */ +#undef __NR_mmap +#undef __NR_mmap2 + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +#include /* for PAGE_SIZE */ +static __always_inline void *_dl_memset(void*,int,size_t); +static __always_inline ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset); + +static __ptr_t +_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE; + +/* This is a hack to enable the dynamic loader to run within a + simulator that doesn't support mmap, with a number of very ugly + tricks. Also, it's not as useful as it sounds, since only dynamic + executables without DT_NEEDED dependencies can be run. AFAIK, they + can only be created with -pie. This trick suffices to enable the + dynamic loader to obtain a blank page that it maps early in the + bootstrap. */ + if ((flags & MAP_FIXED) == 0) + { + void *_dl_mmap_base = 0; + __ptr_t *ret = 0; + + if (! _dl_mmap_base) + { + void *stack; + __asm__ ("mov sp, %0" : "=r" (stack)); + _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE); + retry: + if (((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void **)_dl_mmap_base)[771])) + { + while (((void**)_dl_mmap_base)[177]) + { + _dl_mmap_base = ((void**)_dl_mmap_base)[177]; + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + } + } + else + { + int i; + for (i = 0; i < (int)PAGE_SIZE; i++) + if (*(char*)(_dl_mmap_base + i)) + break; + if (i != PAGE_SIZE) + { + _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE); + goto retry; + } + ((void**)_dl_mmap_base)[-1] = + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + } + + if (_dl_mmap_base) + { + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE); + _dl_mmap_base = + ((void**)_dl_mmap_base)[177] = + ((void**)_dl_mmap_base)[771] = + (char*)_dl_mmap_base + plen + PAGE_SIZE; + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + + if ((flags & MAP_ANONYMOUS) != 0) + { + _dl_memset (ret, 0, plen); + return ret; + } + + flags |= MAP_FIXED; + addr = ret; + } + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { +#if 0 + __set_errno (EINVAL); +#endif + return MAP_FAILED; + } + if ((flags & MAP_FIXED) != 0) + { + if (_dl_pread(fd, addr, len, offset) != (ssize_t)len) + return (void*)MAP_FAILED; + if (plen != len) + _dl_memset (addr + len, 0, plen - len); + return addr; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +#endif + +#ifdef __NR_pread +#ifdef DYNAMIC_LOADER_IN_SIMULATOR +#include + +#define __NR___syscall_lseek __NR_lseek +static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count); + +static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset, + int, whence); +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR); + ssize_t ret; + + if (orig == -1) + return -1; + + if (__syscall_lseek (fd, offset, SEEK_SET) != offset) + return -1; + + ret = _dl_read (fd, buf, count); + + if (__syscall_lseek (fd, orig, SEEK_SET) != orig) + ((void(*)())0)(); + + return ret; +} +#else +#define __NR___syscall_pread __NR_pread +static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo); + +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset))); +} +#endif +#endif + +#ifdef __NR_sram_alloc +#define __NR__dl_sram_alloc __NR_sram_alloc +static __always_inline _syscall2(__ptr_t, _dl_sram_alloc, + size_t, len, unsigned long, flags); +#endif + +#ifdef __NR_sram_free +#define __NR__dl_sram_free __NR_sram_free +static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr); +#endif + +#ifdef __NR_dma_memcpy +#define __NR__dl_dma_memcpy __NR_dma_memcpy +static __always_inline _syscall3(__ptr_t, _dl_dma_memcpy, + __ptr_t, dest, __ptr_t, src, size_t, len); +#endif + +#define __UCLIBC_MMAP_HAS_6_ARGS__ diff --git a/ldso/ldso/bfin/dl-sysdep.h b/ldso/ldso/bfin/dl-sysdep.h new file mode 100644 index 0000000..52df4c9 --- /dev/null +++ b/ldso/ldso/bfin/dl-sysdep.h @@ -0,0 +1,229 @@ + /* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + Based on ../i386/dl-sysdep.h + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#undef ELF_USES_RELOCA + +/* JMPREL relocs are inside the DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP + +#define DL_NO_COPY_RELOCS + +#define HAVE_DL_INLINES_H + +/* + * Initialization sequence for a GOT. Copy the resolver function + * descriptor and the pointer to the elf_resolve/link_map data + * structure. Initialize the got_value in the module while at that. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + (MODULE)->loadaddr.got_value = (GOT_BASE); \ + GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \ + GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \ + GOT_BASE[2] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_BLACKFIN +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "BFIN" + +struct elf_resolve; + +struct funcdesc_value +{ + void *entry_point; + void *got_value; +} __attribute__((__aligned__(8))); + + +extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); + +/* 4KiB page alignment. Should perhaps be made dynamic using + getpagesize(), based on AT_PAGESZ from auxvt? */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +struct funcdesc_ht; + +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { \ + static const char __attribute__((section(".text"))) __s[] = (S); \ + const char *__p, *__scratch; \ + __asm__ ("call 1f;\n1:\n\t" \ + "%1 = RETS;\n\t" \ + "%0 = [%3 + 1b@GOT17M4];\n\t" \ + "%1 = %1 - %0;\n\t" \ + "%1 = %1 + %2;\n\t" \ + : "=&d" (__scratch), "=&d" (__p) \ + : "d" (__s), "a" (dl_boot_got_pointer) : "RETS"); \ + SEND_STDERR (__p); \ + { int __t; \ + for (__t = 0; __t < 0x1000000; __t++) __asm__ __volatile__ (""); } \ + } while (0) + +#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr + +#define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \ + ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value)) + +#define _dl_stabilize_funcdesc(val) \ + ({ __asm__ ("" : "+m" (*(val))); (val); }) + +#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \ + void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \ + (* SIGNATURE pf)(__VA_ARGS__); }) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \ + dl_boot_ldsomap ?: dl_boot_progmap)) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap)) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR), (NULL))) +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht)) +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).got_value) + +/* This is called from dladdr(), such that we map a function + descriptor's address to the function's entry point before trying to + find in which library it's defined. */ +#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS)) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + +/* + * Compute the GOT address. On several platforms, we use assembly + * here. on FR-V FDPIC, there's no way to compute the GOT address, + * since the offset between text and data is not fixed, so we arrange + * for the assembly _dl_boot to pass this value as an argument to + * _dl_boot. */ +#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + +/* We only support loading FDPIC independently-relocatable shared + libraries. It probably wouldn't be too hard to support loading + shared libraries that require relocation by the same amount, but we + don't know that they exist or would be useful, and the dynamic + loader code could leak the whole-library map unless we keeping a + bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's + keep things simple for now. */ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + if (((epnt)->e_flags & EF_BFIN_FDPIC) && ! ((epnt)->e_flags & EF_BFIN_PIC)) \ + (piclib) = 2; \ + else \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + return NULL; \ + } \ +\ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +/* We want to return to dlsym() a function descriptor if the symbol + turns out to be a function. */ +#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \ + (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \ + && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \ + ? _dl_funcdesc_for ((void *)DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value), \ + (TPNT)->loadaddr.got_value) \ + : DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value)) + +#define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) \ + __dl_is_special_segment(EPNT, PPNT) +#define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \ + __dl_map_segment (EPNT, PPNT, INFILE, FLAGS) + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_fdpic_loadmap *dl_boot_progmap, Elf32_Addr dl_boot_got_pointer +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap, dl_boot_got_pointer + + +#ifdef __USE_GNU +# include +#else +# define __USE_GNU +# include +# undef __USE_GNU +#endif + +#include +static __inline__ void +elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ +#if 0 + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = DL_RELOC_ADDR (load_off, *reloc_addr); + } while (--relative_count); +#endif +} diff --git a/ldso/ldso/bfin/elfinterp.c b/ldso/ldso/bfin/elfinterp.c new file mode 100644 index 0000000..ac24337 --- /dev/null +++ b/ldso/ldso/bfin/elfinterp.c @@ -0,0 +1,350 @@ +/* Blackfin ELF shared library loader suppport + Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + Lots of code copied from ../i386/elfinterp.c, so: + Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + David Engel, Hongjiu Lu and Mitch D'Souza + Copyright (C) 2001-2002, Erik Andersen + All rights reserved. + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +#include /* __attribute_used__ */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +struct funcdesc_value volatile *__attribute__((__visibility__("hidden"))) +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + struct elf_resolve *new_tpnt; + char *new_addr; + struct funcdesc_value funcval; + struct funcdesc_value volatile *got_entry; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname= strtab + symtab[symtab_index].st_name; + + if (reloc_type != R_BFIN_FUNCDESC_VALUE) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of GOT entry fix up */ + got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt); + if (!new_addr) { + new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt); + if (!new_addr) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + } + + funcval.entry_point = new_addr; + funcval.got_value = new_tpnt->loadaddr.got_value; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", + got_entry->entry_point, got_entry->got_value, + funcval.entry_point, funcval.got_value, + got_entry); + } + if (1 || !_dl_debug_nofixups) { + *got_entry = funcval; + } +#else + *got_entry = funcval; +#endif + + return got_entry; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (res <0) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (res >0) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long reloc_value = 0, *reloc_addr; + struct { unsigned long v; } __attribute__((__packed__)) + *reloc_addr_packed; + unsigned long symbol_addr; + struct elf_resolve *symbol_tpnt; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); + __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr)); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long) DL_RELOC_ADDR(tpnt->loadaddr, symtab[symtab_index].st_value); + symbol_tpnt = tpnt; + } else { + + symbol_addr = (unsigned long) + _dl_lookup_hash(symname, scope, NULL, 0, &symbol_tpnt); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + { + if ((long)reloc_addr_packed & 3) + old_val = reloc_addr_packed->v; + else + old_val = *reloc_addr; + } + else + old_val = 0; +#endif + switch (reloc_type) { + case R_BFIN_unused0: + break; + case R_BFIN_byte4_data: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v += symbol_addr; + else + reloc_value = *reloc_addr += symbol_addr; + break; + case R_BFIN_FUNCDESC_VALUE: + funcval.entry_point = (void*)symbol_addr; + /* The addend of FUNCDESC_VALUE + relocations referencing global + symbols must be ignored, because it + may hold the address of a lazy PLT + entry. */ + if (ELF_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) + funcval.entry_point += *reloc_addr; + reloc_value = (unsigned long)funcval.entry_point; + if (symbol_addr) + funcval.got_value + = symbol_tpnt->loadaddr.got_value; + else + funcval.got_value = 0; + __asm__ ("%0 = %2; %1 = %H2;" + : "=m" (*(struct funcdesc_value *)reloc_addr), "=m" (((long *)reloc_addr)[1]) + : "d" (funcval)); + break; + case R_BFIN_FUNCDESC: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v; + else + reloc_value = *reloc_addr; + if (symbol_addr) + reloc_value = (unsigned long)_dl_funcdesc_for + ((char *)symbol_addr + reloc_value, + symbol_tpnt->loadaddr.got_value); + else + reloc_value = 0; + if ((long)reloc_addr_packed & 3) + reloc_addr_packed->v = reloc_value; + else + *reloc_addr = reloc_value; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr); + switch (reloc_type) { + case R_BFIN_FUNCDESC_VALUE: + _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value); + break; + case R_BFIN_FUNCDESC: + if (! reloc_value) + break; + _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)", + ((struct funcdesc_value *)reloc_value)->entry_point, + ((struct funcdesc_value *)reloc_value)->got_value); + break; + } + } +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, + struct dyn_elf *scope __attribute__((unused)), + ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)), + char *strtab __attribute__((unused))) +{ + int reloc_type; + struct funcdesc_value volatile *reloc_addr; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = (unsigned long)reloc_addr->entry_point; +#endif + switch (reloc_type) { + case R_BFIN_unused0: + break; + case R_BFIN_FUNCDESC_VALUE: + funcval = *reloc_addr; + funcval.entry_point = DL_RELOC_ADDR(tpnt->loadaddr, funcval.entry_point); + funcval.got_value = tpnt->loadaddr.got_value; + *reloc_addr = funcval; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_addr->entry_point, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +/* We don't have copy relocs. */ + +int +_dl_parse_copy_information +(struct dyn_elf *rpnt __attribute__((unused)), + unsigned long rel_addr __attribute__((unused)), + unsigned long rel_size __attribute__((unused))) +{ + return 0; +} + +#ifndef IS_IN_libdl +# include "../../libc/sysdeps/linux/bfin/crtreloc.c" +#endif + diff --git a/ldso/ldso/bfin/resolve.S b/ldso/ldso/bfin/resolve.S new file mode 100644 index 0000000..ae7f4a4 --- /dev/null +++ b/ldso/ldso/bfin/resolve.S @@ -0,0 +1,77 @@ + /* Copyright (C) 2003 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc 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. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + + /* The function below is tail-called by resolver stubs when a + lazily-bound function is called. It must preserve all + registers that could be used to pass arguments to the actual + function. Upon _dl_linux_resolve entry, GR14 holds the + address of a lazy PLT entry, so @(GR14,-4) is the lazy + relocation number that we have to pass to _dl_linux_resolver. + GR15 holds the caller's GOT, from which we extract the + elf_resolve* that _dl_linux_resolver needs as well. + + _dl_linux_resolver() figures out where the jump symbol is + _really_ supposed to have jumped to and returns that to us. + Once we have that, we prepare to tail-call the actual + function, clean up after ourselves, restoring the original + arguments, then jump to the fixed up address. */ + + .text + .p2align 4 + + .hidden __dl_linux_resolve + .global __dl_linux_resolve + .type __dl_linux_resolve,@function + +__dl_linux_resolve: + /* Preserve arguments. */ + [--SP] = RETS; + [--SP] = P0; + [--SP] = R0; + [--SP] = R1; + [--SP] = R2; + sp += -12; + + /* Prepare to call _dl_linux_resolver. */ + R0 = [P3 + 8]; + /* Not aligned for space reasons. */ + R1 = W[P1 + -4] (Z); + P1 += -2; + R1.H = W[P1]; + + P3 = R3; + CALL __dl_linux_resolver; + + /* Move aside return value that contains the FUNCDESC_VALUE. */ + P3 = R0; + P1 = [P3]; + P3 = [P3 + 4]; + + /* Restore arguments. */ + sp += 12; + R2 = [SP++]; + R1 = [SP++]; + R0 = [SP++]; + P0 = [SP++]; + RETS = [SP++]; + + /* Now jump to the actual function. */ + JUMP (P1); + .size __dl_linux_resolve, . - __dl_linux_resolve diff --git a/ldso/ldso/cris/dl-debug.h b/ldso/ldso/cris/dl-debug.h new file mode 100644 index 0000000..f6c03d2 --- /dev/null +++ b/ldso/ldso/cris/dl-debug.h @@ -0,0 +1,42 @@ +/* + * CRIS ELF shared library loader support. + * + * Program to load an elf binary on a linux system, and run it. + * References to symbols in sharable libraries can be resolved + * by either an ELF sharable library or a linux style of shared + * library. + * + * Copyright (C) 2002-2004, Axis Communications AB + * All rights reserved + * + * Author: Tobias Anderberg, + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_CRIS_NONE", "R_CRIS_8", "R_CRIS_16", "R_CRIS_32", + [4] "R_CRIS_8_PCREL", "R_CRIS_16_PCREL", "R_CRIS_32_PCREL", "R_CRIS_GNU_VTINHERIT", + [8] "R_CRIS_GNU_VTENTRY", "R_CRIS_COPY", "R_CRIS_GLOB_DAT", "R_CRIS_JUMP_SLOT", + [16] "R_CRIS_RELATIVE", "R_CRIS_16_GOT", "R_CRIS_32_GOT", "R_CRIS_16_GOTPLT", + [32] "R_CRIS_32_GOTPLT", "R_CRIS_32_GOTREL", "R_CRIS_32_PLT_GOTREL", "R_CRIS_32_PLT_PCREL", +}; diff --git a/ldso/ldso/cris/dl-startup.h b/ldso/ldso/cris/dl-startup.h new file mode 100644 index 0000000..dc9cd8f --- /dev/null +++ b/ldso/ldso/cris/dl-startup.h @@ -0,0 +1,81 @@ +/* + * Architecture specific code used by dl-startup.c + */ + +/* This code fixes the stack pointer so that the dynamic linker + * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +__asm__("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + +__asm__("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#endif /* __arch_v32 */ + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1) + + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + *reloc_addr = symbol_addr; + break; + case R_CRIS_16_PCREL: + *(short *) *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 2; + break; + case R_CRIS_32_PCREL: + *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 4; + break; + case R_CRIS_NONE: + break; + case R_CRIS_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + _dl_exit(1); + break; + } +} diff --git a/ldso/ldso/cris/dl-syscalls.h b/ldso/ldso/cris/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/cris/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h new file mode 100644 index 0000000..c68541d --- /dev/null +++ b/ldso/ldso/cris/dl-sysdep.h @@ -0,0 +1,111 @@ +/* CRIS can never use Elf32_Rel relocations. */ +#define ELF_USES_RELOCA + +#include + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[1] = (unsigned long) MODULE; \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ +} + +/* Defined some magic numbers that this ld.so should accept. */ +#define MAGIC1 EM_CRIS +#undef MAGIC2 +#define ELF_TARGET "CRIS" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry); + +/* 8192 bytes alignment */ +#define PAGE_ALIGN 0xffffe000 +#define ADDR_ALIGN 0x1fff +#define OFFS_ALIGN 0xffffe000 + +/* The union of reloc-type-classes where the reloc TYPE is a member. + + TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a + relocation for a PLT entry, that is, for which a PLT entry should not + be allowed to define the value. The GNU linker for CRIS can merge a + .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT), + so we need to match both these reloc types. + + TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed + to resolve to one of the main executable's symbols, as for a COPY + reloc. */ +#define elf_machine_type_class(type) \ + ((((((type) == R_CRIS_JUMP_SLOT)) \ + || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY)) + +static __inline__ Elf32_Addr +elf_machine_dynamic(void) +{ + /* Don't just set this to an asm variable "r0" since that's not logical + (like, the variable is uninitialized and the register is fixed) and + may make GCC trip over itself doing register allocation. Yes, I'm + paranoid. Why do you ask? */ + Elf32_Addr *got; + + __asm__ ("move.d $r0,%0" : "=rm" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. We do it like + m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry + for it, and peeking into the GOT table, which is set to the link-time + file-relative symbol value (regardless of whether the target is REL or + RELA). We subtract this link-time file-relative value from the "local" + value we calculate from GOT position and GOT offset. FIXME: Perhaps + there's some other symbol we could use, that we don't *have* to force a + GOT entry for. */ + +static __inline__ Elf32_Addr +elf_machine_load_address(void) +{ + Elf32_Addr gotaddr_diff; + +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else + __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" + "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif + return gotaddr_diff; +} + +static __inline__ void +elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (void *)rel_addr; + + --rpnt; + do { + Elf32_Addr *const reloc_addr = + (void *)(load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/cris/elfinterp.c b/ldso/ldso/cris/elfinterp.c new file mode 100644 index 0000000..7c71df8 --- /dev/null +++ b/ldso/ldso/cris/elfinterp.c @@ -0,0 +1,294 @@ +/* + * CRIS ELF shared library loader support. + * + * Program to load an elf binary on a linux system, and run it. + * References to symbols in sharable libraries can be resolved + * by either an ELF sharable library or a linux style of shared + * library. + * + * Copyright (C) 2002-2004, Axis Communications AB + * All rights reserved + * + * Author: Tobias Anderberg, + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Defined in resolve.S. */ +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + int symtab_index; + char *strtab; + char *symname; + char *new_addr; + char *rel_addr; + char **got_addr; + Elf32_Sym *symtab; + ELF_RELOC *this_reloc; + unsigned long instr_addr; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_CRIS_JUMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched: %x ==> %x @ %x", + *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + int symtab_index; + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + /* Pass over to actual relocation function. */ + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n", + _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + if (symtab[symtab_index].st_shndx != SHN_UNDEF && + ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long)tpnt->loadaddr; + } else { + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + } + + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + + symbol_addr += rpnt->r_addend; + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_CRIS_NONE: + break; + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + *reloc_addr = symbol_addr; + break; + case R_CRIS_COPY: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + break; + case R_CRIS_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + /* Don't care about these, just keep the compiler happy. */ + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_CRIS_NONE: + break; + case R_CRIS_JUMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +/* External interface to the generic part of the dynamic linker. */ + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/cris/resolve.S b/ldso/ldso/cris/resolve.S new file mode 100644 index 0000000..9ca27b5 --- /dev/null +++ b/ldso/ldso/cris/resolve.S @@ -0,0 +1,89 @@ +/* + * This function is _not_ called directly. It is jumped to from PLT when + * attempting to use a symbol that has not yet been resolved. The first time a + * jump symbol (such as a function call inside a shared library) is used + * (before it gets resolved) it will jump here. When we get called the stack + * contains reloc_offset and tpnt is in MOF. + * + * We save all the registers, setup R10 and R11 with the right arguments then + * call _dl_linux_resolver(tpnt, reloc_offset). _dl_linux_resolver() figures + * out where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + */ + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + +_dl_linux_resolve: + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 +#ifdef __PIC__ + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 +#else + jsr _dl_linux_resolver +#endif + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ + + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/ldso/ldso/dl-array.c b/ldso/ldso/dl-array.c new file mode 100644 index 0000000..dabb466 --- /dev/null +++ b/ldso/ldso/dl-array.c @@ -0,0 +1,84 @@ +/* vi: set sw=4 ts=4: */ +/* + * This file contains the helper routines to run init and fini functions. + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "ldso.h" + +static void _dl_run_array_forward(unsigned long array, unsigned long size, + DL_LOADADDR_TYPE loadaddr) +{ + if (array != 0) { + unsigned int j; + unsigned int jm; + ElfW(Addr) *addrs; + jm = size / sizeof (ElfW(Addr)); + addrs = (ElfW(Addr) *) DL_RELOC_ADDR(loadaddr, array); + for (j = 0; j < jm; ++j) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void))); + } + } +} + +void _dl_run_init_array(struct elf_resolve *tpnt); +void _dl_run_init_array(struct elf_resolve *tpnt) +{ + _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], + tpnt->dynamic_info[DT_INIT_ARRAYSZ], + tpnt->loadaddr); +} + +void _dl_app_init_array(void); +void _dl_app_init_array(void) +{ + _dl_run_init_array(_dl_loaded_modules); +} + +void _dl_run_fini_array(struct elf_resolve *tpnt); +void _dl_run_fini_array(struct elf_resolve *tpnt) +{ + if (tpnt->dynamic_info[DT_FINI_ARRAY]) { + ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI_ARRAY]); + unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); + while (i-- > 0) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) array[i]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void))); + } + } +} + +void _dl_app_fini_array(void); +void _dl_app_fini_array(void) +{ + _dl_run_fini_array(_dl_loaded_modules); +} + diff --git a/ldso/ldso/dl-debug.c b/ldso/ldso/dl-debug.c new file mode 100644 index 0000000..7ce8bfb --- /dev/null +++ b/ldso/ldso/dl-debug.c @@ -0,0 +1,106 @@ +/* vi: set sw=4 ts=4: */ +/* common debug code for ELF shared library loader + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * Copyright (C) 2002-2004, Axis Communications AB + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +#if defined (__SUPPORT_LD_DEBUG__) + +/* include the arch-specific _dl_reltypes_tab */ +#include "dl-debug.h" + +static const char *_dl_reltypes(int type) +{ + static char buf[50]; + const char *str; + int tabsize; + + tabsize = (int)(sizeof(_dl_reltypes_tab) / sizeof(_dl_reltypes_tab[0])); + + if (type >= tabsize || (str = _dl_reltypes_tab[type]) == NULL) + str = _dl_simple_ltoa(buf, (unsigned long)type); + + return str; +} +static void debug_sym(ElfW(Sym) *symtab, char *strtab, int symtab_index) +{ + if (!_dl_debug_symbols || !symtab_index) + return; + + _dl_dprintf(_dl_debug_file, + "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x", + strtab + symtab[symtab_index].st_name, + symtab[symtab_index].st_value, + symtab[symtab_index].st_size, + symtab[symtab_index].st_info, + symtab[symtab_index].st_other, + symtab[symtab_index].st_shndx); +} + +static void debug_reloc(ElfW(Sym) *symtab, char *strtab, ELF_RELOC *rpnt) +{ + if (!_dl_debug_reloc) + return; + + if (_dl_debug_symbols) { + _dl_dprintf(_dl_debug_file, "\n\t"); + } else { + int symtab_index; + const char *sym; + + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0"; + + _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym); + } + + _dl_dprintf(_dl_debug_file, "%s\toffset=%x", + _dl_reltypes(ELF_R_TYPE(rpnt->r_info)), + rpnt->r_offset); +#ifdef ELF_USES_RELOCA + _dl_dprintf(_dl_debug_file, "\taddend=%x", rpnt->r_addend); +#endif + _dl_dprintf(_dl_debug_file, "\n"); +} + +#else + +#define debug_sym(symtab, strtab, symtab_index) +#define debug_reloc(symtab, strtab, rpnt) + +#endif /* __SUPPORT_LD_DEBUG__ */ diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c new file mode 100644 index 0000000..d22eccc --- /dev/null +++ b/ldso/ldso/dl-elf.c @@ -0,0 +1,956 @@ +/* vi: set sw=4 ts=4: */ +/* + * This file contains the helper routines to load an ELF shared + * library into memory and add the symbol table info to the chain. + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "ldso.h" + +#ifdef __LDSO_CACHE_SUPPORT__ + +static caddr_t _dl_cache_addr = NULL; +static size_t _dl_cache_size = 0; + +int _dl_map_cache(void) +{ + int fd; + struct stat st; + header_t *header; + libentry_t *libent; + int i, strtabsize; + + if (_dl_cache_addr == (caddr_t) - 1) + return -1; + else if (_dl_cache_addr != NULL) + return 0; + + if (_dl_stat(LDSO_CACHE, &st) + || (fd = _dl_open(LDSO_CACHE, O_RDONLY, 0)) < 0) { + _dl_cache_addr = (caddr_t) - 1; /* so we won't try again */ + return -1; + } + + _dl_cache_size = st.st_size; + _dl_cache_addr = _dl_mmap(0, _dl_cache_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0); + _dl_close(fd); + if (_dl_mmap_check_error(_dl_cache_addr)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_CACHE); + return -1; + } + + header = (header_t *) _dl_cache_addr; + + if (_dl_cache_size < sizeof(header_t) || + _dl_memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN) + || _dl_memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN) + || _dl_cache_size < + (sizeof(header_t) + header->nlibs * sizeof(libentry_t)) + || _dl_cache_addr[_dl_cache_size - 1] != '\0') + { + _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, + LDSO_CACHE); + goto fail; + } + + strtabsize = _dl_cache_size - sizeof(header_t) - + header->nlibs * sizeof(libentry_t); + libent = (libentry_t *) & header[1]; + + for (i = 0; i < header->nlibs; i++) { + if (libent[i].sooffset >= strtabsize || + libent[i].liboffset >= strtabsize) + { + _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, LDSO_CACHE); + goto fail; + } + } + + return 0; + +fail: + _dl_munmap(_dl_cache_addr, _dl_cache_size); + _dl_cache_addr = (caddr_t) - 1; + return -1; +} + +int _dl_unmap_cache(void) +{ + if (_dl_cache_addr == NULL || _dl_cache_addr == (caddr_t) - 1) + return -1; + +#if 1 + _dl_munmap(_dl_cache_addr, _dl_cache_size); + _dl_cache_addr = NULL; +#endif + + return 0; +} +#endif + + +void +_dl_protect_relro (struct elf_resolve *l) +{ + ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr); + ElfW(Addr) start = (base & ~(_dl_pagesize - 1)); + ElfW(Addr) end = ((base + l->relro_size) & ~(_dl_pagesize - 1)); + _dl_if_debug_dprint("RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end); + if (start != end && + _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) { + _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname); + _dl_exit(0); + } +} + +/* This function's behavior must exactly match that + * in uClibc/ldso/util/ldd.c */ +static struct elf_resolve * +search_for_named_library(const char *name, int secure, const char *path_list, + struct dyn_elf **rpnt) +{ + char *path, *path_n, *mylibname; + struct elf_resolve *tpnt; + int done; + + if (path_list==NULL) + return NULL; + + /* We need a writable copy of this string, but we don't + * need this allocated permanently since we don't want + * to leak memory, so use alloca to put path on the stack */ + done = _dl_strlen(path_list); + path = alloca(done + 1); + + /* another bit of local storage */ + mylibname = alloca(2050); + + _dl_memcpy(path, path_list, done+1); + + /* Unlike ldd.c, don't bother to eliminate double //s */ + + /* Replace colons with zeros in path_list */ + /* : at the beginning or end of path maps to CWD */ + /* :: anywhere maps CWD */ + /* "" maps to CWD */ + done = 0; + path_n = path; + do { + if (*path == 0) { + *path = ':'; + done = 1; + } + if (*path == ':') { + *path = 0; + if (*path_n) + _dl_strcpy(mylibname, path_n); + else + _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */ + _dl_strcat(mylibname, "/"); + _dl_strcat(mylibname, name); + if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) + return tpnt; + path_n = path+1; + } + path++; + } while (!done); + return NULL; +} + +/* Used to return error codes back to dlopen et. al. */ +unsigned long _dl_error_number; +unsigned long _dl_internal_error_number; + +struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, + struct elf_resolve *tpnt, char *full_libname, int __attribute__((unused)) trace_loaded_objects) +{ + char *pnt; + struct elf_resolve *tpnt1; + char *libname; + + _dl_internal_error_number = 0; + libname = full_libname; + + /* quick hack to ensure mylibname buffer doesn't overflow. don't + allow full_libname or any directory to be longer than 1024. */ + if (_dl_strlen(full_libname) > 1024) + goto goof; + + /* Skip over any initial initial './' and '/' stuff to + * get the short form libname with no path garbage */ + pnt = _dl_strrchr(libname, '/'); + if (pnt) { + libname = pnt + 1; + } + + _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); + /* If the filename has any '/', try it straight and leave it at that. + For IBCS2 compatibility under linux, we substitute the string + /usr/i486-sysv4/lib for /usr/lib in library names. */ + + if (libname != full_libname) { + _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); + tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); + if (tpnt1) { + return tpnt1; + } + } + + /* + * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or + * the default path of /usr/lib. Check in rpath directories. + */ +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; + } +#endif + + /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ + if (_dl_library_path) { + _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) + { + return tpnt1; + } + } + + /* + * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH. + */ +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; + } +#endif + + /* + * Where should the cache be searched? There is no such concept in the + * ABI, so we have some flexibility here. For now, search it before + * the hard coded paths that follow (i.e before /lib and /usr/lib). + */ +#ifdef __LDSO_CACHE_SUPPORT__ + if (_dl_cache_addr != NULL && _dl_cache_addr != (caddr_t) - 1) { + int i; + header_t *header = (header_t *) _dl_cache_addr; + libentry_t *libent = (libentry_t *) & header[1]; + char *strs = (char *) &libent[header->nlibs]; + + _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); + for (i = 0; i < header->nlibs; i++) { + if ((libent[i].flags == LIB_ELF || + libent[i].flags == LIB_ELF_LIBC0 || + libent[i].flags == LIB_ELF_LIBC5) && + _dl_strcmp(libname, strs + libent[i].sooffset) == 0 && + (tpnt1 = _dl_load_elf_shared_library(secure, + rpnt, strs + libent[i].liboffset))) + return tpnt1; + } + } +#endif + + /* Look for libraries wherever the shared library loader + * was installed */ + _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); + if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) + { + return tpnt1; + } + + + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/util/ldd.c */ + _dl_if_debug_dprint("\tsearching full lib path list\n"); + if ((tpnt1 = search_for_named_library(libname, secure, + UCLIBC_RUNTIME_PREFIX "lib:" + UCLIBC_RUNTIME_PREFIX "usr/lib" +#ifndef __LDSO_CACHE_SUPPORT__ + ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" +#endif + , rpnt) + ) != NULL) + { + return tpnt1; + } + +goof: + /* Well, we shot our wad on that one. All we can do now is punt */ + if (_dl_internal_error_number) + _dl_error_number = _dl_internal_error_number; + else + _dl_error_number = LD_ERROR_NOFILE; + _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname); + return NULL; +} + + +/* + * Read one ELF library into memory, mmap it into the correct locations and + * add the symbol info to the symbol chain. Perform any relocations that + * are required. + */ + +struct elf_resolve *_dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname) +{ + ElfW(Ehdr) *epnt; + unsigned long dynamic_addr = 0; + ElfW(Dyn) *dpnt; + struct elf_resolve *tpnt; + ElfW(Phdr) *ppnt; + char *status, *header; + unsigned long dynamic_info[DYNAMIC_SIZE]; + unsigned long *lpnt; + unsigned long libaddr; + unsigned long minvma = 0xffffffff, maxvma = 0; + int i, flags, piclib, infile; + ElfW(Addr) relro_addr = 0; + size_t relro_size = 0; + struct stat st; + DL_LOADADDR_TYPE lib_loadaddr; + DL_INIT_LOADADDR_EXTRA_DECLS + + libaddr = 0; + infile = _dl_open(libname, O_RDONLY, 0); + if (infile < 0) { + _dl_internal_error_number = LD_ERROR_NOFILE; + return NULL; + } + + if (_dl_fstat(infile, &st) < 0) { + _dl_internal_error_number = LD_ERROR_NOFILE; + _dl_close(infile); + return NULL; + } + /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), + we don't load the library if it isn't setuid. */ + if (secure) + if (!(st.st_mode & S_ISUID)) { + _dl_close(infile); + return NULL; + } + + /* Check if file is already loaded */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) { + /* Already loaded */ + tpnt->usage_count++; + _dl_close(infile); + return tpnt; + } + } + header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(header)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_close(infile); + return NULL; + } + + _dl_read(infile, header, _dl_pagesize); + epnt = (ElfW(Ehdr) *) (intptr_t) header; + if (epnt->e_ident[0] != 0x7f || + epnt->e_ident[1] != 'E' || + epnt->e_ident[2] != 'L' || + epnt->e_ident[3] != 'F') + { + _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname, + libname); + _dl_internal_error_number = LD_ERROR_NOTELF; + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1 +#ifdef MAGIC2 + && epnt->e_machine != MAGIC2 +#endif + )) + { + _dl_internal_error_number = + (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC); + _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET + "\n", _dl_progname, libname); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + + piclib = 1; + for (i = 0; i < epnt->e_phnum; i++) { + + if (ppnt->p_type == PT_DYNAMIC) { + if (dynamic_addr) + _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n", + _dl_progname, libname); + dynamic_addr = ppnt->p_vaddr; + } + + if (ppnt->p_type == PT_LOAD) { + /* See if this is a PIC library. */ + if (i == 0 && ppnt->p_vaddr > 0x1000000) { + piclib = 0; + minvma = ppnt->p_vaddr; + } + if (piclib && ppnt->p_vaddr < minvma) { + minvma = ppnt->p_vaddr; + } + if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) { + maxvma = ppnt->p_vaddr + ppnt->p_memsz; + } + } + ppnt++; + } + + DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname); + + maxvma = (maxvma + ADDR_ALIGN) & ~ADDR_ALIGN; + minvma = minvma & ~0xffffU; + + flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ; + if (!piclib) + flags |= MAP_FIXED; + + if (piclib == 0 || piclib == 1) { + status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), + maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(status)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + libaddr = (unsigned long) status; + flags |= MAP_FIXED; + } + + /* Get the memory to store the library */ + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + + DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum); + + for (i = 0; i < epnt->e_phnum; i++) { + if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) { + char *addr; + + addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags); + if (addr == NULL) + goto cant_map; + + DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt); + ppnt++; + continue; + } + if (ppnt->p_type == PT_GNU_RELRO) { + relro_addr = ppnt->p_vaddr; + relro_size = ppnt->p_memsz; + } + if (ppnt->p_type == PT_LOAD) { + char *tryaddr; + ssize_t size; + + /* See if this is a PIC library. */ + if (i == 0 && ppnt->p_vaddr > 0x1000000) { + piclib = 0; + /* flags |= MAP_FIXED; */ + } + + if (ppnt->p_flags & PF_W) { + unsigned long map_size; + char *cpnt; + char *piclib2map = 0; + + if (piclib == 2 && + /* We might be able to avoid this + call if memsz doesn't require + an additional page, but this + would require mmap to always + return page-aligned addresses + and a whole number of pages + allocated. Unfortunately on + uClinux may return misaligned + addresses and may allocate + partial pages, so we may end up + doing unnecessary mmap calls. + + This is what we could do if we + knew mmap would always return + aligned pages: + + ((ppnt->p_vaddr + ppnt->p_filesz + + ADDR_ALIGN) + & PAGE_ALIGN) + < ppnt->p_vaddr + ppnt->p_memsz) + + Instead, we have to do this: */ + ppnt->p_filesz < ppnt->p_memsz) + { + piclib2map = (char *) + _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + + ppnt->p_memsz, + LXFLAGS(ppnt->p_flags), + flags | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(piclib2map)) + goto cant_map; + DL_INIT_LOADADDR_HDR + (lib_loadaddr, piclib2map + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + + tryaddr = piclib == 2 ? piclib2map + : ((char*) (piclib ? libaddr : 0) + + (ppnt->p_vaddr & PAGE_ALIGN)); + + size = (ppnt->p_vaddr & ADDR_ALIGN) + + ppnt->p_filesz; + + /* For !MMU, mmap to fixed address will fail. + So instead of desperately call mmap and fail, + we set status to MAP_FAILED to save a call + to mmap (). */ +#ifndef __ARCH_USE_MMU__ + if (piclib2map == 0) +#endif + status = (char *) _dl_mmap + (tryaddr, size, LXFLAGS(ppnt->p_flags), + flags | (piclib2map ? MAP_FIXED : 0), + infile, ppnt->p_offset & OFFS_ALIGN); +#ifndef __ARCH_USE_MMU__ + else + status = MAP_FAILED; +#endif +#ifdef _DL_PREAD + if (_dl_mmap_check_error(status) && piclib2map + && (_DL_PREAD (infile, tryaddr, size, + ppnt->p_offset & OFFS_ALIGN) + == size)) + status = tryaddr; +#endif + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) { + cant_map: + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + if (! piclib2map) { + DL_INIT_LOADADDR_HDR + (lib_loadaddr, status + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + /* Now we want to allocate and + zero-out any data from the end of + the region we mapped in from the + file (filesz) to the end of the + loadable segment (memsz). We may + need additional pages for memsz, + that we map in below, and we can + count on the kernel to zero them + out, but we have to zero out stuff + in the last page that we mapped in + from the file. However, we can't + assume to have actually obtained + full pages from the kernel, since + we didn't ask for them, and uClibc + may not give us full pages for + small allocations. So only zero + out up to memsz or the end of the + page, whichever comes first. */ + + /* CPNT is the beginning of the memsz + portion not backed by filesz. */ + cpnt = (char *) (status + size); + + /* MAP_SIZE is the address of the + beginning of the next page. */ + map_size = (ppnt->p_vaddr + ppnt->p_filesz + + ADDR_ALIGN) & PAGE_ALIGN; + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + _dl_memset (cpnt, 0, + MIN (map_size + - (ppnt->p_vaddr + + ppnt->p_filesz), + ppnt->p_memsz + - ppnt->p_filesz)); + + if (map_size < ppnt->p_vaddr + ppnt->p_memsz + && !piclib2map) { + tryaddr = map_size + (char*)(piclib ? libaddr : 0); + status = (char *) _dl_mmap(tryaddr, + ppnt->p_vaddr + ppnt->p_memsz - map_size, + LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (_dl_mmap_check_error(status) + || tryaddr != status) + goto cant_map; + } + } else { + tryaddr = (piclib == 2 ? 0 + : (char *) (ppnt->p_vaddr & PAGE_ALIGN) + + (piclib ? libaddr : 0)); + size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz; + status = (char *) _dl_mmap + (tryaddr, size, LXFLAGS(ppnt->p_flags), + flags | (piclib == 2 ? MAP_EXECUTABLE + | MAP_DENYWRITE : 0), + infile, ppnt->p_offset & OFFS_ALIGN); + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) + goto cant_map; + DL_INIT_LOADADDR_HDR + (lib_loadaddr, status + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + + /* if (libaddr == 0 && piclib) { + libaddr = (unsigned long) status; + flags |= MAP_FIXED; + } */ + } + ppnt++; + } + _dl_close(infile); + + /* For a non-PIC library, the addresses are all absolute */ + if (piclib) { + dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr); + } + + /* + * OK, the ELF library is now loaded into VM in the correct locations + * The next step is to go through and do the dynamic linking (if needed). + */ + + /* Start by scanning the dynamic section to get all of the pointers */ + + if (!dynamic_addr) { + _dl_internal_error_number = LD_ERROR_NODYNAMIC; + _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n", + _dl_progname, libname); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + dpnt = (ElfW(Dyn) *) dynamic_addr; + _dl_memset(dynamic_info, 0, sizeof(dynamic_info)); + _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr); + /* If the TEXTREL is set, this means that we need to make the pages + writable before we perform relocations. Do this now. They get set + back again later. */ + + if (dynamic_info[DT_TEXTREL]) { +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + for (i = 0; i < epnt->e_phnum; i++, ppnt++) { + if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) + _dl_mprotect((void *) ((piclib ? libaddr : 0) + + (ppnt->p_vaddr & PAGE_ALIGN)), + (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, + PROT_READ | PROT_WRITE | PROT_EXEC); + } +#else + _dl_dprintf(_dl_debug_file, "Can't modify %s's text section. Use GCC option -fPIC for shared objects, please.\n",libname); + _dl_exit(1); +#endif + } + + tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info, + dynamic_addr, 0); + tpnt->relro_addr = relro_addr; + tpnt->relro_size = relro_size; + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff); + tpnt->n_phent = epnt->e_phnum; + + /* + * Add this object into the symbol chain + */ + if (*rpnt) { + (*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf)); + (*rpnt)->next->prev = (*rpnt); + *rpnt = (*rpnt)->next; + } +#ifndef SHARED + /* When statically linked, the first time we dlopen a DSO + * the *rpnt is NULL, so we need to allocate memory for it, + * and initialize the _dl_symbol_table. + */ + else { + *rpnt = _dl_symbol_tables = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset(*rpnt, 0, sizeof(struct dyn_elf)); + } +#endif + (*rpnt)->dyn = tpnt; + tpnt->symbol_scope = _dl_symbol_tables; + tpnt->usage_count++; + tpnt->libtype = elf_lib; + + /* + * OK, the next thing we need to do is to insert the dynamic linker into + * the proper entry in the GOT so that the PLT symbols can be properly + * resolved. + */ + + lpnt = (unsigned long *) dynamic_info[DT_PLTGOT]; + + if (lpnt) { + lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]); + INIT_GOT(lpnt, tpnt); + } + + _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname); + _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr)); + _dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n", + DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent); + + _dl_munmap(header, _dl_pagesize); + + return tpnt; +} + +/* now_flag must be RTLD_NOW or zero */ +int _dl_fixup(struct dyn_elf *rpnt, int now_flag) +{ + int goof = 0; + struct elf_resolve *tpnt; + ElfW(Word) reloc_size, relative_count; + ElfW(Addr) reloc_addr; + + if (rpnt->next) + goof = _dl_fixup(rpnt->next, now_flag); + if (goof) + return goof; + tpnt = rpnt->dyn; + + if (!(tpnt->init_flag & RELOCS_DONE)) + _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname); + + if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) { + _dl_if_debug_dprint("%s: can't handle %s relocation records\n", + _dl_progname, UNSUPPORTED_RELOC_STR); + goof++; + return goof; + } + + reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]; +/* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its + range. Note that according to the ELF spec, this is completely legal! */ +#ifdef ELF_MACHINE_PLTREL_OVERLAP + reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ]; +#endif + if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] && + !(tpnt->init_flag & RELOCS_DONE)) { + reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; + relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */ + reloc_size -= relative_count * sizeof(ELF_RELOC); + elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count); + reloc_addr += relative_count * sizeof(ELF_RELOC); + } + goof += _dl_parse_relocation_information(rpnt, + reloc_addr, + reloc_size); + tpnt->init_flag |= RELOCS_DONE; + } + if (tpnt->dynamic_info[DT_BIND_NOW]) + now_flag = RTLD_NOW; + if (tpnt->dynamic_info[DT_JMPREL] && + (!(tpnt->init_flag & JMP_RELOCS_DONE) || + (now_flag && !(tpnt->rtld_flags & now_flag)))) { + tpnt->rtld_flags |= now_flag; + if (!(tpnt->rtld_flags & RTLD_NOW)) { + _dl_parse_lazy_relocation_information(rpnt, + tpnt->dynamic_info[DT_JMPREL], + tpnt->dynamic_info [DT_PLTRELSZ]); + } else { + goof += _dl_parse_relocation_information(rpnt, + tpnt->dynamic_info[DT_JMPREL], + tpnt->dynamic_info[DT_PLTRELSZ]); + } + tpnt->init_flag |= JMP_RELOCS_DONE; + } + return goof; +} + +/* Minimal printf which handles only %s, %d, and %x */ +void _dl_dprintf(int fd, const char *fmt, ...) +{ +#if __WORDSIZE > 32 + long int num; +#else + int num; +#endif + va_list args; + char *start, *ptr, *string; + static char *buf; + + if (!fmt) + return; + + buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(buf)) { + _dl_write(fd, "mmap of a spare page failed!\n", 29); + _dl_exit(20); + } + + start = ptr = buf; + + if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) { + _dl_write(fd, "overflow\n", 11); + _dl_exit(20); + } + + _dl_strcpy(buf, fmt); + va_start(args, fmt); + + while (start) { + while (*ptr != '%' && *ptr) { + ptr++; + } + + if (*ptr == '%') { + *ptr++ = '\0'; + _dl_write(fd, start, _dl_strlen(start)); + + switch (*ptr++) { + case 's': + string = va_arg(args, char *); + + if (!string) + _dl_write(fd, "(null)", 6); + else + _dl_write(fd, string, _dl_strlen(string)); + break; + + case 'i': + case 'd': + { + char tmp[22]; +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif + string = _dl_simple_ltoa(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + case 'x': + case 'X': + { + char tmp[22]; +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif + string = _dl_simple_ltoahex(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + default: + _dl_write(fd, "(null)", 6); + break; + } + + start = ptr; + } else { + _dl_write(fd, start, _dl_strlen(start)); + start = NULL; + } + } + _dl_munmap(buf, _dl_pagesize); + return; +} + +char *_dl_strdup(const char *string) +{ + char *retval; + int len; + + len = _dl_strlen(string); + retval = _dl_malloc(len + 1); + _dl_strcpy(retval, string); + return retval; +} + +void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off) +{ + __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off); +} + +/* we want this in ldso.so and libdl.a but nowhere else */ +#ifdef __USE_GNU +#if defined IS_IN_rtld || (defined IS_IN_libdl && ! defined SHARED) +extern __typeof(dl_iterate_phdr) __dl_iterate_phdr; +int +__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data) +{ + struct elf_resolve *l; + struct dl_phdr_info info; + int ret = 0; + + for (l = _dl_loaded_modules; l != NULL; l = l->next) { + info.dlpi_addr = l->loadaddr; + info.dlpi_name = l->libname; + info.dlpi_phdr = l->ppnt; + info.dlpi_phnum = l->n_phent; + ret = callback (&info, sizeof (struct dl_phdr_info), data); + if (ret) + break; + } + return ret; +} +strong_alias(__dl_iterate_phdr, dl_iterate_phdr) +#endif +#endif diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c new file mode 100644 index 0000000..2a39335 --- /dev/null +++ b/ldso/ldso/dl-hash.c @@ -0,0 +1,367 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2004 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + + +/* Various symbol table handling functions, including symbol lookup */ + +/* + * This is the start of the linked list that describes all of the files present + * in the system with pointers to all of the symbol, string, and hash tables, + * as well as all of the other good stuff in the binary. + */ +struct elf_resolve *_dl_loaded_modules = NULL; + +/* + * This is the list of modules that are loaded when the image is first + * started. As we add more via dlopen, they get added into other + * chains. + */ +struct dyn_elf *_dl_symbol_tables = NULL; + +/* + * This is the list of modules that are loaded via dlopen. We may need + * to search these for RTLD_GLOBAL files. + */ +struct dyn_elf *_dl_handles = NULL; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ +/* This is the new hash function that is used by the ELF linker to generate the + * GNU hash table that each executable and library will have if --hash-style=[gnu,both] + * is passed to the linker. We need it to decode the GNU hash table. */ +static __inline__ Elf_Symndx _dl_gnu_hash (const unsigned char *name) +{ + unsigned long h = 5381; + unsigned char c; + for (c = *name; c != '\0'; c = *++name) + h = h * 33 + c; + return h & 0xffffffff; +} +#endif + +/* This is the hash function that is used by the ELF linker to generate the + * hash table that each executable and library is required to have. We need + * it to decode the hash table. */ +static __inline__ Elf_Symndx _dl_elf_hash(const unsigned char *name) +{ + unsigned long hash=0; + unsigned long tmp; + + while (*name) { + hash = (hash << 4) + *name++; + tmp = hash & 0xf0000000; + /* The algorithm specified in the ELF ABI is as follows: + if (tmp != 0) + hash ^= tmp >> 24; + hash &= ~tmp; + But the following is equivalent and a lot + faster, especially on modern processors. */ + hash ^= tmp; + hash ^= tmp >> 24; + } + return hash; +} + +/* + * We call this function when we have just read an ELF library or executable. + * We add the relevant info to the symbol chain, so that we can resolve all + * externals properly. + */ +struct elf_resolve *_dl_add_elf_hash_table(const char *libname, + DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, + attribute_unused unsigned long dynamic_size) +{ + Elf_Symndx *hash_addr; + struct elf_resolve *tpnt; + int i; + + if (!_dl_loaded_modules) { + tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + } else { + tpnt = _dl_loaded_modules; + while (tpnt->next) + tpnt = tpnt->next; + tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); + _dl_memset(tpnt->next, 0, sizeof(struct elf_resolve)); + tpnt->next->prev = tpnt; + tpnt = tpnt->next; + } + + tpnt->next = NULL; + tpnt->init_flag = 0; + tpnt->libname = _dl_strdup(libname); + tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr; + tpnt->libtype = loaded_file; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (dynamic_info[DT_GNU_HASH_IDX] != 0) { + Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX]; + + tpnt->nbucket = *hash32++; + Elf32_Word symbias = *hash32++; + Elf32_Word bitmask_nwords = *hash32++; + /* Must be a power of two. */ + _dl_assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); + tpnt->l_gnu_bitmask_idxbits = bitmask_nwords - 1; + tpnt->l_gnu_shift = *hash32++; + + tpnt->l_gnu_bitmask = (ElfW(Addr) *) hash32; + hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; + + tpnt->l_gnu_buckets = hash32; + hash32 += tpnt->nbucket; + tpnt->l_gnu_chain_zero = hash32 - symbias; + } else + /* Fall using old SysV hash table if GNU hash is not present */ +#endif + + if (dynamic_info[DT_HASH] != 0) { + hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH]; + tpnt->nbucket = *hash_addr++; + tpnt->nchain = *hash_addr++; + tpnt->elf_buckets = hash_addr; + hash_addr += tpnt->nbucket; + tpnt->chains = hash_addr; + } + tpnt->loadaddr = loadaddr; + tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0); + for (i = 0; i < DYNAMIC_SIZE; i++) + tpnt->dynamic_info[i] = dynamic_info[i]; + return tpnt; +} + + +/* Routine to check whether the symbol matches. */ +static __attribute_noinline__ const ElfW(Sym) * +check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class) +{ + if (type_class & (sym->st_shndx == SHN_UNDEF)) + /* undefined symbol itself */ + return NULL; + + if (sym->st_value == 0) + /* No value */ + return NULL; + + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC + && ELF_ST_TYPE(sym->st_info) != STT_COMMON) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC + * and STT_COMMON entries since these are no + * code/data definitions + */ + return NULL; + + if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0) + return NULL; + + /* This is the matching symbol */ + return sym; +} + + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + +static __always_inline const ElfW(Sym) * +_dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, + const char* undef_name, int type_class) +{ + Elf_Symndx symidx; + const ElfW(Sym) *sym; + char *strtab; + + const ElfW(Addr) *bitmask = tpnt->l_gnu_bitmask; + + ElfW(Addr) bitmask_word = bitmask[(hash / __ELF_NATIVE_CLASS) & tpnt->l_gnu_bitmask_idxbits]; + + unsigned int hashbit1 = hash & (__ELF_NATIVE_CLASS - 1); + unsigned int hashbit2 = ((hash >> tpnt->l_gnu_shift) & (__ELF_NATIVE_CLASS - 1)); + _dl_assert (bitmask != NULL); + + if (unlikely((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1)) { + unsigned long rem; + Elf32_Word bucket; + + do_rem (rem, hash, tpnt->nbucket); + bucket = tpnt->l_gnu_buckets[rem]; + + if (bucket != 0) { + const Elf32_Word *hasharr = &tpnt->l_gnu_chain_zero[bucket]; + do { + if (((*hasharr ^ hash) >> 1) == 0) { + symidx = hasharr - tpnt->l_gnu_chain_zero; + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + sym = check_match (&symtab[symidx], strtab, undef_name, type_class); + if (sym != NULL) + return sym; + } + } while ((*hasharr++ & 1u) == 0); + } + } + /* No symbol found. */ + return NULL; +} +#endif + +static __always_inline const ElfW(Sym) * +_dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, const char* undef_name, int type_class) +{ + unsigned long hn; + char *strtab; + const ElfW(Sym) *sym; + Elf_Symndx symidx; + + /* Avoid calling .urem here. */ + do_rem(hn, hash, tpnt->nbucket); + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + + _dl_assert(tpnt->elf_buckets != NULL); + + for (symidx = tpnt->elf_buckets[hn]; symidx != STN_UNDEF; symidx = tpnt->chains[symidx]) { + sym = check_match (&symtab[symidx], strtab, undef_name, type_class); + if (sym != NULL) + /* At this point the symbol is that we are looking for */ + return sym; + } + /* No symbol found into the current module*/ + return NULL; +} + +/* + * This function resolves externals, and this is either called when we process + * relocations or when we call an entry in the PLT table for the first time. + */ +char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, + struct elf_resolve *mytpnt, int type_class +#ifdef __FDPIC__ + , struct elf_resolve **tpntp +#endif + ) +{ + struct elf_resolve *tpnt = NULL; + ElfW(Sym) *symtab; + + unsigned long elf_hash_number = 0xffffffff; + const ElfW(Sym) *sym = NULL; + + const ElfW(Sym) *weak_sym = 0; + struct elf_resolve *weak_tpnt = 0; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); +#endif + + for (; rpnt; rpnt = rpnt->next) { + tpnt = rpnt->dyn; + + if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { + if (mytpnt == tpnt) + ; + else { + struct init_fini_list *tmp; + + for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { + if (tmp->tpnt == tpnt) + break; + } + if (!tmp) + continue; + } + } + /* Don't search the executable when resolving a copy reloc. */ + if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) + continue; + + /* If the hash table is empty there is nothing to do here. */ + if (tpnt->nbucket == 0) + continue; + + symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + /* Prefer GNU hash style, if any */ + if (tpnt->l_gnu_bitmask) { + sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); + if (sym != NULL) + /* If sym has been found, do not search further */ + break; + } else { +#endif + /* Use the old SysV-style hash table */ + + /* Calculate the old sysv hash number only once */ + if (elf_hash_number == 0xffffffff) + elf_hash_number = _dl_elf_hash((const unsigned char *)name); + + sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); + if (sym != NULL) + break; +#ifdef __LDSO_GNU_HASH_SUPPORT__ + } +#endif + } /* end of for (; rpnt; rpnt = rpnt->next) { */ + + if (sym) { + /* At this point we have found the requested symbol, do binding */ + switch (ELF_ST_BIND(sym->st_info)) { + case STB_WEAK: +#if 0 +/* Perhaps we should support old style weak symbol handling + * per what glibc does when you export LD_DYNAMIC_WEAK */ + if (!weak_sym) { + weak_tpnt = tpnt; + weak_sym = sym; + } + break; +#endif + case STB_GLOBAL: +#ifdef __FDPIC__ + if (tpntp) + *tpntp = tpnt; +#endif + return (char *) DL_FIND_HASH_VALUE (tpnt, type_class, sym); + default: /* Local symbols not handled here */ + break; + } + } + if (weak_sym) { +#ifdef __FDPIC__ + if (tpntp) + *tpntp = weak_tpnt; +#endif + return (char *) DL_FIND_HASH_VALUE (weak_tpnt, type_class, weak_sym); + } +#ifdef __FDPIC__ + if (tpntp) + *tpntp = NULL; +#endif + return NULL; +} diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c new file mode 100644 index 0000000..42fb44e --- /dev/null +++ b/ldso/ldso/dl-startup.c @@ -0,0 +1,325 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The main trick with this program is that initially, we ourselves are not + * dynamicly linked. This means that we cannot access any global variables or + * call any functions. No globals initially, since the Global Offset Table + * (GOT) is initialized by the linker assuming a virtual address of 0, and no + * function calls initially since the Procedure Linkage Table (PLT) is not yet + * initialized. + * + * There are additional initial restrictions - we cannot use large switch + * statements, since the compiler generates tables of addresses and jumps + * through them. We cannot use normal syscall stubs, because these all + * reference the errno global variable which is not yet initialized. We _can_ + * use all of the local stack variables that we want. We _can_ use inline + * functions, because these do not transfer control to a new address, but they + * must be static so that they are not exported from the modules. + * + * Life is further complicated by the fact that initially we do not want to do + * a complete dynamic linking. We want to allow the user to supply new + * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD). So + * initially, we only perform relocations for variables that start with "_dl_" + * since ANSI specifies that the user is not supposed to redefine any of these + * variables. + * + * Fortunately, the linker itself leaves a few clues lying around, and when the + * kernel starts the image, there are a few further clues. First of all, there + * is Auxiliary Vector Table information sitting on which is provided to us by + * the kernel, and which includes information about the load address that the + * program interpreter was loaded at, the number of sections, the address the + * application was loaded at and so forth. Here this information is stored in + * the array auxvt. For details see linux/fs/binfmt_elf.c where it calls + * NEW_AUX_ENT() a bunch of time.... + * + * Next, we need to find the GOT. On most arches there is a register pointing + * to the GOT, but just in case (and for new ports) I've added some (slow) C + * code to locate the GOT for you. + * + * This code was originally written for SVr4, and there the kernel would load + * all text pages R/O, so they needed to call mprotect a zillion times to mark + * all text pages as writable so dynamic linking would succeed. Then when they + * were done, they would change the protections for all the pages back again. + * Well, under Linux everything is loaded writable (since Linux does copy on + * write anyways) so all the mprotect stuff has been disabled. + * + * Initially, we do not have access to _dl_malloc since we can't yet make + * function calls, so we mmap one page to use as scratch space. Later on, when + * we can call _dl_malloc we reuse this this memory. This is also beneficial, + * since we do not want to use the same memory pool as malloc anyway - esp if + * the user redefines malloc to do something funky. + * + * Our first task is to perform a minimal linking so that we can call other + * portions of the dynamic linker. Once we have done this, we then build the + * list of modules that the application requires, using LD_LIBRARY_PATH if this + * is not a suid program (/usr/lib otherwise). Once this is done, we can do + * the dynamic linking as required, and we must omit the things we did to get + * the dynamic linker up and running in the first place. After we have done + * this, we just have a few housekeeping chores and we can transfer control to + * the user's application. + */ + +#include "ldso.h" + +/* Pull in all the arch specific stuff */ +#include "dl-startup.h" + +/* Static declarations */ +int (*_dl_elf_main) (int, char **, char **); + +static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */ +strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */ + +/* When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + auxvt[0...N] Auxiliary Vector Table elements (mixed types) +*/ +DL_START(unsigned long args) +{ + unsigned int argc; + char **argv, **envp; + DL_LOADADDR_TYPE load_addr; + ElfW(Addr) got; + unsigned long *aux_dat; + ElfW(Ehdr) *header; + struct elf_resolve tpnt_tmp; + struct elf_resolve *tpnt = &tpnt_tmp; + ElfW(auxv_t) auxvt[AT_EGID + 1]; + ElfW(Dyn) *dpnt; + + /* WARNING! -- we cannot make _any_ funtion calls until we have + * taken care of fixing up our own relocations. Making static + * inline calls is ok, but _no_ function calls. Not yet + * anyways. */ + + /* First obtain the information on the stack that tells us more about + what binary is loaded, where it is loaded, etc, etc */ + GET_ARGV(aux_dat, args); + argc = *(aux_dat - 1); + argv = (char **) aux_dat; + aux_dat += argc; /* Skip over the argv pointers */ + aux_dat++; /* Skip over NULL at end of argv */ + envp = (char **) aux_dat; +#ifndef NO_EARLY_SEND_STDERR + SEND_EARLY_STDERR_DEBUG("argc="); + SEND_NUMBER_STDERR_DEBUG(argc, 0); + SEND_EARLY_STDERR_DEBUG(" argv="); + SEND_ADDRESS_STDERR_DEBUG(argv, 0); + SEND_EARLY_STDERR_DEBUG(" envp="); + SEND_ADDRESS_STDERR_DEBUG(envp, 1); +#endif + while (*aux_dat) + aux_dat++; /* Skip over the envp pointers */ + aux_dat++; /* Skip over NULL at end of envp */ + + /* Place -1 here as a checkpoint. We later check if it was changed + * when we read in the auxvt */ + auxvt[AT_UID].a_type = -1; + + /* The junk on the stack immediately following the environment is + * the Auxiliary Vector Table. Read out the elements of the auxvt, + * sort and store them in auxvt for later use. */ + while (*aux_dat) { + ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; + + if (auxv_entry->a_type <= AT_EGID) { + _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); + } + aux_dat += 2; + } + + /* locate the ELF header. We need this done as soon as possible + * (esp since SEND_STDERR() needs this on some platforms... */ + if (!auxvt[AT_BASE].a_un.a_val) + auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); + DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val); + header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + + /* Check the ELF header to make sure everything looks ok. */ + if (!header || header->e_ident[EI_CLASS] != ELF_CLASS || + header->e_ident[EI_VERSION] != EV_CURRENT + /* Do not use an inline _dl_strncmp here or some arches + * will blow chunks, i.e. those that need to relocate all + * string constants... */ + || header->e_ident[EI_MAG0] != ELFMAG0 + || header->e_ident[EI_MAG1] != ELFMAG1 + || header->e_ident[EI_MAG2] != ELFMAG2 + || header->e_ident[EI_MAG3] != ELFMAG3) + { + SEND_EARLY_STDERR("Invalid ELF header\n"); + _dl_exit(0); + } + SEND_EARLY_STDERR_DEBUG("ELF header="); + SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1); + + /* Locate the global offset table. Since this code must be PIC + * we can take advantage of the magic offset register, if we + * happen to know what that is for this architecture. If not, + * we can always read stuff out of the ELF file to find it... */ + DL_BOOT_COMPUTE_GOT(got); + + /* Now, finally, fix up the location of the dynamic stuff */ + DL_BOOT_COMPUTE_DYN (dpnt, got, load_addr); + + SEND_EARLY_STDERR_DEBUG("First Dynamic section entry="); + SEND_ADDRESS_STDERR_DEBUG(dpnt, 1); + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + tpnt->loadaddr = load_addr; + /* OK, that was easy. Next scan the DYNAMIC section of the image. + We are only doing ourself right now - we will have to do the rest later */ + SEND_EARLY_STDERR_DEBUG("Scanning DYNAMIC section\n"); + tpnt->dynamic_addr = dpnt; +#if defined(NO_FUNCS_BEFORE_BOOTSTRAP) + /* Some architectures cannot call functions here, must inline */ + __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); +#else + _dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); +#endif + + SEND_EARLY_STDERR_DEBUG("Done scanning DYNAMIC section\n"); + +#if defined(PERFORM_BOOTSTRAP_GOT) + + SEND_EARLY_STDERR_DEBUG("About to do specific GOT bootstrap\n"); + /* some arches (like MIPS) we have to tweak the GOT before relocations */ + PERFORM_BOOTSTRAP_GOT(tpnt); + +#endif + +#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) + + /* OK, now do the relocations. We do not do a lazy binding here, so + that once we are done, we have considerably more flexibility. */ + SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n"); + + { + int goof, indx; +#ifdef ELF_MACHINE_PLTREL_OVERLAP +# define INDX_MAX 1 +#else +# define INDX_MAX 2 +#endif + goof = 0; + for (indx = 0; indx < INDX_MAX; indx++) { + unsigned int i; + unsigned long *reloc_addr; + unsigned long symbol_addr; + int symtab_index; + ElfW(Sym) *sym; + ELF_RELOC *rpnt; + unsigned long rel_addr, rel_size; + ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + + rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); + rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : + tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); + + if (!rel_addr) + continue; + + /* Now parse the relocation information */ + /* Since ldso is linked with -Bsymbolic, all relocs will be RELATIVE(for those archs that have + RELATIVE relocs) which means that the for(..) loop below has nothing to do and can be deleted. + Possibly one should add a HAVE_RELATIVE_RELOCS directive and #ifdef away some code. */ + if (!indx && relative_count) { + rel_size -= relative_count * sizeof(ELF_RELOC); + elf_machine_relative(load_addr, rel_addr, relative_count); + rel_addr += relative_count * sizeof(ELF_RELOC); + } + + rpnt = (ELF_RELOC *) rel_addr; + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym = NULL; + if (symtab_index) { + char *strtab; + ElfW(Sym) *symtab; + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + sym = &symtab[symtab_index]; + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value); + +#ifndef EARLY_STDERR_SPECIAL + SEND_STDERR_DEBUG("relocating symbol: "); + SEND_STDERR_DEBUG(strtab + sym->st_name); + SEND_STDERR_DEBUG("\n"); +#endif + } else { + SEND_STDERR_DEBUG("relocating unknown symbol\n"); + } + /* Use this machine-specific macro to perform the actual relocation. */ + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); + } + } + + if (goof) { + _dl_exit(14); + } + } +#endif + + /* Wahoo!!! */ + SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n"); + + /* Now we have done the mandatory linking of some things. We are now + free to start using global variables, since these things have all been + fixed up by now. Still no function calls outside of this library, + since the dynamic resolver is not yet ready. */ + + __rtld_stack_end = (void *)(argv - 1); + + _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv + DL_GET_READY_TO_RUN_EXTRA_ARGS); + + + /* Transfer control to the application. */ + SEND_STDERR_DEBUG("transfering control to application @ "); + _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val; + SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1); + +#ifndef START + return _dl_elf_main; +#else + START(); +#endif +} diff --git a/ldso/ldso/frv/dl-debug.h b/ldso/ldso/frv/dl-debug.h new file mode 100644 index 0000000..9b146a6 --- /dev/null +++ b/ldso/ldso/frv/dl-debug.h @@ -0,0 +1,29 @@ +/* FR-V FDPIC ELF shared library loader suppport + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Lots of code copied from ../i386/elfinterp.c, so: + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2002, Erik Andersen + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_FRV_NONE", "R_FRV_32", + [2] "R_FRV_LABEL16", "R_FRV_LABEL24", + [4] "R_FRV_LO16", "R_FRV_HI16", + [6] "R_FRV_GPREL12", "R_FRV_GPRELU12", + [8] "R_FRV_GPREL32", "R_FRV_GPRELHI", "R_FRV_GPRELLO", + [11] "R_FRV_GOT12", "R_FRV_GOTHI", "R_FRV_GOTLO", + [14] "R_FRV_FUNCDESC", + [15] "R_FRV_FUNCDESC_GOT12", "R_FRV_FUNCDESC_GOTHI", "R_FRV_FUNCDESC_GOTLO", + [18] "R_FRV_FUNCDESC_VALUE", "R_FRV_FUNCDESC_GOTOFF12", + [20] "R_FRV_FUNCDESC_GOTOFFHI", "R_FRV_FUNCDESC_GOTOFFLO", + [22] "R_FRV_GOTOFF12", "R_FRV_GOTOFFHI", "R_FRV_GOTOFFLO", +#if 0 + [200] "R_FRV_GNU_VTINHERIT", "R_FRV_GNU_VTENTRY" +#endif +}; diff --git a/ldso/ldso/frv/dl-inlines.h b/ldso/ldso/frv/dl-inlines.h new file mode 100644 index 0000000..95233a7 --- /dev/null +++ b/ldso/ldso/frv/dl-inlines.h @@ -0,0 +1,456 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _dl_assert +# define _dl_assert(expr) +#endif + +/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete + load map. */ +static __always_inline void +__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, void *got_value, + struct elf32_fdpic_loadmap *map) +{ + if (map->version != 0) + { + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); + _dl_exit(-1); + } + if (map->nsegs == 0) + { + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); + _dl_exit(-1); + } + loadaddr->got_value = got_value; + loadaddr->map = map; +} + +/* Figure out how many LOAD segments there are in the given headers, + and allocate a block for the load map big enough for them. + got_value will be properly initialized later on, with INIT_GOT. */ +static __always_inline int +__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt, + int pcnt) +{ + int count = 0, i; + size_t size; + + for (i = 0; i < pcnt; i++) + if (ppnt[i].p_type == PT_LOAD) + count++; + + loadaddr->got_value = 0; + + size = sizeof (struct elf32_fdpic_loadmap) + + sizeof (struct elf32_fdpic_loadseg) * count; + loadaddr->map = _dl_malloc (size); + if (! loadaddr->map) + _dl_exit (-1); + + loadaddr->map->version = 0; + loadaddr->map->nsegs = 0; + + return count; +} + +/* Incrementally initialize a load map. */ +static __always_inline void +__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr, + Elf32_Phdr *phdr, int maxsegs) +{ + struct elf32_fdpic_loadseg *segdata; + + if (loadaddr.map->nsegs == maxsegs) + _dl_exit (-1); + + segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; + segdata->addr = (Elf32_Addr) addr; + segdata->p_vaddr = phdr->p_vaddr; + segdata->p_memsz = phdr->p_memsz; + +#if defined (__SUPPORT_LD_DEBUG__) + { + extern char *_dl_debug; + extern int _dl_debug_file; + if (_dl_debug) + _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", + loadaddr.map->nsegs-1, + segdata->p_vaddr, segdata->addr, segdata->p_memsz); + } +#endif +} + +static __always_inline void __dl_loadaddr_unmap +(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht); + +/* Figure out whether the given address is in one of the mapped + segments. */ +static __always_inline int +__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr) +{ + struct elf32_fdpic_loadmap *map = loadaddr.map; + int c; + + for (c = 0; c < map->nsegs; c++) + if ((void*)map->segs[c].addr <= p + && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) + return 1; + + return 0; +} + +static __always_inline void * _dl_funcdesc_for (void *entry_point, void *got_value); + +/* The hashcode handling code below is heavily inspired in libiberty's + hashtab code, but with most adaptation points and support for + deleting elements removed. + + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). */ + +static __always_inline unsigned long +higher_prime_number (unsigned long n) +{ + /* These are primes that are near, but slightly smaller than, a + power of two. */ + static const unsigned long primes[] = { + (unsigned long) 7, + (unsigned long) 13, + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, + /* 4294967291L */ + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + }; + + const unsigned long *low = &primes[0]; + const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])]; + + while (low != high) + { + const unsigned long *mid = low + (high - low) / 2; + if (n > *mid) + low = mid + 1; + else + high = mid; + } + +#if 0 + /* If we've run out of primes, abort. */ + if (n > *low) + { + fprintf (stderr, "Cannot find prime bigger than %lu\n", n); + abort (); + } +#endif + + return *low; +} + +struct funcdesc_ht +{ + /* Table itself. */ + struct funcdesc_value **entries; + + /* Current size (in entries) of the hash table */ + size_t size; + + /* Current number of elements. */ + size_t n_elements; +}; + +static __always_inline int +hash_pointer (const void *p) +{ + return (int) ((long)p >> 3); +} + +static __always_inline struct funcdesc_ht * +htab_create (void) +{ + struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht)); + + if (! ht) + return NULL; + ht->size = 3; + ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size); + if (! ht->entries) + return NULL; + + ht->n_elements = 0; + + _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size); + + return ht; +} + +/* This is only called from _dl_loadaddr_unmap, so it's safe to call + _dl_free(). See the discussion below. */ +static __always_inline void +htab_delete (struct funcdesc_ht *htab) +{ + int i; + + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i]) + _dl_free (htab->entries[i]); + + _dl_free (htab->entries); + _dl_free (htab); +} + +/* Similar to htab_find_slot, but without several unwanted side effects: + - Does not call htab->eq_f when it finds an existing entry. + - Does not change the count of elements/searches/collisions in the + hash table. + This function also assumes there are no deleted entries in the table. + HASH is the hash value for the element to be inserted. */ + +static __always_inline struct funcdesc_value ** +find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash) +{ + size_t size = htab->size; + unsigned int index = hash % size; + struct funcdesc_value **slot = htab->entries + index; + int hash2; + + if (! *slot) + return slot; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + slot = htab->entries + index; + if (! *slot) + return slot; + } +} + +/* The following function changes size of memory allocated for the + entries and repeatedly inserts the table elements. The occupancy + of the table after the call will be about 50%. Naturally the hash + table must already exist. Remember also that the place of the + table entries is changed. If memory allocation failures are allowed, + this function will return zero, indicating that the table could not be + expanded. If all goes well, it will return a non-zero value. */ + +static __always_inline int +htab_expand (struct funcdesc_ht *htab) +{ + struct funcdesc_value **oentries; + struct funcdesc_value **olimit; + struct funcdesc_value **p; + struct funcdesc_value **nentries; + size_t nsize; + + oentries = htab->entries; + olimit = oentries + htab->size; + + /* Resize only when table after removal of unused elements is either + too full or too empty. */ + if (htab->n_elements * 2 > htab->size) + nsize = higher_prime_number (htab->n_elements * 2); + else + nsize = htab->size; + + nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize); + _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize); + if (nentries == NULL) + return 0; + htab->entries = nentries; + htab->size = nsize; + + p = oentries; + do + { + if (*p) + *find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point)) + = *p; + + p++; + } + while (p < olimit); + +#if 0 /* We can't tell whether this was allocated by the _dl_malloc() + built into ld.so or malloc() in the main executable or libc, + and calling free() for something that wasn't malloc()ed could + do Very Bad Things (TM). Take the conservative approach + here, potentially wasting as much memory as actually used by + the hash table, even if multiple growths occur. That's not + so bad as to require some overengineered solution that would + enable us to keep track of how it was allocated. */ + _dl_free (oentries); +#endif + return 1; +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. + When inserting an entry, NULL may be returned if memory allocation + fails. */ + +static __always_inline struct funcdesc_value ** +htab_find_slot (struct funcdesc_ht *htab, void *ptr, int insert) +{ + unsigned int index; + int hash, hash2; + size_t size; + struct funcdesc_value **entry; + + if (htab->size * 3 <= htab->n_elements * 4 + && htab_expand (htab) == 0) + return NULL; + + hash = hash_pointer (ptr); + + size = htab->size; + index = hash % size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + } + + empty_entry: + if (!insert) + return NULL; + + htab->n_elements++; + return entry; +} + +void * +_dl_funcdesc_for (void *entry_point, void *got_value) +{ + struct elf_resolve *tpnt = ((void**)got_value)[2]; + struct funcdesc_ht *ht = tpnt->funcdesc_ht; + struct funcdesc_value **entry; + + _dl_assert (got_value == tpnt->loadaddr.got_value); + + if (! ht) + { + ht = htab_create (); + if (! ht) + return (void*)-1; + tpnt->funcdesc_ht = ht; + } + + entry = htab_find_slot (ht, entry_point, 1); + if (*entry) + { + _dl_assert ((*entry)->entry_point == entry_point); + return _dl_stabilize_funcdesc (*entry); + } + + *entry = _dl_malloc (sizeof (struct funcdesc_value)); + (*entry)->entry_point = entry_point; + (*entry)->got_value = got_value; + + return _dl_stabilize_funcdesc (*entry); +} + +static __always_inline void const * +_dl_lookup_address (void const *address) +{ + struct elf_resolve *rpnt; + struct funcdesc_value const *fd; + + /* Make sure we don't make assumptions about its alignment. */ + __asm__ ("" : "+r" (address)); + + if ((Elf32_Addr)address & 7) + /* It's not a function descriptor. */ + return address; + + fd = (struct funcdesc_value const *)address; + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) + { + if (! rpnt->funcdesc_ht) + continue; + + if (fd->got_value != rpnt->loadaddr.got_value) + continue; + + address = htab_find_slot (rpnt->funcdesc_ht, (void*)fd->entry_point, 0); + + if (address && *(struct funcdesc_value *const*)address == fd) + { + address = (*(struct funcdesc_value *const*)address)->entry_point; + break; + } + else + address = fd; + } + + return address; +} + +void +__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr, + struct funcdesc_ht *funcdesc_ht) +{ + int i; + + for (i = 0; i < loadaddr.map->nsegs; i++) + _dl_munmap ((void*)loadaddr.map->segs[i].addr, + loadaddr.map->segs[i].p_memsz); + + /* _dl_unmap is only called for dlopen()ed libraries, for which + calling free() is safe, or before we've completed the initial + relocation, in which case calling free() is probably pointless, + but still safe. */ + _dl_free (loadaddr.map); + if (funcdesc_ht) + htab_delete (funcdesc_ht); +} diff --git a/ldso/ldso/frv/dl-startup.h b/ldso/ldso/frv/dl-startup.h new file mode 100644 index 0000000..674f81c --- /dev/null +++ b/ldso/ldso/frv/dl-startup.h @@ -0,0 +1,133 @@ +/* Copyright (C) 2003 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Any assembly language/system dependent hacks needed to setup + * boot1.c so it will work as expected and cope with whatever platform + * specific wierdness is needed for this architecture. + + * We override the default _dl_boot function, and replace it with a + * bit of asm. Then call the real _dl_boot function, which is now + * named _dl_boot2. */ + +/* At program start-up, gr16 contains a pointer to a + elf32_fdpic_loadmap that describes how the executable was loaded + into memory. gr17 contains a pointer to the interpreter (our!) + loadmap, if there is an interpreter, or 0 if we're being run as an + executable. gr18 holds a pointer to the interpreter's dynamic + section, if there is an interpreter, or to the executable's dynamic + section, otherwise. If the executable is not dynamic, gr18 is 0. + + We rely on the fact that the linker adds a pointer to the + _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that + __self_reloc returns the relocated pointer to us, so that we can + use this value to initialize the PIC register. */ + +__asm__("" \ +" .text\n" \ +" .global _dl_boot\n" \ +" .type _dl_boot,@function\n" \ +"_dl_boot:\n" \ +" call .Lcall\n" \ +".Lcall:\n" \ +" movsg lr, gr4\n" \ +" sethi.p #gprelhi(.Lcall), gr5\n"\ +" setlo #gprello(.Lcall), gr5\n"\ +" mov.p gr17, gr8\n" \ +" cmp gr17, gr0, icc0\n" \ +" sub.p gr4, gr5, gr4\n" \ +" ckeq icc0, cc4\n" \ +" cmov.p gr16, gr8, cc4, 1\n" \ +" sethi #gprelhi(__ROFIXUP_LIST__), gr9\n" \ +" sethi.p #gprelhi(__ROFIXUP_END__), gr10\n" \ +" setlo #gprello(__ROFIXUP_LIST__), gr9\n" \ +" setlo.p #gprello(__ROFIXUP_END__), gr10\n" \ +" add gr9, gr4, gr9\n" \ +" add.p gr10, gr4, gr10\n" \ +" call __self_reloc\n" \ +" mov.p gr8, gr15\n" \ +" mov gr16, gr9\n" \ +" mov.p gr17, gr10\n" \ +" mov gr18, gr11\n" \ +" addi.p sp, #4, gr13\n" \ +" addi sp, #-8, sp\n" \ +" mov.p sp, gr12\n" \ +" call _dl_boot2\n" \ +" ldd.p @(sp, gr0), gr14\n" \ +" addi sp, #8, sp\n" \ +" movgs gr0, lr\n" \ +" jmpl @(gr14, gr0)\n" \ +" .size _dl_boot,.-_dl_boot\n" \ +); + +#define _dl_boot _dl_boot2 +#define DL_BOOT(X) \ +static void __attribute__ ((used)) \ +_dl_boot (void *dl_boot_got_pointer, \ + struct elf32_fdpic_loadmap *dl_boot_progmap, \ + struct elf32_fdpic_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + struct funcdesc_value *dl_main_funcdesc, \ + X) + +struct elf32_fdpic_loadmap; + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) + +/* + * Compute the GOT address. On several platforms, we use assembly + * here. on FR-V FDPIC, there's no way to compute the GOT address, + * since the offset between text and data is not fixed, so we arrange + * for the assembly _dl_boot to pass this value as an argument to + * _dl_boot. */ +#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_FRV_32: \ + *(REL) += (SYMBOL); \ + break; \ + case R_FRV_FUNCDESC_VALUE: \ + { \ + struct funcdesc_value fv = { \ + (void*)((SYMBOL) + *(REL)), \ + (LOAD).got_value \ + }; \ + *(struct funcdesc_value volatile *)(REL) = fv; \ + break; \ + } \ + default: \ + _dl_exit(1); \ + } + +/* + * Transfer control to the user's application, once the dynamic loader + * is done. We return the address of the function's entry point to + * _dl_boot, see boot1_arch.h. + */ +#define START() do { \ + struct elf_resolve *exec_mod = _dl_loaded_modules; \ + dl_main_funcdesc->entry_point = _dl_elf_main; \ + while (exec_mod->libtype != elf_executable) \ + exec_mod = exec_mod->next; \ + dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \ + /* _dl_dprintf(2, "entry point is (%x,%x)\n", dl_main_funcdesc->entry_point, dl_main_funcdesc->got_value); */ \ + return; \ +} while (0) diff --git a/ldso/ldso/frv/dl-syscalls.h b/ldso/ldso/frv/dl-syscalls.h new file mode 100644 index 0000000..a4bff1d --- /dev/null +++ b/ldso/ldso/frv/dl-syscalls.h @@ -0,0 +1,175 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +#include + +/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ + +#if DYNAMIC_LOADER_IN_SIMULATOR +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset); + +/* Make sure we don't get another definition of _dl_mmap from the + machine-independent code. */ +#undef __NR_mmap +#undef __NR_mmap2 + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +#include /* for PAGE_SIZE */ +static __always_inline void *_dl_memset(void*,int,size_t); +static __always_inline ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset); + +static __ptr_t +_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE; + +/* This is a hack to enable the dynamic loader to run within a + simulator that doesn't support mmap, with a number of very ugly + tricks. Also, it's not as useful as it sounds, since only dynamic + executables without DT_NEEDED dependencies can be run. AFAIK, they + can only be created with -pie. This trick suffices to enable the + dynamic loader to obtain a blank page that it maps early in the + bootstrap. */ + if ((flags & MAP_FIXED) == 0) + { + void *_dl_mmap_base = 0; + __ptr_t *ret = 0; + + if (! _dl_mmap_base) + { + void *stack; + __asm__ ("mov sp, %0" : "=r" (stack)); + _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE); + retry: + if (((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void **)_dl_mmap_base)[771])) + { + while (((void**)_dl_mmap_base)[177]) + { + _dl_mmap_base = ((void**)_dl_mmap_base)[177]; + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + } + } + else + { + int i; + for (i = 0; i < (int)PAGE_SIZE; i++) + if (*(char*)(_dl_mmap_base + i)) + break; + if (i != PAGE_SIZE) + { + _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE); + goto retry; + } + ((void**)_dl_mmap_base)[-1] = + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + } + + if (_dl_mmap_base) + { + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE); + _dl_mmap_base = + ((void**)_dl_mmap_base)[177] = + ((void**)_dl_mmap_base)[771] = + (char*)_dl_mmap_base + plen + PAGE_SIZE; + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + + if ((flags & MAP_ANONYMOUS) != 0) + { + _dl_memset (ret, 0, plen); + return ret; + } + + flags |= MAP_FIXED; + addr = ret; + } + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { +#if 0 + __set_errno (EINVAL); +#endif + return MAP_FAILED; + } + if ((flags & MAP_FIXED) != 0) + { + if (_dl_pread(fd, addr, len, offset) != (ssize_t)len) + return (void*)MAP_FAILED; + if (plen != len) + _dl_memset (addr + len, 0, plen - len); + return addr; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +#endif + +#ifdef __NR_pread +#ifdef DYNAMIC_LOADER_IN_SIMULATOR +#include + +#define __NR___syscall_lseek __NR_lseek +static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count); + +static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset, + int, whence); +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR); + ssize_t ret; + + if (orig == -1) + return -1; + + if (__syscall_lseek (fd, offset, SEEK_SET) != offset) + return -1; + + ret = _dl_read (fd, buf, count); + + if (__syscall_lseek (fd, orig, SEEK_SET) != orig) + ((void(*)())0)(); + + return ret; +} +#else +#define __NR___syscall_pread __NR_pread +static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo); + +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset))); +} +#endif +#endif diff --git a/ldso/ldso/frv/dl-sysdep.h b/ldso/ldso/frv/dl-sysdep.h new file mode 100644 index 0000000..32d86ed --- /dev/null +++ b/ldso/ldso/frv/dl-sysdep.h @@ -0,0 +1,191 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Based on ../i386/dl-sysdep.h + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#undef ELF_USES_RELOCA + +/* JMPREL relocs are inside the DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP + +#define DL_NO_COPY_RELOCS + +/* + * Initialization sequence for a GOT. Copy the resolver function + * descriptor and the pointer to the elf_resolve/link_map data + * structure. Initialize the got_value in the module while at that. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + (MODULE)->loadaddr.got_value = (GOT_BASE); \ + GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \ + GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \ + GOT_BASE[2] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_CYGNUS_FRV +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "FR-V" + +struct elf_resolve; + +struct funcdesc_value +{ + void *entry_point; + void *got_value; +} __attribute__((__aligned__(8))); + + +extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); + +/* 16KiB page alignment. Should perhaps be made dynamic using + getpagesize(), based on AT_PAGESZ from auxvt? */ +#define PAGE_ALIGN 0xffffc000 +#define ADDR_ALIGN 0x3fff +#define OFFS_ALIGN 0x7fffc000 + +struct funcdesc_ht; + +/* We must force strings used early in the bootstrap into the data + segment, such that they are referenced with GOTOFF instead of + GPREL, because GPREL needs the GOT to have already been + relocated. */ +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { static char __s[] = (S); SEND_STDERR (__s); } while (0) + +#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr + +#define DL_RELOC_ADDR(ADDR, LOADADDR) \ + (__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \ + ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value)) + +#define _dl_stabilize_funcdesc(val) \ + ({ __asm__ ("" : "+m" (*(val))); (val); }) + +#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \ + void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \ + (* SIGNATURE pf)(__VA_ARGS__); }) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \ + dl_boot_ldsomap ?: dl_boot_progmap)) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap)) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR), (NULL))) +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht)) +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).got_value) + +/* This is called from dladdr(), such that we map a function + descriptor's address to the function's entry point before trying to + find in which library it's defined. */ +#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS)) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + +/* Make sure we only load libraries that use the same number of + general-purpose and floating-point registers the dynamic loader was + compiled for. */ +#define DL_CHECK_REG_COUNT(flags) \ + (((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_32 ? __FRV_GPR__ == 32 : 1) \ + && ((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_64 ? __FRV_GPR__ == 64 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_32 ? __FRV_FPR__ == 32 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_64 ? __FRV_FPR__ == 64 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_NONE ? __FRV_FPR__ == 0 : 1)) + +/* We only support loading FDPIC independently-relocatable shared + libraries. It probably wouldn't be too hard to support loading + shared libraries that require relocation by the same amount, but we + don't know that they exist or would be useful, and the dynamic + loader code could leak the whole-library map unless we keeping a + bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's + keep things simple for now. */ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + if (((epnt)->e_flags & EF_FRV_FDPIC) && ! ((epnt)->e_flags & EF_FRV_PIC)) \ + (piclib) = 2; \ + else \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + return NULL; \ + } \ +\ + if (! DL_CHECK_REG_COUNT ((epnt)->e_flags)) \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' assumes different register counts" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + } \ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +/* We want to return to dlsym() a function descriptor if the symbol + turns out to be a function. */ +#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \ + (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \ + && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \ + ? _dl_funcdesc_for (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr), \ + (TPNT)->loadaddr.got_value) \ + : DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr)) + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_fdpic_loadmap *dl_boot_progmap +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap + + + + +#ifdef __USE_GNU +# include +#else +# define __USE_GNU +# include +# undef __USE_GNU +#endif diff --git a/ldso/ldso/frv/elfinterp.c b/ldso/ldso/frv/elfinterp.c new file mode 100644 index 0000000..df41f97 --- /dev/null +++ b/ldso/ldso/frv/elfinterp.c @@ -0,0 +1,355 @@ +/* FR-V FDPIC ELF shared library loader suppport + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Lots of code copied from ../i386/elfinterp.c, so: + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2002, Erik Andersen + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +struct funcdesc_value volatile attribute_hidden * +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + struct elf_resolve *new_tpnt; + char *new_addr; + struct funcdesc_value funcval; + struct funcdesc_value volatile *got_entry; + char *symname; + + rel_addr = DL_RELOC_ADDR (tpnt->dynamic_info[DT_JMPREL], + tpnt->loadaddr); + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t) + DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], + tpnt->loadaddr); + strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr); + symname= strtab + symtab[symtab_index].st_name; + + if (reloc_type != R_FRV_FUNCDESC_VALUE) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of GOT entry fix up */ + got_entry = (struct funcdesc_value *) + DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_find_hash_mod(symname, tpnt->symbol_scope, NULL, 0, + &new_tpnt); + if (!new_addr) { + new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0, + &new_tpnt); + if (!new_addr) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + } + + funcval.entry_point = new_addr; + funcval.got_value = new_tpnt->loadaddr.got_value; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", + got_entry->entry_point, got_entry->got_value, + funcval.entry_point, funcval.got_value, + got_entry); + } + if (!_dl_debug_nofixups) { + *got_entry = funcval; + } +#else + *got_entry = funcval; +#endif + + return got_entry; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t) DL_RELOC_ADDR (rel_addr, tpnt->loadaddr); + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t) + DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], tpnt->loadaddr); + strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr); + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (res <0) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + else if (res >0) + { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long reloc_value = 0, *reloc_addr; + struct { unsigned long v; } __attribute__((__packed__)) + *reloc_addr_packed; + unsigned long symbol_addr; + struct elf_resolve *symbol_tpnt; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t) + DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr); + __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr)); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long) + DL_RELOC_ADDR (symtab[symtab_index].st_value, + tpnt->loadaddr); + symbol_tpnt = tpnt; + } else { + + symbol_addr = (unsigned long) + _dl_find_hash_mod(symname, scope, NULL, 0, &symbol_tpnt); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + { + if ((long)reloc_addr_packed & 3) + old_val = reloc_addr_packed->v; + else + old_val = *reloc_addr; + } + else + old_val = 0; +#endif + switch (reloc_type) { + case R_FRV_NONE: + break; + case R_FRV_32: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v += symbol_addr; + else + reloc_value = *reloc_addr += symbol_addr; + break; + case R_FRV_FUNCDESC_VALUE: + funcval.entry_point = (void*)symbol_addr; + /* The addend of FUNCDESC_VALUE + relocations referencing global + symbols must be ignored, because it + may hold the address of a lazy PLT + entry. */ + if (ELF32_ST_BIND + (symtab[symtab_index].st_info) + == STB_LOCAL) + funcval.entry_point += *reloc_addr; + reloc_value = (unsigned long)funcval.entry_point; + if (symbol_addr) + funcval.got_value + = symbol_tpnt->loadaddr.got_value; + else + funcval.got_value = 0; + __asm__ ("std%I0\t%1, %M0" + : "=m" (*(struct funcdesc_value *)reloc_addr) + : "e" (funcval)); + break; + case R_FRV_FUNCDESC: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v; + else + reloc_value = *reloc_addr; + if (symbol_addr) + reloc_value = (unsigned long)_dl_funcdesc_for + ((char *)symbol_addr + reloc_value, + symbol_tpnt->loadaddr.got_value); + else + reloc_value = 0; + if ((long)reloc_addr_packed & 3) + reloc_addr_packed->v = reloc_value; + else + *reloc_addr = reloc_value; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr); + switch (reloc_type) { + case R_FRV_FUNCDESC_VALUE: + _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value); + break; + case R_FRV_FUNCDESC: + if (! reloc_value) + break; + _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)", + ((struct funcdesc_value *)reloc_value)->entry_point, + ((struct funcdesc_value *)reloc_value)->got_value); + break; + } + } +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, + struct dyn_elf *scope __attribute_used__, + ELF_RELOC *rpnt, Elf32_Sym *symtab __attribute_used__, + char *strtab __attribute_used__) +{ + int reloc_type; + struct funcdesc_value volatile *reloc_addr; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (struct funcdesc_value *)(intptr_t) + DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = (unsigned long)reloc_addr->entry_point; +#endif + switch (reloc_type) { + case R_FRV_NONE: + break; + case R_FRV_FUNCDESC_VALUE: + funcval = *reloc_addr; + funcval.entry_point = + DL_RELOC_ADDR (funcval.entry_point, + tpnt->loadaddr); + funcval.got_value = tpnt->loadaddr.got_value; + *reloc_addr = funcval; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_addr->entry_point, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +/* We don't have copy relocs. */ + +int +_dl_parse_copy_information +(struct dyn_elf *rpnt __attribute_used__, + unsigned long rel_addr __attribute_used__, + unsigned long rel_size __attribute_used__) +{ + return 0; +} + +#ifndef LIBDL +# include "../../libc/sysdeps/linux/frv/crtreloc.c" +#endif + diff --git a/ldso/ldso/frv/resolve.S b/ldso/ldso/frv/resolve.S new file mode 100644 index 0000000..9dde727 --- /dev/null +++ b/ldso/ldso/frv/resolve.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + + /* The function below is tail-called by resolver stubs when a + lazily-bound function is called. It must preserve all + registers that could be used to pass arguments to the actual + function. Upon _dl_linux_resolve entry, GR14 holds the + address of a lazy PLT entry, so @(GR14,-4) is the lazy + relocation number that we have to pass to _dl_linux_resolver. + GR15 holds the caller's GOT, from which we extract the + elf_resolve* that _dl_linux_resolver needs as well. + + _dl_linux_resolver() figures out where the jump symbol is + _really_ supposed to have jumped to and returns that to us. + Once we have that, we prepare to tail-call the actual + function, clean up after ourselves, restoring the original + arguments, then jump to the fixed up address. */ + + .text + .p2align 4 + + .hidden _dl_linux_resolve + .global _dl_linux_resolve + .type _dl_linux_resolve,@function + +_dl_linux_resolve: + /* Preserve arguments. */ + addi sp, -8*4, sp + stdi gr8, @(sp, 8) + stdi gr10, @(sp, 16) + stdi gr12, @(sp, 24) + movsg lr,gr8 + st gr8, @(sp,gr0) + + /* Prepare to call _dl_linux_resolver. */ + ldi @(gr15, 8), gr8 + ldi @(gr14, -4), gr9 + mov.p gr5, gr15 + call _dl_linux_resolver + + /* Move aside return value that contains the FUNCDESC_VALUE. */ + ldd @(gr8,gr0),gr14 + + /* Restore arguments. */ + ld @(sp, gr0), gr8 + movgs gr8,lr + lddi @(sp, 24), gr12 + lddi @(sp, 16), gr10 + lddi @(sp, 8), gr8 + addi sp, 8*4, sp + + /* Now jump to the actual function. */ + jmpl @(gr14, gr0) + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/ldso/ldso/i386/dl-debug.h b/ldso/ldso/i386/dl-debug.h new file mode 100644 index 0000000..72a01f8 --- /dev/null +++ b/ldso/ldso/i386/dl-debug.h @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* i386 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", + [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", + [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", +}; diff --git a/ldso/ldso/i386/dl-startup.h b/ldso/ldso/i386/dl-startup.h new file mode 100644 index 0000000..45f69b8 --- /dev/null +++ b/ldso/ldso/i386/dl-startup.h @@ -0,0 +1,65 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2004 by Erik Andersen + */ +__asm__ ( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " call _dl_start\n" + " # Save the user entry point address in %edi.\n" + " movl %eax, %edi\n" + " # Point %ebx at the GOT.\n" + " call 1f\n" + "1: popl %ebx\n" + " addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx\n" + " # See if we were run as a command with the executable file\n" + " # name as an extra leading argument.\n" + " movl _dl_skip_args@GOTOFF(%ebx), %eax\n" + " # Pop the original argument count.\n" + " popl %edx\n" + " # Adjust the stack pointer to skip _dl_skip_args words.\n" + " leal (%esp,%eax,4), %esp\n" + " # Subtract _dl_skip_args from argc.\n" + " subl %eax, %edx\n" + " # Push argc back on the stack.\n" + " push %edx\n" + " # Pass our FINI ptr() to the user in %edx, as per ELF ABI.\n" + " leal _dl_fini@GOTOFF(%ebx), %edx\n" + " # Jump to the user's entry point.\n" + " jmp *%edi\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) + { + case R_386_32: + *reloc_addr += symbol_addr; + break; + case R_386_PC32: + *reloc_addr += symbol_addr - (unsigned long) reloc_addr; + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_386_RELATIVE: + *reloc_addr += load_addr; + break; + default: + _dl_exit(1); + } +} diff --git a/ldso/ldso/i386/dl-syscalls.h b/ldso/ldso/i386/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/i386/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h new file mode 100644 index 0000000..7090c92 --- /dev/null +++ b/ldso/ldso/i386/dl-sysdep.h @@ -0,0 +1,80 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_386 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "386" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr elf_machine_dynamic (void) attribute_unused; +static __inline__ Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("%ebx"); + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr elf_machine_load_address (void) attribute_unused; +static __inline__ Elf32_Addr +elf_machine_load_address (void) +{ + /* It doesn't matter what variable this is, the reference never makes + it to assembly. We need a dummy reference to some global variable + via the GOT to make sure the compiler initialized %ebx in time. */ + Elf32_Addr addr; + __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n" + "subl _dl_start@GOT(%%ebx), %0" + : "=r" (addr) : "m" (_dl_errno) : "cc"); + return addr; +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr += load_off; + } while (--relative_count); +} diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c new file mode 100644 index 0000000..62e854d --- /dev/null +++ b/ldso/ldso/i386/elfinterp.c @@ -0,0 +1,294 @@ +/* vi: set sw=4 ts=4: */ +/* i386 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched: %x ==> %x @ %x", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", + _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", + reloc_type, tpnt->libname); +#endif + return res; + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_32: + *reloc_addr += symbol_addr; + break; + case R_386_PC32: + *reloc_addr += symbol_addr - (unsigned long)reloc_addr; + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_386_RELATIVE: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + case R_386_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/i386/resolve.S b/ldso/ldso/i386/resolve.S new file mode 100644 index 0000000..e8d77bb --- /dev/null +++ b/ldso/ldso/i386/resolve.S @@ -0,0 +1,51 @@ +/* + * This function is _not_ called directly. It is jumped to (so no return + * address is on the stack) when attempting to use a symbol that has not yet + * been resolved. The first time a jump symbol (such as a function call inside + * a shared library) is used (before it gets resolved) it will jump here to + * _dl_linux_resolve. When we get called the stack looks like this: + * reloc_entry + * tpnt + * + * This function saves all the registers, puts a copy of reloc_entry and tpnt + * on the stack (as function arguments) then make the function call + * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out + * where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + * found them, then we jump to the fixed up address, which is where the jump + * symbol that got us here really wanted to jump to in the first place. + * -Erik Andersen + */ + +.text + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: + pusha /* preserve all regs */ + lea 0x20(%esp),%eax /* eax = tpnt and reloc_entry params */ + pushl 4(%eax) /* push copy of reloc_entry param */ + pushl (%eax) /* push copy of tpnt param */ + +#ifdef __PIC__ + call .L24 +.L24: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L24],%ebx + movl _dl_linux_resolver@GOT(%ebx),%ebx /* eax = resolved func */ + call *%ebx +#else + call _dl_linux_resolver +#endif + movl %eax,0x28(%esp) /* store func addr over original + * tpnt param */ + addl $0x8,%esp /* remove copy parameters */ + popa /* restore regs */ + ret $4 /* jump to func removing original + * reloc_entry param from stack */ +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c new file mode 100644 index 0000000..46cc91c --- /dev/null +++ b/ldso/ldso/ldso.c @@ -0,0 +1,947 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" +#include "unsecvars.h" + +/* Pull in common debug code */ +#include "dl-debug.c" + +#define ALLOW_ZERO_PLTGOT + +/* Pull in the value of _dl_progname */ +#include LDSO_ELFINTERP + +/* Global variables used within the shared library loader */ +char *_dl_library_path = 0; /* Where we look for libraries */ +char *_dl_preload = 0; /* Things to be loaded before the libs */ +char *_dl_ldsopath = 0; /* Location of the shared lib loader */ +int _dl_secure = 1; /* Are we dealing with setuid stuff? */ +int _dl_errno = 0; /* We can't use the real errno in ldso */ +size_t _dl_pagesize = 0; /* Store the page size for use later */ +struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */ +void *(*_dl_malloc_function) (size_t size) = NULL; +void (*_dl_free_function) (void *p) = NULL; + +#ifdef __SUPPORT_LD_DEBUG__ +char *_dl_debug = 0; +char *_dl_debug_symbols = 0; +char *_dl_debug_move = 0; +char *_dl_debug_reloc = 0; +char *_dl_debug_detail = 0; +char *_dl_debug_nofixups = 0; +char *_dl_debug_bindings = 0; +int _dl_debug_file = 2; +#endif + +/* Needed for standalone execution. */ +unsigned long attribute_hidden _dl_skip_args = 0; +const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */ +#include "dl-startup.c" +#include "dl-array.c" +/* Forward function declarations */ +static int _dl_suid_ok(void); + +/* + * This stub function is used by some debuggers. The idea is that they + * can set an internal breakpoint on it, so that we are notified when the + * address mapping is changed in some way. + */ +void _dl_debug_state(void); +rtld_hidden_proto(_dl_debug_state, noinline); +void _dl_debug_state(void) +{ + /* Make sure GCC doesn't recognize this function as pure, to avoid + * having the calls optimized away. + */ + __asm__(""); +} +rtld_hidden_def(_dl_debug_state); + +static unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */ +static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ + +static struct elf_resolve **init_fini_list; +static unsigned int nlist; /* # items in init_fini_list */ +extern void _start(void); + +#ifdef __UCLIBC_HAS_SSP__ +# include +uintptr_t stack_chk_guard; +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + * in local thread area. */ +uintptr_t __stack_chk_guard attribute_relro; +# ifdef __UCLIBC_HAS_SSP_COMPAT__ +strong_alias(__stack_chk_guard,__guard) +# endif +# elif defined __UCLIBC_HAS_SSP_COMPAT__ +uintptr_t __guard attribute_relro; +# endif +#endif + +static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) +{ + unsigned int i; + struct elf_resolve * tpnt; + + for (i = 0; i < nlist; ++i) { + tpnt = init_fini_list[i]; + if (tpnt->init_flag & FINI_FUNCS_CALLED) + continue; + tpnt->init_flag |= FINI_FUNCS_CALLED; + _dl_run_fini_array(tpnt); + if (tpnt->dynamic_info[DT_FINI]) { + void (*dl_elf_func) (void); + + dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]); + _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname); + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + } +} + +void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, + ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, + char **argv + DL_GET_READY_TO_RUN_EXTRA_PARMS) +{ + ElfW(Addr) app_mapaddr = 0; + ElfW(Phdr) *ppnt; + ElfW(Dyn) *dpnt; + char *lpntstr; + unsigned int i; + int unlazy = 0, trace_loaded_objects = 0; + struct dyn_elf *rpnt; + struct elf_resolve *tcurr; + struct elf_resolve *tpnt1; + struct elf_resolve app_tpnt_tmp; + struct elf_resolve *app_tpnt = &app_tpnt_tmp; + struct r_debug *debug_addr; + unsigned long *lpnt; + unsigned long *_dl_envp; /* The environment address */ + ElfW(Addr) relro_addr = 0; + size_t relro_size = 0; + struct stat st; + + /* Wahoo!!! We managed to make a function call! Get malloc + * setup so we can use _dl_dprintf() to print debug noise + * instead of the SEND_STDERR macros used in dl-startup.c */ + + _dl_memset(app_tpnt, 0x00, sizeof(*app_tpnt)); + + /* Store the page size for later use */ + _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + /* Make it so _dl_malloc can use the page of memory we have already + * allocated. We shouldn't need to grab any more memory. This must + * be first since things like _dl_dprintf() use _dl_malloc()... + */ + _dl_malloc_addr = (unsigned char *)_dl_pagesize; + _dl_mmap_zero = 0; + + /* Wahoo!!! */ + _dl_debug_early("Cool, ldso survived making function calls\n"); + + /* Now we have done the mandatory linking of some things. We are now + * free to start using global variables, since these things have all + * been fixed up by now. Still no function calls outside of this + * library, since the dynamic resolver is not yet ready. + */ + if (argv[0]) { + _dl_progname = argv[0]; + } + + if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { + _dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n"); + _dl_exit(1); + } + + /* Start to build the tables of the modules that are required for + * this beast to run. We start with the basic executable, and then + * go from there. Eventually we will run across ourself, and we + * will need to properly deal with that as well. + */ + rpnt = NULL; + if (_dl_getenv("LD_BIND_NOW", envp)) + unlazy = RTLD_NOW; + + /* Now we need to figure out what kind of options are selected. + * Note that for SUID programs we ignore the settings in + * LD_LIBRARY_PATH. + */ + if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || + (auxvt[AT_UID].a_un.a_val != (size_t)-1 && + auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val && + auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) { + _dl_secure = 0; + _dl_preload = _dl_getenv("LD_PRELOAD", envp); + _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp); + } else { + static const char unsecure_envvars[] = +#ifdef EXTRA_UNSECURE_ENVVARS + EXTRA_UNSECURE_ENVVARS +#endif + UNSECURE_ENVVARS; + const char *nextp; + _dl_secure = 1; + + nextp = unsecure_envvars; + do { + _dl_unsetenv (nextp, envp); + /* We could use rawmemchr but this need not be fast. */ + nextp = (char *) _dl_strchr(nextp, '\0') + 1; + } while (*nextp != '\0'); + _dl_preload = NULL; + _dl_library_path = NULL; + /* SUID binaries can be exploited if they do LAZY relocation. */ + unlazy = RTLD_NOW; + } + + /* sjhill: your TLS init should go before this */ +#ifdef __UCLIBC_HAS_SSP__ + /* Set up the stack checker's canary. */ + stack_chk_guard = _dl_setup_stack_chk_guard (); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +# ifdef __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +# else + __stack_chk_guard = stack_chk_guard; +# endif +#endif + + /* At this point we are now free to examine the user application, + * and figure out which libraries are supposed to be called. Until + * we have this list, we will not be completely ready for dynamic + * linking. + */ + + /* Find the runtime load address of the main executable. This may be + * different from what the ELF header says for ET_DYN/PIE executables. + */ + { + unsigned int idx; + ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + + for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++) + if (phdr->p_type == PT_PHDR) { + DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); + break; + } + + if (DL_LOADADDR_BASE(app_tpnt->loadaddr)) + _dl_debug_early("Position Independent Executable: " + "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr)); + } + + /* + * This is used by gdb to locate the chain of shared libraries that are + * currently loaded. + */ + debug_addr = _dl_malloc(sizeof(struct r_debug)); + _dl_memset(debug_addr, 0, sizeof(struct r_debug)); + + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { + if (ppnt->p_type == PT_GNU_RELRO) { + relro_addr = ppnt->p_vaddr; + relro_size = ppnt->p_memsz; + } + if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) { + app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr); + } + if (ppnt->p_type == PT_DYNAMIC) { + dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr); + _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr); +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + /* Ugly, ugly. We need to call mprotect to change the + * protection of the text pages so that we can do the + * dynamic linking. We can set the protection back + * again once we are done. + */ + _dl_debug_early("calling mprotect on the application program\n"); + /* Now cover the application program. */ + if (app_tpnt->dynamic_info[DT_TEXTREL]) { + ElfW(Phdr) *ppnt_outer = ppnt; + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { + if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) + _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN), + ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) + + (unsigned long) ppnt->p_filesz, + PROT_READ | PROT_WRITE | PROT_EXEC); + } + ppnt = ppnt_outer; + } +#else + if (app_tpnt->dynamic_info[DT_TEXTREL]) { + _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n"); + _dl_exit(1); + } +#endif + +#ifndef ALLOW_ZERO_PLTGOT + /* make sure it's really there. */ + if (app_tpnt->dynamic_info[DT_PLTGOT] == 0) + continue; +#endif + /* OK, we have what we need - slip this one into the list. */ + app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr, + app_tpnt->dynamic_info, + (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr), + ppnt->p_filesz); + _dl_loaded_modules->libtype = elf_executable; + _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; + _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); + rpnt->dyn = _dl_loaded_modules; + app_tpnt->mapaddr = app_mapaddr; + app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; + app_tpnt->usage_count++; + app_tpnt->symbol_scope = _dl_symbol_tables; + lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]); +#ifdef ALLOW_ZERO_PLTGOT + if (lpnt) +#endif + INIT_GOT(lpnt, _dl_loaded_modules); + } + + /* OK, fill this in - we did not have this before */ + if (ppnt->p_type == PT_INTERP) { + char *ptmp; + + tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr); + + /* Store the path where the shared lib loader was found + * for later use + */ + _dl_ldsopath = _dl_strdup(tpnt->libname); + ptmp = _dl_strrchr(_dl_ldsopath, '/'); + if (ptmp != _dl_ldsopath) + *ptmp = '\0'; + + _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname); + } + } + app_tpnt->relro_addr = relro_addr; + app_tpnt->relro_size = relro_size; + +#ifdef __SUPPORT_LD_DEBUG__ + _dl_debug = _dl_getenv("LD_DEBUG", envp); + if (_dl_debug) { + if (_dl_strstr(_dl_debug, "all")) { + _dl_debug_detail = _dl_debug_move = _dl_debug_symbols + = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1; + } else { + _dl_debug_detail = _dl_strstr(_dl_debug, "detail"); + _dl_debug_move = _dl_strstr(_dl_debug, "move"); + _dl_debug_symbols = _dl_strstr(_dl_debug, "sym"); + _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc"); + _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix"); + _dl_debug_bindings = _dl_strstr(_dl_debug, "bind"); + } + } + + { + const char *dl_debug_output; + + dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp); + + if (dl_debug_output) { + char tmp[22], *tmp1, *filename; + int len1, len2; + + _dl_memset(tmp, 0, sizeof(tmp)); + tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid()); + + len1 = _dl_strlen(dl_debug_output); + len2 = _dl_strlen(tmp1); + + filename = _dl_malloc(len1+len2+2); + + if (filename) { + _dl_strcpy (filename, dl_debug_output); + filename[len1] = '.'; + _dl_strcpy (&filename[len1+1], tmp1); + + _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644); + if (_dl_debug_file < 0) { + _dl_debug_file = 2; + _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename); + } + } + } + } +#endif + + if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) { + trace_loaded_objects++; + } + +#ifndef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) { + _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n"); + _dl_exit(1); + } +#endif + + /* + * OK, fix one more thing - set up debug_addr so it will point + * to our chain. Later we may need to fill in more fields, but this + * should be enough for now. + */ + debug_addr->r_map = (struct link_map *) _dl_loaded_modules; + debug_addr->r_version = 1; + debug_addr->r_ldbase = DL_LOADADDR_BASE(load_addr); + debug_addr->r_brk = (unsigned long) &_dl_debug_state; + _dl_debug_addr = debug_addr; + + /* Do not notify the debugger until the interpreter is in the list */ + + /* OK, we now have the application in the list, and we have some + * basic stuff in place. Now search through the list for other shared + * libraries that should be loaded, and insert them on the list in the + * correct order. + */ + + _dl_map_cache(); + + if (_dl_preload) { + char c, *str, *str2; + + str = _dl_preload; + while (*str == ':' || *str == ' ' || *str == '\t') + str++; + + while (*str) { + str2 = str; + while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t') + str2++; + c = *str2; + *str2 = '\0'; + + if (!_dl_secure || _dl_strchr(str, '/') == NULL) { + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname); + + tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects); + if (!tpnt1) { +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) + _dl_dprintf(1, "\t%s => not found\n", str); + else +#endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str); + _dl_exit(15); + } + } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + /* This is a real hack to make + * ldd not print the library + * itself when run on a + * library. + */ + if (_dl_strcmp(_dl_progname, str) != 0) + _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +#endif + } + } + + *str2 = c; + str = str2; + while (*str == ':' || *str == ' ' || *str == '\t') + str++; + } + } + +#ifdef __LDSO_PRELOAD_FILE_SUPPORT__ + do { + char *preload; + int fd; + char c, *cp, *cp2; + + if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) { + break; + } + + if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) { + _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n", + _dl_progname, LDSO_PRELOAD); + break; + } + + preload = (caddr_t) _dl_mmap(0, st.st_size + 1, + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + _dl_close(fd); + if (preload == (caddr_t) -1) { + _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_PRELOAD); + break; + } + + /* convert all separators and comments to spaces */ + for (cp = preload; *cp; /*nada */ ) { + if (*cp == ':' || *cp == '\t' || *cp == '\n') { + *cp++ = ' '; + } else if (*cp == '#') { + do { + *cp++ = ' '; + } while (*cp != '\n' && *cp != '\0'); + } else { + cp++; + } + } + + /* find start of first library */ + for (cp = preload; *cp && *cp == ' '; cp++) + /*nada */ ; + + while (*cp) { + /* find end of library */ + for (cp2 = cp; *cp && *cp != ' '; cp++) + /*nada */ ; + c = *cp; + *cp = '\0'; + + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname); + + tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects); + if (!tpnt1) { +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) + _dl_dprintf(1, "\t%s => not found\n", cp2); + else +#endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2); + _dl_exit(15); + } + } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + cp2, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +#endif + } + + /* find start of next library */ + *cp = c; + for ( /*nada */ ; *cp && *cp == ' '; cp++) + /*nada */ ; + } + + _dl_munmap(preload, st.st_size + 1); + } while (0); +#endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */ + + nlist = 0; + for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { + ElfW(Dyn) *this_dpnt; + + nlist++; + for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) { + if (this_dpnt->d_tag == DT_NEEDED) { + char *name; + struct init_fini_list *tmp; + + lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val); + name = _dl_get_last_path_component(lpntstr); + if (_dl_strcmp(name, UCLIBC_LDSO) == 0) + continue; + + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname); + + if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) { +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) { + _dl_dprintf(1, "\t%s => not found\n", lpntstr); + continue; + } else +#endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr); + _dl_exit(16); + } + } + + tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */ + tmp->tpnt = tpnt1; + tmp->next = tcurr->init_fini; + tcurr->init_fini = tmp; + + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + lpntstr, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +#endif + } + } + } + _dl_unmap_cache(); + + --nlist; /* Exclude the application. */ + init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *)); + i = 0; + for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { + init_fini_list[i++] = tcurr; + } + + /* Sort the INIT/FINI list in dependency order. */ + for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { + unsigned int j, k; + + for (j = 0; init_fini_list[j] != tcurr; ++j) + /* Empty */; + for (k = j + 1; k < nlist; ++k) { + struct init_fini_list *runp = init_fini_list[k]->init_fini; + + for (; runp; runp = runp->next) { + if (runp->tpnt == tcurr) { + struct elf_resolve *here = init_fini_list[k]; + _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j); + for (i = (k - j); i; --i) + init_fini_list[i+j] = init_fini_list[i+j-1]; + init_fini_list[j] = here; + ++j; + break; + } + } + } + } +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug) { + _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n"); + for (i = 0; i < nlist; i++) { + struct init_fini_list *tmp; + + _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n", + init_fini_list[i]->libname); + tmp = init_fini_list[i]->init_fini; + for (; tmp; tmp = tmp->next) + _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname); + _dl_dprintf(_dl_debug_file, "\n"); + } + } +#endif + + /* + * If the program interpreter is not in the module chain, add it. + * This will be required for dlopen to be able to access the internal + * functions in the dynamic linker and to relocate the interpreter + * again once all libs are loaded. + */ + if (tpnt) { + ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff); + int j; + + tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr, + tpnt->dynamic_info, + (unsigned long)tpnt->dynamic_addr, + 0); + + if (_dl_stat(tpnt->libname, &st) >= 0) { + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + } + tpnt->n_phent = epnt->e_phnum; + tpnt->ppnt = myppnt; + for (j = 0; j < epnt->e_phnum; j++, myppnt++) { + if (myppnt->p_type == PT_GNU_RELRO) { + tpnt->relro_addr = myppnt->p_vaddr; + tpnt->relro_size = myppnt->p_memsz; + break; + } + } + tpnt->libtype = program_interpreter; + tpnt->usage_count++; + tpnt->symbol_scope = _dl_symbol_tables; + if (rpnt) { + rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf)); + rpnt->next->prev = rpnt; + rpnt = rpnt->next; + } else { + rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); + } + rpnt->dyn = tpnt; + tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ +#ifdef RERELOCATE_LDSO + /* Only rerelocate functions for now. */ + tpnt->init_flag = RELOCS_DONE; + lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]); +# ifdef ALLOW_ZERO_PLTGOT + if (tpnt->dynamic_info[DT_PLTGOT]) +# endif + INIT_GOT(lpnt, tpnt); +#else + tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE; +#endif + tpnt = NULL; + } + +#ifdef __LDSO_LDD_SUPPORT__ + /* End of the line for ldd.... */ + if (trace_loaded_objects) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1, + rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr)); + _dl_exit(0); + } +#endif + + _dl_debug_early("Beginning relocation fixups\n"); + +#ifdef __mips__ + /* + * Relocation of the GOT entries for MIPS have to be done + * after all the libraries have been loaded. + */ + _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy); +#endif + + /* + * OK, now all of the kids are tucked into bed in their proper + * addresses. Now we go through and look for REL and RELA records that + * indicate fixups to the GOT tables. We need to do this in reverse + * order so that COPY directives work correctly. + */ + if (_dl_symbol_tables) + if (_dl_fixup(_dl_symbol_tables, unlazy)) + _dl_exit(-1); + + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if (tpnt->relro_size) + _dl_protect_relro (tpnt); + } + + /* OK, at this point things are pretty much ready to run. Now we need + * to touch up a few items that are required, and then we can let the + * user application have at it. Note that the dynamic linker itself + * is not guaranteed to be fully dynamicly linked if we are using + * ld.so.1, so we have to look up each symbol individually. + */ + + _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0); + if (_dl_envp) + *_dl_envp = (unsigned long) envp; + +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + { + unsigned int j; + ElfW(Phdr) *myppnt; + + /* We had to set the protections of all pages to R/W for + * dynamic linking. Set text pages back to R/O. + */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) { + if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) { + _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN), + (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags)); + } + } + } + + } +#endif + /* Notify the debugger we have added some objects. */ + _dl_debug_addr->r_state = RT_ADD; + _dl_debug_state(); + + /* Run pre-initialization functions for the executable. */ + _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY], + _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ], + _dl_loaded_modules->loadaddr); + + /* Run initialization functions for loaded objects. For the + main executable, they will be run from __uClibc_main. */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; + tpnt->init_fini = NULL; /* Clear, since alloca was used */ + if (tpnt->init_flag & INIT_FUNCS_CALLED) + continue; + tpnt->init_flag |= INIT_FUNCS_CALLED; + + if (tpnt->dynamic_info[DT_INIT]) { + void (*dl_elf_func) (void); + + dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]); + + _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname); + + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + + _dl_run_init_array(tpnt); + } + + /* Find the real malloc function and make ldso functions use that from now on */ + _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc", + _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); + + /* Notify the debugger that all objects are now mapped in. */ + _dl_debug_addr->r_state = RT_CONSISTENT; + _dl_debug_state(); +} + +char *_dl_getenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + + while ((pnt = *envp++)) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + continue; + return pnt + 1; + } + return 0; +} + +void _dl_unsetenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + char **newenvp = envp; + + for (pnt = *envp; pnt; pnt = *++envp) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + *newenvp++ = *envp; + } + *newenvp++ = *envp; + return; +} + +static int _dl_suid_ok(void) +{ + __kernel_uid_t uid, euid; + __kernel_gid_t gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if (uid == euid && gid == egid) { + return 1; + } + return 0; +} + +void *_dl_malloc(size_t size) +{ + void *retval; + +#if 0 + _dl_debug_early("request for %d bytes\n", size); +#endif + + if (_dl_malloc_function) + return (*_dl_malloc_function) (size); + + if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) { + size_t rounded_size; + + /* Since the above assumes we get a full page even if + we request less than that, make sure we request a + full page, since uClinux may give us less than than + a full page. We might round even + larger-than-a-page sizes, but we end up never + reusing _dl_mmap_zero/_dl_malloc_addr in that case, + so we don't do it. + + The actual page size doesn't really matter; as long + as we're self-consistent here, we're safe. */ + if (size < _dl_pagesize) + rounded_size = (size + _dl_pagesize - 1) & _dl_pagesize; + else + rounded_size = size; + + _dl_debug_early("mmapping more memory\n"); + _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(_dl_mmap_zero)) { + _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname); + _dl_exit(20); + } + } + retval = _dl_malloc_addr; + _dl_malloc_addr += size; + + /* + * Align memory to DL_MALLOC_ALIGN byte boundary. Some + * platforms require this, others simply get better + * performance. + */ + _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1)); + return retval; +} + +void _dl_free (void *p) +{ + if (_dl_free_function) + (*_dl_free_function) (p); +} + +#include "dl-hash.c" +#include "dl-elf.c" diff --git a/ldso/ldso/m68k/dl-debug.h b/ldso/ldso/m68k/dl-debug.h new file mode 100644 index 0000000..a9a80a0 --- /dev/null +++ b/ldso/ldso/m68k/dl-debug.h @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* m68k ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Adapted to ELF/68k by Andreas Schwab. + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_68K_NONE", + [1] "R_68K_32", "R_68K_16", "R_68K_8", + [4] "R_68K_PC32", "R_68K_PC16", "R_68K_PC8", + [7] "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8", + [10] "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O", + [13] "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8", + [16] "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O", + [19] "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE", + [23] "R_68K_NUM" +}; diff --git a/ldso/ldso/m68k/dl-startup.h b/ldso/ldso/m68k/dl-startup.h new file mode 100644 index 0000000..2ed9ead --- /dev/null +++ b/ldso/ldso/m68k/dl-startup.h @@ -0,0 +1,86 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2005 by Erik Andersen + */ + +__asm__ ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ +_start:\n\ + move.l %sp, -(%sp)\n\ + jbsr _dl_start\n\ + addq.l #4, %sp\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ +.type _dl_start_user,@function\n\ +_dl_start_user:\n\ + # Save the user entry point address in %a4.\n\ + move.l %d0, %a4\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + move.l _dl_skip_args(%pc), %d0\n\ + # Pop the original argument count\n\ + move.l (%sp)+, %d1\n\ + # Subtract _dl_skip_args from it.\n\ + sub.l %d0, %d1\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + lea (%sp, %d0*4), %sp\n\ + # Push back the modified argument count.\n\ + move.l %d1, -(%sp)\n\ + # Pass our finalizer function to the user in %a1.\n\ + lea _dl_fini(%pc), %a1\n\ + # Initialize %fp with the stack pointer.\n\ + move.l %sp, %fp\n\ + # Jump to the user's entry point.\n\ + jmp (%a4)\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) + { + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) load_addr + + (rpnt->r_addend ? : *reloc_addr)); + break; + default: + _dl_exit (1); + } +} diff --git a/ldso/ldso/m68k/dl-syscalls.h b/ldso/ldso/m68k/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/m68k/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/m68k/dl-sysdep.h b/ldso/ldso/m68k/dl-sysdep.h new file mode 100644 index 0000000..e42be31 --- /dev/null +++ b/ldso/ldso/m68k/dl-sysdep.h @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2005 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* Initialization sequence for a GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) (MODULE); \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_68K +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "m68k" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver (struct elf_resolve *, int); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("%a5"); + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr addr; + __asm__ ("lea _dl_start(%%pc), %0\n\t" + "sub.l _dl_start@GOT.w(%%a5), %0" + : "=a" (addr)); + return addr; +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c new file mode 100644 index 0000000..8f7364f --- /dev/null +++ b/ldso/ldso/m68k/elfinterp.c @@ -0,0 +1,326 @@ +/* vi: set sw=4 ts=4: */ +/* m68k ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Adapted to ELF/68k by Andreas Schwab. + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_68K_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + *got_addr = new_addr; + + return (unsigned int)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + /* handled by elf_machine_relative() + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) tpnt->loadaddr + / * Compatibility kludge. * / + + (rpnt->r_addend ? : *reloc_addr)); + */ + break; + case R_68K_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy ((void *) reloc_addr, + (void *) symbol_addr, + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef LAZY_RELOC_WORKS +#ifdef LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_JMP_SLOT: + *reloc_addr += (unsigned int) tpnt->loadaddr; + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/m68k/resolve.S b/ldso/ldso/m68k/resolve.S new file mode 100644 index 0000000..1bd5c00 --- /dev/null +++ b/ldso/ldso/m68k/resolve.S @@ -0,0 +1,28 @@ +/* + * These are various helper routines that are needed to run an ELF image. + */ + +.text +.even + +.globl _dl_linux_resolve + .type _dl_linux_resolve,@function +_dl_linux_resolve: + # Save %a0 (struct return address) and %a1. + move.l %a0, -(%sp) + move.l %a1, -(%sp) + # Call the real address resolver. + jbsr _dl_linux_resolver + # Restore register %a0 and %a1. + move.l (%sp)+, %a1 + move.l (%sp)+, %a0 + # Pop parameters + addq.l #8, %sp + # Call real function. +#if defined __mcoldfire__ + move.l %d0,-(%sp) + rts +#else + jmp (%d0) +#endif +.size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/ldso/ldso/mips/README b/ldso/ldso/mips/README new file mode 100644 index 0000000..9ca6a86 --- /dev/null +++ b/ldso/ldso/mips/README @@ -0,0 +1,52 @@ +Almost all of the code present in these source files was taken +from GLIBC. In the descriptions below, all files mentioned are +with respect to the top level GLIBC source directory accept for +code taken from the Linux kernel. + +boot1_arch.h +------------ +Contains code to fix up the stack pointer so that the dynamic +linker can find argc, argv and Auxillary Vector Table (AVT). +The code is taken from the function 'RTLD_START' in the file +'sysdeps/mips/dl-machine.h'. + +elfinterp.c +----------- +Contains the runtime resolver code taken from the function +'__dl_runtime_resolve' in 'sysdeps/mips/dl-machine.h'. Also +contains the function to perform relocations for objects +other than the linker itself. The code was taken from the +function 'elf_machine_rel' in 'sysdeps/mips/dl-machine.h'. + +dl-syscalls.h +------------- +Used to contain all the macro functions for the system calls +as well as the list of system calls supported. We now include + but with the __set_errno macro defined empty +so we can use the same file for the linker as well as userspace. +Original code was taken from the Linux kernel source 2.4.17 and +can be found in the file 'include/asm-mips/unistd.h'. + +dl-sysdep.h +----------- +Contains bootstrap code for the dynamic linker, magic numbers +for detecting MIPS target types and some macros. The macro +function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic +linker's GOT so that function calls can be made. The code is +taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the +file 'sysdeps/mips/dl-machine.h'. The other macro function +'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for +the dynamic loader. The code is taken from the function +'elf_machine_rel' in the file 'sysdeps/mips/dl-machine.h'. The +final macro function is 'INIT_GOT' which initializes the GOT +for the application being dynamically linked and loaded. The +code is taken from the functions 'elf_machine_runtime_setup' +and 'elf_machine_got_rel' in 'sysdeps/mips/dl-machine.h'. + +resolve.S +--------- +Contains the low-level assembly code for the dynamic runtime +resolver. The code is taken from the assembly code function +'_dl_runtime_resolve' in the file 'sysdeps/mips/dl-machine.h'. +The code looks a bit different since we only need to pass the +symbol index and the old GP register. diff --git a/ldso/ldso/mips/dl-debug.h b/ldso/ldso/mips/dl-debug.h new file mode 100644 index 0000000..07a2add --- /dev/null +++ b/ldso/ldso/mips/dl-debug.h @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* mips/mipsel ELF shared library loader suppport + * + Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", + [3] "R_MIPS_REL32", "R_MIPS_26", "R_MIPS_HI16", + [6] "R_MIPS_LO16", "R_MIPS_GPREL16", "R_MIPS_LITERAL", + [9] "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16", + [12] "R_MIPS_GPREL32", + [16] "R_MIPS_SHIFT5", "R_MIPS_SHIFT6", "R_MIPS_64", + [19] "R_MIPS_GOT_DISP", "R_MIPS_GOT_PAGE", "R_MIPS_GOT_OFST", + [22] "R_MIPS_GOT_HI16", "R_MIPS_GOT_LO16", "R_MIPS_SUB", + [25] "R_MIPS_INSERT_A", "R_MIPS_INSERT_B", "R_MIPS_DELETE", + [28] "R_MIPS_HIGHER", "R_MIPS_HIGHEST", "R_MIPS_CALL_HI16", + [31] "R_MIPS_CALL_LO16", "R_MIPS_SCN_DISP", "R_MIPS_REL16", + [34] "R_MIPS_ADD_IMMEDIATE", "R_MIPS_PJUMP", "R_MIPS_RELGOT", + [37] "R_MIPS_JALR", +}; diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h new file mode 100644 index 0000000..606b162 --- /dev/null +++ b/ldso/ldso/mips/dl-startup.h @@ -0,0 +1,190 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2005 by Erik Andersen + */ + + +#include +__asm__("" + " .text\n" + " .globl _start\n" + " .ent _start\n" + " .type _start,@function\n" + "_start:\n" + " .set noreorder\n" + " move $25, $31\n" + " bal 0f\n" + " nop\n" + "0:\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " .cpload $31\n" +#else /* N32 || N64 */ + " .cpsetup $31, $2, 0b\n" +#endif /* N32 || N64 */ + " move $31, $25\n" + " .set reorder\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dla $4, _DYNAMIC\n" + " sd $4, -0x7ff0($28)\n" +#else /* O32 || N32 */ + " la $4, _DYNAMIC\n" + " sw $4, -0x7ff0($28)\n" +#endif /* O32 || N32 */ + " move $4, $29\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " subu $29, 16\n" +#endif +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dla $8, .coff\n" +#else /* O32 || N32 */ + " la $8, .coff\n" +#endif /* O32 || N32 */ + " bltzal $8, .coff\n" + ".coff:\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dsubu $8, $31, $8\n" + " dla $25, _dl_start\n" + " daddu $25, $8\n" +#else /* O32 || N32 */ + " subu $8, $31, $8\n" + " la $25, _dl_start\n" + " addu $25, $8\n" +#endif /* O32 || N32 */ + " jalr $25\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " addiu $29, 16\n" +#endif + " move $16, $28\n" + " move $17, $2\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " ld $2, _dl_skip_args\n" + " beq $2, $0, 1f\n" + " ld $4, 0($29)\n" + " dsubu $4, $2\n" + " dsll $2, 2\n" + " daddu $29, $2\n" + " sd $4, 0($29)\n" + "1:\n" + " ld $5, 0($29)\n" + " dla $6, 8 ($29)\n" + " dsll $7, $5, 2\n" + " daddu $7, $7, $6\n" + " daddu $7, $7, 4\n" + " and $2, $29, -4 * 4\n" + " sd $29, -8($2)\n" + " dsubu $29, $2, 32\n" + " ld $29, 24($29)\n" + " dla $2, _dl_fini\n" +#else /* O32 || N32 */ + " lw $2, _dl_skip_args\n" + " beq $2, $0, 1f\n" + " lw $4, 0($29)\n" + " subu $4, $2\n" + " sll $2, 2\n" + " addu $29, $2\n" + " sw $4, 0($29)\n" + "1:\n" + " lw $5, 0($29)\n" + " la $6, 4 ($29)\n" + " sll $7, $5, 2\n" + " addu $7, $7, $6\n" + " addu $7, $7, 4\n" + " and $2, $29, -2 * 4\n" + " sw $29, -4($2)\n" + " subu $29, $2, 32\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " .cprestore 16\n" +#endif + " lw $29, 28($29)\n" + " la $2, _dl_fini\n" +#endif /* O32 || N32 */ + " move $25, $17\n" + " jr $25\n" + ".end _start\n" + ".size _start, . -_start\n" + "\n\n" + "\n\n" + ".previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1) + + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + + +/* + * Here is a macro to perform the GOT relocation. This is only + * used when bootstrapping the dynamic loader. + */ +#define PERFORM_BOOTSTRAP_GOT(tpnt) \ +do { \ + ElfW(Sym) *sym; \ + ElfW(Addr) i; \ + register ElfW(Addr) gp __asm__ ("$28"); \ + ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp); \ + \ + /* Add load address displacement to all local GOT entries */ \ + i = 2; \ + while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ + mipsgot[i++] += tpnt->loadaddr; \ + \ + /* Handle global GOT entries */ \ + mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \ + sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + \ + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \ + i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\ + \ + while (i--) { \ + if (sym->st_shndx == SHN_UNDEF || \ + sym->st_shndx == SHN_COMMON) \ + *mipsgot = tpnt->loadaddr + sym->st_value; \ + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && \ + *mipsgot != sym->st_value) \ + *mipsgot += tpnt->loadaddr; \ + else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { \ + if (sym->st_other == 0) \ + *mipsgot += tpnt->loadaddr; \ + } \ + else \ + *mipsgot = tpnt->loadaddr + sym->st_value; \ + \ + mipsgot++; \ + sym++; \ + } \ +} while (0) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. + */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */ +#define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32) +#else /* N32 || O32 */ +#define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32 +#endif +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF_R_TYPE((RELP)->r_info)) { \ + case R_MIPS_BOOTSTRAP_RELOC: \ + if (SYMTAB) { \ + if (symtab_indexdynamic_info[DT_MIPS_GOTSYM_IDX])\ + *REL += SYMBOL; \ + } \ + else { \ + *REL += LOAD; \ + } \ + break; \ + case R_MIPS_NONE: \ + break; \ + default: \ + SEND_STDERR("Aiieeee!"); \ + _dl_exit(1); \ + } diff --git a/ldso/ldso/mips/dl-syscalls.h b/ldso/ldso/mips/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/mips/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h new file mode 100644 index 0000000..312b9e8 --- /dev/null +++ b/ldso/ldso/mips/dl-sysdep.h @@ -0,0 +1,220 @@ +/* vi: set sw=8 ts=8: */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include + +#ifdef __mips64 /* from glibc sysdeps/mips/elf/ldsodefs.h 1.4 */ +/* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each + relocation entry specifies up to three actual relocations, all at + the same address. The first relocation which required a symbol + uses the symbol in the r_sym field. The second relocation which + requires a symbol uses the symbol in the r_ssym field. If all + three relocations require a symbol, the third one uses a zero + value. + + We define these structures in internal headers because we're not + sure we want to make them part of the ABI yet. Eventually, some of + this may move into elf/elf.h. */ + +/* An entry in a 64 bit SHT_REL section. */ + +typedef struct +{ + Elf32_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type1; /* 1st relocation type */ +} _Elf64_Mips_R_Info; + +typedef union +{ + Elf64_Xword r_info_number; + _Elf64_Mips_R_Info r_info_fields; +} _Elf64_Mips_R_Info_union; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */ +} Elf64_Mips_Rel; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Mips_Rela; + +#define ELF64_MIPS_R_SYM(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) +#define ELF64_MIPS_R_TYPE(i) \ + (((_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1 \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_type2 << 8) \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_type3 << 16) \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_ssym << 24)) +#define ELF64_MIPS_R_INFO(sym, type) \ + (__extension__ (_Elf64_Mips_R_Info_union) \ + (__extension__ (_Elf64_Mips_R_Info) \ + { (sym), ELF64_MIPS_R_SSYM (type), \ + ELF64_MIPS_R_TYPE3 (type), \ + ELF64_MIPS_R_TYPE2 (type), \ + ELF64_MIPS_R_TYPE1 (type) \ + }).r_info_number) +/* These macros decompose the value returned by ELF64_MIPS_R_TYPE, and + compose it back into a value that it can be used as an argument to + ELF64_MIPS_R_INFO. */ +#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff) +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) +#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) +#define ELF64_MIPS_R_TYPEENC(type1, type2, type3, ssym) \ + ((type1) \ + | ((Elf32_Word)(type2) << 8) \ + | ((Elf32_Word)(type3) << 16) \ + | ((Elf32_Word)(ssym) << 24)) + +#undef ELF64_R_SYM +#define ELF64_R_SYM(i) ELF64_MIPS_R_SYM (i) +#undef ELF64_R_TYPE +#define ELF64_R_TYPE(i) ELF64_MIPS_R_TYPE (i) +#undef ELF64_R_INFO +#define ELF64_R_INFO(sym, type) ELF64_MIPS_R_INFO ((sym), (type)) +#endif /* __mips64 */ + +#include + +#define ARCH_NUM 3 +#define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM) +#define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1) +#define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_MIPS_GOTSYM) \ + dynamic[DT_MIPS_GOTSYM_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \ + dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_SYMTABNO) \ + dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \ + *(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr; \ +} while (0) + +/* Initialization sequence for the application/library GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + unsigned long idx; \ + \ + /* Check if this is the dynamic linker itself */ \ + if (MODULE->libtype == program_interpreter) \ + continue; \ + \ + /* Fill in first two GOT entries according to the ABI */ \ + GOT_BASE[0] = (unsigned long) _dl_runtime_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ + \ + /* Add load address displacement to all local GOT entries */ \ + idx = 2; \ + while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ + GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \ + \ +} while (0) + + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_MIPS +#define MAGIC2 EM_MIPS_RS3_LE + + +/* Used for error messages */ +#define ELF_TARGET "MIPS" + + +unsigned long __dl_runtime_resolve(unsigned long sym_index, + unsigned long old_gpreg); + +struct elf_resolve; +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); + +/* 4096 bytes alignment */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 +#define PAGE_ALIGN (~0xfffUL) +#define ADDR_ALIGN 0xfffUL +#define OFFS_ALIGN (0x10000000000UL-0x1000) +#else /* O32 || N32 */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 +#endif /* O32 || N32 */ + +#define elf_machine_type_class(type) ELF_RTYPE_CLASS_PLT +/* MIPS does not have COPY relocs */ +#define DL_NO_COPY_RELOCS + +#define OFFSET_GP_GOT 0x7ff0 + +static __inline__ ElfW(Addr) * +elf_mips_got_from_gpreg (ElfW(Addr) gpreg) +{ + /* FIXME: the offset of gp from GOT may be system-dependent. */ + return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT); +} + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. We assume its $gp points to the primary GOT. */ +static __inline__ ElfW(Addr) +elf_machine_dynamic (void) +{ + register ElfW(Addr) gp __asm__ ("$28"); + return *elf_mips_got_from_gpreg (gp); +} + +#define STRINGXP(X) __STRING(X) +#define STRINGXV(X) STRINGV_(X) +#define STRINGV_(...) # __VA_ARGS__ +#if _MIPS_SIM == _MIPS_SIM_ABI64 +#define PTR_LA dla +#define PTR_SUBU dsubu +#else +#define PTR_LA la +#define PTR_SUBU subu +#endif + +/* Return the run-time load address of the shared object. */ +static __inline__ ElfW(Addr) +elf_machine_load_address (void) +{ + ElfW(Addr) addr; + __asm__ (" .set noreorder\n" + " " STRINGXP (PTR_LA) " %0, 0f\n" + " bltzal $0, 0f\n" + " nop\n" + "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n" + " .set reorder\n" + : "=r" (addr) + : /* No inputs */ + : "$31"); + return addr; +} + +static __inline__ void +elf_machine_relative (ElfW(Addr) load_off, const ElfW(Addr) rel_addr, + ElfW(Word) relative_count) +{ + /* No RELATIVE relocs in MIPS? */ +} + +#ifdef __mips64 +#define DL_MALLOC_ALIGN 8 /* N64/N32 needs 8 byte alignment */ +#endif diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c new file mode 100644 index 0000000..1b03d94 --- /dev/null +++ b/ldso/ldso/mips/elfinterp.c @@ -0,0 +1,237 @@ +/* vi: set sw=4 ts=4: */ +/* mips/mipsel ELF shared library loader suppport + * + Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +extern int _dl_runtime_resolve(void); + +#define OFFSET_GP_GOT 0x7ff0 + +unsigned long __dl_runtime_resolve(unsigned long sym_index, + unsigned long old_gpreg) +{ + unsigned long *got = (unsigned long *) (old_gpreg - OFFSET_GP_GOT); + struct elf_resolve *tpnt = (struct elf_resolve *) got[1]; + ElfW(Sym) *sym; + char *strtab; + unsigned long local_gotno; + unsigned long gotsym; + unsigned long new_addr; + unsigned long instr_addr; + char **got_addr; + char *symname; + + gotsym = tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + local_gotno = tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; + + sym = ((ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]) + sym_index; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + sym->st_name; + + new_addr = (unsigned long) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + + /* Address of jump instruction to fix up */ + instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym); + got_addr = (char **) instr_addr; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = (char*)new_addr; + } +#else + *got_addr = (char*)new_addr; +#endif + + return new_addr; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + /* Nothing to do */ + return; +} + +int _dl_parse_relocation_information(struct dyn_elf *xpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + ElfW(Sym) *symtab; + ElfW(Rel) *rpnt; + char *strtab; + unsigned long i; + unsigned long *got; + unsigned long *reloc_addr=NULL; + unsigned long symbol_addr; + int reloc_type, symtab_index; + struct elf_resolve *tpnt = xpnt->dyn; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val=0; +#endif + + /* Now parse the relocation information */ + rel_size = rel_size / sizeof(ElfW(Rel)); + rpnt = (ElfW(Rel) *) rel_addr; + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT]; + + for (i = 0; i < rel_size; i++, rpnt++) { + reloc_addr = (unsigned long *) (tpnt->loadaddr + + (unsigned long) rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); +#if defined (__SUPPORT_LD_DEBUG__) + if (reloc_addr) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { +#if _MIPS_SIM == _MIPS_SIM_ABI64 + case (R_MIPS_64 << 8) | R_MIPS_REL32: +#else /* O32 || N32 */ + case R_MIPS_REL32: +#endif /* O32 || N32 */ + if (symtab_index) { + if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]) + *reloc_addr += + symtab[symtab_index].st_value + + (unsigned long) tpnt->loadaddr; + else { + *reloc_addr += got[symtab_index + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX] - + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]]; + } + } + else { + *reloc_addr += (unsigned long) tpnt->loadaddr; + } + break; + case R_MIPS_NONE: + break; + default: + { + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(1); + } + } + + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail && reloc_addr) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +/* Relocate the global GOT entries for the object */ +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy) +{ + ElfW(Sym) *sym; + char *strtab; + unsigned long i, tmp_lazy; + unsigned long *got_entry; + + for (; tpnt ; tpnt = tpnt->next) { + + /* We don't touch the dynamic linker */ + if (tpnt->libtype == program_interpreter) + continue; + + /* Setup the loop variables */ + got_entry = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]) + + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; + sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc) + _dl_dprintf(2, "_dl_perform_mips_global_got_relocations for '%s'\n", tpnt->libname); +#endif + tmp_lazy = lazy && !tpnt->dynamic_info[DT_BIND_NOW]; + /* Relocate the global GOT entries for the object */ + while (i--) { + if (sym->st_shndx == SHN_UNDEF) { + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value && tmp_lazy) { + *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + } + } + else if (sym->st_shndx == SHN_COMMON) { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + } + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + *got_entry != sym->st_value && tmp_lazy) { + *got_entry += (unsigned long) tpnt->loadaddr; + } + else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { + if (sym->st_other == 0) + *got_entry += (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + } + + got_entry++; + sym++; + } + } +} + diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S new file mode 100644 index 0000000..f5d988a --- /dev/null +++ b/ldso/ldso/mips/resolve.S @@ -0,0 +1,114 @@ +/* + * Linux dynamic resolving code for MIPS. Fixes up the GOT entry as + * indicated in register t8 and jumps to the resolved address. Shamelessly + * ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Copyright (C) 1996-2001 Kazumoto Kojima + * Copyright (C) 2002 Steven J. Hill + * + */ + +#include +.text +.align 2 +.globl _dl_runtime_resolve +.type _dl_runtime_resolve,@function +.ent _dl_runtime_resolve +_dl_runtime_resolve: +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .frame $29, 40, $31 + .set noreorder + + /* Save GP. */ + move $3, $28 + + /* Save arguments and sp value on stack. */ + subu $29, 40 + + /* Modify t9 ($25) so as to point .cpload instruction. */ + addiu $25, 12 + + /* Compute GP. */ + .set noreorder + .cpload $25 + .set reorder + + /* Save slot call pc. */ + move $2, $31 + .cprestore 32 + + /* Store function arguments from registers to stack */ + sw $15, 36($29) + sw $4, 16($29) + sw $5, 20($29) + sw $6, 24($29) + sw $7, 28($29) + + /* Setup functions args and call __dl_runtime_resolve */ + move $4, $24 + move $5, $3 + jal __dl_runtime_resolve + + /* Restore function arguments from stack to registers */ + lw $31, 36($29) + lw $4, 16($29) + lw $5, 20($29) + lw $6, 24($29) + lw $7, 28($29) + + /* Do a tail call to the original function */ + addiu $29, 40 +#else /* N32 || N64 */ + .set noreorder + + /* Save GP. */ + move $3, $28 + + /* Save arguments and sp value on stack. */ + dsubu $29, 80 + + /* Compute GP. */ + .set noreorder + .cpsetup $25, 0, _dl_runtime_resolve + .set reorder + + /* Store function arguments from registers to stack */ + sd $15, 72($29) + sd $4, 8($29) + sd $5, 16($29) + sd $6, 24($29) + sd $7, 32($29) + sd $8, 40($29) + sd $9, 48($29) + sd $10, 56($29) + sd $11, 64($29) + + /* Setup functions args and call __dl_runtime_resolve */ + move $4, $24 + move $5, $3 + jal __dl_runtime_resolve + + /* Restore function arguments from stack to registers */ + ld $31, 72($29) + ld $4, 8($29) + ld $5, 16($29) + ld $6, 24($29) + ld $7, 32($29) + ld $8, 40($29) + ld $9, 48($29) + ld $10, 56($29) + ld $11, 64($29) + + /* Do a tail call to the original function */ + .cpreturn + daddu $29, 80 +#endif /* N32 || N64 */ + move $25, $2 + jr $25 +.end _dl_runtime_resolve +.previous + diff --git a/ldso/ldso/powerpc/dl-debug.h b/ldso/ldso/powerpc/dl-debug.h new file mode 100644 index 0000000..cf203d2 --- /dev/null +++ b/ldso/ldso/powerpc/dl-debug.h @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* powerpc shared library loader suppport + * + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2003-2004 Erik Andersen + * Copyright (C) 2004 Joakim Tjernlund + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = + { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16", + "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA", + "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN", + "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN", + "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO", + "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24", + "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE", + "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32", + "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI", + "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF", + "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA", +}; diff --git a/ldso/ldso/powerpc/dl-startup.h b/ldso/ldso/powerpc/dl-startup.h new file mode 100644 index 0000000..50e72c3 --- /dev/null +++ b/ldso/ldso/powerpc/dl-startup.h @@ -0,0 +1,89 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + * Copyright (C) 2005 by Joakim Tjernlund + */ + +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " mr 3,1\n" /* Pass SP to _dl_start in r3 */ + " li 0,0\n" + " stwu 1,-16(1)\n" /* Make room on stack for _dl_start to store LR */ + " stw 0,0(1)\n" /* Clear Stack frame */ + " bl _dl_start@local\n" /* Perform relocation */ + /* Save the address of the apps entry point in CTR register */ + " mtctr 3\n" /* application entry point */ +#ifdef HAVE_ASM_PPC_REL16 + " bcl 20,31,1f\n" + "1: mflr 31\n" + " addis 31,31,_GLOBAL_OFFSET_TABLE_-1b@ha\n" + " addi 31,31,_GLOBAL_OFFSET_TABLE_-1b@l\n" +#else + " bl _GLOBAL_OFFSET_TABLE_-4@local\n" /* Put our GOT pointer in r31, */ + " mflr 31\n" +#endif + " addi 1,1,16\n" /* Restore SP */ + " lwz 7,_dl_skip_args@got(31)\n" /* load EA of _dl_skip_args */ + " lwz 7,0(7)\n" /* Load word from _dl_skip_args */ + " lwz 8,0(1)\n" /* Load argc from stack */ + " subf 8,7,8\n" /* Subtract _dl_skip_args from argc. */ + " slwi 7,7,2\n" /* Multiply by 4 */ + " stwux 8,1,7\n" /* Adjust the stack pointer to skip _dl_skip_args words and store adjusted argc on stack. */ +#if 0 + /* Try beeing SVR4 ABI compliant?, even though it is not needed for uClibc on Linux */ + /* argc */ + " lwz 3,0(1)\n" + /* find argv one word offset from the stack pointer */ + " addi 4,1,4\n" + /* find environment pointer (argv+argc+1) */ + " lwz 5,0(1)\n" + " addi 5,5,1\n" + " rlwinm 5,5,2,0,29\n" + " add 5,5,4\n" + /* pass the auxilary vector in r6. This is passed to us just after _envp. */ + "2: lwzu 0,4(6)\n" + " cmpwi 0,0\n" + " bne 2b\n" + " addi 6,6,4\n" +#endif + /* Pass a termination function pointer (in this case _dl_fini) in r3. */ + /* Paulus promized he would keep r3 zero in the exec ABI. */ + " lwz 3,_dl_fini@got(31)\n" + " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */ + " bctr\n" /* Jump to entry point */ + " .size _start,.-_start\n" + " .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + {int type=ELF32_R_TYPE((RELP)->r_info); \ + Elf32_Addr finaladdr=(SYMBOL)+(RELP)->r_addend;\ + if (type==R_PPC_RELATIVE) { \ + *REL=(Elf32_Word)(LOAD)+(RELP)->r_addend;\ + } else if (type==R_PPC_ADDR32 || type==R_PPC_GLOB_DAT) {\ + *REL=finaladdr; \ + } else if (type==R_PPC_JMP_SLOT) { \ + Elf32_Sword delta=finaladdr-(Elf32_Word)(REL);\ + *REL=OPCODE_B(delta); \ + PPC_DCBST(REL); PPC_SYNC; PPC_ICBI(REL);\ + } else { \ + _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\ + } \ + } diff --git a/ldso/ldso/powerpc/dl-syscalls.h b/ldso/ldso/powerpc/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/powerpc/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/powerpc/dl-sysdep.h b/ldso/ldso/powerpc/dl-sysdep.h new file mode 100644 index 0000000..7684822 --- /dev/null +++ b/ldso/ldso/powerpc/dl-sysdep.h @@ -0,0 +1,187 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE) + +/* Stuff for the PLT. */ +#define PLT_INITIAL_ENTRY_WORDS 18 +#define PLT_LONGBRANCH_ENTRY_WORDS 0 +#define PLT_TRAMPOLINE_ENTRY_WORDS 6 +#define PLT_DOUBLE_SIZE (1<<13) +#define PLT_ENTRY_START_WORDS(entry_number) \ + (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 \ + + ((entry_number) > PLT_DOUBLE_SIZE \ + ? ((entry_number) - PLT_DOUBLE_SIZE)*2 \ + : 0)) +#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries) + +/* Macros to build PowerPC opcode words. */ +#define OPCODE_ADDI(rd,ra,simm) \ + (0x38000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff)) +#define OPCODE_ADDIS(rd,ra,simm) \ + (0x3c000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff)) +#define OPCODE_ADD(rd,ra,rb) \ + (0x7c000214 | (rd) << 21 | (ra) << 16 | (rb) << 11) +#define OPCODE_B(target) (0x48000000 | ((target) & 0x03fffffc)) +#define OPCODE_BA(target) (0x48000002 | ((target) & 0x03fffffc)) +#define OPCODE_BCTR() 0x4e800420 +#define OPCODE_LWZ(rd,d,ra) \ + (0x80000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff)) +#define OPCODE_LWZU(rd,d,ra) \ + (0x84000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff)) +#define OPCODE_MTCTR(rd) (0x7C0903A6 | (rd) << 21) +#define OPCODE_RLWINM(ra,rs,sh,mb,me) \ + (0x54000000 | (rs) << 21 | (ra) << 16 | (sh) << 11 | (mb) << 6 | (me) << 1) + +#define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm) +#define OPCODE_ADDIS_HI(rd,ra,value) \ + OPCODE_ADDIS(rd,ra,((value) + 0x8000) >> 16) +#define OPCODE_LIS_HI(rd,value) OPCODE_ADDIS_HI(rd,0,value) +#define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh) + + +#define PPC_DCBST(where) __asm__ __volatile__ ("dcbst 0,%0" : : "r"(where) : "memory") +#define PPC_SYNC __asm__ __volatile__ ("sync" : : : "memory") +#define PPC_ISYNC __asm__ __volatile__ ("sync; isync" : : : "memory") +#define PPC_ICBI(where) __asm__ __volatile__ ("icbi 0,%0" : : "r"(where) : "memory") +#define PPC_DIE __asm__ __volatile__ ("tweq 0,0") + +/* Here we define the magic numbers that this dynamic loader should accept */ + +#define MAGIC1 EM_PPC +#undef MAGIC2 +/* Used for error messages */ +#define ELF_TARGET "powerpc" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); +void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +/* We never want to use a PLT entry as the destination of a + reloc, when what is being relocated is a branch. This is + partly for efficiency, but mostly so we avoid loops. */ +#define elf_machine_type_class(type) \ + ((((type) == R_PPC_JMP_SLOT \ + || (type) == R_PPC_REL24 \ + || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* The SVR4 ABI specifies that the JMPREL relocs must be inside the + DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* Return the value of the GOT pointer. */ +static __inline__ Elf32_Addr * __attribute__ ((const)) +ppc_got (void) +{ + Elf32_Addr *got; +#ifdef HAVE_ASM_PPC_REL16 + __asm__ (" bcl 20,31,1f\n" + "1:mflr %0\n" + " addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n" + " addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n" + : "=b" (got) : : "lr"); +#else + __asm__ (" bl _GLOBAL_OFFSET_TABLE_-4@local" + : "=l" (got)); +#endif + return got; +} + +/* Return the link-time address of _DYNAMIC, stored as + the first value in the GOT. */ +static __inline__ Elf32_Addr __attribute__ ((const)) +elf_machine_dynamic (void) +{ + return *ppc_got(); +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr __attribute__ ((const)) +elf_machine_load_address (void) +{ + Elf32_Addr *branchaddr; + Elf32_Addr runtime_dynamic; + + /* This is much harder than you'd expect. Possibly I'm missing something. + The 'obvious' way: + + Apparently, "bcl 20,31,$+4" is what should be used to load LR + with the address of the next instruction. + I think this is so that machines that do bl/blr pairing don't + get confused. + + __asm__ ("bcl 20,31,0f ;" + "0: mflr 0 ;" + "lis %0,0b@ha;" + "addi %0,%0,0b@l;" + "subf %0,%0,0" + : "=b" (addr) : : "r0", "lr"); + + doesn't work, because the linker doesn't have to (and in fact doesn't) + update the @ha and @l references; the loader (which runs after this + code) will do that. + + Instead, we use the following trick: + + The linker puts the _link-time_ address of _DYNAMIC at the first + word in the GOT. We could branch to that address, if we wanted, + by using an @local reloc; the linker works this out, so it's safe + to use now. We can't, of course, actually branch there, because + we'd cause an illegal instruction exception; so we need to compute + the address ourselves. That gives us the following code: */ + + /* Get address of the 'b _DYNAMIC@local'... */ + __asm__ ("bcl 20,31,0f;" + "b _DYNAMIC@local;" + "0:" + : "=l"(branchaddr)); + + /* So now work out the difference between where the branch actually points, + and the offset of that location in memory from the start of the file. */ + runtime_dynamic = ((Elf32_Addr) branchaddr + + ((Elf32_Sword) (*branchaddr << 6 & 0xffffff00) >> 6)); + + return runtime_dynamic - elf_machine_dynamic (); +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { /* PowerPC handles pre increment/decrement better */ + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} + +#define ARCH_NUM 1 +#define DT_PPC_GOT_IDX (DT_NUM + OS_NUM) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_PPC_GOT) \ + dynamic[DT_PPC_GOT_IDX] = dpnt->d_un.d_ptr; \ +} while (0) diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c new file mode 100644 index 0000000..eeb3250 --- /dev/null +++ b/ldso/ldso/powerpc/elfinterp.c @@ -0,0 +1,430 @@ +/* vi: set sw=4 ts=4: */ +/* powerpc shared library loader suppport + * + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2003-2004 Erik Andersen + * Copyright (C) 2004 Joakim Tjernlund + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt) +{ + Elf32_Word *tramp; + Elf32_Word num_plt_entries; + Elf32_Word data_words; + Elf32_Word rel_offset_words; + Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve; + + if (tpnt->dynamic_info[DT_JMPREL] == 0) + return; + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + tpnt->dynamic_info[DT_PPC_GOT_IDX] += tpnt->loadaddr; + return; + } + num_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC); + rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries); + data_words = (Elf32_Word) (plt + rel_offset_words); + tpnt->data_words = data_words; + + plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words); + plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11); + + plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11); + plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR(); + + /* [4] */ + /* [5] */ + tramp = (Elf32_Word *) (plt + PLT_TRAMPOLINE_ENTRY_WORDS); + + /* For the long entries, subtract off data_words. */ + tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words); + tramp[1] = OPCODE_ADDI(11,11,-data_words); + + /* Multiply index of entry by 3 (in r11). */ + tramp[2] = OPCODE_SLWI(12,11,1); + tramp[3] = OPCODE_ADD(11,12,11); + if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000) { + /* Load address of link map in r12. */ + tramp[4] = OPCODE_LI (12, (Elf32_Word) tpnt); + tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) tpnt); + + /* Call _dl_linux_resolve . */ + tramp[6] = OPCODE_BA (dlrr); + } else { + /* Get address of _dl_linux_resolve in CTR. */ + tramp[4] = OPCODE_LI(12,dlrr); + tramp[5] = OPCODE_ADDIS_HI(12,12,dlrr); + tramp[6] = OPCODE_MTCTR(12); + + /* Load address of link map in r12. */ + tramp[7] = OPCODE_LI(12,(Elf32_Word) tpnt); + tramp[8] = OPCODE_ADDIS_HI(12,12,(Elf32_Word) tpnt); + + /* Call _dl_linux_resolve. */ + tramp[9] = OPCODE_BCTR(); + } + /* [16] unused */ + /* [17] unused */ + + PPC_DCBST(plt); + PPC_DCBST(plt+4); + PPC_DCBST(plt+8); + PPC_DCBST(plt+12); + PPC_DCBST(plt+16-1); + PPC_SYNC; + PPC_ICBI(plt); + PPC_ICBI(plt+16-1); + PPC_ISYNC; +} + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rel_addr; + int symtab_index; + char *symname; + Elf32_Addr *reloc_addr; + Elf32_Addr finaladdr; + Elf32_Sword delta; + + rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (void *)rel_addr + reloc_entry; + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,this_reloc); + +#if defined (__SUPPORT_LD_DEBUG__) + if (unlikely(ELF32_R_TYPE(this_reloc->r_info) != R_PPC_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocation\n", _dl_progname); + _dl_exit(1); + } +#endif + + /* Address of dump instruction to fix up */ + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + this_reloc->r_offset); + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, (Elf32_Addr)reloc_addr); +#endif + + /* Get the address of the GOT entry */ + finaladdr = (Elf32_Addr) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!finaladdr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + finaladdr += this_reloc->r_addend; +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "%x\n", finaladdr); +#endif + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + *reloc_addr = finaladdr; + } else { + delta = finaladdr - (Elf32_Word)reloc_addr; + if (delta<<6>>6 == delta) { + *reloc_addr = OPCODE_B(delta); + } else if (finaladdr <= 0x01fffffc) { + *reloc_addr = OPCODE_BA (finaladdr); + } else { + /* Warning: we don't handle double-sized PLT entries */ + Elf32_Word *plt, *data_words, index, offset; + + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + offset = reloc_addr - plt; + index = (offset - PLT_INITIAL_ENTRY_WORDS)/2; + data_words = (Elf32_Word *)tpnt->data_words; + reloc_addr += 1; + + data_words[index] = finaladdr; + PPC_SYNC; + *reloc_addr = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4); + } + + /* instructions were modified */ + PPC_DCBST(reloc_addr); + PPC_SYNC; + PPC_ICBI(reloc_addr); + PPC_ISYNC; + } + return finaladdr; +} + +static __inline__ int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + Elf32_Addr *reloc_addr; + Elf32_Addr finaladdr; + + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + reloc_addr = (Elf32_Addr *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symbol_addr = tpnt->loadaddr; /* For R_PPC_RELATIVE */ + symtab_index = ELF32_R_SYM(rpnt->r_info); + symname = strtab + symtab[symtab_index].st_name; + if (symtab_index) { + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; + } +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + finaladdr = (Elf32_Addr) (symbol_addr + rpnt->r_addend); + + switch (reloc_type) { + case R_PPC_RELATIVE: + case R_PPC_ADDR32: + case R_PPC_GLOB_DAT: + *reloc_addr = finaladdr; + goto out_nocode; /* No code code modified */ + case R_PPC_JMP_SLOT: + { + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + *reloc_addr = finaladdr; + goto out_nocode; /* No code code modified */ + } else { + Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr; + if (delta<<6>>6 == delta) { + *reloc_addr = OPCODE_B(delta); + } else if (finaladdr <= 0x01fffffc) { + *reloc_addr = OPCODE_BA (finaladdr); + } else { + /* Warning: we don't handle double-sized PLT entries */ + Elf32_Word *plt, *data_words, index, offset; + + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + offset = reloc_addr - plt; + index = (offset - PLT_INITIAL_ENTRY_WORDS)/2; + data_words = (Elf32_Word *)tpnt->data_words; + + data_words[index] = finaladdr; + reloc_addr[0] = OPCODE_LI(11,index*4); + reloc_addr[1] = OPCODE_B((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4); + + /* instructions were modified */ + PPC_DCBST(reloc_addr+1); + PPC_SYNC; + PPC_ICBI(reloc_addr+1); + } + } + break; + } + case R_PPC_COPY: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy((char *) reloc_addr, (char *) finaladdr, symtab[symtab_index].st_size); + goto out_nocode; /* No code code modified */ + case R_PPC_ADDR16_HA: + finaladdr += 0x8000; /* fall through. */ + case R_PPC_ADDR16_HI: + finaladdr >>= 16; /* fall through. */ + case R_PPC_ADDR16_LO: + *(short *)reloc_addr = finaladdr; + break; + case R_PPC_REL24: +#if 0 + { + Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr; + if (unlikely(delta<<6>>6 != delta)) { + _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t" + "Compile shared libraries with -fPIC!\n", + _dl_progname, symname); + _dl_exit(1); + } + *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc); + break; + } +#else + _dl_dprintf(2,"R_PPC_REL24: Compile shared libraries with -fPIC!\n"); + return -1; +#endif + case R_PPC_NONE: + goto out_nocode; /* No code code modified */ + default: + _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "%s ", _dl_reltypes(reloc_type)); +#endif + if (symtab_index) + _dl_dprintf(2, "'%s'\n", symname); + return -1; + } + + /* instructions were modified */ + PPC_DCBST(reloc_addr); + PPC_SYNC; + PPC_ICBI(reloc_addr); + PPC_ISYNC; + out_nocode: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); +#endif + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + struct elf_resolve *tpnt = rpnt->dyn; + Elf32_Word *plt, offset, i, num_plt_entries, rel_offset_words; + + num_plt_entries = rel_size / sizeof(ELF_RELOC); + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + /* Secure PLT */ + Elf32_Addr *got = (Elf32_Addr *)tpnt->dynamic_info[DT_PPC_GOT_IDX]; + Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve; + + got[1] = (Elf32_Addr) dlrr; + got[2] = (Elf32_Addr) tpnt; + + /* Relocate everything in .plt by the load address offset. */ + while (num_plt_entries-- != 0) + *plt++ += tpnt->loadaddr; + return; + } + + rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries); + + /* Set up the lazy PLT entries. */ + offset = PLT_INITIAL_ENTRY_WORDS; + i = 0; + /* Warning: we don't handle double-sized PLT entries */ + while (i < num_plt_entries) { + plt[offset ] = OPCODE_LI(11, i * 4); + plt[offset+1] = OPCODE_B((PLT_TRAMPOLINE_ENTRY_WORDS + 2 - (offset+1)) * 4); + i++; + offset += 2; + } + /* Now, we've modified code. We need to write the changes from + the data cache to a second-level unified cache, then make + sure that stale data in the instruction cache is removed. + (In a multiprocessor system, the effect is more complex.) + Most of the PLT shouldn't be in the instruction cache, but + there may be a little overlap at the start and the end. + + Assumes that dcbst and icbi apply to lines of 16 bytes or + more. Current known line sizes are 16, 32, and 128 bytes. */ + for (i = 0; i < rel_offset_words; i += 4) + PPC_DCBST (plt + i); + PPC_DCBST (plt + rel_offset_words - 1); + PPC_SYNC; + PPC_ICBI (plt); + PPC_ICBI (plt + rel_offset_words - 1); + PPC_ISYNC; +} + +static __inline__ int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res <0)) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); +#endif + return res; + } + if (unlikely(res >0)) + { + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } + return 0; +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/powerpc/resolve.S b/ldso/ldso/powerpc/resolve.S new file mode 100644 index 0000000..c83337c --- /dev/null +++ b/ldso/ldso/powerpc/resolve.S @@ -0,0 +1,57 @@ +/* + * Stolen from glibc-2.2.2 by David Schleef + */ + +.text +.align 4 + +.globl _dl_linux_resolver + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: +/* We need to save the registers used to pass parameters, and register 0, + which is used by _mcount; the registers are saved in a stack frame. */ + stwu 1,-64(1) + stw 0,12(1) + stw 3,16(1) + stw 4,20(1) +/* The code that calls this has put parameters for 'fixup' in r12 and r11. */ + mr 3,12 + stw 5,24(1) + mr 4,11 + stw 6,28(1) + mflr 0 +/* We also need to save some of the condition register fields. */ + stw 7,32(1) + stw 0,48(1) + stw 8,36(1) + mfcr 0 + stw 9,40(1) + stw 10,44(1) + stw 0,8(1) + bl _dl_linux_resolver@local +/* 'fixup' returns the address we want to branch to. */ + mtctr 3 +/* Put the registers back... */ + lwz 0,48(1) + lwz 10,44(1) + lwz 9,40(1) + mtlr 0 + lwz 8,36(1) + lwz 0,8(1) + lwz 7,32(1) + lwz 6,28(1) + mtcrf 0xFF,0 + lwz 5,24(1) + lwz 4,20(1) + lwz 3,16(1) + lwz 0,12(1) +/* ...unwind the stack frame, and jump to the PLT entry we updated. */ + addi 1,1,64 + bctr + +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve + diff --git a/ldso/ldso/sh/dl-debug.h b/ldso/ldso/sh/dl-debug.h new file mode 100644 index 0000000..e862da1 --- /dev/null +++ b/ldso/ldso/sh/dl-debug.h @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* SuperH ELF shared library loader suppport + * + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_SH_NONE", "R_SH_DIR32", "R_SH_REL32", "R_SH_DIR8WPN", + [4] "R_SH_IND12W", "R_SH_DIR8WPL", "R_SH_DIR8WPZ", "R_SH_DIR8BP", + [8] "R_SH_DIR8W", "R_SH_DIR8L", + [25] "R_SH_SWITCH16","R_SH_SWITCH32","R_SH_USES", + [28] "R_SH_COUNT", "R_SH_ALIGN", "R_SH_CODE", "R_SH_DATA", + [32] "R_SH_LABEL", "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT","R_SH_GNU_VTENTRY", +[160] "R_SH_GOT32", "R_SH_PLT32", "R_SH_COPY", "R_SH_GLOB_DAT", +[164] "R_SH_JMP_SLOT","R_SH_RELATIVE","R_SH_GOTOFF", "R_SH_GOTPC", +}; diff --git a/ldso/ldso/sh/dl-startup.h b/ldso/ldso/sh/dl-startup.h new file mode 100644 index 0000000..7a3fdf2 --- /dev/null +++ b/ldso/ldso/sh/dl-startup.h @@ -0,0 +1,68 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. */ + +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " mov r15, r4\n" + " mov.l .L_dl_start, r0\n" + " bsrf r0\n" + " add #4, r4\n" + ".jmp_loc:\n" + " mov r0, r8 ! Save the user entry point address in r8\n" + " mov.l .L_got, r12 ! Load the GOT on r12\n" + " mova .L_got, r0\n" + " add r0, r12\n" + " mov.l .L_dl_fini, r0\n" + " mov.l @(r0,r12), r4 ! Pass the finalizer in r4\n" + " jmp @r8\n" + " nop\n" + ".L_dl_start:\n" + " .long _dl_start-.jmp_loc\n" + ".L_dl_fini:\n" + " .long _dl_fini@GOT\n" + ".L_got:\n" + " .long _GLOBAL_OFFSET_TABLE_\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_SH_REL32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + break; \ + case R_SH_DIR32: \ + case R_SH_GLOB_DAT: \ + case R_SH_JMP_SLOT: \ + *(REL) = (SYMBOL) + (RELP)->r_addend; \ + break; \ + case R_SH_RELATIVE: \ + *(REL) = (LOAD) + (RELP)->r_addend; \ + break; \ + case R_SH_NONE: \ + break; \ + default: \ + _dl_exit(1); \ + } diff --git a/ldso/ldso/sh/dl-syscalls.h b/ldso/ldso/sh/dl-syscalls.h new file mode 100644 index 0000000..712852c --- /dev/null +++ b/ldso/ldso/sh/dl-syscalls.h @@ -0,0 +1,14 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + +#if __GNUC_PREREQ (4, 1) +#warning !!! gcc 4.1 and later have problems with __always_inline so redefined as inline +# ifdef __always_inline +# undef __always_inline +# define __always_inline __inline__ +# endif +#endif diff --git a/ldso/ldso/sh/dl-sysdep.h b/ldso/ldso/sh/dl-sysdep.h new file mode 100644 index 0000000..fd0f236 --- /dev/null +++ b/ldso/ldso/sh/dl-sysdep.h @@ -0,0 +1,174 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) (MODULE); \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_SH +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "sh" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +static __inline__ unsigned int +_dl_urem(unsigned int n, unsigned int base) +{ + int res; + + __asm__ (""\ + "mov #0, r0\n\t" \ + "div0u\n\t" \ + "" \ + "! get one bit from the msb of the numerator into the T\n\t" \ + "! bit and divide it by whats in %2. Put the answer bit\n\t" \ + "! into the T bit so it can come out again at the bottom\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1\n\t" + : "=r" (res) + : "0" (n), "r" (base) + : "r0","cc"); + + return n - (base * res); +} + +#define do_rem(result, n, base) ((result) = _dl_urem((n), (base))) + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + register Elf32_Addr *got; + __asm__ ("mov r12,%0" :"=r" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + Elf32_Addr addr; + __asm__ ("mov.l 1f,r0\n\ + mov.l 3f,r2\n\ + add r12,r2\n\ + mov.l @(r0,r12),r0\n\ + bra 2f\n\ + sub r0,r2\n\ + .align 2\n\ + 1: .long _dl_start@GOT\n\ + 3: .long _dl_start@GOTOFF\n\ + 2: mov r2,%0" + : "=r" (addr) : : "r0", "r1", "r2"); + return addr; +} + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Addr value; + Elf32_Rela * rpnt = (void *)rel_addr; + + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset); + + if (rpnt->r_addend) + value = load_off + rpnt->r_addend; + else { + COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3); + value += load_off; + } + COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3); + rpnt++; + } while (--relative_count); +#undef COPY_UNALIGNED_WORD +} diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c new file mode 100644 index 0000000..6cb8e08 --- /dev/null +++ b/ldso/ldso/sh/elfinterp.c @@ -0,0 +1,285 @@ +/* vi: set sw=4 ts=4: */ +/* SuperH ELF shared library loader suppport + * + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_SH_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of jump instruction to fix up */ + instr_addr = (unsigned long) (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **) instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long) got_addr < 0x20000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + /* Now parse the relocation information */ + + rpnt = (ELF_RELOC *)(intptr_t) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + + /* + * The caller should handle the error: undefined reference to weak symbols + * are not fatal. + */ + return 1; + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy((char *) reloc_addr, (char *) symbol_addr, symtab[symtab_index].st_size); + } + return 0; /* no further LD_DEBUG messages for copy relocs */ + case R_SH_DIR32: + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_SH_REL32: + *reloc_addr = symbol_addr + rpnt->r_addend - + (unsigned long) reloc_addr; + break; + case R_SH_RELATIVE: + *reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend; + break; + default: + + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_JMP_SLOT: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); +#endif + return 0; + +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/sh/resolve.S b/ldso/ldso/sh/resolve.S new file mode 100644 index 0000000..e66d316 --- /dev/null +++ b/ldso/ldso/sh/resolve.S @@ -0,0 +1,98 @@ +/* + * Stolen from glibc-2.2.2 by Eddie C. Dost + */ + + .text + .globl _dl_linux_resolver + .globl _dl_linux_resolve + .type _dl_linux_resolve, @function + .balign 16 +_dl_linux_resolve: + mov.l r2, @-r15 ! see Note2 below + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + mov.l r12, @-r15 + movt r3 ! Save T flag + mov.l r3, @-r15 + +#ifdef HAVE_FPU + sts.l fpscr, @-r15 + mov #8,r3 + swap.w r3, r3 + lds r3, fpscr + fmov.s fr11, @-r15 + fmov.s fr10, @-r15 + fmov.s fr9, @-r15 + fmov.s fr8, @-r15 + fmov.s fr7, @-r15 + fmov.s fr6, @-r15 + fmov.s fr5, @-r15 + fmov.s fr4, @-r15 +#endif + sts.l pr, @-r15 +/* Note - The PLT entries have been "optimised" not to use r2. r2 is used by + GCC to return the address of large structures, so it should not be + corrupted here. This does mean however, that those PLTs does not conform + to the SH PIC ABI. That spec says that r0 contains the type of the PLT + and r2 contains the GOT id. The GNU Plt version stores the GOT id in r0 and + ignores the type. We can easily detect this difference however, + since the type will always be 0 or 8, and the GOT ids will always be + greater than or equal to 12. + + Found in binutils/bfd/elf32-sh.c by Stefan Allius + + Note2 - we also have to preserve r2 on the stack as the call into + C code (_dl_linux_resolver) will use r2 as a scratch register and we + need it for the address for returning structures, + David McCullough . + */ + mov #8 ,r5 + cmp/gt r5, r0 + bt 1f + mov r2, r0 ! link map address in r2 (SH PIC ABI) +1: + mov r0, r4 ! link map address in r0 (GNUs PLT) + mova .LG, r0 + mov.l .LG, r5 + add r5, r0 + mov.l 3f, r5 + mov.l @(r0, r5),r5 + jsr @r5 + mov r1, r5 ! Reloc offset + + lds.l @r15+, pr ! Get register content back + +#ifdef HAVE_FPU + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + lds.l @r15+, fpscr +#endif + + mov.l @r15+, r3 + shal r3 ! Load T flag + mov.l @r15+, r12 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + jmp @r0 ! Jump to function address + mov.l @r15+, r2 ! see Note2 above + + .balign 4 + +3: + .long _dl_linux_resolver@GOT +.LG: + .long _GLOBAL_OFFSET_TABLE_ + .size _dl_linux_resolve, . - _dl_linux_resolve + diff --git a/ldso/ldso/sh64/dl-debug.h b/ldso/ldso/sh64/dl-debug.h new file mode 100644 index 0000000..485aac7 --- /dev/null +++ b/ldso/ldso/sh64/dl-debug.h @@ -0,0 +1,79 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/elfinterp.c + * + * SuperH (sh64) ELF shared library loader suppport + * + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + /* SHcompact relocs */ + [0] = "R_SH_NONE", "R_SH_DIR32", + "R_SH_REL32", "R_SH_DIR8WPN", + [4] = "R_SH_IND12W", "R_SH_DIR8WPL", + "R_SH_DIR8WPZ", "R_SH_DIR8BP", + [8] = "R_SH_DIR8W", "R_SH_DIR8L", + [25] = "R_SH_SWITCH16", "R_SH_SWITCH32", + "R_SH_USES", "R_SH_COUNT", + [29] = "R_SH_ALIGN", "R_SH_CODE", + "R_SH_DATA", "R_SH_LABEL", + [33] = "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT", + "R_SH_GNU_VTENTRY", + [160] = "R_SH_GOT32", "R_SH_PLT32", + "R_SH_COPY", "R_SH_GLOB_DAT", + [164] = "R_SH_JMP_SLOT", "R_SH_RELATIVE", + "R_SH_GOTOFF", "R_SH_GOTPC", + + /* SHmedia relocs */ + [45] = "R_SH_DIR5U", "R_SH_DIR6U", + "R_SH_DIR6S", "R_SH_DIR10S", + [49] = "R_SH_DIR10SW", "R_SH_DIR10SL", + "R_SH_DIR10SQ", + [169] = "R_SH_GOT_LOW16", "R_SH_GOT_MEDLOW16", + "R_SH_GOT_MEDHI16", "R_SH_GOT_HI16", + [173] = "R_SH_GOTPLT_LOW16", "R_SH_GOTPLT_MEDLOW16", + "R_SH_GOTPLT_MEDHI16", "R_SH_GOTPLT_HI16", + [177] = "R_SH_PLT_LOW16", "R_SH_PLT_MEDLOW16", + "R_SH_PLT_MEDHI16", "R_SH_PLT_HI16", + [181] = "R_SH_GOTOFF_LOW16", "R_SH_GOTOFF_MEDLOW16", + "R_SH_GOTOFF_MEDHI16", "R_SH_GOTOFF_HI16", + [185] = "R_SH_GOTPC_LOW16", "R_SH_GOTPC_MEDLOW16", + "R_SH_GOTPC_MEDHI16", "R_SH_GOTPC_HI16", + [189] = "R_SH_GOT10BY4", "R_SH_GOTPLT10BY4", + "R_SH_GOT10BY8", "R_SH_GOTPLT10BY8", + [193] = "R_SH_COPY64", "R_SH_GLOB_DAT64", + "R_SH_JMP_SLOT64", "R_SH_RELATIVE64", + [197] = "R_SH_RELATIVE_LOW16", "R_SH_RELATIVE_MEDLOW16", + "R_SH_RELATIVE_MEDHI16","R_SH_RELATIVE_HI16", + [242] = "R_SH_SHMEDIA_CODE", "R_SH_PT_16", + "R_SH_IMMS16", "R_SH_IMMU16", + [246] = "R_SH_IMM_LOW16", "R_SH_IMM_LOW16_PCREL", + "R_SH_IMM_MEDLOW16", "R_SH_IMM_MEDLOW16_PCREL", + [250] = "R_SH_IMM_MEDHI16", "R_SH_IMM_MEDHI16_PCREL", + "R_SH_IMM_HI16", "R_SH_IMM_HI16_PCREL", + [254] = "R_SH_64", "R_SH_64_PCREL", +}; diff --git a/ldso/ldso/sh64/dl-startup.h b/ldso/ldso/sh64/dl-startup.h new file mode 100644 index 0000000..33512a9 --- /dev/null +++ b/ldso/ldso/sh64/dl-startup.h @@ -0,0 +1,117 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + */ + +__asm__("" \ +" .section .text..SHmedia32,\"ax\"\n" \ +" .globl _start\n" \ +" .type _start, @function\n" \ +" .align 5\n" \ +"_start:\n" \ +" ! Set r12 to point to GOT\n" \ +" movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) >> 16) & 0xffff), r12\n" \ +" shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) & 0xffff), r12\n" \ +".LZZZ3:\n" \ +" ptrel/u r12, tr0\n" \ +" gettr tr0, r12 ! GOT address\n" \ +" add r18, r63, r11 ! save return address - needed?\n" \ +" add r15, r63, r2 ! arg = stack pointer\n" \ +" pt _dl_start, tr0 ! should work even if PIC\n" \ +" blink tr0, r18 ! call _dl_start - user EP is in r2\n" \ +" add r2, r63, r28\n" \ +" movi (((_dl_fini@GOT) >> 16) & 0xffff), r1\n" \ +" shori ((_dl_fini@GOT) & 0xffff), r1\n" \ +" ldx.l r1, r12, r2\n" \ +" add r11, r63, r18\n" \ +" ptabs/l r28, tr0\n" \ +" blink tr0, r63\n" \ +" .size _start,.-_start\n" +" .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *)ARGS)+1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ + +#include + +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + const unsigned int r_type = ELF32_R_TYPE((RELP)->r_info); \ + int lsb = !!((SYMTAB)->st_other & STO_SH5_ISA32); \ + \ + switch (r_type) { \ + case R_SH_REL32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + break; \ + case R_SH_DIR32: \ + case R_SH_GLOB_DAT: \ + case R_SH_JMP_SLOT: \ + *(REL) = ((SYMBOL) + (RELP)->r_addend) | lsb; \ + break; \ + case R_SH_RELATIVE: \ + *(REL) = (LOAD) + (RELP)->r_addend; \ + break; \ + case R_SH_RELATIVE_LOW16: \ + case R_SH_RELATIVE_MEDLOW16: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = (LOAD) + (RELP)->r_addend; \ + \ + if (r_type == R_SH_RELATIVE_MEDLOW16) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_IMM_LOW16: \ + case R_SH_IMM_MEDLOW16: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = ((SYMBOL) + (RELP)->r_addend) | lsb; \ + \ + if (r_type == R_SH_IMM_MEDLOW16) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_IMM_LOW16_PCREL: \ + case R_SH_IMM_MEDLOW16_PCREL: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + \ + if (r_type == R_SH_IMM_MEDLOW16_PCREL) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_NONE: \ + break; \ + default: \ + _dl_exit(1); \ + } diff --git a/ldso/ldso/sh64/dl-syscalls.h b/ldso/ldso/sh64/dl-syscalls.h new file mode 100644 index 0000000..4fe50fa --- /dev/null +++ b/ldso/ldso/sh64/dl-syscalls.h @@ -0,0 +1,25 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + +#undef __syscall_return +#define __syscall_return(type, res) \ +do { \ + /* \ + * Note: when returning from kernel the return value is in r9 \ + * \ + * This prevents conflicts between return value and arg1 \ + * when dispatching signal handler, in other words makes \ + * life easier in the system call epilogue (see entry.S) \ + */ \ + register unsigned long __sr2 __asm__ ("r2") = res; \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + _dl_errno = -(res); \ + __sr2 = -1; \ + } \ + return (type)(__sr2); \ +} while (0) + diff --git a/ldso/ldso/sh64/dl-sysdep.h b/ldso/ldso/sh64/dl-sysdep.h new file mode 100644 index 0000000..21bfffc --- /dev/null +++ b/ldso/ldso/sh64/dl-sysdep.h @@ -0,0 +1,169 @@ +/* vi: set sw=8 ts=8: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long)_dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long)(MODULE); \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_SH +#undef MAGIC2 +/* Used for error messages */ +#define ELF_TARGET "sh64" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr elf_machine_dynamic(void) +{ + register Elf32_Addr *got; + + /* + * The toolchain adds 32768 to the GOT address, we compensate for + * that in the movi/sub pair. + * + * XXX: If this is cleaned up in the toolchain, we can end up + * saving 2 instructions and subsequently free up r1 from the + * clobber list.. + */ + __asm__ ( + "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) >> 16) & 0xffff), r2\n\t" + "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) & 0xffff), r2\n\t" + ".LZZZ1:\tptrel/u r2, tr0\n\t" + "movi\t32768, r1\n\t" + "gettr\ttr0, r2\n\t" + "sub\tr2, r1, %0\n\t" + : "=r" (got) + : /* no inputs */ + : "r1", "r2", "tr0" + ); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr elf_machine_load_address(void) +{ + Elf32_Addr addr; + + __asm__ ( + "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) >> 16) & 0xffff), r0\n\t" + "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) & 0xffff), r0\n\t" + ".LZZZ2:\tptrel/u r0, tr0\n\t" + "movi\t(((_dl_start@GOTOFF) >> 16) & 0xffff), r2\n\t" + "shori\t((_dl_start@GOTOFF) & 0xffff), r2\n\t" + "gettr\ttr0, r0\n\t" + "add\tr2, r0, r2\n\t" + "movi\t(((_dl_start@GOT) >> 16) & 0xffff), r1\n\t" + "shori\t((_dl_start@GOT) & 0xffff), r1\n\t" + "ldx.l\tr1, r0, r1\n\t" + "sub\tr2, r1, %0\n\t" + : "=r" (addr) + : /* no inputs */ + : "r0", "r1", "r2", "tr0" + ); + + return addr; +} + +/* + * XXX: As we don't need to worry about r25 clobbering, we could probably + * get away with inlining {st,ld}{x,}.l and friends here instead and + * forego gcc's idea of code generation. + */ +#define COPY_UNALIGNED_WORD(swp, twp, align) \ +{ \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + \ + switch ((align)) { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ +} + +static __inline__ void +elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Addr value, word; + Elf32_Rela *rpnt = (void *)rel_addr; + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + + do { + Elf32_Addr *const reloc_addr = + (void *)(load_off + rpnt->r_offset); + int align = (int)reloc_addr & 3; + + switch (reloc_type) { + case R_SH_RELATIVE_LOW16: + COPY_UNALIGNED_WORD(reloc_addr, &word, align); + word &= ~0x3fffc00; + value = (rpnt->r_addend + load_off); + word |= (value & 0xffff) << 10; + COPY_UNALIGNED_WORD(&word, reloc_addr, align); + break; + case R_SH_RELATIVE_MEDLOW16: + COPY_UNALIGNED_WORD(reloc_addr, &word, align); + word &= ~0x3fffc00; + value = (rpnt->r_addend + load_off) >> 16; + word |= (value & 0xffff) << 10; + COPY_UNALIGNED_WORD(&word, reloc_addr, align); + break; + default: + if (rpnt->r_addend) { + value = load_off + rpnt->r_addend; + } else { + COPY_UNALIGNED_WORD(reloc_addr, &value, align); + value += load_off; + } + + COPY_UNALIGNED_WORD(&value, reloc_addr, align); + break; + } + + rpnt++; + } while (--relative_count); +#undef COPY_UNALIGNED_WORD +} diff --git a/ldso/ldso/sh64/elfinterp.c b/ldso/ldso/sh64/elfinterp.c new file mode 100644 index 0000000..845ff4f --- /dev/null +++ b/ldso/ldso/sh64/elfinterp.c @@ -0,0 +1,346 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/elfinterp.c + * + * SuperH (sh64) ELF shared library loader suppport + * + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_SH_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump reloc\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of jump instruction to fix up */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + +#ifdef __SUPPORT_LD_DEBUG__ + if ((unsigned long)got_addr < 0x20000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", + symname); + + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, + struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, + char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#ifdef __SUPPORT_LD_DEBUG__ + "%s\n", _dl_reltypes(reloc_type) +#else + "%x\n", reloc_type +#endif + ); + + _dl_exit(-res); + } + if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + + return res; + } + } + + return 0; +} + +static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index, lsb; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#ifdef __SUPPORT_LD_DEBUG__ + unsigned long old_val; +#endif + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32); + symname = strtab + symtab[symtab_index].st_name; + reloc_addr = (unsigned long *)(intptr_t) + (tpnt->loadaddr + (unsigned long)rpnt->r_offset); + + if (symtab_index) { + int stb; + + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + stb = ELF32_ST_BIND(symtab[symtab_index].st_info); + + if (stb != STB_WEAK && !symbol_addr) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#ifdef __SUPPORT_LD_DEBUG__ + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_COPY: + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, symtab[symtab_index].st_size); + break; + case R_SH_DIR32: + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + *reloc_addr = (symbol_addr + rpnt->r_addend) | lsb; + break; + case R_SH_REL32: + *reloc_addr = symbol_addr + rpnt->r_addend - + (unsigned long)reloc_addr; + break; + case R_SH_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + case R_SH_RELATIVE_LOW16: + case R_SH_RELATIVE_MEDLOW16: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + + if (reloc_type == R_SH_RELATIVE_MEDLOW16) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + case R_SH_IMM_LOW16: + case R_SH_IMM_MEDLOW16: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = (symbol_addr + rpnt->r_addend) | lsb; + + if (reloc_type == R_SH_IMM_MEDLOW16) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + case R_SH_IMM_LOW16_PCREL: + case R_SH_IMM_MEDLOW16_PCREL: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = symbol_addr + rpnt->r_addend - + (unsigned long)reloc_addr; + + if (reloc_type == R_SH_IMM_MEDLOW16_PCREL) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + default: + return -1; /*call _dl_exit(1) */ + } + +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type, symtab_index, lsb; + unsigned long *reloc_addr; +#ifdef __SUPPORT_LD_DEBUG__ + unsigned long old_val; +#endif + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32); + reloc_addr = (unsigned long *)(intptr_t) + (tpnt->loadaddr + (unsigned long)rpnt->r_offset); + +#ifdef __SUPPORT_LD_DEBUG__ + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr | lsb; + break; + default: + return -1; /*call _dl_exit(1) */ + } + +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/sh64/resolve.S b/ldso/ldso/sh64/resolve.S new file mode 100644 index 0000000..ca915d2 --- /dev/null +++ b/ldso/ldso/sh64/resolve.S @@ -0,0 +1,95 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/resolve.S + * + * SuperH (sh64) dynamic resolver support + * + * Copyright (C) 2003 Paul Mundt + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + + .section .text..SHmedia32,"ax" + .globl _dl_linux_resolver + .globl _dl_linux_resolve + .type _dl_linux_resolve, @function + + .balign 16 +_dl_linux_resolve: + addi r15, -72, r15 ! make room on the stack + pt _dl_linux_resolver, tr0 + st.q r15, 0, r2 ! save regs + st.q r15, 8, r3 + st.q r15, 16, r4 + st.q r15, 24, r5 + st.q r15, 32, r6 + st.q r15, 40, r7 + st.q r15, 48, r8 + st.q r15, 56, r9 + st.q r15, 64, r18 + +#ifdef HAVE_FPU + addi r15, -48, r15 ! make room for FP regs + fst.d r15, 0, dr0 ! save FP regs + fst.d r15, 8, dr2 + fst.d r15, 16, dr4 + fst.d r15, 24, dr6 + fst.d r15, 32, dr8 + fst.d r15, 40, dr10 +#endif + + /* + * Args for _dl_linux_resolver(), set in r17/r21 by PLT code + */ + + add r17, r63, r2 ! link map address + add r21, r63, r3 ! GOT offset + blink tr0, r18 ! call _dl_linux_resolver() + ptabs/l r2, tr0 ! save result = addr of function called + +#ifdef HAVE_FPU + fld.d r15, 0, dr0 ! restore FP regs + fld.d r15, 8, dr2 + fld.d r15, 16, dr4 + fld.d r15, 24, dr6 + fld.d r15, 32, dr8 + fld.d r15, 40, dr10 + addi r15, 48, r15 +#endif + + ld.q r15, 0, r2 ! restore regs + ld.q r15, 8, r3 + ld.q r15, 16, r4 + ld.q r15, 24, r5 + ld.q r15, 32, r6 + ld.q r15, 40, r7 + ld.q r15, 48, r8 + ld.q r15, 56, r9 + ld.q r15, 64, r18 + + addi r15, 72, r15 + blink tr0, r63 ! jump to function address + + .size _dl_linux_resolve, . - _dl_linux_resolve + diff --git a/ldso/ldso/sparc/dl-debug.h b/ldso/ldso/sparc/dl-debug.h new file mode 100644 index 0000000..1249f77 --- /dev/null +++ b/ldso/ldso/sparc/dl-debug.h @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* sparc ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char * _dl_reltypes_tab[] = { + "R_SPARC_NONE", "R_SPARC_8", + "R_SPARC_16", "R_SPARC_32", "R_SPARC_DISP8", "R_SPARC_DISP16", + "R_SPARC_DISP32", "R_SPARC_WDISP30", "R_SPARC_WDISP22", + "R_SPARC_HI22", "R_SPARC_22", "R_SPARC_13", "R_SPARC_LO10", + "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", "R_SPARC_PC10", + "R_SPARC_PC22", "R_SPARC_WPLT30", "R_SPARC_COPY", + "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", "R_SPARC_RELATIVE", + "R_SPARC_UA32" +}; diff --git a/ldso/ldso/sparc/dl-startup.h b/ldso/ldso/sparc/dl-startup.h new file mode 100644 index 0000000..cc11ec1 --- /dev/null +++ b/ldso/ldso/sparc/dl-startup.h @@ -0,0 +1,78 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. See arm/boot1_arch.h for an example of what + * can be done. + */ + +__asm__ ("\ + .text\n\ + .global _start\n\ + .type _start,%function\n\ + .align 32\n\ + .register %g2, #scratch\n\ +_start:\n\ + /* Allocate space for functions to drop their arguments. */\n\ + sub %sp, 6*4, %sp\n\ + /* Pass pointer to argument block to _dl_start. */\n\ + call _dl_start\n\ + add %sp, 22*4, %o0\n\ + /* FALTHRU */\n\ + .globl _dl_start_user\n\ + .type _dl_start_user, @function\n\ +_dl_start_user:\n\ + /* Load the PIC register. */\n\ +1: call 2f\n\ + sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ +2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ + add %l7, %o7, %l7\n\ + /* Save the user entry point address in %l0 */\n\ + mov %o0, %l0\n\ + /* See if we were run as a command with the executable file name as an\n\ + extra leading argument. If so, adjust the contents of the stack. */\n\ + sethi %hi(_dl_skip_args), %g2\n\ + or %g2, %lo(_dl_skip_args), %g2\n\ + ld [%l7+%g2], %i0\n\ + ld [%i0], %i0\n\ + tst %i0\n\ + /* Pass our finalizer function to the user in %g1. */\n\ + sethi %hi(_dl_fini), %g1\n\ + or %g1, %lo(_dl_fini), %g1\n\ + ld [%l7+%g1], %g1\n\ + /* Jump to the user's entry point and deallocate the extra stack we got. */\n\ + jmp %l0\n\ + add %sp, 6*4, %sp\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. We assume that argc is stored + * at the word just below the argvp that we return here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ +switch(ELF_R_TYPE((RELP)->r_info)) { \ + case R_SPARC_32: \ + case R_SPARC_GLOB_DAT: \ + *REL = SYMBOL + (RELP)->r_addend; \ + break; \ + case R_SPARC_JMP_SLOT: \ + REL[1] = 0x03000000 | ((SYMBOL >> 10) & 0x3fffff); \ + REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \ + break; \ + case R_SPARC_NONE: \ + case R_SPARC_WDISP30: \ + break; \ + case R_SPARC_RELATIVE: \ + *REL += (unsigned int) LOAD + (RELP)->r_addend; \ + break; \ + default: \ + _dl_exit(1); \ +} diff --git a/ldso/ldso/sparc/dl-syscalls.h b/ldso/ldso/sparc/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/sparc/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/sparc/dl-sysdep.h b/ldso/ldso/sparc/dl-sysdep.h new file mode 100644 index 0000000..27cb97e --- /dev/null +++ b/ldso/ldso/sparc/dl-sysdep.h @@ -0,0 +1,171 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. For the Sparc, this points to the + * PLT, and we need to initialize a couple of the slots. The PLT should + * look like: + * + * save %sp, -64, %sp + * call _dl_linux_resolve + * nop + * .word implementation_dependent + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = 0x9de3bfc0; /* save %sp, -64, %sp */ \ + GOT_BASE[1] = 0x40000000 | (((unsigned int) _dl_linux_resolve - (unsigned int) GOT_BASE - 4) >> 2); \ + GOT_BASE[2] = 0x01000000; /* nop */ \ + GOT_BASE[3] = (int) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept + * Note that SPARCV9 doesn't use EM_SPARCV9 since the userland is still 32-bit. + */ +#if defined(__sparc_v9__) || defined(__sparc_v8__) +#define MAGIC1 EM_SPARC32PLUS +#else +#define MAGIC1 EM_SPARC +#endif + +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "sparc" + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* + * Define this if you want a dynamic loader that works on Solaris. + */ + +#ifndef COMPILE_ASM +/* Cheap modulo implementation, taken from arm/ld_sysdep.h. */ +static __inline__ unsigned long +sparc_mod(unsigned long m, unsigned long p) +{ + unsigned long i, t, inc; + + i = p; + t = 0; + + while (!(i & (1 << 31))) { + i <<= 1; + t++; + } + + t--; + + for (inc = t; inc > 2; inc--) { + i = p << inc; + + if (i & (1 << 31)) + break; + + while (m >= i) { + m -= i; + i <<= 1; + if (i & (1 << 31)) + break; + if (i < p) + break; + } + } + + while (m >= p) + m -= p; + + return m; +} + +#define do_rem(result, n, base) ((result) = sparc_mod(n, base)) +#endif + +/* 4096 bytes alignment */ +#if defined(__sparc_v9__) +/* ...but 8192 is required for mmap() on sparc64 kernel */ +#define PAGE_ALIGN 0xffffe000 +#define ADDR_ALIGN 0x1fff +#define OFFS_ALIGN 0x7fffe000 +#elif defined(__sparc_v8__) +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 +#endif + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* The SPARC overlaps DT_RELA and DT_PLTREL. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* We have to do this because elf_machine_{dynamic,load_address} can be + invoked from functions that have no GOT references, and thus the compiler + has no obligation to load the PIC register. */ +#define LOAD_PIC_REG(PIC_REG) \ +do { register Elf32_Addr pc __asm__("o7"); \ + __asm__("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call 1f\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \ + "1:\tadd %1, %0, %1" \ + : "=r" (pc), "=r" (PIC_REG)); \ +} while (0) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __inline__ Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("%l7"); + + LOAD_PIC_REG (got); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr +elf_machine_load_address (void) +{ + register Elf32_Addr *pc __asm__ ("%o7"), *got __asm__ ("%l7"); + + __asm__ ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" + "call 1f\n\t" + " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" + "call _DYNAMIC\n\t" + "call _GLOBAL_OFFSET_TABLE_\n" + "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got)); + + /* got is now l_addr + _GLOBAL_OFFSET_TABLE_ + *got is _DYNAMIC + pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8 + pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12 */ + return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4; +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c new file mode 100644 index 0000000..9b425fc --- /dev/null +++ b/ldso/ldso/sparc/elfinterp.c @@ -0,0 +1,372 @@ +/* vi: set sw=4 ts=4: */ +/* sparc ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +/* Program to load an ELF binary on a linux system, and run it. +References to symbols in sharable libraries can be resolved by either +an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +/* Some SPARC opcodes we need to use for self-modifying code. */ +#define OPCODE_NOP 0x01000000 /* nop */ +#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ +#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ +#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ +#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + /* + * Generate the correct relocation index into the .rela.plt section. + */ + reloc_entry = (reloc_entry >> 10) - 0xc; + + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + { + got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff)); + got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff)); + } + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */ + + switch (reloc_type) { + case R_SPARC_NONE: + break; + +#if 0 /* these dont really seem to be useful */ + case R_SPARC_8: + *(char *) reloc_addr = symbol_addr; + break; + case R_SPARC_16: + *(short *) reloc_addr = symbol_addr; + break; + case R_SPARC_DISP8: + *(char *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; + case R_SPARC_DISP16: + *(short *) reloc_addr = (symbol_addr) - (Elf32_Addr) reloc_addr; + break; +#endif + + case R_SPARC_DISP32: + *reloc_addr = symbol_addr - (unsigned int) reloc_addr; + break; + + case R_SPARC_LO10: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff); + break; + + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + *reloc_addr = symbol_addr; + break; + + case R_SPARC_JMP_SLOT: +/* +value = symbol_addr; +value += reloc->r_addend; +disp = value - reloc_addr; +reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff); +reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10); + reloc_addr[1] = OPCODE_JMP_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) & 0x3ff); + reloc_addr[0] = OPCODE_SETHI_G1 | ((symbol_addr-(Elf32_Addr)reloc_addr) >> 10); +*/ + reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff); + reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff); + break; + + case R_SPARC_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + case R_SPARC_WDISP30: + *reloc_addr = (*reloc_addr & 0xc0000000)| + ((symbol_addr - (unsigned int) reloc_addr) >> 2); + break; + + case R_SPARC_HI22: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10); + break; + + case R_SPARC_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef __SPARC_LAZY_RELOC_WORKS +#ifdef __SPARC_LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef __SPARC_LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/sparc/resolve.S b/ldso/ldso/sparc/resolve.S new file mode 100644 index 0000000..253400a --- /dev/null +++ b/ldso/ldso/sparc/resolve.S @@ -0,0 +1,22 @@ +/* + * These are various helper routines that are needed to run an ELF image. + */ + +.text +.align 16 + +.globl _dl_linux_resolve +.type _dl_linux_resolve,#function +_dl_linux_resolve: + /* + * Call the resolver - pass the address of the PLT so that we can + * figure out which module we are in. + */ + mov %o7,%o1 + call _dl_linux_resolver + mov %g1,%o0 + + jmpl %o0,%o7 + restore +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve diff --git a/ldso/ldso/x86_64/dl-debug.h b/ldso/ldso/x86_64/dl-debug.h new file mode 100644 index 0000000..d605a03 --- /dev/null +++ b/ldso/ldso/x86_64/dl-debug.h @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* x86_64 debug code for ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 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. + */ + +static const char *_dl_reltypes_tab[] = { + [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", + [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", + [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S", + [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8", + [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD", + [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32" +}; diff --git a/ldso/ldso/x86_64/dl-startup.h b/ldso/ldso/x86_64/dl-startup.h new file mode 100644 index 0000000..6da8880 --- /dev/null +++ b/ldso/ldso/x86_64/dl-startup.h @@ -0,0 +1,64 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2005 by Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Parts taken from glibc/sysdeps/x86_64/dl-machine.h + */ +__asm__ ( + " .text\n" + " .global _start\n" + " .type _start,%function\n" + "_start:\n" + " movq %rsp, %rdi\n" + " call _dl_start\n" + " # Save the user entry point address in %r12.\n" + " movq %rax, %r12\n" + " # See if we were run as a command with the executable file\n" + " # name as an extra leading argument.\n" + " movl _dl_skip_args(%rip), %eax\n" + " # Pop the original argument count.\n" + " popq %rdx\n" + " # Adjust the stack pointer to skip _dl_skip_args words.\n" + " leaq (%rsp,%rax,8), %rsp\n" + " # Subtract _dl_skip_args from argc.\n" + " subl %eax, %edx\n" + " # Push argc back on the stack.\n" + " pushq %rdx\n" + " # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n" + " leaq _dl_fini(%rip), %rdx\n" + " # Jump to the user's entry point.\n" + " jmp *%r12\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) +{ + switch (ELF_R_TYPE(rpnt->r_info)) { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_X86_64_DTPMOD64: + *reloc_addr = 1; + break; + case R_X86_64_NONE: + case R_X86_64_DTPOFF64: + break; + case R_X86_64_TPOFF64: + *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr; + break; + default: + _dl_exit(1); + } +} diff --git a/ldso/ldso/x86_64/dl-syscalls.h b/ldso/ldso/x86_64/dl-syscalls.h new file mode 100644 index 0000000..996bb87 --- /dev/null +++ b/ldso/ldso/x86_64/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h new file mode 100644 index 0000000..202eab1 --- /dev/null +++ b/ldso/ldso/x86_64/dl-sysdep.h @@ -0,0 +1,113 @@ +/* vi: set sw=4 ts=4: */ +/* yoinked from glibc/sysdeps/x86_64/dl-machine.h */ +/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_X86_64 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "x86_64" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_X86_64_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf64_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf64_Addr addr; + + /* This works because we have our GOT address available in the small PIC + model. */ + addr = (Elf64_Addr) &_DYNAMIC; + + return addr; +} + + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf64_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + register Elf64_Addr addr, tmp; + + /* The easy way is just the same as on x86: + leaq _dl_start, %0 + leaq _dl_start(%%rip), %1 + subq %0, %1 + but this does not work with binutils since we then have + a R_X86_64_32S relocation in a shared lib. + + Instead we store the address of _dl_start in the data section + and compare it with the current value that we can get via + an RIP relative addressing mode. */ + + __asm__ ("movq 1f(%%rip), %1\n" + "0:\tleaq _dl_start(%%rip), %0\n\t" + "subq %1, %0\n\t" + ".section\t.data\n" + "1:\t.quad _dl_start\n\t" + ".previous\n\t" + : "=r" (addr), "=r" (tmp) : : "cc"); + + return addr; +} + +static __always_inline void +elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr, + Elf64_Word relative_count) +{ + Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr; + --rpnt; + do { + Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c new file mode 100644 index 0000000..e78a809 --- /dev/null +++ b/ldso/ldso/x86_64/elfinterp.c @@ -0,0 +1,321 @@ +/* vi: set sw=4 ts=4: */ +/* x86_64 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + reloc_type = ELF_R_TYPE(this_reloc->r_info); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_X86_64_JUMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + *got_addr = new_addr; + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + ElfW(Sym) *sym; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type)); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_X86_64_NONE: + break; + + case R_X86_64_64: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + case R_X86_64_PC32: + *reloc_addr = symbol_addr + rpnt->r_addend - rpnt->r_offset; + break; + + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + /* handled by elf_machine_relative() + case R_X86_64_RELATIVE: + *reloc_addr = map->l_addr + rpnt->r_addend; + break; + */ + case R_X86_64_DTPMOD64: + *reloc_addr = 1; + break; + case R_X86_64_DTPOFF64: + *reloc_addr = sym->st_value + rpnt->r_addend; + break; + case R_X86_64_TPOFF64: + *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr; + break; + case R_X86_64_32: + *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend; + /* XXX: should check for overflow eh ? */ + break; + + case R_X86_64_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_X86_64_NONE: + break; + case R_X86_64_JUMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/ldso/ldso/x86_64/resolve.S b/ldso/ldso/x86_64/resolve.S new file mode 100644 index 0000000..ac1d182 --- /dev/null +++ b/ldso/ldso/x86_64/resolve.S @@ -0,0 +1,62 @@ +/* + * This function is _not_ called directly. It is jumped to (so no return + * address is on the stack) when attempting to use a symbol that has not yet + * been resolved. The first time a jump symbol (such as a function call inside + * a shared library) is used (before it gets resolved) it will jump here to + * _dl_linux_resolve. When we get called the stack looks like this: + * reloc_entry + * tpnt + * + * This function saves all the registers, puts a copy of reloc_entry and tpnt + * on the stack (as function arguments) then make the function call + * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out + * where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + * found them, then we jump to the fixed up address, which is where the jump + * symbol that got us here really wanted to jump to in the first place. + * -Erik Andersen + */ + +/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */ + +.text + +.global _dl_linux_resolve +.type _dl_linux_resolve,%function + +_dl_linux_resolve: + subq $56,%rsp + /* Preserve registers otherwise clobbered. */ + movq %rax, (%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rsi, 24(%rsp) + movq %rdi, 32(%rsp) + movq %r8, 40(%rsp) + movq %r9, 48(%rsp) + + movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */ + movq %rsi, %r11 /* Multiply by 24 */ + addq %r11, %rsi + addq %r11, %rsi + shlq $3, %rsi + movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */ + call _dl_linux_resolver /* Call resolver. */ + movq %rax, %r11 /* Save return value */ + + /* Get register content back. */ + movq 48(%rsp), %r9 + movq 40(%rsp), %r8 + movq 32(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rdx + movq 8(%rsp), %rcx + movq (%rsp), %rax + + addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */ + jmp *%r11 /* Jump to function address. */ + +.size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/ldso/ldso/xtensa/dl-debug.h b/ldso/ldso/xtensa/dl-debug.h new file mode 100644 index 0000000..327defc --- /dev/null +++ b/ldso/ldso/xtensa/dl-debug.h @@ -0,0 +1,61 @@ +/* vi: set sw=4 ts=4: */ +/* Xtensa ELF shared library loader suppport + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + "R_XTENSA_NONE", + "R_XTENSA_32", + "R_XTENSA_RTLD", + "R_XTENSA_GLOB_DAT", + "R_XTENSA_JMP_SLOT", + "R_XTENSA_RELATIVE", + "R_XTENSA_PLT", + "R_XTENSA_UNUSED7", + "R_XTENSA_OP0", + "R_XTENSA_OP1", + "R_XTENSA_OP2", + "R_XTENSA_ASM_EXPAND", + "R_XTENSA_ASM_SIMPLIFY", + "R_XTENSA_UNUSED13", + "R_XTENSA_UNUSED14", + "R_XTENSA_GNU_VTINHERIT", + "R_XTENSA_GNU_VTENTRY", + "R_XTENSA_DIFF8", + "R_XTENSA_DIFF16", + "R_XTENSA_DIFF32", + "R_XTENSA_SLOT0_OP", + "R_XTENSA_SLOT1_OP", + "R_XTENSA_SLOT2_OP", + "R_XTENSA_SLOT3_OP", + "R_XTENSA_SLOT4_OP", + "R_XTENSA_SLOT5_OP", + "R_XTENSA_SLOT6_OP", + "R_XTENSA_SLOT7_OP", + "R_XTENSA_SLOT8_OP", + "R_XTENSA_SLOT9_OP", + "R_XTENSA_SLOT10_OP", + "R_XTENSA_SLOT11_OP", + "R_XTENSA_SLOT12_OP", + "R_XTENSA_SLOT13_OP", + "R_XTENSA_SLOT14_OP", + "R_XTENSA_SLOT0_ALT", + "R_XTENSA_SLOT1_ALT", + "R_XTENSA_SLOT2_ALT", + "R_XTENSA_SLOT3_ALT", + "R_XTENSA_SLOT4_ALT", + "R_XTENSA_SLOT5_ALT", + "R_XTENSA_SLOT6_ALT", + "R_XTENSA_SLOT7_ALT", + "R_XTENSA_SLOT8_ALT", + "R_XTENSA_SLOT9_ALT", + "R_XTENSA_SLOT10_ALT", + "R_XTENSA_SLOT11_ALT", + "R_XTENSA_SLOT12_ALT", + "R_XTENSA_SLOT13_ALT", + "R_XTENSA_SLOT14_ALT" +}; diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h new file mode 100644 index 0000000..8ae9624 --- /dev/null +++ b/ldso/ldso/xtensa/dl-startup.h @@ -0,0 +1,106 @@ +/* vi: set sw=4 ts=4: */ +/* + * Xtensa ELF code used by dl-startup.c. + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * Parts taken from glibc/sysdeps/xtensa/dl-machine.h. + */ + +__asm__ ( + " .text\n" + " .align 4\n" + " .global _start\n" + " .type _start, @function\n" + "_start:\n" + " # Compute load offset in a2: the GOT has not yet been relocated\n" + " # but the entries for local symbols contain the relative offsets\n" + " # and we can explicitly add the load offset in this code.\n" + " _call0 0f\n" + " .align 4\n" + "0: movi a3, _start+3\n" + " sub a2, a0, a3\n" + " # Make sure a0 is cleared to mark the top of stack.\n" + " movi a0, 0\n" + " # user_entry_point = _dl_start(pointer to argument block)\n" + " movi a4, _dl_start\n" + " mov a6, sp\n" + " add a4, a4, a2\n" + " callx4 a4\n" + " # Save user_entry_point so we can jump to it.\n" + " mov a3, a6\n" + " l32i a7, sp, 0 # load argc\n" + " # Load _dl_skip_args into a4.\n" + " movi a4, _dl_skip_args\n" + " l32i a4, a4, 0\n" + " bnez a4, .Lfixup_stack\n" + ".Lfixup_stack_ret:\n" + " # Pass finalizer (_dl_fini) in a2 to the user entry point.\n" + " movi a2, _dl_fini\n" + " # Jump to user's entry point (_start).\n" + " jx a3\n" + ".Lfixup_stack:\n" + " # argc -= _dl_skip_args (with argc @ sp+0)\n" + " sub a7, a7, a4\n" + " s32i a7, sp, 0\n" + " # Shift everything by _dl_skip_args.\n" + " addi a5, sp, 4 # a5 = destination ptr = argv\n" + " add a4, a5, a4 # a4 = source ptr = argv + _dl_skip_args\n" + " # Shift argv.\n" + "1: l32i a6, a4, 0\n" + " addi a4, a4, 4\n" + " s32i a6, a5, 0\n" + " addi a5, a5, 4\n" + " bnez a6, 1b\n" + " # Shift envp.\n" + "2: l32i a6, a4, 0\n" + " addi a4, a4, 4\n" + " s32i a6, a5, 0\n" + " addi a5, a5, 4\n" + " bnez a6, 2b\n" + " # Shift auxiliary table.\n" + "3: l32i a6, a4, 0\n" + " l32i a8, a4, 4\n" + " addi a4, a4, 8\n" + " s32i a6, a5, 0\n" + " s32i a8, a5, 4\n" + " addi a5, a5, 8\n" + " bnez a6, 3b\n" + " j .Lfixup_stack_ret"); + +/* Get a pointer to the argv value. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* Function calls are not safe until the GOT relocations have been done. */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +#define PERFORM_BOOTSTRAP_GOT(tpnt) \ +do { \ + xtensa_got_location *got_loc; \ + unsigned long l_addr = tpnt->loadaddr; \ + Elf32_Word relative_count; \ + unsigned long rel_addr; \ + int x; \ +\ + got_loc = (xtensa_got_location *) \ + (tpnt->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \ +\ + for (x = 0; x < tpnt->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) { \ + Elf32_Addr got_start, got_end; \ + got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \ + got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \ + & ~(PAGE_SIZE - 1)); \ + _dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \ + PROT_READ | PROT_WRITE | PROT_EXEC); \ + } \ +\ + /* The following is a stripped down version of the code following \ + the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c. That \ + code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \ + to be done here instead. */ \ + relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \ + rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \ + if (rel_addr) \ + elf_machine_relative(load_addr, rel_addr, relative_count); \ +} while (0) diff --git a/ldso/ldso/xtensa/dl-syscalls.h b/ldso/ldso/xtensa/dl-syscalls.h new file mode 100644 index 0000000..4b42a57 --- /dev/null +++ b/ldso/ldso/xtensa/dl-syscalls.h @@ -0,0 +1,7 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + diff --git a/ldso/ldso/xtensa/dl-sysdep.h b/ldso/ldso/xtensa/dl-sysdep.h new file mode 100644 index 0000000..b58feff --- /dev/null +++ b/ldso/ldso/xtensa/dl-sysdep.h @@ -0,0 +1,132 @@ +/* Machine-dependent ELF dynamic relocation. + Parts copied from glibc/sysdeps/xtensa/dl-machine.h + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +#include + +/* Translate a processor specific dynamic tag to the index + in l_info array. */ +#define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM) + +typedef struct xtensa_got_location_struct { + Elf32_Off offset; + Elf32_Word length; +} xtensa_got_location; + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE, MODULE) \ + do { \ + xtensa_got_location *got_loc; \ + Elf32_Addr l_addr = MODULE->loadaddr; \ + int x; \ + \ + got_loc = (xtensa_got_location *) \ + (MODULE->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \ + \ + for (x = 0; x < MODULE->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) \ + { \ + Elf32_Addr got_start, got_end; \ + got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \ + got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \ + & ~(PAGE_SIZE - 1)); \ + _dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start, \ + PROT_READ | PROT_WRITE | PROT_EXEC); \ + } \ + \ + /* Fill in first GOT entry according to the ABI. */ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + } while (0) + +/* Parse dynamic info */ +#define ARCH_NUM 2 +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ + do { \ + if (dpnt->d_tag == DT_XTENSA_GOT_LOC_OFF) \ + dynamic[DT_XTENSA (GOT_LOC_OFF)] = dpnt->d_un.d_ptr; \ + else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ) \ + dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val; \ + } while (0) + +/* Here we define the magic numbers that this dynamic loader should accept. */ +#define MAGIC1 EM_XTENSA +#undef MAGIC2 + +/* Used for error messages. */ +#define ELF_TARGET "Xtensa" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver (struct elf_resolve *, int); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + undefined references should not be allowed to define the value. */ +#define elf_machine_type_class(type) \ + (((type) == R_XTENSA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) + +/* Return the link-time address of _DYNAMIC. */ +static __inline__ Elf32_Addr +elf_machine_dynamic (void) +{ + /* This function is only used while bootstrapping the runtime linker. + The "_DYNAMIC" symbol is always local so its GOT entry will initially + contain the link-time address. */ + return (Elf32_Addr) &_DYNAMIC; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr addr, tmp; + + /* At this point, the runtime linker is being bootstrapped and the GOT + entry used for ".Lhere" will contain the link address. The CALL0 will + produce the dynamic address of ".Lhere" + 3. Thus, the end result is + equal to "dynamic_address(.Lhere) - link_address(.Lhere)". */ + __asm__ ("\ + movi %0, .Lhere\n\ + mov %1, a0\n\ +.Lhere: _call0 0f\n\ + .align 4\n\ +0: sub %0, a0, %0\n\ + mov a0, %1" + : "=a" (addr), "=a" (tmp)); + + return addr - 3; +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr; + while (relative_count--) + { + Elf32_Addr *const reloc_addr = (Elf32_Addr *) (load_off + rpnt->r_offset); + *reloc_addr += load_off + rpnt->r_addend; + rpnt++; + } +} diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c new file mode 100644 index 0000000..a459431 --- /dev/null +++ b/ldso/ldso/xtensa/elfinterp.c @@ -0,0 +1,285 @@ +/* vi: set sw=4 ts=4: */ +/* Xtensa ELF shared library loader suppport + * + * Copyright (C) 2007 Tensilica Inc. + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +unsigned long +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + char *symname; + + rel_addr = (char *) tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry); + reloc_type = ELF32_R_TYPE (this_reloc->r_info); + symtab_index = ELF32_R_SYM (this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely (reloc_type != R_XTENSA_JMP_SLOT)) { + _dl_dprintf (2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit (1); + } + + /* Address of the literal to fix up. */ + got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr); + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash (symname, tpnt->symbol_scope, tpnt, + ELF_RTYPE_CLASS_PLT); + if (unlikely (!new_addr)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf (_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + + +static int +_dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size /= sizeof (ELF_RELOC); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM (rpnt->r_info); + + debug_sym (symtab, strtab, symtab_index); + debug_reloc (symtab, strtab, rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf (2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf (2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely (res < 0)) { + int reloc_type = ELF32_R_TYPE (rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf (2, "can't handle reloc type %s\n", + _dl_reltypes (reloc_type)); +#else + _dl_dprintf (2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit (-res); + } + if (unlikely (res > 0)) { + _dl_dprintf (2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + + +static int +_dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + Elf32_Sym *sym; + Elf32_Addr *reloc_addr; + Elf32_Addr symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + Elf32_Addr old_val; +#endif + + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE (rpnt->r_info); + symtab_index = ELF32_R_SYM (rpnt->r_info); + sym = &symtab[symtab_index]; + symbol_addr = 0; + symname = strtab + sym->st_name; + + if (symtab_index) { + symbol_addr = (Elf32_Addr) + _dl_find_hash (symname, scope, tpnt, + elf_machine_type_class (reloc_type)); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (unlikely (!symbol_addr && + ELF32_ST_BIND (sym->st_info) != STB_WEAK)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_XTENSA_NONE: + break; + + case R_XTENSA_GLOB_DAT: + case R_XTENSA_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + case R_XTENSA_RTLD: + if (rpnt->r_addend == 1) { + /* Grab the function pointer stashed at the beginning of the + GOT by the GOT_INIT function. */ + *reloc_addr = *(Elf32_Addr *) tpnt->dynamic_info[DT_PLTGOT]; + } else if (rpnt->r_addend == 2) { + /* Store the link map for the object. */ + *reloc_addr = (Elf32_Addr) tpnt; + } else { + _dl_exit (1); + } + break; + + case R_XTENSA_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + Elf32_Addr *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + Elf32_Addr old_val; +#endif + + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE (rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_XTENSA_JMP_SLOT: + /* Perform a RELATIVE reloc on the GOT entry that transfers + to the stub function. */ + *reloc_addr += tpnt->loadaddr; + break; + case R_XTENSA_NONE: + break; + default: + _dl_exit (1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x", + old_val, *reloc_addr, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information (struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void) _dl_parse (rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information (struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse (rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, + _dl_do_reloc); +} diff --git a/ldso/ldso/xtensa/resolve.S b/ldso/ldso/xtensa/resolve.S new file mode 100644 index 0000000..902cd82 --- /dev/null +++ b/ldso/ldso/xtensa/resolve.S @@ -0,0 +1,57 @@ +/* Xtensa dynamic resolver. + Parts copied from glibc/sysdeps/xtensa/dl-trampoline.S + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#define MIN_FRAME_SIZE 32 + +#ifdef __XTENSA_EB__ +#define XTENSA_IMM12_FLD_OFFSET 8 +#else /* __XTENSA_EL__ */ +#define XTENSA_IMM12_FLD_OFFSET 12 +#endif /* __XTENSA_EL__ */ + + .text + .align 4 + .global _dl_linux_resolve + .type _dl_linux_resolve, @function +_dl_linux_resolve: + /* Fix up the high 2 bits of the return address. */ + movi a13, 0f + slli a12, a0, 2 +0: extui a13, a13, 30, 2 + ssai 2 + src a12, a13, a12 + + /* Call the fixup function. */ + movi a8, _dl_linux_resolver + callx8 a8 + + /* Extract the target's frame size from the ENTRY instruction. */ + l32i a11, a10, 0 + extui a11, a11, XTENSA_IMM12_FLD_OFFSET, 12 + slli a11, a11, 3 + + addi a11, a11, -MIN_FRAME_SIZE + sub a11, sp, a11 + movsp sp, a11 + + /* Jump to the next instruction past the ENTRY. */ + addi a10, a10, 3 + jx a10 + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/ldso/libdl/Makefile b/ldso/libdl/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/ldso/libdl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/ldso/libdl/Makefile.in b/ldso/libdl/Makefile.in new file mode 100644 index 0000000..3d55e42 --- /dev/null +++ b/ldso/libdl/Makefile.in @@ -0,0 +1,57 @@ +# Makefile.in for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libdl := -DNOT_IN_libc -DIS_IN_libdl $(SSP_ALL_CFLAGS) + +CFLAGS-libdl += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso + +CFLAGS-libdl += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" + +ifeq ($(SUPPORT_LD_DEBUG),y) +CFLAGS-libdl += -D__SUPPORT_LD_DEBUG__ +endif + +CFLAGS-libdl.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" + +LDFLAGS-libdl.so := $(LDFLAGS) -Wl,-fini,dl_cleanup + +LIBS-libdl.so := $(LIBS) $(ldso) + +libdl_FULL_NAME := libdl-$(VERSION).so + +libdl_DIR := $(top_srcdir)ldso/libdl +libdl_OUT := $(top_builddir)ldso/libdl + +libdl_SRC := $(libdl_DIR)/libdl.c +libdl_OBJ := $(patsubst $(libdl_DIR)/%.c,$(libdl_OUT)/%.o,$(libdl_SRC)) + +resolve := $(top_builddir)ldso/ldso/$(TARGET_ARCH)/resolve.o + +libdl-a-y := $(libdl_OBJ) $(resolve) +ifeq ($(DOPIC),y) +libdl-a-y := $(libdl-a-y:.o=.os) +endif +libdl-so-y := $(libdl_OUT)/libdl.oS + +lib-a-$(HAVE_SHARED) += $(top_builddir)lib/libdl.a +lib-so-y += $(top_builddir)lib/libdl.so +objclean-y += libdl_clean + +$(top_builddir)lib/libdl.so: $(libdl_OUT)/libdl_so.a $(libc.depend) + $(call link.so,$(libdl_FULL_NAME),$(MAJOR_VERSION)) + +$(libdl_OUT)/libdl_so.a: $(libdl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libdl.a: $(libdl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +libdl_clean: + $(do_rm) $(addprefix $(libdl_OUT)/*., o os oS a) diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c new file mode 100644 index 0000000..f914cf3 --- /dev/null +++ b/ldso/libdl/libdl.c @@ -0,0 +1,806 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include /* Needed for 'strstr' prototype' */ +#include + + +#ifdef SHARED + +/* When libdl is loaded as a shared library, we need to load in + * and use a pile of symbols from ldso... */ + +extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, int); +extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, + struct elf_resolve *, char *, int); +extern int _dl_fixup(struct dyn_elf *rpnt, int lazy); +extern void _dl_protect_relro(struct elf_resolve * tpnt); +extern int _dl_errno; +extern struct dyn_elf *_dl_symbol_tables; +extern struct dyn_elf *_dl_handles; +extern struct elf_resolve *_dl_loaded_modules; +extern struct r_debug *_dl_debug_addr; +extern unsigned long _dl_error_number; +extern void *(*_dl_malloc_function)(size_t); +extern void (*_dl_free_function) (void *p); +extern void _dl_run_init_array(struct elf_resolve *); +extern void _dl_run_fini_array(struct elf_resolve *); +#ifdef __LDSO_CACHE_SUPPORT__ +int _dl_map_cache(void); +int _dl_unmap_cache(void); +#endif +#ifdef __mips__ +extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); +#endif +#ifdef __SUPPORT_LD_DEBUG__ +extern char *_dl_debug; +#endif + + +#else /* SHARED */ + +#define _dl_malloc malloc +#define _dl_free free + +/* When libdl is linked as a static library, we need to replace all + * the symbols that otherwise would have been loaded in from ldso... */ + +#ifdef __SUPPORT_LD_DEBUG__ +char *_dl_debug = 0; +char *_dl_debug_symbols = 0; +char *_dl_debug_move = 0; +char *_dl_debug_reloc = 0; +char *_dl_debug_detail = 0; +char *_dl_debug_nofixups = 0; +char *_dl_debug_bindings = 0; +int _dl_debug_file = 2; +#endif +const char *_dl_progname = ""; /* Program name */ +void *(*_dl_malloc_function)(size_t); +void (*_dl_free_function) (void *p); +char *_dl_library_path = 0; /* Where we look for libraries */ +char *_dl_ldsopath = 0; /* Location of the shared lib loader */ +int _dl_errno = 0; /* We can't use the real errno in ldso */ +size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */ +/* This global variable is also to communicate with debuggers such as gdb. */ +struct r_debug *_dl_debug_addr = NULL; + +#include "../ldso/dl-array.c" +#include "../ldso/dl-debug.c" +#include LDSO_ELFINTERP +#include "../ldso/dl-hash.c" +#define _dl_trace_loaded_objects 0 +#include "../ldso/dl-elf.c" +#endif /* SHARED */ + +#ifdef __SUPPORT_LD_DEBUG__ +# define _dl_if_debug_print(fmt, args...) \ + do { \ + if (_dl_debug) \ + fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \ + } while (0) +#else +# define _dl_if_debug_print(fmt, args...) +#endif + +static int do_dlclose(void *, int need_fini); + + +static const char *dl_error_names[] = { + "", + "File not found", + "Unable to open /dev/zero", + "Not an ELF file", +#if defined (__i386__) + "Not i386 binary", +#elif defined (__sparc__) + "Not sparc binary", +#elif defined (__mc68000__) + "Not m68k binary", +#else + "Unrecognized binary type", +#endif + "Not an ELF shared library", + "Unable to mmap file", + "No dynamic section", +#ifdef ELF_USES_RELOCA + "Unable to process REL relocs", +#else + "Unable to process RELA relocs", +#endif + "Bad handle", + "Unable to resolve symbol" +}; + +void dl_cleanup(void) __attribute__ ((destructor)); +void dl_cleanup(void) +{ + struct dyn_elf *h, *n; + + for (h = _dl_handles; h; h = n) { + n = h->next_handle; + do_dlclose(h, 1); + } +} + +void *dlopen(const char *libname, int flag) +{ + struct elf_resolve *tpnt, *tfrom; + struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; + ElfW(Addr) from; + struct elf_resolve *tpnt1; + void (*dl_brk) (void); + int now_flag; + struct init_fini_list *tmp, *runp, *runp2, *dep_list; + unsigned int nlist, i; + struct elf_resolve **init_fini_list; + static bool _dl_init; + + /* A bit of sanity checking... */ + if (!(flag & (RTLD_LAZY|RTLD_NOW))) { + _dl_error_number = LD_BAD_HANDLE; + return NULL; + } + + from = (ElfW(Addr)) __builtin_return_address(0); + + if (!_dl_init) { + _dl_init = true; + _dl_malloc_function = malloc; + _dl_free_function = free; + } + /* Cover the trivial case first */ + if (!libname) + return _dl_symbol_tables; + +#ifndef SHARED +# ifdef __SUPPORT_LD_DEBUG__ + _dl_debug = getenv("LD_DEBUG"); + if (_dl_debug) { + if (_dl_strstr(_dl_debug, "all")) { + _dl_debug_detail = _dl_debug_move = _dl_debug_symbols + = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1; + } else { + _dl_debug_detail = strstr(_dl_debug, "detail"); + _dl_debug_move = strstr(_dl_debug, "move"); + _dl_debug_symbols = strstr(_dl_debug, "sym"); + _dl_debug_reloc = strstr(_dl_debug, "reloc"); + _dl_debug_nofixups = strstr(_dl_debug, "nofix"); + _dl_debug_bindings = strstr(_dl_debug, "bind"); + } + } +# endif +#endif + + _dl_map_cache(); + + /* + * Try and locate the module we were called from - we + * need this so that we get the correct RPATH/RUNPATH. Note that + * this is the current behavior under Solaris, but the + * ABI+ specifies that we should only use the RPATH from + * the application. Thus this may go away at some time + * in the future. + */ + { + struct dyn_elf *dpnt; + tfrom = NULL; + for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { + tpnt = dpnt->dyn; + if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) + tfrom = tpnt; + } + } + for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); + + relro_ptr = rpnt; + now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; + if (getenv("LD_BIND_NOW")) + now_flag = RTLD_NOW; + +#ifndef SHARED + /* When statically linked, the _dl_library_path is not yet initialized */ + _dl_library_path = getenv("LD_LIBRARY_PATH"); +#endif + + /* Try to load the specified library */ + _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n", + (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0)); + tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0); + + if (tpnt == NULL) { + _dl_unmap_cache(); + return NULL; + } + dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); + _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf)); + dyn_chain->dyn = tpnt; + tpnt->rtld_flags |= (flag & RTLD_GLOBAL); + + dyn_chain->next_handle = _dl_handles; + _dl_handles = dyn_ptr = dyn_chain; + + if (tpnt->usage_count > 1) { + _dl_if_debug_print("Lib: %s already opened\n", libname); + /* see if there is a handle from a earlier dlopen */ + for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) { + if (handle->dyn == tpnt) { + dyn_chain->init_fini.init_fini = handle->init_fini.init_fini; + dyn_chain->init_fini.nlist = handle->init_fini.nlist; + for (i = 0; i < dyn_chain->init_fini.nlist; i++) + dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL); + dyn_chain->next = handle->next; + break; + } + } + return dyn_chain; + } else { + tpnt->init_flag |= DL_OPENED; + } + + _dl_if_debug_print("Looking for needed libraries\n"); + nlist = 0; + runp = alloca(sizeof(*runp)); + runp->tpnt = tpnt; + runp->next = NULL; + dep_list = runp2 = runp; + for (; runp; runp = runp->next) + { + ElfW(Dyn) *dpnt; + char *lpntstr; + + nlist++; + runp->tpnt->init_fini = NULL; /* clear any previous dependcies */ + for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag == DT_NEEDED) { + lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] + + dpnt->d_un.d_val); + _dl_if_debug_print("Trying to load '%s', needed by '%s'\n", + lpntstr, runp->tpnt->libname); + tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0); + if (!tpnt1) + goto oops; + + tpnt1->rtld_flags |= (flag & RTLD_GLOBAL); + + /* This list is for dlsym() and relocation */ + dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); + _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf)); + dyn_ptr = dyn_ptr->next; + dyn_ptr->dyn = tpnt1; + /* Used to record RTLD_LOCAL scope */ + tmp = alloca(sizeof(struct init_fini_list)); + tmp->tpnt = tpnt1; + tmp->next = runp->tpnt->init_fini; + runp->tpnt->init_fini = tmp; + + for (tmp=dep_list; tmp; tmp = tmp->next) { + if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */ + _dl_if_debug_print("Circular dependency, skipping '%s',\n", + tmp->tpnt->libname); + tpnt1->usage_count--; + break; + } + } + if (!tmp) { /* Don't add if circular dependency detected */ + runp2->next = alloca(sizeof(*runp)); + runp2 = runp2->next; + runp2->tpnt = tpnt1; + runp2->next = NULL; + } + } + } + } + init_fini_list = malloc(nlist * sizeof(struct elf_resolve *)); + dyn_chain->init_fini.init_fini = init_fini_list; + dyn_chain->init_fini.nlist = nlist; + i = 0; + for (runp2 = dep_list; runp2; runp2 = runp2->next) { + init_fini_list[i++] = runp2->tpnt; + for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) { + if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) { + tmp = malloc(sizeof(struct init_fini_list)); + tmp->tpnt = runp->tpnt; + tmp->next = runp2->tpnt->rtld_local; + runp2->tpnt->rtld_local = tmp; + } + } + + } + /* Sort the INIT/FINI list in dependency order. */ + for (runp2 = dep_list; runp2; runp2 = runp2->next) { + unsigned int j, k; + for (j = 0; init_fini_list[j] != runp2->tpnt; ++j) + /* Empty */; + for (k = j + 1; k < nlist; ++k) { + struct init_fini_list *ele = init_fini_list[k]->init_fini; + + for (; ele; ele = ele->next) { + if (ele->tpnt == runp2->tpnt) { + struct elf_resolve *here = init_fini_list[k]; + _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); + for (i = (k - j); i; --i) + init_fini_list[i+j] = init_fini_list[i+j-1]; + init_fini_list[j] = here; + ++j; + break; + } + } + } + } +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug) { + fprintf(stderr, "\nINIT/FINI order and dependencies:\n"); + for (i = 0; i < nlist; i++) { + fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname); + runp = init_fini_list[i]->init_fini; + for (; runp; runp = runp->next) + fprintf(stderr, " %s ", runp->tpnt->libname); + fprintf(stderr, "\n"); + } + } +#endif + + _dl_if_debug_print("Beginning dlopen relocation fixups\n"); + /* + * OK, now all of the kids are tucked into bed in their proper addresses. + * Now we go through and look for REL and RELA records that indicate fixups + * to the GOT tables. We need to do this in reverse order so that COPY + * directives work correctly */ +#ifdef __mips__ + /* + * Relocation of the GOT entries for MIPS have to be done + * after all the libraries have been loaded. + */ + _dl_perform_mips_global_got_relocations(tpnt, !now_flag); +#endif + + if (_dl_fixup(dyn_chain, now_flag)) + goto oops; + + if (relro_ptr) { + for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) { + if (rpnt->dyn->relro_size) + _dl_protect_relro(rpnt->dyn); + } + } + /* TODO: Should we set the protections of all pages back to R/O now ? */ + + + /* Notify the debugger we have added some objects. */ + if (_dl_debug_addr) { + dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; + if (dl_brk != NULL) { + _dl_debug_addr->r_state = RT_ADD; + (*dl_brk) (); + + _dl_debug_addr->r_state = RT_CONSISTENT; + (*dl_brk) (); + } + } + + /* Run the ctors and setup the dtors */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; + if (tpnt->init_flag & INIT_FUNCS_CALLED) + continue; + tpnt->init_flag |= INIT_FUNCS_CALLED; + + if (tpnt->dynamic_info[DT_INIT]) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]); + if (dl_elf_func) { + _dl_if_debug_print("running ctors for library %s at '%p'\n", + tpnt->libname, dl_elf_func); + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + } + + _dl_run_init_array(tpnt); + } + + _dl_unmap_cache(); + return (void *) dyn_chain; + +oops: + /* Something went wrong. Clean up and return NULL. */ + _dl_unmap_cache(); + do_dlclose(dyn_chain, 0); + return NULL; +} + +void *dlsym(void *vhandle, const char *name) +{ + struct elf_resolve *tpnt, *tfrom; + struct dyn_elf *handle; + ElfW(Addr) from; + struct dyn_elf *rpnt; + void *ret; + /* Nastiness to support underscore prefixes. */ +#ifdef __UCLIBC_UNDERSCORES__ + char tmp_buf[80]; + char *name2 = tmp_buf; + size_t nlen = strlen (name) + 1; + if (nlen + 1 > sizeof (tmp_buf)) + name2 = malloc (nlen + 1); + if (name2 == 0) { + _dl_error_number = LD_ERROR_MMAP_FAILED; + return 0; + } + name2[0] = '_'; + memcpy (name2 + 1, name, nlen); +#else + const char *name2 = name; +#endif + handle = (struct dyn_elf *) vhandle; + + /* First of all verify that we have a real handle + of some kind. Return NULL if not a valid handle. */ + + if (handle == NULL) + handle = _dl_symbol_tables; + else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) { + for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) + if (rpnt == handle) + break; + if (!rpnt) { + _dl_error_number = LD_BAD_HANDLE; + ret = NULL; + goto out; + } + } else if (handle == RTLD_NEXT) { + /* + * Try and locate the module we were called from - we + * need this so that we know where to start searching + * from. We never pass RTLD_NEXT down into the actual + * dynamic loader itself, as it doesn't know + * how to properly treat it. + */ + from = (ElfW(Addr)) __builtin_return_address(0); + + tfrom = NULL; + for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) { + tpnt = rpnt->dyn; + if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) { + tfrom = tpnt; + handle = rpnt->next; + } + } + } + tpnt = NULL; + if (handle == _dl_symbol_tables) + tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ + ret = _dl_find_hash(name2, handle, tpnt, ELF_RTYPE_CLASS_DLSYM); + + /* + * Nothing found. + */ + if (!ret) + _dl_error_number = LD_NO_SYMBOL; +out: +#ifdef __UCLIBC_UNDERSCORES__ + if (name2 != tmp_buf) + free (name2); +#endif + return ret; +} + +#if 0 +void *dlvsym(void *vhandle, const char *name, const char *version) +{ + return dlsym(vhandle, name); +} +#endif + +static int do_dlclose(void *vhandle, int need_fini) +{ + struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp; + struct init_fini_list *runp, *tmp; + ElfW(Phdr) *ppnt; + struct elf_resolve *tpnt, *run_tpnt; + int (*dl_elf_fini) (void); + void (*dl_brk) (void); + struct dyn_elf *handle; + unsigned int end; + unsigned int i, j; + + handle = (struct dyn_elf *) vhandle; + if (handle == _dl_symbol_tables) + return 0; + rpnt1 = NULL; + for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) { + if (rpnt == handle) + break; + rpnt1 = rpnt; + } + + if (!rpnt) { + _dl_error_number = LD_BAD_HANDLE; + return 1; + } + if (rpnt1) + rpnt1->next_handle = rpnt->next_handle; + else + _dl_handles = rpnt->next_handle; + _dl_if_debug_print("%s: usage count: %d\n", + handle->dyn->libname, handle->dyn->usage_count); + if (handle->dyn->usage_count != 1) { + handle->dyn->usage_count--; + free(handle); + return 0; + } + /* OK, this is a valid handle - now close out the file */ + for (j = 0; j < handle->init_fini.nlist; ++j) { + tpnt = handle->init_fini.init_fini[j]; + if (--tpnt->usage_count == 0) { + if ((tpnt->dynamic_info[DT_FINI] + || tpnt->dynamic_info[DT_FINI_ARRAY]) + && need_fini && + !(tpnt->init_flag & FINI_FUNCS_CALLED)) { + tpnt->init_flag |= FINI_FUNCS_CALLED; + _dl_run_fini_array(tpnt); + + if (tpnt->dynamic_info[DT_FINI]) { + dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]); + _dl_if_debug_print("running dtors for library %s at '%p'\n", + tpnt->libname, dl_elf_fini); + DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void))); + } + } + + _dl_if_debug_print("unmapping: %s\n", tpnt->libname); + end = 0; + for (i = 0, ppnt = tpnt->ppnt; + i < tpnt->n_phent; ppnt++, i++) { + if (ppnt->p_type != PT_LOAD) + continue; + if (end < ppnt->p_vaddr + ppnt->p_memsz) + end = ppnt->p_vaddr + ppnt->p_memsz; + } + DL_LIB_UNMAP (tpnt, end); + /* Free elements in RTLD_LOCAL scope list */ + for (runp = tpnt->rtld_local; runp; runp = tmp) { + tmp = runp->next; + free(runp); + } + + /* Next, remove tpnt from the loaded_module list */ + if (_dl_loaded_modules == tpnt) { + _dl_loaded_modules = tpnt->next; + if (_dl_loaded_modules) + _dl_loaded_modules->prev = 0; + } else + for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) + if (run_tpnt->next == tpnt) { + _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname); + run_tpnt->next = run_tpnt->next->next; + if (run_tpnt->next) + run_tpnt->next->prev = run_tpnt; + break; + } + + /* Next, remove tpnt from the global symbol table list */ + if (_dl_symbol_tables) { + if (_dl_symbol_tables->dyn == tpnt) { + _dl_symbol_tables = _dl_symbol_tables->next; + if (_dl_symbol_tables) + _dl_symbol_tables->prev = 0; + } else + for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { + if (rpnt1->next->dyn == tpnt) { + _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname); + rpnt1_tmp = rpnt1->next->next; + free(rpnt1->next); + rpnt1->next = rpnt1_tmp; + if (rpnt1->next) + rpnt1->next->prev = rpnt1; + break; + } + } + } + free(tpnt->libname); + free(tpnt); + } + } + free(handle->init_fini.init_fini); + free(handle); + + + if (_dl_debug_addr) { + dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; + if (dl_brk != NULL) { + _dl_debug_addr->r_state = RT_DELETE; + (*dl_brk) (); + + _dl_debug_addr->r_state = RT_CONSISTENT; + (*dl_brk) (); + } + } + + return 0; +} + +int dlclose(void *vhandle) +{ + return do_dlclose(vhandle, 1); +} + +char *dlerror(void) +{ + const char *retval; + + if (!_dl_error_number) + return NULL; + retval = dl_error_names[_dl_error_number]; + _dl_error_number = 0; + return (char *)retval; +} + +/* + * Dump information to stderr about the current loaded modules + */ +#ifdef __USE_GNU +static char *type[] = { "Lib", "Exe", "Int", "Mod" }; + +int dlinfo(void) +{ + struct elf_resolve *tpnt; + struct dyn_elf *rpnt, *hpnt; + + fprintf(stderr, "List of loaded modules\n"); + /* First start with a complete list of all of the loaded files. */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + fprintf(stderr, "\t%p %p %p %s %d %s\n", + DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope, + type[tpnt->libtype], + tpnt->usage_count, tpnt->libname); + } + + /* Next dump the module list for the application itself */ + fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables); + for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); + + for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) { + fprintf(stderr, "Modules for handle %p\n", hpnt); + for (rpnt = hpnt; rpnt; rpnt = rpnt->next) + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); + } + return 0; +} + +int dladdr(const void *__address, Dl_info * __info) +{ + struct elf_resolve *pelf; + struct elf_resolve *rpnt; + + _dl_map_cache(); + + /* + * Try and locate the module address is in + */ + pelf = NULL; + + _dl_if_debug_print("__address: %p __info: %p\n", __address, __info); + + __address = DL_LOOKUP_ADDRESS (__address); + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) { + struct elf_resolve *tpnt; + + tpnt = rpnt; + + _dl_if_debug_print("Module \"%s\" at %p\n", + tpnt->libname, DL_LOADADDR_BASE(tpnt->loadaddr)); + + if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf)) + pelf = tpnt; + } + + if (!pelf) { + return 0; + } + + /* + * Try and locate the symbol of address + */ + + { + char *strtab; + ElfW(Sym) *symtab; + unsigned int hn, si, sn, sf; + ElfW(Addr) sa = 0; + + /* Set the info for the object the address lies in */ + __info->dli_fname = pelf->libname; + __info->dli_fbase = (void *)pelf->mapaddr; + + symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]); + strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); + + sf = sn = 0; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (pelf->l_gnu_bitmask) { + for (hn = 0; hn < pelf->nbucket; hn++) { + si = pelf->l_gnu_buckets[hn]; + if (!si) + continue; + + const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si]; + do { + ElfW(Addr) symbol_addr; + + symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); + if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + sa = symbol_addr; + sn = si; + sf = 1; + } + _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, symbol_addr); + ++si; + } while ((*hasharr++ & 1u) == 0); + } + } else +#endif + for (hn = 0; hn < pelf->nbucket; hn++) { + for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) { + ElfW(Addr) symbol_addr; + + symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); + if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + sa = symbol_addr; + sn = si; + sf = 1; + } + + _dl_if_debug_print("Symbol \"%s\" at %p\n", + strtab + symtab[si].st_name, symbol_addr); + } + } + + if (sf) { + /* A nearest symbol has been found; fill the entries */ + __info->dli_sname = strtab + symtab[sn].st_name; + __info->dli_saddr = (void *)sa; + } else { + /* No symbol found, fill entries with NULL value, + only the containing object will be returned. */ + __info->dli_sname = NULL; + __info->dli_saddr = NULL; + } + return 1; + } +} +#endif diff --git a/ldso/man/Makefile b/ldso/man/Makefile new file mode 100644 index 0000000..d36225f --- /dev/null +++ b/ldso/man/Makefile @@ -0,0 +1,22 @@ +# Makefile for uClibc +# +# Copyright (C) 2000,2001,2005 Erik Andersen +# +# Derived in part from the Linux-8086 C library, the GNU C Library, and several +# other sundry sources. Files within this library are copyright by their +# respective copyright holders. +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include ../Config.mk + +ALL = #ld.so.info + +all: $(ALL) + +ld.so.info: ld.so.texi + makeinfo $< + +clean: + $(RM) $(ALL) *~ diff --git a/ldso/man/dlopen.3 b/ldso/man/dlopen.3 new file mode 100644 index 0000000..8d1e09e --- /dev/null +++ b/ldso/man/dlopen.3 @@ -0,0 +1,218 @@ +.\" -*- nroff -*- +.\" Copyright 1995 Yggdrasil Computing, Incorporated. +.\" written by Adam J. Richter (adam@yggdrasil.com), +.\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com). +.\" +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License, or (at your option) any later version. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual 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 General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, write to the Free +.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +.\" USA. +.\" +.TH DLOPEN 3 "16 May 1995" "Linux" "Linux Programmer's Manual" +.SH NAME +dlclose, dlerror, dlopen, dlsym \- Programming interface to dynamic linking loader. +.SH SYNOPSIS +.B #include +.sp +.BI "void *dlopen (const char *" "filename" ", int " flag "); +.br +.BI "const char *dlerror(void);" +.br +.BI "void *dlsym(void *"handle ", char *"symbol ");" +.br +.BI "int dladdr(void *"address ", Dl_info *"dlip ");" +.br +.BI "int dlclose (void *"handle "); +.sp +Special symbols: +.BR "_init" ", " "_fini" ". " +.SH DESCRIPTION +.B dlopen +loads a dynamic library from the file named by the null terminated +string +.I filename +and returns an opaque "handle" for the dynamic library. +If +.I filename +is not an absolute path (i.e., it does not begin with a "/"), then the +file is searched for in the following locations: +.RS +.PP +A colon-separated list of directories in the user's +\fBLD_LIBRARY\fP path environment variable. +.PP +The list of libraries specified in \fI/etc/ld.so.cache\fP. +.PP +\fI/usr/lib\fP, followed by \fI/lib\fP. +.RE +.PP +If +.I filename +is a NULL pointer, then the returned handle is for the main program. +.PP +External references in the library are resolved using the libraries +in that library's dependency list and any other libraries previously +opened with the +.B RTLD_GLOBAL +flag. +If the executable was linked +with the flag "-rdynamic", then the global symbols in the executable +will also be used to resolve references in a dynamically loaded +library. +.PP +.I flag +must be either +.BR RTLD_LAZY , +meaning resolve undefined symbols as code from the dynamic library is +executed, or +.BR RTLD_NOW , +meaning resolve all undefined symbols before +.B dlopen +returns, and fail if this cannot be done. +Optionally, +.B RTLD_GLOBAL +may be or'ed with +.IR flag, +in which case the external symbols defined in the library will be +made available to subsequently loaded libraries. +.PP +If the library exports a routine named +.BR _init , +then that code is executed before dlopen returns. +If the same library is loaded twice with +.BR dlopen() , +the same file handle is returned. The dl library maintains link +counts for dynamic file handles, so a dynamic library is not +deallocated until +.B dlclose +has been called on it as many times as +.B dlopen +has succeeded on it. +.PP +If +.B dlopen +fails for any reason, it returns NULL. +A human readable string describing the most recent error that occurred +from any of the dl routines (dlopen, dlsym or dlclose) can be +extracted with +.BR dlerror() . +.B dlerror +returns NULL if no errors have occurred since initialization or since +it was last called. (Calling +.B dlerror() +twice consecutively, will always result in the second call returning +NULL.) + +.B dlsym +takes a "handle" of a dynamic library returned by dlopen and the null +terminated symbol name, returning the address where that symbol is +loaded. If the symbol is not found, +.B dlsym +returns NULL; however, the correct way to test for an error from +.B dlsym +is to save the result of +.B dlerror +into a variable, and then check if saved value is not NULL. +This is because the value of the symbol could actually be NULL. +It is also necessary to save the results of +.B dlerror +into a variable because if +.B dlerror +is called again, it will return NULL. +.PP +.B dladdr +returns information about the shared library containing the memory +location specified by +.IR address . +.B dladdr +returns zero on success and non-zero on error. +.PP +.B dlclose +decrements the reference count on the dynamic library handle +.IR handle . +If the reference count drops to zero and no other loaded libraries use +symbols in it, then the dynamic library is unloaded. If the dynamic +library exports a routine named +.BR _fini , +then that routine is called just before the library is unloaded. +.SH EXAMPLES +.B Load the math library, and print the cosine of 2.0: +.RS +.nf +.if t .ft CW +#include + +int main(int argc, char **argv) { + void *handle = dlopen ("/lib/libm.so", RTLD_LAZY); + double (*cosine)(double) = dlsym(handle, "cos"); + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +} +.if t .ft P +.fi +.PP +If this program were in a file named "foo.c", you would build the program +with the following command: +.RS +.LP +gcc -rdynamic -o foo foo.c -ldl +.RE +.RE +.LP +.B Do the same thing, but check for errors at every step: +.RS +.nf +.if t .ft CW +#include +#include + +int main(int argc, char **argv) { + void *handle; + double (*cosine)(double); + char *error; + + handle = dlopen ("/lib/libm.so", RTLD_LAZY); + if (!handle) { + fputs (dlerror(), stderr); + exit(1); + } + + cosine = dlsym(handle, "cos"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } + + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +} +.if t .ft P +.fi +.RE +.SH ACKNOWLEDGEMENTS +The dlopen interface standard comes from Solaris. +The Linux dlopen implementation was primarily written by +Eric Youngdale with help from Mitch D'Souza, David Engel, +Hongjiu Lu, Andreas Schwab and others. +The manual page was written by Adam Richter. +.SH SEE ALSO +.BR ld(1) , +.BR ld.so(8) , +.BR ldconfig(8) , +.BR ldd(1) , +.BR ld.so.info . diff --git a/ldso/man/ld.so.8 b/ldso/man/ld.so.8 new file mode 100644 index 0000000..59ec853 --- /dev/null +++ b/ldso/man/ld.so.8 @@ -0,0 +1,113 @@ +.TH ld.so 8 "14 March 1998" +.SH NAME +ld.so/ld-linux.so \- dynamic linker/loader +.SH DESCRIPTION +.B ld.so +loads the shared libraries needed by a program, prepares the program +to run, and then runs it. +Unless explicitly specified via the +.B \-static +option to +.B ld +during compilation, all Linux programs are incomplete and require +further linking at run time. +.PP +The necessary shared libraries needed by the program are searched for +in the following order +.IP o +Using the environment variable +.B LD_LIBRARY_PATH +.RB ( LD_AOUT_LIBRARY_PATH +for a.out programs). +Except if the executable is a setuid/setgid binary, in which case it +is ignored. +.IP o +From the cache file +.BR /etc/ld.so.cache +which contains a compiled list of candidate libraries previously found +in the augmented library path. +.IP o +In the default path +.BR /usr/lib , +and then +.BR /lib . +.SH ENVIRONMENT +.TP +.B LD_LIBRARY_PATH +A colon-separated list of directories in which to search for +ELF libraries at execution-time. +Similar to the +.B PATH +environment variable. +.TP +.B LD_PRELOAD +A whitespace-separated list of additional, user-specified, ELF shared +libraries to be loaded before all others. +This can be used to selectively override functions in other shared libraries. +For setuid/setgid ELF binaries, only libraries in the standard search +directories that are also setgid will be loaded. +.TP +.B LD_TRACE_LOADED_OBJECTS +If present, causes the program to list its dynamic library dependencies, +as if run by ldd, instead of running normally. +.TP +.B LD_BIND_NOW +If present, causes the dynamic linker to resolve all symbols at program +startup instead of when they are first referenced. +.TP +.B LD_AOUT_LIBRARY_PATH +A colon-separated list of directories in which to search for +a.out libraries at execution-time. +Similar to the +.B PATH +environment variable. +.TP +.B LD_AOUT_PRELOAD +The name of an additional, user-specified, a.out shared library to be loaded +after all others. +This can be used to selectively override functions in other shared libraries. +.TP +.B LD_NOWARN +Suppress warnings about a.out libraries with incompatible minor +version numbers. +.TP +.B LD_KEEPDIR +Don't ignore the directory in the names of a.out libraries to be loaded. +Use of this option is strongly discouraged. +.SH FILES +.PD 0 +.TP 20 +.B /lib/ld.so +a.out dynamic linker/loader +.TP 20 +.B /lib/ld-linux.so.* +ELF dynamic linker/loader +.TP +.B /etc/ld.so.cache +File containing a compiled list of directories in which to search for +libraries and an ordered list of candidate libraries. +.TP +.B /etc/ld.so.preload +File containing a whitespace separated list of ELF shared libraries to +be loaded before the program. +libraries and an ordered list of candidate libraries. +.TP +.B lib*.so* +shared libraries +.PD +.SH SEE ALSO +.BR ldd (1), +.BR ldconfig (8). +.SH BUGS +.LP +Currently +.B ld.so +has no means of unloading and searching for compatible or newer version of +libraries. +.PP +.B ld.so +functionality is only available for executables compiled using libc version +4.4.3 or greater. +.SH AUTHORS +David Engel, Eric Youngdale, Peter MacDonald, Hongjiu Lu, Linus +Torvalds, Lars Wirzenius and Mitch D'Souza (not necessarily in that order). diff --git a/ldso/man/ld.so.texi b/ldso/man/ld.so.texi new file mode 100644 index 0000000..4e5fb84 --- /dev/null +++ b/ldso/man/ld.so.texi @@ -0,0 +1,411 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename ld.so.info +@settitle ld.so : Dynamic-Link Library support +@c %**end of header + +@ifinfo +This file documents the dynamic-link support libraries and utilities for the +Linux OS, version 1.8.1. + +Copyright 1996 Michael Deutschmann + +This document is subject to the GNU General Public License as published by +the Free Software foundation, version 2 or later (your choice). + +Note: The software described in this document is under a different copyright +and license. + +@end ifinfo + +@titlepage +@title ld.so +@subtitle Dynamic Link library support for the Linux OS. +@author David Engel +@author Eric Youngdale +@author Peter Macdonald +@author Hongjiu Lu +@author Mitch D'Souza +@author Michael Deutschmann (this documentation) + +@page +Copyright @copyright{} 1996 Michael Deutschmann + +This document is subject to the GNU General Public License as published by +the Free Software foundation, version 2 or later (your choice). + +Note: The software described in this document is under a different copyright +and license. +@end titlepage + +@ifinfo +@node Top +@top + +The @code{ld.so} module provides dynamic linked library support in Linux. +This file documents @code{ld.so} and its companion software. + +@menu +* intro:: Introduction + +* ld.so:: The dynamic linker core program +* ldd:: A utility to print out dependencies +* ldconfig:: A utility to maintain the cache and symlinks +* libdl:: Manual dynamic linking library +@end menu + +@end ifinfo + +@node intro +@unnumbered Introduction + +The @code{ld.so} suite contains special files and utilities needed for linux +to handle @dfn{dynamic libraries}. + +Ordinary static libraries (@file{lib*.a} files) are included into executables +that use their functions. A file that only uses static libraries needs less +intelligence to load, but takes up more space. If many executables use the +same library, there can be much wastage of storage space, since multiple +copies of the library functions are scattered across the executables. +However, static libraries are easier to make. + +Dynamic libraries (@file{lib*.so*} files) are not copied into executables --- +the executable is written in such a way that it will automatically load the +libraries. In linux, the executable will first load the special library +@code{ld.so} or @code{ld-linux.so}, which contains the intelligence +to load further dynamic libraries. Since multiple files end up getting +executable data from the same file, dynamic libraries are also known as +shared libraries. + +Linux executables come in two flavors, @sc{elf} and a.out. + +a.out is the original executable format used by Linux. It has somewhat less +overhead than @sc{elf}. However creating shared libraries for a.out is +@emph{very} involved, and each a.out shared library must be explicitly +registered. + +@sc{elf} is a more recent format, which supports a much simpler method of +creating libraries. @sc{elf} libraries may also be linked manually +(@pxref{libdl}). + +Since many library authors prefer @sc{elf} and no longer release shared a.out +libraries, a.out is moribund on Linux. This version of the @code{ld.so} can +be compiled to support only @sc{elf}, or to support both formats. (The last +release of ld.so to support a.out alone was 1.8.0.) + +@node ld.so +@chapter @code{ld.so}: Dynamic linker core + +@code{ld.so} works behind the scenes to handle dynamic libraries in Linux. +Users will almost never have to deal with it directly, but in special cases +one can send instructions to it through environment variables. Also, if +something is wrong with your libraries (usually an incorrect version) ld.so +will give error messages. + +Actually @code{ld.so} is the a.out linker. The new @sc{elf} executables are +handled by a related program @code{ld-linux.so}. + +@menu +* files:: Configuration files used by the suite +* environment:: Environment settings that tweak @code{ld.so} +* errors:: Complaints @code{ld.so} might make +@end menu + +@node files +@section Configuration Files + +@table @file +@item /etc/ld.so.cache +A file created by @code{ldconfig} and used to speed linking. It's structure +is private to the suite. + +@item /etc/ld.so.conf +A simple list of directories to scan for libraries, in addition to +@file{/usr/lib} and @file{/lib}, which are hardwired. It may contain +comments started with a @samp{#}. + +@item /etc/ld.so.preload +A list of libraries to preload. This allows preloading libraries for +setuid/setgid executables securely. It may contain comments. +@end table + +@node environment +@section Environment Variables + +@table @code +@item LD_AOUT_LIBRARY_PATH +@itemx LD_LIBRARY_PATH +These variables supply a library path for finding dynamic libraries, in the +standard colon seperated format. These variables are ignored when executing +setuid/setgid programs, because otherwise they would be a security hazard. +@code{ld.so} will use @code{LD_AOUT_LIBRARY_PATH} and @code{ld-linux.so} will +use @code{LD_LIBRARY_PATH}. + +@item LD_AOUT_PRELOAD +@itemx LD_PRELOAD +These variables allow an extra library not specified in the executable to be +loaded. Generally this is only useful if you want to override a function. +These are also ignored when running setuid/setgid executables. @code{ld.so} +will use @code{LD_AOUT_PRELOAD} and @code{ld-linux.so} will use +@code{LD_PRELOAD}. + +@item LD_NOWARN +If non-empty, errors about incompatible minor revisions are suppressed. + +@item LD_KEEPDIR +If non-empty, allow executables to specify absolute library names. This +option is deprecated. +@c FIXME: +@c The following are things I noticed in the ld-linux.so source. +@c I don't really understand 'em. Could someone help me? +@c +@c @item LD_BIND_NOW +@c This option is used by the @code{ld-linux.so} only. I don't know +@c what it does. (I suspect, looking at the code, that it specifies +@c "RTLD_NOW" rather than "RTLD_LAZY" mode for the shared libraries.) +@c +@c @item LD_TRACE_LOADED_OBJECTS +@c @itemx LD_WARN +@c These seem to have something to do with the communication between the +@c @code{ld-linux.so} and @code{ldd}. I don't know more. +@end table + +@node errors +@section Errors + +@table @samp +@item Can't find library @var{library} +The executable required a dynamically linked library that ld.so cannot find. +Your symbolic links may be not set right, or you may have not installed a +library needed by the program. + +@item Can't load library @var{library} +The library is corrupt. + +@item Incompatible library @var{library} +@itemx Require major version @var{x} and found @var{y} +Your version of the library is incompatible with the executable. Recompiling +the executable, or upgrading the library will fix the problem. + +@item using incompatible library @var{library} +@itemx Desire minor version >= @var{x} and found @var{y}. +Your version of the library is older than that expected by the executable, +but not so old that the library interface has radically changed, so the +linker will attempt to run anyway. There is a chance that it will work, but +you should upgrade the library or recompile the software. The environment +variable @code{LD_NOWARN} can be used to supress this message. + +@item too many directories in library path +The linker only supports up to 32 library directories. You have too many. + +@item dynamic linker error in @var{blah} +The linker is having trouble handling a binary - it is probably corrupt. + +@item can't map cache file @var{cache-file} +@itemx cache file @var{cache-file} @var{blah} +The linker cache file (generally @file{/etc/ld.so.cache}) is corrupt or +non-existent. These errors can be ignored, and can be prevented by +regenerating the cache file with @code{ldconfig}. +@end table + +@node ldd +@chapter @code{ldd}: Dependency scanner + +@code{ldd} is a utility that prints out the dynamic libraries that an +executable is linked to. + +Actually @code{ldd} works by signalling ld.so to print the dependencies. +For a.out executables this is done by starting the executable with +@code{argc} equal to 0. The linker detects this and prints the dependencies. +(This can cause problems with @emph{very} old binaries, which would run as +normal only with an inappropriate @code{argc}.) + +For @sc{elf} executables, special environment variables are used to tell the +linker to print the dependencies. + +@code{ldd} has a few options: + +@table @samp +@item -v +Print the version number of @code{ldd} itself + +@item -V +Print the version number of the dynamic linker + +@item -d +Report missing functions. This is only supported for @sc{elf} executables. + +@item -r +Report missing objects. This is also only available for @sc{elf} +executables. +@end table + +@node ldconfig +@chapter @code{ldconfig}: Setup program + +This utility is used by the system administrator to automatically set up +symbolic links needed by the libraries, and also to set up the cache file. + +@code{ldconfig} is run after new dynamic libraries are installed, and if the +cache file or links are damaged. It is also run when upgrading the +@code{ld.so} suite itself. + +The @file{/lib} and @file{/usr/lib} directories, and any listed in the file +@file{/etc/ld.so.conf} are scanned by default unless @samp{-n} is used. +Additional directories may be specified on the command line. + +It has the following options: + +@table @samp +@item -D +Enter debug mode. Implies @samp{-N} and @samp{-X}. + +@item -v +Verbose. Print out links created and directories scanned. + +@item -n +Check directories specified on the commandline @emph{only}. + +@item -N +Do not regenerate the cache. + +@item -X +Do not rebuild symbolic links. + +@item -l +Set up symbolic links for only libraries presented on the command line. + +@item -p +Print out the library pathnames in the cache file (@file{/etc/ld.so.cache}) +@end table + +@node libdl +@chapter User dynamic linking library + +The @code{ld.so} package includes a small library of functions +(@code{libdl}) to allow manual dynamic linking. Normally programs are linked +so that dynamic functions and objects are automagically available. These +functions allow one to manually load and access a symbol from a library. +They are only available for @sc{elf} executables. + +@menu +* using libdl:: General points +* functions:: How to use the functions +* example:: A sample program +@end menu + +@node using libdl +@section Overview + +To access this library, add the flag @samp{-ldl} to your compile command when +linking the executable. You also must include the header file +@code{dlfcn.h}. You may also need the flag @samp{-rdynamic}, which enables +resolving references in the loaded libraries against your executable. + +Generally, you will first use @code{dlopen} to open a library. Then you use +@code{dlsym} one or more times to access symbols. Finally you use +@code{dlclose} to close the library. + +These facilities are most useful for language interpreters that provide +access to external libraries. Without @code{libdl}, it would be neccessary +to link the interpreter executable with any and all external libraries +needed by the programs it runs. With @code{libdl}, the interpreter only +needs to be linked with the libraries it uses itself, and can dynamically +load in additional ones if programs need it. + +@node functions +@section Functions + +@deftypefun void *dlopen ( const char @var{filename}, int @var{flags} ) + +This function opens the dynamic library specified by @var{filename} +and returns an abstract handle, which can be used in subsequent calls to +@code{dlsym}. The function will respect the @code{LD_ELF_LIBRARY_PATH} and +@code{LD_LIBRARY_PATH} environment variables. + +@end deftypefun + +The following flags can be used with @code{dlopen}: + +@deftypevr Macro int RTLD_LAZY +Resolve symbols in the library as they are needed. +@end deftypevr + +@deftypevr Macro int RTLD_NOW +Resolve all symbols in the library before returning, and fail if not all can +be resolved. This is mutually exclusive with @code{RTLD_LAZY}. +@end deftypevr + +@deftypevr Macro int RTLD_GLOBAL +Make symbols in this library available for resolving symbols in other +libraries loaded with @code{dlopen}. +@end deftypevr + +@deftypefun int dlclose ( void *@var{handle} ) + +This function releases a library handle. + +Note that if a library opened twice, the handle will be the same. However, +a reference count is used, so you should still close the library as many +times as you open it. + +@end deftypefun + +@deftypefun void *dlsym (void *@var{handle},char *@var{symbol-name}) + +This function looks up the name @var{symbol-name} in the library and returns +it in the void pointer. + +If there is an error, a null pointer will be returned. However, it is +possible for a valid name in the library to have a null value, so +@code{dlerror} should be used to check if there was an error. + +@end deftypefun + +@deftypefun {libdl function} {const char} *dlerror( void ) + +This function is used to read the error state. It returns a human-readable +string describing the last error, or null, meaning no error. + +The function resets the error value each time it is called, so the result +should be copied into a variable. If the function is called more than once +after an error, the second and subsequent calls will return null. + +@end deftypefun + +@node example +@section Example program + +Here is an example program that prints the cosine of two by manually linking +to the math library: + +@example +@c The following was snarfed verbatim from the dlopen.3 man file. +#include +#include + +int main(int argc, char **argv) @{ + void *handle; + double (*cosine)(double); + char *error; + + handle = dlopen ("/lib/libm.so", RTLD_LAZY); + if (!handle) @{ + fputs (dlerror(), stderr); + exit(1); + @} + + cosine = dlsym(handle, "cos"); + if ((error = dlerror()) != NULL) @{ + fputs(error, stderr); + exit(1); + @} + + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +@} +@end example + +@contents + +@bye diff --git a/ldso/man/ldconfig.8 b/ldso/man/ldconfig.8 new file mode 100644 index 0000000..8228529 --- /dev/null +++ b/ldso/man/ldconfig.8 @@ -0,0 +1,189 @@ +.TH ldconfig 8 "14 March 1998" +.SH NAME +ldconfig \- determine run-time link bindings +.SH SYNOPSIS +ldconfig +.RB [ \-DvqnNX ] +.RB [ \-f\ conf ] +.RB [ \-C\ cache ] +.RB [ \-r\ root ] +.IR directory \ ... +.PD 0 +.PP +.PD +ldconfig +.B \-l +.RB [ \-Dvq ] +.IR library \ ... +.PD 0 +.PP +.PD +ldconfig +.B \-p +.SH DESCRIPTION +.B ldconfig +creates the necessary links and cache (for use by the run-time linker, +.IR ld.so ) +to the most recent shared libraries found in the directories specified +on the command line, in the file +.IR /etc/ld.so.conf , +and in the trusted directories +.RI ( /usr/lib +and +.IR /lib ). +.B ldconfig +checks the header and file names of the libraries it encounters when +determining which versions should have their links updated. +.B ldconfig +ignores symbolic links when scanning for libraries. +.PP +.B ldconfig +will attempt to deduce the type of ELF libs (ie. libc5 or libc6/glibc) +based on what C libs if any the library was linked against, therefore when +making dynamic libraries, it is wise to explicitly link against libc (use -lc). +.PP +Some existing libs do not contain enough information to allow the deduction of +their type, therefore the +.IR /etc/ld.so.conf +file format allows the specification of an expected type. This is +.B only +used for those ELF libs which we can not work out. The format +is like this "dirname=TYPE", where type can be libc4, libc5 or libc6. +(This syntax also works on the command line). Spaces are +.B not +allowed. Also see the +.B -p +option. +.PP +Directory names containing an +.B = are no longer legal +unless they also have an expected type specifier. +.PP +.B ldconfig +should normally be run by the super-user as it may require write +permission on some root owned directories and files. +It is normally run automatically at bootup, from /etc/rc, or manually +whenever new DLL's are installed. +.SH OPTIONS +.TP +.B \-D +Debug mode. +Implies +.B \-N +and +.BR \-X . +.TP +.B \-v +Verbose mode. +Print current version number, the name of each directory as it +is scanned and any links that are created. +Overrides quiet mode. +.TP +.B \-q +Quiet mode. +Don't print warnings. +.TP +.B \-n +Only process directories specified on the command line. +Don't process the trusted directories +.RI ( /usr/lib +and +.IR /lib ) +nor those specified in +.IR /etc/ld.so.conf . +Implies +.BR \-N . +.TP +.B \-N +Don't rebuild the cache. +Unless +.B \-X +is also specified, links are still updated. +.TP +.B \-X +Don't update links. +Unless +.B \-N +is also specified, the cache is still rebuilt. +.TP +.B \-f conf +Use +.B conf +instead of +.IR /etc/ld.so.conf . +.TP +.B \-C cache +Use +.B cache +instead of +.IR /etc/ld.so.cache . +.TP +.B \-r root +Change to and use +.B root +as the root directory. +.TP +.B \-l +Library mode. +Manually link individual libraries. +Intended for use by experts only. +.TP +.B \-p +Print the lists of directories and candidate libraries stored in +the current cache. +.SH EXAMPLES +In the bootup file +.I /etc/rc +having the line +.RS + +/sbin/ldconfig -v + +.RE +will set up the correct links for the shared binaries and rebuild +the cache. +.TP +On the command line +.RS + +# /sbin/ldconfig -n /lib + +.RE +as root after the installation of a new DLL, will properly update the +shared library symbolic links in /lib. + +.SH FILES +.PD 0 +.TP 20 +.B /lib/ld.so +execution time linker/loader +.TP 20 +.B /etc/ld.so.conf +File containing a list of colon, space, tab, newline, or comma spearated +directories in which to search for libraries. +.TP 20 +.B /etc/ld.so.cache +File containing an ordered list of libraries found in the directories +specified in +.BR /etc/ld.so.conf . +.TP +.B lib*.so.version +shared libraries +.PD +.SH SEE ALSO +.BR ldd (1), +.BR ld.so (8). +.SH BUGS +.LP +.BR ldconfig 's +functionality, in conjunction with +.BR ld.so , +is only available for executables compiled using libc version 4.4.3 or greater. +.PP +.BR ldconfig , +being a user process, must be run manually and has no means of dynamically +determining and relinking shared libraries for use by +.BR ld.so +when a new DLL is installed. +.SH AUTHORS +David Engel and Mitch D'Souza. diff --git a/ldso/man/ldd.1 b/ldso/man/ldd.1 new file mode 100644 index 0000000..20c5578 --- /dev/null +++ b/ldso/man/ldd.1 @@ -0,0 +1,59 @@ +.\" Copyright 1995-2000 David Engel (david@ods.com) +.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu) +.\" Most of this was copied from the README file. Do not restrict distribution. +.\" May be distributed under the GNU General Public License +.TH LDD 1 "14 March 1998" +.SH NAME +ldd \- print shared library dependencies +.SH SYNOPSIS +.B ldd +.RB [ \-vVdr ] +program|library ... +.SH DESCRIPTION +.B ldd +prints the shared libraries required by each program or shared library +specified on the command line. +If a shared library name does not contain a '/', +.B ldd +attempts to locate the library in the standard locations. +To run +.B ldd +on a shared library in the current directory, a "./" must be prepended +to its name. +.SH OPTIONS +.TP +.B \-v +Print the version number of +.BR ldd . +.TP +.B \-V +Print the version number of the dynamic linker, +.BR ld.so . +.TP +.B \-d +Perform relocations and report any missing functions (ELF only). +.TP +.B \-r +Perform relocations for both data objects and functions, and +report any missing objects (ELF only). +.SH BUGS +.B ldd +does not work very well on libc.so.5 itself. +.PP +.B ldd +does not work on a.out shared libraries. +.PP +.B ldd +does not work with some extremely old a.out programs which were +built before +.B ldd +support was added to the compiler releases. +If you use +.B ldd +on one of these programs, the program will attempt to run with argc = 0 and +the results will be unpredictable. +.SH AUTHOR +David Engel. +.SH SEE ALSO +.BR ldconfig (8), +.BR ld.so (8). diff --git a/libc/Makefile b/libc/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/Makefile.in b/libc/Makefile.in new file mode 100644 index 0000000..16768db --- /dev/null +++ b/libc/Makefile.in @@ -0,0 +1,100 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libc_DIR := $(top_srcdir)libc +libc_OUT := $(top_builddir)libc + +# Check if the target architecture has a version script for +# libc, and if so, include it when linking. +VERSION_SCRIPT := $(wildcard $(libc_DIR)/sysdeps/linux/$(TARGET_ARCH)/libc.map) +ifneq ($(VERSION_SCRIPT),) +VERSION_SCRIPT := -Wl,--version-script,$(VERSION_SCRIPT) +endif + +LDFLAGS-libc.so := $(LDFLAGS) $(VERSION_SCRIPT) -Wl,-init,$(SYMBOL_PREFIX)__uClibc_init + +LIBS-libc.so := $(interp) $(ldso) $(top_builddir)lib/$(NONSHARED_LIBNAME) + +# we have SHARED_MAJORNAME=libc.so.$(MAJOR_VERSION) defined in Rules.mak +libc_FULL_NAME := libuClibc-$(VERSION).so + +# this comes first, so duplicate removal works correctly +include $(libc_DIR)/sysdeps/Makefile.in + +include $(libc_DIR)/misc/Makefile.in +include $(libc_DIR)/pwd_grp/Makefile.in +include $(libc_DIR)/stdio/Makefile.in +include $(libc_DIR)/string/Makefile.in +include $(libc_DIR)/termios/Makefile.in +include $(libc_DIR)/inet/Makefile.in +include $(libc_DIR)/signal/Makefile.in +include $(libc_DIR)/stdlib/Makefile.in +include $(libc_DIR)/unistd/Makefile.in + +ifeq ($(DOPIC),y) +libc-a-y = $(libc-y:.o=.os) $(libc-static-y:.o=.os) +else +libc-a-y = $(libc-y) $(libc-static-y) +endif + +ifeq ($(DOMULTI),n) +libc-so-y = $(libc-y:.o=.os) $(libc-shared-y) +else +all_sources = $(libc-y:.o=.c) +all_sources += $(libc-shared-y:.oS=.c) +libc-multi-y = $(filter-out $(libc-nomulti-y:.o=.c),$(all_sources)) +endif + +lib-a-y += $(top_builddir)lib/libc.a +lib-gdb-y += $(top_builddir)lib/libc.gdb +lib-so-y += $(libc.depend) +objclean-y += libc_clean + +OUTPUT_FORMAT = $(CC) $(CFLAGS) -Wl,--verbose 2>&1 | $(SED) -n 's/^OUTPUT_FORMAT("\([^"]*\)",.*/OUTPUT_FORMAT ( \1 )/p' + +ifeq ($(DOMULTI),n) +$(libc.depend): $(libc_OUT)/libc_so.a $(LIBS-libc.so) + $(call link.so,$(libc_FULL_NAME),$(MAJOR_VERSION)) +else +$(libc.depend): $(libc_OUT)/libc.oS $(libc-nomulti-y:.o=.oS) | $(LIBS-libc.so) + $(call linkm.so,$(libc_FULL_NAME),$(MAJOR_VERSION)) +endif + $(Q)$(RM) $@ + $(Q)cp $(top_srcdir)extra/scripts/format.lds $@ + $(Q)echo "$(shell $(OUTPUT_FORMAT))" >> $@ +ifeq ($(COMPAT_ATEXIT),y) + $(Q)echo "GROUP ( $(NONSHARED_LIBNAME) $(SHARED_MAJORNAME) $(ASNEEDED) )" >> $@ +else + $(Q)echo "GROUP ( $(SHARED_MAJORNAME) $(NONSHARED_LIBNAME) $(ASNEEDED) )" >> $@ +endif + +$(libc_OUT)/libc_so.a: $(libc-so-y) | $(top_builddir)lib/libc.a $(top_builddir)lib/$(NONSHARED_LIBNAME) + $(Q)$(RM) $@ +ifeq ($(DOPIC),y) + $(Q)$(STRIPTOOL) $(STRIP_FLAGS) $(libc-shared-y) +else + $(do_strip) +endif + $(do_ar) + +$(libc_OUT)/libc.oS: $(libc-multi-y) | $(top_builddir)lib/libc.a $(top_builddir)lib/$(NONSHARED_LIBNAME) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libc.a: $(libc-a-y) | $(crt-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +# We use libc_so.a so that we can compile the shared library with special +# flags - i.e. -mleaf-id-shared-library. The static libc.a needs to be +# compiled without it. +$(top_builddir)lib/libc.gdb: $(libc_OUT)/libc_so.a $(LINK_FLAT_CRTS) + $(call link-flat.so,$(@:.gdb=),$(UCLIBC_SHARED_FLAT_ID)) + +libc_clean: + $(do_rm) $(addprefix $(libc_OUT)/*., o os oS a) diff --git a/libc/inet/.indent.pro b/libc/inet/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/inet/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/inet/Makefile b/libc/inet/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/inet/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in new file mode 100644 index 0000000..f905c8e --- /dev/null +++ b/libc/inet/Makefile.in @@ -0,0 +1,67 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)libc/inet/rpc/Makefile.in + +INET_DIR := $(top_srcdir)libc/inet +INET_OUT := $(top_builddir)libc/inet + +CSRC := +ifneq ($(UCLIBC_HAS_CRYPT_IMPL)$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) +# des uses nthol +CSRC += ntohl.c +endif +ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) +CSRC += getservice.c getproto.c hostid.c getnetent.c getnetbynm.c getnetbyad.c \ + inet_net.c herror.c if_index.c gai_strerror.c getaddrinfo.c \ + ether_addr.c ifaddrs.c ntop.c +endif +ifeq ($(UCLIBC_HAS_IPV6),y) +CSRC += in6_addr.c +endif + +# multi source addr.c +addr_CSRC := inet_aton.c inet_addr.c inet_ntoa.c inet_makeaddr.c \ + inet_lnaof.c inet_netof.c +ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) +CSRC += $(addr_CSRC) +endif + +# multi source resolv.c +resolv_CSRC += encodeh.c decodeh.c encoded.c decoded.c lengthd.c encodeq.c \ + decodeq.c lengthq.c encodea.c decodea.c \ + dnslookup.c resolveaddress.c opennameservers.c \ + closenameservers.c resolvename.c gethostbyname.c res_init.c \ + res_query.c gethostbyaddr.c read_etc_hosts_r.c get_hosts_byname_r.c \ + get_hosts_byaddr_r.c gethostbyname2.c getnameinfo.c gethostent.c \ + gethostbyname_r.c gethostbyname2_r.c gethostbyaddr_r.c \ + res_comp.c ns_name.c ethers.c +ifneq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),) +CSRC += $(resolv_CSRC) + +# unused ATM +CSRC += encodep.c decodep.c formquery.c +endif + + +# multi source socketcalls.c +socketcalls_CSRC += accept.c bind.c connect.c getpeername.c getsockname.c \ + getsockopt.c listen.c recv.c recvfrom.c recvmsg.c send.c sendmsg.c \ + sendto.c setsockopt.c shutdown.c socket.c socketpair.c +ifeq ($(UCLIBC_HAS_SOCKET),y) +CSRC += $(socketcalls_CSRC) opensock.c +endif + +INET_SRC := $(patsubst %.c,$(INET_DIR)/%.c,$(CSRC)) +INET_OBJ := $(patsubst %.c,$(INET_OUT)/%.o,$(CSRC)) + +libc-y += $(INET_OBJ) + +objclean-y += inet_clean + +inet_clean: + $(do_rm) $(addprefix $(INET_OUT)/*., o os) diff --git a/libc/inet/accept.c b/libc/inet/accept.c new file mode 100644 index 0000000..0217a68 --- /dev/null +++ b/libc/inet/accept.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_accept +#include "socketcalls.c" diff --git a/libc/inet/addr.c b/libc/inet/addr.c new file mode 100644 index 0000000..2a0bb84 --- /dev/null +++ b/libc/inet/addr.c @@ -0,0 +1,223 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Manuel Novoa III Dec 2000 + * + * Converted to use my new (un)signed long (long) to string routines, which + * are smaller than the previous functions and don't require static buffers. + * In the process, removed the reference to strcat and cut object size of + * inet_ntoa in half (from 190 bytes down to 94). + * + * Manuel Novoa III Feb 2002 + * + * Changed to use _int10tostr. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include + +#ifdef L_inet_aton +/* + * More undocumented inet_aton features. + * (read: uclibc doesnt support but glibc does) + * http://www.mkssoftware.com/docs/man3/inet_aton.3.asp + * + * *cp can take the form of: + * a.b.c.d - {a,b,c,d} -> 1 byte + * a.b.c - {a,b} -> 1 byte {c} -> 2 bytes + * a.b - {a} -> 1 byte {b} -> 3 bytes + * a - {a} -> 4 bytes + * + * Each part may be decimal, octal, or hexadecimal as in ISO C. + * 0x or 0X -> hexadecimal + * leading 0 -> octal + * all else -> decimal + */ +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif +libc_hidden_proto(inet_aton) +int inet_aton(const char *cp, struct in_addr *addrptr) +{ + in_addr_t addr; + int value; + int part; + + if (cp == NULL) { + return 0; + } + + addr = 0; + for (part = 1; part <= 4; part++) { + + if (!isdigit(*cp)) + return 0; + + value = 0; + while (isdigit(*cp)) { + value *= 10; + value += *cp++ - '0'; + if (value > 255) + return 0; + } + + if (part < 4) { + if (*cp++ != '.') + return 0; + } else { + char c = *cp++; + if (c != '\0' && !isspace(c)) + return 0; + } + + addr <<= 8; + addr |= value; + } + + /* W. Richard Stevens in his book UNIX Network Programming, + * Volume 1, second edition, on page 71 says: + * + * An undocumented feature of inet_aton is that if addrptr is + * a null pointer, the function still performs it validation + * of the input string, but does not store the result. + */ + if (addrptr) { + addrptr->s_addr = htonl(addr); + } + + return 1; +} +libc_hidden_def(inet_aton) +#endif + +#ifdef L_inet_addr +libc_hidden_proto(inet_aton) + +libc_hidden_proto(inet_addr) +in_addr_t inet_addr(const char *cp) +{ + struct in_addr a; + + if (!inet_aton(cp, &a)) + return INADDR_NONE; + else + return a.s_addr; +} +libc_hidden_def(inet_addr) +#endif + +#ifdef L_inet_ntoa + +#define INET_NTOA_MAX_LEN 16 /* max 12 digits + 3 '.'s + 1 nul */ + +libc_hidden_proto(inet_ntoa_r) +char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN]) +{ + in_addr_t addr = ntohl(in.s_addr); + int i; + char *p, *q; + + q = 0; + p = buf + INET_NTOA_MAX_LEN - 1; /* cannot use sizeof(buf) here */ + for (i = 0; i < 4; i++ ) { + p = _int10tostr(p, addr & 0xff) - 1; + addr >>= 8; + if (q) { + *q = '.'; + } + q = p; + } + + return p+1; +} +libc_hidden_def(inet_ntoa_r) + +libc_hidden_proto(inet_ntoa) +char *inet_ntoa(struct in_addr in) +{ + static char buf[INET_NTOA_MAX_LEN]; + return inet_ntoa_r(in, buf); +} +libc_hidden_def(inet_ntoa) +#endif + +#ifdef L_inet_makeaddr + +/* for some reason it does not remove the jump relocation */ +/* Experimentally off - libc_hidden_proto(memmove) */ + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +libc_hidden_proto(inet_makeaddr) +struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host) +{ + in_addr_t addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216UL) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return *(struct in_addr *)&addr; +} +libc_hidden_def(inet_makeaddr) +#endif + +#ifdef L_inet_lnaof +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +in_addr_t inet_lnaof(struct in_addr in) +{ + in_addr_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (i & IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return (i & IN_CLASSB_HOST); + else + return (i & IN_CLASSC_HOST); +} +#endif + +#ifdef L_inet_netof + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +libc_hidden_proto(inet_netof) +in_addr_t +inet_netof(struct in_addr in) +{ + in_addr_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} +libc_hidden_def(inet_netof) +#endif diff --git a/libc/inet/bind.c b/libc/inet/bind.c new file mode 100644 index 0000000..d13e226 --- /dev/null +++ b/libc/inet/bind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_bind +#include "socketcalls.c" diff --git a/libc/inet/closenameservers.c b/libc/inet/closenameservers.c new file mode 100644 index 0000000..ca4dae3 --- /dev/null +++ b/libc/inet/closenameservers.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_closenameservers +#include "resolv.c" diff --git a/libc/inet/connect.c b/libc/inet/connect.c new file mode 100644 index 0000000..bddbe16 --- /dev/null +++ b/libc/inet/connect.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_connect +#include "socketcalls.c" diff --git a/libc/inet/decodea.c b/libc/inet/decodea.c new file mode 100644 index 0000000..409a978 --- /dev/null +++ b/libc/inet/decodea.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodea +#include "resolv.c" diff --git a/libc/inet/decoded.c b/libc/inet/decoded.c new file mode 100644 index 0000000..73849ef --- /dev/null +++ b/libc/inet/decoded.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decoded +#include "resolv.c" diff --git a/libc/inet/decodeh.c b/libc/inet/decodeh.c new file mode 100644 index 0000000..86681fa --- /dev/null +++ b/libc/inet/decodeh.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodeh +#include "resolv.c" diff --git a/libc/inet/decodep.c b/libc/inet/decodep.c new file mode 100644 index 0000000..40b0bda --- /dev/null +++ b/libc/inet/decodep.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodep +#include "resolv.c" diff --git a/libc/inet/decodeq.c b/libc/inet/decodeq.c new file mode 100644 index 0000000..a610967 --- /dev/null +++ b/libc/inet/decodeq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodeq +#include "resolv.c" diff --git a/libc/inet/dnslookup.c b/libc/inet/dnslookup.c new file mode 100644 index 0000000..4ffc34f --- /dev/null +++ b/libc/inet/dnslookup.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_dnslookup +#include "resolv.c" diff --git a/libc/inet/encodea.c b/libc/inet/encodea.c new file mode 100644 index 0000000..628f9ba --- /dev/null +++ b/libc/inet/encodea.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodea +#include "resolv.c" diff --git a/libc/inet/encoded.c b/libc/inet/encoded.c new file mode 100644 index 0000000..d606187 --- /dev/null +++ b/libc/inet/encoded.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encoded +#include "resolv.c" diff --git a/libc/inet/encodeh.c b/libc/inet/encodeh.c new file mode 100644 index 0000000..1d54880 --- /dev/null +++ b/libc/inet/encodeh.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodeh +#include "resolv.c" diff --git a/libc/inet/encodep.c b/libc/inet/encodep.c new file mode 100644 index 0000000..d2f248b --- /dev/null +++ b/libc/inet/encodep.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodep +#include "resolv.c" diff --git a/libc/inet/encodeq.c b/libc/inet/encodeq.c new file mode 100644 index 0000000..be1a312 --- /dev/null +++ b/libc/inet/encodeq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodeq +#include "resolv.c" diff --git a/libc/inet/ether_addr.c b/libc/inet/ether_addr.c new file mode 100644 index 0000000..8e19a0f --- /dev/null +++ b/libc/inet/ether_addr.c @@ -0,0 +1,104 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. +*/ + +/* + * 2002-12-24 Nick Fedchik + * - initial uClibc port + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(ether_ntoa_r) +libc_hidden_proto(sprintf) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +libc_hidden_proto(__ctype_tolower_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +#endif + +struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr) +{ + size_t cnt; + + for (cnt = 0; cnt < 6; ++cnt) { + unsigned int number; + char ch; + + ch = _tolower(*asc++); + if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) + return NULL; + number = isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); + + ch = _tolower(*asc); + if ((cnt < 5 && ch != ':') + || (cnt == 5 && ch != '\0' && !isspace(ch))) { + ++asc; + if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) + return NULL; + number <<= 4; + number += isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); + + ch = *asc; + if (cnt < 5 && ch != ':') + return NULL; + } + + /* Store result. */ + addr->ether_addr_octet[cnt] = (unsigned char) number; + + /* Skip ':'. */ + ++asc; + } + + return addr; +} +libc_hidden_def(ether_aton_r) + +struct ether_addr *ether_aton(const char *asc) +{ + static struct ether_addr result; + + return ether_aton_r(asc, &result); +} + +char *ether_ntoa_r(const struct ether_addr *addr, char *buf) +{ + sprintf(buf, "%x:%x:%x:%x:%x:%x", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]); + return buf; +} +libc_hidden_def(ether_ntoa_r) + +char *ether_ntoa(const struct ether_addr *addr) +{ + static char asc[18]; + + return ether_ntoa_r(addr, asc); +} diff --git a/libc/inet/ethers.c b/libc/inet/ethers.c new file mode 100644 index 0000000..857e5d1 --- /dev/null +++ b/libc/inet/ethers.c @@ -0,0 +1,122 @@ +/* + * libc/inet/ethers.c + * + * Programmatic interface for the /etc/ethers file + * + * Copyright 2007 by Matthew Wilcox + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#define ETHER_LINE_LEN 256 + +/* + * Internal function which returns a pointer to the part of the line + * with the start of the hostname, or NULL if we couldn't parse the line. + * Note that this line may have a comment symbol on it somewhere; if so + * it will return NULL if the # is before or within the ether_addr, and + * succeed if the # is before or within the host. It's up to the callers + * to be aware of this. + * + * I would have preferred to write a NUL to the location of the comment + * character, but ether_line takes a const argument. See __ether_line_w. + */ +static const char *__ether_line(const char *line, struct ether_addr *addr) +{ + struct ether_addr *res = ether_aton_r(line, addr); + if (!res) + return NULL; + + while (*line && (*line != ' ') && (*line != '\t')) + line++; + while (*line && ((*line == ' ') || (*line == '\t'))) + line++; + return (*line) ? line : NULL; +} + +/* + * Strips out the comment before calling __ether_line. We can do this, + * since we know the buffer is writable. + */ +static const char *__ether_line_w(char *line, struct ether_addr *addr) +{ + char *end = strchr(line, '#'); + if (!end) + end = strchr(line, '\n'); + if (end) + *end = '\0'; + return __ether_line(line, addr); +} + +int ether_line(const char *line, struct ether_addr *addr, char *hostname) +{ + const char *name = __ether_line(line, addr); + if (!name) + return -1; + + while (*name) { + if ((*name == '#') || isspace(*name)) + break; + *hostname++ = *name++; + } + *hostname = '\0'; + + return 0; +} + +int ether_ntohost(char *hostname, const struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + struct ether_addr tmp_addr; + const char *cp = __ether_line_w(buf, &tmp_addr); + if (!cp) + continue; + if (memcmp(addr, &tmp_addr, sizeof(tmp_addr))) + continue; + + strcpy(hostname, cp); + res = 0; + break; + } + + fclose(fp); + return res; +} + +int ether_hostton(const char *hostname, struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + const char *cp = __ether_line_w(buf, addr); + if (!cp) + continue; + if (strcasecmp(hostname, cp)) + continue; + + res = 0; + break; + } + + fclose(fp); + return res; +} diff --git a/libc/inet/formquery.c b/libc/inet/formquery.c new file mode 100644 index 0000000..2c53e33 --- /dev/null +++ b/libc/inet/formquery.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_formquery +#include "resolv.c" diff --git a/libc/inet/gai_strerror.c b/libc/inet/gai_strerror.c new file mode 100644 index 0000000..61688ba --- /dev/null +++ b/libc/inet/gai_strerror.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include + +#define N_(x) x +#define _(x) x +static const struct + { + int code; + const char *msg; + } +values[] = + { + { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, + { EAI_AGAIN, N_("Temporary failure in name resolution") }, + { EAI_BADFLAGS, N_("Bad value for ai_flags") }, + { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, + { EAI_FAMILY, N_("ai_family not supported") }, + { EAI_MEMORY, N_("Memory allocation failure") }, + { EAI_NODATA, N_("No address associated with hostname") }, + { EAI_NONAME, N_("Name or service not known") }, + { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, + { EAI_SOCKTYPE, N_("ai_socktype not supported") }, + { EAI_SYSTEM, N_("System error") }, + { EAI_INPROGRESS, N_("Processing request in progress") }, + { EAI_CANCELED, N_("Request canceled") }, + { EAI_NOTCANCELED, N_("Request not canceled") }, + { EAI_ALLDONE, N_("All requests done") }, + { EAI_INTR, N_("Interrupted by a signal") } + }; + +const char * +gai_strerror (int code) +{ + size_t i; + for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i) + if (values[i].code == code) + return _(values[i].msg); + + return _("Unknown error"); +} diff --git a/libc/inet/get_hosts_byaddr_r.c b/libc/inet/get_hosts_byaddr_r.c new file mode 100644 index 0000000..c377aec --- /dev/null +++ b/libc/inet/get_hosts_byaddr_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_get_hosts_byaddr_r +#include "resolv.c" diff --git a/libc/inet/get_hosts_byname_r.c b/libc/inet/get_hosts_byname_r.c new file mode 100644 index 0000000..7ad1e3f --- /dev/null +++ b/libc/inet/get_hosts_byname_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_get_hosts_byname_r +#include "resolv.c" diff --git a/libc/inet/getaddrinfo.c b/libc/inet/getaddrinfo.c new file mode 100644 index 0000000..0fe3fdf --- /dev/null +++ b/libc/inet/getaddrinfo.c @@ -0,0 +1,893 @@ +/* + * Copyright 1996 by Craig Metz + * Copyright (C) 2000-2006 Erik Andersen + * Portions from the GNU C library, + * Copyright (C) 2003, 2006 Free Software Foundation, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* $USAGI: getaddrinfo.c,v 1.16 2001/10/04 09:52:03 sekiya Exp $ */ + +/* The Inner Net License, Version 2.00 + + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of the all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by , The Inner + Net, and other contributors. + +5. Neither the name(s) of the author(s) nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ITS AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + If these license terms cause you a real problem, contact the author. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* libc_hidden_proto(strcmp) */ +/* libc_hidden_proto(stpcpy) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(getservbyname_r) +libc_hidden_proto(gethostbyname2_r) +libc_hidden_proto(gethostbyaddr_r) +libc_hidden_proto(inet_pton) +libc_hidden_proto(inet_ntop) +libc_hidden_proto(strtoul) +libc_hidden_proto(if_nametoindex) +libc_hidden_proto(__h_errno_location) +/* libc_hidden_proto(uname) */ +#ifdef __UCLIBC_HAS_IPV6__ +libc_hidden_proto(in6addr_loopback) +#endif + +#define GAIH_OKIFUNSPEC 0x0100 +#define GAIH_EAI ~(GAIH_OKIFUNSPEC) + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +/* Useful for having small structure members/global variables */ +typedef int8_t socktype_t; +typedef int8_t family_t; +typedef int8_t protocol_t; +struct BUG_too_small { + char BUG_socktype_t_too_small[(0 + | SOCK_STREAM + | SOCK_DGRAM + | SOCK_RAW + ) <= 127 ? 1 : -1]; + char BUG_family_t_too_small[(0 + | AF_UNSPEC + | AF_INET + | AF_INET6 + ) <= 127 ? 1 : -1]; + char BUG_protocol_t_too_small[(0 + | IPPROTO_TCP + | IPPROTO_UDP + ) <= 127 ? 1 : -1]; +}; + +struct gaih_service { + const char *name; + int num; +}; + +struct gaih_servtuple { + struct gaih_servtuple *next; + int socktype; + int protocol; + int port; +}; + +struct gaih_addrtuple { + struct gaih_addrtuple *next; + int family; + char addr[16]; + uint32_t scopeid; +}; + +struct gaih_typeproto { + socktype_t socktype; + protocol_t protocol; + int8_t protoflag; + char name[4]; +}; +/* Values for `protoflag'. */ +#define GAI_PROTO_NOSERVICE 1 +#define GAI_PROTO_PROTOANY 2 + +static const struct gaih_typeproto gaih_inet_typeproto[] = { + { 0 , 0 , 0, "" }, + { SOCK_STREAM, IPPROTO_TCP, 0, "tcp" }, + { SOCK_DGRAM , IPPROTO_UDP, 0, "udp" }, + { SOCK_RAW , 0 , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" }, + { 0 , 0 , 0, "" }, +}; + +struct gaih { + int family; + int (*gaih)(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai); +}; + +#define SEEN_IPV4 1 +#define SEEN_IPV6 2 + +static unsigned __check_pf(void) +{ + unsigned seen = 0; +#if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__ + { + /* Get the interface list via getifaddrs. */ + struct ifaddrs *ifa = NULL; + struct ifaddrs *runp; + if (getifaddrs(&ifa) != 0) { + /* We cannot determine what interfaces are available. + * Be optimistic. */ +#if defined __UCLIBC_HAS_IPV4__ + seen |= SEEN_IPV4; +#endif /* __UCLIBC_HAS_IPV4__ */ +#if defined __UCLIBC_HAS_IPV6__ + seen |= SEEN_IPV6; +#endif /* __UCLIBC_HAS_IPV6__ */ + return seen; + } + + for (runp = ifa; runp != NULL; runp = runp->ifa_next) +#if defined __UCLIBC_HAS_IPV4__ + if (runp->ifa_addr->sa_family == PF_INET) + seen |= SEEN_IPV4; +#endif /* __UCLIBC_HAS_IPV4__ */ +#if defined __UCLIBC_HAS_IPV6__ + if (runp->ifa_addr->sa_family == PF_INET6) + seen |= SEEN_IPV6; +#endif /* __UCLIBC_HAS_IPV6__ */ + + freeifaddrs(ifa); + } +#else + /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */ +#if defined __UCLIBC_HAS_IPV4__ + seen |= SEEN_IPV4; +#endif /* __UCLIBC_HAS_IPV4__ */ +#if defined __UCLIBC_HAS_IPV6__ + seen |= SEEN_IPV6; +#endif /* __UCLIBC_HAS_IPV6__ */ + +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + return seen; +} + +static int addrconfig(sa_family_t af) +{ + int s; + int ret; + int saved_errno = errno; + unsigned seen; + + seen = __check_pf(); +#if defined __UCLIBC_HAS_IPV4__ + if (af == AF_INET) + ret = seen & SEEN_IPV4; + else +#endif +#if defined __UCLIBC_HAS_IPV6__ + if (af == AF_INET6) + ret = seen & SEEN_IPV6; + else +#endif + { + s = socket(af, SOCK_DGRAM, 0); + ret = 1; /* Assume PF_UNIX. */ + if (s < 0) { + if (errno != EMFILE) + ret = 0; + } else + close(s); + } + __set_errno(saved_errno); + return ret; +} + +#if 0 +/* Using Unix sockets this way is a security risk. */ +static int +gaih_local(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + struct utsname utsname; + struct addrinfo *ai = *pai; + + if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + + if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) + if (uname(&utsname) < 0) + return -EAI_SYSTEM; + + if (name != NULL) { + if (strcmp(name, "localhost") && + strcmp(name, "local") && + strcmp(name, "unix") && + strcmp(name, utsname.nodename)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + + if (req->ai_protocol || req->ai_socktype) { + const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; + + while (tp->name[0] + && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 + || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)) + ) { + ++tp; + } + if (! tp->name[0]) { + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } + + *pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + + ((req->ai_flags & AI_CANONNAME) + ? (strlen(utsname.nodename) + 1) : 0)); + if (ai == NULL) + return -EAI_MEMORY; + + ai->ai_next = NULL; + ai->ai_flags = req->ai_flags; + ai->ai_family = AF_LOCAL; + ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; + ai->ai_protocol = req->ai_protocol; + ai->ai_addrlen = sizeof(struct sockaddr_un); + ai->ai_addr = (void *)ai + sizeof(struct addrinfo); +#if SALEN + ((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ + + ((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL; + memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX); + + if (service) { + struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr; + + if (strchr(service->name, '/') != NULL) { + if (strlen(service->name) >= sizeof(sunp->sun_path)) + return GAIH_OKIFUNSPEC | -EAI_SERVICE; + + strcpy(sunp->sun_path, service->name); + } else { + if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path)) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name); + } + } else { + /* This is a dangerous use of the interface since there is a time + window between the test for the file and the actual creation + (done by the caller) in which a file with the same name could + be created. */ + char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path; + + if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0 + || __gen_tempname(buf, __GT_NOCREATE) != 0 + ) { + return -EAI_SYSTEM; + } + } + + ai->ai_canonname = NULL; + if (req->ai_flags & AI_CANONNAME) + ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un), + utsname.nodename); + return 0; +} +#endif /* 0 */ + +static int +gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp, + const struct addrinfo *req, struct gaih_servtuple *st) +{ + struct servent *s; + size_t tmpbuflen = 1024; + struct servent ts; + char *tmpbuf; + int r; + + while (1) { + tmpbuf = alloca(tmpbuflen); + r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s); + if (r == 0 && s != NULL) + break; + if (r != ERANGE) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + tmpbuflen *= 2; + } + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); + st->port = s->s_port; + return 0; +} + +/* NB: also uses h,pat,rc,no_data variables */ +#define gethosts(_family, _type) \ +{ \ + int i, herrno; \ + size_t tmpbuflen; \ + struct hostent th; \ + char *tmpbuf; \ + \ + tmpbuflen = 512; \ + no_data = 0; \ + do { \ + tmpbuflen *= 2; \ + tmpbuf = alloca(tmpbuflen); \ + rc = gethostbyname2_r(name, _family, &th, tmpbuf, \ + tmpbuflen, &h, &herrno); \ + } while (rc == ERANGE && herrno == NETDB_INTERNAL); \ + if (rc != 0) { \ + if (herrno == NETDB_INTERNAL) { \ + __set_h_errno(herrno); \ + return -EAI_SYSTEM; \ + } \ + if (herrno == TRY_AGAIN) \ + no_data = EAI_AGAIN; \ + else \ + no_data = (herrno == NO_DATA); \ + } else if (h != NULL) { \ + for (i = 0; h->h_addr_list[i]; i++) { \ + if (*pat == NULL) { \ + *pat = alloca(sizeof(struct gaih_addrtuple)); \ + (*pat)->scopeid = 0; \ + } \ + (*pat)->next = NULL; \ + (*pat)->family = _family; \ + memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type)); \ + pat = &((*pat)->next); \ + } \ + } \ +} + +static int +gaih_inet(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + struct gaih_servtuple nullserv; + + const struct gaih_typeproto *tp = gaih_inet_typeproto; + struct gaih_servtuple *st = &nullserv; + struct gaih_addrtuple *at = NULL; + int rc; + int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) + && (req->ai_flags & AI_V4MAPPED); + unsigned seen = __check_pf(); + + memset(&nullserv, 0, sizeof(nullserv)); + + if (req->ai_protocol || req->ai_socktype) { + ++tp; + while (tp->name[0] + && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol) + ) + ) { + ++tp; + } + if (! tp->name[0]) { + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } + + if (service != NULL) { + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + + if (service->num < 0) { + if (tp->name[0]) { + st = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, st); + if (rc) + return rc; + } else { + struct gaih_servtuple **pst = &st; + for (tp++; tp->name[0]; tp++) { + struct gaih_servtuple *newp; + + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + continue; + + if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + continue; + if (req->ai_protocol != 0 + && !(tp->protoflag & GAI_PROTO_PROTOANY) + && req->ai_protocol != tp->protocol) + continue; + + newp = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, newp); + if (rc) { + if (rc & GAIH_OKIFUNSPEC) + continue; + return rc; + } + + *pst = newp; + pst = &(newp->next); + } + if (st == &nullserv) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } else { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = htons(service->num); + } + } else if (req->ai_socktype || req->ai_protocol) { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = 0; + } else { + /* + * Neither socket type nor protocol is set. Return all socket types + * we know about. + */ + struct gaih_servtuple **lastp = &st; + for (++tp; tp->name[0]; ++tp) { + struct gaih_servtuple *newp; + + newp = alloca(sizeof(struct gaih_servtuple)); + newp->next = NULL; + newp->socktype = tp->socktype; + newp->protocol = tp->protocol; + newp->port = 0; + + *lastp = newp; + lastp = &newp->next; + } + } + + if (name != NULL) { + at = alloca(sizeof(struct gaih_addrtuple)); + at->family = AF_UNSPEC; + at->scopeid = 0; + at->next = NULL; + + if (inet_pton(AF_INET, name, at->addr) > 0) { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) + at->family = AF_INET; + else + return -EAI_FAMILY; + } + +#if defined __UCLIBC_HAS_IPV6__ + if (at->family == AF_UNSPEC) { + char *namebuf = strdupa(name); + char *scope_delim; + + scope_delim = strchr(namebuf, SCOPE_DELIMITER); + if (scope_delim != NULL) + *scope_delim = '\0'; + + if (inet_pton(AF_INET6, namebuf, at->addr) > 0) { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + at->family = AF_INET6; + else + return -EAI_FAMILY; + + if (scope_delim != NULL) { + int try_numericscope = 0; + if (IN6_IS_ADDR_LINKLOCAL(at->addr) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) { + at->scopeid = if_nametoindex(scope_delim + 1); + if (at->scopeid == 0) + try_numericscope = 1; + } else + try_numericscope = 1; + + if (try_numericscope != 0) { + char *end; + assert(sizeof(uint32_t) <= sizeof(unsigned long)); + at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10); + if (*end != '\0') + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + } + } + } +#endif + + if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) { + struct hostent *h; + struct gaih_addrtuple **pat = &at; + int no_data = 0; + int no_inet6_data; + + /* + * If we are looking for both IPv4 and IPv6 address we don't want + * the lookup functions to automatically promote IPv4 addresses to + * IPv6 addresses. + */ +#if defined __UCLIBC_HAS_IPV6__ + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) + gethosts(AF_INET6, struct in6_addr); +#endif + no_inet6_data = no_data; + + if (req->ai_family == AF_INET + || (!v4mapped && req->ai_family == AF_UNSPEC) + || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))) + ) { + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) + gethosts(AF_INET, struct in_addr); + } + + if (no_data != 0 && no_inet6_data != 0) { + /* If both requests timed out report this. */ + if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) + return -EAI_AGAIN; + /* + * We made requests but they turned out no data. + * The name is known, though. + */ + return (GAIH_OKIFUNSPEC | -EAI_AGAIN); + } + } + + if (at->family == AF_UNSPEC) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } else { + struct gaih_addrtuple *atr; + + atr = at = alloca(sizeof(struct gaih_addrtuple)); + memset(at, '\0', sizeof(struct gaih_addrtuple)); + if (req->ai_family == 0) { + at->next = alloca(sizeof(struct gaih_addrtuple)); + memset(at->next, '\0', sizeof(struct gaih_addrtuple)); + } +#if defined __UCLIBC_HAS_IPV6__ + if (req->ai_family == 0 || req->ai_family == AF_INET6) { + at->family = AF_INET6; + if ((req->ai_flags & AI_PASSIVE) == 0) + memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr)); + atr = at->next; + } +#endif + if (req->ai_family == 0 || req->ai_family == AF_INET) { + atr->family = AF_INET; + if ((req->ai_flags & AI_PASSIVE) == 0) + *(uint32_t*)atr->addr = htonl(INADDR_LOOPBACK); + } + } + + if (pai == NULL) + return 0; + + { + const char *c = NULL; + struct gaih_servtuple *st2; + struct gaih_addrtuple *at2 = at; + size_t socklen, namelen; + sa_family_t family; + + /* + * buffer is the size of an unformatted IPv6 address in + * printable format. + */ + char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + + while (at2 != NULL) { + if (req->ai_flags & AI_CANONNAME) { + struct hostent *h = NULL; + int herrno; + struct hostent th; + size_t tmpbuflen = 512; + char *tmpbuf; + + do { + tmpbuflen *= 2; + tmpbuf = alloca(tmpbuflen); + //if (tmpbuf == NULL) + // return -EAI_MEMORY; + rc = gethostbyaddr_r(at2->addr, + ((at2->family == AF_INET6) + ? sizeof(struct in6_addr) + : sizeof(struct in_addr)), + at2->family, + &th, tmpbuf, tmpbuflen, + &h, &herrno); + } while (rc == errno && herrno == NETDB_INTERNAL); + + if (rc != 0 && herrno == NETDB_INTERNAL) { + __set_h_errno(herrno); + return -EAI_SYSTEM; + } + + if (h == NULL) + c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); + else + c = h->h_name; + + if (c == NULL) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + + namelen = strlen(c) + 1; + } else + namelen = 0; + +#if defined __UCLIBC_HAS_IPV6__ + if (at2->family == AF_INET6 || v4mapped) { + family = AF_INET6; + socklen = sizeof(struct sockaddr_in6); + } +#endif +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ + else +#endif +#if defined __UCLIBC_HAS_IPV4__ + { + family = AF_INET; + socklen = sizeof(struct sockaddr_in); + } +#endif + for (st2 = st; st2 != NULL; st2 = st2->next) { + if (req->ai_flags & AI_ADDRCONFIG) { + if (family == AF_INET && !(seen & SEEN_IPV4)) + break; +#if defined __UCLIBC_HAS_IPV6__ + else if (family == AF_INET6 && !(seen & SEEN_IPV6)) + break; +#endif + } + *pai = malloc(sizeof(struct addrinfo) + socklen + namelen); + if (*pai == NULL) + return -EAI_MEMORY; + + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = family; + (*pai)->ai_socktype = st2->socktype; + (*pai)->ai_protocol = st2->protocol; + (*pai)->ai_addrlen = socklen; + (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); +#if SALEN + (*pai)->ai_addr->sa_len = socklen; +#endif /* SALEN */ + (*pai)->ai_addr->sa_family = family; + +#if defined __UCLIBC_HAS_IPV6__ + if (family == AF_INET6) { + struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; + + sin6p->sin6_flowinfo = 0; + if (at2->family == AF_INET6) { + memcpy(&sin6p->sin6_addr, + at2->addr, sizeof(struct in6_addr)); + } else { + sin6p->sin6_addr.s6_addr32[0] = 0; + sin6p->sin6_addr.s6_addr32[1] = 0; + sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); + memcpy(&sin6p->sin6_addr.s6_addr32[3], + at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3])); + } + sin6p->sin6_port = st2->port; + sin6p->sin6_scope_id = at2->scopeid; + } +#endif +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ + else +#endif +#if defined __UCLIBC_HAS_IPV4__ + { + struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; + + memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr)); + sinp->sin_port = st2->port; + memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero)); + } +#endif + if (c) { + (*pai)->ai_canonname = ((void *) (*pai) + + sizeof(struct addrinfo) + socklen); + strcpy((*pai)->ai_canonname, c); + } else { + (*pai)->ai_canonname = NULL; + } + (*pai)->ai_next = NULL; + pai = &((*pai)->ai_next); + } + + at2 = at2->next; + } + } + return 0; +} + +static const struct gaih gaih[] = { +#if defined __UCLIBC_HAS_IPV6__ + { PF_INET6, gaih_inet }, +#endif + { PF_INET, gaih_inet }, +#if 0 + { PF_LOCAL, gaih_local }, +#endif + { PF_UNSPEC, NULL } +}; + +libc_hidden_proto(freeaddrinfo) +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *p; + + while (ai != NULL) { + p = ai; + ai = ai->ai_next; + free(p); + } +} +libc_hidden_def(freeaddrinfo) + +libc_hidden_proto(getaddrinfo) +int +getaddrinfo(const char *name, const char *service, + const struct addrinfo *hints, struct addrinfo **pai) +{ + int i = 0, j, last_i = 0; + struct addrinfo *p = NULL, **end; + const struct gaih *g = gaih, *pg = NULL; + struct gaih_service gaih_service, *pservice; + struct addrinfo default_hints; + + if (name != NULL && name[0] == '*' && name[1] == 0) + name = NULL; + + if (service != NULL && service[0] == '*' && service[1] == 0) + service = NULL; + + if (name == NULL && service == NULL) + return EAI_NONAME; + + if (hints == NULL) { + memset(&default_hints, 0, sizeof(default_hints)); + if (AF_UNSPEC) + default_hints.ai_family = AF_UNSPEC; + hints = &default_hints; + } + + if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| + AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) + return EAI_BADFLAGS; + + if ((hints->ai_flags & AI_CANONNAME) && name == NULL) + return EAI_BADFLAGS; + + if (service && service[0]) { + char *c; + gaih_service.name = service; + gaih_service.num = strtoul(gaih_service.name, &c, 10); + if (*c != '\0') { + if (hints->ai_flags & AI_NUMERICSERV) + return EAI_NONAME; + gaih_service.num = -1; + } else { + /* + * Can't specify a numerical socket unless a protocol + * family was given. + */ + if (hints->ai_socktype == 0 && hints->ai_protocol == 0) + return EAI_SERVICE; + } + pservice = &gaih_service; + } else + pservice = NULL; + + end = NULL; + if (pai) + end = &p; + + j = 0; + while (g->gaih) { + if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) { + if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) { + ++g; + continue; + } + j++; + if (pg == NULL || pg->gaih != g->gaih) { + pg = g; + i = g->gaih(name, pservice, hints, end); + if (i != 0) { + last_i = i; + if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) + continue; + if (p) + freeaddrinfo(p); + return -(i & GAIH_EAI); + } + if (end) + while (*end) + end = &((*end)->ai_next); + } + } + ++g; + } + + if (j == 0) + return EAI_FAMILY; + + if (p) { + *pai = p; + return 0; + } + + if (pai == NULL && last_i == 0) + return 0; + + /* if (p) - never happens, see above */ + /* freeaddrinfo(p); */ + + return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME; +} +libc_hidden_def(getaddrinfo) diff --git a/libc/inet/gethostbyaddr.c b/libc/inet/gethostbyaddr.c new file mode 100644 index 0000000..ae8a543 --- /dev/null +++ b/libc/inet/gethostbyaddr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyaddr +#include "resolv.c" diff --git a/libc/inet/gethostbyaddr_r.c b/libc/inet/gethostbyaddr_r.c new file mode 100644 index 0000000..6235c82 --- /dev/null +++ b/libc/inet/gethostbyaddr_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyaddr_r +#include "resolv.c" diff --git a/libc/inet/gethostbyname.c b/libc/inet/gethostbyname.c new file mode 100644 index 0000000..3d46ab0 --- /dev/null +++ b/libc/inet/gethostbyname.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname +#include "resolv.c" diff --git a/libc/inet/gethostbyname2.c b/libc/inet/gethostbyname2.c new file mode 100644 index 0000000..6858016 --- /dev/null +++ b/libc/inet/gethostbyname2.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname2 +#include "resolv.c" diff --git a/libc/inet/gethostbyname2_r.c b/libc/inet/gethostbyname2_r.c new file mode 100644 index 0000000..06d058a --- /dev/null +++ b/libc/inet/gethostbyname2_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname2_r +#include "resolv.c" diff --git a/libc/inet/gethostbyname_r.c b/libc/inet/gethostbyname_r.c new file mode 100644 index 0000000..fc9e56d --- /dev/null +++ b/libc/inet/gethostbyname_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname_r +#include "resolv.c" diff --git a/libc/inet/gethostent.c b/libc/inet/gethostent.c new file mode 100644 index 0000000..16133c0 --- /dev/null +++ b/libc/inet/gethostent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostent +#include "resolv.c" diff --git a/libc/inet/getnameinfo.c b/libc/inet/getnameinfo.c new file mode 100644 index 0000000..fbfd3ed --- /dev/null +++ b/libc/inet/getnameinfo.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getnameinfo +#include "resolv.c" diff --git a/libc/inet/getnetbyad.c b/libc/inet/getnetbyad.c new file mode 100644 index 0000000..c916a18 --- /dev/null +++ b/libc/inet/getnetbyad.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __FORCE_GLIBC +#include +#include +#include + +libc_hidden_proto(setnetent) +libc_hidden_proto(getnetent) +libc_hidden_proto(endnetent) + +extern smallint _net_stayopen attribute_hidden; + +struct netent *getnetbyaddr (uint32_t net, int type) +{ + register struct netent *p; + + setnetent(_net_stayopen); + while ((p = getnetent())) + if (p->n_addrtype == type && p->n_net == net) + break; + if (!_net_stayopen) + endnetent(); + return (p); +} diff --git a/libc/inet/getnetbynm.c b/libc/inet/getnetbynm.c new file mode 100644 index 0000000..9f36551 --- /dev/null +++ b/libc/inet/getnetbynm.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +libc_hidden_proto(setnetent) +libc_hidden_proto(getnetent) +libc_hidden_proto(endnetent) + +extern smallint _net_stayopen attribute_hidden; + +struct netent * +getnetbyname(const char *name) +{ + register struct netent *p; + register char **cp; + + setnetent(_net_stayopen); + while ((p = getnetent())) { + if (strcmp(p->n_name, name) == 0) + break; + for (cp = p->n_aliases; *cp != 0; cp++) + if (strcmp(*cp, name) == 0) + goto found; + } +found: + if (!_net_stayopen) + endnetent(); + return (p); +} diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c new file mode 100644 index 0000000..863266d --- /dev/null +++ b/libc/inet/getnetent.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(inet_network) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets) +libc_hidden_proto(abort) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + + +#define MAXALIASES 35 +static const char NETDB[] = _PATH_NETWORKS; +static FILE *netf = NULL; +static char *line = NULL; +static struct netent net; +static char *net_aliases[MAXALIASES]; + +smallint _net_stayopen attribute_hidden; + +libc_hidden_proto(setnetent) +void setnetent(int f) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL) + netf = fopen(NETDB, "r" ); + else + rewind(netf); + if (f) _net_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); + return; +} +libc_hidden_def(setnetent) + +libc_hidden_proto(endnetent) +void endnetent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netf) { + fclose(netf); + netf = NULL; + } + _net_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endnetent) + +static char * any(register char *cp, char *match) +{ + register char *mp, c; + + while ((c = *cp)) { + for (mp = match; *mp; mp++) + if (*mp == c) + return (cp); + cp++; + } + return ((char *)0); +} + +libc_hidden_proto(getnetent) +struct netent *getnetent(void) +{ + char *p; + register char *cp, **q; + struct netent *rv = NULL; + + __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) { + goto DONE; + } +again: + + if (!line) { + line = malloc(BUFSIZ + 1); + if (!line) + abort(); + } + + p = fgets(line, BUFSIZ, netf); + if (p == NULL) { + goto DONE; + } + if (*p == '#') + goto again; + cp = any(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + net.n_name = p; + cp = any(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = any(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + net.n_net = inet_network(cp); + net.n_addrtype = AF_INET; + q = net.n_aliases = net_aliases; + if (p != NULL) + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &net_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = any(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + rv = &net; +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; +} +libc_hidden_def(getnetent) diff --git a/libc/inet/getpeername.c b/libc/inet/getpeername.c new file mode 100644 index 0000000..74825a7 --- /dev/null +++ b/libc/inet/getpeername.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpeername +#include "socketcalls.c" diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c new file mode 100644 index 0000000..a079f64 --- /dev/null +++ b/libc/inet/getproto.c @@ -0,0 +1,279 @@ +/* +** protocols.c /etc/protocols access functions +** +** This file is part of the NYS Library. +** +** The NYS Library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public License as +** published by the Free Software Foundation; either version 2 of the +** License, or (at your option) any later version. +** +** The NYS Library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with the NYS Library; see the file COPYING.LIB. If +** not, write to the Free Software Foundation, Inc., 675 Mass Ave, +** Cambridge, MA 02139, USA. +** +** +** Copyright (c) 1983 Regents of the University of California. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. All advertising materials mentioning features or use of this software +** must display the following acknowledgement: +** This product includes software developed by the University of +** California, Berkeley and its contributors. +** 4. Neither the name of the University nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(fopen) +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strpbrk) */ +libc_hidden_proto(atoi) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets) +libc_hidden_proto(fclose) +libc_hidden_proto(abort) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + + +#define MAXALIASES 35 +#define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) + +static FILE *protof = NULL; +static struct protoent proto; +static char *static_aliases = NULL; +static smallint proto_stayopen; + +static void __initbuf(void) +{ + if (!static_aliases) { + static_aliases = malloc(SBUFSIZE); + if (!static_aliases) + abort(); + } +} + +libc_hidden_proto(setprotoent) +void setprotoent(int f) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (protof == NULL) + protof = fopen(_PATH_PROTOCOLS, "r" ); + else + rewind(protof); + if (f) proto_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setprotoent) + +libc_hidden_proto(endprotoent) +void endprotoent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (protof) { + fclose(protof); + protof = NULL; + } + proto_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endprotoent) + +libc_hidden_proto(getprotoent_r) +int getprotoent_r(struct protoent *result_buf, + char *buf, size_t buflen, + struct protoent **result) +{ + char *p; + register char *cp, **q; + char **proto_aliases; + char *line; + int rv; + + *result = NULL; + + if (buflen < sizeof(*proto_aliases)*MAXALIASES) { + errno=ERANGE; + return errno; + } + __UCLIBC_MUTEX_LOCK(mylock); + proto_aliases=(char **)buf; + buf+=sizeof(*proto_aliases)*MAXALIASES; + buflen-=sizeof(*proto_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { + errno=rv=ERANGE; + goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) { + rv=errno; + goto DONE; + } +again: + if ((p = fgets(line, BUFSIZ, protof)) == NULL) { + rv=TRY_AGAIN; + goto DONE; + } + + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + result_buf->p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + result_buf->p_proto = atoi(cp); + q = result_buf->p_aliases = proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + *result=result_buf; + rv = 0; +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; +} +libc_hidden_def(getprotoent_r) + +struct protoent * getprotoent(void) +{ + struct protoent *result; + + __initbuf(); + getprotoent_r(&proto, static_aliases, SBUFSIZE, &result); + return result; +} + + +libc_hidden_proto(getprotobyname_r) +int getprotobyname_r(const char *name, + struct protoent *result_buf, + char *buf, size_t buflen, + struct protoent **result) +{ + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) { + if (strcmp(result_buf->p_name, name) == 0) + break; + for (cp = result_buf->p_aliases; *cp != 0; cp++) + if (strcmp(*cp, name) == 0) + goto found; + } +found: + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; +} +libc_hidden_def(getprotobyname_r) + + +struct protoent * getprotobyname(const char *name) +{ + struct protoent *result; + + __initbuf(); + getprotobyname_r(name, &proto, static_aliases, SBUFSIZE, &result); + return result; +} + + +libc_hidden_proto(getprotobynumber_r) +int getprotobynumber_r (int proto_num, + struct protoent *result_buf, + char *buf, size_t buflen, + struct protoent **result) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) + if (result_buf->p_proto == proto_num) + break; + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; +} +libc_hidden_def(getprotobynumber_r) + +struct protoent * getprotobynumber(int proto_num) +{ + struct protoent *result; + + __initbuf(); + getprotobynumber_r(proto_num, &proto, static_aliases, + SBUFSIZE, &result); + return result; +} + diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c new file mode 100644 index 0000000..bb1d6d2 --- /dev/null +++ b/libc/inet/getservice.c @@ -0,0 +1,285 @@ +/* +** services.c /etc/services access functions +** +** This file is part of the NYS Library. +** +** The NYS Library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public License as +** published by the Free Software Foundation; either version 2 of the +** License, or (at your option) any later version. +** +** The NYS Library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with the NYS Library; see the file COPYING.LIB. If +** not, write to the Free Software Foundation, Inc., 675 Mass Ave, +** Cambridge, MA 02139, USA. +** +** +** Copyright (c) 1983 Regents of the University of California. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. All advertising materials mentioning features or use of this software +** must display the following acknowledgement: +** This product includes software developed by the University of +** California, Berkeley and its contributors. +** 4. Neither the name of the University nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strpbrk) */ +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(atoi) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets) +libc_hidden_proto(abort) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + + + +#define MAXALIASES 35 +#define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) + +static FILE *servf = NULL; +static struct servent serv; +static char *servbuf = NULL; +static smallint serv_stayopen; + +static void __initbuf(void) +{ + if (!servbuf) { + servbuf = malloc(SBUFSIZE); + if (!servbuf) + abort(); + } +} + +libc_hidden_proto(setservent) +void setservent(int f) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (servf == NULL) + servf = fopen(_PATH_SERVICES, "r" ); + else + rewind(servf); + if (f) serv_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setservent) + +libc_hidden_proto(endservent) +void endservent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (servf) { + fclose(servf); + servf = NULL; + } + serv_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endservent) + +libc_hidden_proto(getservent_r) +int getservent_r(struct servent * result_buf, + char * buf, size_t buflen, + struct servent ** result) +{ + char *p; + register char *cp, **q; + char **serv_aliases; + char *line; + int rv; + + *result=NULL; + + if (buflen < sizeof(*serv_aliases)*MAXALIASES) { + errno=ERANGE; + return errno; + } + __UCLIBC_MUTEX_LOCK(mylock); + serv_aliases=(char **)buf; + buf+=sizeof(*serv_aliases)*MAXALIASES; + buflen-=sizeof(*serv_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { + errno=rv=ERANGE; + goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { + errno=rv=EIO; + goto DONE; + } +again: + if ((p = fgets(line, BUFSIZ, servf)) == NULL) { + errno=rv=EIO; + goto DONE; + } + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + result_buf->s_name = p; + p = strpbrk(p, " \t"); + if (p == NULL) + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + result_buf->s_port = htons((u_short)atoi(p)); + result_buf->s_proto = cp; + q = result_buf->s_aliases = serv_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &serv_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + *result=result_buf; + rv = 0; +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; +} +libc_hidden_def(getservent_r) + +struct servent * getservent(void) +{ + struct servent *result; + + __initbuf(); + getservent_r(&serv, servbuf, SBUFSIZE, &result); + return result; +} + +libc_hidden_proto(getservbyname_r) +int getservbyname_r(const char *name, const char *proto, + struct servent * result_buf, char * buf, size_t buflen, + struct servent ** result) +{ + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->s_name) == 0) + goto gotname; + for (cp = result_buf->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; +gotname: + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; +} +libc_hidden_def(getservbyname_r) + +struct servent *getservbyname(const char *name, const char *proto) +{ + struct servent *result; + + __initbuf(); + getservbyname_r(name, proto, &serv, servbuf, SBUFSIZE, &result); + return result; +} + + +libc_hidden_proto(getservbyport_r) +int getservbyport_r(int port, const char *proto, + struct servent * result_buf, char * buf, + size_t buflen, struct servent ** result) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { + if (result_buf->s_port != port) + continue; + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; +} +libc_hidden_def(getservbyport_r) + +libc_hidden_proto(getservbyport) +struct servent * getservbyport(int port, const char *proto) +{ + struct servent *result; + + __initbuf(); + getservbyport_r(port, proto, &serv, servbuf, SBUFSIZE, &result); + return result; +} +libc_hidden_def(getservbyport) diff --git a/libc/inet/getsockname.c b/libc/inet/getsockname.c new file mode 100644 index 0000000..4a4d6a1 --- /dev/null +++ b/libc/inet/getsockname.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getsockname +#include "socketcalls.c" diff --git a/libc/inet/getsockopt.c b/libc/inet/getsockopt.c new file mode 100644 index 0000000..48f72e9 --- /dev/null +++ b/libc/inet/getsockopt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getsockopt +#include "socketcalls.c" diff --git a/libc/inet/herror.c b/libc/inet/herror.c new file mode 100644 index 0000000..b465783 --- /dev/null +++ b/libc/inet/herror.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +libc_hidden_proto(fprintf) +libc_hidden_proto(__h_errno_location) + +static const char error_msg[] = "Resolver error"; +static const char *const h_errlist[] = { + "Error 0", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +static const int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; + +/* + * herror -- print the error indicated by the h_errno value. + */ +libc_hidden_proto(herror) +void herror(const char *s) +{ + static const char colon_space[] = ": "; + const char *p; + const char *c; + + c = colon_space; + if (!s || !*s) { + c += 2; + } + p = error_msg; + if ((h_errno >= 0) && (h_errno < h_nerr)) { + p = h_errlist[h_errno]; + } + fprintf(stderr, "%s%s%s\n", s, c, p); +} +libc_hidden_def(herror) + + +const char *hstrerror(int err) +{ + if ((unsigned)err < h_nerr) + return(h_errlist[err]); + + return error_msg; +} diff --git a/libc/inet/hostid.c b/libc/inet/hostid.c new file mode 100644 index 0000000..4972dce --- /dev/null +++ b/libc/inet/hostid.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(open) +libc_hidden_proto(close) +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(getuid) +libc_hidden_proto(geteuid) +libc_hidden_proto(gethostbyname_r) +libc_hidden_proto(gethostname) + +#define HOSTID "/etc/hostid" + +#ifdef __USE_BSD +int sethostid(long int new_id) +{ + int fd; + int ret; + + if (geteuid() || getuid()) return __set_errno(EPERM); + if ((fd=open(HOSTID,O_CREAT|O_WRONLY,0644))<0) return -1; + ret = write(fd,(void *)&new_id,sizeof(new_id)) == sizeof(new_id) + ? 0 : -1; + close (fd); + return ret; +} +#endif + +long int gethostid(void) +{ + char host[MAXHOSTNAMELEN + 1]; + int fd, id; + + /* If hostid was already set then we can return that value. + * It is not an error if we cannot read this file. It is not even an + * error if we cannot read all the bytes, we just carry on trying... + */ + if ((fd=open(HOSTID,O_RDONLY))>=0 && read(fd,(void *)&id,sizeof(id))) + { + close (fd); + return id; + } + if (fd >= 0) close (fd); + + /* Try some methods of returning a unique 32 bit id. Clearly IP + * numbers, if on the internet, will have a unique address. If they + * are not on the internet then we can return 0 which means they should + * really set this number via a sethostid() call. If their hostname + * returns the loopback number (i.e. if they have put their hostname + * in the /etc/hosts file with 127.0.0.1) then all such hosts will + * have a non-unique hostid, but it doesn't matter anyway and + * gethostid() will return a non zero number without the need for + * setting one anyway. + * Mitch + */ + if (gethostname(host,MAXHOSTNAMELEN)>=0 && *host) { + struct hostent *hp; + struct in_addr in; + struct hostent ghbn_h; + char ghbn_buf[sizeof(struct in_addr) + + sizeof(struct in_addr *)*2 + + sizeof(char *)*((2 + 5/*MAX_ALIASES*/ + + 1)/*ALIAS_DIM*/) + + 256/*namebuffer*/ + 32/* margin */]; + int ghbn_errno; + + /* replace gethostbyname() with gethostbyname_r() - ron@zing.net */ + /*if ((hp = gethostbyname(host)) == (struct hostent *)NULL)*/ + gethostbyname_r(host, &ghbn_h, ghbn_buf, sizeof(ghbn_buf), &hp, &ghbn_errno); + + if (hp == (struct hostent *)NULL) + + /* This is not a error if we get here, as all it means is that + * this host is not on a network and/or they have not + * configured their network properly. So we return the unset + * hostid which should be 0, meaning that they should set it !! + */ + return 0; + else { + memcpy((char *) &in, (char *) hp->h_addr, hp->h_length); + + /* Just so it doesn't look exactly like the IP addr */ + return(in.s_addr<<16|in.s_addr>>16); + } + } + else return 0; + +} diff --git a/libc/inet/if_index.c b/libc/inet/if_index.c new file mode 100644 index 0000000..36c6be4 --- /dev/null +++ b/libc/inet/if_index.c @@ -0,0 +1,346 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Reworked Dec 2002 by Erik Andersen + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netlinkaccess.h" + +/* Experimentally off - libc_hidden_proto(strncpy) */ +/* Experimentally off - libc_hidden_proto(strdup) */ +libc_hidden_proto(ioctl) +libc_hidden_proto(close) +#if __ASSUME_NETLINK_SUPPORT +/* Experimentally off - libc_hidden_proto(strndup) */ +#endif + +extern int __opensock(void) attribute_hidden; + +libc_hidden_proto(if_nametoindex) +unsigned int +if_nametoindex(const char* ifname) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return 0; +#else + struct ifreq ifr; + int fd = __opensock(); + + if (fd < 0) + return 0; + + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; + close(fd); + if (saved_errno == EINVAL) + __set_errno(ENOSYS); + return 0; + } + + close(fd); + return ifr.ifr_ifindex; +#endif +} +libc_hidden_def(if_nametoindex) + +libc_hidden_proto(if_freenameindex) +void +if_freenameindex (struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + free (ptr->if_name); + ++ptr; + } + free (ifn); +} +libc_hidden_def(if_freenameindex) + +libc_hidden_proto(if_nameindex) +#if !__ASSUME_NETLINK_SUPPORT +struct if_nameindex * +if_nameindex (void) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else + int fd = __opensock (); + struct ifconf ifc; + unsigned int nifs, i; + int rq_len; + struct if_nameindex *idx = NULL; +# define RQ_IFS 4 + + if (fd < 0) + return NULL; + + ifc.ifc_buf = NULL; + + /* Guess on the correct buffer size... */ + rq_len = RQ_IFS * sizeof (struct ifreq); + + /* Read all the interfaces out of the kernel. */ + /* Note: alloca's in this loop are diff from glibc because it's smaller */ + do + { + ifc.ifc_buf = extend_alloca (ifc.ifc_buf, rq_len, 2 * rq_len); + ifc.ifc_len = rq_len; + + if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) + { + close (fd); + return NULL; + } + } + while (ifc.ifc_len == rq_len); + + nifs = ifc.ifc_len / sizeof(struct ifreq); + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + close(fd); + __set_errno(ENOBUFS); + return NULL; + } + + for (i = 0; i < nifs; ++i) + { + struct ifreq *ifr = &ifc.ifc_req[i]; + idx[i].if_name = strdup (ifr->ifr_name); + if (idx[i].if_name == NULL + || ioctl (fd, SIOCGIFINDEX, ifr) < 0) + { + int saved_errno = errno; + unsigned int j; + + for (j = 0; j < i; ++j) + free (idx[j].if_name); + free(idx); + close(fd); + if (saved_errno == EINVAL) + saved_errno = ENOSYS; + else if (saved_errno == ENOMEM) + saved_errno = ENOBUFS; + __set_errno (saved_errno); + return NULL; + } + idx[i].if_index = ifr->ifr_ifindex; + } + + idx[i].if_index = 0; + idx[i].if_name = NULL; + + close(fd); + return idx; +#endif +} +#else +struct if_nameindex * +if_nameindex (void) +{ + unsigned int nifs = 0; + struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; + struct if_nameindex *idx = NULL; + struct netlink_res *nlp; + + if (__netlink_open (&nh) < 0) + return NULL; + + + /* Tell the kernel that we wish to get a list of all + active interfaces. Collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) + goto exit_free; + + /* Count the interfaces. */ + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + ++nifs; + } + } + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + nomem: + __set_errno (ENOBUFS); + goto exit_free; + } + + /* Add the interfaces. */ + nifs = 0; + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + idx[nifs].if_index = ifim->ifi_index; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + if (rta->rta_type == IFLA_IFNAME) + { + idx[nifs].if_name = strndup (rta_data, rta_payload); + if (idx[nifs].if_name == NULL) + { + idx[nifs].if_index = 0; + if_freenameindex (idx); + idx = NULL; + goto nomem; + } + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + + ++nifs; + } + } + } + + idx[nifs].if_index = 0; + idx[nifs].if_name = NULL; + + exit_free: + __netlink_free_handle (&nh); + __netlink_close (&nh); + + return idx; +} +#endif +libc_hidden_def(if_nameindex) + +char * +if_indextoname (unsigned int ifindex, char *ifname) +{ +#if !defined SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else +# ifdef SIOCGIFNAME + /* Use ioctl to avoid searching the list. */ + struct ifreq ifr; + int fd; + + fd = __opensock (); + + if (fd < 0) + return NULL; + + ifr.ifr_ifindex = ifindex; + if (ioctl (fd, SIOCGIFNAME, &ifr) < 0) + { + int serrno = errno; + close (fd); + if (serrno == ENODEV) + /* POSIX requires ENXIO. */ + serrno = ENXIO; + __set_errno (serrno); + return NULL; + } + close (fd); + + return strncpy (ifname, ifr.ifr_name, IFNAMSIZ); +# else + struct if_nameindex *idx; + struct if_nameindex *p; + char *result = NULL; + + idx = if_nameindex(); + + if (idx != NULL) + { + for (p = idx; p->if_index || p->if_name; ++p) + if (p->if_index == ifindex) + { + result = strncpy (ifname, p->if_name, IFNAMSIZ); + break; + } + + if_freenameindex (idx); + + if (result == NULL) + __set_errno (ENXIO); + } + return result; +# endif +#endif +} + diff --git a/libc/inet/ifaddrs.c b/libc/inet/ifaddrs.c new file mode 100644 index 0000000..775d311 --- /dev/null +++ b/libc/inet/ifaddrs.c @@ -0,0 +1,865 @@ +/* getifaddrs -- get names and addresses of all network interfaces + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netlinkaccess.h" + +libc_hidden_proto(socket) +libc_hidden_proto(close) +/* Experimentally off - libc_hidden_proto(time) */ +libc_hidden_proto(sendto) +libc_hidden_proto(recvmsg) +libc_hidden_proto(bind) +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(mempcpy) */ +libc_hidden_proto(getsockname) +libc_hidden_proto(fclose) +libc_hidden_proto(abort) + +#ifndef __libc_use_alloca +# define __libc_use_alloca(x) (x < __MAX_ALLOCA_CUTOFF) +#endif + + +#if __ASSUME_NETLINK_SUPPORT +#ifdef __UCLIBC_SUPPORT_AI_ADDRCONFIG__ +/* struct to hold the data for one ifaddrs entry, so we can allocate + everything at once. */ +struct ifaddrs_storage +{ + struct ifaddrs ifa; + union + { + /* Save space for the biggest of the four used sockaddr types and + avoid a lot of casts. */ + struct sockaddr sa; + struct sockaddr_ll sl; + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } addr, netmask, broadaddr; + char name[IF_NAMESIZE + 1]; +}; +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + + +void +__netlink_free_handle (struct netlink_handle *h) +{ + struct netlink_res *ptr; + int saved_errno = errno; + + ptr = h->nlm_list; + while (ptr != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = ptr->next; + free (ptr); + ptr = tmpptr; + } + + __set_errno (saved_errno); +} + + +static int +__netlink_sendreq (struct netlink_handle *h, int type) +{ + struct + { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + struct sockaddr_nl nladdr; + + if (h->seq == 0) + h->seq = time (NULL); + + req.nlh.nlmsg_len = sizeof (req); + req.nlh.nlmsg_type = type; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = h->seq; + req.g.rtgen_family = AF_UNSPEC; + + memset (&nladdr, '\0', sizeof (nladdr)); + nladdr.nl_family = AF_NETLINK; + + return TEMP_FAILURE_RETRY (sendto (h->fd, (void *) &req, sizeof (req), 0, + (struct sockaddr *) &nladdr, + sizeof (nladdr))); +} + + +int +__netlink_request (struct netlink_handle *h, int type) +{ + struct netlink_res *nlm_next; + struct netlink_res **new_nlm_list; + static volatile size_t buf_size = 4096; + char *buf; + struct sockaddr_nl nladdr; + struct nlmsghdr *nlmh; + ssize_t read_len; + bool done = false; + bool use_malloc = false; + + if (__netlink_sendreq (h, type) < 0) + return -1; + + size_t this_buf_size = buf_size; + if (__libc_use_alloca (this_buf_size)) + buf = alloca (this_buf_size); + else + { + buf = malloc (this_buf_size); + if (buf != NULL) + use_malloc = true; + else + goto out_fail; + } + + struct iovec iov = { buf, this_buf_size }; + + if (h->nlm_list != NULL) + new_nlm_list = &h->end_ptr->next; + else + new_nlm_list = &h->nlm_list; + + while (! done) + { + struct msghdr msg = + { + (void *) &nladdr, sizeof (nladdr), + &iov, 1, + NULL, 0, + 0 + }; + + read_len = TEMP_FAILURE_RETRY (recvmsg (h->fd, &msg, 0)); + if (read_len < 0) + goto out_fail; + + if (nladdr.nl_pid != 0) + continue; + + if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0)) + { + if (this_buf_size >= SIZE_MAX / 2) + goto out_fail; + + nlm_next = *new_nlm_list; + while (nlm_next != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = nlm_next->next; + free (nlm_next); + nlm_next = tmpptr; + } + *new_nlm_list = NULL; + + if (__libc_use_alloca (2 * this_buf_size)) + buf = extend_alloca (buf, this_buf_size, 2 * this_buf_size); + else + { + this_buf_size *= 2; + + char *new_buf = realloc (use_malloc ? buf : NULL, this_buf_size); + if (new_buf == NULL) + goto out_fail; + new_buf = buf; + + use_malloc = true; + } + buf_size = this_buf_size; + + iov.iov_base = buf; + iov.iov_len = this_buf_size; + + /* Increase sequence number, so that we can distinguish + between old and new request messages. */ + h->seq++; + + if (__netlink_sendreq (h, type) < 0) + goto out_fail; + + continue; + } + + size_t count = 0; + size_t remaining_len = read_len; + for (nlmh = (struct nlmsghdr *) buf; + NLMSG_OK (nlmh, remaining_len); + nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len)) + { + if ((pid_t) nlmh->nlmsg_pid != h->pid + || nlmh->nlmsg_seq != h->seq) + continue; + + ++count; + if (nlmh->nlmsg_type == NLMSG_DONE) + { + /* We found the end, leave the loop. */ + done = true; + break; + } + if (nlmh->nlmsg_type == NLMSG_ERROR) + { + struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh); + if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) + errno = EIO; + else + errno = -nlerr->error; + goto out_fail; + } + } + + /* If there was nothing with the expected nlmsg_pid and nlmsg_seq, + there is no point to record it. */ + if (count == 0) + continue; + + nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) + + read_len); + if (nlm_next == NULL) + goto out_fail; + nlm_next->next = NULL; + nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); + nlm_next->size = read_len; + nlm_next->seq = h->seq; + if (h->nlm_list == NULL) + h->nlm_list = nlm_next; + else + h->end_ptr->next = nlm_next; + h->end_ptr = nlm_next; + } + + if (use_malloc) + free (buf); + return 0; + +out_fail: + if (use_malloc) + free (buf); + return -1; +} + + +void +__netlink_close (struct netlink_handle *h) +{ + /* Don't modify errno. */ + int serrno = errno; + close(h->fd); + __set_errno(serrno); +} + + +/* Open a NETLINK socket. */ +int +__netlink_open (struct netlink_handle *h) +{ + struct sockaddr_nl nladdr; + + h->fd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (h->fd < 0) + goto out; + + memset (&nladdr, '\0', sizeof (nladdr)); + nladdr.nl_family = AF_NETLINK; + if (bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0) + { + close_and_out: + __netlink_close (h); + out: + return -1; + } + /* Determine the ID the kernel assigned for this netlink connection. + It is not necessarily the PID if there is more than one socket + open. */ + socklen_t addr_len = sizeof (nladdr); + if (getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0) + goto close_and_out; + h->pid = nladdr.nl_pid; + return 0; +} + + +#ifdef __UCLIBC_SUPPORT_AI_ADDRCONFIG__ +/* We know the number of RTM_NEWLINK entries, so we reserve the first + # of entries for this type. All RTM_NEWADDR entries have an index + pointer to the RTM_NEWLINK entry. To find the entry, create + a table to map kernel index entries to our index numbers. + Since we get at first all RTM_NEWLINK entries, it can never happen + that a RTM_NEWADDR index is not known to this map. */ +static int +internal_function +map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max) +{ + int i; + + for (i = 0; i < max; i++) + { + if (map[i] == -1) + { + map[i] = index; + if (i > 0) + ifas[i - 1].ifa.ifa_next = &ifas[i].ifa; + return i; + } + else if (map[i] == index) + return i; + } + /* This should never be reached. If this will be reached, we have + a very big problem. */ + abort (); +} + + +/* Create a linked list of `struct ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. */ +int +getifaddrs (struct ifaddrs **ifap) +{ + struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; + struct netlink_res *nlp; + struct ifaddrs_storage *ifas; + unsigned int i, newlink, newaddr, newaddr_idx; + int *map_newlink_data; + size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */ + char *ifa_data_ptr; /* Pointer to the unused part of memory for + ifa_data. */ + int result = 0; + + if (ifap) + *ifap = NULL; + + if (__netlink_open (&nh) < 0) + { + return -1; + } + + /* Tell the kernel that we wish to get a list of all + active interfaces, collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) + { + result = -1; + goto exit_free; + } + + /* Now ask the kernel for all addresses which are assigned + to an interface and collect all data for every interface. + Since we store the addresses after the interfaces in the + list, we will later always find the interface before the + corresponding addresses. */ + ++nh.seq; + if (__netlink_request (&nh, RTM_GETADDR) < 0) + { + result = -1; + goto exit_free; + } + + /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate + enough memory. */ + newlink = newaddr = 0; + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + /* A RTM_NEWLINK message can have IFLA_STATS data. We need to + know the size before creating the list to allocate enough + memory. */ + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + while (RTA_OK (rta, rtasize)) + { + size_t rta_payload = RTA_PAYLOAD (rta); + + if (rta->rta_type == IFLA_STATS) + { + ifa_data_size += rta_payload; + break; + } + else + rta = RTA_NEXT (rta, rtasize); + } + ++newlink; + } + else if (nlh->nlmsg_type == RTM_NEWADDR) + ++newaddr; + } + } + + /* Return if no interface is up. */ + if ((newlink + newaddr) == 0) + goto exit_free; + + /* Allocate memory for all entries we have and initialize next + pointer. */ + ifas = (struct ifaddrs_storage *) calloc (1, + (newlink + newaddr) + * sizeof (struct ifaddrs_storage) + + ifa_data_size); + if (ifas == NULL) + { + result = -1; + goto exit_free; + } + + /* Table for mapping kernel index to entry in our list. */ + map_newlink_data = alloca (newlink * sizeof (int)); + memset (map_newlink_data, '\xff', newlink * sizeof (int)); + + ifa_data_ptr = (char *) &ifas[newlink + newaddr]; + newaddr_idx = 0; /* Counter for newaddr index. */ + + /* Walk through the list of data we got from the kernel. */ + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through one message and look at the type: If it is our + message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach + the end or we find the end marker (in this case we ignore the + following data. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + int ifa_index = 0; + + /* Check if the message is the one we want */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + /* We found a new interface. Now extract everything from the + interface data we got and need. */ + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + /* Interfaces are stored in the first "newlink" entries + of our list, starting in the order as we got from the + kernel. */ + ifa_index = map_newlink (ifim->ifi_index - 1, ifas, + map_newlink_data, newlink); + ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + switch (rta->rta_type) + { + case IFLA_ADDRESS: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + { + ifas[ifa_index].addr.sl.sll_family = AF_PACKET; + memcpy (ifas[ifa_index].addr.sl.sll_addr, + (char *) rta_data, rta_payload); + ifas[ifa_index].addr.sl.sll_halen = rta_payload; + ifas[ifa_index].addr.sl.sll_ifindex + = ifim->ifi_index; + ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type; + + ifas[ifa_index].ifa.ifa_addr + = &ifas[ifa_index].addr.sa; + } + break; + + case IFLA_BROADCAST: + if (rta_payload <= sizeof (ifas[ifa_index].broadaddr)) + { + ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET; + memcpy (ifas[ifa_index].broadaddr.sl.sll_addr, + (char *) rta_data, rta_payload); + ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload; + ifas[ifa_index].broadaddr.sl.sll_ifindex + = ifim->ifi_index; + ifas[ifa_index].broadaddr.sl.sll_hatype + = ifim->ifi_type; + + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + } + break; + + case IFLA_IFNAME: /* Name of Interface */ + if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name)) + { + ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name; + *(char *) mempcpy (ifas[ifa_index].name, rta_data, + rta_payload) = '\0'; + } + break; + + case IFLA_STATS: /* Statistics of Interface */ + ifas[ifa_index].ifa.ifa_data = ifa_data_ptr; + ifa_data_ptr += rta_payload; + memcpy (ifas[ifa_index].ifa.ifa_data, rta_data, + rta_payload); + break; + + case IFLA_UNSPEC: + break; + case IFLA_MTU: + break; + case IFLA_LINK: + break; + case IFLA_QDISC: + break; + default: + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + } + else if (nlh->nlmsg_type == RTM_NEWADDR) + { + struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFA_RTA (ifam); + size_t rtasize = IFA_PAYLOAD (nlh); + + /* New Addresses are stored in the order we got them from + the kernel after the interfaces. Theoretically it is possible + that we have holes in the interface part of the list, + but we always have already the interface for this address. */ + ifa_index = newlink + newaddr_idx; + ifas[ifa_index].ifa.ifa_flags + = ifas[map_newlink (ifam->ifa_index - 1, ifas, + map_newlink_data, newlink)].ifa.ifa_flags; + if (ifa_index > 0) + ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa; + ++newaddr_idx; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + switch (rta->rta_type) + { + case IFA_ADDRESS: + { + struct sockaddr *sa; + + if (ifas[ifa_index].ifa.ifa_addr != NULL) + { + /* In a point-to-poing network IFA_ADDRESS + contains the destination address, local + address is supplied in IFA_LOCAL attribute. + destination address and broadcast address + are stored in an union, so it doesn't matter + which name we use. */ + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + sa = &ifas[ifa_index].broadaddr.sa; + } + else + { + ifas[ifa_index].ifa.ifa_addr + = &ifas[ifa_index].addr.sa; + sa = &ifas[ifa_index].addr.sa; + } + + sa->sa_family = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&((struct sockaddr_in *) sa)->sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ((struct sockaddr_in6 *) sa)->sin6_scope_id + = ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (sa->sa_data, rta_data, rta_payload); + break; + } + } + break; + + case IFA_LOCAL: + if (ifas[ifa_index].ifa.ifa_addr != NULL) + { + /* If ifa_addr is set and we get IFA_LOCAL, + assume we have a point-to-point network. + Move address to correct field. */ + ifas[ifa_index].broadaddr = ifas[ifa_index].addr; + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + memset (&ifas[ifa_index].addr, '\0', + sizeof (ifas[ifa_index].addr)); + } + + ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa; + ifas[ifa_index].ifa.ifa_addr->sa_family + = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&ifas[ifa_index].addr.s4.sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&ifas[ifa_index].addr.s6.sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ifas[ifa_index].addr.s6.sin6_scope_id = + ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (ifas[ifa_index].addr.sa.sa_data, + rta_data, rta_payload); + break; + } + break; + + case IFA_BROADCAST: + /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */ + if (ifas[ifa_index].ifa.ifa_broadaddr != NULL) + memset (&ifas[ifa_index].broadaddr, '\0', + sizeof (ifas[ifa_index].broadaddr)); + + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + ifas[ifa_index].ifa.ifa_broadaddr->sa_family + = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ifas[ifa_index].broadaddr.s6.sin6_scope_id + = ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (&ifas[ifa_index].broadaddr.sa.sa_data, + rta_data, rta_payload); + break; + } + break; + + case IFA_LABEL: + if (rta_payload + 1 <= sizeof (ifas[ifa_index].name)) + { + ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name; + *(char *) mempcpy (ifas[ifa_index].name, rta_data, + rta_payload) = '\0'; + } + else + abort (); + break; + + case IFA_UNSPEC: + break; + case IFA_CACHEINFO: + break; + default: + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + + /* If we didn't get the interface name with the + address, use the name from the interface entry. */ + if (ifas[ifa_index].ifa.ifa_name == NULL) + ifas[ifa_index].ifa.ifa_name + = ifas[map_newlink (ifam->ifa_index - 1, ifas, + map_newlink_data, newlink)].ifa.ifa_name; + + /* Calculate the netmask. */ + if (ifas[ifa_index].ifa.ifa_addr + && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC + && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET) + { + uint32_t max_prefixlen = 0; + char *cp = NULL; + + ifas[ifa_index].ifa.ifa_netmask + = &ifas[ifa_index].netmask.sa; + + switch (ifas[ifa_index].ifa.ifa_addr->sa_family) + { + case AF_INET: + cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr; + max_prefixlen = 32; + break; + + case AF_INET6: + cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr; + max_prefixlen = 128; + break; + } + + ifas[ifa_index].ifa.ifa_netmask->sa_family + = ifas[ifa_index].ifa.ifa_addr->sa_family; + + if (cp != NULL) + { + char c; + unsigned int preflen; + + if ((max_prefixlen > 0) && + (ifam->ifa_prefixlen > max_prefixlen)) + preflen = max_prefixlen; + else + preflen = ifam->ifa_prefixlen; + + for (i = 0; i < (preflen / 8); i++) + *cp++ = 0xff; + c = 0xff; + c <<= (8 - (preflen % 8)); + *cp = c; + } + } + } + } + } + + assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size); + + if (newaddr_idx > 0) + { + for (i = 0; i < newlink; ++i) + if (map_newlink_data[i] == -1) + { + /* We have fewer links then we anticipated. Adjust the + forward pointer to the first address entry. */ + ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa; + } + + if (i == 0 && newlink > 0) + /* No valid link, but we allocated memory. We have to + populate the first entry. */ + memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage)); + } + + if (ifap != NULL) + *ifap = &ifas[0].ifa; + + exit_free: + __netlink_free_handle (&nh); + __netlink_close (&nh); + + return result; +} + + +void +freeifaddrs (struct ifaddrs *ifa) +{ + free (ifa); +} + +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + +#endif /* __ASSUME_NETLINK_SUPPORT */ diff --git a/libc/inet/in6_addr.c b/libc/inet/in6_addr.c new file mode 100644 index 0000000..c2ab375 --- /dev/null +++ b/libc/inet/in6_addr.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include + +#ifdef __UCLIBC_HAS_IPV6__ +const struct in6_addr in6addr_any = +{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; +libc_hidden_proto(in6addr_loopback) +const struct in6_addr in6addr_loopback = +{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; +libc_hidden_data_def(in6addr_loopback) +#endif /* __UCLIBC_HAS_IPV6__ */ + + diff --git a/libc/inet/inet_addr.c b/libc/inet/inet_addr.c new file mode 100644 index 0000000..445f850 --- /dev/null +++ b/libc/inet/inet_addr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_makeaddr +#include "addr.c" diff --git a/libc/inet/inet_aton.c b/libc/inet/inet_aton.c new file mode 100644 index 0000000..d79ba07 --- /dev/null +++ b/libc/inet/inet_aton.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_aton +#include "addr.c" diff --git a/libc/inet/inet_lnaof.c b/libc/inet/inet_lnaof.c new file mode 100644 index 0000000..9887a43 --- /dev/null +++ b/libc/inet/inet_lnaof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_lnaof +#include "addr.c" diff --git a/libc/inet/inet_makeaddr.c b/libc/inet/inet_makeaddr.c new file mode 100644 index 0000000..9f94696 --- /dev/null +++ b/libc/inet/inet_makeaddr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_addr +#include "addr.c" diff --git a/libc/inet/inet_net.c b/libc/inet/inet_net.c new file mode 100644 index 0000000..e46c9a5 --- /dev/null +++ b/libc/inet/inet_net.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +libc_hidden_proto(inet_network) +in_addr_t +inet_network(const char *cp) +{ + u_char c; + int got_data; + u_int base, dots; + in_addr_t res, val; + + res = 0; + dots = 0; + again: + val = 0; + got_data = 0; + if (*cp == '0') { + cp++; + if (*cp == 'x' || *cp == 'X') { + cp++; + base = 16; + } else { + base = 8; + got_data = 1; + } + } else + base = 10; + while ((c = *cp) != '\0') { + if (isdigit(c)) { + if (base == 8 && c > '7') + return (INADDR_NONE); + val = val * base + c - '0'; + } else if (base == 16 && isxdigit(c)) + val = (val << 4) + 10 - (islower(c) ? 'a' : 'A'); + else + break; + if (val > 0xff) + return (INADDR_NONE); + cp++; + got_data = 1; + } + if (!got_data) + return (INADDR_NONE); + if (dots != 0) + res <<= 8; + res |= val; + if (c == '.') { + if (++dots == 4) + return (INADDR_NONE); + cp++; + goto again; + } + if (c != '\0') + return (INADDR_NONE); + return (res); +} +libc_hidden_def(inet_network) diff --git a/libc/inet/inet_netof.c b/libc/inet/inet_netof.c new file mode 100644 index 0000000..045c120 --- /dev/null +++ b/libc/inet/inet_netof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_netof +#include "addr.c" diff --git a/libc/inet/inet_ntoa.c b/libc/inet/inet_ntoa.c new file mode 100644 index 0000000..83ed138 --- /dev/null +++ b/libc/inet/inet_ntoa.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_ntoa +#include "addr.c" diff --git a/libc/inet/lengthd.c b/libc/inet/lengthd.c new file mode 100644 index 0000000..07c7fc6 --- /dev/null +++ b/libc/inet/lengthd.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lengthd +#include "resolv.c" diff --git a/libc/inet/lengthq.c b/libc/inet/lengthq.c new file mode 100644 index 0000000..e62e6f2 --- /dev/null +++ b/libc/inet/lengthq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lengthq +#include "resolv.c" diff --git a/libc/inet/listen.c b/libc/inet/listen.c new file mode 100644 index 0000000..32e3478 --- /dev/null +++ b/libc/inet/listen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_listen +#include "socketcalls.c" diff --git a/libc/inet/netlinkaccess.h b/libc/inet/netlinkaccess.h new file mode 100644 index 0000000..5111d38 --- /dev/null +++ b/libc/inet/netlinkaccess.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETLINKACCESS_H +#define _NETLINKACCESS_H 1 + +#include +#include +#include +#include + +#if defined __ASSUME_NETLINK_SUPPORT || defined __UCLIBC_USE_NETLINK__ +#define _LINUX_TYPES_H +typedef uint8_t __u8; +typedef uint16_t __u16; +typedef uint32_t __u32; +typedef uint64_t __u64; +typedef int32_t __s32; +#include +#include + +struct netlink_res +{ + struct netlink_res *next; + struct nlmsghdr *nlh; + size_t size; /* Size of response. */ + uint32_t seq; /* sequential number we used. */ +}; + + +struct netlink_handle +{ + int fd; /* Netlink file descriptor. */ + pid_t pid; /* Process ID. */ + uint32_t seq; /* The sequence number we use currently. */ + struct netlink_res *nlm_list; /* Pointer to list of responses. */ + struct netlink_res *end_ptr; /* For faster append of new entries. */ +}; + + +#ifndef __ASSUME_NETLINK_SUPPORT +#define __ASSUME_NETLINK_SUPPORT 1 +#endif + +extern int __netlink_open (struct netlink_handle *h) attribute_hidden; +extern void __netlink_close (struct netlink_handle *h) attribute_hidden; +extern void __netlink_free_handle (struct netlink_handle *h) attribute_hidden; +extern int __netlink_request (struct netlink_handle *h, int type) attribute_hidden; + +#else +#define __ASSUME_NETLINK_SUPPORT 0 +#endif + +#endif /* _NETLINKACCESS_H */ diff --git a/libc/inet/ns_name.c b/libc/inet/ns_name.c new file mode 100644 index 0000000..158a1a3 --- /dev/null +++ b/libc/inet/ns_name.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ns_name +#include "resolv.c" diff --git a/libc/inet/ntohl.c b/libc/inet/ntohl.c new file mode 100644 index 0000000..dfadf80 --- /dev/null +++ b/libc/inet/ntohl.c @@ -0,0 +1,60 @@ +/* vi: set sw=4 ts=4: + * Functions to convert between host and network byte order. + * + * Copyright (C) 2003-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +uint32_t ntohl (uint32_t x); +uint16_t ntohs (uint16_t x); +uint32_t htonl (uint32_t x); +uint16_t htons (uint16_t x); + +#if __BYTE_ORDER == __BIG_ENDIAN +uint32_t ntohl (uint32_t x) +{ + return x; +} + +uint16_t ntohs (uint16_t x) +{ + return x; +} + +uint32_t htonl (uint32_t x) +{ + return x; +} + +uint16_t htons (uint16_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +uint32_t ntohl (uint32_t x) +{ + return __bswap_32(x); +} + +uint16_t ntohs (uint16_t x) +{ + return __bswap_16(x); +} + +uint32_t htonl (uint32_t x) +{ + return __bswap_32(x); +} + +uint16_t htons (uint16_t x) +{ + return __bswap_16(x); +} +#else +#error "You seem to have an unsupported byteorder" +#endif diff --git a/libc/inet/ntop.c b/libc/inet/ntop.c new file mode 100644 index 0000000..f19556d --- /dev/null +++ b/libc/inet/ntop.c @@ -0,0 +1,409 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(sprintf) +libc_hidden_proto(tolower) + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const u_char *src, char *dst, size_t size) +{ + char tmp[sizeof ("255.255.255.255") + 1] = "\0"; + int octet; + int i; + + i = 0; + for (octet = 0; octet <= 3; octet++) { + +#if 0 /* since src is unsigned char, it will never be > 255 ... */ + if (src[octet] > 255) { + __set_errno (ENOSPC); + return (NULL); + } +#endif + tmp[i++] = '0' + src[octet] / 100; + if (tmp[i - 1] == '0') { + tmp[i - 1] = '0' + (src[octet] / 10 % 10); + if (tmp[i - 1] == '0') i--; + } else { + tmp[i++] = '0' + (src[octet] / 10 % 10); + } + tmp[i++] = '0' + src[octet] % 10; + tmp[i++] = '.'; + } + tmp[i - 1] = '\0'; + + if (strlen (tmp) > size) { + __set_errno (ENOSPC); + return (NULL); + } + + return strcpy(dst, tmp); +} + + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ + +#ifdef __UCLIBC_HAS_IPV6__ + +static const char * +inet_ntop6(const u_char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp; + struct { int base, len; } best, cur; + u_int words[8]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < 16; i += 2) + words[i / 2] = (src[i] << 8) | src[i + 1]; + best.base = -1; + cur.base = -1; + best.len = best.len; /* shutting up compiler warning */ + cur.len = cur.len; /* shutting up compiler warning */ + for (i = 0; i < 8; i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < 8; i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == 8) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + __set_errno (ENOSPC); + return (NULL); + } + return strcpy(dst, tmp); +} +#endif /* __UCLIBC_HAS_IPV6__ */ + + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, u_char *dst) +{ + int saw_digit, octets, ch; + u_char tmp[4], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + + if (ch >= '0' && ch <= '9') { + u_int new = *tp * 10 + (ch - '0'); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, 4); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ + +#ifdef __UCLIBC_HAS_IPV6__ + +/* We cannot use the macro version of tolower() or very bad + * things happen when '*src++' gets evaluated multiple times. + * So undef it here so we get the function version of tolower + * instead. + */ +#undef tolower + +static int +inet_pton6(const char *src, u_char *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + u_char tmp[16], *tp, *endp, *colonp; + const char *curtok; + int ch, saw_xdigit; + u_int val; + + + tp = memset(tmp, '\0', 16); + endp = tp + 16; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = tolower (*src++)) != '\0') { + const char *pch; + + pch = strchr(xdigits, ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + 2 > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + 4) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += 4; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + 2 > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, 16); + return (1); +} + +#endif /* __UCLIBC_HAS_IPV6__ */ + + + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +libc_hidden_proto(inet_ntop) +const char * +inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + __set_errno (EAFNOSUPPORT); + return (NULL); + } + /* NOTREACHED */ +} +libc_hidden_def(inet_ntop) + + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +libc_hidden_proto(inet_pton) +int +inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + __set_errno (EAFNOSUPPORT); + return (-1); + } + /* NOTREACHED */ +} +libc_hidden_def(inet_pton) diff --git a/libc/inet/opennameservers.c b/libc/inet/opennameservers.c new file mode 100644 index 0000000..effd108 --- /dev/null +++ b/libc/inet/opennameservers.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_opennameservers +#include "resolv.c" diff --git a/libc/inet/opensock.c b/libc/inet/opensock.c new file mode 100644 index 0000000..a2c09dc --- /dev/null +++ b/libc/inet/opensock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(socket) + +/* Return a socket of any type. The socket can be used in subsequent + ioctl calls to talk to the kernel. */ +int __opensock(void) attribute_hidden; +int +__opensock (void) +{ + int fd; +#ifdef __UCLIBC_HAS_IPV6__ + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd<0) +#endif /* __UCLIBC_HAS_IPV6__ */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + return(fd); +} diff --git a/libc/inet/read_etc_hosts_r.c b/libc/inet/read_etc_hosts_r.c new file mode 100644 index 0000000..6504e54 --- /dev/null +++ b/libc/inet/read_etc_hosts_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_read_etc_hosts_r +#include "resolv.c" diff --git a/libc/inet/recv.c b/libc/inet/recv.c new file mode 100644 index 0000000..1c77ce3 --- /dev/null +++ b/libc/inet/recv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recv +#include "socketcalls.c" diff --git a/libc/inet/recvfrom.c b/libc/inet/recvfrom.c new file mode 100644 index 0000000..ec683f6 --- /dev/null +++ b/libc/inet/recvfrom.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recvfrom +#include "socketcalls.c" diff --git a/libc/inet/recvmsg.c b/libc/inet/recvmsg.c new file mode 100644 index 0000000..db51d8b --- /dev/null +++ b/libc/inet/recvmsg.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recvmsg +#include "socketcalls.c" diff --git a/libc/inet/res_comp.c b/libc/inet/res_comp.c new file mode 100644 index 0000000..8aee6b1 --- /dev/null +++ b/libc/inet/res_comp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_comp +#include "resolv.c" diff --git a/libc/inet/res_init.c b/libc/inet/res_init.c new file mode 100644 index 0000000..09caf49 --- /dev/null +++ b/libc/inet/res_init.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_init +#include "resolv.c" diff --git a/libc/inet/res_query.c b/libc/inet/res_query.c new file mode 100644 index 0000000..c662510 --- /dev/null +++ b/libc/inet/res_query.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_query +#include "resolv.c" diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c new file mode 100644 index 0000000..044059d --- /dev/null +++ b/libc/inet/resolv.c @@ -0,0 +1,2840 @@ +/* resolv.c: DNS Resolver + * + * Copyright (C) 1998 Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + */ + +/* + * Portions Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * + * 5-Oct-2000 W. Greathouse wgreathouse@smva.com + * Fix memory leak and memory corruption. + * -- Every name resolution resulted in + * a new parse of resolv.conf and new + * copy of nameservers allocated by + * strdup. + * -- Every name resolution resulted in + * a new read of resolv.conf without + * resetting index from prior read... + * resulting in exceeding array bounds. + * + * Limit nameservers read from resolv.conf + * + * Add "search" domains from resolv.conf + * + * Some systems will return a security + * signature along with query answer for + * dynamic DNS entries. + * -- skip/ignore this answer + * + * Include arpa/nameser.h for defines. + * + * General cleanup + * + * 20-Jun-2001 Michal Moskal + * partial IPv6 support (i.e. gethostbyname2() and resolve_address2() + * functions added), IPv6 nameservers are also supported. + * + * 6-Oct-2001 Jari Korva + * more IPv6 support (IPv6 support for gethostbyaddr(); + * address family parameter and improved IPv6 support for get_hosts_byname + * and read_etc_hosts; getnameinfo() port from glibc; defined + * defined ip6addr_any and in6addr_loopback) + * + * 2-Feb-2002 Erik Andersen + * Added gethostent(), sethostent(), and endhostent() + * + * 17-Aug-2002 Manuel Novoa III + * Fixed __read_etc_hosts_r to return alias list, and modified buffer + * allocation accordingly. See MAX_ALIASES and ALIAS_DIM below. + * This fixes the segfault in the Python 2.2.1 socket test. + * + * 04-Jan-2003 Jay Kulpinski + * Fixed __decode_dotted to count the terminating null character + * in a host name. + * + * 02-Oct-2003 Tony J. White + * Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(), + * and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools + * and openldap. + * + * 7-Sep-2004 Erik Andersen + * Added gethostent_r() + * + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* poll() is not supported in kernel <= 2.0, therefore if __NR_poll is + * not available, we assume an old Linux kernel is in use and we will + * use select() instead. */ +#include +#ifndef __NR_poll +# define USE_SELECT +#endif + +__UCLIBC_MUTEX_EXTERN(__resolv_lock); + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memmove) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncat) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +/* libc_hidden_proto(strnlen) */ +/* Experimentally off - libc_hidden_proto(strstr) */ +/* Experimentally off - libc_hidden_proto(strcasecmp) */ +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(random) +libc_hidden_proto(getservbyport) +libc_hidden_proto(uname) +libc_hidden_proto(inet_addr) +libc_hidden_proto(inet_aton) +libc_hidden_proto(inet_pton) +libc_hidden_proto(inet_ntop) +libc_hidden_proto(connect) +libc_hidden_proto(poll) +libc_hidden_proto(select) +libc_hidden_proto(recv) +libc_hidden_proto(send) +libc_hidden_proto(printf) +libc_hidden_proto(sprintf) +libc_hidden_proto(snprintf) +libc_hidden_proto(fgets) +libc_hidden_proto(gethostbyname) +libc_hidden_proto(gethostbyname_r) +libc_hidden_proto(gethostbyname2_r) +libc_hidden_proto(gethostbyaddr) +libc_hidden_proto(gethostbyaddr_r) +libc_hidden_proto(ns_name_uncompress) +libc_hidden_proto(ns_name_unpack) +libc_hidden_proto(ns_name_ntop) +libc_hidden_proto(res_init) +libc_hidden_proto(res_query) +libc_hidden_proto(res_querydomain) +libc_hidden_proto(gethostent_r) +libc_hidden_proto(fprintf) +libc_hidden_proto(__h_errno_location) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif +int __libc_getdomainname(char *name, size_t len); +libc_hidden_proto(__libc_getdomainname) + + +#define MAX_RECURSE 5 +#define REPLY_TIMEOUT 10 +#define MAX_RETRIES 3 +#define MAX_SERVERS 3 +#define MAX_SEARCH 4 + +#define MAX_ALIASES 5 + +/* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */ +#define ALIAS_DIM (2 + MAX_ALIASES + 1) + +#undef DEBUG +/* #define DEBUG */ + +#ifdef DEBUG +#define DPRINTF(X,args...) fprintf(stderr, X, ##args) +#else +#define DPRINTF(X,args...) +#endif /* DEBUG */ + +/* Make sure the incoming char * buffer is aligned enough to handle our random + * structures. This define is the same as we use for malloc alignment (which + * has same requirements). The offset is the number of bytes we need to adjust + * in order to attain desired alignment. + */ +#define ALIGN_ATTR __alignof__(double __attribute_aligned__ (sizeof(size_t))) +#define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % ALIGN_ATTR) + + +/* Global stuff (stuff needing to be locked to be thread safe)... */ +extern int __nameservers attribute_hidden; +extern char * __nameserver[MAX_SERVERS] attribute_hidden; +extern int __searchdomains attribute_hidden; +extern char * __searchdomain[MAX_SEARCH] attribute_hidden; + + + +/* Structs */ +struct resolv_header { + int id; + int qr,opcode,aa,tc,rd,ra,rcode; + int qdcount; + int ancount; + int nscount; + int arcount; +}; + +struct resolv_question { + char * dotted; + int qtype; + int qclass; +}; + +struct resolv_answer { + char * dotted; + int atype; + int aclass; + int ttl; + int rdlength; + const unsigned char * rdata; + int rdoffset; + char* buf; + size_t buflen; + size_t add_count; +}; + +enum etc_hosts_action { + GET_HOSTS_BYNAME = 0, + GETHOSTENT, + GET_HOSTS_BYADDR, +}; + +/* function prototypes */ +extern int __get_hosts_byname_r(const char * name, int type, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) attribute_hidden; +extern int __get_hosts_byaddr_r(const char * addr, int len, int type, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) attribute_hidden; +extern FILE * __open_etc_hosts(void) attribute_hidden; +extern int __read_etc_hosts_r(FILE *fp, const char * name, int type, + enum etc_hosts_action action, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) attribute_hidden; +extern int __dns_lookup(const char * name, int type, int nscount, + char ** nsip, unsigned char ** outpacket, struct resolv_answer * a) attribute_hidden; + +extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen) attribute_hidden; +extern int __decode_dotted(const unsigned char * const message, int offset, + char * dest, int maxlen) attribute_hidden; +extern int __length_dotted(const unsigned char * const message, int offset) attribute_hidden; +extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen) attribute_hidden; +extern int __decode_header(unsigned char * data, struct resolv_header * h) attribute_hidden; +extern int __encode_question(const struct resolv_question * const q, + unsigned char * dest, int maxlen) attribute_hidden; +extern int __decode_question(const unsigned char * const message, int offset, + struct resolv_question * q) attribute_hidden; +extern int __encode_answer(struct resolv_answer * a, + unsigned char * dest, int maxlen) attribute_hidden; +extern int __decode_answer(const unsigned char * message, int offset, + int len, struct resolv_answer * a) attribute_hidden; +extern int __length_question(const unsigned char * const message, int offset) attribute_hidden; +extern void __open_nameservers(void) attribute_hidden; +extern void __close_nameservers(void) attribute_hidden; +extern int __dn_expand(const u_char *, const u_char *, const u_char *, + char *, int); + +#ifdef L_encodeh +int attribute_hidden __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) +{ + if (maxlen < HFIXEDSZ) + return -1; + + dest[0] = (h->id & 0xff00) >> 8; + dest[1] = (h->id & 0x00ff) >> 0; + dest[2] = (h->qr ? 0x80 : 0) | + ((h->opcode & 0x0f) << 3) | + (h->aa ? 0x04 : 0) | + (h->tc ? 0x02 : 0) | + (h->rd ? 0x01 : 0); + dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f); + dest[4] = (h->qdcount & 0xff00) >> 8; + dest[5] = (h->qdcount & 0x00ff) >> 0; + dest[6] = (h->ancount & 0xff00) >> 8; + dest[7] = (h->ancount & 0x00ff) >> 0; + dest[8] = (h->nscount & 0xff00) >> 8; + dest[9] = (h->nscount & 0x00ff) >> 0; + dest[10] = (h->arcount & 0xff00) >> 8; + dest[11] = (h->arcount & 0x00ff) >> 0; + + return HFIXEDSZ; +} +#endif + +#ifdef L_decodeh +int attribute_hidden __decode_header(unsigned char *data, struct resolv_header *h) +{ + h->id = (data[0] << 8) | data[1]; + h->qr = (data[2] & 0x80) ? 1 : 0; + h->opcode = (data[2] >> 3) & 0x0f; + h->aa = (data[2] & 0x04) ? 1 : 0; + h->tc = (data[2] & 0x02) ? 1 : 0; + h->rd = (data[2] & 0x01) ? 1 : 0; + h->ra = (data[3] & 0x80) ? 1 : 0; + h->rcode = data[3] & 0x0f; + h->qdcount = (data[4] << 8) | data[5]; + h->ancount = (data[6] << 8) | data[7]; + h->nscount = (data[8] << 8) | data[9]; + h->arcount = (data[10] << 8) | data[11]; + + return HFIXEDSZ; +} +#endif + +#ifdef L_encoded +/* Encode a dotted string into nameserver transport-level encoding. + This routine is fairly dumb, and doesn't attempt to compress + the data */ + +int attribute_hidden __encode_dotted(const char *dotted, unsigned char *dest, int maxlen) +{ + unsigned used = 0; + + while (dotted && *dotted) { + char *c = strchr(dotted, '.'); + int l = c ? c - dotted : strlen(dotted); + + /* two consecutive dots are not valid */ + if (l == 0) + return -1; + + if (l >= (maxlen - used - 1)) + return -1; + + dest[used++] = l; + memcpy(dest + used, dotted, l); + used += l; + + if (c) + dotted = c + 1; + else + break; + } + + if (maxlen < 1) + return -1; + + dest[used++] = 0; + + return used; +} +#endif + +#ifdef L_decoded +/* Decode a dotted string from nameserver transport-level encoding. + This routine understands compressed data. */ + +int attribute_hidden __decode_dotted(const unsigned char * const data, int offset, + char *dest, int maxlen) +{ + int l; + bool measure = 1; + unsigned total = 0; + unsigned used = 0; + + if (!data) + return -1; + + while ((l = data[offset++])) { + if (measure) + total++; + if ((l & 0xc0) == (0xc0)) { + if (measure) + total++; + /* compressed item, redirect */ + offset = ((l & 0x3f) << 8) | data[offset]; + measure = 0; + continue; + } + + if ((used + l + 1) >= maxlen) + return -1; + + memcpy(dest + used, data + offset, l); + offset += l; + used += l; + if (measure) + total += l; + + if (data[offset] != 0) + dest[used++] = '.'; + else + dest[used++] = '\0'; + } + + /* The null byte must be counted too */ + if (measure) + total++; + + DPRINTF("Total decode len = %d\n", total); + + return total; +} +#endif + +#ifdef L_lengthd +/* Returns -1 only if data == NULL */ +int attribute_hidden __length_dotted(const unsigned char * const data, int offset) +{ + int orig_offset = offset; + int l; + + if (!data) + return -1; + + while ((l = data[offset++])) { + if ((l & 0xc0) == (0xc0)) { + offset++; + break; + } + + offset += l; + } + + return offset - orig_offset; +} +#endif + +#ifdef L_encodeq +int attribute_hidden __encode_question(const struct resolv_question * const q, + unsigned char *dest, int maxlen) +{ + int i; + + i = __encode_dotted(q->dotted, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + + if (maxlen < 4) + return -1; + + dest[0] = (q->qtype & 0xff00) >> 8; + dest[1] = (q->qtype & 0x00ff) >> 0; + dest[2] = (q->qclass & 0xff00) >> 8; + dest[3] = (q->qclass & 0x00ff) >> 0; + + return i + 4; +} +#endif + +#ifdef L_decodeq +int attribute_hidden __decode_question(const unsigned char * const message, int offset, + struct resolv_question *q) +{ + char temp[256]; + int i; + + i = __decode_dotted(message, offset, temp, sizeof(temp)); + if (i < 0) + return i; + + offset += i; + +//TODO: what if strdup fails? + q->dotted = strdup(temp); + q->qtype = (message[offset + 0] << 8) | message[offset + 1]; + q->qclass = (message[offset + 2] << 8) | message[offset + 3]; + + return i + 4; +} +#endif + +#ifdef L_lengthq +/* Returns -1 only if message == NULL */ +int attribute_hidden __length_question(const unsigned char * const message, int offset) +{ + int i; + + /* returns -1 only if message == NULL */ + i = __length_dotted(message, offset); + if (i < 0) + return i; + + return i + 4; +} +#endif + +#ifdef L_encodea +int attribute_hidden __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen) +{ + int i; + + i = __encode_dotted(a->dotted, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + + if (maxlen < (RRFIXEDSZ + a->rdlength)) + return -1; + + *dest++ = (a->atype & 0xff00) >> 8; + *dest++ = (a->atype & 0x00ff) >> 0; + *dest++ = (a->aclass & 0xff00) >> 8; + *dest++ = (a->aclass & 0x00ff) >> 0; + *dest++ = (a->ttl & 0xff000000) >> 24; + *dest++ = (a->ttl & 0x00ff0000) >> 16; + *dest++ = (a->ttl & 0x0000ff00) >> 8; + *dest++ = (a->ttl & 0x000000ff) >> 0; + *dest++ = (a->rdlength & 0xff00) >> 8; + *dest++ = (a->rdlength & 0x00ff) >> 0; + memcpy(dest, a->rdata, a->rdlength); + + return i + RRFIXEDSZ + a->rdlength; +} +#endif + +#ifdef L_decodea +int attribute_hidden __decode_answer(const unsigned char *message, int offset, + int len, struct resolv_answer *a) +{ + char temp[256]; + int i; + + DPRINTF("decode_answer(start): off %d, len %d\n", offset, len); + i = __decode_dotted(message, offset, temp, sizeof(temp)); + if (i < 0) + return i; + + message += offset + i; + len -= i + RRFIXEDSZ + offset; + if (len < 0) { + DPRINTF("decode_answer: off %d, len %d, i %d\n", offset, len, i); + return len; + } + +// TODO: what if strdup fails? + a->dotted = strdup(temp); + a->atype = (message[0] << 8) | message[1]; + message += 2; + a->aclass = (message[0] << 8) | message[1]; + message += 2; + a->ttl = (message[0] << 24) | + (message[1] << 16) | (message[2] << 8) | (message[3] << 0); + message += 4; + a->rdlength = (message[0] << 8) | message[1]; + message += 2; + a->rdata = message; + a->rdoffset = offset + i + RRFIXEDSZ; + + DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength); + + if (len < a->rdlength) + return -1; + return i + RRFIXEDSZ + a->rdlength; +} +#endif + +#ifdef L_encodep +int __encode_packet(struct resolv_header *h, + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) attribute_hidden; +int __encode_packet(struct resolv_header *h, + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) +{ + int i, total = 0; + unsigned j; + + i = __encode_header(h, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + total += i; + + for (j = 0; j < h->qdcount; j++) { + i = __encode_question(q[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + + for (j = 0; j < h->ancount; j++) { + i = __encode_answer(an[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + for (j = 0; j < h->nscount; j++) { + i = __encode_answer(ns[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + for (j = 0; j < h->arcount; j++) { + i = __encode_answer(ar[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + + return total; +} +#endif + +#ifdef L_decodep +int __decode_packet(unsigned char *data, struct resolv_header *h) attribute_hidden; +int __decode_packet(unsigned char *data, struct resolv_header *h) +{ + return __decode_header(data, h); +} +#endif + +#ifdef L_formquery +int __form_query(int id, const char *name, int type, unsigned char *packet, int maxlen); +int __form_query(int id, const char *name, int type, unsigned char *packet, + int maxlen) +{ + struct resolv_header h; + struct resolv_question q; + int i, j; + + memset(&h, 0, sizeof(h)); + h.id = id; + h.qdcount = 1; + + q.dotted = (char *) name; + q.qtype = type; + q.qclass = C_IN; /* CLASS_IN */ + + i = __encode_header(&h, packet, maxlen); + if (i < 0) + return i; + + j = __encode_question(&q, packet + i, maxlen - i); + if (j < 0) + return j; + + return i + j; +} +#endif + +#ifdef L_dnslookup +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +/* Just for the record, having to lock __dns_lookup() just for these two globals + * is pretty lame. I think these two variables can probably be de-global-ized, + * which should eliminate the need for doing locking here... Needs a closer + * look anyways. */ +static int static_ns = 0; +/* uint16: minimizing rw data size, even if code grows a tiny bit. + * rw data costs more. */ +static uint16_t static_id = 1; + +/* On entry: + * a.buf(len) = auxiliary buffer for IP addresses after first one + * a.add_count = how many additional addresses are there already + * outpacket = where to save ptr to raw packet? can be NULL + * On exit: + * ret < 0: error, all other data is not valid + * a.add_count & a.buf: updated + * a.rdlength: length of addresses (4 bytes for IPv4) + * *outpacket: updated (packet is malloced, you need to free it) + * a.rdata: points into *outpacket to 1st IP addr + * NB: don't pass outpacket == NULL if you need to use a.rdata! + * a.atype: type of query? + * a.dotted: which name we _actually_ used. May contain search domains + * appended. (why the filed is called "dotted" I have no idea) + * This is a malloced string. May be NULL because strdup failed. + */ +int attribute_hidden __dns_lookup(const char *name, int type, + int nscount, char **nsip, + unsigned char **outpacket, + struct resolv_answer *a) +{ + int i, j, len, fd, pos, rc; +#ifdef USE_SELECT + struct timeval tv; + fd_set fds; +#else + struct pollfd fds; +#endif + struct resolv_header h; + struct resolv_question q; + struct resolv_answer ma; + bool first_answer = 1; + unsigned retries = 0; + unsigned char *packet = malloc(PACKETSZ); + char *dns, *lookup = malloc(MAXDNAME); + int variant = -1; /* search domain to append, -1 - none */ + int local_ns = -1, local_id = -1; + bool ends_with_dot; + union { + struct sockaddr sa; +#ifdef __UCLIBC_HAS_IPV4__ + struct sockaddr_in sa4; +#endif +#ifdef __UCLIBC_HAS_IPV6__ + struct sockaddr_in6 sa6; +#endif + } sa; + + fd = -1; + + if (!packet || !lookup || !nscount || !name[0]) + goto fail; + + DPRINTF("Looking up type %d answer for '%s'\n", type, name); + + ends_with_dot = (name[strlen(name) - 1] == '.'); + + /* Mess with globals while under lock */ + __UCLIBC_MUTEX_LOCK(mylock); + local_ns = static_ns % nscount; + local_id = static_id; + __UCLIBC_MUTEX_UNLOCK(mylock); + + while (retries < MAX_RETRIES) { + if (fd != -1) + close(fd); + + memset(packet, 0, PACKETSZ); + + memset(&h, 0, sizeof(h)); + + ++local_id; + local_id &= 0xffff; + h.id = local_id; + h.qdcount = 1; + h.rd = 1; + + DPRINTF("encoding header\n", h.rd); + + i = __encode_header(&h, packet, PACKETSZ); + if (i < 0) + goto fail; + + strncpy(lookup, name, MAXDNAME); + __UCLIBC_MUTEX_LOCK(__resolv_lock); + /* nsip is really __nameserver[] which is a global that + needs to hold __resolv_lock before access!! */ + dns = nsip[local_ns]; +/* TODO: all future accesses to 'dns' were guarded by __resolv_lock too. + * Why? We already fetched nsip[local_ns] here, + * future changes to nsip[] by other threads cannot affect us. + * We can use 'dns' without locking. If I'm wrong, + * please explain in comments why locking is needed. + * One thing that worries me is - what if __close_nameservers() free()s + * dns under us? __resolv_lock'ing around accesses to dns won't help either, + * as free() might occur between accesses! + */ + if (variant >= 0) { + if (variant < __searchdomains) { + strncat(lookup, ".", MAXDNAME); + strncat(lookup, __searchdomain[variant], MAXDNAME); + } + } + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + DPRINTF("lookup name: %s\n", lookup); + q.dotted = lookup; + q.qtype = type; + q.qclass = C_IN; /* CLASS_IN */ + + j = __encode_question(&q, packet+i, PACKETSZ-i); + if (j < 0) + goto fail; + + len = i + j; + + DPRINTF("On try %d, sending query to port %d of machine %s\n", + retries+1, NAMESERVER_PORT, dns); + + sa.sa.sa_family = AF_INET; +#ifdef __UCLIBC_HAS_IPV6__ + //__UCLIBC_MUTEX_LOCK(__resolv_lock); + ///* 'dns' is really __nameserver[] which is a global that + // needs to hold __resolv_lock before access!! */ + if (inet_pton(AF_INET6, dns, &sa.sa6.sin6_addr) > 0) + sa.sa.sa_family = AF_INET6; + //__UCLIBC_MUTEX_UNLOCK(__resolv_lock); +#endif + /* Connect to the UDP socket so that asyncronous errors are returned */ +#ifdef __UCLIBC_HAS_IPV6__ + if (sa.sa.sa_family == AF_INET6) { + sa.sa6.sin6_port = htons(NAMESERVER_PORT); + /* sa6.sin6_addr is already here */ + } else +#endif +#ifdef __UCLIBC_HAS_IPV4__ + { + sa.sa4.sin_port = htons(NAMESERVER_PORT); + //__UCLIBC_MUTEX_LOCK(__resolv_lock); + ///* 'dns' is really __nameserver[] which is a global that + // needs to hold __resolv_lock before access!! */ + sa.sa4.sin_addr.s_addr = inet_addr(dns); + //__UCLIBC_MUTEX_UNLOCK(__resolv_lock); + } +#endif + fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + retries++; + continue; + } + rc = connect(fd, &sa.sa, sizeof(sa)); + if (rc < 0) { + if (errno == ENETUNREACH) { + /* routing error, presume not transient */ + goto tryall; + } + /* retry */ + retries++; + continue; + } + + DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n", + len, h.id, h.qr); + + send(fd, packet, len, 0); + +#ifdef USE_SELECT + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = REPLY_TIMEOUT; + tv.tv_usec = 0; + if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) { + DPRINTF("Timeout\n"); + /* timed out, so retry send and receive, + * to next nameserver on queue */ + goto tryall; + } +#else + fds.fd = fd; + fds.events = POLLIN; + if (poll(&fds, 1, REPLY_TIMEOUT * 1000) <= 0) { + DPRINTF("Timeout\n"); + /* timed out, so retry send and receive, + * to next nameserver on queue */ + goto tryall; + } +#endif + + len = recv(fd, packet, PACKETSZ, 0); + if (len < HFIXEDSZ) { + /* too short! */ + goto again; + } + + __decode_header(packet, &h); + + DPRINTF("id = %d, qr = %d\n", h.id, h.qr); + + if ((h.id != local_id) || (!h.qr)) { + /* unsolicited */ + goto again; + } + + DPRINTF("Got response (i think)!\n"); + DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n", + h.qdcount, h.ancount, h.nscount, h.arcount); + DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n", + h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode); + + if (h.rcode == NXDOMAIN) { +// bug 660 says we treat negative response as an error and retry +// which is, eh, an error. :) We were incurring long delays because of this. + /* if possible, try next search domain */ + if (!ends_with_dot) { + int sdomains; + __UCLIBC_MUTEX_LOCK(__resolv_lock); + sdomains = __searchdomains; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (variant < sdomains - 1) { + /* next search */ + variant++; + continue; + } + } + /* this is not an error - don't goto again! */ + h_errno = HOST_NOT_FOUND; + goto fail1; + } + if (h.rcode != 0) /* error */ + goto again; + /* code below won't work correctly with h.ancount == 0, so... */ + if (h.ancount < 1) { + h_errno = NO_DATA; /* is this correct code? */ + goto fail1; + } + + pos = HFIXEDSZ; + + for (j = 0; j < h.qdcount; j++) { + DPRINTF("Skipping question %d at %d\n", j, pos); + /* returns -1 only if packet == NULL (can't happen) */ + i = __length_question(packet, pos); + //if (i < 0) + // goto again; + DPRINTF("Length of question %d is %d\n", j, i); + pos += i; + } + DPRINTF("Decoding answer at pos %d\n", pos); + + first_answer = 1; + for (j = 0; j < h.ancount && pos < len; j++) { + i = __decode_answer(packet, pos, len, &ma); + if (i < 0) { + DPRINTF("failed decode %d\n", i); + /* if the message was truncated and we have + decoded some answers, pretend it's OK */ + if (j && h.tc) + break; + goto again; + } + pos += i; + + if (first_answer) { + ma.buf = a->buf; + ma.buflen = a->buflen; + ma.add_count = a->add_count; + memcpy(a, &ma, sizeof(ma)); + if (a->atype != T_SIG && (NULL == a->buf || (type != T_A && type != T_AAAA))) + break; + if (a->atype != type) { + free(a->dotted); + continue; + } + a->add_count = h.ancount - j - 1; + if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) + break; + a->add_count = 0; + first_answer = 0; + } else { + free(ma.dotted); + if (ma.atype != type) + continue; + if (a->rdlength != ma.rdlength) { + free(a->dotted); + DPRINTF("Answer address len(%u) differs from original(%u)\n", + ma.rdlength, a->rdlength); + goto again; + } + memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); + ++a->add_count; + } + } + + DPRINTF("Answer name = |%s|\n", a->dotted); + DPRINTF("Answer type = |%d|\n", a->atype); + + close(fd); + + if (outpacket) + *outpacket = packet; + else + free(packet); + free(lookup); + + /* Mess with globals while under lock */ + __UCLIBC_MUTEX_LOCK(mylock); + static_ns = local_ns; + static_id = local_id; + __UCLIBC_MUTEX_UNLOCK(mylock); + + return len; /* success! */ + + tryall: + /* if there are other nameservers, give them a go, + otherwise return with error */ + variant = -1; + local_ns = (local_ns + 1) % nscount; + if (local_ns == 0) + retries++; + + continue; + + again: + /* if there are searchdomains, try them or fallback as passed */ + if (!ends_with_dot) { + int sdomains; + __UCLIBC_MUTEX_LOCK(__resolv_lock); + sdomains = __searchdomains; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (variant < sdomains - 1) { + /* next search */ + variant++; + continue; + } + } + /* next server, first search */ + local_ns = (local_ns + 1) % nscount; + if (local_ns == 0) + retries++; + variant = -1; + } + + fail: + h_errno = NETDB_INTERNAL; + fail1: + if (fd != -1) + close(fd); + free(lookup); + free(packet); + /* Mess with globals while under lock */ + if (local_ns != -1) { + __UCLIBC_MUTEX_LOCK(mylock); + static_ns = local_ns; + static_id = local_id; + __UCLIBC_MUTEX_UNLOCK(mylock); + } + return -1; +} +#endif + +#ifdef L_opennameservers + +/* We use __resolv_lock to guard access to the + * '__nameservers' and __searchdomains globals */ +int __nameservers; +char * __nameserver[MAX_SERVERS]; +int __searchdomains; +char * __searchdomain[MAX_SEARCH]; + +__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +/* + * we currently read formats not quite the same as that on normal + * unix systems, we can have a list of nameservers after the keyword. + */ + +void attribute_hidden __open_nameservers(void) +{ + FILE *fp; + int i; +#define RESOLV_ARGS 5 + char szBuffer[128], *p, *argv[RESOLV_ARGS]; + int argc; + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + if (__nameservers > 0) + goto DONE; + + if ((fp = fopen("/etc/resolv.conf", "r")) || + (fp = fopen("/etc/config/resolv.conf", "r"))) + { + while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + for (p = szBuffer; *p && isspace(*p); p++) + /* skip white space */; + if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ + continue; + argc = 0; + while (*p && argc < RESOLV_ARGS) { + argv[argc++] = p; + while (*p && !isspace(*p) && *p != '\n') + p++; + while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ + *p++ = '\0'; + } + + if (strcmp(argv[0], "nameserver") == 0) { + for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { +// TODO: what if strdup fails? + __nameserver[__nameservers++] = strdup(argv[i]); + DPRINTF("adding nameserver %s\n", argv[i]); + } + } + + /* domain and search are mutually exclusive, the last one wins */ + if (strcmp(argv[0],"domain") == 0 || strcmp(argv[0],"search") == 0) { + while (__searchdomains > 0) { + free(__searchdomain[--__searchdomains]); + __searchdomain[__searchdomains] = NULL; + } + for (i = 1; i < argc && __searchdomains < MAX_SEARCH; i++) { +// TODO: what if strdup fails? + __searchdomain[__searchdomains++] = strdup(argv[i]); + DPRINTF("adding search %s\n", argv[i]); + } + } + } + fclose(fp); + DPRINTF("nameservers = %d\n", __nameservers); + goto DONE; + } + DPRINTF("failed to open %s\n", "resolv.conf"); + h_errno = NO_RECOVERY; + + /* rv = -1; */ + + DONE: + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + /* return rv; */ +} +#endif + + +#ifdef L_closenameservers + +void attribute_hidden __close_nameservers(void) +{ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + while (__nameservers > 0) { + free(__nameserver[--__nameservers]); + __nameserver[__nameservers] = NULL; + } + while (__searchdomains > 0) { + free(__searchdomain[--__searchdomains]); + __searchdomain[__searchdomains] = NULL; + } + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); +} +#endif + +#ifdef L_gethostbyname + +struct hostent *gethostbyname(const char *name) +{ + static struct hostent h; + static char buf[sizeof(struct in_addr) + + sizeof(struct in_addr *)*2 + + sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno); + + return hp; +} +libc_hidden_def(gethostbyname) +#endif + +#ifdef L_gethostbyname2 + +struct hostent *gethostbyname2(const char *name, int family) +{ +#ifndef __UCLIBC_HAS_IPV6__ + return family == AF_INET ? gethostbyname(name) : (struct hostent*)0; +#else /* __UCLIBC_HAS_IPV6__ */ + static struct hostent h; + static char buf[sizeof(struct in6_addr) + + sizeof(struct in6_addr *)*2 + + sizeof(char *)*ALIAS_DIM + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno); + + return hp; +#endif /* __UCLIBC_HAS_IPV6__ */ +} +#endif + + + +#ifdef L_res_init +/* We use __resolv_lock to guard access to global '_res' */ +struct __res_state _res; + +int res_init(void) +{ + struct __res_state *rp = &(_res); + + __UCLIBC_MUTEX_LOCK(__resolv_lock); /* must be a recursive lock! */ + __close_nameservers(); + __open_nameservers(); + rp->retrans = RES_TIMEOUT; + rp->retry = 4; + rp->options = RES_INIT; + rp->id = (u_int) random(); + rp->nsaddr.sin_addr.s_addr = INADDR_ANY; + rp->nsaddr.sin_family = AF_INET; + rp->nsaddr.sin_port = htons(NAMESERVER_PORT); + rp->ndots = 1; + /** rp->pfcode = 0; **/ + rp->_vcsock = -1; + /** rp->_flags = 0; **/ + /** rp->qhook = NULL; **/ + /** rp->rhook = NULL; **/ + /** rp->_u._ext.nsinit = 0; **/ + + if (__searchdomains) { + int i; + for (i = 0; i < __searchdomains; i++) + rp->dnsrch[i] = __searchdomain[i]; + } + + if (__nameservers) { + int i; + struct in_addr a; + for (i = 0; i < __nameservers; i++) { + if (inet_aton(__nameserver[i], &a)) { + rp->nsaddr_list[i].sin_addr = a; + rp->nsaddr_list[i].sin_family = AF_INET; + rp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); + } + } + } + rp->nscount = __nameservers; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + return 0; +} +libc_hidden_def(res_init) + +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close(void) +{ + __close_nameservers(); + memset(&_res, 0, sizeof(_res)); +} +#endif + +#endif + + +#ifdef L_res_query + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +int res_query(const char *dname, int class, int type, + unsigned char *answer, int anslen) +{ + int i; + unsigned char * packet = NULL; + struct resolv_answer a; + int __nameserversXX; + char ** __nameserverXX; + + if (!dname || class != 1 /* CLASS_IN */) { + h_errno = NO_RECOVERY; + return -1; + } + + memset(&a, '\0', sizeof(a)); + __open_nameservers(); + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX = __nameservers; + __nameserverXX = __nameserver; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { + h_errno = TRY_AGAIN; + return -1; + } + + free(a.dotted); + + if (a.atype == type) { /* CNAME */ + i = MIN(anslen, i); + memcpy(answer, packet, i); + } + free(packet); + return i; +} +libc_hidden_def(res_query) + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in h_errno. + */ +#define __TRAILING_DOT (1<<0) +#define __GOT_NODATA (1<<1) +#define __GOT_SERVFAIL (1<<2) +#define __TRIED_AS_IS (1<<3) +int res_search(const char *name, int class, int type, u_char *answer, + int anslen) +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *)(void *)answer; + u_int dots; + unsigned _state = 0; + int ret, saved_herrno; + u_long _res_options; + unsigned _res_ndots; + char **_res_dnsrch; + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) { + h_errno = NETDB_INTERNAL; + return -1; + } + + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + + if (cp > name && *--cp == '.') + _state |= __TRAILING_DOT; + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_ndots = _res.ndots; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (dots >= _res_ndots) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + saved_herrno = h_errno; + _state |= __TRIED_AS_IS; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + _res_dnsrch = _res.dnsrch; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if ((!dots && (_res_options & RES_DEFNAMES)) || + (dots && !(_state & __TRAILING_DOT) && (_res_options & RES_DNSRCH))) { + bool done = 0; + + for (domain = (const char * const *)_res_dnsrch; + *domain && !done; + domain++) { + + ret = res_querydomain(name, *domain, class, type, + answer, anslen); + if (ret > 0) + return ret; + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + h_errno = TRY_AGAIN; + return -1; + } + + switch (h_errno) { + case NO_DATA: + _state |= __GOT_NODATA; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + _state |= __GOT_SERVFAIL; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done = 1; + } + /* + * if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_DNSRCH)) + done = 1; + } + } + + /* + * if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!(_state & __TRIED_AS_IS)) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + } + + /* + * if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's h_errno + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless h_errno, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + h_errno = saved_herrno; + else if (_state & __GOT_NODATA) + h_errno = NO_DATA; + else if (_state & __GOT_SERVFAIL) + h_errno = TRY_AGAIN; + return -1; +} +#undef __TRAILING_DOT +#undef __GOT_NODATA +#undef __GOT_SERVFAIL +#undef __TRIED_AS_IS +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int res_querydomain(const char *name, const char *domain, int class, int type, + u_char * answer, int anslen) +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + size_t n, d; + u_long _res_options; + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) { + h_errno = NETDB_INTERNAL; + return -1; + } + +#ifdef DEBUG + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (_res_options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", + name, (domain ? domain : ""), class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + if (n > 0 && name[--n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + 1 + d + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); + } + return res_query(longname, class, type, answer, anslen); +} +libc_hidden_def(res_querydomain) + +/* res_mkquery */ +/* res_send */ +/* dn_comp */ +/* dn_expand */ +#endif + +#ifdef L_gethostbyaddr +struct hostent *gethostbyaddr (const void *addr, socklen_t len, int type) +{ + static struct hostent h; + static char buf[ +#ifndef __UCLIBC_HAS_IPV6__ + sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + +#else + sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + +#endif /* __UCLIBC_HAS_IPV6__ */ + sizeof(char *)*ALIAS_DIM + 384 /*namebuffer*/ + 32 /* margin */]; + struct hostent *hp; + + gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno); + + return hp; +} +libc_hidden_def(gethostbyaddr) +#endif + + +#ifdef L_read_etc_hosts_r + +FILE * __open_etc_hosts(void) +{ + FILE * fp; + if ((fp = fopen("/etc/hosts", "r")) == NULL) { + fp = fopen("/etc/config/hosts", "r"); + } + return fp; +} + +int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type, + enum etc_hosts_action action, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) +{ + struct in_addr *in = NULL; + struct in_addr **addr_list = NULL; +#ifdef __UCLIBC_HAS_IPV6__ + struct in6_addr *in6 = NULL; + struct in6_addr **addr_list6 = NULL; +#endif /* __UCLIBC_HAS_IPV6__ */ + char *cp, **alias; + int aliases, i, ret = HOST_NOT_FOUND; + + /* make sure user char * is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + if (unlikely(i)) { + if (buflen < i) + return ERANGE; + buf += i; + buflen -= i; + } + + if (buflen < sizeof(char *)*ALIAS_DIM) + return ERANGE; + alias = (char **)buf; + buf += sizeof(char **)*ALIAS_DIM; + buflen -= sizeof(char **)*ALIAS_DIM; + + if (action != GETHOSTENT) { +#ifdef __UCLIBC_HAS_IPV6__ + char *p = buf; + size_t len = buflen; +#endif /* __UCLIBC_HAS_IPV6__ */ + *h_errnop = NETDB_INTERNAL; + if (buflen < sizeof(*in)) + return ERANGE; + in = (struct in_addr*)buf; + buf += sizeof(*in); + buflen -= sizeof(*in); + + if (buflen < sizeof(*addr_list)*2) + return ERANGE; + addr_list = (struct in_addr **)buf; + buf += sizeof(*addr_list)*2; + buflen -= sizeof(*addr_list)*2; + +#ifdef __UCLIBC_HAS_IPV6__ + if (len < sizeof(*in6)) + return ERANGE; + in6 = (struct in6_addr*)p; + p += sizeof(*in6); + len -= sizeof(*in6); + + if (len < sizeof(*addr_list6)*2) + return ERANGE; + addr_list6 = (struct in6_addr**)p; + p += sizeof(*addr_list6)*2; + len -= sizeof(*addr_list6)*2; + + if (len < buflen) { + buflen = len; + buf = p; + } +#endif /* __UCLIBC_HAS_IPV6__ */ + + if (buflen < 80) + return ERANGE; + + fp = __open_etc_hosts(); + if (fp == NULL) { + *result = NULL; + return errno; + } + } + + *h_errnop = HOST_NOT_FOUND; + while (fgets(buf, buflen, fp)) { + cp = strchr(buf, '#'); + if (cp) + *cp = '\0'; + DPRINTF("Looking at: %s\n", buf); + aliases = 0; + + cp = buf; + while (*cp) { + while (*cp && isspace(*cp)) + *cp++ = '\0'; + if (!*cp) + break; + if (aliases < (2+MAX_ALIASES)) + alias[aliases++] = cp; + while (*cp && !isspace(*cp)) + cp++; + } + alias[aliases] = 0; + + if (aliases < 2) + continue; /* syntax error really */ + + if (action == GETHOSTENT) { + /* Return whatever the next entry happens to be. */ + break; + } + if (action == GET_HOSTS_BYADDR) { + if (strcmp(name, alias[0]) != 0) + continue; + } else { + /* GET_HOSTS_BYNAME */ + for (i = 1; i < aliases; i++) + if (strcasecmp(name, alias[i]) == 0) + break; + if (i >= aliases) + continue; + } + + if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) { + DPRINTF("Found INET\n"); + addr_list[0] = in; + addr_list[1] = 0; + result_buf->h_name = alias[1]; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char**) addr_list; + result_buf->h_aliases = alias + 2; + *result = result_buf; + ret = NETDB_SUCCESS; +#ifdef __UCLIBC_HAS_IPV6__ + } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) { + DPRINTF("Found INET6\n"); + addr_list6[0] = in6; + addr_list6[1] = 0; + result_buf->h_name = alias[1]; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(*in6); + result_buf->h_addr_list = (char**) addr_list6; + result_buf->h_aliases = alias + 2; + *result = result_buf; + ret = NETDB_SUCCESS; +#endif /* __UCLIBC_HAS_IPV6__ */ + } else { + /* continue parsing in the hope the user has multiple + * host types listed in the database like so: + * host + * host + * If looking for an IPv6 addr, don't bail when we got the IPv4 + */ + DPRINTF("Error: Found host but diff network type\n"); + /* NB: gethostbyname2_r depends on this feature + * to avoid looking for IPv6 addr of "localhost" etc */ + ret = TRY_AGAIN; + continue; + } + break; + } + if (action != GETHOSTENT) + fclose(fp); + return ret; +} +#endif + + +#ifdef L_gethostent +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static smallint __stay_open; +static FILE * __gethostent_fp; + +void endhostent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = 0; + if (__gethostent_fp) { + fclose(__gethostent_fp); + __gethostent_fp = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void sethostent(int stay_open) +{ + __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = (stay_open != 0); + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + if (__gethostent_fp == NULL) { + __gethostent_fp = __open_etc_hosts(); + if (__gethostent_fp == NULL) { + *result = NULL; + ret = TRY_AGAIN; + goto DONE; + } + } + + ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT, + result_buf, buf, buflen, result, h_errnop); + if (__stay_open == 0) { + fclose(__gethostent_fp); + __gethostent_fp = NULL; + } +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} +libc_hidden_def(gethostent_r) + +struct hostent *gethostent(void) +{ + static struct hostent h; + static char buf[ +#ifndef __UCLIBC_HAS_IPV6__ + sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + +#else + sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + +#endif /* __UCLIBC_HAS_IPV6__ */ + sizeof(char *)*ALIAS_DIM + + 80 /*namebuffer*/ + 2 /* margin */]; + struct hostent *host; + + __UCLIBC_MUTEX_LOCK(mylock); + gethostent_r(&h, buf, sizeof(buf), &host, &h_errno); + __UCLIBC_MUTEX_UNLOCK(mylock); + return host; +} +#endif + +#ifdef L_get_hosts_byname_r + +int attribute_hidden __get_hosts_byname_r(const char * name, int type, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) +{ + return __read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, + result_buf, buf, buflen, result, h_errnop); +} +#endif + +#ifdef L_get_hosts_byaddr_r + +int attribute_hidden __get_hosts_byaddr_r(const char * addr, int len, int type, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) +{ +#ifndef __UCLIBC_HAS_IPV6__ + char ipaddr[INET_ADDRSTRLEN]; +#else + char ipaddr[INET6_ADDRSTRLEN]; +#endif /* __UCLIBC_HAS_IPV6__ */ + + switch (type) { + case AF_INET: + if (len != sizeof(struct in_addr)) + return 0; + break; +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + if (len != sizeof(struct in6_addr)) + return 0; + break; +#endif /* __UCLIBC_HAS_IPV6__ */ + default: + return 0; + } + + inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); + + return __read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, + result_buf, buf, buflen, result, h_errnop); +} +#endif + +#ifdef L_getnameinfo + +#ifndef min +# define min(x,y) (((x) > (y)) ? (y) : (x)) +#endif /* min */ + +libc_hidden_proto(getnameinfo) +int getnameinfo(const struct sockaddr *sa, socklen_t addrlen, char *host, + socklen_t hostlen, char *serv, socklen_t servlen, + unsigned int flags) +{ + int serrno = errno; + unsigned ok; + struct hostent *h = NULL; + char domain[256]; + + if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)) + return EAI_BADFLAGS; + + if (sa == NULL || addrlen < sizeof (sa_family_t)) + goto BAD_FAM; + + ok = sa->sa_family; + if (ok == AF_LOCAL) /* valid */; +#ifdef __UCLIBC_HAS_IPV4__ + else if (ok == AF_INET) { + if (addrlen < sizeof (struct sockaddr_in)) + goto BAD_FAM; + } +#endif +#ifdef __UCLIBC_HAS_IPV6__ + else if (ok == AF_INET6) { + if (addrlen < sizeof (struct sockaddr_in6)) + goto BAD_FAM; + } +#endif /* __UCLIBC_HAS_IPV6__ */ + else +BAD_FAM: + return EAI_FAMILY; + + ok = 0; + if (host != NULL && hostlen > 0) + switch (sa->sa_family) { + case AF_INET: +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: +#endif /* __UCLIBC_HAS_IPV6__ */ + if (!(flags & NI_NUMERICHOST)) { +#ifdef __UCLIBC_HAS_IPV6__ + if (sa->sa_family == AF_INET6) + h = gethostbyaddr ((const void *) + &(((const struct sockaddr_in6 *) sa)->sin6_addr), + sizeof(struct in6_addr), AF_INET6); +#endif /* __UCLIBC_HAS_IPV6__ */ +#if defined __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ + else +#endif +#ifdef __UCLIBC_HAS_IPV4__ + h = gethostbyaddr ((const void *) + &(((const struct sockaddr_in *)sa)->sin_addr), + sizeof(struct in_addr), AF_INET); +#endif /* __UCLIBC_HAS_IPV4__ */ + + if (h) { + char *c; + if ((flags & NI_NOFQDN) + && (__libc_getdomainname (domain, sizeof(domain)) == 0) + && (c = strstr (h->h_name, domain)) + && (c != h->h_name) && (*(--c) == '.')) { + strncpy (host, h->h_name, + min(hostlen, (size_t) (c - h->h_name))); + host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; + } else { + strncpy (host, h->h_name, hostlen); + } + ok = 1; + } + } + + if (!ok) { + const char *c; + + if (flags & NI_NAMEREQD) { + errno = serrno; + return EAI_NONAME; + } +#ifdef __UCLIBC_HAS_IPV6__ + if (sa->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6p; + + sin6p = (const struct sockaddr_in6 *) sa; + c = inet_ntop (AF_INET6, + (const void *) &sin6p->sin6_addr, host, hostlen); +#if 0 + /* Does scope id need to be supported? */ + uint32_t scopeid; + scopeid = sin6p->sin6_scope_id; + if (scopeid != 0) { + /* Buffer is >= IFNAMSIZ+1. */ + char scopebuf[IFNAMSIZ + 1]; + char *scopeptr; + int ni_numericscope = 0; + size_t real_hostlen = strnlen (host, hostlen); + size_t scopelen = 0; + + scopebuf[0] = SCOPE_DELIMITER; + scopebuf[1] = '\0'; + scopeptr = &scopebuf[1]; + + if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) + || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { + if (if_indextoname (scopeid, scopeptr) == NULL) + ++ni_numericscope; + else + scopelen = strlen (scopebuf); + } else { + ++ni_numericscope; + } + + if (ni_numericscope) + scopelen = 1 + snprintf (scopeptr, + (scopebuf + + sizeof scopebuf + - scopeptr), + "%u", scopeid); + + if (real_hostlen + scopelen + 1 > hostlen) + return EAI_SYSTEM; + memcpy (host + real_hostlen, scopebuf, scopelen + 1); + } +#endif + } +#endif /* __UCLIBC_HAS_IPV6__ */ +#if defined __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ + else +#endif /* __UCLIBC_HAS_IPV6__ && defined __UCLIBC_HAS_IPV4__ */ +#if defined __UCLIBC_HAS_IPV4__ + c = inet_ntop (AF_INET, (const void *) + &(((const struct sockaddr_in *) sa)->sin_addr), + host, hostlen); +#endif /* __UCLIBC_HAS_IPV4__ */ + if (c == NULL) { + errno = serrno; + return EAI_SYSTEM; + } + ok = 1; + } + break; + + case AF_LOCAL: + if (!(flags & NI_NUMERICHOST)) { + struct utsname utsname; + + if (!uname (&utsname)) { + strncpy (host, utsname.nodename, hostlen); + break; + }; + }; + + if (flags & NI_NAMEREQD) { + errno = serrno; + return EAI_NONAME; + } + + strncpy (host, "localhost", hostlen); + break; +/* Already checked above + default: + return EAI_FAMILY; +*/ + } + + if (serv && (servlen > 0)) { + if (sa->sa_family == AF_LOCAL) { + strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); + } else { /* AF_INET || AF_INET6 */ + if (!(flags & NI_NUMERICSERV)) { + struct servent *s; + s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, + ((flags & NI_DGRAM) ? "udp" : "tcp")); + if (s) { + strncpy (serv, s->s_name, servlen); + goto DONE; + } + } + snprintf (serv, servlen, "%d", + ntohs (((const struct sockaddr_in *) sa)->sin_port)); + } + } +DONE: + if (host && (hostlen > 0)) + host[hostlen-1] = 0; + if (serv && (servlen > 0)) + serv[servlen-1] = 0; + errno = serrno; + return 0; +} +libc_hidden_def(getnameinfo) +#endif + + +#ifdef L_gethostbyname_r + +int gethostbyname_r(const char * name, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) +{ + struct in_addr *in; + struct in_addr **addr_list; + char **alias; + unsigned char *packet; + struct resolv_answer a; + int i; + int __nameserversXX; + char ** __nameserverXX; + + *result = NULL; + if (!name) + return EINVAL; + + /* do /etc/hosts first */ + { + int old_errno = errno; /* save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + i = __get_hosts_byname_r(name, AF_INET, result_buf, + buf, buflen, result, h_errnop); + if (i == 0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: + case NO_ADDRESS: + break; + case NETDB_INTERNAL: + if (errno == ENOENT) { + break; + } + /* else fall through */ + default: + return i; + } + __set_errno(old_errno); + } + + DPRINTF("Nothing found in /etc/hosts\n"); + + /* make sure user char * is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + if (unlikely(i)) { + if (buflen < i) + return ERANGE; + buf += i; + buflen -= i; + } + + *h_errnop = NETDB_INTERNAL; + if (buflen < sizeof(*in)) + return ERANGE; + in = (struct in_addr*)buf; + buf += sizeof(*in); + buflen -= sizeof(*in); + + if (buflen < sizeof(*addr_list)*2) + return ERANGE; + addr_list = (struct in_addr**)buf; + buf += sizeof(*addr_list)*2; + buflen -= sizeof(*addr_list)*2; + + addr_list[0] = in; + addr_list[1] = 0; + + if (buflen < sizeof(char *)*ALIAS_DIM) + return ERANGE; + alias = (char **)buf; + buf += sizeof(char **)*ALIAS_DIM; + buflen -= sizeof(char **)*ALIAS_DIM; + + if (buflen < 256) + return ERANGE; + strncpy(buf, name, buflen); + + alias[0] = buf; + alias[1] = NULL; + + /* First check if this is already an address */ + if (inet_aton(name, in)) { + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; + result_buf->h_aliases = alias; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + + __open_nameservers(); + + /*for (;;)*/ { +//FIXME: why was it a loop? It never loops... + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX = __nameservers; + __nameserverXX = __nameserver; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + a.buf = buf; + a.buflen = buflen; + a.add_count = 0; + i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { + *h_errnop = HOST_NOT_FOUND; + DPRINTF("__dns_lookup\n"); + return TRY_AGAIN; + } + + if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen) { + free(a.dotted); + free(packet); + *h_errnop = NETDB_INTERNAL; + DPRINTF("buffer too small for all addresses\n"); + return ERANGE; + } + + if (a.add_count > 0) { + memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); + addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); + addr_list[0] = in; + for (i = a.add_count - 1; i >= 0; --i) + addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); + addr_list[a.add_count + 1] = 0; + buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); + buf = (char*)&addr_list[a.add_count + 2]; + } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype == T_A) { /* ADDRESS */ + memcpy(in, a.rdata, sizeof(*in)); + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO -- generate the full list +#endif + result_buf->h_aliases = alias; /* TODO: generate the full list */ + free(packet); + /*was: break;*/ + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + free(packet); + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } +/* + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; +*/ +} +libc_hidden_def(gethostbyname_r) +#endif + +#ifdef L_gethostbyname2_r + +int gethostbyname2_r(const char *name, int family, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) +{ +#ifndef __UCLIBC_HAS_IPV6__ + return family == (AF_INET) + ? gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop) + : HOST_NOT_FOUND; +#else /* __UCLIBC_HAS_IPV6__ */ + struct in6_addr *in; + struct in6_addr **addr_list; + unsigned char *packet; + struct resolv_answer a; + int i; + int nest = 0; + int __nameserversXX; + char ** __nameserverXX; + int wrong_af = 0; + + if (family == AF_INET) + return gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop); + + if (family != AF_INET6) + return EINVAL; + + __open_nameservers(); + *result = NULL; + if (!name) + return EINVAL; + + /* do /etc/hosts first */ + { + int old_errno = errno; /* Save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + + i = __get_hosts_byname_r(name, family, result_buf, + buf, buflen, result, h_errnop); + if (i == NETDB_SUCCESS) { +//FIXME: restore errno? + return i; + } + switch (*h_errnop) { + case HOST_NOT_FOUND: + wrong_af = (i == TRY_AGAIN); + case NO_ADDRESS: + break; + case NETDB_INTERNAL: + if (errno == ENOENT) { + break; + } + /* else fall through */ + default: + return i; + } + __set_errno(old_errno); + } + + DPRINTF("Nothing found in /etc/hosts\n"); + + *h_errnop = NETDB_INTERNAL; + if (buflen < sizeof(*in)) + return ERANGE; + in = (struct in6_addr*)buf; + buf += sizeof(*in); + buflen -= sizeof(*in); + + if (buflen < sizeof(*addr_list)*2) + return ERANGE; + addr_list = (struct in6_addr**)buf; + buf += sizeof(*addr_list)*2; + buflen -= sizeof(*addr_list)*2; + + addr_list[0] = in; + addr_list[1] = 0; + + if (buflen < 256) + return ERANGE; + strncpy(buf, name, buflen); + + /* First check if this is already an address */ + if (inet_pton(AF_INET6, name, in)) { + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + + /* What if /etc/hosts has it but it's not IPv6? + * F.e. "127.0.0.1 localhost". We don't do DNS query for such hosts - + * "ping localhost" should be fast even if DNS server is down! */ + if (wrong_af) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + memset(&a, '\0', sizeof(a)); + + for (;;) { + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX = __nameservers; + __nameserverXX = __nameserver; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype == T_CNAME) { /* CNAME */ + DPRINTF("Got a CNAME in gethostbyname()\n"); + i = __decode_dotted(packet, a.rdoffset, buf, buflen); + free(packet); + + if (i < 0) { + *h_errnop = NO_RECOVERY; + return -1; + } + if (++nest > MAX_RECURSE) { + *h_errnop = NO_RECOVERY; + return -1; + } + continue; + } + if (a.atype == T_AAAA) { /* ADDRESS */ + memcpy(in, a.rdata, sizeof(*in)); + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; + free(packet); + break; + } + free(packet); + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; +#endif /* __UCLIBC_HAS_IPV6__ */ +} +libc_hidden_def(gethostbyname2_r) +#endif + +#ifdef L_gethostbyaddr_r +int gethostbyaddr_r(const void *addr, socklen_t len, int type, + struct hostent * result_buf, + char * buf, size_t buflen, + struct hostent ** result, + int * h_errnop) + +{ + struct in_addr *in; + struct in_addr **addr_list; +#ifdef __UCLIBC_HAS_IPV6__ + char *qp; + size_t plen; + struct in6_addr *in6; + struct in6_addr **addr_list6; +#endif /* __UCLIBC_HAS_IPV6__ */ + char **alias; + unsigned char *packet; + struct resolv_answer a; + int i; + int nest = 0; + int __nameserversXX; + char ** __nameserverXX; + + *result = NULL; + if (!addr) + return EINVAL; + + memset((char *) &a, '\0', sizeof(a)); + + switch (type) { + case AF_INET: + if (len != sizeof(struct in_addr)) + return EINVAL; + break; +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + if (len != sizeof(struct in6_addr)) + return EINVAL; + break; +#endif /* __UCLIBC_HAS_IPV6__ */ + default: + return EINVAL; + } + + /* do /etc/hosts first */ + if ((i = __get_hosts_byaddr_r(addr, len, type, result_buf, + buf, buflen, result, h_errnop)) == 0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: + case NO_ADDRESS: + break; + default: + return i; + } + + __open_nameservers(); + +#ifdef __UCLIBC_HAS_IPV6__ + qp = buf; + plen = buflen; +#endif /* __UCLIBC_HAS_IPV6__ */ + + *h_errnop = NETDB_INTERNAL; + if (buflen < sizeof(*in)) + return ERANGE; + in = (struct in_addr*)buf; + buf += sizeof(*in); + buflen -= sizeof(*in); + + if (buflen < sizeof(*addr_list)*2) + return ERANGE; + addr_list = (struct in_addr**)buf; + buf += sizeof(*addr_list)*2; + buflen -= sizeof(*addr_list)*2; + + if (buflen < sizeof(char *)*ALIAS_DIM) + return ERANGE; + alias = (char **)buf; + buf += sizeof(*alias)*ALIAS_DIM; + buflen -= sizeof(*alias)*ALIAS_DIM; + +#ifdef __UCLIBC_HAS_IPV6__ + if (plen < sizeof(*in6)) + return ERANGE; + in6 = (struct in6_addr*)qp; + qp += sizeof(*in6); + plen -= sizeof(*in6); + + if (plen < sizeof(*addr_list6)*2) + return ERANGE; + addr_list6 = (struct in6_addr**)qp; + qp += sizeof(*addr_list6)*2; + plen -= sizeof(*addr_list6)*2; + + if (plen < buflen) { + buflen = plen; + buf = qp; + } +#endif /* __UCLIBC_HAS_IPV6__ */ + + if (buflen < 256) + return ERANGE; + + if (type == AF_INET) { + unsigned char *tmp_addr = (unsigned char *)addr; + + memcpy(&in->s_addr, addr, len); + + addr_list[0] = in; + + sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", + tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); +#ifdef __UCLIBC_HAS_IPV6__ + } else { + memcpy(in6->s6_addr, addr, len); + + addr_list6[0] = in6; + qp = buf; + + for (i = len - 1; i >= 0; i--) { + qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf, + (in6->s6_addr[i] >> 4) & 0xf); + } + strcpy(qp, "ip6.arpa"); +#endif /* __UCLIBC_HAS_IPV6__ */ + } + + addr_list[1] = 0; + + alias[0] = buf; + alias[1] = 0; + + for (;;) { + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX = __nameservers; + __nameserverXX = __nameserver; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype == T_CNAME) { /* CNAME */ + DPRINTF("Got a CNAME in gethostbyaddr()\n"); + i = __decode_dotted(packet, a.rdoffset, buf, buflen); + free(packet); + + if (i < 0) { + *h_errnop = NO_RECOVERY; + return -1; + } + if (++nest > MAX_RECURSE) { + *h_errnop = NO_RECOVERY; + return -1; + } + continue; + } + + if (a.atype == T_PTR) { /* ADDRESS */ + i = __decode_dotted(packet, a.rdoffset, buf, buflen); + free(packet); + + result_buf->h_name = buf; + result_buf->h_addrtype = type; + + if (type == AF_INET) { + result_buf->h_length = sizeof(*in); +#ifdef __UCLIBC_HAS_IPV6__ + } else { + result_buf->h_length = sizeof(*in6); +#endif /* __UCLIBC_HAS_IPV6__ */ + } + + result_buf->h_addr_list = (char **) addr_list; + result_buf->h_aliases = alias; + break; + } + + free(packet); + *h_errnop = NO_ADDRESS; + return TRY_AGAIN; + } + + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; +} +libc_hidden_def(gethostbyaddr_r) +#endif + +#ifdef L_res_comp +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return n; +} +#endif /* L_res_comp */ + +#ifdef L_ns_name +/* + * printable(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * return: + * boolean. + */ +static int printable(int ch) +{ + return (ch > 0x20 && ch < 0x7f); +} + +/* + * special(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * return: + * boolean. + */ +static int special(int ch) +{ + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return 1; + default: + return 0; + } +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int ns_name_uncompress(const u_char *msg, const u_char *eom, + const u_char *src, char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return -1; + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return -1; + return n; +} +libc_hidden_def(ns_name_uncompress) + + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + static const char digits[] = "0123456789"; + + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + /* Some kind of compression pointer. */ + __set_errno(EMSGSIZE); + return -1; + } + if (dn != dst) { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '.'; + } + if (dn + n >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + for ((void)NULL; n > 0; n--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '.'; + } + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\0'; + return (dn - dst); +} +libc_hidden_def(ns_name_ntop) + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + /* Limit checks. */ + if (dstp + n + 1 >= dstlim || srcp + n >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + checked += n + 1; + *dstp++ = n; + memcpy(dstp, srcp, n); + dstp += n; + srcp += n; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + __set_errno(EMSGSIZE); + return -1; + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + __set_errno(EMSGSIZE); + return -1; + } + break; + + default: + __set_errno(EMSGSIZE); + return -1; /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return len; +} +libc_hidden_def(ns_name_unpack) +#endif /* L_ns_name */ +/* vi: set sw=4 ts=4: */ diff --git a/libc/inet/resolveaddress.c b/libc/inet/resolveaddress.c new file mode 100644 index 0000000..d57366c --- /dev/null +++ b/libc/inet/resolveaddress.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_resolveaddress +#include "resolv.c" diff --git a/libc/inet/resolvename.c b/libc/inet/resolvename.c new file mode 100644 index 0000000..157878f --- /dev/null +++ b/libc/inet/resolvename.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_resolvename +#include "resolv.c" diff --git a/libc/inet/rpc/.indent.pro b/libc/inet/rpc/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/inet/rpc/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/inet/rpc/Makefile b/libc/inet/rpc/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/inet/rpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/inet/rpc/Makefile.in b/libc/inet/rpc/Makefile.in new file mode 100644 index 0000000..1d1081b --- /dev/null +++ b/libc/inet/rpc/Makefile.in @@ -0,0 +1,45 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-rpc := -fno-strict-aliasing + +ifneq ($(UCLIBC_HAS_FULL_RPC),y) +# For now, only compile the stuff needed to do an NFS mount.... +CSRC:= authunix_prot.c auth_none.c auth_unix.c bindresvport.c \ + clnt_perror.c clnt_simple.c clnt_tcp.c clnt_udp.c \ + create_xid.c getrpcent.c \ + pmap_clnt.c pm_getmaps.c pm_getport.c pmap_prot.c pmap_prot2.c \ + rcmd.c rexec.c rpc_cmsg.c rpc_commondata.c rpc_dtablesize.c \ + rpc_prot.c rpc_thread.c rtime.c ruserpass.c sa_len.c \ + svc.c svc_auth.c svc_authux.c \ + xdr.c xdr_array.c xdr_mem.c xdr_rec.c xdr_reference.c +endif + +INET_RPC_DIR:=$(top_srcdir)libc/inet/rpc +INET_RPC_OUT:=$(top_builddir)libc/inet/rpc + +ifeq ($(UCLIBC_HAS_FULL_RPC),y) +INET_RPC_SRC:=$(wildcard $(INET_RPC_DIR)/*.c) +else +INET_RPC_SRC:=$(patsubst %.c,$(INET_RPC_DIR)/%.c,$(CSRC)) +endif +# rpc_thread.oS is better, because the header adds unneeded references to __pthread_internal_tsd* +INET_RPC_SRC:=$(filter-out $(INET_RPC_DIR)/rpc_thread.c,$(INET_RPC_SRC)) + +INET_RPC_OBJ:=$(patsubst $(INET_RPC_DIR)/%.c,$(INET_RPC_OUT)/%.o,$(INET_RPC_SRC)) + +libc-static-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.o +libc-shared-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.oS + +libc-nomulti-$(UCLIBC_HAS_RPC) += $(INET_RPC_OUT)/rpc_thread.o + +libc-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OBJ) + +objclean-y+=inet_rpc_clean + +inet_rpc_clean: + $(do_rm) $(addprefix $(INET_RPC_OUT)/*., o os oS) diff --git a/libc/inet/rpc/auth_none.c b/libc/inet/rpc/auth_none.c new file mode 100644 index 0000000..0585102 --- /dev/null +++ b/libc/inet/rpc/auth_none.c @@ -0,0 +1,140 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * auth_none.c + * Creates a client authentication handle for passing "null" + * credentials and verifiers to remote systems. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" + +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_opaque_auth) + +#define MAX_MARSHAL_SIZE 20 + +/* + * Authenticator operations routines + */ +static void authnone_verf (AUTH *); +static void authnone_destroy (AUTH *); +static bool_t authnone_marshal (AUTH *, XDR *); +static bool_t authnone_validate (AUTH *, struct opaque_auth *); +static bool_t authnone_refresh (AUTH *); + +static const struct auth_ops ops = { + authnone_verf, + authnone_marshal, + authnone_validate, + authnone_refresh, + authnone_destroy +}; + +/* Internal data and routines */ + +struct authnone_private_s { + AUTH no_client; + char marshalled_client[MAX_MARSHAL_SIZE]; + u_int mcnt; +}; +#ifdef __UCLIBC_HAS_THREADS__ +#define authnone_private (*(struct authnone_private_s **)&RPC_THREAD_VARIABLE(authnone_private_s)) +#else +static struct authnone_private_s *authnone_private; +#endif + +libc_hidden_proto(authnone_create) +AUTH * +authnone_create (void) +{ + struct authnone_private_s *ap; + XDR xdr_stream; + XDR *xdrs; + + ap = (struct authnone_private_s *) authnone_private; + if (ap == NULL) + { + ap = (struct authnone_private_s *) calloc (1, sizeof (*ap)); + if (ap == NULL) + return NULL; + authnone_private = ap; + } + if (!ap->mcnt) + { + ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = (struct auth_ops *)&ops; + xdrs = &xdr_stream; + xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHAL_SIZE, + XDR_ENCODE); + (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred); + (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); + } + return (&ap->no_client); +} +libc_hidden_def(authnone_create) + +static bool_t +authnone_marshal (AUTH *client attribute_unused, XDR *xdrs) +{ + struct authnone_private_s *ap; + + ap = authnone_private; + if (ap == NULL) + return FALSE; + return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt); +} + +static void +authnone_verf (AUTH *auth attribute_unused) +{ +} + +static bool_t +authnone_validate (AUTH *auth attribute_unused, struct opaque_auth *oa attribute_unused) +{ + return TRUE; +} + +static bool_t +authnone_refresh (AUTH *auth attribute_unused) +{ + return FALSE; +} + +static void +authnone_destroy (AUTH *auth attribute_unused) +{ +} diff --git a/libc/inet/rpc/auth_unix.c b/libc/inet/rpc/auth_unix.c new file mode 100644 index 0000000..0654b51 --- /dev/null +++ b/libc/inet/rpc/auth_unix.c @@ -0,0 +1,355 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * auth_unix.c, Implements UNIX style authentication parameters. + * + * The system is very weak. The client uses no encryption for it's + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(sysconf) +libc_hidden_proto(getegid) +libc_hidden_proto(geteuid) +libc_hidden_proto(getgroups) +libc_hidden_proto(gethostname) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_authunix_parms) +libc_hidden_proto(xdr_opaque_auth) +libc_hidden_proto(gettimeofday) +libc_hidden_proto(fputs) +libc_hidden_proto(perror) +libc_hidden_proto(abort) +#ifdef USE_IN_LIBIO +libc_hidden_proto(fwprintf) +#endif + +/* + * Unix authenticator operations vector + */ +static void authunix_nextverf (AUTH *); +static bool_t authunix_marshal (AUTH *, XDR *); +static bool_t authunix_validate (AUTH *, struct opaque_auth *); +static bool_t authunix_refresh (AUTH *); +static void authunix_destroy (AUTH *); + +static struct auth_ops auth_unix_ops = { + authunix_nextverf, + authunix_marshal, + authunix_validate, + authunix_refresh, + authunix_destroy +}; + +/* + * This struct is pointed to by the ah_private field of an auth_handle. + */ +struct audata { + struct opaque_auth au_origcred; /* original credentials */ + struct opaque_auth au_shcred; /* short hand cred */ + u_long au_shfaults; /* short hand cache faults */ + char au_marshed[MAX_AUTH_BYTES]; + u_int au_mpos; /* xdr pos at end of marshed */ +}; +#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) + +static bool_t marshal_new_auth (AUTH *) internal_function; + + +/* + * Create a unix style authenticator. + * Returns an auth handle with the given stuff in it. + */ +libc_hidden_proto(authunix_create) +AUTH * +authunix_create (char *machname, uid_t uid, gid_t gid, int len, + gid_t *aup_gids) +{ + struct authunix_parms aup; + char mymem[MAX_AUTH_BYTES]; + struct timeval now; + XDR xdrs; + AUTH *auth; + struct audata *au; + + /* + * Allocate and set up auth handle + */ + auth = (AUTH *) mem_alloc (sizeof (*auth)); + au = (struct audata *) mem_alloc (sizeof (*au)); + if (auth == NULL || au == NULL) + { +no_memory: +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("authunix_create: out of memory\n")); + else +#endif + (void) fputs (_("authunix_create: out of memory\n"), stderr); + mem_free (auth, sizeof (*auth)); + mem_free (au, sizeof (*au)); + return NULL; + } + auth->ah_ops = &auth_unix_ops; + auth->ah_private = (caddr_t) au; + auth->ah_verf = au->au_shcred = _null_auth; + au->au_shfaults = 0; + + /* + * fill in param struct from the given params + */ + (void) gettimeofday (&now, (struct timezone *) 0); + aup.aup_time = now.tv_sec; + aup.aup_machname = machname; + aup.aup_uid = uid; + aup.aup_gid = gid; + aup.aup_len = (u_int) len; + aup.aup_gids = aup_gids; + + /* + * Serialize the parameters into origcred + */ + xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); + if (!xdr_authunix_parms (&xdrs, &aup)) + abort (); + au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs); + au->au_origcred.oa_flavor = AUTH_UNIX; + au->au_origcred.oa_base = mem_alloc ((u_int) len); + if (au->au_origcred.oa_base == NULL) + goto no_memory; + memcpy(au->au_origcred.oa_base, mymem, (u_int) len); + + /* + * set auth handle to reflect new cred. + */ + auth->ah_cred = au->au_origcred; + marshal_new_auth (auth); + return auth; +} +libc_hidden_def(authunix_create) + +/* + * Returns an auth handle with parameters determined by doing lots of + * syscalls. + */ +libc_hidden_proto(authunix_create_default) +AUTH * +authunix_create_default (void) +{ + int len; + char machname[MAX_MACHINE_NAME + 1]; + uid_t uid; + gid_t gid; + int max_nr_groups = sysconf (_SC_NGROUPS_MAX); + gid_t *gids = NULL; + AUTH *ret_auth; + + if (max_nr_groups) { + gids = (gid_t*)malloc(sizeof(*gids) * max_nr_groups); + if (gids == NULL) + abort (); + } + + if (gethostname (machname, MAX_MACHINE_NAME) == -1) + abort (); + machname[MAX_MACHINE_NAME] = 0; + uid = geteuid (); + gid = getegid (); + + if ((len = getgroups (max_nr_groups, gids)) < 0) + abort (); + /* This braindamaged Sun code forces us here to truncate the + list of groups to NGRPS members since the code in + authuxprot.c transforms a fixed array. Grrr. */ + ret_auth = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids); + free (gids); + return ret_auth; +} +libc_hidden_def(authunix_create_default) + +/* + * authunix operations + */ + +static void +authunix_nextverf (AUTH *auth attribute_unused) +{ + /* no action necessary */ +} + +static bool_t +authunix_marshal (AUTH *auth, XDR *xdrs) +{ + struct audata *au = AUTH_PRIVATE (auth); + + return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos); +} + +static bool_t +authunix_validate (AUTH *auth, struct opaque_auth *verf) +{ + struct audata *au; + XDR xdrs; + + if (verf->oa_flavor == AUTH_SHORT) + { + au = AUTH_PRIVATE (auth); + xdrmem_create (&xdrs, verf->oa_base, verf->oa_length, + XDR_DECODE); + + if (au->au_shcred.oa_base != NULL) + { + mem_free (au->au_shcred.oa_base, + au->au_shcred.oa_length); + au->au_shcred.oa_base = NULL; + } + if (xdr_opaque_auth (&xdrs, &au->au_shcred)) + { + auth->ah_cred = au->au_shcred; + } + else + { + xdrs.x_op = XDR_FREE; + (void) xdr_opaque_auth (&xdrs, &au->au_shcred); + au->au_shcred.oa_base = NULL; + auth->ah_cred = au->au_origcred; + } + marshal_new_auth (auth); + } + return TRUE; +} + +static bool_t +authunix_refresh (AUTH *auth) +{ + struct audata *au = AUTH_PRIVATE (auth); + struct authunix_parms aup; + struct timeval now; + XDR xdrs; + int stat; + + if (auth->ah_cred.oa_base == au->au_origcred.oa_base) + { + /* there is no hope. Punt */ + return FALSE; + } + au->au_shfaults++; + + /* first deserialize the creds back into a struct authunix_parms */ + aup.aup_machname = NULL; + aup.aup_gids = (gid_t *) NULL; + xdrmem_create (&xdrs, au->au_origcred.oa_base, + au->au_origcred.oa_length, XDR_DECODE); + stat = xdr_authunix_parms (&xdrs, &aup); + if (!stat) + goto done; + + /* update the time and serialize in place */ + (void) gettimeofday (&now, (struct timezone *) 0); + aup.aup_time = now.tv_sec; + xdrs.x_op = XDR_ENCODE; + XDR_SETPOS (&xdrs, 0); + stat = xdr_authunix_parms (&xdrs, &aup); + if (!stat) + goto done; + auth->ah_cred = au->au_origcred; + marshal_new_auth (auth); +done: + /* free the struct authunix_parms created by deserializing */ + xdrs.x_op = XDR_FREE; + (void) xdr_authunix_parms (&xdrs, &aup); + XDR_DESTROY (&xdrs); + return stat; +} + +static void +authunix_destroy (AUTH *auth) +{ + struct audata *au = AUTH_PRIVATE (auth); + + mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length); + + if (au->au_shcred.oa_base != NULL) + mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length); + + mem_free (auth->ah_private, sizeof (struct audata)); + + if (auth->ah_verf.oa_base != NULL) + mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length); + + mem_free ((caddr_t) auth, sizeof (*auth)); +} + +/* + * Marshals (pre-serializes) an auth struct. + * sets private data, au_marshed and au_mpos + */ +static bool_t +internal_function +marshal_new_auth (AUTH *auth) +{ + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + struct audata *au = AUTH_PRIVATE (auth); + + xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); + if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) || + (!xdr_opaque_auth (xdrs, &(auth->ah_verf)))) + perror (_("auth_none.c - Fatal marshalling problem")); + else + au->au_mpos = XDR_GETPOS (xdrs); + + XDR_DESTROY (xdrs); + + return TRUE; +} diff --git a/libc/inet/rpc/authunix_prot.c b/libc/inet/rpc/authunix_prot.c new file mode 100644 index 0000000..62d1cb7 --- /dev/null +++ b/libc/inet/rpc/authunix_prot.c @@ -0,0 +1,73 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * authunix_prot.c + * XDR for UNIX style authentication parameters for RPC + */ + +#include +#include +#include +#include + +libc_hidden_proto(xdr_string) +libc_hidden_proto(xdr_u_int) +libc_hidden_proto(xdr_array) +libc_hidden_proto(xdr_u_long) +libc_hidden_proto(xdr_u_short) + +/* + * XDR for unix authentication parameters. + * Unfortunately, none of these can be declared const. + */ +libc_hidden_proto(xdr_authunix_parms) +bool_t +xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p) +{ + if (xdr_u_long (xdrs, &(p->aup_time)) + && xdr_string (xdrs, &(p->aup_machname), MAX_MACHINE_NAME) + && (sizeof (uid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_uid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_uid))) + && (sizeof (gid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_gid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_gid))) + && xdr_array (xdrs, (caddr_t *) & (p->aup_gids), + & (p->aup_len), NGRPS, sizeof (gid_t), + (sizeof (gid_t) == sizeof (short int) + ? (xdrproc_t) xdr_u_short : (xdrproc_t) xdr_u_int))) + { + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_authunix_parms) diff --git a/libc/inet/rpc/bindresvport.c b/libc/inet/rpc/bindresvport.c new file mode 100644 index 0000000..3f266e6 --- /dev/null +++ b/libc/inet/rpc/bindresvport.c @@ -0,0 +1,94 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(bind) +libc_hidden_proto(getpid) + +/* + * Bind a socket to a privileged IP port + */ +libc_hidden_proto(bindresvport) +int +bindresvport (int sd, struct sockaddr_in *sin) +{ + int res; + static short port; + struct sockaddr_in myaddr; + int i; + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + + if (sin == (struct sockaddr_in *) 0) + { + sin = &myaddr; + memset (sin, 0, sizeof (*sin)); + sin->sin_family = AF_INET; + } + else if (sin->sin_family != AF_INET) + { + __set_errno (EPFNOSUPPORT); + return -1; + } + + if (port == 0) + { + port = (getpid () % NPORTS) + STARTPORT; + } + res = -1; + __set_errno (EADDRINUSE); + + for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; ++i) + { + sin->sin_port = htons (port); + if (++port > ENDPORT) + { + port = STARTPORT; + } + res = bind(sd, (struct sockaddr *)sin, sizeof(struct sockaddr_in)); + } + + return res; +} +libc_hidden_def(bindresvport) diff --git a/libc/inet/rpc/clnt_generic.c b/libc/inet/rpc/clnt_generic.c new file mode 100644 index 0000000..54bd0e9 --- /dev/null +++ b/libc/inet/rpc/clnt_generic.c @@ -0,0 +1,189 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1987, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +libc_hidden_proto(clnttcp_create) +libc_hidden_proto(clntudp_create) +libc_hidden_proto(clntunix_create) +libc_hidden_proto(getprotobyname_r) +libc_hidden_proto(gethostbyname_r) +libc_hidden_proto(__rpc_thread_createerr) + +/* + * Generic client creation: takes (hostname, program-number, protocol) and + * returns client handle. Default options are set, which the user can + * change using the rpc equivalent of ioctl()'s. + */ +CLIENT * +clnt_create (const char *hostname, u_long prog, u_long vers, + const char *proto) +{ + struct hostent hostbuf, *h; + size_t hstbuflen; + char *hsttmpbuf; + struct protoent protobuf, *p; + size_t prtbuflen; + char *prttmpbuf; + struct sockaddr_in sin; + struct sockaddr_un sun; + int sock; + struct timeval tv; + CLIENT *client; + int herr; + + if (strcmp (proto, "unix") == 0) + { + memset ((char *)&sun, 0, sizeof (sun)); + sun.sun_family = AF_UNIX; + strcpy (sun.sun_path, hostname); + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) + return NULL; +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + return client; + } + + hstbuflen = 1024; + hsttmpbuf = alloca (hstbuflen); + while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen, + &h, &herr) != 0 + || h == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST; + return NULL; + } + else + { + /* Enlarge the buffer. */ + hstbuflen *= 2; + hsttmpbuf = alloca (hstbuflen); + } + + if (h->h_addrtype != AF_INET) + { + /* + * Only support INET for now + */ + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EAFNOSUPPORT; + return NULL; + } + sin.sin_family = h->h_addrtype; + sin.sin_port = 0; + memset (sin.sin_zero, 0, sizeof (sin.sin_zero)); + memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length); + + prtbuflen = 1024; + prttmpbuf = alloca (prtbuflen); + while (getprotobyname_r (proto, &protobuf, prttmpbuf, prtbuflen, &p) != 0 + || p == NULL) + if (errno != ERANGE) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_UNKNOWNPROTO; + ce->cf_error.re_errno = EPFNOSUPPORT; + return NULL; + } + else + { + /* Enlarge the buffer. */ + prtbuflen *= 2; + prttmpbuf = alloca (prtbuflen); + } + + sock = RPC_ANYSOCK; + switch (p->p_proto) + { + case IPPROTO_UDP: + tv.tv_sec = 5; + tv.tv_usec = 0; + client = clntudp_create (&sin, prog, vers, tv, &sock); + if (client == NULL) + { + return NULL; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + case IPPROTO_TCP: + client = clnttcp_create (&sin, prog, vers, &sock, 0, 0); + if (client == NULL) + { + return NULL; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + default: + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EPFNOSUPPORT; + } + return (NULL); + } + return client; +} diff --git a/libc/inet/rpc/clnt_perror.c b/libc/inet/rpc/clnt_perror.c new file mode 100644 index 0000000..7e6c907 --- /dev/null +++ b/libc/inet/rpc/clnt_perror.c @@ -0,0 +1,448 @@ +/* @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_perror.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include "rpc_private.h" + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(sprintf) +libc_hidden_proto(__glibc_strerror_r) +libc_hidden_proto(fputs) +#ifdef USE_IN_LIBIO +libc_hidden_proto(fwprintf) +#endif + +static char *auth_errmsg (enum auth_stat stat) internal_function; + +#ifdef __UCLIBC_HAS_THREADS__ +/* + * Making buf a preprocessor macro requires renaming the local + * buf variable in a few functions. Overriding a global variable + * with a local variable of the same name is a bad idea, anyway. + */ +#define buf (*(char **)&RPC_THREAD_VARIABLE(clnt_perr_buf_s)) +#else +static char *buf; +#endif + +static char * +_buf (void) +{ + if (buf == NULL) + buf = (char *) malloc (256); + return buf; +} + +struct rpc_errtab +{ + enum clnt_stat status; + unsigned int message_off; +}; + +static const char rpc_errstr[] = +{ +#define RPC_SUCCESS_IDX 0 + _("RPC: Success") + "\0" +#define RPC_CANTENCODEARGS_IDX (RPC_SUCCESS_IDX + sizeof "RPC: Success") + _("RPC: Can't encode arguments") + "\0" +#define RPC_CANTDECODERES_IDX (RPC_CANTENCODEARGS_IDX \ + + sizeof "RPC: Can't encode arguments") + _("RPC: Can't decode result") + "\0" +#define RPC_CANTSEND_IDX (RPC_CANTDECODERES_IDX \ + + sizeof "RPC: Can't decode result") + _("RPC: Unable to send") + "\0" +#define RPC_CANTRECV_IDX (RPC_CANTSEND_IDX \ + + sizeof "RPC: Unable to send") + _("RPC: Unable to receive") + "\0" +#define RPC_TIMEDOUT_IDX (RPC_CANTRECV_IDX \ + + sizeof "RPC: Unable to receive") + _("RPC: Timed out") + "\0" +#define RPC_VERSMISMATCH_IDX (RPC_TIMEDOUT_IDX \ + + sizeof "RPC: Timed out") + _("RPC: Incompatible versions of RPC") + "\0" +#define RPC_AUTHERROR_IDX (RPC_VERSMISMATCH_IDX \ + + sizeof "RPC: Incompatible versions of RPC") + _("RPC: Authentication error") + "\0" +#define RPC_PROGUNAVAIL_IDX (RPC_AUTHERROR_IDX \ + + sizeof "RPC: Authentication error") + _("RPC: Program unavailable") + "\0" +#define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \ + + sizeof "RPC: Program unavailable") + _("RPC: Program/version mismatch") + "\0" +#define RPC_PROCUNAVAIL_IDX (RPC_PROGVERSMISMATCH_IDX \ + + sizeof "RPC: Program/version mismatch") + _("RPC: Procedure unavailable") + "\0" +#define RPC_CANTDECODEARGS_IDX (RPC_PROCUNAVAIL_IDX \ + + sizeof "RPC: Procedure unavailable") + _("RPC: Server can't decode arguments") + "\0" +#define RPC_SYSTEMERROR_IDX (RPC_CANTDECODEARGS_IDX \ + + sizeof "RPC: Server can't decode arguments") + _("RPC: Remote system error") + "\0" +#define RPC_UNKNOWNHOST_IDX (RPC_SYSTEMERROR_IDX \ + + sizeof "RPC: Remote system error") + _("RPC: Unknown host") + "\0" +#define RPC_UNKNOWNPROTO_IDX (RPC_UNKNOWNHOST_IDX \ + + sizeof "RPC: Unknown host") + _("RPC: Unknown protocol") + "\0" +#define RPC_PMAPFAILURE_IDX (RPC_UNKNOWNPROTO_IDX \ + + sizeof "RPC: Unknown protocol") + _("RPC: Port mapper failure") + "\0" +#define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \ + + sizeof "RPC: Port mapper failure") + _("RPC: Program not registered") + "\0" +#define RPC_FAILED_IDX (RPC_PROGNOTREGISTERED_IDX \ + + sizeof "RPC: Program not registered") + _("RPC: Failed (unspecified error)") +}; + +static const struct rpc_errtab rpc_errlist[] = +{ + { RPC_SUCCESS, RPC_SUCCESS_IDX }, + { RPC_CANTENCODEARGS, RPC_CANTENCODEARGS_IDX }, + { RPC_CANTDECODERES, RPC_CANTDECODERES_IDX }, + { RPC_CANTSEND, RPC_CANTSEND_IDX }, + { RPC_CANTRECV, RPC_CANTRECV_IDX }, + { RPC_TIMEDOUT, RPC_TIMEDOUT_IDX }, + { RPC_VERSMISMATCH, RPC_VERSMISMATCH_IDX }, + { RPC_AUTHERROR, RPC_AUTHERROR_IDX }, + { RPC_PROGUNAVAIL, RPC_PROGUNAVAIL_IDX }, + { RPC_PROGVERSMISMATCH, RPC_PROGVERSMISMATCH_IDX }, + { RPC_PROCUNAVAIL, RPC_PROCUNAVAIL_IDX }, + { RPC_CANTDECODEARGS, RPC_CANTDECODEARGS_IDX }, + { RPC_SYSTEMERROR, RPC_SYSTEMERROR_IDX }, + { RPC_UNKNOWNHOST, RPC_UNKNOWNHOST_IDX }, + { RPC_UNKNOWNPROTO, RPC_UNKNOWNPROTO_IDX }, + { RPC_PMAPFAILURE, RPC_PMAPFAILURE_IDX }, + { RPC_PROGNOTREGISTERED, RPC_PROGNOTREGISTERED_IDX }, + { RPC_FAILED, RPC_FAILED_IDX } +}; + + +/* + * This interface for use by clntrpc + */ +libc_hidden_proto(clnt_sperrno) +char * +clnt_sperrno (enum clnt_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (rpc_errlist) / sizeof (struct rpc_errtab); i++) + { + if (rpc_errlist[i].status == stat) + { + return (char*)_(rpc_errstr + rpc_errlist[i].message_off); + } + } + return _("RPC: (unknown error code)"); +} +libc_hidden_def(clnt_sperrno) + +void +clnt_perrno (enum clnt_stat num) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_sperrno (num)); + else +#endif + (void) fputs (clnt_sperrno (num), stderr); +} + +/* + * Print reply error info + */ +libc_hidden_proto(clnt_sperror) +char * +clnt_sperror (CLIENT * rpch, const char *msg) +{ + char chrbuf[1024]; + struct rpc_err e; + char *err; + char *str = _buf (); + char *strstart = str; + int len; + + if (str == NULL) + return NULL; + CLNT_GETERR (rpch, &e); + + len = sprintf (str, "%s: ", msg); + str += len; + + (void) strcpy(str, clnt_sperrno(e.re_status)); + str += strlen(str); + + switch (e.re_status) + { + case RPC_SUCCESS: + case RPC_CANTENCODEARGS: + case RPC_CANTDECODERES: + case RPC_TIMEDOUT: + case RPC_PROGUNAVAIL: + case RPC_PROCUNAVAIL: + case RPC_CANTDECODEARGS: + case RPC_SYSTEMERROR: + case RPC_UNKNOWNHOST: + case RPC_UNKNOWNPROTO: + case RPC_PMAPFAILURE: + case RPC_PROGNOTREGISTERED: + case RPC_FAILED: + break; + + case RPC_CANTSEND: + case RPC_CANTRECV: + __glibc_strerror_r (e.re_errno, chrbuf, sizeof chrbuf); + len = sprintf (str, "; errno = %s", chrbuf); + str += len; + break; + + case RPC_VERSMISMATCH: + len= sprintf (str, _("; low version = %lu, high version = %lu"), + e.re_vers.low, e.re_vers.high); + str += len; + break; + + case RPC_AUTHERROR: + err = auth_errmsg (e.re_why); + (void) strcpy(str, _("; why = ")); + str += strlen(str); + + if (err != NULL) + { + (void) strcpy(str, err); + str += strlen(str); + } + else + { + len = sprintf (str, _("(unknown authentication error - %d)"), + (int) e.re_why); + str += len; + } + break; + + case RPC_PROGVERSMISMATCH: + len = sprintf (str, _("; low version = %lu, high version = %lu"), + e.re_vers.low, e.re_vers.high); + str += len; + break; + + default: /* unknown */ + len = sprintf (str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2); + str += len; + break; + } + *str = '\n'; + *++str = '\0'; + return (strstart); +} +libc_hidden_def(clnt_sperror) + +libc_hidden_proto(clnt_perror) +void +clnt_perror (CLIENT * rpch, const char *msg) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_sperror (rpch, msg)); + else +#endif + (void) fputs (clnt_sperror (rpch, msg), stderr); +} +libc_hidden_def(clnt_perror) + +libc_hidden_proto(clnt_spcreateerror) +char * +clnt_spcreateerror (const char *msg) +{ + char chrbuf[1024]; + char *str = _buf (); + char *cp; + int len; + struct rpc_createerr *ce; + + if (str == NULL) + return NULL; + ce = &get_rpc_createerr (); + len = sprintf (str, "%s: ", msg); + cp = str + len; + (void) strcpy(cp, clnt_sperrno (ce->cf_stat)); + cp += strlen(cp); + + switch (ce->cf_stat) + { + case RPC_PMAPFAILURE: + (void) strcpy(cp, " - "); + cp += strlen(cp); + + (void) strcpy(cp, clnt_sperrno (ce->cf_error.re_status)); + cp += strlen(cp); + + break; + + case RPC_SYSTEMERROR: + (void) strcpy(cp, " - "); + cp += strlen(cp); + + __glibc_strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf); + (void) strcpy(cp, chrbuf); + cp += strlen(cp); + break; + default: + break; + } + *cp = '\n'; + *++cp = '\0'; + return str; +} +libc_hidden_def(clnt_spcreateerror) + +void +clnt_pcreateerror (const char *msg) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_spcreateerror (msg)); + else +#endif + (void) fputs (clnt_spcreateerror (msg), stderr); +} + +struct auth_errtab +{ + enum auth_stat status; + unsigned int message_off; +}; + +static const char auth_errstr[] = +{ +#define AUTH_OK_IDX 0 + _("Authentication OK") + "\0" +#define AUTH_BADCRED_IDX (AUTH_OK_IDX + sizeof "Authentication OK") + _("Invalid client credential") + "\0" +#define AUTH_REJECTEDCRED_IDX (AUTH_BADCRED_IDX \ + + sizeof "Invalid client credential") + _("Server rejected credential") + "\0" +#define AUTH_BADVERF_IDX (AUTH_REJECTEDCRED_IDX \ + + sizeof "Server rejected credential") + _("Invalid client verifier") + "\0" +#define AUTH_REJECTEDVERF_IDX (AUTH_BADVERF_IDX \ + + sizeof "Invalid client verifier") + _("Server rejected verifier") + "\0" +#define AUTH_TOOWEAK_IDX (AUTH_REJECTEDVERF_IDX \ + + sizeof "Server rejected verifier") + _("Client credential too weak") + "\0" +#define AUTH_INVALIDRESP_IDX (AUTH_TOOWEAK_IDX \ + + sizeof "Client credential too weak") + _("Invalid server verifier") + "\0" +#define AUTH_FAILED_IDX (AUTH_INVALIDRESP_IDX \ + + sizeof "Invalid server verifier") + _("Failed (unspecified error)") +}; + +static const struct auth_errtab auth_errlist[] = +{ + { AUTH_OK, AUTH_OK_IDX }, + { AUTH_BADCRED, AUTH_BADCRED_IDX }, + { AUTH_REJECTEDCRED, AUTH_REJECTEDCRED_IDX }, + { AUTH_BADVERF, AUTH_BADVERF_IDX }, + { AUTH_REJECTEDVERF, AUTH_REJECTEDVERF_IDX }, + { AUTH_TOOWEAK, AUTH_TOOWEAK_IDX }, + { AUTH_INVALIDRESP, AUTH_INVALIDRESP_IDX }, + { AUTH_FAILED, AUTH_FAILED_IDX } +}; + +static char * +internal_function +auth_errmsg (enum auth_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (auth_errlist) / sizeof (struct auth_errtab); i++) + { + if (auth_errlist[i].status == stat) + { + return (char*)_(auth_errstr + auth_errlist[i].message_off); + } + } + return NULL; +} + + +static void __attribute_used__ +free_mem (void) +{ + free (buf); +} diff --git a/libc/inet/rpc/clnt_raw.c b/libc/inet/rpc/clnt_raw.c new file mode 100644 index 0000000..b44bd38 --- /dev/null +++ b/libc/inet/rpc/clnt_raw.c @@ -0,0 +1,261 @@ +/* @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_raw.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Memory based rpc for simple testing and timing. + * Interface to create an rpc client and server in the same process. + * This lets us simulate rpc and get round trip overhead, without + * any interference from the kernel. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" +#include +#include + +libc_hidden_proto(perror) +libc_hidden_proto(authnone_create) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_callhdr) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xdr_opaque_auth) +libc_hidden_proto(svc_getreq) +libc_hidden_proto(_seterr_reply) + +#define MCALL_MSG_SIZE 24 + +/* + * This is the "network" we will be moving stuff over. + */ +struct clntraw_private_s + { + CLIENT client_object; + XDR xdr_stream; + char _raw_buf[UDPMSGSIZE]; + char mashl_callmsg[MCALL_MSG_SIZE]; + u_int mcnt; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define clntraw_private (*(struct clntraw_private_s **)&RPC_THREAD_VARIABLE(clntraw_private_s)) +#else +static struct clntraw_private_s *clntraw_private; +#endif + +static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntraw_abort (void); +static void clntraw_geterr (CLIENT *, struct rpc_err *); +static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntraw_control (CLIENT *, int, char *); +static void clntraw_destroy (CLIENT *); + +static struct clnt_ops client_ops = +{ + clntraw_call, + clntraw_abort, + clntraw_geterr, + clntraw_freeres, + clntraw_destroy, + clntraw_control +}; + +/* + * Create a client handle for memory based rpc. + */ +CLIENT * +clntraw_create (u_long prog, u_long vers) +{ + struct clntraw_private_s *clp = clntraw_private; + struct rpc_msg call_msg; + XDR *xdrs = &clp->xdr_stream; + CLIENT *client = &clp->client_object; + + if (clp == 0) + { + clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp)); + if (clp == 0) + return (0); + clntraw_private = clp; + } + /* + * pre-serialize the static part of the call msg and stash it away + */ + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + xdrmem_create (xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); + if (!xdr_callhdr (xdrs, &call_msg)) + { + perror (_ ("clnt_raw.c - Fatal header serialization error.")); + } + clp->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); + + /* + * Set xdrmem for client/server shared buffer + */ + xdrmem_create (xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE); + + /* + * create client handle + */ + client->cl_ops = &client_ops; + client->cl_auth = authnone_create (); + return client; +} + +static enum clnt_stat +clntraw_call (h, proc, xargs, argsp, xresults, resultsp, timeout) + CLIENT *h; + u_long proc; + xdrproc_t xargs; + caddr_t argsp; + xdrproc_t xresults; + caddr_t resultsp; + struct timeval timeout attribute_unused; +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + struct rpc_msg msg; + enum clnt_stat status; + struct rpc_err error; + + if (clp == NULL) + return RPC_FAILED; +call_again: + /* + * send request + */ + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + ((struct rpc_msg *) clp->mashl_callmsg)->rm_xid++; + if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg, clp->mcnt)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + { + return (RPC_CANTENCODEARGS); + } + (void) XDR_GETPOS (xdrs); /* called just to cause overhead */ + + /* + * We have to call server input routine here because this is + * all going on in one process. Yuk. + */ + svc_getreq (1); + + /* + * get results + */ + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = resultsp; + msg.acpted_rply.ar_results.proc = xresults; + if (!xdr_replymsg (xdrs, &msg)) + return RPC_CANTDECODERES; + _seterr_reply (&msg, &error); + status = error.re_status; + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + } /* end successful completion */ + else + { + if (AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + if (msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf)); + } + } + + return status; +} + +static void +clntraw_geterr (CLIENT *cl attribute_unused, struct rpc_err *err attribute_unused) +{ +} + + +static bool_t +clntraw_freeres (CLIENT *cl attribute_unused, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + bool_t rval; + + if (clp == NULL) + { + rval = (bool_t) RPC_FAILED; + return rval; + } + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntraw_abort (void) +{ +} + +static bool_t +clntraw_control (CLIENT *cl attribute_unused, int i attribute_unused, char *c attribute_unused) +{ + return FALSE; +} + +static void +clntraw_destroy (CLIENT *cl attribute_unused) +{ +} diff --git a/libc/inet/rpc/clnt_simple.c b/libc/inet/rpc/clnt_simple.c new file mode 100644 index 0000000..745a502 --- /dev/null +++ b/libc/inet/rpc/clnt_simple.c @@ -0,0 +1,170 @@ +/* @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include "rpc_private.h" +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(close) +libc_hidden_proto(clntudp_create) +libc_hidden_proto(gethostbyname_r) + +struct callrpc_private_s + { + CLIENT *client; + int socket; + u_long oldprognum, oldversnum, valid; + char *oldhost; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define callrpc_private (*(struct callrpc_private_s **)&RPC_THREAD_VARIABLE(callrpc_private_s)) +#else +static struct callrpc_private_s *callrpc_private; +#endif + +int +callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, + xdrproc_t inproc, const char *in, xdrproc_t outproc, char *out) +{ + struct callrpc_private_s *crp = callrpc_private; + struct sockaddr_in server_addr; + enum clnt_stat clnt_stat; + struct hostent hostbuf, *hp; + struct timeval timeout, tottimeout; + + if (crp == 0) + { + crp = (struct callrpc_private_s *) calloc (1, sizeof (*crp)); + if (crp == 0) + return 0; + callrpc_private = crp; + } + if (crp->oldhost == NULL) + { + crp->oldhost = malloc (256); + crp->oldhost[0] = 0; + crp->socket = RPC_ANYSOCK; + } + if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum + && strcmp (crp->oldhost, host) == 0) + { + /* reuse old client */ + } + else + { + size_t buflen; + char *buffer; + int herr; + + crp->valid = 0; + if (crp->socket != RPC_ANYSOCK) + { + (void) close (crp->socket); + crp->socket = RPC_ANYSOCK; + } + if (crp->client) + { + clnt_destroy (crp->client); + crp->client = NULL; + } + + buflen = 1024; + buffer = alloca (buflen); + while (gethostbyname_r (host, &hostbuf, buffer, buflen, + &hp, &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + return (int) RPC_UNKNOWNHOST; + else + { + /* Enlarge the buffer. */ + buflen *= 2; + buffer = alloca (buflen); + } + + timeout.tv_usec = 0; + timeout.tv_sec = 5; + memcpy ((char *) &server_addr.sin_addr, hp->h_addr, hp->h_length); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + if ((crp->client = clntudp_create (&server_addr, (u_long) prognum, + (u_long) versnum, timeout, &crp->socket)) == NULL) + return (int) get_rpc_createerr().cf_stat; + crp->valid = 1; + crp->oldprognum = prognum; + crp->oldversnum = versnum; + (void) strncpy (crp->oldhost, host, 255); + crp->oldhost[255] = '\0'; + } + tottimeout.tv_sec = 25; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call (crp->client, procnum, inproc, (char *) in, + outproc, out, tottimeout); + /* + * if call failed, empty cache + */ + if (clnt_stat != RPC_SUCCESS) + crp->valid = 0; + return (int) clnt_stat; +} + +#ifdef __UCLIBC_HAS_THREADS__ +void attribute_hidden __rpc_thread_clnt_cleanup (void) +{ + struct callrpc_private_s *rcp = RPC_THREAD_VARIABLE(callrpc_private_s); + + if (rcp) { + if (rcp->client) + CLNT_DESTROY (rcp->client); + free (rcp); + } +} +#endif /* __UCLIBC_HAS_THREADS__ */ diff --git a/libc/inet/rpc/clnt_tcp.c b/libc/inet/rpc/clnt_tcp.c new file mode 100644 index 0000000..23e4ca8 --- /dev/null +++ b/libc/inet/rpc/clnt_tcp.c @@ -0,0 +1,566 @@ +/* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_tcp.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * TCP based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + +libc_hidden_proto(socket) +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(close) +libc_hidden_proto(authnone_create) +libc_hidden_proto(xdrrec_create) +libc_hidden_proto(xdrrec_endofrecord) +libc_hidden_proto(xdrrec_skiprecord) +libc_hidden_proto(xdr_callhdr) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xdr_opaque_auth) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_void) +libc_hidden_proto(pmap_getport) +libc_hidden_proto(_seterr_reply) +libc_hidden_proto(connect) +libc_hidden_proto(bindresvport) +libc_hidden_proto(poll) +libc_hidden_proto(fputs) +libc_hidden_proto(__rpc_thread_createerr) +#ifdef USE_IN_LIBIO +libc_hidden_proto(fwprintf) +#endif + +extern u_long _create_xid (void) attribute_hidden; + +#define MCALL_MSG_SIZE 24 + +struct ct_data + { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_in ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readtcp (char *, char *, int); +static int writetcp (char *, char *, int); + +static enum clnt_stat clnttcp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clnttcp_abort (void); +static void clnttcp_geterr (CLIENT *, struct rpc_err *); +static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clnttcp_control (CLIENT *, int, char *); +static void clnttcp_destroy (CLIENT *); + +static struct clnt_ops tcp_ops = +{ + clnttcp_call, + clnttcp_abort, + clnttcp_geterr, + clnttcp_freeres, + clnttcp_destroy, + clnttcp_control +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +libc_hidden_proto(clnttcp_create) +CLIENT * +clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct; + struct rpc_msg call_msg; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clnttcp_create: out of memory\n")); + else +#endif + (void) fputs (_("clnttcp_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no port number given ask the pmap for one + */ + if (raddr->sin_port == 0) + { + u_short port; + if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0) + { + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return ((CLIENT *) NULL); + } + raddr->sin_port = htons (port); + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); + if ((*sockp < 0) + || (connect (*sockp, (struct sockaddr *) raddr, + sizeof (*raddr)) < 0)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp >= 0) + (void) close (*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } + else + { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, + XDR_ENCODE); + if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) + { + if (ct->ct_closeit) + { + (void) close (*sockp); + } + goto fooy; + } + ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); + XDR_DESTROY (&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t) ct, readtcp, writetcp); + h->cl_ops = &tcp_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create (); + return h; + +fooy: + /* + * Something goofed, free stuff and barf + */ + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return ((CLIENT *) NULL); +} +libc_hidden_def(clnttcp_create) + +static enum clnt_stat +clnttcp_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) + CLIENT *h; + u_long proc; + xdrproc_t xdr_args; + caddr_t args_ptr; + xdrproc_t xdr_results; + caddr_t results_ptr; + struct timeval timeout; +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return (ct->ct_error.re_status); + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0) + { + return ct->ct_error.re_status = RPC_TIMEDOUT; + } + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) + { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + if (!xdrrec_skiprecord (xdrs)) + return (ct->ct_error.re_status); + /* now decode and validate the response header */ + if (!xdr_replymsg (xdrs, &reply_msg)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return ct->ct_error.re_status; + } + if ((u_int32_t) reply_msg.rm_xid == (u_int32_t) x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clnttcp_geterr (h, errp) + CLIENT *h; + struct rpc_err *errp; +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clnttcp_freeres (cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clnttcp_abort () +{ +} + +static bool_t +clnttcp_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + ct->ct_wait = *(struct timeval *) info; + ct->ct_waitset = TRUE; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_in *) info = ct->ct_addr; + break; + case CLGET_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *)info = ntohl (*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *)ct->ct_mcall = htonl (*(u_long *)info - 1); + /* decrement by 1 as clnttcp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl (*(u_long *)(ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl (*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clnttcp_destroy (CLIENT *h) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) + { + (void) close (ct->ct_sock); + } + XDR_DESTROY (&(ct->ct_xdrs)); + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); +} + +/* + * Interface between xdr serializer and tcp connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readtcp (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *)ctptr; + struct pollfd fd; + int milliseconds = (ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (poll(&fd, 1, milliseconds)) + { + case 0: + ct->ct_error.re_status = RPC_TIMEDOUT; + return -1; + + case -1: + if (errno == EINTR) + continue; + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = errno; + return -1; + } + break; + } + switch (len = read (ct->ct_sock, buf, len)) + { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return len; +} + +static int +writetcp (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data*)ctptr; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = write (ct->ct_sock, buf, cnt)) == -1) + { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return -1; + } + } + return len; +} diff --git a/libc/inet/rpc/clnt_udp.c b/libc/inet/rpc/clnt_udp.c new file mode 100644 index 0000000..1d7cb48 --- /dev/null +++ b/libc/inet/rpc/clnt_udp.c @@ -0,0 +1,631 @@ +/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_udp.c, Implements a UDP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +libc_hidden_proto(fwprintf) +#endif + +#ifdef IP_RECVERR +#include "errqueue.h" +#include +#endif + +/* Experimentally off - libc_hidden_proto(memcmp) */ +libc_hidden_proto(ioctl) +libc_hidden_proto(socket) +libc_hidden_proto(close) +/* CMSG_NXTHDR is using it */ +libc_hidden_proto(__cmsg_nxthdr) + +libc_hidden_proto(authnone_create) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_callhdr) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xdr_opaque_auth) +libc_hidden_proto(pmap_getport) +libc_hidden_proto(_seterr_reply) +libc_hidden_proto(setsockopt) +libc_hidden_proto(bindresvport) +libc_hidden_proto(recvfrom) +libc_hidden_proto(sendto) +libc_hidden_proto(recvmsg) +libc_hidden_proto(poll) +libc_hidden_proto(fputs) +libc_hidden_proto(__rpc_thread_createerr) + +extern u_long _create_xid (void) attribute_hidden; + +/* + * UDP bases client side rpc operations + */ +static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntudp_abort (void); +static void clntudp_geterr (CLIENT *, struct rpc_err *); +static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntudp_control (CLIENT *, int, char *); +static void clntudp_destroy (CLIENT *); + +static struct clnt_ops udp_ops = +{ + clntudp_call, + clntudp_abort, + clntudp_geterr, + clntudp_freeres, + clntudp_destroy, + clntudp_control +}; + +/* + * Private data kept per client handle + */ +struct cu_data + { + int cu_sock; + bool_t cu_closeit; + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; + struct timeval cu_total; + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; + char *cu_outbuf; + u_int cu_recvsz; + char cu_inbuf[1]; + }; + +/* + * Create a UDP based client handle. + * If *sockp<0, *sockp is set to a newly created UPD socket. + * If raddr->sin_port is 0 a binder on the remote machine + * is consulted for the correct port number. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is initialized to null authentication. + * Caller may wish to set this something more useful. + * + * wait is the amount of time used between retransmitting a call if + * no response has been heard; retransmission occurs until the actual + * rpc call times out. + * + * sendsz and recvsz are the maximum allowable packet sizes that can be + * sent and received. + */ +libc_hidden_proto(clntudp_bufcreate) +CLIENT * +clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, + struct timeval wait, int *sockp, u_int sendsz, + u_int recvsz) +{ + CLIENT *cl; + struct cu_data *cu = NULL; + struct rpc_msg call_msg; + + cl = (CLIENT *) mem_alloc (sizeof (CLIENT)); + sendsz = ((sendsz + 3) / 4) * 4; + recvsz = ((recvsz + 3) / 4) * 4; + cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz); + if (cl == NULL || cu == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clntudp_create: out of memory\n")); + else +#endif + (void) fputs (_("clntudp_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; + + if (raddr->sin_port == 0) + { + u_short port; + if ((port = + pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0) + { + goto fooy; + } + raddr->sin_port = htons (port); + } + cl->cl_ops = &udp_ops; + cl->cl_private = (caddr_t) cu; + cu->cu_raddr = *raddr; + cu->cu_rlen = sizeof (cu->cu_raddr); + cu->cu_wait = wait; + cu->cu_total.tv_sec = -1; + cu->cu_total.tv_usec = -1; + cu->cu_sendsz = sendsz; + cu->cu_recvsz = recvsz; + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = program; + call_msg.rm_call.cb_vers = version; + xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf, + sendsz, XDR_ENCODE); + if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg)) + { + goto fooy; + } + cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs)); + if (*sockp < 0) + { + int dontblock = 1; + + *sockp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (*sockp < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + goto fooy; + } + /* attempt to bind to prov port */ + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); + /* the sockets rpc controls are non-blocking */ + (void) ioctl (*sockp, FIONBIO, (char *) &dontblock); +#ifdef IP_RECVERR + { + int on = 1; + setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on)); + } +#endif + cu->cu_closeit = TRUE; + } + else + { + cu->cu_closeit = FALSE; + } + cu->cu_sock = *sockp; + cl->cl_auth = authnone_create (); + return cl; +fooy: + if (cu) + mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz); + if (cl) + mem_free ((caddr_t) cl, sizeof (CLIENT)); + return (CLIENT *) NULL; +} +libc_hidden_def(clntudp_bufcreate) + +libc_hidden_proto(clntudp_create) +CLIENT * +clntudp_create (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp) +{ + + return clntudp_bufcreate (raddr, program, version, wait, sockp, + UDPMSGSIZE, UDPMSGSIZE); +} +libc_hidden_def(clntudp_create) + +static int +is_network_up (int sock) +{ + struct ifconf ifc; + char buf[UDPMSGSIZE]; + struct ifreq ifreq, *ifr; + int n; + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) == 0) + { + ifr = ifc.ifc_req; + for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) + { + ifreq = *ifr; + if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) + break; + + if ((ifreq.ifr_flags & IFF_UP) + && ifr->ifr_addr.sa_family == AF_INET) + return 1; + } + } + return 0; +} + +static enum clnt_stat +clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout) + CLIENT *cl; /* client handle */ + u_long proc; /* procedure number */ + xdrproc_t xargs; /* xdr routine for args */ + caddr_t argsp; /* pointer to args */ + xdrproc_t xresults; /* xdr routine for results */ + caddr_t resultsp; /* pointer to results */ + struct timeval utimeout; /* seconds to wait before giving up */ +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs; + int outlen = 0; + int inlen; + socklen_t fromlen; + struct pollfd fd; + int milliseconds = (cu->cu_wait.tv_sec * 1000) + + (cu->cu_wait.tv_usec / 1000); + struct sockaddr_in from; + struct rpc_msg reply_msg; + XDR reply_xdrs; + struct timeval time_waited; + bool_t ok; + int nrefreshes = 2; /* number of times to refresh cred */ + struct timeval timeout; + int anyup; /* any network interface up */ + + if (cu->cu_total.tv_usec == -1) + { + timeout = utimeout; /* use supplied timeout */ + } + else + { + timeout = cu->cu_total; /* use default timeout */ + } + + time_waited.tv_sec = 0; + time_waited.tv_usec = 0; +call_again: + xdrs = &(cu->cu_outxdrs); + if (xargs == NULL) + goto get_reply; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, cu->cu_xdrpos); + /* + * the transaction is the first thing in the out buffer + */ + (*(uint32_t *) (cu->cu_outbuf))++; + if ((!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (cl->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + outlen = (int) XDR_GETPOS (xdrs); + +send_again: + if (sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0, + (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) + != outlen) + { + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTSEND); + } + + /* + * Hack to provide rpc-based message passing + */ + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) + { + return (cu->cu_error.re_status = RPC_TIMEDOUT); + } + get_reply: + /* + * sub-optimal code appears here because we have + * some clock time to spare while the packets are in flight. + * (We assume that this is actually only executed once.) + */ + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + fd.fd = cu->cu_sock; + fd.events = POLLIN; + anyup = 0; + for (;;) + { + switch (poll (&fd, 1, milliseconds)) + { + + case 0: + if (anyup == 0) + { + anyup = is_network_up (cu->cu_sock); + if (!anyup) + return (cu->cu_error.re_status = RPC_CANTRECV); + } + + time_waited.tv_sec += cu->cu_wait.tv_sec; + time_waited.tv_usec += cu->cu_wait.tv_usec; + while (time_waited.tv_usec >= 1000000) + { + time_waited.tv_sec++; + time_waited.tv_usec -= 1000000; + } + if ((time_waited.tv_sec < timeout.tv_sec) || + ((time_waited.tv_sec == timeout.tv_sec) && + (time_waited.tv_usec < timeout.tv_usec))) + goto send_again; + return (cu->cu_error.re_status = RPC_TIMEDOUT); + + /* + * buggy in other cases because time_waited is not being + * updated. + */ + case -1: + if (errno == EINTR) + continue; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } +#ifdef IP_RECVERR + if (fd.revents & POLLERR) + { + struct msghdr msg; + struct cmsghdr *cmsg; + struct sock_extended_err *e; + struct sockaddr_in err_addr; + struct iovec iov; + char *cbuf = (char *) alloca (outlen + 256); + int ret; + + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; + msg.msg_namelen = sizeof (err_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + msg.msg_control = cbuf; + msg.msg_controllen = 256; + ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE); + if (ret >= 0 + && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0 + && (msg.msg_flags & MSG_ERRQUEUE) + && ((msg.msg_namelen == 0 + && ret >= 12) + || (msg.msg_namelen == sizeof (err_addr) + && err_addr.sin_family == AF_INET + && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr, + sizeof (err_addr.sin_addr)) == 0 + && err_addr.sin_port == cu->cu_raddr.sin_port))) + for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + } +#endif + do + { + fromlen = sizeof (struct sockaddr); + inlen = recvfrom (cu->cu_sock, cu->cu_inbuf, + (int) cu->cu_recvsz, 0, + (struct sockaddr *) &from, &fromlen); + } + while (inlen < 0 && errno == EINTR); + if (inlen < 0) + { + if (errno == EWOULDBLOCK) + continue; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + if (inlen < 4) + continue; + + /* see if reply transaction id matches sent id. + Don't do this if we only wait for a replay */ + if (xargs != NULL + && (*((u_int32_t *) (cu->cu_inbuf)) + != *((u_int32_t *) (cu->cu_outbuf)))) + continue; + /* we now assume we have the proper reply */ + break; + } + + /* + * now decode and validate the response + */ + xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE); + ok = xdr_replymsg (&reply_xdrs, &reply_msg); + /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ + if (ok) + { + _seterr_reply (&reply_msg, &(cu->cu_error)); + if (cu->cu_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (cl->cl_auth, + &reply_msg.acpted_rply.ar_verf)) + { + cu->cu_error.re_status = RPC_AUTHERROR; + cu->cu_error.re_why = AUTH_INVALIDRESP; + } + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, + &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth)) + { + nrefreshes--; + goto call_again; + } + } /* end of unsuccessful completion */ + } /* end of valid reply message */ + else + { + cu->cu_error.re_status = RPC_CANTDECODERES; + } + return cu->cu_error.re_status; +} + +static void +clntudp_geterr (CLIENT *cl, struct rpc_err *errp) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + *errp = cu->cu_error; +} + + +static bool_t +clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs = &(cu->cu_outxdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntudp_abort (void) +{ +} + +static bool_t +clntudp_control (CLIENT *cl, int request, char *info) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + switch (request) + { + case CLSET_FD_CLOSE: + cu->cu_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + cu->cu_closeit = FALSE; + break; + case CLSET_TIMEOUT: + cu->cu_total = *(struct timeval *) info; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = cu->cu_total; + break; + case CLSET_RETRY_TIMEOUT: + cu->cu_wait = *(struct timeval *) info; + break; + case CLGET_RETRY_TIMEOUT: + *(struct timeval *) info = cu->cu_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_in *) info = cu->cu_raddr; + break; + case CLGET_FD: + *(int *)info = cu->cu_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1); + /* decrement by 1 as clntudp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + +static void +clntudp_destroy (CLIENT *cl) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + if (cu->cu_closeit) + { + (void) close (cu->cu_sock); + } + XDR_DESTROY (&(cu->cu_outxdrs)); + mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz)); + mem_free ((caddr_t) cl, sizeof (CLIENT)); +} diff --git a/libc/inet/rpc/clnt_unix.c b/libc/inet/rpc/clnt_unix.c new file mode 100644 index 0000000..73be742 --- /dev/null +++ b/libc/inet/rpc/clnt_unix.c @@ -0,0 +1,634 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt_unix.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * TCP based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(getpid) +libc_hidden_proto(authnone_create) +libc_hidden_proto(xdrrec_create) +libc_hidden_proto(xdrrec_endofrecord) +libc_hidden_proto(xdrrec_skiprecord) +libc_hidden_proto(xdr_callhdr) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xdr_opaque_auth) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_void) +libc_hidden_proto(getegid) +libc_hidden_proto(geteuid) +libc_hidden_proto(_seterr_reply) +libc_hidden_proto(setsockopt) +libc_hidden_proto(connect) +libc_hidden_proto(recvmsg) +libc_hidden_proto(sendmsg) +libc_hidden_proto(poll) +libc_hidden_proto(fputs) +libc_hidden_proto(__rpc_thread_createerr) + +extern u_long _create_xid (void) attribute_hidden; + +#define MCALL_MSG_SIZE 24 + +struct ct_data + { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_un ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readunix (char *, char *, int); +static int writeunix (char *, char *, int); + +static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntunix_abort (void); +static void clntunix_geterr (CLIENT *, struct rpc_err *); +static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntunix_control (CLIENT *, int, char *); +static void clntunix_destroy (CLIENT *); + +static struct clnt_ops unix_ops = +{ + clntunix_call, + clntunix_abort, + clntunix_geterr, + clntunix_freeres, + clntunix_destroy, + clntunix_control +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +libc_hidden_proto(clntunix_create) +CLIENT * +clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + struct rpc_msg call_msg; + int len; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clntunix_create: out of memory\n")); + else +#endif + (void) fputs (_("clntunix_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = socket (AF_UNIX, SOCK_STREAM, 0); + len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1; + if (*sockp < 0 + || connect (*sockp, (struct sockaddr *) raddr, len) < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp != -1) + close (*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } + else + { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); + if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) + { + if (ct->ct_closeit) + close (*sockp); + goto fooy; + } + ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); + XDR_DESTROY (&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t) ct, readunix, writeunix); + h->cl_ops = &unix_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create (); + return h; + +fooy: + /* + * Something goofed, free stuff and barf + */ + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return (CLIENT *) NULL; +} +libc_hidden_def(clntunix_create) + +static enum clnt_stat +clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) + CLIENT *h; + u_long proc; + xdrproc_t xdr_args; + caddr_t args_ptr; + xdrproc_t xdr_results; + caddr_t results_ptr; + struct timeval timeout; +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return ct->ct_error.re_status; + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0) + return ct->ct_error.re_status = RPC_TIMEDOUT; + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) + { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + if (!xdrrec_skiprecord (xdrs)) + return ct->ct_error.re_status; + /* now decode and validate the response header */ + if (!xdr_replymsg (xdrs, &reply_msg)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return ct->ct_error.re_status; + } + if (reply_msg.rm_xid == x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clntunix_geterr (CLIENT *h, struct rpc_err *errp) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clntunix_freeres (cl, xdr_res, res_ptr) + CLIENT *cl; + xdrproc_t xdr_res; + caddr_t res_ptr; +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntunix_abort () +{ +} + +static bool_t +clntunix_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + ct->ct_wait = *(struct timeval *) info; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_un *) info = ct->ct_addr; + break; + case CLGET_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1); + /* decrement by 1 as clntunix_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl (*(u_long *) info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *) info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clntunix_destroy (CLIENT *h) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) + { + (void) close (ct->ct_sock); + } + XDR_DESTROY (&(ct->ct_xdrs)); + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); +} + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; +#ifdef SCM_CREDENTIALS + static char cm[CMSG_SPACE(sizeof (struct ucred))]; +#endif + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred)); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred))); + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = getpid (); + cred.uid = geteuid (); + cred.gid = getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + + +/* + * Interface between xdr serializer and unix connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readunix (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *) ctptr; + struct pollfd fd; + int milliseconds = ((ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000)); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (poll (&fd, 1, milliseconds)) + { + case 0: + ct->ct_error.re_status = RPC_TIMEDOUT; + return -1; + + case -1: + if (errno == EINTR) + continue; + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = errno; + return -1; + } + break; + } + switch (len = __msgread (ct->ct_sock, buf, len)) + { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return len; +} + +static int +writeunix (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data *) ctptr; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1) + { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return -1; + } + } + return len; +} diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c new file mode 100644 index 0000000..e3ee479 --- /dev/null +++ b/libc/inet/rpc/create_xid.c @@ -0,0 +1,62 @@ +/* Copyright (c) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +libc_hidden_proto(lrand48_r) +libc_hidden_proto(srand48_r) +libc_hidden_proto(gettimeofday) + +/* The RPC code is not threadsafe, but new code should be threadsafe. */ + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +static smallint is_initialized; +static struct drand48_data __rpc_lrand48_data; + +u_long _create_xid (void) attribute_hidden; +u_long _create_xid (void) +{ + unsigned long res; + + __UCLIBC_MUTEX_LOCK(mylock); + + if (!is_initialized) + { + struct timeval now; + + gettimeofday (&now, (struct timezone *) 0); + srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); + is_initialized = 1; + } + + lrand48_r (&__rpc_lrand48_data, &res); + + __UCLIBC_MUTEX_UNLOCK(mylock); + + return res; +} diff --git a/libc/inet/rpc/errqueue.h b/libc/inet/rpc/errqueue.h new file mode 100644 index 0000000..9ed6dc6 --- /dev/null +++ b/libc/inet/rpc/errqueue.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux version. */ + +#ifndef _BITS_ERRQUEUE_H +#define _BITS_ERRQUEUE_H 1 + +#include +#include + +struct sock_extended_err + { + u_int32_t ee_errno; + u_int8_t ee_origin; + u_int8_t ee_type; + u_int8_t ee_code; + u_int8_t ee_pad; + u_int32_t ee_info; + u_int32_t ee_data; + }; + +#define SO_EE_ORIGIN_NONE 0 +#define SO_EE_ORIGIN_LOCAL 1 +#define SO_EE_ORIGIN_ICMP 2 +#define SO_EE_ORIGIN_ICMP6 3 + +#define SO_EE_OFFENDER(see) \ + ((struct sockaddr *)(((struct sock_extended_err)(see))+1)) + +#endif /* bits/errqueue.h */ diff --git a/libc/inet/rpc/get_myaddress.c b/libc/inet/rpc/get_myaddress.c new file mode 100644 index 0000000..a6ba078 --- /dev/null +++ b/libc/inet/rpc/get_myaddress.c @@ -0,0 +1,114 @@ +/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * get_myaddress.c + * + * Get client's IP address via ioctl. This avoids using the yellowpages. + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +/* Order of following two #includes reversed by roland@gnu */ +#include +#include + +libc_hidden_proto(ioctl) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(perror) +libc_hidden_proto(exit) + +/* + * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces. We return information from a loopback + * interface only if there are no other possible interfaces. + */ +void +get_myaddress (struct sockaddr_in *addr) +{ + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + int len, loopback = 0; + + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror ("get_myaddress: socket"); + exit (1); + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("get_myaddress: ioctl (get interface configuration)")); + exit (1); + } + + again: + ifr = ifc.ifc_req; + for (len = ifc.ifc_len; len; len -= sizeof ifreq) + { + ifreq = *ifr; + if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror ("get_myaddress: ioctl"); + exit (1); + } + if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET) + && (!(ifreq.ifr_flags & IFF_LOOPBACK) || + (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK)))) + { + *addr = *((struct sockaddr_in *) &ifr->ifr_addr); + addr->sin_port = htons (PMAPPORT); + close (s); + return; + } + ifr++; + } + if (loopback == 0) + { + loopback = 1; + goto again; + } + close (s); +} diff --git a/libc/inet/rpc/getrpcent.c b/libc/inet/rpc/getrpcent.c new file mode 100644 index 0000000..186bd13 --- /dev/null +++ b/libc/inet/rpc/getrpcent.c @@ -0,0 +1,362 @@ +/* @(#)getrpcent.c 2.2 88/07/29 4.0 RPCSRC */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1985 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(atoi) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets) + +/* + * Internet version. + */ +static struct rpcdata { + FILE *rpcf; + char *current; + int currentlen; + int stayopen; +#define MAXALIASES 35 + char *rpc_aliases[MAXALIASES]; + struct rpcent rpc; + char line[BUFSIZ + 1]; + char *domain; +} *rpcdata; + +static char RPCDB[] = "/etc/rpc"; + +static struct rpcdata *_rpcdata(void) +{ + register struct rpcdata *d = rpcdata; + + if (d == NULL) { + d = (struct rpcdata *) calloc(1, sizeof(struct rpcdata)); + + rpcdata = d; + } + return d; +} + +libc_hidden_proto(endrpcent) +void endrpcent(void) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return; + if (d->stayopen) + return; + free(d->current); + d->current = NULL; + if (d->rpcf) { + fclose(d->rpcf); + d->rpcf = NULL; + } +} +libc_hidden_def(endrpcent) + +libc_hidden_proto(setrpcent) +void setrpcent(int f) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return; + if (d->rpcf == NULL) + d->rpcf = fopen(RPCDB, "r"); + else + rewind(d->rpcf); + free(d->current); + d->current = NULL; + d->stayopen |= f; +} +libc_hidden_def(setrpcent) + +static struct rpcent *interpret(struct rpcdata *); + +static struct rpcent *__get_next_rpcent(struct rpcdata *d) +{ + if (fgets(d->line, BUFSIZ, d->rpcf) == NULL) + return NULL; + return interpret(d); +} + +libc_hidden_proto(getrpcent) +struct rpcent *getrpcent(void) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return NULL; + if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL) + return NULL; + return __get_next_rpcent(d); +} +libc_hidden_def(getrpcent) + +libc_hidden_proto(getrpcbynumber) +struct rpcent *getrpcbynumber(register int number) +{ + register struct rpcdata *d = _rpcdata(); + register struct rpcent *rpc; + + if (d == NULL) + return NULL; + setrpcent(0); + while ((rpc = getrpcent())) { + if (rpc->r_number == number) + break; + } + endrpcent(); + return rpc; +} +libc_hidden_def(getrpcbynumber) + +libc_hidden_proto(getrpcbyname) +struct rpcent *getrpcbyname(const char *name) +{ + struct rpcent *rpc; + char **rp; + + setrpcent(0); + while ((rpc = getrpcent())) { + if (strcmp(rpc->r_name, name) == 0) + return rpc; + for (rp = rpc->r_aliases; *rp != NULL; rp++) { + if (strcmp(*rp, name) == 0) + return rpc; + } + } + endrpcent(); + return NULL; +} +libc_hidden_def(getrpcbyname) + +#ifdef __linux__ +static char *firstwhite(char *s) +{ + char *s1, *s2; + + s1 = strchr(s, ' '); + s2 = strchr(s, '\t'); + if (s1) { + if (s2) + return (s1 < s2) ? s1 : s2; + else + return s1; + } else + return s2; +} +#endif + +static struct rpcent *interpret(register struct rpcdata *d) +{ + char *p; + register char *cp, **q; + + p = d->line; + d->line[strlen(p)-1] = '\n'; + if (*p == '#') + return __get_next_rpcent(d); + cp = strchr(p, '#'); + if (cp == NULL) { + cp = strchr(p, '\n'); + if (cp == NULL) + return __get_next_rpcent(d); + } + *cp = '\0'; +#ifdef __linux__ + if ((cp = firstwhite(p))) + *cp++ = 0; + else + return __get_next_rpcent(d); +#else + cp = strchr(p, ' '); + if (cp == NULL) { + cp = strchr(p, '\t'); + if (cp == NULL) + return __get_next_rpcent(d); + } + *cp++ = '\0'; +#endif + /* THIS STUFF IS INTERNET SPECIFIC */ + d->rpc.r_name = d->line; + while (*cp == ' ' || *cp == '\t') + cp++; + d->rpc.r_number = atoi(cp); + q = d->rpc.r_aliases = d->rpc_aliases; +#ifdef __linux__ + if ((cp = firstwhite(cp))) + *cp++ = '\0'; +#else + cp = strchr(p, ' '); + if (cp != NULL) + *cp++ = '\0'; + else { + cp = strchr(p, '\t'); + if (cp != NULL) + *cp++ = '\0'; + } +#endif + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &(d->rpc_aliases[MAXALIASES - 1])) + *q++ = cp; +#ifdef __linux__ + if ((cp = firstwhite(cp))) + *cp++ = '\0'; +#else + cp = strchr(p, ' '); + if (cp != NULL) + *cp++ = '\0'; + else { + cp = strchr(p, '\t'); + if (cp != NULL) + *cp++ = '\0'; + } +#endif + } + *q = NULL; + return &d->rpc; +} + +#if defined(__UCLIBC_HAS_REENTRANT_RPC__) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +static int __copy_rpcent(struct rpcent *r, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + size_t i, s; + + *result = NULL; + + if (!r) + return ENOENT; + + /* copy the struct from the shared mem */ + memset(result_buf, 0x00, sizeof(*result_buf)); + memset(buffer, 0x00, buflen); + + result_buf->r_number = r->r_number; + + /* copy the aliases ... need to not only copy the alias strings, + * but the array of pointers to the alias strings */ + i = 0; + while (r->r_aliases[i++]) ; + + s = i-- * sizeof(char*); + if (buflen < s) + goto err_out; + result_buf->r_aliases = (char**)buffer; + buffer += s; + buflen -= s; + + while (i-- > 0) { + s = strlen(r->r_aliases[i]) + 1; + if (buflen < s) + goto err_out; + result_buf->r_aliases[i] = buffer; + buffer += s; + buflen -= s; + memcpy(result_buf->r_aliases[i], r->r_aliases[i], s); + } + + /* copy the name */ + i = strlen(r->r_name); + if (buflen <= i) + goto err_out; + result_buf->r_name = buffer; + memcpy(result_buf->r_name, r->r_name, i); + + /* that was a hoot eh ? */ + *result = result_buf; + + return 0; +err_out: + return ERANGE; +} + +int getrpcbynumber_r(int number, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcbynumber(number), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +int getrpcbyname_r(const char *name, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcbyname(name), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +int getrpcent_r(struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcent(), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ diff --git a/libc/inet/rpc/getrpcport.c b/libc/inet/rpc/getrpcport.c new file mode 100644 index 0000000..0a57d1d --- /dev/null +++ b/libc/inet/rpc/getrpcport.c @@ -0,0 +1,81 @@ +/* @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI"; +#endif + +/* + * Copyright (c) 1985 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(pmap_getport) +libc_hidden_proto(gethostbyname_r) + +int +getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto) +{ + struct sockaddr_in addr; + struct hostent hostbuf, *hp; + size_t buflen; + char *buffer; + int herr; + + buflen = 1024; + buffer = alloca (buflen); + while (gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + return 0; + else + { + /* Enlarge the buffer. */ + buflen *= 2; + buffer = alloca (buflen); + } + + memcpy ((char *) &addr.sin_addr, hp->h_addr, hp->h_length); + addr.sin_family = AF_INET; + addr.sin_port = 0; + return pmap_getport (&addr, prognum, versnum, proto); +} diff --git a/libc/inet/rpc/pm_getmaps.c b/libc/inet/rpc/pm_getmaps.c new file mode 100644 index 0000000..1760adf --- /dev/null +++ b/libc/inet/rpc/pm_getmaps.c @@ -0,0 +1,89 @@ +/* @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_getmap.c + * Client interface to pmap rpc service. + * contains pmap_getmaps, which is only tcp service involved + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(clnt_perror) +libc_hidden_proto(clnttcp_create) +libc_hidden_proto(xdr_pmap) +libc_hidden_proto(xdr_pmaplist) +libc_hidden_proto(xdr_void) + +/* + * Get a copy of the current port maps. + * Calls the pmap service remotely to do get the maps. + */ +struct pmaplist * +pmap_getmaps (struct sockaddr_in *address) +{ + struct pmaplist *head = (struct pmaplist *) NULL; + int _socket = -1; + struct timeval minutetimeout; + CLIENT *client; + + minutetimeout.tv_sec = 60; + minutetimeout.tv_usec = 0; + address->sin_port = htons (PMAPPORT); + + /* Don't need a reserved port to get ports from the portmapper. */ + client = clnttcp_create (address, PMAPPROG, + PMAPVERS, &_socket, 50, 500); + if (client != (CLIENT *) NULL) + { + if (CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_pmaplist, (caddr_t)&head, + minutetimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("pmap_getmaps rpc problem")); + } + CLNT_DESTROY (client); + } + /* (void)__close(_socket); CLNT_DESTROY already closed it */ + address->sin_port = 0; + return head; +} diff --git a/libc/inet/rpc/pm_getport.c b/libc/inet/rpc/pm_getport.c new file mode 100644 index 0000000..327fb91 --- /dev/null +++ b/libc/inet/rpc/pm_getport.c @@ -0,0 +1,102 @@ +/* @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_getport.c + * Client interface to pmap rpc service. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(clntudp_bufcreate) +libc_hidden_proto(__rpc_thread_createerr) +libc_hidden_proto(xdr_u_short) +libc_hidden_proto(xdr_pmap) + +static const struct timeval timeout = +{5, 0}; +static const struct timeval tottimeout = +{60, 0}; + +/* + * Find the mapped port for program,version. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +libc_hidden_proto(pmap_getport) +u_short +pmap_getport (address, program, version, protocol) + struct sockaddr_in *address; + u_long program; + u_long version; + u_int protocol; +{ + u_short port = 0; + int _socket = -1; + CLIENT *client; + struct pmap parms; + + address->sin_port = htons (PMAPPORT); + client = clntudp_bufcreate (address, PMAPPROG, + PMAPVERS, timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != (CLIENT *) NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = 0; /* not needed or used */ + if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, + (caddr_t)&parms, (xdrproc_t)xdr_u_short, + (caddr_t)&port, tottimeout) != RPC_SUCCESS) + { + ce->cf_stat = RPC_PMAPFAILURE; + clnt_geterr (client, &ce->cf_error); + } + else if (port == 0) + { + ce->cf_stat = RPC_PROGNOTREGISTERED; + } + CLNT_DESTROY (client); + } + /* (void)__close(_socket); CLNT_DESTROY already closed it */ + address->sin_port = 0; + return port; +} +libc_hidden_def(pmap_getport) diff --git a/libc/inet/rpc/pmap_clnt.c b/libc/inet/rpc/pmap_clnt.c new file mode 100644 index 0000000..8ac41f2 --- /dev/null +++ b/libc/inet/rpc/pmap_clnt.c @@ -0,0 +1,187 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * pmap_clnt.c + * Client interface to pmap rpc service. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(ioctl) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(perror) +libc_hidden_proto(exit) +libc_hidden_proto(clnt_perror) +libc_hidden_proto(clntudp_bufcreate) +libc_hidden_proto(xdr_bool) +libc_hidden_proto(xdr_pmap) + +/* + * Same as get_myaddress, but we try to use the loopback + * interface. portmap caches interfaces, and on DHCP clients, + * it could be that only loopback is started at this time. + */ +static bool_t +__get_myaddress (struct sockaddr_in *addr) +{ + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + int len, loopback = 1; + + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror ("__get_myaddress: socket"); + exit (1); + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("__get_myaddress: ioctl (get interface configuration)")); + exit (1); + } + + again: + ifr = ifc.ifc_req; + for (len = ifc.ifc_len; len; len -= sizeof ifreq) + { + ifreq = *ifr; + if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror ("__get_myaddress: ioctl"); + exit (1); + } + if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET) + && ((ifreq.ifr_flags & IFF_LOOPBACK) || (loopback == 0))) + { + *addr = *((struct sockaddr_in *) &ifr->ifr_addr); + addr->sin_port = htons (PMAPPORT); + close (s); + return TRUE; + } + ifr++; + } + if (loopback == 1) + { + loopback = 0; + goto again; + } + close (s); + return FALSE; +} + + +static const struct timeval timeout = {5, 0}; +static const struct timeval tottimeout = {60, 0}; + +/* + * Set a mapping between program,version and port. + * Calls the pmap service remotely to do the mapping. + */ +libc_hidden_proto(pmap_set) +bool_t +pmap_set (u_long program, u_long version, int protocol, u_short port) +{ + struct sockaddr_in myaddress; + int _socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, + timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client == (CLIENT *) NULL) + return (FALSE); + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = port; + if (CLNT_CALL (client, PMAPPROC_SET, (xdrproc_t)xdr_pmap, (caddr_t)&parms, + (xdrproc_t)xdr_bool, (caddr_t)&rslt, + tottimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("Cannot register service")); + rslt = FALSE; + } + CLNT_DESTROY (client); + /* (void)close(_socket); CLNT_DESTROY closes it */ + return rslt; +} +libc_hidden_def (pmap_set) + +/* + * Remove the mapping between program,version and port. + * Calls the pmap service remotely to do the un-mapping. + */ +libc_hidden_proto(pmap_unset) +bool_t +pmap_unset (u_long program, u_long version) +{ + struct sockaddr_in myaddress; + int _socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, + timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client == (CLIENT *) NULL) + return FALSE; + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_port = parms.pm_prot = 0; + CLNT_CALL (client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap, (caddr_t)&parms, + (xdrproc_t)xdr_bool, (caddr_t)&rslt, tottimeout); + CLNT_DESTROY (client); + /* (void)close(_socket); CLNT_DESTROY already closed it */ + return rslt; +} +libc_hidden_def (pmap_unset) diff --git a/libc/inet/rpc/pmap_prot.c b/libc/inet/rpc/pmap_prot.c new file mode 100644 index 0000000..0ae2c88 --- /dev/null +++ b/libc/inet/rpc/pmap_prot.c @@ -0,0 +1,60 @@ +/* @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_prot.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +libc_hidden_proto(xdr_u_long) + +libc_hidden_proto(xdr_pmap) +bool_t +xdr_pmap (xdrs, regs) + XDR *xdrs; + struct pmap *regs; +{ + + if (xdr_u_long (xdrs, ®s->pm_prog) && + xdr_u_long (xdrs, ®s->pm_vers) && + xdr_u_long (xdrs, ®s->pm_prot)) + return xdr_u_long (xdrs, ®s->pm_port); + return FALSE; +} +libc_hidden_def(xdr_pmap) diff --git a/libc/inet/rpc/pmap_prot2.c b/libc/inet/rpc/pmap_prot2.c new file mode 100644 index 0000000..5adc4ee --- /dev/null +++ b/libc/inet/rpc/pmap_prot2.c @@ -0,0 +1,123 @@ +/* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_prot2.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +libc_hidden_proto(xdr_bool) +libc_hidden_proto(xdr_reference) +libc_hidden_proto(xdr_pmap) + +/* + * What is going on with linked lists? (!) + * First recall the link list declaration from pmap_prot.h: + * + * struct pmaplist { + * struct pmap pml_map; + * struct pmaplist *pml_map; + * }; + * + * Compare that declaration with a corresponding xdr declaration that + * is (a) pointer-less, and (b) recursive: + * + * typedef union switch (bool_t) { + * + * case TRUE: struct { + * struct pmap; + * pmaplist_t foo; + * }; + * + * case FALSE: struct {}; + * } pmaplist_t; + * + * Notice that the xdr declaration has no nxt pointer while + * the C declaration has no bool_t variable. The bool_t can be + * interpreted as ``more data follows me''; if FALSE then nothing + * follows this bool_t; if TRUE then the bool_t is followed by + * an actual struct pmap, and then (recursively) by the + * xdr union, pamplist_t. + * + * This could be implemented via the xdr_union primitive, though this + * would cause a one recursive call per element in the list. Rather than do + * that we can ``unwind'' the recursion + * into a while loop and do the union arms in-place. + * + * The head of the list is what the C programmer wishes to past around + * the net, yet is the data that the pointer points to which is interesting; + * this sounds like a job for xdr_reference! + */ +libc_hidden_proto(xdr_pmaplist) +bool_t +xdr_pmaplist (xdrs, rp) + XDR *xdrs; + struct pmaplist **rp; +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + int freeing = (xdrs->x_op == XDR_FREE); + struct pmaplist **next = NULL; + + while (TRUE) + { + more_elements = (bool_t) (*rp != NULL); + if (!xdr_bool (xdrs, &more_elements)) + return FALSE; + if (!more_elements) + return TRUE; /* we are done */ + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing) + next = &((*rp)->pml_next); + if (!xdr_reference (xdrs, (caddr_t *) rp, + (u_int) sizeof (struct pmaplist), + (xdrproc_t) xdr_pmap)) + return FALSE; + rp = freeing ? next : &((*rp)->pml_next); + } +} +libc_hidden_def(xdr_pmaplist) diff --git a/libc/inet/rpc/pmap_rmt.c b/libc/inet/rpc/pmap_rmt.c new file mode 100644 index 0000000..759534a --- /dev/null +++ b/libc/inet/rpc/pmap_rmt.c @@ -0,0 +1,440 @@ +/* @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_rmt.c + * Client interface to pmap rpc service. + * remote call and broadcast service + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef _POSIX_SOURCE /* Ultrix needs --roland@gnu */ +#include /* Ultrix needs before net/if --roland@gnu */ +#include +#include +#include +#define MAX_BROADCAST_SIZE 1400 + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(ioctl) +libc_hidden_proto(perror) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(authunix_create_default) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_callmsg) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xdr_reference) +libc_hidden_proto(xdr_u_long) +libc_hidden_proto(xdr_void) +libc_hidden_proto(xdr_rmtcallres) +libc_hidden_proto(xdr_rmtcall_args) +libc_hidden_proto(inet_makeaddr) +libc_hidden_proto(inet_netof) +libc_hidden_proto(clntudp_create) +libc_hidden_proto(setsockopt) +libc_hidden_proto(recvfrom) +libc_hidden_proto(sendto) +libc_hidden_proto(poll) +libc_hidden_proto(fprintf) + + +extern u_long _create_xid (void) attribute_hidden; + +static const struct timeval timeout = {3, 0}; + +/* + * pmapper remote-call-service interface. + * This routine is used to call the pmapper remote call service + * which will look up a service program in the port maps, and then + * remotely call that routine with the given parameters. This allows + * programs to do a lookup and call in one step. + */ +enum clnt_stat +pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) + struct sockaddr_in *addr; + u_long prog, vers, proc; + xdrproc_t xdrargs, xdrres; + caddr_t argsp, resp; + struct timeval tout; + u_long *port_ptr; +{ + int _socket = -1; + CLIENT *client; + struct rmtcallargs a; + struct rmtcallres r; + enum clnt_stat stat; + + addr->sin_port = htons (PMAPPORT); + client = clntudp_create (addr, PMAPPROG, PMAPVERS, timeout, &_socket); + if (client != (CLIENT *) NULL) + { + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.args_ptr = argsp; + a.xdr_args = xdrargs; + r.port_ptr = port_ptr; + r.results_ptr = resp; + r.xdr_results = xdrres; + stat = CLNT_CALL (client, PMAPPROC_CALLIT, (xdrproc_t)xdr_rmtcall_args, + (caddr_t)&a, (xdrproc_t)xdr_rmtcallres, + (caddr_t)&r, tout); + CLNT_DESTROY (client); + } + else + { + stat = RPC_FAILED; + } + /* (void)close(_socket); CLNT_DESTROY already closed it */ + addr->sin_port = 0; + return stat; +} + + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rmtcall_args (XDR *xdrs, struct rmtcallargs *cap) +{ + u_int lenposition, argposition, position; + + if (xdr_u_long (xdrs, &(cap->prog)) && + xdr_u_long (xdrs, &(cap->vers)) && + xdr_u_long (xdrs, &(cap->proc))) + { + u_long dummy_arglen = 0; + lenposition = XDR_GETPOS (xdrs); + if (!xdr_u_long (xdrs, &dummy_arglen)) + return FALSE; + argposition = XDR_GETPOS (xdrs); + if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr)) + return FALSE; + position = XDR_GETPOS (xdrs); + cap->arglen = (u_long) position - (u_long) argposition; + XDR_SETPOS (xdrs, lenposition); + if (!xdr_u_long (xdrs, &(cap->arglen))) + return FALSE; + XDR_SETPOS (xdrs, position); + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_rmtcall_args) + +/* + * XDR remote call results + * written for XDR_DECODE direction only + */ +bool_t +xdr_rmtcallres (xdrs, crp) + XDR *xdrs; + struct rmtcallres *crp; +{ + caddr_t port_ptr; + + port_ptr = (caddr_t) crp->port_ptr; + if (xdr_reference (xdrs, &port_ptr, sizeof (u_long), (xdrproc_t) xdr_u_long) + && xdr_u_long (xdrs, &crp->resultslen)) + { + crp->port_ptr = (u_long *) port_ptr; + return (*(crp->xdr_results)) (xdrs, crp->results_ptr); + } + return FALSE; +} +libc_hidden_def(xdr_rmtcallres) + + +/* + * The following is kludged-up support for simple rpc broadcasts. + * Someday a large, complicated system will replace these trivial + * routines which only support udp/ip . + */ + +static int +internal_function +getbroadcastnets (struct in_addr *addrs, int sock, char *buf) + /* int sock: any valid socket will do */ + /* char *buf: why allocate more when we can use existing... */ +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct sockaddr_in *sin; + int n, i; + + ifc.ifc_len = UDPMSGSIZE; + ifc.ifc_buf = buf; + if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("broadcast: ioctl (get interface configuration)")); + return (0); + } + ifr = ifc.ifc_req; + for (i = 0, n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) + { + ifreq = *ifr; + if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror (_("broadcast: ioctl (get interface flags)")); + continue; + } + if ((ifreq.ifr_flags & IFF_BROADCAST) && + (ifreq.ifr_flags & IFF_UP) && + ifr->ifr_addr.sa_family == AF_INET) + { + sin = (struct sockaddr_in *) &ifr->ifr_addr; +#ifdef SIOCGIFBRDADDR /* 4.3BSD */ + if (ioctl (sock, SIOCGIFBRDADDR, (char *) &ifreq) < 0) + { + addrs[i++] = inet_makeaddr (inet_netof + /* Changed to pass struct instead of s_addr member + by roland@gnu. */ + (sin->sin_addr), INADDR_ANY); + } + else + { + addrs[i++] = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr; + } +#else /* 4.2 BSD */ + addrs[i++] = inet_makeaddr (inet_netof + (sin->sin_addr.s_addr), INADDR_ANY); +#endif + } + } + return i; +} + + +enum clnt_stat +clnt_broadcast (prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) + u_long prog; /* program number */ + u_long vers; /* version number */ + u_long proc; /* procedure number */ + xdrproc_t xargs; /* xdr routine for args */ + caddr_t argsp; /* pointer to args */ + xdrproc_t xresults; /* xdr routine for results */ + caddr_t resultsp; /* pointer to results */ + resultproc_t eachresult; /* call with each result obtained */ +{ + enum clnt_stat stat = RPC_FAILED; + AUTH *unix_auth = authunix_create_default (); + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + struct timeval t; + int outlen, inlen, nets; + socklen_t fromlen; + int sock; + int on = 1; + struct pollfd fd; + int milliseconds; + int i; + bool_t done = FALSE; + u_long xid; + u_long port; + struct in_addr addrs[20]; + struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ + struct rmtcallargs a; + struct rmtcallres r; + struct rpc_msg msg; + char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; + + /* + * initialization: create a socket, a broadcast address, and + * preserialize the arguments into a send buffer. + */ + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("Cannot create socket for broadcast rpc")); + stat = RPC_CANTSEND; + goto done_broad; + } +#ifdef SO_BROADCAST + if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) + { + perror (_("Cannot set socket option SO_BROADCAST")); + stat = RPC_CANTSEND; + goto done_broad; + } +#endif /* def SO_BROADCAST */ + fd.fd = sock; + fd.events = POLLIN; + nets = getbroadcastnets (addrs, sock, inbuf); + memset ((char *) &baddr, 0, sizeof (baddr)); + baddr.sin_family = AF_INET; + baddr.sin_port = htons (PMAPPORT); + baddr.sin_addr.s_addr = htonl (INADDR_ANY); +/* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */ + msg.rm_xid = xid = _create_xid (); + t.tv_usec = 0; + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = PMAPPROG; + msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_proc = PMAPPROC_CALLIT; + msg.rm_call.cb_cred = unix_auth->ah_cred; + msg.rm_call.cb_verf = unix_auth->ah_verf; + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.xdr_args = xargs; + a.args_ptr = argsp; + r.port_ptr = &port; + r.xdr_results = xresults; + r.results_ptr = resultsp; + xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); + if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a))) + { + stat = RPC_CANTENCODEARGS; + goto done_broad; + } + outlen = (int) xdr_getpos (xdrs); + xdr_destroy (xdrs); + /* + * Basic loop: broadcast a packet and wait a while for response(s). + * The response timeout grows larger per iteration. + */ + for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) + { + for (i = 0; i < nets; i++) + { + baddr.sin_addr = addrs[i]; + if (sendto (sock, outbuf, outlen, 0, + (struct sockaddr *) &baddr, + sizeof (struct sockaddr)) != outlen) + { + perror (_("Cannot send broadcast packet")); + stat = RPC_CANTSEND; + goto done_broad; + } + } + if (eachresult == NULL) + { + stat = RPC_SUCCESS; + goto done_broad; + } + recv_again: + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = (caddr_t) & r; + msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres; + milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000; + switch (poll(&fd, 1, milliseconds)) + { + + case 0: /* timed out */ + stat = RPC_TIMEDOUT; + continue; + + case -1: /* some kind of error */ + if (errno == EINTR) + goto recv_again; + perror (_("Broadcast poll problem")); + stat = RPC_CANTRECV; + goto done_broad; + + } /* end of poll results switch */ + try_again: + fromlen = sizeof (struct sockaddr); + inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0, + (struct sockaddr *) &raddr, &fromlen); + if (inlen < 0) + { + if (errno == EINTR) + goto try_again; + perror (_("Cannot receive reply to broadcast")); + stat = RPC_CANTRECV; + goto done_broad; + } + if ((size_t) inlen < sizeof (u_long)) + goto recv_again; + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE); + if (xdr_replymsg (xdrs, &msg)) + { + if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) && + (msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) + { + raddr.sin_port = htons ((u_short) port); + done = (*eachresult) (resultsp, &raddr); + } + /* otherwise, we just ignore the errors ... */ + } + else + { +#ifdef notdef + /* some kind of deserialization problem ... */ + if ((u_int32_t) msg.rm_xid == (u_int32_t) xid) + fprintf (stderr, "Broadcast deserialization problem"); + /* otherwise, just random garbage */ +#endif + } + xdrs->x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + (void) xdr_replymsg (xdrs, &msg); + (void) (*xresults) (xdrs, resultsp); + xdr_destroy (xdrs); + if (done) + { + stat = RPC_SUCCESS; + goto done_broad; + } + else + { + goto recv_again; + } + } +done_broad: + (void) close (sock); + AUTH_DESTROY (unix_auth); + return stat; +} diff --git a/libc/inet/rpc/rcmd.c b/libc/inet/rpc/rcmd.c new file mode 100644 index 0000000..cd8d620 --- /dev/null +++ b/libc/inet/rpc/rcmd.c @@ -0,0 +1,782 @@ +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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 project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. + */ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; +#endif /* LIBC_SCCS and not lint */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif +#include + +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +/* Experimentally off - libc_hidden_proto(memmove) */ +libc_hidden_proto(getpid) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(fcntl) +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(perror) +libc_hidden_proto(lstat) +libc_hidden_proto(fstat) +libc_hidden_proto(tolower) +libc_hidden_proto(sysconf) +libc_hidden_proto(getline) +libc_hidden_proto(geteuid) +libc_hidden_proto(seteuid) +libc_hidden_proto(getpwnam_r) +libc_hidden_proto(gethostbyname) +libc_hidden_proto(gethostbyname_r) +libc_hidden_proto(fileno) +libc_hidden_proto(sleep) +libc_hidden_proto(inet_addr) +libc_hidden_proto(inet_ntoa) +libc_hidden_proto(herror) +libc_hidden_proto(bind) +libc_hidden_proto(connect) +libc_hidden_proto(sigblock) +libc_hidden_proto(snprintf) +libc_hidden_proto(poll) +libc_hidden_proto(accept) +libc_hidden_proto(listen) +libc_hidden_proto(sigsetmask) +libc_hidden_proto(getc_unlocked) +libc_hidden_proto(__fgetc_unlocked) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(fprintf) +libc_hidden_proto(__h_errno_location) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +libc_hidden_proto(__ctype_tolower_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +#endif + +libc_hidden_proto(rresvport) + +/* some forward declarations */ +static int __ivaliduser2(FILE *hostf, u_int32_t raddr, + const char *luser, const char *ruser, const char *rhost); +static int iruserok2 (u_int32_t raddr, int superuser, const char *ruser, + const char *luser, const char *rhost); + + +int rcmd(ahost, rport, locuser, remuser, cmd, fd2p) + char **ahost; + u_short rport; + const char *locuser, *remuser, *cmd; + int *fd2p; +{ +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + int herr; + struct hostent hostbuf; + size_t hstbuflen; + char *tmphstbuf; +#endif + struct hostent *hp; + struct sockaddr_in sin, from; + struct pollfd pfd[2]; + int32_t oldmask; + pid_t pid; + int s, lport, timo; + char c; + + pid = getpid(); + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + hstbuflen = 1024; +#ifdef __ARCH_USE_MMU__ + tmphstbuf = alloca (hstbuflen); +#else + tmphstbuf = malloc (hstbuflen); +#endif + + while (gethostbyname_r (*ahost, &hostbuf, tmphstbuf, + hstbuflen, &hp, &herr) != 0 || hp == NULL) + { + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + __set_h_errno (herr); +#ifndef __ARCH_USE_MMU__ + free(tmphstbuf); +#endif + herror(*ahost); + return -1; + } + else + { + /* Enlarge the buffer. */ + hstbuflen *= 2; +#ifdef __ARCH_USE_MMU__ + tmphstbuf = alloca (hstbuflen); +#else + free(tmphstbuf); + tmphstbuf = malloc (hstbuflen); +#endif + } + } +#ifndef __ARCH_USE_MMU__ + free(tmphstbuf); +#endif +#else /* call the non-reentrant version */ + if ((hp = gethostbyname(*ahost)) == NULL) { + return -1; + } +#endif + pfd[0].events = POLLIN; + pfd[1].events = POLLIN; + + *ahost = hp->h_name; + oldmask = sigblock(sigmask(SIGURG)); /* __sigblock */ + for (timo = 1, lport = IPPORT_RESERVED - 1;;) { + s = rresvport(&lport); + if (s < 0) { + if (errno == EAGAIN) + (void)fprintf(stderr, + "rcmd: socket: All ports in use\n"); + else + (void)fprintf(stderr, "rcmd: socket: %m\n"); + sigsetmask(oldmask); /* sigsetmask */ + return -1; + } + fcntl(s, F_SETOWN, pid); + sin.sin_family = hp->h_addrtype; + memmove(&sin.sin_addr, hp->h_addr_list[0], + MIN (sizeof (sin.sin_addr), hp->h_length)); + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) /* __connect */ + break; + (void)close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + if (errno == ECONNREFUSED && timo <= 16) { + (void)sleep(timo); /* __sleep */ + timo *= 2; + continue; + } + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + (void)fprintf(stderr, "connect to address %s: ", + inet_ntoa(sin.sin_addr)); + __set_errno (oerrno); + perror(0); + hp->h_addr_list++; + memmove(&sin.sin_addr, hp->h_addr_list[0], + MIN (sizeof (sin.sin_addr), hp->h_length)); + (void)fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } + (void)fprintf(stderr, "%s: %m\n", hp->h_name); + sigsetmask(oldmask); /* __sigsetmask */ + return -1; + } + lport--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = rresvport(&lport), s3; + socklen_t len = sizeof(from); + + if (s2 < 0) + goto bad; + listen(s2, 1); + (void)snprintf(num, sizeof(num), "%d", lport); /* __snprintf */ + if (write(s, num, strlen(num)+1) != strlen(num)+1) { + (void)fprintf(stderr, + "rcmd: write (setting up stderr): %m\n"); + (void)close(s2); + goto bad; + } + pfd[0].fd = s; + pfd[1].fd = s2; + __set_errno (0); + if (poll (pfd, 2, -1) < 1 || (pfd[1].revents & POLLIN) == 0){ + if (errno != 0) + (void)fprintf(stderr, "rcmd: poll (setting up stderr): %m\n"); + else + (void)fprintf(stderr, "poll: protocol failure in circuit setup\n"); + (void)close(s2); + goto bad; + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + (void)close(s2); + if (s3 < 0) { + (void)fprintf(stderr, + "rcmd: accept: %m\n"); + lport = 0; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED || + from.sin_port < IPPORT_RESERVED / 2) { + (void)fprintf(stderr, + "socket: protocol failure in circuit setup\n"); + goto bad2; + } + } + (void)write(s, locuser, strlen(locuser)+1); + (void)write(s, remuser, strlen(remuser)+1); + (void)write(s, cmd, strlen(cmd)+1); + if (read(s, &c, 1) != 1) { + (void)fprintf(stderr, + "rcmd: %s: %m\n", *ahost); + goto bad2; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void)write(STDERR_FILENO, &c, 1); + if (c == '\n') + break; + } + goto bad2; + } + sigsetmask(oldmask); + return s; +bad2: + if (lport) + (void)close(*fd2p); +bad: + (void)close(s); + sigsetmask(oldmask); + return -1; +} + +int rresvport(int *alport) +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return -1; + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + return s; + if (errno != EADDRINUSE) { + (void)close(s); + return -1; + } + (*alport)--; + if (*alport == IPPORT_RESERVED/2) { + (void)close(s); + __set_errno (EAGAIN); /* close */ + return -1; + } + } + + return -1; +} +libc_hidden_def(rresvport) + +/* This needs to be exported ... while it is not a documented interface + * for rcp related apps, it's a required one that is used to control the + * rhost behavior. Legacy sucks. + */ +int __check_rhosts_file = 1; + +int ruserok(rhost, superuser, ruser, luser) + const char *rhost, *ruser, *luser; + int superuser; +{ + struct hostent *hp; + u_int32_t addr; + char **ap; +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + size_t buflen; + char *buffer; + int herr; + struct hostent hostbuf; +#endif + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + buflen = 1024; +#ifdef __ARCH_USE_MMU__ + buffer = alloca (buflen); +#else + buffer = malloc (buflen); +#endif + + while (gethostbyname_r (rhost, &hostbuf, buffer, + buflen, &hp, &herr) != 0 || hp == NULL) + { + if (herr != NETDB_INTERNAL || errno != ERANGE) { +#ifndef __ARCH_USE_MMU__ + free(buffer); +#endif + return -1; + } else + { + /* Enlarge the buffer. */ + buflen *= 2; +#ifdef __ARCH_USE_MMU__ + buffer = alloca (buflen); +#else + free(buffer); + buffer = malloc (buflen); +#endif + } + } +#ifndef __ARCH_USE_MMU__ + free(buffer); +#endif +#else + if ((hp = gethostbyname(rhost)) == NULL) { + return -1; + } +#endif + for (ap = hp->h_addr_list; *ap; ++ap) { + memmove(&addr, *ap, sizeof(addr)); + if (iruserok2(addr, superuser, ruser, luser, rhost) == 0) + return 0; + } + return -1; +} + + +/* Extremely paranoid file open function. */ +static FILE * +iruserfopen (const char *file, uid_t okuser) +{ + struct stat st; + char *cp = NULL; + FILE *res = NULL; + + /* If not a regular file, if owned by someone other than user or + root, if writeable by anyone but the owner, or if hardlinked + anywhere, quit. */ + if (lstat (file, &st)) + cp = "lstat failed"; + else if (!S_ISREG (st.st_mode)) + cp = "not regular file"; + else + { + res = fopen (file, "r"); + if (!res) + cp = "cannot open"; + else if (fstat (fileno (res), &st) < 0) + cp = "fstat failed"; + else if (st.st_uid && st.st_uid != okuser) + cp = "bad owner"; + else if (st.st_mode & (S_IWGRP|S_IWOTH)) + cp = "writeable by other than owner"; + else if (st.st_nlink > 1) + cp = "hard linked somewhere"; + } + + /* If there were any problems, quit. */ + if (cp != NULL) + { + if (res) + fclose (res); + return NULL; + } + + return res; +} + + +/* + * New .rhosts strategy: We are passed an ip address. We spin through + * hosts.equiv and .rhosts looking for a match. When the .rhosts only + * has ip addresses, we don't have to trust a nameserver. When it + * contains hostnames, we spin through the list of addresses the nameserver + * gives us and look for a match. + * + * Returns 0 if ok, -1 if not ok. + */ +static int +iruserok2 (raddr, superuser, ruser, luser, rhost) + u_int32_t raddr; + int superuser; + const char *ruser, *luser, *rhost; +{ + FILE *hostf = NULL; + int isbad = -1; + + if (!superuser) + hostf = iruserfopen (_PATH_HEQUIV, 0); + + if (hostf) { + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); + fclose (hostf); + + if (!isbad) + return 0; + } + + if (__check_rhosts_file || superuser) { + char *pbuf; + struct passwd *pwd; + size_t dirlen; + uid_t uid; + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + struct passwd pwdbuf; +#ifdef __ARCH_USE_MMU__ + char *buffer = alloca (buflen); +#else + char *buffer = malloc (buflen); +#endif + + if (getpwnam_r (luser, &pwdbuf, buffer, + buflen, &pwd) != 0 || pwd == NULL) + { +#ifndef __ARCH_USE_MMU__ + free(buffer); +#endif + return -1; + } +#ifndef __ARCH_USE_MMU__ + free(buffer); +#endif +#else + if ((pwd = getpwnam(luser)) == NULL) + return -1; +#endif + + dirlen = strlen (pwd->pw_dir); + pbuf = malloc (dirlen + sizeof "/.rhosts"); + strcpy (pbuf, pwd->pw_dir); + strcat (pbuf, "/.rhosts"); + + /* Change effective uid while reading .rhosts. If root and + reading an NFS mounted file system, can't read files that + are protected read/write owner only. */ + uid = geteuid (); + seteuid (pwd->pw_uid); + hostf = iruserfopen (pbuf, pwd->pw_uid); + free(pbuf); + + if (hostf != NULL) { + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); + fclose (hostf); + } + + seteuid (uid); + return isbad; + } + return -1; +} + +/* This is the exported version. */ +int iruserok (u_int32_t raddr, int superuser, const char * ruser, const char * luser); +int iruserok (u_int32_t raddr, int superuser, const char * ruser, const char * luser) +{ + return iruserok2 (raddr, superuser, ruser, luser, "-"); +} + + +/* + * XXX + * Don't make static, used by lpd(8). + * + * This function is not used anymore. It is only present because lpd(8) + * calls it (!?!). We simply call __invaliduser2() with an illegal rhost + * argument. This means that netgroups won't work in .rhost/hosts.equiv + * files. If you want lpd to work with netgroups, fix lpd to use ruserok() + * or PAM. + * Returns 0 if ok, -1 if not ok. + */ +int +__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser); +int +__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser) +{ + return __ivaliduser2(hostf, raddr, luser, ruser, "-"); +} + + +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ +static int +__icheckhost (u_int32_t raddr, char *lhost, const char *rhost) +{ + struct hostent *hp; + u_int32_t laddr; + int negate=1; /* Multiply return with this to get -1 instead of 1 */ + char **pp; + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + int save_errno; + size_t buflen; + char *buffer; + struct hostent hostbuf; + int herr; +#endif + +#ifdef HAVE_NETGROUP + /* Check nis netgroup. */ + if (strncmp ("+@", lhost, 2) == 0) + return innetgr (&lhost[2], rhost, NULL, NULL); + + if (strncmp ("-@", lhost, 2) == 0) + return -innetgr (&lhost[2], rhost, NULL, NULL); +#endif /* HAVE_NETGROUP */ + + /* -host */ + if (strncmp ("-", lhost,1) == 0) { + negate = -1; + lhost++; + } else if (strcmp ("+",lhost) == 0) { + return 1; /* asking for trouble, but ok.. */ + } + + /* Try for raw ip address first. */ + if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE) + return negate * (! (raddr ^ laddr)); + + /* Better be a hostname. */ +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + buflen = 1024; + buffer = malloc(buflen); + save_errno = errno; + + while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) + != 0) { + free(buffer); + return (0); + } + free(buffer); + __set_errno (save_errno); +#else + hp = gethostbyname(lhost); +#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ + + if (hp == NULL) + return 0; + + /* Spin through ip addresses. */ + for (pp = hp->h_addr_list; *pp; ++pp) + if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) + return negate; + + /* No match. */ + return (0); +} + +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ +static int +__icheckuser (const char *luser, const char *ruser) +{ + + /* + luser is user entry from .rhosts/hosts.equiv file + ruser is user id on remote host + */ + +#ifdef HAVE_NETGROUP + /* [-+]@netgroup */ + if (strncmp ("+@", luser, 2) == 0) + return innetgr (&luser[2], NULL, ruser, NULL); + + if (strncmp ("-@", luser,2) == 0) + return -innetgr (&luser[2], NULL, ruser, NULL); +#endif /* HAVE_NETGROUP */ + + /* -user */ + if (strncmp ("-", luser, 1) == 0) + return -(strcmp (&luser[1], ruser) == 0); + + /* + */ + if (strcmp ("+", luser) == 0) + return 1; + + /* simple string match */ + return strcmp (ruser, luser) == 0; +} + +/* + * Returns 1 for blank lines (or only comment lines) and 0 otherwise + */ +static int +__isempty(char *p) +{ + while (*p && isspace (*p)) { + ++p; + } + + return (*p == '\0' || *p == '#') ? 1 : 0 ; +} + +/* + * Returns 0 if positive match, -1 if _not_ ok. + */ +static int +__ivaliduser2(hostf, raddr, luser, ruser, rhost) + FILE *hostf; + u_int32_t raddr; + const char *luser, *ruser, *rhost; +{ + register const char *user; + register char *p; + int hcheck, ucheck; + char *buf = NULL; + size_t bufsize = 0; + int retval = -1; + + while (getline (&buf, &bufsize, hostf) > 0) { + buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */ + p = buf; + + /* Skip empty or comment lines */ + if (__isempty (p)) { + continue; + } + + /* Skip lines that are too long. */ + if (strchr (p, '\n') == NULL) { + int ch = getc_unlocked (hostf); + + while (ch != '\n' && ch != EOF) + ch = getc_unlocked (hostf); + continue; + } + + for (;*p && !isspace(*p); ++p) { + *p = tolower (*p); + } + + /* Next we want to find the permitted name for the remote user. */ + if (*p == ' ' || *p == '\t') { + /* terminate hostname and skip spaces */ + for (*p++='\0'; *p && isspace (*p); ++p); + + user = p; /* this is the user's name */ + while (*p && !isspace (*p)) + ++p; /* find end of user's name */ + } else + user = p; + + *p = '\0'; /* terminate username (+host?) */ + + /* buf -> host(?) ; user -> username(?) */ + + /* First check host part */ + hcheck = __icheckhost (raddr, buf, rhost); + + if (hcheck < 0) + break; + + if (hcheck) { + /* Then check user part */ + if (! (*user)) + user = luser; + + ucheck = __icheckuser (user, ruser); + + /* Positive 'host user' match? */ + if (ucheck > 0) { + retval = 0; + break; + } + + /* Negative 'host -user' match? */ + if (ucheck < 0) + break; + + /* Neither, go on looking for match */ + } + } + + free (buf); + + return retval; +} diff --git a/libc/inet/rpc/rexec.c b/libc/inet/rpc/rexec.c new file mode 100644 index 0000000..2eb567e --- /dev/null +++ b/libc/inet/rpc/rexec.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(close) +libc_hidden_proto(socket) +libc_hidden_proto(perror) +libc_hidden_proto(sprintf) +libc_hidden_proto(snprintf) +libc_hidden_proto(getsockname) +libc_hidden_proto(getnameinfo) +libc_hidden_proto(getaddrinfo) +libc_hidden_proto(freeaddrinfo) +libc_hidden_proto(sleep) +libc_hidden_proto(atoi) +libc_hidden_proto(connect) +libc_hidden_proto(accept) +libc_hidden_proto(listen) +libc_hidden_proto(ruserpass) + +#define SA_LEN(_x) __libc_sa_len((_x)->sa_family) +extern int __libc_sa_len (sa_family_t __af) __THROW attribute_hidden; + +int rexecoptions; +char ahostbuf[NI_MAXHOST] attribute_hidden; + +libc_hidden_proto(rexec_af) +int +rexec_af(char **ahost, int rport, const char *name, const char *pass, const char *cmd, int *fd2p, sa_family_t af) +{ + struct sockaddr_storage sa2, from; + struct addrinfo hints, *res0; + const char *orig_name = name; + const char *orig_pass = pass; + u_short port = 0; + int s, timo = 1, s3; + char c; + int gai; + char servbuff[NI_MAXSERV]; + + snprintf(servbuff, sizeof(servbuff), "%d", ntohs(rport)); + servbuff[sizeof(servbuff) - 1] = '\0'; + + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = af; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + gai = getaddrinfo(*ahost, servbuff, &hints, &res0); + if (gai){ + /* XXX: set errno? */ + return -1; + } + + if (res0->ai_canonname){ + strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf)); + ahostbuf[sizeof(ahostbuf)-1] = '\0'; + *ahost = ahostbuf; + } + else{ + *ahost = NULL; + __set_errno (ENOENT); + return -1; + } + ruserpass(res0->ai_canonname, &name, &pass); +retry: + s = socket(res0->ai_family, res0->ai_socktype, 0); + if (s < 0) { + perror("rexec: socket"); + return (-1); + } + if (connect(s, res0->ai_addr, res0->ai_addrlen) < 0) { + if (errno == ECONNREFUSED && timo <= 16) { + (void) close(s); + sleep(timo); + timo *= 2; + goto retry; + } + perror(res0->ai_canonname); + return (-1); + } + if (fd2p == 0) { + (void) write(s, "", 1); + port = 0; + } else { + char num[32]; + int s2; + socklen_t sa2len; + + s2 = socket(res0->ai_family, res0->ai_socktype, 0); + if (s2 < 0) { + (void) close(s); + return (-1); + } + listen(s2, 1); + sa2len = sizeof (sa2); + if (getsockname(s2, (struct sockaddr *)&sa2, &sa2len) < 0) { + perror("getsockname"); + (void) close(s2); + goto bad; + } else if (sa2len != SA_LEN((struct sockaddr *)&sa2)) { + __set_errno(EINVAL); + (void) close(s2); + goto bad; + } + port = 0; + if (!getnameinfo((struct sockaddr *)&sa2, sa2len, + NULL, 0, servbuff, sizeof(servbuff), + NI_NUMERICSERV)) + port = atoi(servbuff); + (void) sprintf(num, "%u", port); + (void) write(s, num, strlen(num)+1); + { socklen_t len = sizeof (from); + s3 = TEMP_FAILURE_RETRY (accept(s2, (struct sockaddr *)&from, + &len)); + close(s2); + if (s3 < 0) { + perror("accept"); + port = 0; + goto bad; + } + } + *fd2p = s3; + } + (void) write(s, name, strlen(name) + 1); + /* should public key encypt the password here */ + (void) write(s, pass, strlen(pass) + 1); + (void) write(s, cmd, strlen(cmd) + 1); + + /* We don't need the memory allocated for the name and the password + in ruserpass anymore. */ + if (name != orig_name) + free ((char *) name); + if (pass != orig_pass) + free ((char *) pass); + + if (read(s, &c, 1) != 1) { + perror(*ahost); + goto bad; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad; + } + freeaddrinfo(res0); + return (s); +bad: + if (port) + (void) close(*fd2p); + (void) close(s); + freeaddrinfo(res0); + return (-1); +} +libc_hidden_def(rexec_af) + +int +rexec(ahost, rport, name, pass, cmd, fd2p) + char **ahost; + int rport; + const char *name, *pass, *cmd; + int *fd2p; +{ + return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET); +} diff --git a/libc/inet/rpc/rpc_cmsg.c b/libc/inet/rpc/rpc_cmsg.c new file mode 100644 index 0000000..3206aae --- /dev/null +++ b/libc/inet/rpc/rpc_cmsg.c @@ -0,0 +1,215 @@ +/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_callmsg.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(xdr_enum) +libc_hidden_proto(xdr_opaque) +libc_hidden_proto(xdr_u_int) +libc_hidden_proto(xdr_u_long) +libc_hidden_proto(xdr_opaque_auth) + +/* + * XDR a call message + */ +libc_hidden_proto(xdr_callmsg) +bool_t +xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg) +{ + int32_t *buf; + struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) + { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) + { + IXDR_PUT_LONG (buf, cmsg->rm_xid); + IXDR_PUT_ENUM (buf, cmsg->rm_direction); + if (cmsg->rm_direction != CALL) + return FALSE; + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + return FALSE; + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog); + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers); + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc); + oa = &cmsg->rm_call.cb_cred; + IXDR_PUT_ENUM (buf, oa->oa_flavor); + IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length)); + } + oa = &cmsg->rm_call.cb_verf; + IXDR_PUT_ENUM (buf, oa->oa_flavor); + IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); + */ + } + return TRUE; + } + } + if (xdrs->x_op == XDR_DECODE) + { + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) + { + cmsg->rm_xid = IXDR_GET_LONG (buf); + cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type); + if (cmsg->rm_direction != CALL) + { + return FALSE; + } + cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + { + return FALSE; + } + cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) + { + if (xdr_enum (xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int (xdrs, &oa->oa_length) == FALSE) + { + return FALSE; + } + } + else + { + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + } + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + return TRUE; + } + } + if ( + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_cred))) + return xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_verf)); + return FALSE; +} +libc_hidden_def(xdr_callmsg) diff --git a/libc/inet/rpc/rpc_commondata.c b/libc/inet/rpc/rpc_commondata.c new file mode 100644 index 0000000..187d915 --- /dev/null +++ b/libc/inet/rpc/rpc_commondata.c @@ -0,0 +1,47 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#include +#include +#include + +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + + +/* + * This file should only contain common data (global data) that is exported + * by public interfaces + */ +struct opaque_auth _null_auth; +fd_set svc_fdset; +struct rpc_createerr rpc_createerr; +struct pollfd *svc_pollfd; +int svc_max_pollfd; diff --git a/libc/inet/rpc/rpc_dtablesize.c b/libc/inet/rpc/rpc_dtablesize.c new file mode 100644 index 0000000..11a7ad4 --- /dev/null +++ b/libc/inet/rpc/rpc_dtablesize.c @@ -0,0 +1,58 @@ +/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro"; +#endif + +#define __FORCE_GLIBC +#define __USE_BSD +#include + +#include +#include + +libc_hidden_proto(getdtablesize) + +/* + * Cache the result of getdtablesize(), so we don't have to do an + * expensive system call every time. + */ +libc_hidden_proto(_rpc_dtablesize) +int +_rpc_dtablesize(void) +{ + static int size; + + if (size == 0) + size = getdtablesize (); + + return size; +} +libc_hidden_def(_rpc_dtablesize) diff --git a/libc/inet/rpc/rpc_private.h b/libc/inet/rpc/rpc_private.h new file mode 100644 index 0000000..1525005 --- /dev/null +++ b/libc/inet/rpc/rpc_private.h @@ -0,0 +1,56 @@ +#ifndef _RPC_RPC_H +#include + +/* Now define the internal interfaces. */ +extern u_long _create_xid (void) attribute_hidden; + +libc_hidden_proto(__rpc_thread_createerr) + +/* + * Multi-threaded support + * Group all global and static variables into a single spot. + * This area is allocated on a per-thread basis + */ +#ifdef __UCLIBC_HAS_THREADS__ +#include +struct rpc_thread_variables { + fd_set svc_fdset_s; /* Global, rpc_common.c */ + struct rpc_createerr rpc_createerr_s; /* Global, rpc_common.c */ + struct pollfd *svc_pollfd_s; /* Global, rpc_common.c */ + int svc_max_pollfd_s; /* Global, rpc_common.c */ + + void *authnone_private_s; /* auth_none.c */ + + void *clnt_perr_buf_s; /* clnt_perr.c */ + + void *clntraw_private_s; /* clnt_raw.c */ + + void *callrpc_private_s; /* clnt_simp.c */ + + void *key_call_private_s; /* key_call.c */ + + void *authdes_cache_s; /* svcauth_des.c */ + void *authdes_lru_s; /* svcauth_des.c */ + + void *svc_xports_s; /* svc.c */ + void *svc_head_s; /* svc.c */ + + void *svcraw_private_s; /* svc_raw.c */ + + void *svcsimple_proglst_s; /* svc_simple.c */ + void *svcsimple_transp_s; /* svc_simple.c */ +}; + +extern struct rpc_thread_variables *__rpc_thread_variables(void) + __attribute__ ((const)) attribute_hidden; +extern void __rpc_thread_svc_cleanup (void) attribute_hidden; +extern void __rpc_thread_clnt_cleanup (void) attribute_hidden; +/*extern void __rpc_thread_key_cleanup (void) attribute_hidden;*/ + +extern void __rpc_thread_destroy (void); + +#define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x) + +#endif /* __UCLIBC_HAS_THREADS__ */ + +#endif diff --git a/libc/inet/rpc/rpc_prot.c b/libc/inet/rpc/rpc_prot.c new file mode 100644 index 0000000..74658e6 --- /dev/null +++ b/libc/inet/rpc/rpc_prot.c @@ -0,0 +1,296 @@ +/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_prot.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements the rpc message definition, + * its serializer and some common rpc utility routines. + * The routines are meant for various implementations of rpc - + * they are NOT for the rpc client or rpc service implementations! + * Because authentication stuff is easy and is part of rpc, the opaque + * routines are also in this program. + */ + +#define __FORCE_GLIBC +#include + +#include + +#include + +libc_hidden_proto(xdr_bytes) +libc_hidden_proto(xdr_union) +libc_hidden_proto(xdr_enum) +libc_hidden_proto(xdr_opaque) +libc_hidden_proto(xdr_u_long) + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +libc_hidden_proto(xdr_opaque_auth) +bool_t +xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap) +{ + + if (xdr_enum (xdrs, &(ap->oa_flavor))) + return xdr_bytes (xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES); + return FALSE; +} +libc_hidden_def(xdr_opaque_auth) + +/* + * XDR a DES block + */ +bool_t +xdr_des_block (XDR *xdrs, des_block *blkp) +{ + return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block)); +} + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +libc_hidden_proto(xdr_accepted_reply) +bool_t +xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_opaque_auth (xdrs, &(ar->ar_verf))) + return FALSE; + if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat))) + return FALSE; + switch (ar->ar_stat) + { + case SUCCESS: + return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where)); + case PROG_MISMATCH: + if (!xdr_u_long (xdrs, &(ar->ar_vers.low))) + return FALSE; + return (xdr_u_long (xdrs, &(ar->ar_vers.high))); + default: + return TRUE; + } + return TRUE; /* TRUE => open ended set of problems */ +} +libc_hidden_def(xdr_accepted_reply) + +/* + * XDR the MSG_DENIED part of a reply message union + */ +libc_hidden_proto(xdr_rejected_reply) +bool_t +xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat))) + return FALSE; + switch (rr->rj_stat) + { + case RPC_MISMATCH: + if (!xdr_u_long (xdrs, &(rr->rj_vers.low))) + return FALSE; + return xdr_u_long (xdrs, &(rr->rj_vers.high)); + + case AUTH_ERROR: + return xdr_enum (xdrs, (enum_t *) & (rr->rj_why)); + } + return FALSE; +} +libc_hidden_def(xdr_rejected_reply) + +static const struct xdr_discrim reply_dscrm[3] = +{ + {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply}, + {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply}, + {__dontcare__, NULL_xdrproc_t}}; + +/* + * XDR a reply message + */ +libc_hidden_proto(xdr_replymsg) +bool_t +xdr_replymsg (XDR *xdrs, struct rpc_msg *rmsg) +{ + if (xdr_u_long (xdrs, &(rmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY)) + return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat), + (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm, + NULL_xdrproc_t); + return FALSE; +} +libc_hidden_def(xdr_replymsg) + + +/* + * Serializes the "static part" of a call message header. + * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. + * The rm_xid is not really static, but the user can easily munge on the fly. + */ +libc_hidden_proto(xdr_callhdr) +bool_t +xdr_callhdr (XDR *xdrs, struct rpc_msg *cmsg) +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog))) + return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)); + return FALSE; +} +libc_hidden_def(xdr_callhdr) + +/* ************************** Client utility routine ************* */ + +static void +accepted (enum accept_stat acpt_stat, + struct rpc_err *error) +{ + switch (acpt_stat) + { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_ACCEPTED; + error->re_lb.s2 = (long) acpt_stat; +} + +static void +rejected (enum reject_stat rjct_stat, + struct rpc_err *error) +{ + switch (rjct_stat) + { + case RPC_VERSMISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + default: + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_DENIED; + error->re_lb.s2 = (long) rjct_stat; + return; + } +} + +/* + * given a reply message, fills in the error + */ +libc_hidden_proto(_seterr_reply) +void +_seterr_reply (struct rpc_msg *msg, + struct rpc_err *error) +{ + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) + { + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) + { + error->re_status = RPC_SUCCESS; + return; + }; + accepted (msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected (msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) (msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) + { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + default: + break; + } +} +libc_hidden_def(_seterr_reply) diff --git a/libc/inet/rpc/rpc_thread.c b/libc/inet/rpc/rpc_thread.c new file mode 100644 index 0000000..43d2fc5 --- /dev/null +++ b/libc/inet/rpc/rpc_thread.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include "rpc_private.h" + +libc_hidden_proto(__rpc_thread_svc_fdset) +libc_hidden_proto(__rpc_thread_createerr) +libc_hidden_proto(__rpc_thread_svc_pollfd) +libc_hidden_proto(__rpc_thread_svc_max_pollfd) + +#ifdef __UCLIBC_HAS_THREADS__ + +#include + +/* Variable used in non-threaded applications or for the first thread. */ +static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem; +__libc_tsd_define (, RPC_VARS) + +/* + * Task-variable destructor + */ +void +__rpc_thread_destroy (void) +{ + struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS); + + if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) { + __rpc_thread_svc_cleanup (); + __rpc_thread_clnt_cleanup (); + /*__rpc_thread_key_cleanup (); */ + free (tvp->authnone_private_s); + free (tvp->clnt_perr_buf_s); + free (tvp->clntraw_private_s); + free (tvp->svcraw_private_s); + free (tvp->authdes_cache_s); + free (tvp->authdes_lru_s); + free (tvp); + __libc_tsd_set (RPC_VARS, NULL); + } +} + +/* + * Initialize RPC multi-threaded operation + */ +static void +rpc_thread_multi (void) +{ + __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem); +} + + +struct rpc_thread_variables attribute_hidden * +__rpc_thread_variables (void) +{ + __libc_once_define (static, once); + struct rpc_thread_variables *tvp; + + tvp = __libc_tsd_get (RPC_VARS); + if (tvp == NULL) { + __libc_once (once, rpc_thread_multi); + tvp = __libc_tsd_get (RPC_VARS); + if (tvp == NULL) { + tvp = calloc (1, sizeof *tvp); + if (tvp != NULL) + __libc_tsd_set (RPC_VARS, tvp); + else + tvp = __libc_tsd_get (RPC_VARS); + } + } + return tvp; +} + + +/* Global variables If we're single-threaded, or if this is the first + thread using the variable, use the existing global variable. This + provides backwards compatability for existing applications which + dynamically link against this code. */ +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + +fd_set * +__rpc_thread_svc_fdset (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_fdset; + return &tvp->svc_fdset_s; +} + +struct rpc_createerr * +__rpc_thread_createerr (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &rpc_createerr; + return &tvp->rpc_createerr_s; +} + +struct pollfd ** +__rpc_thread_svc_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_pollfd; + return &tvp->svc_pollfd_s; +} + +int * +__rpc_thread_svc_max_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_max_pollfd; + return &tvp->svc_max_pollfd_s; +} +#else + +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + +extern fd_set svc_fdset; +fd_set * __rpc_thread_svc_fdset (void) +{ + return &(svc_fdset); +} + +extern struct rpc_createerr rpc_createerr; +struct rpc_createerr * __rpc_thread_createerr (void) +{ + return &(rpc_createerr); +} + +extern struct pollfd *svc_pollfd; +struct pollfd ** __rpc_thread_svc_pollfd (void) +{ + return &(svc_pollfd); +} + +extern int svc_max_pollfd; +int * __rpc_thread_svc_max_pollfd (void) +{ + return &(svc_max_pollfd); +} + +#endif /* __UCLIBC_HAS_THREADS__ */ + +libc_hidden_def(__rpc_thread_svc_fdset) +libc_hidden_def(__rpc_thread_createerr) +libc_hidden_def(__rpc_thread_svc_pollfd) +libc_hidden_def(__rpc_thread_svc_max_pollfd) diff --git a/libc/inet/rpc/rtime.c b/libc/inet/rpc/rtime.c new file mode 100644 index 0000000..6190868 --- /dev/null +++ b/libc/inet/rpc/rtime.c @@ -0,0 +1,161 @@ +#if 0 +static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket. Since timeserver returns + * with time of day in seconds since Jan 1, 1900, must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(read) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(connect) +libc_hidden_proto(recvfrom) +libc_hidden_proto(sendto) +libc_hidden_proto(poll) +libc_hidden_proto(rtime) + +#define NYEARS (u_long)(1970 - 1900) +#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4))) + +static void do_close (int); + +static void +do_close (int s) +{ + int save; + + save = errno; + close (s); + __set_errno (save); +} + +int +rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, + struct rpc_timeval *timeout) +{ + int s; + struct pollfd fd; + int milliseconds; + int res; + /* RFC 868 says the time is transmitted as a 32-bit value. */ + uint32_t thetime; + struct sockaddr_in from; + socklen_t fromlen; + int type; + + if (timeout == NULL) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + s = socket (AF_INET, type, 0); + if (s < 0) + return (-1); + + addrp->sin_family = AF_INET; + addrp->sin_port = htons (IPPORT_TIMESERVER); + if (type == SOCK_DGRAM) + { + res = sendto (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) addrp, sizeof (*addrp)); + if (res < 0) + { + do_close (s); + return -1; + } + milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + fd.fd = s; + fd.events = POLLIN; + do + res = poll (&fd, 1, milliseconds); + while (res < 0 && errno == EINTR); + if (res <= 0) + { + if (res == 0) + __set_errno (ETIMEDOUT); + do_close (s); + return (-1); + } + fromlen = sizeof (from); + res = recvfrom (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) &from, &fromlen); + do_close (s); + if (res < 0) + return -1; + } + else + { + if (connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) + { + do_close (s); + return -1; + } + res = read (s, (char *) &thetime, sizeof (thetime)); + do_close (s); + if (res < 0) + return (-1); + } + if (res != sizeof (thetime)) + { + __set_errno (EIO); + return -1; + } + thetime = ntohl (thetime); + timep->tv_sec = thetime - TOFFSET; + timep->tv_usec = 0; + return 0; +} +libc_hidden_def (rtime) diff --git a/libc/inet/rpc/ruserpass.c b/libc/inet/rpc/ruserpass.c new file mode 100644 index 0000000..ad6e703 --- /dev/null +++ b/libc/inet/rpc/ruserpass.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcasecmp) */ +/* Experimentally off - libc_hidden_proto(strncasecmp) */ +libc_hidden_proto(getenv) +libc_hidden_proto(printf) +libc_hidden_proto(fstat) +libc_hidden_proto(__fsetlocking) +libc_hidden_proto(getgid) +libc_hidden_proto(getuid) +libc_hidden_proto(getegid) +libc_hidden_proto(geteuid) +libc_hidden_proto(gethostname) +libc_hidden_proto(fileno) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(getc_unlocked) +libc_hidden_proto(__fgetc_unlocked) + +#define _(X) (X) +/* #include "ftp_var.h" */ + +static int token (void); +static FILE *cfile; + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#define ID 10 +#define MACHINE 11 + +static char tokval[100]; + +static const char tokstr[] = +{ +#define TOK_DEFAULT_IDX 0 + "default\0" +#define TOK_LOGIN_IDX (TOK_DEFAULT_IDX + sizeof "default") + "login\0" +#define TOK_PASSWORD_IDX (TOK_LOGIN_IDX + sizeof "login") + "password\0" +#define TOK_PASSWD_IDX (TOK_PASSWORD_IDX + sizeof "password") + "passwd\0" +#define TOK_ACCOUNT_IDX (TOK_PASSWD_IDX + sizeof "passwd") + "account\0" +#define TOK_MACHINE_IDX (TOK_ACCOUNT_IDX + sizeof "account") + "machine\0" +#define TOK_MACDEF_IDX (TOK_MACHINE_IDX + sizeof "machine") + "macdef" +}; + +static const struct toktab { + int tokstr_off; + int tval; +} toktab[]= { + { TOK_DEFAULT_IDX, DEFAULT }, + { TOK_LOGIN_IDX, LOGIN }, + { TOK_PASSWORD_IDX, PASSWD }, + { TOK_PASSWD_IDX, PASSWD }, + { TOK_ACCOUNT_IDX, ACCOUNT }, + { TOK_MACHINE_IDX, MACHINE }, + { TOK_MACDEF_IDX, MACDEF } +}; + + +/* ruserpass - remote password check. + This function also exists in glibc but is undocumented */ +libc_hidden_proto(ruserpass) +int ruserpass(const char *host, const char **aname, const char **apass) +{ + char *hdir, *buf, *tmp; + char myname[1024], *mydomain; + int t, usedefault = 0; + struct stat stb; + + /* Give up when running a setuid or setgid app. */ + if ((getuid() != geteuid()) || getgid() != getegid()) + return -1; + hdir = getenv("HOME"); + if (hdir == NULL) { + /* If we can't get HOME, fail instead of trying ".", + which is no improvement. */ + return -1; + } + + buf = alloca (strlen(hdir) + 8); + strcpy(buf, hdir); + strcat(buf, "/.netrc"); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + printf("%s", buf); + return (0); + } + /* No threads use this stream. */ +#ifdef __UCLIBC_HAS_THREADS__ + __fsetlocking (cfile, FSETLOCKING_BYCALLER); +#endif + if (gethostname(myname, sizeof(myname)) < 0) + myname[0] = '\0'; + mydomain = strchr(myname, '.'); + if (mydomain==NULL) { + mydomain=myname + strlen(myname); + } +next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACHINE: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if ((tmp = strchr(host, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) { + if (*aname == 0) { + char *newp; + newp = malloc((unsigned) strlen(tokval) + 1); + if (newp == NULL) + { + printf(_("out of memory")); + goto bad; + } + *aname = strcpy(newp, tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + } + break; + case PASSWD: + if (strcmp(*aname, "anonymous") && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + printf(_("Error: .netrc file is readable by others.")); + printf(_("Remove password or make file unreadable by others.")); + goto bad; + } + if (token() && *apass == 0) { + char *newp; + newp = malloc((unsigned) strlen(tokval) + 1); + if (newp == NULL) + { + printf(_("out of memory")); + goto bad; + } + *apass = strcpy(newp, tokval); + } + break; + case ACCOUNT: +#if 0 + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + printf("Error: .netrc file is readable by others."); + printf("Remove account or make file unreadable by others."); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aacct, tokval); + } +#endif + break; + case MACDEF: +#if 0 + if (proxy) { + (void) fclose(cfile); + return (0); + } + while ((c=getc_unlocked(cfile)) != EOF && c == ' ' + || c == '\t'); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc_unlocked(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc_unlocked(cfile)) != EOF + && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc_unlocked(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + break; + } + *tmp = '\0'; + } + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } +#endif + break; + default: + printf(_("Unknown .netrc keyword %s"), tokval); + break; + } + goto done; + } +done: + (void) fclose(cfile); + return (0); +bad: + (void) fclose(cfile); + return (-1); +} +libc_hidden_def(ruserpass) + +static int +token() +{ + char *cp; + int c; + int i; + + if (feof_unlocked(cfile) || ferror_unlocked(cfile)) + return (0); + while ((c = getc_unlocked(cfile)) != EOF && + (c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc_unlocked(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc_unlocked(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc_unlocked(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',') { + if (c == '\\') + c = getc_unlocked(cfile); + *cp++ = c; + } + } + *cp = 0; + if (tokval[0] == 0) + return (0); + for (i = 0; i < (int) (sizeof (toktab) / sizeof (toktab[0])); ++i) + if (!strcmp(&tokstr[toktab[i].tokstr_off], tokval)) + return toktab[i].tval; + return (ID); +} diff --git a/libc/inet/rpc/sa_len.c b/libc/inet/rpc/sa_len.c new file mode 100644 index 0000000..3b37eba --- /dev/null +++ b/libc/inet/rpc/sa_len.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#if 0 +#include +#include +#include +#include +#include +#include +#endif + +int __libc_sa_len (sa_family_t af) attribute_hidden; +int __libc_sa_len (sa_family_t af) +{ + switch (af) + { +#if 0 + case AF_APPLETALK: + return sizeof (struct sockaddr_at); + case AF_ASH: + return sizeof (struct sockaddr_ash); + case AF_AX25: + return sizeof (struct sockaddr_ax25); + case AF_ECONET: + return sizeof (struct sockaddr_ec); + case AF_ROSE: + return sizeof (struct sockaddr_rose); + case AF_PACKET: + return sizeof (struct sockaddr_ll); +#endif + case AF_INET: + return sizeof (struct sockaddr_in); + case AF_INET6: + return sizeof (struct sockaddr_in6); + case AF_IPX: + return sizeof (struct sockaddr_ipx); + case AF_LOCAL: + return sizeof (struct sockaddr_un); + } + return 0; +} diff --git a/libc/inet/rpc/svc.c b/libc/inet/rpc/svc.c new file mode 100644 index 0000000..253c063 --- /dev/null +++ b/libc/inet/rpc/svc.c @@ -0,0 +1,526 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * svc.c, Server-side remote procedure call interface. + * + * There are two sets of procedures here. The xprt routines are + * for handling transport handles. The svc routines handle the + * list of service routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include "rpc_private.h" +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(ffs) */ +libc_hidden_proto(pmap_set) +libc_hidden_proto(pmap_unset) +libc_hidden_proto(_authenticate) +libc_hidden_proto(_rpc_dtablesize) +/* used by svc_[max_]pollfd */ +libc_hidden_proto(__rpc_thread_svc_pollfd) +libc_hidden_proto(__rpc_thread_svc_max_pollfd) +/* used by svc_fdset */ +libc_hidden_proto(__rpc_thread_svc_fdset) + +#ifdef __UCLIBC_HAS_THREADS__ +#define xports (*(SVCXPRT ***)&RPC_THREAD_VARIABLE(svc_xports_s)) +#else +static SVCXPRT **xports; +#endif + +#define NULL_SVC ((struct svc_callout *)0) +#define RQCRED_SIZE 400 /* this size is excessive */ + +/* The services list + Each entry represents a set of procedures (an rpc program). + The dispatch routine takes request structs and runs the + appropriate procedure. */ +struct svc_callout { + struct svc_callout *sc_next; + rpcprog_t sc_prog; + rpcvers_t sc_vers; + void (*sc_dispatch) (struct svc_req *, SVCXPRT *); +}; +#ifdef __UCLIBC_HAS_THREADS__ +#define svc_head (*(struct svc_callout **)&RPC_THREAD_VARIABLE(svc_head_s)) +#else +static struct svc_callout *svc_head; +#endif + +/* *************** SVCXPRT related stuff **************** */ + +/* Activate a transport handle. */ +libc_hidden_proto(xprt_register) +void +xprt_register (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if (xports == NULL) + { + xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *)); + if (xports == NULL) /* Don´t add handle */ + return; + } + + if (sock < _rpc_dtablesize ()) + { + xports[sock] = xprt; + if (sock < FD_SETSIZE) + FD_SET (sock, &svc_fdset); + + /* Check if we have an empty slot */ + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == -1) + { + svc_pollfd[i].fd = sock; + svc_pollfd[i].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + return; + } + + ++svc_max_pollfd; + svc_pollfd = realloc (svc_pollfd, + sizeof (struct pollfd) * svc_max_pollfd); + if (svc_pollfd == NULL) /* Out of memory */ + return; + + svc_pollfd[svc_max_pollfd - 1].fd = sock; + svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + } +} +libc_hidden_def(xprt_register) + +/* De-activate a transport handle. */ +libc_hidden_proto(xprt_unregister) +void +xprt_unregister (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt)) + { + xports[sock] = (SVCXPRT *) 0; + + if (sock < FD_SETSIZE) + FD_CLR (sock, &svc_fdset); + + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == sock) + svc_pollfd[i].fd = -1; + } +} +libc_hidden_def(xprt_unregister) + + +/* ********************** CALLOUT list related stuff ************* */ + +/* Search the callout list for a program number, return the callout + struct. */ +static struct svc_callout * +svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev) +{ + register struct svc_callout *s, *p; + + p = NULL_SVC; + for (s = svc_head; s != NULL_SVC; s = s->sc_next) + { + if ((s->sc_prog == prog) && (s->sc_vers == vers)) + goto done; + p = s; + } +done: + *prev = p; + return s; +} + +/* Add a service program to the callout list. + The dispatch routine will be called when a rpc request for this + program number comes in. */ +libc_hidden_proto(svc_register) +bool_t +svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers, + void (*dispatch) (struct svc_req *, SVCXPRT *), + rpcproc_t protocol) +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find (prog, vers, &prev)) != NULL_SVC) + { + if (s->sc_dispatch == dispatch) + goto pmap_it; /* he is registering another xptr */ + return FALSE; + } + s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout)); + if (s == (struct svc_callout *) 0) + return FALSE; + + s->sc_prog = prog; + s->sc_vers = vers; + s->sc_dispatch = dispatch; + s->sc_next = svc_head; + svc_head = s; + +pmap_it: + /* now register the information with the local binder service */ + if (protocol) + return pmap_set (prog, vers, protocol, xprt->xp_port); + + return TRUE; +} +libc_hidden_def(svc_register) + +/* Remove a service program from the callout list. */ +libc_hidden_proto(svc_unregister) +void +svc_unregister (rpcprog_t prog, rpcvers_t vers) +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find (prog, vers, &prev)) == NULL_SVC) + return; + + if (prev == NULL_SVC) + svc_head = s->sc_next; + else + prev->sc_next = s->sc_next; + + s->sc_next = NULL_SVC; + mem_free ((char *) s, (u_int) sizeof (struct svc_callout)); + /* now unregister the information with the local binder service */ + pmap_unset (prog, vers); +} +libc_hidden_def(svc_unregister) + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* Send a reply to an rpc request */ +libc_hidden_proto(svc_sendreply) +bool_t +svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results, + caddr_t xdr_location) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SUCCESS; + rply.acpted_rply.ar_results.where = xdr_location; + rply.acpted_rply.ar_results.proc = xdr_results; + return SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svc_sendreply) + +/* No procedure error reply */ +void +svcerr_noproc (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROC_UNAVAIL; + SVC_REPLY (xprt, &rply); +} + +/* Can't decode args error reply */ +libc_hidden_proto(svcerr_decode) +void +svcerr_decode (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = GARBAGE_ARGS; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_decode) + +/* Some system error */ +void +svcerr_systemerr (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SYSTEM_ERR; + SVC_REPLY (xprt, &rply); +} + +/* Authentication error reply */ +libc_hidden_proto(svcerr_auth) +void +svcerr_auth (SVCXPRT *xprt, enum auth_stat why) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_DENIED; + rply.rjcted_rply.rj_stat = AUTH_ERROR; + rply.rjcted_rply.rj_why = why; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_auth) + +/* Auth too weak error reply */ +void +svcerr_weakauth (SVCXPRT *xprt) +{ + svcerr_auth (xprt, AUTH_TOOWEAK); +} + +/* Program unavailable error reply */ +libc_hidden_proto(svcerr_noprog) +void +svcerr_noprog (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_UNAVAIL; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_noprog) + +/* Program version mismatch error reply */ +libc_hidden_proto(svcerr_progvers) +void +svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers, + rpcvers_t high_vers) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_MISMATCH; + rply.acpted_rply.ar_vers.low = low_vers; + rply.acpted_rply.ar_vers.high = high_vers; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_progvers) + +/* ******************* SERVER INPUT STUFF ******************* */ + +/* + * Get server side input from some transport. + * + * Statement of authentication parameters management: + * This function owns and manages all authentication parameters, specifically + * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and + * the "cooked" credentials (rqst->rq_clntcred). + * However, this function does not know the structure of the cooked + * credentials, so it make the following assumptions: + * a) the structure is contiguous (no pointers), and + * b) the cred structure size does not exceed RQCRED_SIZE bytes. + * In all events, all three parameters are freed upon exit from this routine. + * The storage is trivially management on the call stack in user land, but + * is mallocated in kernel land. + */ + +libc_hidden_proto(svc_getreq_common) +void +svc_getreq_common (const int fd) +{ + enum xprt_stat stat; + struct rpc_msg msg; + register SVCXPRT *xprt; + char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE]; + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + + xprt = xports[fd]; + /* Do we control fd? */ + if (xprt == NULL) + return; + + /* now receive msgs from xprtprt (support batch calls) */ + do + { + if (SVC_RECV (xprt, &msg)) + { + /* now find the exported program and call it */ + struct svc_callout *s; + struct svc_req r; + enum auth_stat why; + rpcvers_t low_vers; + rpcvers_t high_vers; + int prog_found; + + r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + + /* first authenticate the message */ + /* Check for null flavor and bypass these calls if possible */ + + if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL) + { + r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + r.rq_xprt->xp_verf.oa_length = 0; + } + else if ((why = _authenticate (&r, &msg)) != AUTH_OK) + { + svcerr_auth (xprt, why); + goto call_done; + } + + /* now match message with a registered service */ + prog_found = FALSE; + low_vers = 0 - 1; + high_vers = 0; + + for (s = svc_head; s != NULL_SVC; s = s->sc_next) + { + if (s->sc_prog == r.rq_prog) + { + if (s->sc_vers == r.rq_vers) + { + (*s->sc_dispatch) (&r, xprt); + goto call_done; + } + /* found correct version */ + prog_found = TRUE; + if (s->sc_vers < low_vers) + low_vers = s->sc_vers; + if (s->sc_vers > high_vers) + high_vers = s->sc_vers; + } + /* found correct program */ + } + /* if we got here, the program or version + is not served ... */ + if (prog_found) + svcerr_progvers (xprt, low_vers, high_vers); + else + svcerr_noprog (xprt); + /* Fall through to ... */ + } + call_done: + if ((stat = SVC_STAT (xprt)) == XPRT_DIED) + { + SVC_DESTROY (xprt); + break; + } + } + while (stat == XPRT_MOREREQS); +} +libc_hidden_def(svc_getreq_common) + +libc_hidden_proto(svc_getreqset) +void +svc_getreqset (fd_set *readfds) +{ + register u_int32_t mask; + register u_int32_t *maskp; + register int setsize; + register int sock; + register int bit; + + setsize = _rpc_dtablesize (); + maskp = (u_int32_t *) readfds->fds_bits; + for (sock = 0; sock < setsize; sock += 32) + for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1))) + svc_getreq_common (sock + bit - 1); +} +libc_hidden_def(svc_getreqset) + +libc_hidden_proto(svc_getreq) +void +svc_getreq (int rdfds) +{ + fd_set readfds; + + FD_ZERO (&readfds); + readfds.fds_bits[0] = rdfds; + svc_getreqset (&readfds); +} +libc_hidden_def(svc_getreq) + +libc_hidden_proto(svc_getreq_poll) +void +svc_getreq_poll (struct pollfd *pfdp, int pollretval) +{ + register int i; + register int fds_found; + + for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i) + { + register struct pollfd *p = &pfdp[i]; + + if (p->fd != -1 && p->revents) + { + /* fd has input waiting */ + ++fds_found; + + if (p->revents & POLLNVAL) + xprt_unregister (xports[p->fd]); + else + svc_getreq_common (p->fd); + } + } +} +libc_hidden_def(svc_getreq_poll) + +#ifdef __UCLIBC_HAS_THREADS__ + +void attribute_hidden __rpc_thread_svc_cleanup (void) +{ + struct svc_callout *svcp; + + while ((svcp = svc_head) != NULL) + svc_unregister (svcp->sc_prog, svcp->sc_vers); +} + +#endif /* __UCLIBC_HAS_THREADS__ */ diff --git a/libc/inet/rpc/svc_auth.c b/libc/inet/rpc/svc_auth.c new file mode 100644 index 0000000..1a5dcf0 --- /dev/null +++ b/libc/inet/rpc/svc_auth.c @@ -0,0 +1,125 @@ +/* @(#)svc_auth.c 2.4 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_auth.c, Server-side rpc authenticator interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *); + /* no authentication */ +extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *); + /* unix style (uid, gids) */ +extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); + /* short hand unix style */ +#ifdef CONFIG_AUTH_DES +extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); + /* des style */ +#endif + +static const struct + { + enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *); + } +svcauthsw[] = +{ + { _svcauth_null }, /* AUTH_NULL */ + { _svcauth_unix }, /* AUTH_UNIX */ + { _svcauth_short }, /* AUTH_SHORT */ +#ifdef CONFIG_AUTH_DES + { _svcauth_des } /* AUTH_DES */ +#endif +}; +#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */ + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-allocated; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +libc_hidden_proto(_authenticate) +enum auth_stat +_authenticate (register struct svc_req *rqst, struct rpc_msg *msg) +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) + return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg); + + return AUTH_REJECTEDCRED; +} +libc_hidden_def(_authenticate) + +static enum auth_stat +_svcauth_null (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) +{ + return AUTH_OK; +} diff --git a/libc/inet/rpc/svc_authux.c b/libc/inet/rpc/svc_authux.c new file mode 100644 index 0000000..64c911f --- /dev/null +++ b/libc/inet/rpc/svc_authux.c @@ -0,0 +1,163 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_auth_unix.c + * Handles UNIX flavor authentication parameters on the service side of rpc. + * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT. + * _svcauth_unix does full blown unix style uid,gid+gids auth, + * _svcauth_short uses a shorthand auth to index into a cache of longhand auths. + * Note: the shorthand has been gutted for efficiency. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(printf) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_authunix_parms) + +/* + * Unix longhand authenticator + */ +enum auth_stat +_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg) attribute_hidden; +enum auth_stat +_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg) +{ + enum auth_stat stat; + XDR xdrs; + struct authunix_parms *aup; + int32_t *buf; + struct area + { + struct authunix_parms area_aup; + char area_machname[MAX_MACHINE_NAME + 1]; + gid_t area_gids[NGRPS]; + } + *area; + u_int auth_len; + u_int str_len, gid_len; + u_int i; + + area = (struct area *) rqst->rq_clntcred; + aup = &area->area_aup; + aup->aup_machname = area->area_machname; + aup->aup_gids = area->area_gids; + auth_len = (u_int) msg->rm_call.cb_cred.oa_length; + xdrmem_create (&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE); + buf = XDR_INLINE (&xdrs, auth_len); + if (buf != NULL) + { + aup->aup_time = IXDR_GET_LONG (buf); + str_len = IXDR_GET_U_INT32 (buf); + if (str_len > MAX_MACHINE_NAME) + { + stat = AUTH_BADCRED; + goto done; + } + memcpy (aup->aup_machname, (caddr_t) buf, (u_int) str_len); + aup->aup_machname[str_len] = 0; + str_len = RNDUP (str_len); + buf = (int32_t *) ((char *) buf + str_len); + aup->aup_uid = IXDR_GET_LONG (buf); + aup->aup_gid = IXDR_GET_LONG (buf); + gid_len = IXDR_GET_U_INT32 (buf); + if (gid_len > NGRPS) + { + stat = AUTH_BADCRED; + goto done; + } + aup->aup_len = gid_len; + for (i = 0; i < gid_len; i++) + { + aup->aup_gids[i] = IXDR_GET_LONG (buf); + } + /* + * five is the smallest unix credentials structure - + * timestamp, hostname len (0), uid, gid, and gids len (0). + */ + if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) + { + (void) printf ("bad auth_len gid %d str %d auth %d\n", + gid_len, str_len, auth_len); + stat = AUTH_BADCRED; + goto done; + } + } + else if (!xdr_authunix_parms (&xdrs, aup)) + { + xdrs.x_op = XDR_FREE; + (void) xdr_authunix_parms (&xdrs, aup); + stat = AUTH_BADCRED; + goto done; + } + + /* get the verifier */ + if ((u_int)msg->rm_call.cb_verf.oa_length) + { + rqst->rq_xprt->xp_verf.oa_flavor = + msg->rm_call.cb_verf.oa_flavor; + rqst->rq_xprt->xp_verf.oa_base = + msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + msg->rm_call.cb_verf.oa_length; + } + else + { + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; + rqst->rq_xprt->xp_verf.oa_length = 0; + } + stat = AUTH_OK; +done: + XDR_DESTROY (&xdrs); + return stat; +} + + +/* + * Shorthand unix authenticator + * Looks up longhand in a cache. + */ +/*ARGSUSED */ +enum auth_stat +_svcauth_short (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) attribute_hidden; +enum auth_stat +_svcauth_short (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) +{ + return AUTH_REJECTEDCRED; +} diff --git a/libc/inet/rpc/svc_raw.c b/libc/inet/rpc/svc_raw.c new file mode 100644 index 0000000..0cdbbb8 --- /dev/null +++ b/libc/inet/rpc/svc_raw.c @@ -0,0 +1,171 @@ +/* @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_raw.c, This a toy for simple testing and timing. + * Interface to create an rpc client and server in the same UNIX process. + * This lets us simulate rpc and get rpc (round trip) overhead, without + * any interference from the kernel. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" +#include + +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_callmsg) +libc_hidden_proto(xdr_replymsg) + +/* + * This is the "network" that we will be moving data over + */ +struct svcraw_private_s + { + char _raw_buf[UDPMSGSIZE]; + SVCXPRT server; + XDR xdr_stream; + char verf_body[MAX_AUTH_BYTES]; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define svcraw_private (*(struct svcraw_private_s **)&RPC_THREAD_VARIABLE(svcraw_private_s)) +#else +static struct svcraw_private_s *svcraw_private; +#endif + +static bool_t svcraw_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcraw_stat (SVCXPRT *); +static bool_t svcraw_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcraw_destroy (SVCXPRT *); + +static struct xp_ops server_ops = +{ + svcraw_recv, + svcraw_stat, + svcraw_getargs, + svcraw_reply, + svcraw_freeargs, + svcraw_destroy +}; + +SVCXPRT * +svcraw_create (void) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + { + srp = (struct svcraw_private_s *) calloc (1, sizeof (*srp)); + if (srp == 0) + return NULL; + } + srp->server.xp_sock = 0; + srp->server.xp_port = 0; + srp->server.xp_ops = &server_ops; + srp->server.xp_verf.oa_base = srp->verf_body; + xdrmem_create (&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE); + return &srp->server; +} + +static enum xprt_stat +svcraw_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static bool_t +svcraw_recv (xprt, msg) + SVCXPRT *xprt attribute_unused; + struct rpc_msg *msg; +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_callmsg (xdrs, msg)) + return FALSE; + return TRUE; +} + +static bool_t +svcraw_reply (SVCXPRT *xprt attribute_unused, struct rpc_msg *msg) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_replymsg (xdrs, msg)) + return FALSE; + (void) XDR_GETPOS (xdrs); /* called just for overhead */ + return TRUE; +} + +static bool_t +svcraw_getargs (SVCXPRT *xprt attribute_unused, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + return FALSE; + return (*xdr_args) (&srp->xdr_stream, args_ptr); +} + +static bool_t +svcraw_freeargs (SVCXPRT *xprt attribute_unused, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static void +svcraw_destroy (SVCXPRT *xprt attribute_unused) +{ +} diff --git a/libc/inet/rpc/svc_run.c b/libc/inet/rpc/svc_run.c new file mode 100644 index 0000000..50e5fcd --- /dev/null +++ b/libc/inet/rpc/svc_run.c @@ -0,0 +1,95 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * This is the rpc server side idle loop + * Wait for input, call server program. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +libc_hidden_proto(perror) +libc_hidden_proto(svc_getreq_poll) +libc_hidden_proto(poll) +/* used by svc_[max_]pollfd */ +libc_hidden_proto(__rpc_thread_svc_pollfd) +libc_hidden_proto(__rpc_thread_svc_max_pollfd) + +/* This function can be used as a signal handler to terminate the + server loop. */ +void +svc_exit (void) +{ + free (svc_pollfd); + svc_pollfd = NULL; + svc_max_pollfd = 0; +} + +void +svc_run (void) +{ + int i; + + for (;;) + { + struct pollfd *my_pollfd; + + if (svc_max_pollfd == 0 && svc_pollfd == NULL) + return; + + my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd); + for (i = 0; i < svc_max_pollfd; ++i) + { + my_pollfd[i].fd = svc_pollfd[i].fd; + my_pollfd[i].events = svc_pollfd[i].events; + my_pollfd[i].revents = 0; + } + + switch (i = poll (my_pollfd, svc_max_pollfd, -1)) + { + case -1: + free (my_pollfd); + if (errno == EINTR) + continue; + perror (_("svc_run: - poll failed")); + return; + case 0: + free (my_pollfd); + continue; + default: + svc_getreq_poll (my_pollfd, i); + free (my_pollfd); + } + } +} diff --git a/libc/inet/rpc/svc_simple.c b/libc/inet/rpc/svc_simple.c new file mode 100644 index 0000000..72c272a --- /dev/null +++ b/libc/inet/rpc/svc_simple.c @@ -0,0 +1,209 @@ +/* @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include "rpc_private.h" +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(asprintf) +libc_hidden_proto(fputs) +libc_hidden_proto(write) +libc_hidden_proto(exit) +libc_hidden_proto(svc_sendreply) +libc_hidden_proto(svc_register) +libc_hidden_proto(svcerr_decode) +libc_hidden_proto(svcudp_create) +libc_hidden_proto(pmap_unset) +libc_hidden_proto(xdr_void) + +struct proglst_ + { + char *(*p_progname) (char *); + int p_prognum; + int p_procnum; + xdrproc_t p_inproc, p_outproc; + struct proglst_ *p_nxt; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define proglst (*(struct proglst_ **)&RPC_THREAD_VARIABLE(svcsimple_proglst_s)) +#else +static struct proglst_ *proglst; +#endif + + +static void universal (struct svc_req *rqstp, SVCXPRT *transp_s); +#ifdef __UCLIBC_HAS_THREADS__ +#define transp (*(SVCXPRT **)&RPC_THREAD_VARIABLE(svcsimple_transp_s)) +#else +static SVCXPRT *transp; +#endif + +int registerrpc (u_long prognum, u_long versnum, u_long procnum, + char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc); +int +registerrpc (u_long prognum, u_long versnum, u_long procnum, + char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc) +{ + struct proglst_ *pl; + char *buf; + + if (procnum == NULLPROC) + { + + (void) asprintf (&buf, _("can't reassign procedure number %ld\n"), + NULLPROC); + goto err_out; + } + if (transp == 0) + { + transp = svcudp_create (RPC_ANYSOCK); + if (transp == NULL) + { + buf = strdup (_("couldn't create an rpc server\n")); + goto err_out; + } + } + (void) pmap_unset ((u_long) prognum, (u_long) versnum); + if (!svc_register (transp, (u_long) prognum, (u_long) versnum, + universal, IPPROTO_UDP)) + { + (void) asprintf (&buf, _("couldn't register prog %ld vers %ld\n"), + prognum, versnum); + goto err_out; + } + pl = (struct proglst_ *) malloc (sizeof (struct proglst_)); + if (pl == NULL) + { + buf = strdup (_("registerrpc: out of memory\n")); + goto err_out; + } + pl->p_progname = progname; + pl->p_prognum = prognum; + pl->p_procnum = procnum; + pl->p_inproc = inproc; + pl->p_outproc = outproc; + pl->p_nxt = proglst; + proglst = pl; + return 0; + + err_out: +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", buf); + else +#endif + (void) fputs (buf, stderr); + free (buf); + return -1; +} + +static void +universal (struct svc_req *rqstp, SVCXPRT *transp_l) +{ + int prog, proc; + char *outdata; + char xdrbuf[UDPMSGSIZE]; + struct proglst_ *pl; + char *buf = NULL; + + /* + * enforce "procnum 0 is echo" convention + */ + if (rqstp->rq_proc == NULLPROC) + { + if (svc_sendreply (transp_l, (xdrproc_t)xdr_void, (char *) NULL) == FALSE) + { + write (STDERR_FILENO, "xxx\n", 4); + exit (1); + } + return; + } + prog = rqstp->rq_prog; + proc = rqstp->rq_proc; + for (pl = proglst; pl != NULL; pl = pl->p_nxt) + if (pl->p_prognum == prog && pl->p_procnum == proc) + { + /* decode arguments into a CLEAN buffer */ + memset (xdrbuf, 0, sizeof (xdrbuf)); /* required ! */ + if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf)) + { + svcerr_decode (transp_l); + return; + } + outdata = (*(pl->p_progname)) (xdrbuf); + if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void) + /* there was an error */ + return; + if (!svc_sendreply (transp_l, pl->p_outproc, outdata)) + { + (void) asprintf (&buf, + _("trouble replying to prog %d\n"), + pl->p_prognum); + exit (1); + } + /* free the decoded arguments */ + (void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf); + return; + } + (void) asprintf (&buf, _("never registered prog %d\n"), prog); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else +#endif + fputs (buf, stderr); + free (buf); + exit (1); +} diff --git a/libc/inet/rpc/svc_tcp.c b/libc/inet/rpc/svc_tcp.c new file mode 100644 index 0000000..5e46679 --- /dev/null +++ b/libc/inet/rpc/svc_tcp.c @@ -0,0 +1,452 @@ +/* @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_tcp.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a tcp rendezvouser (a listener and connection establisher) + * and a record/tcp stream. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(perror) +libc_hidden_proto(xdrrec_create) +libc_hidden_proto(xdrrec_endofrecord) +libc_hidden_proto(xdrrec_skiprecord) +libc_hidden_proto(xdrrec_eof) +libc_hidden_proto(xdr_callmsg) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xprt_register) +libc_hidden_proto(xprt_unregister) +libc_hidden_proto(getsockname) +libc_hidden_proto(bind) +libc_hidden_proto(bindresvport) +libc_hidden_proto(poll) +libc_hidden_proto(accept) +libc_hidden_proto(listen) +libc_hidden_proto(fputs) +libc_hidden_proto(fclose) +libc_hidden_proto(abort) + +/* + * Ops vector for TCP/IP based rpc service handle + */ +static bool_t svctcp_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svctcp_stat (SVCXPRT *); +static bool_t svctcp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svctcp_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svctcp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svctcp_destroy (SVCXPRT *); + +static const struct xp_ops svctcp_op = +{ + svctcp_recv, + svctcp_stat, + svctcp_getargs, + svctcp_reply, + svctcp_freeargs, + svctcp_destroy +}; + +/* + * Ops vector for TCP/IP rendezvous handler + */ +static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svctcp_rendezvous_abort (void) attribute_noreturn; + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svctcp_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svctcp_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + svctcp_destroy +}; + +static int readtcp (char*, char *, int); +static int writetcp (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct tcp_rendezvous + { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; + }; + +struct tcp_conn + { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; + }; + +/* + * Usage: + * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) tcp based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svctcp_create + * binds it to an arbitrary port. The routine then starts a tcp + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since tcp streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svctcp_create (int sock, u_int sendsize, u_int recvsize) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + { + perror (_("svc_tcp.c - tcp socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset ((char *) &addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) bind (sock, (struct sockaddr *) &addr, len); + } + if ((getsockname (sock, (struct sockaddr *) &addr, &len) != 0) || + (listen (sock, 2) != 0)) + { + perror (_("svc_tcp.c - cannot getsockname or listen")); + if (madesock) + (void) close (sock); + return (SVCXPRT *) NULL; + } + r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", _("svctcp_create: out of memory\n")); + else +#endif + (void) fputs (_("svctcp_create: out of memory\n"), stderr); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svctcp_rendezvous_op; + xprt->xp_port = ntohs (addr.sin_port); + xprt->xp_sock = sock; + xprt_register (xprt); + return xprt; +} + +/* + * Like svtcp_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcfd_create (int fd, u_int sendsize, u_int recvsize); +SVCXPRT * +svcfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct tcp_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn)); + if (xprt == (SVCXPRT *) NULL || cd == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", + _("svc_tcp: makefd_xprt: out of memory\n")); + else +#endif + (void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct tcp_conn)); + return NULL; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create (&(cd->xdrs), sendsize, recvsize, + (caddr_t) xprt, readtcp, writetcp); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svctcp_op; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg attribute_unused) +{ + int sock; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t len; + + r = (struct tcp_rendezvous *) xprt->xp_p1; +again: + len = sizeof (struct sockaddr_in); + if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0) + { + if (errno == EINTR) + goto again; + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &addr, sizeof (addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static void +svctcp_destroy (SVCXPRT *xprt) +{ + struct tcp_conn *cd = (struct tcp_conn *) xprt->xp_p1; + + xprt_unregister (xprt); + (void) close (xprt->xp_sock); + if (xprt->xp_port != 0) + { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } + else + { + /* an actual connection socket */ + XDR_DESTROY (&(cd->xdrs)); + } + mem_free ((caddr_t) cd, sizeof (struct tcp_conn)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + + +/* + * reads data from the tcp connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readtcp (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + if ((len = read (sock, buf, len)) > 0) + return len; + + fatal_err: + ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; +} + +/* + * writes data to the tcp connection. + * Any error is fatal and the connection is closed. + */ +static int +writetcp (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = write (xprt->xp_sock, buf, cnt)) < 0) + { + ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; + } + } + return len; +} + +static enum xprt_stat +svctcp_stat (SVCXPRT *xprt) +{ + struct tcp_conn *cd = + (struct tcp_conn *) (xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return XPRT_DIED; + if (!xdrrec_eof (&(cd->xdrs))) + return XPRT_MOREREQS; + return XPRT_IDLE; +} + +static bool_t +svctcp_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + (void) xdrrec_skiprecord (xdrs); + if (xdr_callmsg (xdrs, msg)) + { + cd->x_id = msg->rm_xid; + return TRUE; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svctcp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return ((*xdr_args) (&(((struct tcp_conn *) + (xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svctcp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(((struct tcp_conn *) (xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args) (xdrs, args_ptr)); +} + +static bool_t +svctcp_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/libc/inet/rpc/svc_udp.c b/libc/inet/rpc/svc_udp.c new file mode 100644 index 0000000..e2c97bd --- /dev/null +++ b/libc/inet/rpc/svc_udp.c @@ -0,0 +1,636 @@ +/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_udp.c, + * Server side for UDP/IP based RPC. (Does some caching in the hopes of + * achieving execute-at-most-once semantics.) + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + +#ifdef IP_PKTINFO +#include +#endif + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(perror) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(xprt_register) +libc_hidden_proto(xprt_unregister) +libc_hidden_proto(xdrmem_create) +libc_hidden_proto(xdr_callmsg) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(getsockname) +libc_hidden_proto(setsockopt) +libc_hidden_proto(bind) +libc_hidden_proto(bindresvport) +libc_hidden_proto(recvfrom) +libc_hidden_proto(sendto) +libc_hidden_proto(recvmsg) +libc_hidden_proto(sendmsg) +libc_hidden_proto(fputs) +libc_hidden_proto(fprintf) + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#ifndef MAX +#define MAX(a, b) ((a > b) ? a : b) +#endif + +static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *); +static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcudp_stat (SVCXPRT *); +static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcudp_destroy (SVCXPRT *); + +static const struct xp_ops svcudp_op = +{ + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp, + u_long *replylenp); +static void cache_set (SVCXPRT *xprt, u_long replylen); + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data + { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char *su_cache; /* cached data, NULL if no cache */ + }; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +libc_hidden_proto(svcudp_bufcreate) +SVCXPRT * +svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct svcudp_data *su; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + int pad; + void *buf; + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("svcudp_create: socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset ((char *) &addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) bind (sock, (struct sockaddr *) &addr, len); + } + if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0) + { + perror (_("svcudp_create - cannot getsockname")); + if (madesock) + (void) close (sock); + return (SVCXPRT *) NULL; + } + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + su = (struct svcudp_data *) mem_alloc (sizeof (*su)); + buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4); + if (xprt == NULL || su == NULL || buf == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("svcudp_create: out of memory\n")); + else +#endif + (void) fputs (_("svcudp_create: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (su, sizeof (*su)); + mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4); + return NULL; + } + su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4; + rpc_buffer (xprt) = buf; + xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_DECODE); + su->su_cache = NULL; + xprt->xp_p2 = (caddr_t) su; + xprt->xp_verf.oa_base = su->su_verfbody; + xprt->xp_ops = &svcudp_op; + xprt->xp_port = ntohs (addr.sin_port); + xprt->xp_sock = sock; + +#ifdef IP_PKTINFO + if ((sizeof (struct iovec) + sizeof (struct msghdr) + + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo)) + > sizeof (xprt->xp_pad)) + { +# ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("svcudp_create: xp_pad is too small for IP_PKTINFO\n")); + else +# endif + (void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"), + stderr); + return NULL; + } + pad = 1; + if (setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad, + sizeof (pad)) == 0) + /* Set the padding to all 1s. */ + pad = 0xff; + else +#endif + /* Clear the padding. */ + pad = 0; + memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad)); + + xprt_register (xprt); + return xprt; +} +libc_hidden_def(svcudp_bufcreate) + +libc_hidden_proto(svcudp_create) +SVCXPRT * +svcudp_create (int sock) +{ + + return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE); +} +libc_hidden_def(svcudp_create) + +static enum xprt_stat +svcudp_stat (xprt) + SVCXPRT *xprt attribute_unused; +{ + + return XPRT_IDLE; +} + +static bool_t +svcudp_recv (xprt, msg) + SVCXPRT *xprt; + struct rpc_msg *msg; +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int rlen; + char *reply; + u_long replylen; + socklen_t len; + + /* It is very tricky when you have IP aliases. We want to make sure + that we are sending the packet from the IP address where the + incoming packet is addressed to. H.J. */ +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + +again: + /* FIXME -- should xp_addrlen be a size_t? */ + len = (socklen_t) sizeof(struct sockaddr_in); +#ifdef IP_PKTINFO + iovp = (struct iovec *) &xprt->xp_pad [0]; + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = su->su_iosz; + mesgp->msg_iov = iovp; + mesgp->msg_iovlen = 1; + mesgp->msg_name = &(xprt->xp_raddr); + mesgp->msg_namelen = len; + mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec) + + sizeof (struct msghdr)]; + mesgp->msg_controllen = sizeof(xprt->xp_pad) + - sizeof (struct iovec) - sizeof (struct msghdr); + rlen = recvmsg (xprt->xp_sock, mesgp, 0); + if (rlen >= 0) + len = mesgp->msg_namelen; + } + else +#endif + rlen = recvfrom (xprt->xp_sock, rpc_buffer (xprt), + (int) su->su_iosz, 0, + (struct sockaddr *) &(xprt->xp_raddr), &len); + xprt->xp_addrlen = len; + if (rlen == -1 && errno == EINTR) + goto again; + if (rlen < 16) /* < 4 32-bit ints? */ + return FALSE; + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_callmsg (xdrs, msg)) + return FALSE; + su->su_xid = msg->rm_xid; + if (su->su_cache != NULL) + { + if (cache_get (xprt, msg, &reply, &replylen)) + { +#ifdef IP_PKTINFO + if (mesgp->msg_iovlen) + { + iovp->iov_base = reply; + iovp->iov_len = replylen; + (void) sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + (void) sendto (xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, len); + return TRUE; + } + } + return TRUE; +} + +static bool_t +svcudp_reply (xprt, msg) + SVCXPRT *xprt; + struct rpc_msg *msg; +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int slen, sent; + bool_t stat = FALSE; +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg (xdrs, msg)) + { + slen = (int) XDR_GETPOS (xdrs); +#ifdef IP_PKTINFO + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp = (struct iovec *) &xprt->xp_pad [0]; + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = slen; + sent = sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + sent = sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0, + (struct sockaddr *) &(xprt->xp_raddr), + xprt->xp_addrlen); + if (sent == slen) + { + stat = TRUE; + if (su->su_cache && slen >= 0) + { + cache_set (xprt, (u_long) slen); + } + } + } + return stat; +} + +static bool_t +svcudp_getargs (xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr); +} + +static bool_t +svcudp_freeargs (xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + XDR *xdrs = &(su_data (xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static void +svcudp_destroy (xprt) + SVCXPRT *xprt; +{ + struct svcudp_data *su = su_data (xprt); + + xprt_unregister (xprt); + (void) close (xprt->xp_sock); + XDR_DESTROY (&(su->su_xdrs)); + mem_free (rpc_buffer (xprt), su->su_iosz); + mem_free ((caddr_t) su, sizeof (struct svcudp_data)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + + +/***********this could be a separate file*********************/ + +/* + * Fifo cache for udp server + * Copies pointers to reply buffers into fifo cache + * Buffers are sent again if retransmissions are detected. + */ + +#define SPARSENESS 4 /* 75% sparse */ + +#ifdef USE_IN_LIBIO +# define CACHE_PERROR(msg) \ + if (_IO_fwide (stderr, 0) > 0) \ + (void) __fwprintf(stderr, L"%s\n", msg); \ + else \ + (void) fprintf(stderr, "%s\n", msg) +#else +# define CACHE_PERROR(msg) \ + (void) fprintf(stderr,"%s\n", msg) +#endif + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define BZERO(addr, type, size) \ + memset((char *) addr, 0, sizeof(type) * (int) (size)) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node + { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char *cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; + }; + + + +/* + * The entire cache + */ +struct udp_cache + { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ + }; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ +int svcudp_enablecache (SVCXPRT *transp, u_long size); +int +svcudp_enablecache (SVCXPRT *transp, u_long size) +{ + struct svcudp_data *su = su_data (transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) + { + CACHE_PERROR (_("enablecache: cache already enabled")); + return 0; + } + uc = ALLOC (struct udp_cache, 1); + if (uc == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache")); + return 0; + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC (cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache data")); + return 0; + } + BZERO (uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC (cache_ptr, size); + if (uc->uc_fifo == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache fifo")); + return 0; + } + BZERO (uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return 1; +} + + +/* + * Set an entry in the cache + */ +static void +cache_set (SVCXPRT *xprt, u_long replylen) +{ + cache_ptr victim; + cache_ptr *vicp; + struct svcudp_data *su = su_data (xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) + { + loc = CACHE_LOC (xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) + { + CACHE_PERROR (_("cache_set: victim not found")); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } + else + { + victim = ALLOC (struct cache_node, 1); + if (victim == NULL) + { + CACHE_PERROR (_("cache_set: victim alloc failed")); + return; + } + newbuf = mem_alloc (su->su_iosz); + if (newbuf == NULL) + { + CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer")); + return; + } + } + + /* + * Store it away + */ + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer (xprt); + rpc_buffer (xprt) = newbuf; + xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_ENCODE); + victim->cache_xid = su->su_xid; + victim->cache_proc = uc->uc_proc; + victim->cache_vers = uc->uc_vers; + victim->cache_prog = uc->uc_prog; + victim->cache_addr = uc->uc_addr; + loc = CACHE_LOC (xprt, victim->cache_xid); + victim->cache_next = uc->uc_entries[loc]; + uc->uc_entries[loc] = victim; + uc->uc_fifo[uc->uc_nextvictim++] = victim; + uc->uc_nextvictim %= uc->uc_size; +} + +/* + * Try to get an entry from the cache + * return 1 if found, 0 if not found + */ +static int +cache_get (xprt, msg, replyp, replylenp) + SVCXPRT *xprt; + struct rpc_msg *msg; + char **replyp; + u_long *replylenp; +{ + u_int loc; + cache_ptr ent; + struct svcudp_data *su = su_data (xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + +#define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) + + loc = CACHE_LOC (xprt, su->su_xid); + for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) + { + if (ent->cache_xid == su->su_xid && + ent->cache_proc == uc->uc_proc && + ent->cache_vers == uc->uc_vers && + ent->cache_prog == uc->uc_prog && + EQADDR (ent->cache_addr, uc->uc_addr)) + { + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + return 1; + } + } + /* + * Failed to find entry + * Remember a few things so we can do a set later + */ + uc->uc_proc = msg->rm_call.cb_proc; + uc->uc_vers = msg->rm_call.cb_vers; + uc->uc_prog = msg->rm_call.cb_prog; + memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr)); + return 0; +} diff --git a/libc/inet/rpc/svc_unix.c b/libc/inet/rpc/svc_unix.c new file mode 100644 index 0000000..2d77904 --- /dev/null +++ b/libc/inet/rpc/svc_unix.c @@ -0,0 +1,563 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_unix.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a unix rendezvouser (a listener and connection establisher) + * and a record/unix stream. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(perror) +libc_hidden_proto(getpid) +libc_hidden_proto(xdrrec_create) +libc_hidden_proto(xdrrec_endofrecord) +libc_hidden_proto(xdrrec_skiprecord) +libc_hidden_proto(xdrrec_eof) +libc_hidden_proto(xdr_callmsg) +libc_hidden_proto(xdr_replymsg) +libc_hidden_proto(xprt_register) +libc_hidden_proto(xprt_unregister) +libc_hidden_proto(getegid) +libc_hidden_proto(geteuid) +libc_hidden_proto(getsockname) +libc_hidden_proto(setsockopt) +libc_hidden_proto(bind) +libc_hidden_proto(recvmsg) +libc_hidden_proto(sendmsg) +libc_hidden_proto(poll) +libc_hidden_proto(accept) +libc_hidden_proto(listen) +libc_hidden_proto(fputs) +libc_hidden_proto(abort) + +/* + * Ops vector for AF_UNIX based rpc service handle + */ +static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcunix_stat (SVCXPRT *); +static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcunix_destroy (SVCXPRT *); + +static const struct xp_ops svcunix_op = +{ + svcunix_recv, + svcunix_stat, + svcunix_getargs, + svcunix_reply, + svcunix_freeargs, + svcunix_destroy +}; + +/* + * Ops vector for AF_UNIX rendezvous handler + */ +static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svcunix_rendezvous_abort (void) attribute_noreturn; + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svcunix_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svcunix_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + svcunix_destroy +}; + +static int readunix (char*, char *, int); +static int writeunix (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct unix_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct unix_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + +/* + * Usage: + * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) unix based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcunix_create + * binds it to an arbitrary port. The routine then starts a unix + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since unix streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + perror (_("svc_unix.c - AF_UNIX socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset (&addr, '\0', sizeof (addr)); + addr.sun_family = AF_UNIX; + len = strlen (path) + 1; + memcpy (addr.sun_path, path, len); + len += sizeof (addr.sun_family); + + bind (sock, (struct sockaddr *) &addr, len); + + if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0 + || listen (sock, 2) != 0) + { + perror (_("svc_unix.c - cannot getsockname or listen")); + if (madesock) + close (sock); + return (SVCXPRT *) NULL; + } + + r = (struct unix_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n")); + else +#endif + fputs (_("svcunix_create: out of memory\n"), stderr); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svcunix_rendezvous_op; + xprt->xp_port = -1; + xprt->xp_sock = sock; + xprt_register (xprt); + return xprt; +} + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcunixfd_create (int fd, u_int sendsize, u_int recvsize); +SVCXPRT * +svcunixfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct unix_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn)); + if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", + _("svc_unix: makefd_xprt: out of memory\n")); + else +#endif + (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct unix_conn)); + return NULL; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create (&(cd->xdrs), sendsize, recvsize, + (caddr_t) xprt, readunix, writeunix); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svcunix_op; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg attribute_unused) +{ + int sock; + struct unix_rendezvous *r; + struct sockaddr_un addr; + struct sockaddr_in in_addr; + socklen_t len; + + r = (struct unix_rendezvous *) xprt->xp_p1; +again: + len = sizeof (struct sockaddr_un); + if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0) + { + if (errno == EINTR) + goto again; + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + memset (&in_addr, '\0', sizeof (in_addr)); + in_addr.sin_family = AF_UNIX; + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static void +svcunix_destroy (SVCXPRT *xprt) +{ + struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1; + + xprt_unregister (xprt); + close (xprt->xp_sock); + if (xprt->xp_port != 0) + { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } + else + { + /* an actual connection socket */ + XDR_DESTROY (&(cd->xdrs)); + } + mem_free ((caddr_t) cd, sizeof (struct unix_conn)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + +#ifdef SCM_CREDENTIALS +struct cmessage { + struct cmsghdr cmsg; + struct ucred cmcred; + /* hack to make sure we have enough memory */ + char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))]; +}; + +/* XXX This is not thread safe, but since the main functions in svc.c + and the rpcgen generated *_svc functions for the daemon are also not + thread safe and uses static global variables, it doesn't matter. */ +static struct cmessage cm; +#endif + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = sizeof (struct cmessage); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = &cm.cmsg; + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = getpid (); + cred.uid = geteuid (); + cred.gid = getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + +/* + * reads data from the unix connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readunix (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + if ((len = __msgread (sock, buf, len)) > 0) + return len; + + fatal_err: + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; +} + +/* + * writes data to the unix connection. + * Any error is fatal and the connection is closed. + */ +static int +writeunix (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0) + { + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; + } + } + return len; +} + +static enum xprt_stat +svcunix_stat (SVCXPRT *xprt) +{ + struct unix_conn *cd = + (struct unix_conn *) (xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return XPRT_DIED; + if (!xdrrec_eof (&(cd->xdrs))) + return XPRT_MOREREQS; + return XPRT_IDLE; +} + +static bool_t +svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + xdrrec_skiprecord (xdrs); + if (xdr_callmsg (xdrs, msg)) + { + cd->x_id = msg->rm_xid; + /* set up verifiers */ +#ifdef SCM_CREDENTIALS + msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX; + msg->rm_call.cb_verf.oa_base = (caddr_t) &cm; + msg->rm_call.cb_verf.oa_length = sizeof (cm); +#endif + return TRUE; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs), + args_ptr); +} + +static bool_t +svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static bool_t +svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/libc/inet/rpc/xdr.c b/libc/inet/rpc/xdr.c new file mode 100644 index 0000000..54e7161 --- /dev/null +++ b/libc/inet/rpc/xdr.c @@ -0,0 +1,767 @@ +/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include + +#include +#include + +#ifdef USE_IN_LIBIO +# include +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(fputs) + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free (xdrproc_t proc, char *objp) +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc) (&x, objp); +} + +/* + * XDR nothing + */ +libc_hidden_proto(xdr_void) +bool_t +xdr_void (void) +{ + return TRUE; +} +libc_hidden_def(xdr_void) + +/* + * XDR long integers + * The definition of xdr_long() is kept for backward + * compatibility. Instead xdr_int() should be used. + */ +libc_hidden_proto(xdr_long) +bool_t +xdr_long (XDR *xdrs, long *lp) +{ + + if (xdrs->x_op == XDR_ENCODE + && (sizeof (int32_t) == sizeof (long) + || (int32_t) *lp == *lp)) + return XDR_PUTLONG (xdrs, lp); + + if (xdrs->x_op == XDR_DECODE) + return XDR_GETLONG (xdrs, lp); + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_long) + +/* + * XDR short integers + */ +libc_hidden_proto(xdr_short) +bool_t +xdr_short (XDR *xdrs, short *sp) +{ + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (long) *sp; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *sp = (short) l; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_short) + +/* + * XDR integers + */ +libc_hidden_proto(xdr_int) +bool_t +xdr_int (XDR *xdrs, int *ip) +{ + +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (long) *ip; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ip = (int) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif INT_MAX == LONG_MAX + return xdr_long (xdrs, (long *) ip); +#elif INT_MAX == SHRT_MAX + return xdr_short (xdrs, (short *) ip); +#else +#error unexpected integer sizes in xdr_int() +#endif +} +libc_hidden_def(xdr_int) + +/* + * XDR unsigned long integers + * The definition of xdr_u_long() is kept for backward + * compatibility. Instead xdr_u_int() should be used. + */ +libc_hidden_proto(xdr_u_long) +bool_t +xdr_u_long (XDR *xdrs, u_long *ulp) +{ + switch (xdrs->x_op) + { + case XDR_DECODE: + { + long int tmp; + + if (XDR_GETLONG (xdrs, &tmp) == FALSE) + return FALSE; + + *ulp = (uint32_t) tmp; + return TRUE; + } + + case XDR_ENCODE: + if (sizeof (uint32_t) != sizeof (u_long) + && (uint32_t) *ulp != *ulp) + return FALSE; + + return XDR_PUTLONG (xdrs, (long *) ulp); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_u_long) + +/* + * XDR unsigned integers + */ +libc_hidden_proto(xdr_u_int) +bool_t +xdr_u_int (XDR *xdrs, u_int *up) +{ +#if UINT_MAX < ULONG_MAX + u_long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * up; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *up = (u_int) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif UINT_MAX == ULONG_MAX + return xdr_u_long (xdrs, (u_long *) up); +#elif UINT_MAX == USHRT_MAX + return xdr_short (xdrs, (short *) up); +#else +#error unexpected integer sizes in xdr_u_int() +#endif +} +libc_hidden_def(xdr_u_int) + +/* + * XDR hyper integers + * same as xdr_u_hyper - open coded to save a proc call! + */ +libc_hidden_proto(xdr_hyper) +bool_t +xdr_hyper (XDR *xdrs, quad_t *llp) +{ + long t1; + unsigned long int t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (long) ((*llp) >> 32); + t2 = (long) (*llp); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + return FALSE; + *llp = ((quad_t) t1) << 32; + *llp |= t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_hyper) + + +/* + * XDR hyper integers + * same as xdr_hyper - open coded to save a proc call! + */ +libc_hidden_proto(xdr_u_hyper) +bool_t +xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) +{ + unsigned long t1; + unsigned long t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (unsigned long) ((*ullp) >> 32); + t2 = (unsigned long) (*ullp); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + return FALSE; + *ullp = ((u_quad_t) t1) << 32; + *ullp |= t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_u_hyper) + +bool_t +xdr_longlong_t (XDR *xdrs, quad_t *llp) +{ + return xdr_hyper (xdrs, llp); +} + +bool_t +xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) +{ + return xdr_u_hyper (xdrs, ullp); +} + +/* + * XDR unsigned short integers + */ +libc_hidden_proto(xdr_u_short) +bool_t +xdr_u_short (XDR *xdrs, u_short *usp) +{ + u_long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * usp; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *usp = (u_short) l; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_u_short) + + +/* + * XDR a char + */ +bool_t +xdr_char (XDR *xdrs, char *cp) +{ + int i; + + i = (*cp); + if (!xdr_int (xdrs, &i)) + { + return FALSE; + } + *cp = i; + return TRUE; +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char (XDR *xdrs, u_char *cp) +{ + u_int u; + + u = (*cp); + if (!xdr_u_int (xdrs, &u)) + { + return FALSE; + } + *cp = u; + return TRUE; +} + +/* + * XDR booleans + */ +libc_hidden_proto(xdr_bool) +bool_t +xdr_bool (XDR *xdrs, bool_t *bp) +{ + long lb; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return XDR_PUTLONG (xdrs, &lb); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &lb)) + { + return FALSE; + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_bool) + +/* + * XDR enumerations + */ +libc_hidden_proto(xdr_enum) +bool_t +xdr_enum (XDR *xdrs, enum_t *ep) +{ + enum sizecheck + { + SIZEVAL + }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == 4) + { +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = *ep; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ep = l; + case XDR_FREE: + return TRUE; + + } + return FALSE; +#else + return xdr_long (xdrs, (long *) ep); +#endif + } + else if (sizeof (enum sizecheck) == sizeof (short)) + { + return xdr_short (xdrs, (short *) ep); + } + else + { + return FALSE; + } +} +libc_hidden_def(xdr_enum) + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +libc_hidden_proto(xdr_opaque) +bool_t +xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) +{ + u_int rndup; + static char crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return TRUE; + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + switch (xdrs->x_op) + { + case XDR_DECODE: + if (!XDR_GETBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup); + + case XDR_ENCODE: + if (!XDR_PUTBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_PUTBYTES (xdrs, xdr_zero, rndup); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_opaque) + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +libc_hidden_proto(xdr_bytes) +bool_t +xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (nodesize == 0) + { + return TRUE; + } + if (sp == NULL) + { + *cpp = sp = (char *) mem_alloc (nodesize); + } + if (sp == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n")); + else +#endif + (void) fputs (_("xdr_bytes: out of memory\n"), stderr); + return FALSE; + } + /* fall into ... */ + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, nodesize); + + case XDR_FREE: + if (sp != NULL) + { + mem_free (sp, nodesize); + *cpp = NULL; + } + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_bytes) + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj (xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); +} + +/* + * XDR a discriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +libc_hidden_proto(xdr_union) +bool_t +xdr_union (XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault) +{ + enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (!xdr_enum (xdrs, dscmp)) + { + return FALSE; + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) + { + if (choices->value == dscm) + return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault) (xdrs, unp, LASTUNSIGNED)); +} +libc_hidden_def(xdr_union) + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +libc_hidden_proto(xdr_string) +bool_t +xdr_string (XDR *xdrs, char **cpp, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) + { + case XDR_FREE: + if (sp == NULL) + { + return TRUE; /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + if (sp == NULL) + return FALSE; + size = strlen (sp); + break; + case XDR_DECODE: + break; + } + if (!xdr_u_int (xdrs, &size)) + { + return FALSE; + } + if (size > maxsize) + { + return FALSE; + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (nodesize == 0) + { + return TRUE; + } + if (sp == NULL) + *cpp = sp = (char *) mem_alloc (nodesize); + if (sp == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_string: out of memory\n")); + else +#endif + (void) fputs (_("xdr_string: out of memory\n"), stderr); + return FALSE; + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, size); + + case XDR_FREE: + mem_free (sp, nodesize); + *cpp = NULL; + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_string) + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring (xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + if (xdr_string (xdrs, cpp, LASTUNSIGNED)) + { + return TRUE; + } + return FALSE; +} diff --git a/libc/inet/rpc/xdr_array.c b/libc/inet/rpc/xdr_array.c new file mode 100644 index 0000000..a2299b6 --- /dev/null +++ b/libc/inet/rpc/xdr_array.c @@ -0,0 +1,180 @@ +/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_array.c, Generic XDR routines implementation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(fputs) +libc_hidden_proto(xdr_u_int) + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +libc_hidden_proto(xdr_array) +bool_t +xdr_array (XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, xdrproc_t elproc) +{ + u_int i; + caddr_t target = *addrp; + u_int c; /* the actual element count */ + bool_t stat = TRUE; + u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + c = *sizep; + /* + * XXX: Let the overflow possibly happen with XDR_FREE because mem_free() + * doesn't actually use its second argument anyway. + */ + if ((c > maxsize || c > UINT_MAX / elsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) + { + case XDR_DECODE: + if (c == 0) + return TRUE; + *addrp = target = mem_alloc (nodesize); + if (target == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_array: out of memory\n")); + else +#endif + (void) fputs (_("xdr_array: out of memory\n"), stderr); + return FALSE; + } + memset (target, 0, nodesize); + break; + + case XDR_FREE: + return TRUE; + default: + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) + { + stat = (*elproc) (xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) + { + mem_free (*addrp, nodesize); + *addrp = NULL; + } + return stat; +} +libc_hidden_def(xdr_array) + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector (xdrs, basep, nelem, elemsize, xdr_elem) + XDR *xdrs; + char *basep; + u_int nelem; + u_int elemsize; + xdrproc_t xdr_elem; +{ + u_int i; + char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) + { + if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) + { + return FALSE; + } + elptr += elemsize; + } + return TRUE; +} diff --git a/libc/inet/rpc/xdr_float.c b/libc/inet/rpc/xdr_float.c new file mode 100644 index 0000000..03632c5 --- /dev/null +++ b/libc/inet/rpc/xdr_float.c @@ -0,0 +1,310 @@ +/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_float.c, Generic XDR routines implementation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "floating point" xdr routines used to (de)serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include + +#include +#include + +/* + * NB: Not portable. + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#define LSW (__FLOAT_WORD_ORDER == __BIG_ENDIAN) + +#ifdef vax + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int mantissa: 23; + unsigned int exp : 8; + unsigned int sign : 1; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} sgl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x0, 0xff, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; +#endif /* vax */ + +bool_t +xdr_float(xdrs, fp) + XDR *xdrs; + float *fp; +{ +#ifdef vax + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTLONG(xdrs, (long *)&is)); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_PUTLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp = *(int *)fp; + return (XDR_PUTLONG(xdrs, &tmp)); + } + break; +#endif + + case XDR_DECODE: +#ifdef vax + vsp = (struct vax_single *)fp; + if (!XDR_GETLONG(xdrs, (long *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_GETLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp; + if (XDR_GETLONG(xdrs, &tmp)) { + *(int *)fp = tmp; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#ifdef vax +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int mantissa1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mantissa2 : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; + +#endif /* vax */ + + +bool_t +xdr_double(xdrs, dp) + XDR *xdrs; + double *dp; +{ +#ifdef vax + struct ieee_double id; + struct vax_double vd; + register struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + vd = *((struct vax_double *)dp); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((vd.mantissa4 == lim->d.mantissa4) && + (vd.mantissa3 == lim->d.mantissa3) && + (vd.mantissa2 == lim->d.mantissa2) && + (vd.mantissa1 == lim->d.mantissa1) && + (vd.exp == lim->d.exp)) { + id = lim->ieee; + goto shipit; + } + } + id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); + id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | + (vd.mantissa3 << 13) | + ((vd.mantissa4 >> 3) & MASK(13)); + shipit: + id.sign = vd.sign; + dp = (double *)&id; +#endif + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_PUTLONG(xdrs, lp+!LSW) && + XDR_PUTLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + tmp[0] = ip[!LSW]; + tmp[1] = ip[LSW]; + return (XDR_PUTLONG(xdrs, tmp) && + XDR_PUTLONG(xdrs, tmp+1)); + } + break; + + case XDR_DECODE: +#ifdef vax + lp = (long *)&id; + if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#else + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_GETLONG(xdrs, lp+!LSW) && + XDR_GETLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + if (XDR_GETLONG(xdrs, tmp+!LSW) && + XDR_GETLONG(xdrs, tmp+LSW)) { + ip[0] = tmp[0]; + ip[1] = tmp[1]; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} diff --git a/libc/inet/rpc/xdr_intXX_t.c b/libc/inet/rpc/xdr_intXX_t.c new file mode 100644 index 0000000..d36d162 --- /dev/null +++ b/libc/inet/rpc/xdr_intXX_t.c @@ -0,0 +1,203 @@ +/* Copyright (c) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* XDR 64bit integers */ +bool_t +xdr_int64_t (XDR *xdrs, int64_t *ip) +{ + int32_t t1; + /* This must be unsigned, otherwise we get problems with sign + extension in the DECODE case. */ + uint32_t t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (int32_t) ((*ip) >> 32); + t2 = (int32_t) (*ip); + return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, &t2)) + return FALSE; + *ip = ((int64_t) t1) << 32; + *ip |= t2; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 64bit unsigned integers */ +bool_t +xdr_uint64_t (XDR *xdrs, uint64_t *uip) +{ + uint32_t t1; + uint32_t t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (uint32_t) ((*uip) >> 32); + t2 = (uint32_t) (*uip); + return (XDR_PUTINT32 (xdrs, (int32_t *) &t1) && + XDR_PUTINT32(xdrs, (int32_t *) &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, (int32_t *) &t1) || + !XDR_GETINT32(xdrs, (int32_t *) &t2)) + return FALSE; + *uip = ((uint64_t) t1) << 32; + *uip |= t2; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 32bit integers */ +bool_t +xdr_int32_t (XDR *xdrs, int32_t *lp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, lp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, lp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 32bit unsigned integers */ +bool_t +xdr_uint32_t (XDR *xdrs, uint32_t *ulp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, (int32_t *) ulp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, (int32_t *) ulp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 16bit integers */ +bool_t +xdr_int16_t (XDR *xdrs, int16_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int16_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 16bit unsigned integers */ +bool_t +xdr_uint16_t (XDR *xdrs, uint16_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint16_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 8bit integers */ +bool_t +xdr_int8_t (XDR *xdrs, int8_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int8_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 8bit unsigned integers */ +bool_t +xdr_uint8_t (XDR *xdrs, uint8_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint8_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} diff --git a/libc/inet/rpc/xdr_mem.c b/libc/inet/rpc/xdr_mem.c new file mode 100644 index 0000000..b7410c4 --- /dev/null +++ b/libc/inet/rpc/xdr_mem.c @@ -0,0 +1,241 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +static bool_t xdrmem_getlong (XDR *, long *); +static bool_t xdrmem_putlong (XDR *, const long *); +static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrmem_putbytes (XDR *, const char *, u_int); +static u_int xdrmem_getpos (const XDR *); +static bool_t xdrmem_setpos (XDR *, u_int); +static int32_t *xdrmem_inline (XDR *, u_int); +static void xdrmem_destroy (XDR *); +static bool_t xdrmem_getint32 (XDR *, int32_t *); +static bool_t xdrmem_putint32 (XDR *, const int32_t *); + +static const struct xdr_ops xdrmem_ops = +{ + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy, + xdrmem_getint32, + xdrmem_putint32 +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +libc_hidden_proto(xdrmem_create) +void +xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} +libc_hidden_def(xdrmem_create) + +/* + * Nothing needs to be done for the memory case. The argument is clearly + * const. + */ + +static void +xdrmem_destroy (XDR *xdrs attribute_unused) +{ +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the long pointed to by lp. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getlong (XDR *xdrs, long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putlong (XDR *xdrs, const long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*lp); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Gets an unaligned number of bytes from the xdrs structure and writes them + * to the address passed in addr. Be very careful when calling this routine + * as it could leave the xdrs pointing to an unaligned structure which is not + * a good idea. None of the things pointed to are const. + */ +static bool_t +xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (addr, xdrs->x_private, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * The complementary function to the above. The same warnings apply about + * unaligned data. The source address is const. + */ +static bool_t +xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (xdrs->x_private, addr, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * Not sure what this one does. But it clearly doesn't modify the contents + * of xdrs. **FIXME** does this not assume u_int == u_long? + */ +static u_int +xdrmem_getpos (const XDR *xdrs) +{ + return (u_long) xdrs->x_private - (u_long) xdrs->x_base; +} + +/* + * xdrs modified + */ +static bool_t +xdrmem_setpos (xdrs, pos) + XDR *xdrs; + u_int pos; +{ + caddr_t newaddr = xdrs->x_base + pos; + caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long) newaddr > (long) lastaddr + || (UINT_MAX < LONG_MAX + && (long) UINT_MAX < (long) lastaddr - (long) newaddr)) + return FALSE; + xdrs->x_private = newaddr; + xdrs->x_handy = (long) lastaddr - (long) newaddr; + return TRUE; +} + +/* + * xdrs modified + */ +static int32_t * +xdrmem_inline (XDR *xdrs, u_int len) +{ + int32_t *buf = 0; + + if (xdrs->x_handy >= len) + { + xdrs->x_handy -= len; + buf = (int32_t *) xdrs->x_private; + xdrs->x_private += len; + } + return buf; +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the int pointed to by ip. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getint32 (XDR *xdrs, int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *ip = ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putint32 (XDR *xdrs, const int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*ip); + xdrs->x_private += 4; + return TRUE; +} diff --git a/libc/inet/rpc/xdr_rec.c b/libc/inet/rpc/xdr_rec.c new file mode 100644 index 0000000..ac331c4 --- /dev/null +++ b/libc/inet/rpc/xdr_rec.c @@ -0,0 +1,675 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). The high order bit encodes + * whether or not the fragment is the last fragment of the record + * (1 => fragment is last, 0 => more fragments to follow. + * The other 31 bits encode the byte length of the fragment. + */ + +#define __FORCE_GLIBC +#include + + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(fputs) +libc_hidden_proto(lseek) + +static bool_t xdrrec_getlong (XDR *, long *); +static bool_t xdrrec_putlong (XDR *, const long *); +static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrrec_putbytes (XDR *, const char *, u_int); +static u_int xdrrec_getpos (const XDR *); +static bool_t xdrrec_setpos (XDR *, u_int); +static int32_t *xdrrec_inline (XDR *, u_int); +static void xdrrec_destroy (XDR *); +static bool_t xdrrec_getint32 (XDR *, int32_t *); +static bool_t xdrrec_putint32 (XDR *, const int32_t *); + +static const struct xdr_ops xdrrec_ops = { + xdrrec_getlong, + xdrrec_putlong, + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy, + xdrrec_getint32, + xdrrec_putint32 +}; + +/* + * A record is composed of one or more record fragments. + * A record fragment is a two-byte header followed by zero to + * 2**32-1 bytes. The header is treated as a long unsigned and is + * encode/decoded to the network via htonl/ntohl. The low order 31 bits + * are a byte count of the fragment. The highest order bit is a boolean: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG (1UL << 31) + +typedef struct rec_strm + { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-going bits + */ + int (*writeit) (char *, char *, int); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of curren fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit) (char *, char *, int); + u_long in_size; /* fixed size of the input buffer */ + caddr_t in_base; + caddr_t in_finger; /* location of next byte to be had */ + caddr_t in_boundry; /* can read up to this location */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; + } +RECSTREAM; + +static u_int fix_buf_size (u_int) internal_function; +static bool_t skip_input_bytes (RECSTREAM *, long) internal_function; +static bool_t flush_out (RECSTREAM *, bool_t) internal_function; +static bool_t set_input_fragment (RECSTREAM *) internal_function; +static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function; + +/* + * Create an xdr handle for xdrrec + * xdrrec_create fills in xdrs. Sendsize and recvsize are + * send and recv buffer sizes (0 => use default). + * tcp_handle is an opaque handle that is passed as the first parameter to + * the procedures readit and writeit. Readit and writeit are read and + * write respectively. They are like the system + * calls expect that they take an opaque handle rather than an fd. + */ +libc_hidden_proto(xdrrec_create) +void +xdrrec_create (XDR *xdrs, u_int sendsize, + u_int recvsize, caddr_t tcp_handle, + int (*readit) (char *, char *, int), + int (*writeit) (char *, char *, int)) +{ + RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM)); + caddr_t tmp; + char *buf; + + sendsize = fix_buf_size (sendsize); + recvsize = fix_buf_size (recvsize); + buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT); + + if (rstrm == NULL || buf == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("xdrrec_create: out of memory\n")); + else +#endif + (void) fputs (_("xdrrec_create: out of memory\n"), stderr); + mem_free (rstrm, sizeof (RECSTREAM)); + mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT); + /* + * This is bad. Should rework xdrrec_create to + * return a handle, and in this case return NULL + */ + return; + } + /* + * adjust sizes and allocate buffer quad byte aligned + */ + rstrm->sendsize = sendsize; + rstrm->recvsize = recvsize; + rstrm->the_buffer = buf; + tmp = rstrm->the_buffer; + if ((size_t)tmp % BYTES_PER_XDR_UNIT) + tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT; + rstrm->out_base = tmp; + rstrm->in_base = tmp + sendsize; + /* + * now the rest ... + */ + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops; + xdrs->x_private = (caddr_t) rstrm; + rstrm->tcp_handle = tcp_handle; + rstrm->readit = readit; + rstrm->writeit = writeit; + rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger += 4; + rstrm->out_boundry += sendsize; + rstrm->frag_sent = FALSE; + rstrm->in_size = recvsize; + rstrm->in_boundry = rstrm->in_base; + rstrm->in_finger = (rstrm->in_boundry += recvsize); + rstrm->fbtbc = 0; + rstrm->last_frag = TRUE; +} +libc_hidden_def(xdrrec_create) + + +/* + * The routines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getlong (XDR *xdrs, long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *buflp = (int32_t *) rstrm->in_finger; + int32_t mylong; + + /* first try the inline, fast case */ + if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && + rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT) + { + *lp = (int32_t) ntohl (*buflp); + rstrm->fbtbc -= BYTES_PER_XDR_UNIT; + rstrm->in_finger += BYTES_PER_XDR_UNIT; + } + else + { + if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong, + BYTES_PER_XDR_UNIT)) + return FALSE; + *lp = (int32_t) ntohl (mylong); + } + return TRUE; +} + +static bool_t +xdrrec_putlong (XDR *xdrs, const long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *dest_lp = (int32_t *) rstrm->out_finger; + + if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) + { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= BYTES_PER_XDR_UNIT; + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + dest_lp = (int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + } + *dest_lp = htonl (*lp); + return TRUE; +} + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int current; + + while (len > 0) + { + current = rstrm->fbtbc; + if (current == 0) + { + if (rstrm->last_frag) + return FALSE; + if (!set_input_fragment (rstrm)) + return FALSE; + continue; + } + current = (len < current) ? len : current; + if (!get_input_bytes (rstrm, addr, current)) + return FALSE; + addr += current; + rstrm->fbtbc -= current; + len -= current; + } + return TRUE; +} + +static bool_t +xdrrec_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int current; + + while (len > 0) + { + current = rstrm->out_boundry - rstrm->out_finger; + current = (len < current) ? len : current; + memcpy (rstrm->out_finger, addr, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry && len > 0) + { + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + } + } + return TRUE; +} + +static u_int +xdrrec_getpos (const XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + long pos; + + pos = lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1); + if (pos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = (u_int) - 1; + break; + } + return (u_int) pos; +} + +static bool_t +xdrrec_setpos (XDR *xdrs, u_int pos) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int currpos = xdrrec_getpos (xdrs); + int delta = currpos - pos; + caddr_t newpos; + + if ((int) currpos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if (newpos > (caddr_t) rstrm->frag_header && + newpos < rstrm->out_boundry) + { + rstrm->out_finger = newpos; + return TRUE; + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int) (rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) + { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return TRUE; + } + break; + + default: + break; + } + return FALSE; +} + +static int32_t * +xdrrec_inline (XDR *xdrs, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *buf = NULL; + + switch (xdrs->x_op) + { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) + { + buf = (int32_t *) rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) + { + buf = (int32_t *) rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + + default: + break; + } + return buf; +} + +static void +xdrrec_destroy (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + mem_free (rstrm->the_buffer, + rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); + mem_free ((caddr_t) rstrm, sizeof (RECSTREAM)); +} + +static bool_t +xdrrec_getint32 (XDR *xdrs, int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *bufip = (int32_t *) rstrm->in_finger; + int32_t mylong; + + /* first try the inline, fast case */ + if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && + rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT) + { + *ip = ntohl (*bufip); + rstrm->fbtbc -= BYTES_PER_XDR_UNIT; + rstrm->in_finger += BYTES_PER_XDR_UNIT; + } + else + { + if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong, + BYTES_PER_XDR_UNIT)) + return FALSE; + *ip = ntohl (mylong); + } + return TRUE; +} + +static bool_t +xdrrec_putint32 (XDR *xdrs, const int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *dest_ip = (int32_t *) rstrm->out_finger; + + if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) + { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= BYTES_PER_XDR_UNIT; + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + dest_ip = (int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + } + *dest_ip = htonl (*ip); + return TRUE; +} + +/* + * Exported routines to manage xdr records + */ + +/* + * Before reading (deserializing from the stream, one should always call + * this procedure to guarantee proper record alignment. + */ +libc_hidden_proto(xdrrec_skiprecord) +bool_t +xdrrec_skiprecord (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) + { + if (!skip_input_bytes (rstrm, rstrm->fbtbc)) + return FALSE; + rstrm->fbtbc = 0; + if ((!rstrm->last_frag) && (!set_input_fragment (rstrm))) + return FALSE; + } + rstrm->last_frag = FALSE; + return TRUE; +} +libc_hidden_def(xdrrec_skiprecord) + +/* + * Lookahead function. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +libc_hidden_proto(xdrrec_eof) +bool_t +xdrrec_eof (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) + { + if (!skip_input_bytes (rstrm, rstrm->fbtbc)) + return TRUE; + rstrm->fbtbc = 0; + if ((!rstrm->last_frag) && (!set_input_fragment (rstrm))) + return TRUE; + } + if (rstrm->in_finger == rstrm->in_boundry) + return TRUE; + return FALSE; +} +libc_hidden_def(xdrrec_eof) + +/* + * The client must tell the package when an end-of-record has occurred. + * The second parameter tells whether the record should be flushed to the + * (output) tcp stream. (This lets the package support batched or + * pipelined procedure calls.) TRUE => immediate flush to tcp connection. + */ +libc_hidden_proto(xdrrec_endofrecord) +bool_t +xdrrec_endofrecord (XDR *xdrs, bool_t sendnow) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent + || rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry) + { + rstrm->frag_sent = FALSE; + return flush_out (rstrm, TRUE); + } + len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + *rstrm->frag_header = htonl ((u_long) len | LAST_FRAG); + rstrm->frag_header = (u_int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + return TRUE; +} +libc_hidden_def(xdrrec_endofrecord) + +/* + * Internal useful routines + */ +static bool_t +internal_function +flush_out (RECSTREAM *rstrm, bool_t eor) +{ + u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; + u_long len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + + *rstrm->frag_header = htonl (len | eormask); + len = rstrm->out_finger - rstrm->out_base; + if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len) + != (int) len) + return FALSE; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT; + return TRUE; +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf (RECSTREAM *rstrm) +{ + caddr_t where; + size_t i; + int len; + + where = rstrm->in_base; + i = (size_t) rstrm->in_boundry % BYTES_PER_XDR_UNIT; + where += i; + len = rstrm->in_size - i; + if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1) + return FALSE; + rstrm->in_finger = where; + where += len; + rstrm->in_boundry = where; + return TRUE; +} + +static bool_t /* knows nothing about records! Only about input buffers */ +internal_function +get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len) +{ + int current; + + while (len > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (len < current) ? len : current; + memcpy (addr, rstrm->in_finger, current); + rstrm->in_finger += current; + addr += current; + len -= current; + } + return TRUE; +} + +static bool_t /* next two bytes of the input stream are treated as a header */ +internal_function +set_input_fragment (RECSTREAM *rstrm) +{ + uint32_t header; + + if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT)) + return FALSE; + header = ntohl (header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect fragment + * sizes. Unfortunately, only a size of zero can be identified as + * 'wildely incorrect', and this only, if it is not the last + * fragment of a message. Ridiculously large fragment sizes may look + * wrong, but we don't have any way to be certain that they aren't + * what the client actually intended to send us. Many existing RPC + * implementations may sent a fragment of size zero as the last + * fragment of a message. + */ + if (header == 0) + return FALSE; + rstrm->fbtbc = header & ~LAST_FRAG; + return TRUE; +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +internal_function +skip_input_bytes (RECSTREAM *rstrm, long cnt) +{ + int current; + + while (cnt > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (cnt < current) ? cnt : current; + rstrm->in_finger += current; + cnt -= current; + } + return TRUE; +} + +static u_int +internal_function +fix_buf_size (u_int s) +{ + if (s < 100) + s = 4000; + return RNDUP (s); +} diff --git a/libc/inet/rpc/xdr_reference.c b/libc/inet/rpc/xdr_reference.c new file mode 100644 index 0000000..6282f9c --- /dev/null +++ b/libc/inet/rpc/xdr_reference.c @@ -0,0 +1,156 @@ +/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; +#endif + +/* + * xdr_reference.c, Generic XDR routines implementation. + * + * Copyright (C) 1987, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * "pointers". See xdr.h for more info on the interface to xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +libc_hidden_proto(fwprintf) +#endif + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(xdr_bool) +libc_hidden_proto(fputs) + +#define LASTUNSIGNED ((u_int)0-1) + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the size of the referneced structure. + * proc is the routine to handle the referenced structure. + */ +libc_hidden_proto(xdr_reference) +bool_t +xdr_reference (XDR *xdrs, caddr_t *pp, u_int size, xdrproc_t proc) +{ + caddr_t loc = *pp; + bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) + { + case XDR_FREE: + return TRUE; + + case XDR_DECODE: + *pp = loc = (caddr_t) mem_alloc (size); + if (loc == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_reference: out of memory\n")); + else +#endif + (void) fputs (_("xdr_reference: out of memory\n"), stderr); + return FALSE; + } + memset (loc, 0, (int) size); + break; + default: + break; + } + + stat = (*proc) (xdrs, loc, LASTUNSIGNED); + + if (xdrs->x_op == XDR_FREE) + { + mem_free (loc, size); + *pp = NULL; + } + return stat; +} +libc_hidden_def(xdr_reference) + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialize + * trees correctly. + * + * What's sent is actually a union: + * + * union object_pointer switch (boolean b) { + * case TRUE: object_data data; + * case FALSE: void nothing; + * } + * + * > objpp: Pointer to the pointer to the object. + * > obj_size: size of the object. + * > xdr_obj: routine to XDR an object. + * + */ +bool_t +xdr_pointer (xdrs, objpp, obj_size, xdr_obj) + XDR *xdrs; + char **objpp; + u_int obj_size; + xdrproc_t xdr_obj; +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (!xdr_bool (xdrs, &more_data)) + { + return FALSE; + } + if (!more_data) + { + *objpp = NULL; + return TRUE; + } + return xdr_reference (xdrs, objpp, obj_size, xdr_obj); +} diff --git a/libc/inet/rpc/xdr_stdio.c b/libc/inet/rpc/xdr_stdio.c new file mode 100644 index 0000000..32689e1 --- /dev/null +++ b/libc/inet/rpc/xdr_stdio.c @@ -0,0 +1,200 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements a XDR on a stdio stream. + * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes + * from the stream. + */ + +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define fflush(s) _IO_fflush (s) +# define fread(p, m, n, s) _IO_fread (p, m, n, s) +# define ftell(s) _IO_ftell (s) +# define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s) +#endif + +libc_hidden_proto(fread) +libc_hidden_proto(fwrite) +libc_hidden_proto(fseek) +libc_hidden_proto(fflush) +libc_hidden_proto(ftell) + +static bool_t xdrstdio_getlong (XDR *, long *); +static bool_t xdrstdio_putlong (XDR *, const long *); +static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrstdio_putbytes (XDR *, const char *, u_int); +static u_int xdrstdio_getpos (const XDR *); +static bool_t xdrstdio_setpos (XDR *, u_int); +static int32_t *xdrstdio_inline (XDR *, u_int); +static void xdrstdio_destroy (XDR *); +static bool_t xdrstdio_getint32 (XDR *, int32_t *); +static bool_t xdrstdio_putint32 (XDR *, const int32_t *); + +/* + * Ops vector for stdio type XDR + */ +static const struct xdr_ops xdrstdio_ops = +{ + xdrstdio_getlong, /* deserialize a long int */ + xdrstdio_putlong, /* serialize a long int */ + xdrstdio_getbytes, /* deserialize counted bytes */ + xdrstdio_putbytes, /* serialize counted bytes */ + xdrstdio_getpos, /* get offset in the stream */ + xdrstdio_setpos, /* set offset in the stream */ + xdrstdio_inline, /* prime stream for inline macros */ + xdrstdio_destroy, /* destroy stream */ + xdrstdio_getint32, /* deserialize a int */ + xdrstdio_putint32 /* serialize a int */ +}; + +/* + * Initialize a stdio xdr stream. + * Sets the xdr stream handle xdrs for use on the stream file. + * Operation flag is set to op. + */ +void +xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops; + xdrs->x_private = (caddr_t) file; + xdrs->x_handy = 0; + xdrs->x_base = 0; +} + +/* + * Destroy a stdio xdr stream. + * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. + */ +static void +xdrstdio_destroy (XDR *xdrs) +{ + (void) fflush ((FILE *) xdrs->x_private); + /* xx should we close the file ?? */ +}; + +static bool_t +xdrstdio_getlong (XDR *xdrs, long *lp) +{ + u_int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *lp = (long) ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putlong (XDR *xdrs, const long *lp) +{ + int32_t mycopy = htonl ((u_int32_t) *lp); + + if (fwrite ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_getbytes (XDR *xdrs, const caddr_t addr, u_int len) +{ + if ((len != 0) && (fread (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if ((len != 0) && (fwrite (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static u_int +xdrstdio_getpos (const XDR *xdrs) +{ + return (u_int) ftell ((FILE *) xdrs->x_private); +} + +static bool_t +xdrstdio_setpos (XDR *xdrs, u_int pos) +{ + return fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0 ? FALSE : TRUE; +} + +static int32_t * +xdrstdio_inline (XDR *xdrs attribute_unused, u_int len attribute_unused) +{ + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return NULL; +} + +static bool_t +xdrstdio_getint32 (XDR *xdrs, int32_t *ip) +{ + int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *ip = ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putint32 (XDR *xdrs, const int32_t *ip) +{ + int32_t mycopy = htonl (*ip); + + ip = &mycopy; + if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} diff --git a/libc/inet/send.c b/libc/inet/send.c new file mode 100644 index 0000000..6b7d44b --- /dev/null +++ b/libc/inet/send.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_send +#include "socketcalls.c" diff --git a/libc/inet/sendmsg.c b/libc/inet/sendmsg.c new file mode 100644 index 0000000..834e839 --- /dev/null +++ b/libc/inet/sendmsg.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sendmsg +#include "socketcalls.c" diff --git a/libc/inet/sendto.c b/libc/inet/sendto.c new file mode 100644 index 0000000..328baa3 --- /dev/null +++ b/libc/inet/sendto.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sendto +#include "socketcalls.c" diff --git a/libc/inet/setsockopt.c b/libc/inet/setsockopt.c new file mode 100644 index 0000000..b0f4a4e --- /dev/null +++ b/libc/inet/setsockopt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_setsockopt +#include "socketcalls.c" diff --git a/libc/inet/shutdown.c b/libc/inet/shutdown.c new file mode 100644 index 0000000..0bcdb9f --- /dev/null +++ b/libc/inet/shutdown.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shutdown +#include "socketcalls.c" diff --git a/libc/inet/socket.c b/libc/inet/socket.c new file mode 100644 index 0000000..752744b --- /dev/null +++ b/libc/inet/socket.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_socket +#include "socketcalls.c" diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c new file mode 100644 index 0000000..e57c045 --- /dev/null +++ b/libc/inet/socketcalls.c @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +#ifdef __NR_socketcall +extern int __socketcall(int call, unsigned long *args) attribute_hidden; + +/* Various socketcall numbers */ +#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 +#endif + + +#ifdef L_accept +extern __typeof(accept) __libc_accept; +#ifdef __NR_accept +#define __NR___libc_accept __NR_accept +_syscall3(int, __libc_accept, int, call, struct sockaddr *, addr, socklen_t *,addrlen) +#elif defined(__NR_socketcall) +int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen) +{ + unsigned long args[3]; + + args[0] = s; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) addrlen; + return __socketcall(SYS_ACCEPT, args); +} +#endif +libc_hidden_proto(accept) +weak_alias(__libc_accept,accept) +libc_hidden_weak(accept) +#endif + +#ifdef L_bind +libc_hidden_proto(bind) +#ifdef __NR_bind +_syscall3(int, bind, int, sockfd, const struct sockaddr *, myaddr, socklen_t, addrlen) +#elif defined(__NR_socketcall) +int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) myaddr; + args[2] = addrlen; + return __socketcall(SYS_BIND, args); +} +#endif +libc_hidden_def(bind) +#endif + +#ifdef L_connect +extern __typeof(connect) __libc_connect; +#ifdef __NR_connect +#define __NR___libc_connect __NR_connect +_syscall3(int, __libc_connect, int, sockfd, const struct sockaddr *, saddr, socklen_t, addrlen) +#elif defined(__NR_socketcall) +int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) saddr; + args[2] = addrlen; + return __socketcall(SYS_CONNECT, args); +} +#endif +libc_hidden_proto(connect) +weak_alias(__libc_connect,connect) +libc_hidden_weak(connect) +#endif + +#ifdef L_getpeername +#ifdef __NR_getpeername +_syscall3(int, getpeername, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen) +#elif defined(__NR_socketcall) +int getpeername(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) paddrlen; + return __socketcall(SYS_GETPEERNAME, args); +} +#endif +#endif + +#ifdef L_getsockname +libc_hidden_proto(getsockname) +#ifdef __NR_getsockname +_syscall3(int, getsockname, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen) +#elif defined(__NR_socketcall) +int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) paddrlen; + return __socketcall(SYS_GETSOCKNAME, args); +} +#endif +libc_hidden_def(getsockname) +#endif + +#ifdef L_getsockopt +#ifdef __NR_getsockopt +_syscall5(int, getsockopt, int, fd, int, level, int, optname, __ptr_t, optval, socklen_t *, optlen) +#elif defined(__NR_socketcall) +int getsockopt(int fd, int level, int optname, __ptr_t optval, + socklen_t * optlen) +{ + unsigned long args[5]; + + args[0] = fd; + args[1] = level; + args[2] = optname; + args[3] = (unsigned long) optval; + args[4] = (unsigned long) optlen; + return (__socketcall(SYS_GETSOCKOPT, args)); +} +#endif +#endif + +#ifdef L_listen +libc_hidden_proto(listen) +#ifdef __NR_listen +_syscall2(int, listen, int, sockfd, int, backlog) +#elif defined(__NR_socketcall) +int listen(int sockfd, int backlog) +{ + unsigned long args[2]; + + args[0] = sockfd; + args[1] = backlog; + return __socketcall(SYS_LISTEN, args); +} +#endif +libc_hidden_def(listen) +#endif + +#ifdef L_recv +extern __typeof(recv) __libc_recv; +#ifdef __NR_recv +#define __NR___libc_recv __NR_recv +_syscall4(ssize_t, __libc_recv, int, sockfd, __ptr_t, buffer, size_t, len, + int, flags) +#elif defined(__NR_socketcall) +/* recv, recvfrom added by bir7@leland.stanford.edu */ +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + unsigned long args[4]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + return (__socketcall(SYS_RECV, args)); +} +#elif defined(__NR_recvfrom) +libc_hidden_proto(recvfrom) +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + return (recvfrom(sockfd, buffer, len, flags, NULL, NULL)); +} +#endif +libc_hidden_proto(recv) +weak_alias(__libc_recv,recv) +libc_hidden_weak(recv) +#endif + +#ifdef L_recvfrom +extern __typeof(recvfrom) __libc_recvfrom; +#ifdef __NR_recvfrom +#define __NR___libc_recvfrom __NR_recvfrom +_syscall6(ssize_t, __libc_recvfrom, int, sockfd, __ptr_t, buffer, size_t, len, + int, flags, struct sockaddr *, to, socklen_t *, tolen) +#elif defined(__NR_socketcall) +/* recv, recvfrom added by bir7@leland.stanford.edu */ +ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags, + struct sockaddr *to, socklen_t * tolen) +{ + unsigned long args[6]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + args[4] = (unsigned long) to; + args[5] = (unsigned long) tolen; + return (__socketcall(SYS_RECVFROM, args)); +} +#endif +libc_hidden_proto(recvfrom) +weak_alias(__libc_recvfrom,recvfrom) +libc_hidden_weak(recvfrom) +#endif + +#ifdef L_recvmsg +extern __typeof(recvmsg) __libc_recvmsg; +#ifdef __NR_recvmsg +#define __NR___libc_recvmsg __NR_recvmsg +_syscall3(ssize_t, __libc_recvmsg, int, sockfd, struct msghdr *, msg, int, flags) +#elif defined(__NR_socketcall) +ssize_t __libc_recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) msg; + args[2] = flags; + return (__socketcall(SYS_RECVMSG, args)); +} +#endif +libc_hidden_proto(recvmsg) +weak_alias(__libc_recvmsg,recvmsg) +libc_hidden_weak(recvmsg) +#endif + +#ifdef L_send +extern __typeof(send) __libc_send; +#ifdef __NR_send +#define __NR___libc_send __NR_send +_syscall4(ssize_t, __libc_send, int, sockfd, const void *, buffer, size_t, len, int, flags) +#elif defined(__NR_socketcall) +/* send, sendto added by bir7@leland.stanford.edu */ +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + unsigned long args[4]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + return (__socketcall(SYS_SEND, args)); +} +#elif defined(__NR_sendto) +libc_hidden_proto(sendto) +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + return (sendto(sockfd, buffer, len, flags, NULL, 0)); +} +#endif +libc_hidden_proto(send) +weak_alias(__libc_send,send) +libc_hidden_weak(send) +#endif + +#ifdef L_sendmsg +extern __typeof(sendmsg) __libc_sendmsg; +#ifdef __NR_sendmsg +#define __NR___libc_sendmsg __NR_sendmsg +_syscall3(ssize_t, __libc_sendmsg, int, sockfd, const struct msghdr *, msg, int, flags) +#elif defined(__NR_socketcall) +ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) msg; + args[2] = flags; + return (__socketcall(SYS_SENDMSG, args)); +} +#endif +libc_hidden_proto(sendmsg) +weak_alias(__libc_sendmsg,sendmsg) +libc_hidden_weak(sendmsg) +#endif + +#ifdef L_sendto +extern __typeof(sendto) __libc_sendto; +#ifdef __NR_sendto +#define __NR___libc_sendto __NR_sendto +_syscall6(ssize_t, __libc_sendto, int, sockfd, const void *, buffer, + size_t, len, int, flags, const struct sockaddr *, to, socklen_t, tolen) +#elif defined(__NR_socketcall) +/* send, sendto added by bir7@leland.stanford.edu */ +ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + unsigned long args[6]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + args[4] = (unsigned long) to; + args[5] = tolen; + return (__socketcall(SYS_SENDTO, args)); +} +#endif +libc_hidden_proto(sendto) +weak_alias(__libc_sendto,sendto) +libc_hidden_weak(sendto) +#endif + +#ifdef L_setsockopt +libc_hidden_proto(setsockopt) +#ifdef __NR_setsockopt +_syscall5(int, setsockopt, int, fd, int, level, int, optname, const void *, optval, socklen_t, optlen) +#elif defined(__NR_socketcall) +/* [sg]etsockoptions by bir7@leland.stanford.edu */ +int setsockopt(int fd, int level, int optname, const void *optval, + socklen_t optlen) +{ + unsigned long args[5]; + + args[0] = fd; + args[1] = level; + args[2] = optname; + args[3] = (unsigned long) optval; + args[4] = optlen; + return (__socketcall(SYS_SETSOCKOPT, args)); +} +#endif +libc_hidden_def(setsockopt) +#endif + +#ifdef L_shutdown +#ifdef __NR_shutdown +_syscall2(int, shutdown, int, sockfd, int, how) +#elif defined(__NR_socketcall) +/* shutdown by bir7@leland.stanford.edu */ +int shutdown(int sockfd, int how) +{ + unsigned long args[2]; + + args[0] = sockfd; + args[1] = how; + return (__socketcall(SYS_SHUTDOWN, args)); +} +#endif +#endif + +#ifdef L_socket +libc_hidden_proto(socket) +#ifdef __NR_socket +_syscall3(int, socket, int, family, int, type, int, protocol) +#elif defined(__NR_socketcall) +int socket(int family, int type, int protocol) +{ + unsigned long args[3]; + + args[0] = family; + args[1] = type; + args[2] = (unsigned long) protocol; + return __socketcall(SYS_SOCKET, args); +} +#endif +libc_hidden_def(socket) +#endif + +#ifdef L_socketpair +#ifdef __NR_socketpair +_syscall4(int, socketpair, int, family, int, type, int, protocol, int *, sockvec) +#elif defined(__NR_socketcall) +int socketpair(int family, int type, int protocol, int sockvec[2]) +{ + unsigned long args[4]; + + args[0] = family; + args[1] = type; + args[2] = protocol; + args[3] = (unsigned long) sockvec; + return __socketcall(SYS_SOCKETPAIR, args); +} +#endif +#endif diff --git a/libc/inet/socketpair.c b/libc/inet/socketpair.c new file mode 100644 index 0000000..f7c4354 --- /dev/null +++ b/libc/inet/socketpair.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_socketpair +#include "socketcalls.c" diff --git a/libc/misc/Makefile b/libc/misc/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/misc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/Makefile.in b/libc/misc/Makefile.in new file mode 100644 index 0000000..104db36 --- /dev/null +++ b/libc/misc/Makefile.in @@ -0,0 +1,33 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +#DIRS:=assert ctype dirent error file fnmatch ftw glob gnu internals intl locale mntent \ +# pthread regex search statfs syslog sysvipc time ttyent utmp wchar wctype wordexp + +include $(top_srcdir)libc/misc/assert/Makefile.in +include $(top_srcdir)libc/misc/ctype/Makefile.in +include $(top_srcdir)libc/misc/dirent/Makefile.in +include $(top_srcdir)libc/misc/error/Makefile.in +include $(top_srcdir)libc/misc/file/Makefile.in +include $(top_srcdir)libc/misc/fnmatch/Makefile.in +include $(top_srcdir)libc/misc/ftw/Makefile.in +include $(top_srcdir)libc/misc/glob/Makefile.in +include $(top_srcdir)libc/misc/gnu/Makefile.in +include $(top_srcdir)libc/misc/internals/Makefile.in +include $(top_srcdir)libc/misc/locale/Makefile.in +include $(top_srcdir)libc/misc/mntent/Makefile.in +include $(top_srcdir)libc/misc/regex/Makefile.in +include $(top_srcdir)libc/misc/search/Makefile.in +include $(top_srcdir)libc/misc/statfs/Makefile.in +include $(top_srcdir)libc/misc/syslog/Makefile.in +include $(top_srcdir)libc/misc/sysvipc/Makefile.in +include $(top_srcdir)libc/misc/time/Makefile.in +include $(top_srcdir)libc/misc/ttyent/Makefile.in +include $(top_srcdir)libc/misc/utmp/Makefile.in +include $(top_srcdir)libc/misc/wchar/Makefile.in +include $(top_srcdir)libc/misc/wctype/Makefile.in +include $(top_srcdir)libc/misc/wordexp/Makefile.in diff --git a/libc/misc/assert/.indent.pro b/libc/misc/assert/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/assert/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/assert/Makefile b/libc/misc/assert/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/assert/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/assert/Makefile.in b/libc/misc/assert/Makefile.in new file mode 100644 index 0000000..22dfeeb --- /dev/null +++ b/libc/misc/assert/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __assert.c + +MISC_ASSERT_DIR := $(top_srcdir)libc/misc/assert +MISC_ASSERT_OUT := $(top_builddir)libc/misc/assert + +MISC_ASSERT_SRC := $(MISC_ASSERT_DIR)/__assert.c +MISC_ASSERT_OBJ := $(MISC_ASSERT_OUT)/__assert.o + +libc-y += $(MISC_ASSERT_OBJ) + +objclean-y += misc_assert_clean + +misc_assert_clean: + $(do_rm) $(addprefix $(MISC_ASSERT_OUT)/*., o os) diff --git a/libc/misc/assert/__assert.c b/libc/misc/assert/__assert.c new file mode 100644 index 0000000..7a2fa1d --- /dev/null +++ b/libc/misc/assert/__assert.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2002 Manuel Novoa III + * An __assert() function compatible with the modified glibc assert.h + * that is used by uClibc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Oct 28, 2002 + * + * ANSI/ISO C99 requires assert() to write to stderr. This means that + * writing to STDERR_FILENO is insufficient, as the user could freopen + * stderr. It is also insufficient to output to fileno(stderr) since + * this would fail in the custom stream case. I didn't remove the + * old code though, as it doesn't use stdio stream functionality + * and is useful in debugging the stdio code. + */ + +#include +#include +#include +#include + +libc_hidden_proto(fprintf) +libc_hidden_proto(abort) + +/* Get the prototype from assert.h as a double-check. */ +#undef NDEBUG +#include +#undef assert + +libc_hidden_proto(__assert) + +#define ASSERT_SHOW_PROGNAME 1 + +static smallint in_assert; /* bss inits to 0. */ + +void attribute_noreturn __assert(const char *assertion, const char * filename, + int linenumber, register const char * function) +{ + if (!in_assert) { + in_assert = 1; + + fprintf(stderr, +#ifdef ASSERT_SHOW_PROGNAME + "%s: %s: %d: %s: Assertion `%s' failed.\n", __uclibc_progname, +#else + "%s: %d: %s: Assertion `%s' failed.\n", +#endif + filename, + linenumber, + /* Function name isn't available with some compilers. */ + ((function == NULL) ? "?function?" : function), + assertion + ); + } + abort(); +} + +libc_hidden_def(__assert) diff --git a/libc/misc/ctype/.indent.pro b/libc/misc/ctype/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/ctype/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/ctype/Makefile b/libc/misc/ctype/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/ctype/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/ctype/Makefile.in b/libc/misc/ctype/Makefile.in new file mode 100644 index 0000000..29b63f3 --- /dev/null +++ b/libc/misc/ctype/Makefile.in @@ -0,0 +1,38 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# multi source ctype.c +COM_SRC := \ + isalnum.c isalpha.c isascii.c iscntrl.c isdigit.c \ + isgraph.c islower.c isprint.c ispunct.c isspace.c \ + isupper.c isxdigit.c toascii.c tolower.c toupper.c \ + isblank.c + +CSRC := $(COM_SRC) + +ifeq ($(UCLIBC_HAS_CTYPE_TABLES),y) +CSRC += __C_ctype_b.c __C_ctype_tolower.c __C_ctype_toupper.c \ + __ctype_b_loc.c __ctype_tolower_loc.c __ctype_toupper_loc.c \ + __ctype_assert.c isctype.c +endif + +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += $(patsubst %.c,%_l.c,$(COM_SRC)) +endif + +MISC_CTYPE_DIR := $(top_srcdir)libc/misc/ctype +MISC_CTYPE_OUT := $(top_builddir)libc/misc/ctype + +MISC_CTYPE_SRC := $(patsubst %.c,$(MISC_CTYPE_DIR)/%.c,$(CSRC)) +MISC_CTYPE_OBJ := $(patsubst %.c,$(MISC_CTYPE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_CTYPE_OBJ) + +objclean-y += misc_ctype_clean + +misc_ctype_clean: + $(do_rm) $(addprefix $(MISC_CTYPE_OUT)/*., o os) diff --git a/libc/misc/ctype/__C_ctype_b.c b/libc/misc/ctype/__C_ctype_b.c new file mode 100644 index 0000000..d22359f --- /dev/null +++ b/libc/misc/ctype/__C_ctype_b.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_b +#include "ctype.c" diff --git a/libc/misc/ctype/__C_ctype_tolower.c b/libc/misc/ctype/__C_ctype_tolower.c new file mode 100644 index 0000000..fc6027f --- /dev/null +++ b/libc/misc/ctype/__C_ctype_tolower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_tolower +#include "ctype.c" diff --git a/libc/misc/ctype/__C_ctype_toupper.c b/libc/misc/ctype/__C_ctype_toupper.c new file mode 100644 index 0000000..ec42fbf --- /dev/null +++ b/libc/misc/ctype/__C_ctype_toupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_toupper +#include "ctype.c" diff --git a/libc/misc/ctype/__ctype_assert.c b/libc/misc/ctype/__ctype_assert.c new file mode 100644 index 0000000..fe45945 --- /dev/null +++ b/libc/misc/ctype/__ctype_assert.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_assert +#include "ctype.c" diff --git a/libc/misc/ctype/__ctype_b_loc.c b/libc/misc/ctype/__ctype_b_loc.c new file mode 100644 index 0000000..11d5046 --- /dev/null +++ b/libc/misc/ctype/__ctype_b_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_b_loc +#include "ctype.c" diff --git a/libc/misc/ctype/__ctype_tolower_loc.c b/libc/misc/ctype/__ctype_tolower_loc.c new file mode 100644 index 0000000..54037a5 --- /dev/null +++ b/libc/misc/ctype/__ctype_tolower_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_tolower_loc +#include "ctype.c" diff --git a/libc/misc/ctype/__ctype_toupper_loc.c b/libc/misc/ctype/__ctype_toupper_loc.c new file mode 100644 index 0000000..e511d0f --- /dev/null +++ b/libc/misc/ctype/__ctype_toupper_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_toupper_loc +#include "ctype.c" diff --git a/libc/misc/ctype/ctype.c b/libc/misc/ctype/ctype.c new file mode 100644 index 0000000..abb76eb --- /dev/null +++ b/libc/misc/ctype/ctype.c @@ -0,0 +1,1119 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#define __NO_CTYPE + +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + +#if EOF >= CHAR_MIN +#define CTYPE_DOMAIN_CHECK(C) \ + (((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) +#else +#define CTYPE_DOMAIN_CHECK(C) \ + ((((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) || ((C) == EOF)) +#endif + +#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +#if EOF == -1 +#define CTYPE_DOMAIN_CHECK(C) \ + (((unsigned int)((C) - EOF)) <= (UCHAR_MAX - EOF)) +#else +#define CTYPE_DOMAIN_CHECK(C) \ + ((((unsigned int)(C)) <= UCHAR_MAX) || ((C) == EOF)) +#endif + +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +/**********************************************************************/ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_isspace +/* emit only once */ +#warning CONSIDER: Should we assert when debugging and __UCLIBC_HAS_CTYPE_CHECKED? +#warning TODO: Fix asserts in to{upper|lower}{_l}. +#warning TODO: Optimize the isx*() funcs. +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ +/**********************************************************************/ +#undef PASTE2 +#define PASTE2(X,Y) X ## Y + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +#undef CTYPE_NAME +#undef ISCTYPE +#undef CTYPE_ALIAS +#ifdef __UCLIBC_DO_XLOCALE +#define CTYPE_NAME(X) __is ## X ## _l +#define ISCTYPE(C,F) __isctype_l( C, F, locale_arg) +#define CTYPE_ALIAS(NAME) strong_alias( __is ## NAME ## _l , is ## NAME ## _l) +#else +#define CTYPE_NAME(X) is ## X +#define ISCTYPE(C,F) __isctype( C, F ) +#define CTYPE_ALIAS(NAME) +#endif + + +#undef CTYPE_BODY + +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) +/* Make sure assert is active for to*() funcs below. */ +#undef NDEBUG +#include + +extern void __isctype_assert(int c, int mask) __attribute__ ((__noreturn__)) attribute_hidden; + +#define CTYPE_BODY(NAME,C,MASK) \ + if (CTYPE_DOMAIN_CHECK(C)) { \ + return ISCTYPE(C, MASK); \ + } \ + __isctype_assert(C, MASK); + +#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__) + +#define CTYPE_BODY(NAME,C,MASK) \ + return CTYPE_DOMAIN_CHECK(C) \ + ? ISCTYPE(C, MASK) \ + : 0; + +#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__) + +#define CTYPE_BODY(NAME,C,MASK) \ + return ISCTYPE(C, MASK); + + +#else /* No checking done. */ + +#error Unknown type of ctype checking! + +#endif + + + +#define IS_FUNC_BODY(NAME) \ +int CTYPE_NAME(NAME) (int c __LOCALE_PARAM ); \ +int CTYPE_NAME(NAME) (int c __LOCALE_PARAM ) \ +{ \ + CTYPE_BODY(NAME,c,PASTE2(_IS,NAME)) \ +} \ +CTYPE_ALIAS(NAME) + + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#define C_MACRO(X) PASTE2(__C_is,X)(c) +#define CTYPE_NAME(X) is ## X + +#define IS_FUNC_BODY(NAME) \ +int CTYPE_NAME(NAME) (int c) \ +{ \ + return C_MACRO(NAME); \ +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +/**********************************************************************/ +#ifdef L___ctype_assert +#ifdef __UCLIBC_HAS_CTYPE_ENFORCED__ + +libc_hidden_proto(fprintf) +libc_hidden_proto(abort) + +attribute_hidden void __isctype_assert(int c, int mask) +{ + fprintf(stderr, "%s: __is*{_l}(%d,%#x {locale})\n", __uclibc_progname, c, mask); + abort(); +} + +#endif +#endif +/**********************************************************************/ +#if defined(L_isalnum) || defined(L_isalnum_l) + +IS_FUNC_BODY(alnum); + +#endif +/**********************************************************************/ +#if defined(L_isalpha) || defined(L_isalpha_l) + +IS_FUNC_BODY(alpha); + +#endif +/**********************************************************************/ +#if defined(L_isblank) || defined(L_isblank_l) + +IS_FUNC_BODY(blank); + +#endif +/**********************************************************************/ +#if defined(L_iscntrl) || defined(L_iscntrl_l) + +IS_FUNC_BODY(cntrl); + +#endif +/**********************************************************************/ +#if defined(L_isdigit) || defined(L_isdigit_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +/* The standards require EOF < 0. */ +#if EOF >= CHAR_MIN +#define __isdigit_char_or_EOF(C) __isdigit_char((C)) +#else +#define __isdigit_char_or_EOF(C) __isdigit_int((C)) +#endif + +int CTYPE_NAME(digit) (int C __LOCALE_PARAM); +int CTYPE_NAME(digit) (int C __LOCALE_PARAM) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + if (CTYPE_DOMAIN_CHECK(C)) { + return __isdigit_char_or_EOF(C); /* C is (unsigned) char or EOF. */ + } + __isctype_assert(C, _ISdigit); +#else + return __isdigit_int(C); /* C could be invalid. */ +#endif +} + +CTYPE_ALIAS(digit) + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +IS_FUNC_BODY(digit); + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#endif +/**********************************************************************/ +#if defined(L_isgraph) || defined(L_isgraph_l) + +IS_FUNC_BODY(graph); + +#endif +/**********************************************************************/ +#if defined(L_islower) || defined(L_islower_l) + +IS_FUNC_BODY(lower); + +#endif +/**********************************************************************/ +#if defined(L_isprint) || defined(L_isprint_l) + +IS_FUNC_BODY(print); + +#endif +/**********************************************************************/ +#if defined(L_ispunct) || defined(L_ispunct_l) + +IS_FUNC_BODY(punct); + +#endif +/**********************************************************************/ +#if defined(L_isspace) || defined(L_isspace_l) + +IS_FUNC_BODY(space); + +#endif +/**********************************************************************/ +#if defined(L_isupper) || defined(L_isupper_l) + +IS_FUNC_BODY(upper); + +#endif +/**********************************************************************/ +#if defined(L_isxdigit) || defined(L_isxdigit_l) + +IS_FUNC_BODY(xdigit); + +#endif +/**********************************************************************/ +#ifdef L_tolower + +#undef tolower +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_tolower_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_tolower) +#endif +libc_hidden_proto(tolower) +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int tolower(int c) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOLOWER)[c] : c; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int tolower(int c) +{ + return __C_tolower(c); +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +libc_hidden_def(tolower) + +#endif +/**********************************************************************/ +#ifdef L_tolower_l + +#undef tolower_l +libc_hidden_proto(tolower_l) +int tolower_l(int c, __locale_t l) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_tolower[c] : c; +} +libc_hidden_def(tolower_l) +weak_alias (tolower_l, __tolower_l) + +#endif +/**********************************************************************/ +#ifdef L_toupper + +#undef toupper +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_toupper_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_toupper) +#endif +libc_hidden_proto(toupper) +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int toupper(int c) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOUPPER)[c] : c; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int toupper(int c) +{ + return __C_toupper(c); +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +libc_hidden_def(toupper) + +#endif +/**********************************************************************/ +#ifdef L_toupper_l + +#undef toupper_l +libc_hidden_proto(toupper_l) +int toupper_l(int c, __locale_t l) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_toupper[c] : c; +} +libc_hidden_def(toupper_l) +weak_alias (toupper_l, __toupper_l) + +#endif +/**********************************************************************/ +#if defined(L_isascii) || defined(L_isascii_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int __XL_NPP(isascii)(int c); +int __XL_NPP(isascii)(int c) +{ + return __isascii(c); /* locale-independent */ +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +libc_hidden_proto(isascii) +int isascii(int c) +{ + return __isascii(c); /* locale-independent */ +} +libc_hidden_def(isascii) + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#endif +/**********************************************************************/ +#if defined(L_toascii) || defined(L_toascii_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int __XL_NPP(toascii)(int c); +int __XL_NPP(toascii)(int c) +{ + return __toascii(c); /* locale-independent */ +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int toascii(int c) +{ + return __toascii(c); /* locale-independent */ +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#endif +/**********************************************************************/ +/* glibc extensions */ +/**********************************************************************/ +#ifdef L_isctype + +int isctype(int c, int mask) +{ + CTYPE_BODY(NAME,c,mask) +} + +#endif +/**********************************************************************/ +#ifdef L___ctype_b_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +const __ctype_mask_t **__ctype_b_loc(void) +{ + return &(__UCLIBC_CURLOCALE_DATA).__ctype_b; +} + +libc_hidden_def(__ctype_b_loc) +#endif + +#endif +/**********************************************************************/ +#ifdef L___ctype_tolower_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +libc_hidden_proto(__ctype_tolower_loc) +const __ctype_touplow_t **__ctype_tolower_loc(void) +{ + return &(__UCLIBC_CURLOCALE_DATA).__ctype_tolower; +} +libc_hidden_def(__ctype_tolower_loc) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___ctype_toupper_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +libc_hidden_proto(__ctype_toupper_loc) +const __ctype_touplow_t **__ctype_toupper_loc(void) +{ + return &(__UCLIBC_CURLOCALE_DATA).__ctype_toupper; +} +libc_hidden_def(__ctype_toupper_loc) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_b + +extern const __ctype_mask_t __C_ctype_b_data[]; +libc_hidden_proto(__C_ctype_b_data) +const __ctype_mask_t __C_ctype_b_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + /* -128 M-^@ */ 0, + /* -127 M-^A */ 0, + /* -126 M-^B */ 0, + /* -125 M-^C */ 0, + /* -124 M-^D */ 0, + /* -123 M-^E */ 0, + /* -122 M-^F */ 0, + /* -121 M-^G */ 0, + /* -120 M-^H */ 0, + /* -119 M-^I */ 0, + /* -118 M-^J */ 0, + /* -117 M-^K */ 0, + /* -116 M-^L */ 0, + /* -115 M-^M */ 0, + /* -114 M-^N */ 0, + /* -113 M-^O */ 0, + /* -112 M-^P */ 0, + /* -111 M-^Q */ 0, + /* -110 M-^R */ 0, + /* -109 M-^S */ 0, + /* -108 M-^T */ 0, + /* -107 M-^U */ 0, + /* -106 M-^V */ 0, + /* -105 M-^W */ 0, + /* -104 M-^X */ 0, + /* -103 M-^Y */ 0, + /* -102 M-^Z */ 0, + /* -101 M-^[ */ 0, + /* -100 M-^\ */ 0, + /* -99 M-^] */ 0, + /* -98 M-^^ */ 0, + /* -97 M-^_ */ 0, + /* -96 M- */ 0, + /* -95 M-! */ 0, + /* -94 M-" */ 0, + /* -93 M-# */ 0, + /* -92 M-$ */ 0, + /* -91 M-% */ 0, + /* -90 M-& */ 0, + /* -89 M-' */ 0, + /* -88 M-( */ 0, + /* -87 M-) */ 0, + /* -86 M-* */ 0, + /* -85 M-+ */ 0, + /* -84 M-, */ 0, + /* -83 M-- */ 0, + /* -82 M-. */ 0, + /* -81 M-/ */ 0, + /* -80 M-0 */ 0, + /* -79 M-1 */ 0, + /* -78 M-2 */ 0, + /* -77 M-3 */ 0, + /* -76 M-4 */ 0, + /* -75 M-5 */ 0, + /* -74 M-6 */ 0, + /* -73 M-7 */ 0, + /* -72 M-8 */ 0, + /* -71 M-9 */ 0, + /* -70 M-: */ 0, + /* -69 M-; */ 0, + /* -68 M-< */ 0, + /* -67 M-= */ 0, + /* -66 M-> */ 0, + /* -65 M-? */ 0, + /* -64 M-@ */ 0, + /* -63 M-A */ 0, + /* -62 M-B */ 0, + /* -61 M-C */ 0, + /* -60 M-D */ 0, + /* -59 M-E */ 0, + /* -58 M-F */ 0, + /* -57 M-G */ 0, + /* -56 M-H */ 0, + /* -55 M-I */ 0, + /* -54 M-J */ 0, + /* -53 M-K */ 0, + /* -52 M-L */ 0, + /* -51 M-M */ 0, + /* -50 M-N */ 0, + /* -49 M-O */ 0, + /* -48 M-P */ 0, + /* -47 M-Q */ 0, + /* -46 M-R */ 0, + /* -45 M-S */ 0, + /* -44 M-T */ 0, + /* -43 M-U */ 0, + /* -42 M-V */ 0, + /* -41 M-W */ 0, + /* -40 M-X */ 0, + /* -39 M-Y */ 0, + /* -38 M-Z */ 0, + /* -37 M-[ */ 0, + /* -36 M-\ */ 0, + /* -35 M-] */ 0, + /* -34 M-^ */ 0, + /* -33 M-_ */ 0, + /* -32 M-` */ 0, + /* -31 M-a */ 0, + /* -30 M-b */ 0, + /* -29 M-c */ 0, + /* -28 M-d */ 0, + /* -27 M-e */ 0, + /* -26 M-f */ 0, + /* -25 M-g */ 0, + /* -24 M-h */ 0, + /* -23 M-i */ 0, + /* -22 M-j */ 0, + /* -21 M-k */ 0, + /* -20 M-l */ 0, + /* -19 M-m */ 0, + /* -18 M-n */ 0, + /* -17 M-o */ 0, + /* -16 M-p */ 0, + /* -15 M-q */ 0, + /* -14 M-r */ 0, + /* -13 M-s */ 0, + /* -12 M-t */ 0, + /* -11 M-u */ 0, + /* -10 M-v */ 0, + /* -9 M-w */ 0, + /* -8 M-x */ 0, + /* -7 M-y */ 0, + /* -6 M-z */ 0, + /* -5 M-{ */ 0, + /* -4 M-| */ 0, + /* -3 M-} */ 0, + /* -2 M-~ */ 0, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + /* -1 M-^? */ 0, + /* 0 ^@ */ _IScntrl, + /* 1 ^A */ _IScntrl, + /* 2 ^B */ _IScntrl, + /* 3 ^C */ _IScntrl, + /* 4 ^D */ _IScntrl, + /* 5 ^E */ _IScntrl, + /* 6 ^F */ _IScntrl, + /* 7 ^G */ _IScntrl, + /* 8 ^H */ _IScntrl, + /* 9 ^I */ _ISspace|_ISblank|_IScntrl, + /* 10 ^J */ _ISspace|_IScntrl, + /* 11 ^K */ _ISspace|_IScntrl, + /* 12 ^L */ _ISspace|_IScntrl, + /* 13 ^M */ _ISspace|_IScntrl, + /* 14 ^N */ _IScntrl, + /* 15 ^O */ _IScntrl, + /* 16 ^P */ _IScntrl, + /* 17 ^Q */ _IScntrl, + /* 18 ^R */ _IScntrl, + /* 19 ^S */ _IScntrl, + /* 20 ^T */ _IScntrl, + /* 21 ^U */ _IScntrl, + /* 22 ^V */ _IScntrl, + /* 23 ^W */ _IScntrl, + /* 24 ^X */ _IScntrl, + /* 25 ^Y */ _IScntrl, + /* 26 ^Z */ _IScntrl, + /* 27 ^[ */ _IScntrl, + /* 28 ^\ */ _IScntrl, + /* 29 ^] */ _IScntrl, + /* 30 ^^ */ _IScntrl, + /* 31 ^_ */ _IScntrl, + /* 32 */ _ISspace|_ISprint|_ISblank, + /* 33 ! */ _ISprint|_ISgraph|_ISpunct, + /* 34 " */ _ISprint|_ISgraph|_ISpunct, + /* 35 # */ _ISprint|_ISgraph|_ISpunct, + /* 36 $ */ _ISprint|_ISgraph|_ISpunct, + /* 37 % */ _ISprint|_ISgraph|_ISpunct, + /* 38 & */ _ISprint|_ISgraph|_ISpunct, + /* 39 ' */ _ISprint|_ISgraph|_ISpunct, + /* 40 ( */ _ISprint|_ISgraph|_ISpunct, + /* 41 ) */ _ISprint|_ISgraph|_ISpunct, + /* 42 * */ _ISprint|_ISgraph|_ISpunct, + /* 43 + */ _ISprint|_ISgraph|_ISpunct, + /* 44 , */ _ISprint|_ISgraph|_ISpunct, + /* 45 - */ _ISprint|_ISgraph|_ISpunct, + /* 46 . */ _ISprint|_ISgraph|_ISpunct, + /* 47 / */ _ISprint|_ISgraph|_ISpunct, + /* 48 0 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 49 1 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 50 2 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 51 3 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 52 4 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 53 5 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 54 6 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 55 7 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 56 8 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 57 9 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 58 : */ _ISprint|_ISgraph|_ISpunct, + /* 59 ; */ _ISprint|_ISgraph|_ISpunct, + /* 60 < */ _ISprint|_ISgraph|_ISpunct, + /* 61 = */ _ISprint|_ISgraph|_ISpunct, + /* 62 > */ _ISprint|_ISgraph|_ISpunct, + /* 63 ? */ _ISprint|_ISgraph|_ISpunct, + /* 64 @ */ _ISprint|_ISgraph|_ISpunct, + /* 65 A */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 66 B */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 67 C */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 68 D */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 69 E */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 70 F */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 71 G */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 72 H */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 73 I */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 74 J */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 75 K */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 76 L */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 77 M */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 78 N */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 79 O */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 80 P */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 81 Q */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 82 R */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 83 S */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 84 T */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 85 U */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 86 V */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 87 W */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 88 X */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 89 Y */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 90 Z */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 91 [ */ _ISprint|_ISgraph|_ISpunct, + /* 92 \ */ _ISprint|_ISgraph|_ISpunct, + /* 93 ] */ _ISprint|_ISgraph|_ISpunct, + /* 94 ^ */ _ISprint|_ISgraph|_ISpunct, + /* 95 _ */ _ISprint|_ISgraph|_ISpunct, + /* 96 ` */ _ISprint|_ISgraph|_ISpunct, + /* 97 a */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 98 b */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 99 c */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 100 d */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 101 e */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 102 f */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 103 g */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 104 h */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 105 i */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 106 j */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 107 k */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 108 l */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 109 m */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 110 n */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 111 o */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 112 p */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 113 q */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 114 r */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 115 s */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 116 t */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 117 u */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 118 v */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 119 w */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 120 x */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 121 y */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 122 z */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 123 { */ _ISprint|_ISgraph|_ISpunct, + /* 124 | */ _ISprint|_ISgraph|_ISpunct, + /* 125 } */ _ISprint|_ISgraph|_ISpunct, + /* 126 ~ */ _ISprint|_ISgraph|_ISpunct, + /* 127 ^? */ _IScntrl, + /* 128 M-^@ */ 0, + /* 129 M-^A */ 0, + /* 130 M-^B */ 0, + /* 131 M-^C */ 0, + /* 132 M-^D */ 0, + /* 133 M-^E */ 0, + /* 134 M-^F */ 0, + /* 135 M-^G */ 0, + /* 136 M-^H */ 0, + /* 137 M-^I */ 0, + /* 138 M-^J */ 0, + /* 139 M-^K */ 0, + /* 140 M-^L */ 0, + /* 141 M-^M */ 0, + /* 142 M-^N */ 0, + /* 143 M-^O */ 0, + /* 144 M-^P */ 0, + /* 145 M-^Q */ 0, + /* 146 M-^R */ 0, + /* 147 M-^S */ 0, + /* 148 M-^T */ 0, + /* 149 M-^U */ 0, + /* 150 M-^V */ 0, + /* 151 M-^W */ 0, + /* 152 M-^X */ 0, + /* 153 M-^Y */ 0, + /* 154 M-^Z */ 0, + /* 155 M-^[ */ 0, + /* 156 M-^\ */ 0, + /* 157 M-^] */ 0, + /* 158 M-^^ */ 0, + /* 159 M-^_ */ 0, + /* 160 M- */ 0, + /* 161 M-! */ 0, + /* 162 M-" */ 0, + /* 163 M-# */ 0, + /* 164 M-$ */ 0, + /* 165 M-% */ 0, + /* 166 M-& */ 0, + /* 167 M-' */ 0, + /* 168 M-( */ 0, + /* 169 M-) */ 0, + /* 170 M-* */ 0, + /* 171 M-+ */ 0, + /* 172 M-, */ 0, + /* 173 M-- */ 0, + /* 174 M-. */ 0, + /* 175 M-/ */ 0, + /* 176 M-0 */ 0, + /* 177 M-1 */ 0, + /* 178 M-2 */ 0, + /* 179 M-3 */ 0, + /* 180 M-4 */ 0, + /* 181 M-5 */ 0, + /* 182 M-6 */ 0, + /* 183 M-7 */ 0, + /* 184 M-8 */ 0, + /* 185 M-9 */ 0, + /* 186 M-: */ 0, + /* 187 M-; */ 0, + /* 188 M-< */ 0, + /* 189 M-= */ 0, + /* 190 M-> */ 0, + /* 191 M-? */ 0, + /* 192 M-@ */ 0, + /* 193 M-A */ 0, + /* 194 M-B */ 0, + /* 195 M-C */ 0, + /* 196 M-D */ 0, + /* 197 M-E */ 0, + /* 198 M-F */ 0, + /* 199 M-G */ 0, + /* 200 M-H */ 0, + /* 201 M-I */ 0, + /* 202 M-J */ 0, + /* 203 M-K */ 0, + /* 204 M-L */ 0, + /* 205 M-M */ 0, + /* 206 M-N */ 0, + /* 207 M-O */ 0, + /* 208 M-P */ 0, + /* 209 M-Q */ 0, + /* 210 M-R */ 0, + /* 211 M-S */ 0, + /* 212 M-T */ 0, + /* 213 M-U */ 0, + /* 214 M-V */ 0, + /* 215 M-W */ 0, + /* 216 M-X */ 0, + /* 217 M-Y */ 0, + /* 218 M-Z */ 0, + /* 219 M-[ */ 0, + /* 220 M-\ */ 0, + /* 221 M-] */ 0, + /* 222 M-^ */ 0, + /* 223 M-_ */ 0, + /* 224 M-` */ 0, + /* 225 M-a */ 0, + /* 226 M-b */ 0, + /* 227 M-c */ 0, + /* 228 M-d */ 0, + /* 229 M-e */ 0, + /* 230 M-f */ 0, + /* 231 M-g */ 0, + /* 232 M-h */ 0, + /* 233 M-i */ 0, + /* 234 M-j */ 0, + /* 235 M-k */ 0, + /* 236 M-l */ 0, + /* 237 M-m */ 0, + /* 238 M-n */ 0, + /* 239 M-o */ 0, + /* 240 M-p */ 0, + /* 241 M-q */ 0, + /* 242 M-r */ 0, + /* 243 M-s */ 0, + /* 244 M-t */ 0, + /* 245 M-u */ 0, + /* 246 M-v */ 0, + /* 247 M-w */ 0, + /* 248 M-x */ 0, + /* 249 M-y */ 0, + /* 250 M-z */ 0, + /* 251 M-{ */ 0, + /* 252 M-| */ 0, + /* 253 M-} */ 0, + /* 254 M-~ */ 0, + /* 255 M-^? */ 0 +}; +libc_hidden_data_def(__C_ctype_b_data) + +libc_hidden_proto(__C_ctype_b) +const __ctype_mask_t *__C_ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_b) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +const __ctype_mask_t *__ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET; +libc_hidden_data_def(__ctype_b) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_tolower + +extern const __ctype_touplow_t __C_ctype_tolower_data[]; +libc_hidden_proto(__C_ctype_tolower_data) +const __ctype_touplow_t __C_ctype_tolower_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + -128, -127, -126, -125, + -124, -123, -122, -121, + -120, -119, -118, -117, + -116, -115, -114, -113, + -112, -111, -110, -109, + -108, -107, -106, -105, + -104, -103, -102, -101, + -100, -99, -98, -97, + -96, -95, -94, -93, + -92, -91, -90, -89, + -88, -87, -86, -85, + -84, -83, -82, -81, + -80, -79, -78, -77, + -76, -75, -74, -73, + -72, -71, -70, -69, + -68, -67, -66, -65, + -64, -63, -62, -61, + -60, -59, -58, -57, + -56, -55, -54, -53, + -52, -51, -50, -49, + -48, -47, -46, -45, + -44, -43, -42, -41, + -40, -39, -38, -37, + -36, -35, -34, -33, + -32, -31, -30, -29, + -28, -27, -26, -25, + -24, -23, -22, -21, + -20, -19, -18, -17, + -16, -15, -14, -13, + -12, -11, -10, -9, + -8, -7, -6, -5, + -4, -3, -2, -1, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 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, + 36, 37, 38, 39, + 40, 41, 42, 43, + 44, 45, 46, 47, + 48, 49, 50, 51, + 52, 53, 54, 55, + 56, 57, 58, 59, + 60, 61, 62, 63, + 64, 97 /* a */, 98 /* b */, 99 /* c */, + 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */, + 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */, + 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */, + 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */, + 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */, + 120 /* x */, 121 /* y */, 122 /* z */, 91, + 92, 93, 94, 95, + 96, 97, 98, 99, + 100, 101, 102, 103, + 104, 105, 106, 107, + 108, 109, 110, 111, + 112, 113, 114, 115, + 116, 117, 118, 119, + 120, 121, 122, 123, + 124, 125, 126, 127, + 128, 129, 130, 131, + 132, 133, 134, 135, + 136, 137, 138, 139, + 140, 141, 142, 143, + 144, 145, 146, 147, + 148, 149, 150, 151, + 152, 153, 154, 155, + 156, 157, 158, 159, + 160, 161, 162, 163, + 164, 165, 166, 167, + 168, 169, 170, 171, + 172, 173, 174, 175, + 176, 177, 178, 179, + 180, 181, 182, 183, + 184, 185, 186, 187, + 188, 189, 190, 191, + 192, 193, 194, 195, + 196, 197, 198, 199, + 200, 201, 202, 203, + 204, 205, 206, 207, + 208, 209, 210, 211, + 212, 213, 214, 215, + 216, 217, 218, 219, + 220, 221, 222, 223, + 224, 225, 226, 227, + 228, 229, 230, 231, + 232, 233, 234, 235, + 236, 237, 238, 239, + 240, 241, 242, 243, + 244, 245, 246, 247, + 248, 249, 250, 251, + 252, 253, 254, 255 +}; +libc_hidden_data_def(__C_ctype_tolower_data) + +libc_hidden_proto(__C_ctype_tolower) +const __ctype_touplow_t *__C_ctype_tolower = __C_ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_tolower) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +libc_hidden_proto(__ctype_tolower) +const __ctype_touplow_t *__ctype_tolower = __C_ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__ctype_tolower) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_toupper + +extern const __ctype_touplow_t __C_ctype_toupper_data[]; +libc_hidden_proto(__C_ctype_toupper_data) +const __ctype_touplow_t __C_ctype_toupper_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + -128, -127, -126, -125, + -124, -123, -122, -121, + -120, -119, -118, -117, + -116, -115, -114, -113, + -112, -111, -110, -109, + -108, -107, -106, -105, + -104, -103, -102, -101, + -100, -99, -98, -97, + -96, -95, -94, -93, + -92, -91, -90, -89, + -88, -87, -86, -85, + -84, -83, -82, -81, + -80, -79, -78, -77, + -76, -75, -74, -73, + -72, -71, -70, -69, + -68, -67, -66, -65, + -64, -63, -62, -61, + -60, -59, -58, -57, + -56, -55, -54, -53, + -52, -51, -50, -49, + -48, -47, -46, -45, + -44, -43, -42, -41, + -40, -39, -38, -37, + -36, -35, -34, -33, + -32, -31, -30, -29, + -28, -27, -26, -25, + -24, -23, -22, -21, + -20, -19, -18, -17, + -16, -15, -14, -13, + -12, -11, -10, -9, + -8, -7, -6, -5, + -4, -3, -2, -1, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 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, + 36, 37, 38, 39, + 40, 41, 42, 43, + 44, 45, 46, 47, + 48, 49, 50, 51, + 52, 53, 54, 55, + 56, 57, 58, 59, + 60, 61, 62, 63, + 64, 65, 66, 67, + 68, 69, 70, 71, + 72, 73, 74, 75, + 76, 77, 78, 79, + 80, 81, 82, 83, + 84, 85, 86, 87, + 88, 89, 90, 91, + 92, 93, 94, 95, + 96, 65 /* A */, 66 /* B */, 67 /* C */, + 68 /* D */, 69 /* E */, 70 /* F */, 71 /* G */, + 72 /* H */, 73 /* I */, 74 /* J */, 75 /* K */, + 76 /* L */, 77 /* M */, 78 /* N */, 79 /* O */, + 80 /* P */, 81 /* Q */, 82 /* R */, 83 /* S */, + 84 /* T */, 85 /* U */, 86 /* V */, 87 /* W */, + 88 /* X */, 89 /* Y */, 90 /* Z */, 123, + 124, 125, 126, 127, + 128, 129, 130, 131, + 132, 133, 134, 135, + 136, 137, 138, 139, + 140, 141, 142, 143, + 144, 145, 146, 147, + 148, 149, 150, 151, + 152, 153, 154, 155, + 156, 157, 158, 159, + 160, 161, 162, 163, + 164, 165, 166, 167, + 168, 169, 170, 171, + 172, 173, 174, 175, + 176, 177, 178, 179, + 180, 181, 182, 183, + 184, 185, 186, 187, + 188, 189, 190, 191, + 192, 193, 194, 195, + 196, 197, 198, 199, + 200, 201, 202, 203, + 204, 205, 206, 207, + 208, 209, 210, 211, + 212, 213, 214, 215, + 216, 217, 218, 219, + 220, 221, 222, 223, + 224, 225, 226, 227, + 228, 229, 230, 231, + 232, 233, 234, 235, + 236, 237, 238, 239, + 240, 241, 242, 243, + 244, 245, 246, 247, + 248, 249, 250, 251, + 252, 253, 254, 255 +}; +libc_hidden_data_def(__C_ctype_toupper_data) + +libc_hidden_proto(__C_ctype_toupper) +const __ctype_touplow_t *__C_ctype_toupper = __C_ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_toupper) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +libc_hidden_proto(__ctype_toupper) +const __ctype_touplow_t *__ctype_toupper = __C_ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__ctype_toupper) + +#endif + +#endif +/**********************************************************************/ diff --git a/libc/misc/ctype/isalnum.c b/libc/misc/ctype/isalnum.c new file mode 100644 index 0000000..8bc8ad6 --- /dev/null +++ b/libc/misc/ctype/isalnum.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalnum +#include "ctype.c" diff --git a/libc/misc/ctype/isalnum_l.c b/libc/misc/ctype/isalnum_l.c new file mode 100644 index 0000000..8ecd9d5 --- /dev/null +++ b/libc/misc/ctype/isalnum_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalnum_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isalpha.c b/libc/misc/ctype/isalpha.c new file mode 100644 index 0000000..22f23d9 --- /dev/null +++ b/libc/misc/ctype/isalpha.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalpha +#include "ctype.c" diff --git a/libc/misc/ctype/isalpha_l.c b/libc/misc/ctype/isalpha_l.c new file mode 100644 index 0000000..10a2ecf --- /dev/null +++ b/libc/misc/ctype/isalpha_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalpha_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isascii.c b/libc/misc/ctype/isascii.c new file mode 100644 index 0000000..84f701f --- /dev/null +++ b/libc/misc/ctype/isascii.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isascii +#include "ctype.c" diff --git a/libc/misc/ctype/isascii_l.c b/libc/misc/ctype/isascii_l.c new file mode 100644 index 0000000..7fe5545 --- /dev/null +++ b/libc/misc/ctype/isascii_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isascii_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isblank.c b/libc/misc/ctype/isblank.c new file mode 100644 index 0000000..d11fe26 --- /dev/null +++ b/libc/misc/ctype/isblank.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isblank +#include "ctype.c" diff --git a/libc/misc/ctype/isblank_l.c b/libc/misc/ctype/isblank_l.c new file mode 100644 index 0000000..144cd93 --- /dev/null +++ b/libc/misc/ctype/isblank_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isblank_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/iscntrl.c b/libc/misc/ctype/iscntrl.c new file mode 100644 index 0000000..4a0c09d --- /dev/null +++ b/libc/misc/ctype/iscntrl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iscntrl +#include "ctype.c" diff --git a/libc/misc/ctype/iscntrl_l.c b/libc/misc/ctype/iscntrl_l.c new file mode 100644 index 0000000..fbee951 --- /dev/null +++ b/libc/misc/ctype/iscntrl_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iscntrl_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isctype.c b/libc/misc/ctype/isctype.c new file mode 100644 index 0000000..a2d0b3d --- /dev/null +++ b/libc/misc/ctype/isctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isctype +#include "ctype.c" diff --git a/libc/misc/ctype/isdigit.c b/libc/misc/ctype/isdigit.c new file mode 100644 index 0000000..e185c89 --- /dev/null +++ b/libc/misc/ctype/isdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isdigit +#include "ctype.c" diff --git a/libc/misc/ctype/isdigit_l.c b/libc/misc/ctype/isdigit_l.c new file mode 100644 index 0000000..5b764f1 --- /dev/null +++ b/libc/misc/ctype/isdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isdigit_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isgraph.c b/libc/misc/ctype/isgraph.c new file mode 100644 index 0000000..c4ad1b7 --- /dev/null +++ b/libc/misc/ctype/isgraph.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isgraph +#include "ctype.c" diff --git a/libc/misc/ctype/isgraph_l.c b/libc/misc/ctype/isgraph_l.c new file mode 100644 index 0000000..005e19f --- /dev/null +++ b/libc/misc/ctype/isgraph_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isgraph_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/islower.c b/libc/misc/ctype/islower.c new file mode 100644 index 0000000..aff65dd --- /dev/null +++ b/libc/misc/ctype/islower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_islower +#include "ctype.c" diff --git a/libc/misc/ctype/islower_l.c b/libc/misc/ctype/islower_l.c new file mode 100644 index 0000000..dd08557 --- /dev/null +++ b/libc/misc/ctype/islower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_islower_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isprint.c b/libc/misc/ctype/isprint.c new file mode 100644 index 0000000..b6f7d6c --- /dev/null +++ b/libc/misc/ctype/isprint.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isprint +#include "ctype.c" diff --git a/libc/misc/ctype/isprint_l.c b/libc/misc/ctype/isprint_l.c new file mode 100644 index 0000000..32f9b3f --- /dev/null +++ b/libc/misc/ctype/isprint_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isprint_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/ispunct.c b/libc/misc/ctype/ispunct.c new file mode 100644 index 0000000..08f7b19 --- /dev/null +++ b/libc/misc/ctype/ispunct.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ispunct +#include "ctype.c" diff --git a/libc/misc/ctype/ispunct_l.c b/libc/misc/ctype/ispunct_l.c new file mode 100644 index 0000000..513bb52 --- /dev/null +++ b/libc/misc/ctype/ispunct_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ispunct_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isspace.c b/libc/misc/ctype/isspace.c new file mode 100644 index 0000000..c8ff567 --- /dev/null +++ b/libc/misc/ctype/isspace.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isspace +#include "ctype.c" diff --git a/libc/misc/ctype/isspace_l.c b/libc/misc/ctype/isspace_l.c new file mode 100644 index 0000000..97e0c99 --- /dev/null +++ b/libc/misc/ctype/isspace_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isspace_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isupper.c b/libc/misc/ctype/isupper.c new file mode 100644 index 0000000..36d6e6e --- /dev/null +++ b/libc/misc/ctype/isupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isupper +#include "ctype.c" diff --git a/libc/misc/ctype/isupper_l.c b/libc/misc/ctype/isupper_l.c new file mode 100644 index 0000000..8aa4dbd --- /dev/null +++ b/libc/misc/ctype/isupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isupper_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/isxdigit.c b/libc/misc/ctype/isxdigit.c new file mode 100644 index 0000000..40919f7 --- /dev/null +++ b/libc/misc/ctype/isxdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isxdigit +#include "ctype.c" diff --git a/libc/misc/ctype/isxdigit_l.c b/libc/misc/ctype/isxdigit_l.c new file mode 100644 index 0000000..5dce7f1 --- /dev/null +++ b/libc/misc/ctype/isxdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isxdigit_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/toascii.c b/libc/misc/ctype/toascii.c new file mode 100644 index 0000000..a63b993 --- /dev/null +++ b/libc/misc/ctype/toascii.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toascii +#include "ctype.c" diff --git a/libc/misc/ctype/toascii_l.c b/libc/misc/ctype/toascii_l.c new file mode 100644 index 0000000..6179526 --- /dev/null +++ b/libc/misc/ctype/toascii_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toascii_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/tolower.c b/libc/misc/ctype/tolower.c new file mode 100644 index 0000000..3673642 --- /dev/null +++ b/libc/misc/ctype/tolower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tolower +#include "ctype.c" diff --git a/libc/misc/ctype/tolower_l.c b/libc/misc/ctype/tolower_l.c new file mode 100644 index 0000000..327e63c --- /dev/null +++ b/libc/misc/ctype/tolower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tolower_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/ctype/toupper.c b/libc/misc/ctype/toupper.c new file mode 100644 index 0000000..a9d8aab --- /dev/null +++ b/libc/misc/ctype/toupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toupper +#include "ctype.c" diff --git a/libc/misc/ctype/toupper_l.c b/libc/misc/ctype/toupper_l.c new file mode 100644 index 0000000..c91d791 --- /dev/null +++ b/libc/misc/ctype/toupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toupper_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/libc/misc/dirent/Makefile b/libc/misc/dirent/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/dirent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/dirent/Makefile.in b/libc/misc/dirent/Makefile.in new file mode 100644 index 0000000..e2a48e7 --- /dev/null +++ b/libc/misc/dirent/Makefile.in @@ -0,0 +1,26 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := alphasort.c closedir.c dirfd.c opendir.c readdir.c rewinddir.c \ + scandir.c seekdir.c telldir.c readdir_r.c + +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += readdir64.c alphasort64.c scandir64.c readdir64_r.c +endif + +MISC_DIRENT_DIR := $(top_srcdir)libc/misc/dirent +MISC_DIRENT_OUT := $(top_builddir)libc/misc/dirent + +MISC_DIRENT_SRC := $(patsubst %.c,$(MISC_DIRENT_DIR)/%.c,$(CSRC)) +MISC_DIRENT_OBJ := $(patsubst %.c,$(MISC_DIRENT_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_DIRENT_OBJ) + +objclean-y += misc_dirent_clean + +misc_dirent_clean: + $(do_rm) $(addprefix $(MISC_DIRENT_OUT)/*., o os) diff --git a/libc/misc/dirent/alphasort.c b/libc/misc/dirent/alphasort.c new file mode 100644 index 0000000..70aa2a5 --- /dev/null +++ b/libc/misc/dirent/alphasort.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(strcmp) */ + +int alphasort(const void * a, const void * b) +{ + return strcmp ((*(const struct dirent **) a)->d_name, + (*(const struct dirent **) b)->d_name); +} + diff --git a/libc/misc/dirent/alphasort64.c b/libc/misc/dirent/alphasort64.c new file mode 100644 index 0000000..de7a87a --- /dev/null +++ b/libc/misc/dirent/alphasort64.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(strcmp) */ + +int alphasort64(const void * a, const void * b) +{ + return strcmp ((*(const struct dirent64 **) a)->d_name, + (*(const struct dirent64 **) b)->d_name); +} diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c new file mode 100644 index 0000000..3dc0bd1 --- /dev/null +++ b/libc/misc/dirent/closedir.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(closedir) +libc_hidden_proto(close) + +int closedir(DIR * dir) +{ + int fd; + + if (!dir) { + __set_errno(EBADF); + return -1; + } + + /* We need to check dd_fd. */ + if (dir->dd_fd == -1) { + __set_errno(EBADF); + return -1; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + fd = dir->dd_fd; + dir->dd_fd = -1; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + free(dir->dd_buf); + free(dir); + return close(fd); +} +libc_hidden_def(closedir) diff --git a/libc/misc/dirent/dirfd.c b/libc/misc/dirent/dirfd.c new file mode 100644 index 0000000..c6f46e9 --- /dev/null +++ b/libc/misc/dirent/dirfd.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "dirstream.h" + +libc_hidden_proto(dirfd) + +int dirfd(DIR * dir) +{ + if (!dir || dir->dd_fd == -1) { + __set_errno(EBADF); + return -1; + } + + return dir->dd_fd; +} +libc_hidden_def(dirfd) diff --git a/libc/misc/dirent/dirstream.h b/libc/misc/dirent/dirstream.h new file mode 100644 index 0000000..370886a --- /dev/null +++ b/libc/misc/dirent/dirstream.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * POSIX Standard: 5.1.2 Directory Operations + */ + +#ifndef _DIRSTREAM_H + +#define _DIRSTREAM_H 1 + +#include +#include + +#include + +/* For now, syscall readdir () only supports one entry at a time. It + * will be changed in the future. +#define NUMENT 3 +*/ +#ifndef NUMENT +#define NUMENT 1 +#endif + +#define SINGLE_READDIR 11 +#define MULTI_READDIR 12 +#define NEW_READDIR 13 + +/* Directory stream type. */ +struct __dirstream { + /* file descriptor */ + int dd_fd; + + /* offset of the next dir entry in buffer */ + size_t dd_nextloc; + + /* bytes of valid entries in buffer */ + size_t dd_size; + + /* -> directory buffer */ + void *dd_buf; + + /* offset of the next dir entry in directory. */ + off_t dd_nextoff; + + /* total size of buffer */ + size_t dd_max; + + /* lock */ + __UCLIBC_MUTEX(dd_lock); +}; /* stream data from opendir() */ + + +extern ssize_t __getdents(int fd, char *buf, size_t count) attribute_hidden; +#ifdef __UCLIBC_HAS_LFS__ +extern ssize_t __getdents64 (int fd, char *buf, size_t count) attribute_hidden; +#endif + +#endif /* dirent.h */ diff --git a/libc/misc/dirent/opendir.c b/libc/misc/dirent/opendir.c new file mode 100644 index 0000000..26ab915 --- /dev/null +++ b/libc/misc/dirent/opendir.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(opendir) +libc_hidden_proto(open) +libc_hidden_proto(fcntl) +libc_hidden_proto(close) +libc_hidden_proto(stat) +libc_hidden_proto(fstat) + +/* opendir just makes an open() call - it return NULL if it fails + * (open sets errno), otherwise it returns a DIR * pointer. + */ +DIR *opendir(const char *name) +{ + int fd; + struct stat statbuf; + DIR *ptr; + +#ifndef O_DIRECTORY + /* O_DIRECTORY is linux specific and has been around since like 2.1.x */ + if (stat(name, &statbuf)) + return NULL; + if (!S_ISDIR(statbuf.st_mode)) { + __set_errno(ENOTDIR); + return NULL; + } +# define O_DIRECTORY 0 +#endif + if ((fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY)) < 0) + return NULL; + + /* Note: we should check to make sure that between the stat() and open() + * call, 'name' didnt change on us, but that's only if O_DIRECTORY isnt + * defined and since Linux has supported it for like ever, i'm not going + * to worry about it right now (if ever). */ + if (fstat(fd, &statbuf) < 0) + goto close_and_ret; + + /* According to POSIX, directory streams should be closed when + * exec. From "Anna Pluzhnikov" . + */ + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + int saved_errno; +close_and_ret: + saved_errno = errno; + close(fd); + __set_errno(saved_errno); + return NULL; + } + if (!(ptr = malloc(sizeof(*ptr)))) + goto nomem_close_and_ret; + + ptr->dd_fd = fd; + ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0; + ptr->dd_max = statbuf.st_blksize; + if (ptr->dd_max < 512) + ptr->dd_max = 512; + + if (!(ptr->dd_buf = calloc(1, ptr->dd_max))) { + free(ptr); +nomem_close_and_ret: + close(fd); + __set_errno(ENOMEM); + return NULL; + } + __pthread_mutex_init(&(ptr->dd_lock), NULL); + return ptr; +} +libc_hidden_def(opendir) diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c new file mode 100644 index 0000000..2fb7a72 --- /dev/null +++ b/libc/misc/dirent/readdir.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#include +#include +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(readdir) + +struct dirent *readdir(DIR * dir) +{ + ssize_t bytes; + struct dirent *de; + + if (!dir) { + __set_errno(EBADF); + return NULL; + } + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + de = NULL; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + + /* Skip deleted files. */ + } while (de->d_ino == 0); + +all_done: + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return de; +} +libc_hidden_def(readdir) diff --git a/libc/misc/dirent/readdir64.c b/libc/misc/dirent/readdir64.c new file mode 100644 index 0000000..e8a29da --- /dev/null +++ b/libc/misc/dirent/readdir64.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(readdir64) +struct dirent64 *readdir64(DIR * dir) +{ + ssize_t bytes; + struct dirent64 *de; + + if (!dir) { + __set_errno(EBADF); + return NULL; + } + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + de = NULL; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + + /* Skip deleted files. */ + } while (de->d_ino == 0); + +all_done: + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + + return de; +} +libc_hidden_def(readdir64) diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c new file mode 100644 index 0000000..2958b1d --- /dev/null +++ b/libc/misc/dirent/readdir64_r.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +libc_hidden_proto(readdir64_r) +int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result) +{ + int ret; + ssize_t bytes; + struct dirent64 *de; + + if (!dir) { + __set_errno(EBADF); + return(EBADF); + } + de = NULL; + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + *result = NULL; + ret = (bytes==0)? 0 : errno; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + /* Skip deleted files. */ + } while (de->d_ino == 0); + + if (de == NULL) { + *result = NULL; + } else { + *result = memcpy (entry, de, de->d_reclen); + } + ret = 0; + +all_done: + + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return((de != NULL)? 0 : ret); +} +libc_hidden_def(readdir64_r) diff --git a/libc/misc/dirent/readdir_r.c b/libc/misc/dirent/readdir_r.c new file mode 100644 index 0000000..194af62 --- /dev/null +++ b/libc/misc/dirent/readdir_r.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +libc_hidden_proto(readdir_r) +int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) +{ + int ret; + ssize_t bytes; + struct dirent *de; + + if (!dir) { + __set_errno(EBADF); + return(EBADF); + } + de = NULL; + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + *result = NULL; + ret = (bytes==0)? 0 : errno; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + /* Skip deleted files. */ + } while (de->d_ino == 0); + + if (de == NULL) { + *result = NULL; + } else { + *result = memcpy (entry, de, de->d_reclen); + } + ret = 0; + +all_done: + + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return((de != NULL)? 0 : ret); +} +libc_hidden_def(readdir_r) diff --git a/libc/misc/dirent/rewinddir.c b/libc/misc/dirent/rewinddir.c new file mode 100644 index 0000000..1bbda08 --- /dev/null +++ b/libc/misc/dirent/rewinddir.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(lseek) + +/* rewinddir() just does an lseek(fd,0,0) - see close for comments */ +void rewinddir(DIR * dir) +{ + if (!dir) { + __set_errno(EBADF); + return; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + lseek(dir->dd_fd, 0, SEEK_SET); + dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); +} diff --git a/libc/misc/dirent/scandir.c b/libc/misc/dirent/scandir.c new file mode 100644 index 0000000..9b0f738 --- /dev/null +++ b/libc/misc/dirent/scandir.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(opendir) +libc_hidden_proto(closedir) +libc_hidden_proto(qsort) +libc_hidden_proto(readdir) + +int scandir(const char *dir, struct dirent ***namelist, + int (*selector) (const struct dirent *), + int (*compar) (const void *, const void *)) +{ + DIR *dp = opendir (dir); + struct dirent *current; + struct dirent **names = NULL; + size_t names_size = 0, pos; + int save; + + if (dp == NULL) + return -1; + + save = errno; + __set_errno (0); + + pos = 0; + while ((current = readdir (dp)) != NULL) { + int use_it = selector == NULL; + + if (! use_it) + { + use_it = (*selector) (current); + /* The selector function might have changed errno. + * It was zero before and it need to be again to make + * the latter tests work. */ + if (! use_it) + __set_errno (0); + } + if (use_it) + { + struct dirent *vnew; + size_t dsize; + + /* Ignore errors from selector or readdir */ + __set_errno (0); + + if (unlikely(pos == names_size)) + { + struct dirent **new; + if (names_size == 0) + names_size = 10; + else + names_size *= 2; + new = (struct dirent **) realloc (names, + names_size * sizeof (struct dirent *)); + if (new == NULL) + break; + names = new; + } + + dsize = ¤t->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current; + vnew = (struct dirent *) malloc (dsize); + if (vnew == NULL) + break; + + names[pos++] = (struct dirent *) memcpy (vnew, current, dsize); + } + } + + if (unlikely(errno != 0)) + { + save = errno; + closedir (dp); + while (pos > 0) + free (names[--pos]); + free (names); + __set_errno (save); + return -1; + } + + closedir (dp); + __set_errno (save); + + /* Sort the list if we have a comparison function to sort with. */ + if (compar != NULL) + qsort (names, pos, sizeof (struct dirent *), compar); + *namelist = names; + return pos; +} diff --git a/libc/misc/dirent/scandir64.c b/libc/misc/dirent/scandir64.c new file mode 100644 index 0000000..de294c6 --- /dev/null +++ b/libc/misc/dirent/scandir64.c @@ -0,0 +1,117 @@ +/* Copyright (C) 1992-1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + */ + +/* Modified for uClibc by Erik Andersen + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(opendir) +libc_hidden_proto(closedir) +libc_hidden_proto(qsort) +libc_hidden_proto(readdir64) + +int scandir64(const char *dir, struct dirent64 ***namelist, + int (*selector) (const struct dirent64 *), + int (*compar) (const void *, const void *)) +{ + DIR *dp = opendir (dir); + struct dirent64 *current; + struct dirent64 **names = NULL; + size_t names_size = 0, pos; + int save; + + if (dp == NULL) + return -1; + + save = errno; + __set_errno (0); + + pos = 0; + while ((current = readdir64 (dp)) != NULL) { + int use_it = selector == NULL; + + if (! use_it) + { + use_it = (*selector) (current); + /* The selector function might have changed errno. + * It was zero before and it need to be again to make + * the latter tests work. */ + if (! use_it) + __set_errno (0); + } + if (use_it) + { + struct dirent64 *vnew; + size_t dsize; + + /* Ignore errors from selector or readdir64 */ + __set_errno (0); + + if (unlikely(pos == names_size)) + { + struct dirent64 **new; + if (names_size == 0) + names_size = 10; + else + names_size *= 2; + new = (struct dirent64 **) realloc (names, + names_size * sizeof (struct dirent64 *)); + if (new == NULL) + break; + names = new; + } + + dsize = ¤t->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current; + vnew = (struct dirent64 *) malloc (dsize); + if (vnew == NULL) + break; + + names[pos++] = (struct dirent64 *) memcpy (vnew, current, dsize); + } + } + if (unlikely(errno != 0)) + { + save = errno; + closedir (dp); + while (pos > 0) + free (names[--pos]); + free (names); + __set_errno (save); + return -1; + } + + closedir (dp); + __set_errno (save); + + /* Sort the list if we have a comparison function to sort with. */ + if (compar != NULL) + qsort (names, pos, sizeof (struct dirent64 *), compar); + *namelist = names; + return pos; +} diff --git a/libc/misc/dirent/seekdir.c b/libc/misc/dirent/seekdir.c new file mode 100644 index 0000000..c418448 --- /dev/null +++ b/libc/misc/dirent/seekdir.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + +libc_hidden_proto(lseek) + +void seekdir(DIR * dir, long int offset) +{ + if (!dir) { + __set_errno(EBADF); + return; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET); + dir->dd_size = dir->dd_nextloc = 0; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); +} diff --git a/libc/misc/dirent/telldir.c b/libc/misc/dirent/telldir.c new file mode 100644 index 0000000..3c5deca --- /dev/null +++ b/libc/misc/dirent/telldir.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + + +long int telldir(DIR * dir) +{ + if (!dir) { + __set_errno(EBADF); + return -1; + } + + /* The next entry. */ + return dir->dd_nextoff; +} diff --git a/libc/misc/error/Makefile b/libc/misc/error/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/error/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/error/Makefile.in b/libc/misc/error/Makefile.in new file mode 100644 index 0000000..d0e60a2 --- /dev/null +++ b/libc/misc/error/Makefile.in @@ -0,0 +1,27 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := +ifeq ($(UCLIBC_HAS_BSD_ERR),y) +CSRC += err.c +endif +ifeq ($(UCLIBC_HAS_GNU_ERROR),y) +CSRC += error.c +endif + +MISC_ERROR_DIR := $(top_srcdir)libc/misc/error +MISC_ERROR_OUT := $(top_builddir)libc/misc/error + +MISC_ERROR_SRC := $(patsubst %.c,$(MISC_ERROR_DIR)/%.c,$(CSRC)) +MISC_ERROR_OBJ := $(patsubst %.c,$(MISC_ERROR_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_ERROR_OBJ) + +objclean-y += misc_error_clean + +misc_error_clean: + $(do_rm) $(addprefix $(MISC_ERROR_OUT)/*., o os) diff --git a/libc/misc/error/err.c b/libc/misc/error/err.c new file mode 100644 index 0000000..ab9c8b7 --- /dev/null +++ b/libc/misc/error/err.c @@ -0,0 +1,129 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Deal with wide oriented stderr case. +#endif + +#if defined __USE_BSD + +libc_hidden_proto(vwarn) +libc_hidden_proto(vwarnx) +libc_hidden_proto(verr) +libc_hidden_proto(verrx) + +libc_hidden_proto(fprintf) +libc_hidden_proto(vfprintf) +libc_hidden_proto(__xpg_strerror_r) +libc_hidden_proto(exit) +libc_hidden_proto(vfprintf) + +static void vwarn_work(const char *format, va_list args, int showerr) +{ + /* 0123 45678 9 a b*/ + static const char fmt[] = "%s: \0: %s\n\0\n"; + const char *f; + char buf[64]; + __STDIO_AUTO_THREADLOCK_VAR; + + /* Do this first, in case something below changes errno. */ + f = fmt + 11; /* At 11. */ + if (showerr) { + f -= 4; /* At 7. */ + __xpg_strerror_r(errno, buf, sizeof(buf)); + } + + __STDIO_AUTO_THREADLOCK(stderr); + + fprintf(stderr, fmt, __uclibc_progname); + if (format) { + vfprintf(stderr, format, args); + f -= 2; /* At 5 (showerr) or 9. */ + } + fprintf(stderr, f, buf); + + __STDIO_AUTO_THREADUNLOCK(stderr); +} + +void vwarn(const char *format, va_list args) +{ + vwarn_work(format, args, 1); +} +libc_hidden_def(vwarn) + +void warn(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vwarn(format, args); + va_end(args); +} + +void vwarnx(const char *format, va_list args) +{ + vwarn_work(format, args, 0); +} +libc_hidden_def(vwarnx) + +void warnx(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vwarnx(format, args); + va_end(args); +} + +void verr(int status, const char *format, va_list args) +{ + vwarn(format, args); + exit(status); +} +libc_hidden_def(verr) + +void attribute_noreturn err(int status, const char *format, ...) +{ + va_list args; + + va_start(args, format); + verr(status, format, args); + /* This should get optimized away. We'll leave it now for safety. */ + /* The loop is added only to keep gcc happy. */ + while(1) + va_end(args); +} + +void verrx(int status, const char *format, va_list args) +{ + vwarnx(format, args); + exit(status); +} +libc_hidden_def(verrx) + +void attribute_noreturn errx(int status, const char *format, ...) +{ + va_list args; + + va_start(args, format); + verrx(status, format, args); + /* This should get optimized away. We'll leave it now for safety. */ + /* The loop is added only to keep gcc happy. */ + while(1) + va_end(args); +} +#endif diff --git a/libc/misc/error/error.c b/libc/misc/error/error.c new file mode 100644 index 0000000..ed4a62e --- /dev/null +++ b/libc/misc/error/error.c @@ -0,0 +1,115 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990-1998, 2000-2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by David MacKenzie . */ +/* Adjusted slightly by Erik Andersen */ + +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strerror) */ +libc_hidden_proto(fprintf) +libc_hidden_proto(exit) +libc_hidden_proto(putc) +libc_hidden_proto(vfprintf) +libc_hidden_proto(fflush) +libc_hidden_proto(fputc) +libc_hidden_proto(__fputc_unlocked) + +/* This variable is incremented each time `error' is called. */ +unsigned int error_message_count = 0; +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +int error_one_per_line; +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +void (*error_print_progname) (void) = NULL; + +extern __typeof(error) __error attribute_hidden; +void __error (int status, int errnum, const char *message, ...) +{ + va_list args; + + fflush (stdout); + + if (error_print_progname) + (*error_print_progname) (); + else + fprintf (stderr, "%s: ", __uclibc_progname); + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + ++error_message_count; + if (errnum) { + fprintf (stderr, ": %s", strerror (errnum)); + } + putc ('\n', stderr); + if (status) + exit (status); +} +weak_alias(__error,error) + +extern __typeof(error_at_line) __error_at_line attribute_hidden; +void __error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +{ + va_list args; + + if (error_one_per_line) { + static const char *old_file_name; + static unsigned int old_line_number; + + if (old_line_number == line_number && + (file_name == old_file_name || !strcmp (old_file_name, file_name))) + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + + fflush (stdout); + + if (error_print_progname) + (*error_print_progname) (); + else + fprintf (stderr, "%s:", __uclibc_progname); + + if (file_name != NULL) + fprintf (stderr, "%s:%d: ", file_name, line_number); + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + + ++error_message_count; + if (errnum) { + fprintf (stderr, ": %s", strerror (errnum)); + } + putc ('\n', stderr); + if (status) + exit (status); +} +weak_alias(__error_at_line,error_at_line) diff --git a/libc/misc/file/Makefile b/libc/misc/file/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/file/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/file/Makefile.in b/libc/misc/file/Makefile.in new file mode 100644 index 0000000..43b639c --- /dev/null +++ b/libc/misc/file/Makefile.in @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +MISC_FILE_DIR := $(top_srcdir)libc/misc/file +MISC_FILE_OUT := $(top_builddir)libc/misc/file + +MISC_FILE_SRC := $(wildcard $(MISC_FILE_DIR)/*.c) +ifneq ($(UCLIBC_HAS_LFS),y) +MISC_FILE_SRC := $(filter-out $(MISC_FILE_DIR)/lockf64.c,$(MISC_FILE_SRC)) +endif +MISC_FILE_OBJ := $(patsubst $(MISC_FILE_DIR)/%.c,$(MISC_FILE_OUT)/%.o,$(MISC_FILE_SRC)) + +libc-y += $(MISC_FILE_OBJ) + +libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_FILE_OUT)/lockf64.o + +objclean-y += misc_file_clean + +misc_file_clean: + $(do_rm) $(addprefix $(MISC_FILE_OUT)/*., o os oS) diff --git a/libc/misc/file/lockf.c b/libc/misc/file/lockf.c new file mode 100644 index 0000000..13b56ab --- /dev/null +++ b/libc/misc/file/lockf.c @@ -0,0 +1,79 @@ +/* Copyright (C) 1994, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include +#include +#include + +libc_hidden_proto(lockf) + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(fcntl) +libc_hidden_proto(getpid) + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +int lockf (int fd, int cmd, off_t len) +{ + struct flock fl; + + memset ((char *) &fl, '\0', sizeof (fl)); + + /* lockf is always relative to the current file position. */ + fl.l_whence = SEEK_CUR; + fl.l_start = 0; + fl.l_len = len; + + switch (cmd) + { + case F_TEST: + /* Test the lock: return 0 if FD is unlocked or locked by this process; + return -1, set errno to EACCES, if another process holds the lock. */ + fl.l_type = F_RDLCK; + if (fcntl (fd, F_GETLK, &fl) < 0) + return -1; + if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) + return 0; + __set_errno(EACCES); + return -1; + + case F_ULOCK: + fl.l_type = F_UNLCK; + cmd = F_SETLK; + break; + case F_LOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLKW; + break; + case F_TLOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLK; + break; + + default: + __set_errno(EINVAL); + return -1; + } + + return fcntl(fd, cmd, &fl); +} +libc_hidden_def(lockf) diff --git a/libc/misc/file/lockf64.c b/libc/misc/file/lockf64.c new file mode 100644 index 0000000..b2ffe5d --- /dev/null +++ b/libc/misc/file/lockf64.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1994, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include + +#ifdef __NR_fcntl64 +#define flock flock64 +#define fcntl fcntl64 +#undef F_GETLK +#define F_GETLK F_GETLK64 +#undef F_SETLK +#define F_SETLK F_SETLK64 +libc_hidden_proto(fcntl64) +#else +libc_hidden_proto(fcntl) +#endif + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(getpid) + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +libc_hidden_proto(lockf64) +int lockf64 (int fd, int cmd, off64_t len64) +{ + struct flock fl; + off_t len = (off_t) len64; + + if (len64 != (off64_t) len) + { + /* We can't represent the length. */ + __set_errno(EOVERFLOW); + return -1; + } + + memset((char *) &fl, '\0', sizeof (fl)); + + /* lockf is always relative to the current file position. */ + fl.l_whence = SEEK_CUR; + fl.l_start = 0; + fl.l_len = len; + + switch (cmd) + { + case F_TEST: + /* Test the lock: return 0 if FD is unlocked or locked by this process; + return -1, set errno to EACCES, if another process holds the lock. */ + fl.l_type = F_RDLCK; + if (fcntl (fd, F_GETLK, &fl) < 0) + return -1; + if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) + return 0; + __set_errno(EACCES); + return -1; + + case F_ULOCK: + fl.l_type = F_UNLCK; + cmd = F_SETLK; + break; + case F_LOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLKW; + break; + case F_TLOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLK; + break; + + default: + __set_errno(EINVAL); + return -1; + } + + return fcntl(fd, cmd, &fl); +} +libc_hidden_def(lockf64) diff --git a/libc/misc/fnmatch/.indent.pro b/libc/misc/fnmatch/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/fnmatch/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/fnmatch/Makefile b/libc/misc/fnmatch/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/fnmatch/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/fnmatch/Makefile.in b/libc/misc/fnmatch/Makefile.in new file mode 100644 index 0000000..ac9076d --- /dev/null +++ b/libc/misc/fnmatch/Makefile.in @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifeq ($(UCLIBC_HAS_FNMATCH_OLD),y) +CSRC := fnmatch_old.c +else +CSRC := fnmatch.c +endif + +MISC_FNMATCH_DIR := $(top_srcdir)libc/misc/fnmatch +MISC_FNMATCH_OUT := $(top_builddir)libc/misc/fnmatch + +MISC_FNMATCH_SRC := $(patsubst %.c,$(MISC_FNMATCH_DIR)/%.c,$(CSRC)) +MISC_FNMATCH_OBJ := $(patsubst %.c,$(MISC_FNMATCH_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_FNMATCH) += $(MISC_FNMATCH_OBJ) + +objclean-y += misc_fnmatch_clean + +misc_fnmatch_clean: + $(do_rm) $(addprefix $(MISC_FNMATCH_OUT)/*., o os) diff --git a/libc/misc/fnmatch/fnmatch.c b/libc/misc/fnmatch/fnmatch.c new file mode 100644 index 0000000..8592d4c --- /dev/null +++ b/libc/misc/fnmatch/fnmatch.c @@ -0,0 +1,476 @@ +/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#ifdef __UCLIBC__ +# undef _LIBC +# define HAVE_STRING_H 1 +# define STDC_HEADERS +# define HAVE___STRCHRNUL 1 +# ifdef __UCLIBC_HAS_WCHAR__ +# define HAVE_WCHAR_H 1 +# define HAVE_WCTYPE_H 1 +# ifdef __UCLIBC_HAS_LOCALE__ +# define HAVE_MBSTATE_T 1 +# define HAVE_MBSRTOWCS 1 +# endif +# endif +#endif + +#include +#include +#include +#include +#include + +#if HAVE_STRING_H || defined _LIBC +# include +#else +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#ifdef __UCLIBC__ +#define __memset memset +/* Experimentally off - libc_hidden_proto(memchr) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(mempcpy) */ +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/*libc_hidden_proto(strchr)*/ +/*libc_hidden_proto(strchrnul)*/ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcoll) */ +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +libc_hidden_proto(__ctype_tolower_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +#endif +libc_hidden_proto(tolower) +libc_hidden_proto(fnmatch) +libc_hidden_proto(getenv) +#endif + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +# ifdef __UCLIBC__ +libc_hidden_proto(wctype) +libc_hidden_proto(iswctype) +libc_hidden_proto(btowc) +# ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(wmemchr) +libc_hidden_proto(wmempcpy) +libc_hidden_proto(wcscat) +/*libc_hidden_proto(wcschr)*/ +/*libc_hidden_proto(wcschrnul)*/ +libc_hidden_proto(wcslen) +libc_hidden_proto(wcscoll) +libc_hidden_proto(towlower) +libc_hidden_proto(mbsrtowcs) +# endif +# endif +#endif + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/elem-hash.h" +# include "../locale/coll-lookup.h" +# include + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +# if !defined _LIBC && !defined getenv && !defined __UCLIBC__ +extern char *getenv (); +# endif + +# ifndef errno +extern int errno; +# endif + +/* Global variable. */ +static smallint posixly_correct; + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (s, c) + const char *s; + int c; +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC +static wchar_t * +__wcschrnul (s, c) + const wchar_t *s; + wint_t c; +{ + wchar_t *result = wcschr (s, c); + if (result == NULL) + result = wcschr (s, '\0'); + return result; +} +# endif + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif +# define CHAR char +# define UCHAR unsigned char +# define INT int +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define L(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen (S) +# define STRCAT(D, S) strcat (D, S) +# define MEMPCPY(D, S, N) mempcpy (D, S, N) +# define MEMCHR(S, C, N) memchr (S, C, N) +# define STRCOLL(S1, S2) strcoll (S1, S2) +# include "fnmatch_loop.c" + + +# if HANDLE_MULTIBYTE +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c)) +# endif +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define L(CS) L##CS +# define BTOWC(C) (C) +# define STRLEN(S) wcslen (S) +# define STRCAT(D, S) wcscat (D, S) +# define MEMPCPY(D, S, N) wmempcpy (D, S, N) +# define MEMCHR(S, C, N) wmemchr (S, C, N) +# define STRCOLL(S1, S2) wcscoll (S1, S2) +# ifndef __UCLIBC__ +# define WIDE_CHAR_VERSION 1 +# endif + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# if defined _LIBC || defined __UCLIBC__ + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(_stdlib_mb_cur_max) +#else +#undef MB_CUR_MAX +#define MB_CUR_MAX 1 +#endif + +int +fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t n; + const char *p; + wchar_t *wpattern = NULL; + wchar_t *wstring = NULL; + + /* Convert the strings into wide characters. */ + __memset (&ps, '\0', sizeof (ps)); + p = pattern; +#ifdef _LIBC + n = strnlen (pattern, 1024); +#else + n = strlen (pattern); +#endif + if (__builtin_expect (n < 1024, 1)) + { + wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + n = mbsrtowcs (wpattern, &p, n + 1, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + __memset (&ps, '\0', sizeof (ps)); + } + if (__builtin_expect (p != NULL, 0)) + { + n = mbsrtowcs (NULL, &pattern, 0, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); + } + + assert (mbsinit (&ps)); +#ifdef _LIBC + n = strnlen (string, 1024); +#else + n = strlen (string); +#endif + p = string; + if (__builtin_expect (n < 1024, 1)) + { + wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + n = mbsrtowcs (wstring, &p, n + 1, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + __memset (&ps, '\0', sizeof (ps)); + } + if (__builtin_expect (p != NULL, 0)) + { + n = mbsrtowcs (NULL, &string, 0, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + (void) mbsrtowcs (wstring, &string, n + 1, &ps); + } + + return internal_fnwmatch (wpattern, wstring, wstring + n, + flags & FNM_PERIOD, flags); + } +# endif /* mbstate_t and mbsrtowcs or _LIBC. */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# else +libc_hidden_def(fnmatch) +# endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/libc/misc/fnmatch/fnmatch_loop.c b/libc/misc/fnmatch/fnmatch_loop.c new file mode 100644 index 0000000..af41727 --- /dev/null +++ b/libc/misc/fnmatch/fnmatch_loop.c @@ -0,0 +1,1205 @@ +/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int FCT (const CHAR *pattern, const CHAR *string, + const CHAR *string_end, int no_leading_period, int flags) + internal_function; +static int EXT (INT opt, const CHAR *pattern, const CHAR *string, + const CHAR *string_end, int no_leading_period, int flags) + internal_function; +static const CHAR *END (const CHAR *patternp) internal_function; + +static int +internal_function +FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, + int no_leading_period, int flags) +{ + register const CHAR *p = pattern, *n = string; + register UCHAR c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const UCHAR *collseq = (const UCHAR *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != L('\0')) + { + int new_no_leading_period = 0; + c = FOLD (c); + + switch (c) + { + case L('?'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == L('/') && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == L('.') && no_leading_period) + return FNM_NOMATCH; + break; + + case L('\\'): + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == L('\0')) + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((UCHAR) *n) != c) + return FNM_NOMATCH; + break; + + case L('*'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n != string_end && *n == L('.') && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == L('?') || c == L('*'); c = *p++) + { + if (*p == L('(') && (flags & FNM_EXTMATCH) != 0) + { + const CHAR *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == L('?')) + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == L('/') + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == L('\0')) + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, L('/'), string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const CHAR *endp; + + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'), + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == L('[') + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == L('@') || c == L('+') || c == L('!')) + && *p == L('('))) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + for (--p; n < endp; ++n, no_leading_period2 = 0) + if (FCT (p, n, string_end, no_leading_period2, flags2) + == 0) + return 0; + } + else if (c == L('/') && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != L('/')) + ++n; + if (n < string_end && *n == L('/') + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) + == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + if (c == L('\\') && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period2 = 0) + if (FOLD ((UCHAR) *n) == c + && (FCT (p, n, string_end, no_leading_period2, flags2) + == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case L('['): + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + CHAR cold; + UCHAR fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == L('.') && no_leading_period) + return FNM_NOMATCH; + + if (*n == L('/') && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == L('!') || (posixly_correct < 0 && *p == L('^'))); + if (not) + ++p; + + fn = FOLD ((UCHAR) *n); + + c = *p++; + for (;;) + { + if (!(flags & FNM_NOESCAPE) && c == L('\\')) + { + if (*p == L('\0')) + return FNM_NOMATCH; + c = FOLD ((UCHAR) *p); + ++p; + + goto normal_bracket; + } + else if (c == L('[') && *p == L(':')) + { + /* Leave room for the null. */ + CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +#endif + const CHAR *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L(':') && p[1] == L(']')) + { + p += 2; + break; + } + if (c < L('a') || c >= L('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L('\0'); + +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((UCHAR) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n)) + || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n)) + || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n)) + || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n)) + || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n)) + || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n)) + || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n)) + || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n)) + || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n)) + || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n)) + || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n)) + || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L('[') && *p == L('=')) + { + UCHAR str[1]; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + + c = *++p; + if (c == L('\0')) + { + p = startp; + c = L('['); + goto normal_bracket; + } + str[0] = c; + + c = *++p; + if (c != L('=') || p[1] != L(']')) + { + p = startp; + c = L('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((UCHAR) *n == str[0]) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const int32_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const UCHAR *cp = (const UCHAR *) str; + + /* This #include defines a local function! */ +# if WIDE_CHAR_VERSION +# include +# else +# include +# endif + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = findidx (&cp); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalance class value. */ + int len = weights[idx]; + int32_t idx2; + const UCHAR *np = (const UCHAR *) n; + + idx2 = findidx (&np); + if (idx2 != 0 && len == weights[idx2]) + { + int cnt = 0; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L('\0')) + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + else + { + int is_range = 0; + +#ifdef _LIBC + int is_seqval = 0; + + if (c == L('[') && *p == L('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L('.') && p[1] == L(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L('-') && p[1] != L('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + unsigned int strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +#endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && __memcmp (str, + &extra[symb_table[2 * elem + + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + + if (! is_range) + { +# ifdef WIDE_CHAR_VERSION + for (c1 = 0; + (int32_t) c1 < wextra[idx]; + ++c1) + if (n[c1] != wextra[1 + c1]) + break; + + if ((int32_t) c1 == wextra[idx]) + goto matched; +# else + for (c1 = 0; c1 < extra[idx]; ++c1) + if (n[c1] != extra[1 + c1]) + break; + + if (c1 == extra[idx]) + goto matched; +# endif + } + + /* Get the collation sequence value. */ + is_seqval = 1; +# ifdef WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == str[0]) + goto matched; + + cold = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +# undef str +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L('-') && p[1] != L('\0') + && p[1] != L(']')); + + if (!is_range && c == fn) + goto matched; + + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ +#ifndef __UCLIBC__ /* this should be probably ifdef _LIBC*/ + is_seqval = 0; +#endif + cold = c; + c = *p++; + } + + if (c == L('-') && *p != L(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + UCHAR cend = *p++; + +# ifdef WIDE_CHAR_VERSION + /* Search in the `names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; +# endif + + is_seqval = 0; + if (cend == L('[') && *p == L('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L('.') && p[1] == L(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + unsigned int strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing + table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && __memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~4; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + /* Get the collation sequence value. */ + is_seqval = 1; +# ifdef WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (symb_table[2 * elem] != 0 && c1 == 1) + { + cend = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } +# undef str + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L('\\')) + cend = *p++; + if (cend == L('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# ifdef WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# ifdef WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# ifdef WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + `strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + UCHAR cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L('\\')) + cend = *p++; + if (cend == L('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + do + { + ignore_next: + c = *p++; + + if (c == L('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L('\\')) + { + if (*p == L('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L('[') && *p == L(':')) + { + int c1 = 0; + const CHAR *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L(':') && p[1] == L(']')) + break; + + if (c < L('a') || c >= L('z')) + { + p = startp; + goto ignore_next; + } + } + p += 2; + c = *p++; + } + else if (c == L('[') && *p == L('=')) + { + c = *++p; + if (c == L('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L('=') || p[1] != L(']')) + return FNM_NOMATCH; + p += 2; + c = *p++; + } + else if (c == L('[') && *p == L('.')) + { + ++p; + while (1) + { + c = *++p; + if (c == '\0') + return FNM_NOMATCH; + + if (*p == L('.') && p[1] == L(']')) + break; + } + p += 2; + c = *p++; + } + } + while (c != L(']')); + if (not) + return FNM_NOMATCH; + } + break; + + case L('+'): + case L('@'): + case L('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, flags); + if (res != -1) + return res; + } + goto normal_match; + + case L('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (UCHAR) *n) + return FNM_NOMATCH; + + new_no_leading_period = 1; + break; + } + /* FALLTHROUGH */ + default: + normal_match: + if (n == string_end || c != FOLD ((UCHAR) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +static const CHAR * +internal_function +END (const CHAR *pattern) +{ + const CHAR *p = pattern; + + while (1) + if (*++p == L('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L(']')) + if (*p++ == L('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') + || *p == L('!')) && p[1] == L('(')) + p = END (p + 1); + else if (*p == L(')')) + break; + + return p + 1; +} + + +static int +internal_function +EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, + int no_leading_period, int flags) +{ + const CHAR *startp; + int level; + struct patternlist + { + struct patternlist *next; + CHAR str[0]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + const CHAR *p; + const CHAR *rs; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; level >= 0; ++p) + if (*p == L('\0')) + /* This is an invalid pattern. */ + return -1; + else if (*p == L('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L(']')) + if (*p++ == L('\0')) + /* This is no valid pattern. */ + return -1; + } + else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') + || *p == L('!')) && p[1] == L('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + \ + if (opt == L('?') || opt == L('@')) \ + newp = alloca (sizeof (struct patternlist) \ + + (pattern_len * sizeof (CHAR))); \ + else \ + newp = alloca (sizeof (struct patternlist) \ + + ((p - startp + 1) * sizeof (CHAR))); \ + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ + newp->next = NULL; \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + } + } + else if (*p == L('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L(')')); +#undef NEW_PATTERN + + switch (opt) + { + case L('*'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + /* FALLTHROUGH */ + + case L('+'): + do + { + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : (rs[-1] == '/' && NO_LEADING_PERIOD (flags) + ? 1 : 0), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0))) + /* It worked. Signal success. */ + return 0; + } + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L('?'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + /* FALLTHROUGH */ + + case L('@'): + do + /* I cannot believe it but `strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if (FCT (STRCAT (list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + /* It worked. Signal success. */ + return 0; + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L('!'): + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) + == 0)) + /* This is successful. */ + return 0; + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + return FNM_NOMATCH; + + default: + assert (! "Invalid extended matching operator"); + break; + } + + return -1; +} + + +#undef FOLD +#undef CHAR +#undef UCHAR +#undef INT +#undef FCT +#undef EXT +#undef END +#undef MEMPCPY +#undef MEMCHR +#undef STRCOLL +#undef STRLEN +#undef STRCAT +#undef L +#undef BTOWC diff --git a/libc/misc/fnmatch/fnmatch_old.c b/libc/misc/fnmatch/fnmatch_old.c new file mode 100644 index 0000000..577e356 --- /dev/null +++ b/libc/misc/fnmatch/fnmatch_old.c @@ -0,0 +1,222 @@ +/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +libc_hidden_proto(fnmatch) + +libc_hidden_proto(tolower) +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +# if defined (STDC_HEADERS) || !defined (isascii) +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int fnmatch(const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') { + c = FOLD(c); + + switch (c) { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string + || ((flags & FNM_FILE_NAME) + && n[-1] == '/'))) return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD(c); + } + if (FOLD(*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) { + if ((flags & FNM_FILE_NAME) && *n == '/') + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + + c1 = FOLD(c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD(*n) == c1) && + fnmatch(p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } + + cstart = cend = FOLD(cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD(c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD(cend); + + c = *p++; + } + + if (FOLD(*n) >= cstart && FOLD(*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD(*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} +libc_hidden_def(fnmatch) +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/libc/misc/ftw/Makefile b/libc/misc/ftw/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/ftw/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/ftw/Makefile.in b/libc/misc/ftw/Makefile.in new file mode 100644 index 0000000..bceab21 --- /dev/null +++ b/libc/misc/ftw/Makefile.in @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := ftw.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += ftw64.c +endif + +MISC_FTW_DIR := $(top_srcdir)libc/misc/ftw +MISC_FTW_OUT := $(top_builddir)libc/misc/ftw + +MISC_FTW_SRC := $(patsubst %.c,$(MISC_FTW_DIR)/%.c,$(CSRC)) +MISC_FTW_OBJ := $(patsubst %.c,$(MISC_FTW_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_FTW) += $(MISC_FTW_OBJ) + +objclean-y += misc_ftw_clean + +misc_ftw_clean: + $(do_rm) $(addprefix $(MISC_FTW_OUT)/*., o os) diff --git a/libc/misc/ftw/ftw.c b/libc/misc/ftw/ftw.c new file mode 100644 index 0000000..c136f1e --- /dev/null +++ b/libc/misc/ftw/ftw.c @@ -0,0 +1,826 @@ +/* File tree walker functions. + Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#ifdef __UCLIBC__ +#undef _LIBC +#define HAVE_DIRENT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_DECL_STPCPY 1 +#define HAVE_MEMPCPY 1 +#endif + +#if __GNUC__ +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + # pragma alloca +# else +char *alloca (); +# endif +# endif +#endif + +#if defined _LIBC +# include +# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent) +#else +# if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen ((dirent)->d_name) +# else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#if HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif +#ifdef _LIBC +# include +#else +# include +#endif + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(dirfd) +libc_hidden_proto(tsearch) +libc_hidden_proto(tfind) +libc_hidden_proto(tdestroy) +libc_hidden_proto(getcwd) +libc_hidden_proto(chdir) +libc_hidden_proto(fchdir) +/* Experimentally off - libc_hidden_proto(mempcpy) */ +libc_hidden_proto(opendir) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(readdir64) +libc_hidden_proto(lstat64) +libc_hidden_proto(stat64) +#endif +libc_hidden_proto(closedir) +/* Experimentally off - libc_hidden_proto(stpcpy) */ +libc_hidden_proto(lstat) +libc_hidden_proto(stat) + +#if ! _LIBC && !HAVE_DECL_STPCPY && !defined stpcpy +char *stpcpy (); +#endif + +#if ! _LIBC && ! defined HAVE_MEMPCPY && ! defined mempcpy +/* Be CAREFUL that there are no side effects in N. */ +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +/* #define NDEBUG 1 */ +#include + +#if !defined _LIBC +# undef __chdir +# define __chdir chdir +# undef __closedir +# define __closedir closedir +# undef __fchdir +# define __fchdir fchdir +# undef __getcwd +# ifndef __UCLIBC__ +# define __getcwd(P, N) xgetcwd () +extern char *xgetcwd (void); +# else +# define __getcwd getcwd +# endif +# undef __mempcpy +# define __mempcpy mempcpy +# undef __opendir +# define __opendir opendir +# undef __readdir64 +# ifndef __UCLIBC_HAS_LFS__ +# define __readdir64 readdir +# else +# define __readdir64 readdir64 +# endif +# undef __stpcpy +# define __stpcpy stpcpy +# undef __tdestroy +# define __tdestroy tdestroy +# undef __tfind +# define __tfind tfind +# undef __tsearch +# define __tsearch tsearch +# undef internal_function +# define internal_function /* empty */ +# ifndef __UCLIBC_HAS_LFS__ +# undef dirent64 +# define dirent64 dirent +# endif +# undef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* Arrange to make lstat calls go through the wrapper function + on systems with an lstat function that does not dereference symlinks + that are specified with a trailing slash. */ +#if ! _LIBC && ! LSTAT_FOLLOWS_SLASHED_SYMLINK && !defined __UCLIBC__ +int rpl_lstat (const char *, struct stat *); +# undef lstat +# define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf) +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +/* Support for the LFS API version. */ +#ifndef FTW_NAME +# define FTW_NAME ftw +# define NFTW_NAME nftw +# define NFTW_OLD_NAME __old_nftw +# define NFTW_NEW_NAME __new_nftw +# define INO_T ino_t +# define STAT stat +# ifdef _LIBC +# define LXSTAT __lxstat +# define XSTAT __xstat +# else +# define LXSTAT(V,f,sb) lstat (f,sb) +# define XSTAT(V,f,sb) stat (f,sb) +# endif +# define FTW_FUNC_T __ftw_func_t +# define NFTW_FUNC_T __nftw_func_t +#endif + +/* We define PATH_MAX if the system does not provide a definition. + This does not artificially limit any operation. PATH_MAX is simply + used as a guesstimate for the expected maximal path length. + Buffers will be enlarged if necessary. */ +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +struct dir_data +{ + DIR *stream; + char *content; +}; + +struct known_object +{ + dev_t dev; + INO_T ino; +}; + +struct ftw_data +{ + /* Array with pointers to open directory streams. */ + struct dir_data **dirstreams; + size_t actdir; + size_t maxdir; + + /* Buffer containing name of currently processed object. */ + char *dirbuf; + size_t dirbufsize; + + /* Passed as fourth argument to `nftw' callback. The `base' member + tracks the content of the `dirbuf'. */ + struct FTW ftw; + + /* Flags passed to `nftw' function. 0 for `ftw'. */ + int flags; + + /* Conversion array for flag values. It is the identity mapping for + `nftw' calls, otherwise it maps the values to those known by + `ftw'. */ + const int *cvt_arr; + + /* Callback function. We always use the `nftw' form. */ + NFTW_FUNC_T func; + + /* Device of starting point. Needed for FTW_MOUNT. */ + dev_t dev; + + /* Data structure for keeping fingerprints of already processed + object. This is needed when not using FTW_PHYS. */ + void *known_objects; +}; + + +/* Internally we use the FTW_* constants used for `nftw'. When invoked + as `ftw', map each flag to the subset of values used by `ftw'. */ +static const int nftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN +}; + +static const int ftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS +}; + + +/* Forward declarations of local functions. */ +static int ftw_dir (struct ftw_data *data, struct STAT *st, + struct dir_data *old_dir) internal_function; + + +static int +object_compare (const void *p1, const void *p2) +{ + /* We don't need a sophisticated and useful comparison. We are only + interested in equality. However, we must be careful not to + accidentally compare `holes' in the structure. */ + const struct known_object *kp1 = p1, *kp2 = p2; + int cmp1; + cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino); + if (cmp1 != 0) + return cmp1; + return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev); +} + + +static __inline__ int +add_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object *newp = malloc (sizeof (struct known_object)); + if (newp == NULL) + return -1; + newp->dev = st->st_dev; + newp->ino = st->st_ino; + return __tsearch (newp, &data->known_objects, object_compare) ? 0 : -1; +} + + +static __inline__ int +find_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object obj; + obj.dev = st->st_dev; + obj.ino = st->st_ino; + return __tfind (&obj, &data->known_objects, object_compare) != NULL; +} + + +static __inline__ int +__attribute ((always_inline)) +open_dir_stream (struct ftw_data *data, struct dir_data *dirp) +{ + int result = 0; + + if (data->dirstreams[data->actdir] != NULL) + { + /* Oh, oh. We must close this stream. Get all remaining + entries and store them as a list in the `content' member of + the `struct dir_data' variable. */ + size_t bufsize = 1024; + char *buf = malloc (bufsize); + + if (buf == NULL) + result = -1; + else + { + DIR *st = data->dirstreams[data->actdir]->stream; + struct dirent64 *d; + size_t actsize = 0; + + while ((d = __readdir64 (st)) != NULL) + { + size_t this_len = NAMLEN (d); + if (actsize + this_len + 2 >= bufsize) + { + char *newp; + bufsize += MAX (1024, 2 * this_len); + newp = (char *) realloc (buf, bufsize); + if (newp == NULL) + { + /* No more memory. */ + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + break; + } + buf = newp; + } + + *((char *) __mempcpy (buf + actsize, d->d_name, this_len)) + = '\0'; + actsize += this_len + 1; + } + + /* Terminate the list with an additional NUL byte. */ + buf[actsize++] = '\0'; + + /* Shrink the buffer to what we actually need. */ + data->dirstreams[data->actdir]->content = realloc (buf, actsize); + if (data->dirstreams[data->actdir]->content == NULL) + { + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + } + else + { + __closedir (st); + data->dirstreams[data->actdir]->stream = NULL; + data->dirstreams[data->actdir] = NULL; + } + } + } + + /* Open the new stream. */ + if (result == 0) + { + const char *name = ((data->flags & FTW_CHDIR) + ? data->dirbuf + data->ftw.base: data->dirbuf); + assert (data->dirstreams[data->actdir] == NULL); + + dirp->stream = __opendir (name); + if (dirp->stream == NULL) + result = -1; + else + { + dirp->content = NULL; + data->dirstreams[data->actdir] = dirp; + + if (++data->actdir == data->maxdir) + data->actdir = 0; + } + } + + return result; +} + + +static int +internal_function +process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, + size_t namlen) +{ + struct STAT st; + int result = 0; + int flag = 0; + size_t new_buflen; + + if (name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0'))) + /* Don't process the "." and ".." entries. */ + return 0; + + new_buflen = data->ftw.base + namlen + 2; + if (data->dirbufsize < new_buflen) + { + /* Enlarge the buffer. */ + char *newp; + + data->dirbufsize = 2 * new_buflen; + newp = (char *) realloc (data->dirbuf, data->dirbufsize); + if (newp == NULL) + return -1; + data->dirbuf = newp; + } + + *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + + if ((data->flags & FTW_CHDIR) == 0) + name = data->dirbuf; + + if (((data->flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) + { + if (errno != EACCES && errno != ENOENT) + result = -1; + else if (!(data->flags & FTW_PHYS) + && LXSTAT (_STAT_VER, name, &st) == 0 + && S_ISLNK (st.st_mode)) + flag = FTW_SLN; + else + flag = FTW_NS; + } + else + { + if (S_ISDIR (st.st_mode)) + flag = FTW_D; + else if (S_ISLNK (st.st_mode)) + flag = FTW_SL; + else + flag = FTW_F; + } + + if (result == 0 + && (flag == FTW_NS + || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) + { + if (flag == FTW_D) + { + if ((data->flags & FTW_PHYS) + || (!find_object (data, &st) + /* Remember the object. */ + && (result = add_object (data, &st)) == 0)) + result = ftw_dir (data, &st, dir); + } + else + result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], + &data->ftw); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE) + result = 0; + + return result; +} + + +static int +__attribute ((noinline)) +internal_function +ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir) +{ + struct dir_data dir; + struct dirent64 *d; + int previous_base = data->ftw.base; + int result; + char *startp; + + /* Open the stream for this directory. This might require that + another stream has to be closed. */ + result = open_dir_stream (data, &dir); + if (result != 0) + { + if (errno == EACCES) + /* We cannot read the directory. Signal this with a special flag. */ + result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); + + return result; + } + + /* First, report the directory (if not depth-first). */ + if (!(data->flags & FTW_DEPTH)) + { + result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); + if (result != 0) + { + int save_err; +fail: + save_err = errno; + __closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + return result; + } + } + + /* If necessary, change to this directory. */ + if (data->flags & FTW_CHDIR) + { + if (__fchdir (dirfd (dir.stream)) < 0) + { + result = -1; + goto fail; + } + } + + /* Next, update the `struct FTW' information. */ + ++data->ftw.level; + startp = strchr (data->dirbuf, '\0'); + /* There always must be a directory name. */ + assert (startp != data->dirbuf); + if (startp[-1] != '/') + *startp++ = '/'; + data->ftw.base = startp - data->dirbuf; + + while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL) + { + result = process_entry (data, &dir, d->d_name, NAMLEN (d)); + if (result != 0) + break; + } + + if (dir.stream != NULL) + { + /* The stream is still open. I.e., we did not need more + descriptors. Simply close the stream now. */ + int save_err = errno; + + assert (dir.content == NULL); + + __closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + } + else + { + int save_err; + char *runp = dir.content; + + while (result == 0 && *runp != '\0') + { + char *endp = strchr (runp, '\0'); + + result = process_entry (data, &dir, runp, endp - runp); + + runp = endp + 1; + } + + save_err = errno; + free (dir.content); + __set_errno (save_err); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS) + result = 0; + + /* Prepare the return, revert the `struct FTW' information. */ + data->dirbuf[data->ftw.base - 1] = '\0'; + --data->ftw.level; + data->ftw.base = previous_base; + + /* Finally, if we process depth-first report the directory. */ + if (result == 0 && (data->flags & FTW_DEPTH)) + result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + + if (old_dir + && (data->flags & FTW_CHDIR) + && (result == 0 + || ((data->flags & FTW_ACTIONRETVAL) + && (result != -1 && result != FTW_STOP)))) + { + /* Change back to the parent directory. */ + int done = 0; + if (old_dir->stream != NULL) + if (__fchdir (dirfd (old_dir->stream)) == 0) + done = 1; + + if (!done) + { + if (data->ftw.base == 1) + { + if (__chdir ("/") < 0) + result = -1; + } + else + if (__chdir ("..") < 0) + result = -1; + } + } + + return result; +} + + +static int +__attribute ((noinline)) +internal_function +ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + int flags) +{ + struct ftw_data data; + struct STAT st; + int result = 0; + int save_err; + char *cwd = NULL; + char *cp; + + /* First make sure the parameters are reasonable. */ + if (dir[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + data.dirstreams = (struct dir_data **) alloca (data.maxdir + * sizeof (struct dir_data *)); + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + + /* PATH_MAX is always defined when we get here. */ + data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); + data.dirbuf = (char *) malloc (data.dirbufsize); + if (data.dirbuf == NULL) + return -1; + cp = __stpcpy (data.dirbuf, dir); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') + --cp; + *cp = '\0'; + + data.ftw.level = 0; + + /* Find basename. */ + while (cp > data.dirbuf && cp[-1] != '/') + --cp; + data.ftw.base = cp - data.dirbuf; + + data.flags = flags; + + /* This assignment might seem to be strange but it is what we want. + The trick is that the first three arguments to the `ftw' and + `nftw' callback functions are equal. Therefore we can call in + every case the callback using the format of the `nftw' version + and get the correct result since the stack layout for a function + call in C allows this. */ + data.func = (NFTW_FUNC_T) func; + + /* Since we internally use the complete set of FTW_* values we need + to reduce the value range before calling a `ftw' callback. */ + data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; + + /* No object known so far. */ + data.known_objects = NULL; + + /* Now go to the directory containing the initial file/directory. */ + if (flags & FTW_CHDIR) + { + /* GNU extension ahead. */ + cwd = __getcwd (NULL, 0); + if (cwd == NULL) + result = -1; + else if (data.ftw.base > 0) + { + /* Change to the directory the file is in. In data.dirbuf + we have a writable copy of the file name. Just NUL + terminate it for now and change the directory. */ + if (data.ftw.base == 1) + /* I.e., the file is in the root directory. */ + result = __chdir ("/"); + else + { + char ch = data.dirbuf[data.ftw.base - 1]; + data.dirbuf[data.ftw.base - 1] = '\0'; + result = __chdir (data.dirbuf); + data.dirbuf[data.ftw.base - 1] = ch; + } + } + } + + /* Get stat info for start directory. */ + if (result == 0) + { + const char *name = ((data.flags & FTW_CHDIR) + ? data.dirbuf + data.ftw.base + : data.dirbuf); + + if (((flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) + { + if (!(flags & FTW_PHYS) + && errno == ENOENT + && LXSTAT (_STAT_VER, name, &st) == 0 + && S_ISLNK (st.st_mode)) + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], + &data.ftw); + else + /* No need to call the callback since we cannot say anything + about the object. */ + result = -1; + } + else + { + if (S_ISDIR (st.st_mode)) + { + /* Remember the device of the initial directory in case + FTW_MOUNT is given. */ + data.dev = st.st_dev; + + /* We know this directory now. */ + if (!(flags & FTW_PHYS)) + result = add_object (&data, &st); + + if (result == 0) + result = ftw_dir (&data, &st, NULL); + } + else + { + int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; + + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], + &data.ftw); + } + } + + if ((flags & FTW_ACTIONRETVAL) + && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS)) + result = 0; + } + + /* Return to the start directory (if necessary). */ + if (cwd != NULL) + { + save_err = errno; + __chdir (cwd); + free (cwd); + __set_errno (save_err); + } + + /* Free all memory. */ + save_err = errno; + __tdestroy (data.known_objects, free); + free (data.dirbuf); + __set_errno (save_err); + + return result; +} + + + +/* Entry points. */ + +int +FTW_NAME (const char *path, FTW_FUNC_T func, int descriptors) +{ + return ftw_startup (path, 0, func, descriptors, 0); +} + +#ifndef _LIBC +int +NFTW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + return ftw_startup (path, 1, func, descriptors, flags); +} +#else + +#include + +int NFTW_NEW_NAME (const char *, NFTW_FUNC_T, int, int); + +int +NFTW_NEW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + if (flags + & ~(FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH | FTW_ACTIONRETVAL)) + { + __set_errno (EINVAL); + return -1; + } + return ftw_startup (path, 1, func, descriptors, flags); +} + +versioned_symbol (libc, NFTW_NEW_NAME, NFTW_NAME, GLIBC_2_3_3); + +#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3) + +/* Older nftw* version just ignored all unknown flags. */ + +int NFTW_OLD_NAME (const char *, NFTW_FUNC_T, int, int); + +int +attribute_compat_text_section +NFTW_OLD_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + flags &= (FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH); + return ftw_startup (path, 1, func, descriptors, flags); +} + +compat_symbol (libc, NFTW_OLD_NAME, NFTW_NAME, GLIBC_2_1); +#endif +#endif diff --git a/libc/misc/ftw/ftw64.c b/libc/misc/ftw/ftw64.c new file mode 100644 index 0000000..de2fe22 --- /dev/null +++ b/libc/misc/ftw/ftw64.c @@ -0,0 +1,32 @@ +/* File tree walker functions. LFS version. + Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FTW_NAME ftw64 +#define NFTW_NAME nftw64 +#define NFTW_OLD_NAME __old_nftw64 +#define NFTW_NEW_NAME __new_nftw64 +#define INO_T ino64_t +#define STAT stat64 +#define LXSTAT(V,f,sb) lstat64(f,sb) +#define XSTAT(V,f,sb) stat64(f,sb) +#define FTW_FUNC_T __ftw64_func_t +#define NFTW_FUNC_T __nftw64_func_t + +#include "ftw.c" diff --git a/libc/misc/glob/.indent.pro b/libc/misc/glob/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/glob/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/glob/Makefile b/libc/misc/glob/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/glob/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/glob/Makefile.in b/libc/misc/glob/Makefile.in new file mode 100644 index 0000000..b7a2afc --- /dev/null +++ b/libc/misc/glob/Makefile.in @@ -0,0 +1,31 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifeq ($(UCLIBC_HAS_GNU_GLOB),y) +CSRC := glob.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += glob64.c +endif +else +CSRC := glob-susv3.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += glob64-susv3.c +endif +endif + +MISC_GLOB_DIR := $(top_srcdir)libc/misc/glob +MISC_GLOB_OUT := $(top_builddir)libc/misc/glob + +MISC_GLOB_SRC := $(patsubst %.c,$(MISC_GLOB_DIR)/%.c,$(CSRC)) +MISC_GLOB_OBJ := $(patsubst %.c,$(MISC_GLOB_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_GLOB) += $(MISC_GLOB_OBJ) + +objclean-y += misc_glob_clean + +misc_glob_clean: + $(do_rm) $(addprefix $(MISC_GLOB_OUT)/*., o os) diff --git a/libc/misc/glob/glob-susv3.c b/libc/misc/glob/glob-susv3.c new file mode 100644 index 0000000..00963c3 --- /dev/null +++ b/libc/misc/glob/glob-susv3.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_LFS__ +# define BUILD_GLOB64 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(opendir) +libc_hidden_proto(closedir) +libc_hidden_proto(qsort) +libc_hidden_proto(fnmatch) + +struct match +{ + struct match *next; + char name[1]; +}; + +#ifdef BUILD_GLOB64 +extern int __glob_is_literal(const char *p, int useesc) attribute_hidden; +extern int __glob_append(struct match **tail, const char *name, size_t len, int mark) attribute_hidden; +extern int __glob_ignore_err(const char *path, int err) attribute_hidden; +extern void __glob_freelist(struct match *head) attribute_hidden; +extern int __glob_sort(const void *a, const void *b) attribute_hidden; +extern int __glob_match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_LFS__ +# define stat stat64 +# define readdir_r readdir64_r +# define dirent dirent64 +libc_hidden_proto(readdir64_r) +libc_hidden_proto(stat64) +# define struct_stat struct stat64 +#else +libc_hidden_proto(readdir_r) +libc_hidden_proto(stat) +# define struct_stat struct stat +#endif + +/* keep only one copy of these */ +#ifndef __GLOB64 + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_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; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_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; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_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 = __glob_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 (__glob_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 = __glob_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 = __glob_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 (__glob_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; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_ignore_err(const char *path, int err) +{ + return 0; +} + +# ifndef BUILD_GLOB64 +static +# endif +void __glob_freelist(struct match *head) +{ + struct match *match, *next; + for (match=head->next; match; match=next) { + next = match->next; + free(match); + } +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_sort(const void *a, const void *b) +{ + return strcmp(*(const char **)a, *(const char **)b); +} +#endif /* !__GLOB64 */ + +#ifdef __GLOB64 +libc_hidden_proto(glob64) +#else +libc_hidden_proto(glob) +#endif +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 = __glob_ignore_err; + + if (!(flags & GLOB_APPEND)) { + g->gl_offs = offs; + g->gl_pathc = 0; + g->gl_pathv = NULL; + } + + if (*p) error = __glob_match_in_dir(d, p, flags, errfunc, &tail); + if (error == GLOB_NOSPACE) { + __glob_freelist(&head); + return error; + } + + for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++); + if (!cnt) { + if (flags & GLOB_NOCHECK) { + tail = &head; + if (__glob_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) { + __glob_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) { + __glob_freelist(&head); + return GLOB_NOSPACE; + } + for (i=0; igl_pathv[i] = NULL; + } + for (i=0, tail=head.next; inext, 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 *), __glob_sort); + + return error; +} +#ifdef __GLOB64 +libc_hidden_def(glob64) +#else +libc_hidden_def(glob) +#endif + +#ifdef __GLOB64 +libc_hidden_proto(globfree64) +#else +libc_hidden_proto(globfree) +#endif +void globfree(glob_t *g) +{ + size_t i; + for (i=0; igl_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; +} +#ifdef __GLOB64 +libc_hidden_def(globfree64) +#else +libc_hidden_def(globfree) +#endif diff --git a/libc/misc/glob/glob.c b/libc/misc/glob/glob.c new file mode 100644 index 0000000..6ccbda4 --- /dev/null +++ b/libc/misc/glob/glob.c @@ -0,0 +1,1093 @@ +/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#undef ENABLE_GLOB_BRACE_EXPANSION +#undef ENABLE_GLOB_TILDE_EXPANSION + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(closedir) +libc_hidden_proto(fnmatch) +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(mempcpy) */ +libc_hidden_proto(opendir) +libc_hidden_proto(qsort) +libc_hidden_proto(readdir) +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcoll) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strrchr) */ + + +#ifdef ENABLE_GLOB_TILDE_EXPANSION +#include +libc_hidden_proto(getpwnam_r) +#endif + +#ifdef COMPILE_GLOB64 +#undef stat +#define stat stat64 +#define struct_stat64 struct stat64 +#define __stat64(fname, buf) stat64 (fname, buf) +#define dirent dirent64 +#define __readdir readdir64 +#define __readdir64 readdir64 +#define glob_t glob64_t +#define glob(pattern, flags, errfunc, pglob) glob64 (pattern, flags, errfunc, pglob) +#define globfree(pglob) globfree64 (pglob) +libc_hidden_proto(stat64) +libc_hidden_proto(readdir64) +#else +#define __readdir readdir +#ifdef __UCLIBC_HAS_LFS__ +#define __readdir64 readdir64 +libc_hidden_proto(readdir64) +#else +#define __readdir64 readdir +#endif +#define struct_stat64 struct stat +#define __stat64(fname, buf) stat (fname, buf) +libc_hidden_proto(stat) +#endif + + +/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available + if the `d_type' member for `struct dirent' is available. + HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ +#if defined _DIRENT_HAVE_D_TYPE +/* True if the directory entry D must be of type T. */ +# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) + +/* True if the directory entry D might be a symbolic link. */ +# define DIRENT_MIGHT_BE_SYMLINK(d) \ + ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) + +/* True if the directory entry D might be a directory. */ +# define DIRENT_MIGHT_BE_DIR(d) \ + ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) + +#else /* !HAVE_D_TYPE */ +# define DIRENT_MUST_BE(d, t) false +# define DIRENT_MIGHT_BE_SYMLINK(d) true +# define DIRENT_MIGHT_BE_DIR(d) true +#endif /* HAVE_D_TYPE */ + + +# define NAMLEN(dirent) strlen((dirent)->d_name) +#ifdef _D_NAMLEN +# undef NAMLEN +# define NAMLEN(d) _D_NAMLEN(d) +#endif + +# if defined _DIRENT_HAVE_D_NAMLEN +# define CONVERT_D_NAMLEN(d64, d32) (d64)->d_namlen = (d32)->d_namlen; +# else +# define CONVERT_D_NAMLEN(d64, d32) +# endif + +# define CONVERT_D_INO(d64, d32) (d64)->d_ino = (d32)->d_ino; + +# ifdef _DIRENT_HAVE_D_TYPE +# define CONVERT_D_TYPE(d64, d32) (d64)->d_type = (d32)->d_type; +# else +# define CONVERT_D_TYPE(d64, d32) +# endif + +# define CONVERT_DIRENT_DIRENT64(d64, d32) \ + memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ + CONVERT_D_NAMLEN (d64, d32) \ + CONVERT_D_INO (d64, d32) \ + CONVERT_D_TYPE (d64, d32) + +extern int __collated_compare (const void *a, const void *b) attribute_hidden; +extern int __prefix_array (const char *dirname, char **array, size_t n) attribute_hidden; +#if defined ENABLE_GLOB_BRACE_EXPANSION +extern const char *__next_brace_sub (const char *cp, int flags) attribute_hidden; +#endif + +libc_hidden_proto(glob_pattern_p) +#ifndef COMPILE_GLOB64 +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ +int glob_pattern_p(const char *pattern, int quote) +{ + register const char *p; + int open = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) + { + case '?': + case '*': + return 1; + + case '\\': + if (quote && p[1] != '\0') + ++p; + break; + + case '[': + open = 1; + break; + + case ']': + if (open) + return 1; + break; + } + + return 0; +} +libc_hidden_def(glob_pattern_p) + + +/* Do a collated comparison of A and B. */ +int __collated_compare (const void *a, const void *b) +{ + const char *const s1 = *(const char *const * const) a; + const char *const s2 = *(const char *const * const) b; + + if (s1 == s2) + return 0; + if (s1 == NULL) + return 1; + if (s2 == NULL) + return -1; + return strcoll (s1, s2); +} + + +/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's + elements in place. Return nonzero if out of memory, zero if successful. + A slash is inserted between DIRNAME and each elt of ARRAY, + unless DIRNAME is just "/". Each old element of ARRAY is freed. + If ADD_SLASH is non-zero, allocate one character more than + necessary, so that a slash can be appended later. */ +int __prefix_array (const char *dirname, char **array, size_t n) +{ + register size_t i; + size_t dirlen = strlen (dirname); +# define DIRSEP_CHAR '/' + + if (dirlen == 1 && dirname[0] == '/') + /* DIRNAME is just "/", so normal prepending would get us "//foo". + We want "/foo" instead, so don't prepend any chars from DIRNAME. */ + dirlen = 0; + + for (i = 0; i < n; ++i) + { + size_t eltlen = strlen (array[i]) + 1; + char *new = (char *) malloc (dirlen + 1 + eltlen); + if (new == NULL) + { + while (i > 0) + free (array[--i]); + return 1; + } + + { + char *endp = mempcpy (new, dirname, dirlen); + *endp++ = DIRSEP_CHAR; + mempcpy (endp, array[i], eltlen); + } + free (array[i]); + array[i] = new; + } + + return 0; +} + +#if defined ENABLE_GLOB_BRACE_EXPANSION +/* Find the end of the sub-pattern in a brace expression. */ +const char * +__next_brace_sub (const char *cp, int flags) +{ + unsigned int depth = 0; + while (*cp != '\0') + if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\') + { + if (*++cp == '\0') + break; + ++cp; + } + else + { + if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) + break; + + if (*cp++ == '{') + depth++; + } + + return *cp != '\0' ? cp : NULL; +} +#endif +#endif + + +static int +link_exists_p (const char *dir, size_t dirlen, const char *fname, + glob_t *pglob, int flags) +{ + size_t fnamelen = strlen (fname); + char *fullname = (char *) alloca (dirlen + 1 + fnamelen + 1); + struct stat st; + struct_stat64 st64; + + mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), + fname, fnamelen + 1); + + return (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0); +} + +/* Like `glob', but PATTERN is a final pathname component, + and matches are searched for in DIRECTORY. + The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. + The GLOB_APPEND flag is assumed to be set (always appends). */ +static int glob_in_dir (const char *pattern, const char *directory, int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) +{ + size_t dirlen = strlen (directory); + void *stream = NULL; + struct globlink + { + struct globlink *next; + char *name; + }; + struct globlink *names = NULL; + size_t nfound; + int meta; + int save; + + meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); + if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + { + /* We need not do any tests. The PATTERN contains no meta + characters and we must not return an error therefore the + result will always contain exactly one name. */ + flags |= GLOB_NOCHECK; + nfound = 0; + } + else if (meta == 0 && + ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL)) + { + /* Since we use the normal file functions we can also use stat() + to verify the file is there. */ + struct stat st; + struct_stat64 st64; + size_t patlen = strlen (pattern); + char *fullname = (char *) alloca (dirlen + 1 + patlen + 1); + + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + pattern, patlen + 1); + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0) + /* We found this file to be existing. Now tell the rest + of the function to copy this name into the result. */ + flags |= GLOB_NOCHECK; + + nfound = 0; + } + else + { + if (pattern[0] == '\0') + { + /* This is a special case for matching directories like in + "*a/". */ + names = (struct globlink *) alloca (sizeof (struct globlink)); + names->name = (char *) malloc (1); + if (names->name == NULL) + goto memory_error; + names->name[0] = '\0'; + names->next = NULL; + nfound = 1; + meta = 0; + } + else + { + stream = ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_opendir) (directory) + : opendir (directory)); + if (stream == NULL) + { + if (errno != ENOTDIR + && ((errfunc != NULL && (*errfunc) (directory, errno)) + || (flags & GLOB_ERR))) + return GLOB_ABORTED; + nfound = 0; + meta = 0; + } + else + { + int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) + | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) + ); + nfound = 0; + flags |= GLOB_MAGCHAR; + + while (1) + { + const char *name; + size_t len; +#if defined __UCLIBC_HAS_LFS__ && !defined COMPILE_GLOB64 + struct dirent64 *d; + union + { + struct dirent64 d64; + char room [offsetof (struct dirent64, d_name[0]) + + NAME_MAX + 1]; + } + d64buf; + + if (flags & GLOB_ALTDIRFUNC) + { + struct dirent *d32 = (*pglob->gl_readdir) (stream); + if (d32 != NULL) + { + CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); + d = &d64buf.d64; + } + else + d = NULL; + } + else + d = __readdir64 (stream); +#else + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) + ? ((struct dirent *) + (*pglob->gl_readdir) (stream)) + : __readdir (stream)); +#endif + if (d == NULL) + break; +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) + if (! REAL_DIR_ENTRY (d)) + continue; + + /* If we shall match only directories use the information + provided by the dirent call if possible. */ + if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) + continue; + + name = d->d_name; + + if (fnmatch (pattern, name, fnm_flags) == 0) + { + /* If the file we found is a symlink we have to + make sure the target file exists. */ + if (!DIRENT_MIGHT_BE_SYMLINK (d) + || link_exists_p (directory, dirlen, name, pglob, + flags)) + { + struct globlink *new = (struct globlink *) + alloca (sizeof (struct globlink)); + len = NAMLEN (d); + new->name = (char *) malloc (len + 1); + if (new->name == NULL) + goto memory_error; + *((char *) mempcpy (new->name, name, len)) = '\0'; + new->next = names; + names = new; + ++nfound; + } + } + } + } + } + } + + if (nfound == 0 && (flags & GLOB_NOCHECK)) + { + size_t len = strlen (pattern); + nfound = 1; + names = (struct globlink *) alloca (sizeof (struct globlink)); + names->next = NULL; + names->name = (char *) malloc (len + 1); + if (names->name == NULL) + goto memory_error; + *((char *) mempcpy (names->name, pattern, len)) = '\0'; + } + + if (nfound != 0) + { + char **new_gl_pathv; + + new_gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + pglob->gl_offs + nfound + 1) + * sizeof (char *)); + if (new_gl_pathv == NULL) + goto memory_error; + pglob->gl_pathv = new_gl_pathv; + + for (; names != NULL; names = names->next) + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + pglob->gl_flags = flags; + } + + save = errno; + if (stream != NULL) + { + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + } + __set_errno (save); + + return nfound == 0 ? GLOB_NOMATCH : 0; + + memory_error: + { + int save2 = errno; + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + __set_errno (save2); + } + while (names != NULL) + { + free (names->name); + names = names->next; + } + return GLOB_NOSPACE; +} + +#ifdef COMPILE_GLOB64 +libc_hidden_proto(glob64) +libc_hidden_proto(globfree64) +#else +libc_hidden_proto(glob) +libc_hidden_proto(globfree) +#endif +/* Do glob searching for PATTERN, placing results in PGLOB. + The bits defined above may be set in FLAGS. + If a directory cannot be opened or read and ERRFUNC is not nil, + it is called with the pathname that caused the error, and the + `errno' value from the failing call; if it returns non-zero + `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +int +glob ( + const char *pattern, + int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) +{ + const char *filename; + const char *dirname; + size_t dirlen; + int status; + size_t oldcount; + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) + { + __set_errno (EINVAL); + return -1; + } + + + if (!(flags & GLOB_DOOFFS)) + /* Have to do this so `globfree' knows where to start freeing. It + also makes all the code that uses gl_offs simpler. */ + pglob->gl_offs = 0; + +#if defined ENABLE_GLOB_BRACE_EXPANSION + if (flags & GLOB_BRACE) + { + const char *begin; + + if (flags & GLOB_NOESCAPE) + begin = strchr (pattern, '{'); + else + { + begin = pattern; + while (1) + { + if (*begin == '\0') + { + begin = NULL; + break; + } + + if (*begin == '\\' && begin[1] != '\0') + ++begin; + else if (*begin == '{') + break; + + ++begin; + } + } + + if (begin != NULL) + { + /* Allocate working buffer large enough for our work. Note that + we have at least an opening and closing brace. */ + size_t firstc; + char *alt_start; + const char *p; + const char *next; + const char *rest; + size_t rest_len; + char onealt[strlen (pattern) - 1]; + + /* We know the prefix for all sub-patterns. */ + alt_start = mempcpy (onealt, pattern, begin - pattern); + + /* Find the first sub-pattern and at the same time find the + rest after the closing brace. */ + next = __next_brace_sub (begin + 1, flags); + if (next == NULL) + { + /* It is an illegal expression. */ + return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + } + + /* Now find the end of the whole brace expression. */ + rest = next; + while (*rest != '}') + { + rest = __next_brace_sub (rest + 1, flags); + if (rest == NULL) + { + /* It is an illegal expression. */ + return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + } + } + /* Please note that we now can be sure the brace expression + is well-formed. */ + rest_len = strlen (++rest) + 1; + + /* We have a brace expression. BEGIN points to the opening {, + NEXT points past the terminator of the first element, and END + points past the final }. We will accumulate result names from + recursive runs for each brace alternative in the buffer using + GLOB_APPEND. */ + + if (!(flags & GLOB_APPEND)) + { + /* This call is to set a new vector, so clear out the + vector so we can append to it. */ + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + firstc = pglob->gl_pathc; + + p = begin + 1; + while (1) + { + int result; + + /* Construct the new glob expression. */ + mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); + + result = glob (onealt, + ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) + | GLOB_APPEND), errfunc, pglob); + + /* If we got an error, return it. */ + if (result && result != GLOB_NOMATCH) + { + if (!(flags & GLOB_APPEND)) + { + globfree (pglob); + pglob->gl_pathc = 0; + } + return result; + } + + if (*next == '}') + /* We saw the last entry. */ + break; + + p = next + 1; + next = __next_brace_sub (p, flags); + /* assert (next != NULL); */ + } + + + if (pglob->gl_pathc != firstc) + /* We found some entries. */ + return 0; + else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + return GLOB_NOMATCH; + } + } +#endif + + /* Find the filename. */ + filename = strrchr (pattern, '/'); + if (filename == NULL) + { + /* This can mean two things: a simple name or "~name". The latter + case is nothing but a notation for a directory. */ + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') + { + dirname = pattern; + dirlen = strlen (pattern); + + /* Set FILENAME to NULL as a special flag. This is ugly but + other solutions would require much more code. We test for + this special case below. */ + filename = NULL; + } + else + { + filename = pattern; + dirname = "."; + dirlen = 0; + } + } + else if (filename == pattern) + { + /* "/pattern". */ + dirname = "/"; + dirlen = 1; + ++filename; + } + else + { + char *newp; + dirlen = filename - pattern; + newp = (char *) alloca (dirlen + 1); + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; + dirname = newp; + ++filename; + + if (filename[0] == '\0' + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); + return val; + } + } + + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_pathv = NULL; + else + { + size_t i; + pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) + * sizeof (char *)); + if (pglob->gl_pathv == NULL) + return GLOB_NOSPACE; + + for (i = 0; i <= pglob->gl_offs; ++i) + pglob->gl_pathv[i] = NULL; + } + } + + oldcount = pglob->gl_pathc + pglob->gl_offs; + +#if defined ENABLE_GLOB_TILDE_EXPANSION + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + { + if (dirname[1] == '\0' || dirname[1] == '/') + { + /* Look up home directory. */ + const char *home_dir = getenv ("HOME"); + if (home_dir == NULL || home_dir[0] == '\0') + { + int success; + char *name; +# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX) + size_t buflen = GET_LOGIN_NAME_MAX () + 1; + + if (buflen == 0) + /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try + a moderate value. */ + buflen = 20; + name = (char *) alloca (buflen); + + success = getlogin_r (name, buflen) == 0; + if (success) + { + struct passwd *p; +# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) + long int pwbuflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + + pwtmpbuf = (char *) alloca (pwbuflen); + + while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) + != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, + 2 * pwbuflen); + __set_errno (save); + } + if (p != NULL) + home_dir = p->pw_dir; + } + } + if (home_dir == NULL || home_dir[0] == '\0') + { + if (flags & GLOB_TILDE_CHECK) + return GLOB_NOMATCH; + else + home_dir = "~"; /* No luck. */ + } + /* Now construct the full directory. */ + if (dirname[1] == '\0') + dirname = home_dir; + else + { + char *newp; + size_t home_len = strlen (home_dir); + newp = (char *) alloca (home_len + dirlen); + mempcpy (mempcpy (newp, home_dir, home_len), + &dirname[1], dirlen); + dirname = newp; + } + } + else + { + char *end_name = strchr (dirname, '/'); + const char *user_name; + const char *home_dir; + + if (end_name == NULL) + user_name = dirname + 1; + else + { + char *newp; + newp = (char *) alloca (end_name - dirname); + *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) + = '\0'; + user_name = newp; + } + + /* Look up specific user's home directory. */ + { + struct passwd *p; + long int buflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + + pwtmpbuf = (char *) alloca (buflen); + + while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); + __set_errno (save); + } + if (p != NULL) + home_dir = p->pw_dir; + else + home_dir = NULL; + } + /* If we found a home directory use this. */ + if (home_dir != NULL) + { + char *newp; + size_t home_len = strlen (home_dir); + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); + newp = (char *) alloca (home_len + rest_len + 1); + *((char *) mempcpy (mempcpy (newp, home_dir, home_len), + end_name, rest_len)) = '\0'; + dirname = newp; + } + else + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the + home directory. */ + return GLOB_NOMATCH; + } + } + + /* Now test whether we looked for "~" or "~NAME". In this case we + can give the answer now. */ + if (filename == NULL) + { + struct stat st; + struct_stat64 st64; + + /* Return the directory if we don't check for error or if it exists. */ + if ((flags & GLOB_NOCHECK) + || (((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_stat) (dirname, &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode))))) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv + = (char **) realloc (pglob->gl_pathv, + (newcount + 1 + 1) * sizeof (char *)); + if (new_gl_pathv == NULL) + { + nospace: + free (pglob->gl_pathv); + pglob->gl_pathv = NULL; + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + pglob->gl_pathv = new_gl_pathv; + + pglob->gl_pathv[newcount] = strdup (dirname); + if (pglob->gl_pathv[newcount] == NULL) + goto nospace; + pglob->gl_pathv[++newcount] = NULL; + ++pglob->gl_pathc; + pglob->gl_flags = flags; + + return 0; + } + + /* Not found. */ + return GLOB_NOMATCH; + } +#endif + + if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) + { + /* The directory name contains metacharacters, so we + have to glob for the directory, and then glob for + the pattern in each directory found. */ + glob_t dirs; + size_t i; + + if ((flags & GLOB_ALTDIRFUNC) != 0) + { + /* Use the alternative access functions also in the recursive + call. */ + dirs.gl_opendir = pglob->gl_opendir; + dirs.gl_readdir = pglob->gl_readdir; + dirs.gl_closedir = pglob->gl_closedir; + dirs.gl_stat = pglob->gl_stat; + dirs.gl_lstat = pglob->gl_lstat; + } + + status = glob (dirname, + ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE + | GLOB_ALTDIRFUNC)) + | GLOB_NOSORT | GLOB_ONLYDIR), + errfunc, &dirs); + if (status != 0) + return status; + + /* We have successfully globbed the preceding directory name. + For each name we found, call glob_in_dir on it and FILENAME, + appending the results to PGLOB. */ + for (i = 0; i < dirs.gl_pathc; ++i) + { + int old_pathc; + + old_pathc = pglob->gl_pathc; + status = glob_in_dir (filename, dirs.gl_pathv[i], + ((flags | GLOB_APPEND) + & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), + errfunc, pglob); + if (status == GLOB_NOMATCH) + /* No matches in this directory. Try the next. */ + continue; + + if (status != 0) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return status; + } + + /* Stick the directory on the front of each name. */ + if (__prefix_array (dirs.gl_pathv[i], + &pglob->gl_pathv[old_pathc + pglob->gl_offs], + pglob->gl_pathc - old_pathc)) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + } + + flags |= GLOB_MAGCHAR; + + /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. + But if we have not found any matching entry and the GLOB_NOCHECK + flag was set we must return the input pattern itself. */ + if (pglob->gl_pathc + pglob->gl_offs == oldcount) + { + /* No matches. */ + if (flags & GLOB_NOCHECK) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv = (char **) realloc (pglob->gl_pathv, + (newcount + 2) + * sizeof (char *)); + if (new_gl_pathv == NULL) + { + globfree (&dirs); + return GLOB_NOSPACE; + } + pglob->gl_pathv = new_gl_pathv; + + pglob->gl_pathv[newcount] = strdup (pattern); + if (pglob->gl_pathv[newcount] == NULL) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + + ++pglob->gl_pathc; + ++newcount; + + pglob->gl_pathv[newcount] = NULL; + pglob->gl_flags = flags; + } + else + { + globfree (&dirs); + return GLOB_NOMATCH; + } + } + + globfree (&dirs); + } + else + { + int old_pathc = pglob->gl_pathc; + + status = glob_in_dir (filename, dirname, flags, errfunc, pglob); + if (status != 0) + return status; + + if (dirlen > 0) + { + /* Stick the directory on the front of each name. */ + if (__prefix_array (dirname, + &pglob->gl_pathv[old_pathc + pglob->gl_offs], + pglob->gl_pathc - old_pathc)) + { + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + } + } + + if (flags & GLOB_MARK) + { + /* Append slashes to directory names. */ + size_t i; + struct stat st; + struct_stat64 st64; + + for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i) + if (((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (pglob->gl_pathv[i], &st64) == 0 + && S_ISDIR (st64.st_mode)))) + { + size_t len = strlen (pglob->gl_pathv[i]) + 2; + char *new = realloc (pglob->gl_pathv[i], len); + if (new == NULL) + { + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + strcpy (&new[len - 2], "/"); + pglob->gl_pathv[i] = new; + } + } + + if (!(flags & GLOB_NOSORT)) + { + /* Sort the vector. */ + qsort (&pglob->gl_pathv[oldcount], + pglob->gl_pathc + pglob->gl_offs - oldcount, + sizeof (char *), __collated_compare); + } + + return 0; +} +#ifdef COMPILE_GLOB64 +libc_hidden_def(glob64) +#else +libc_hidden_def(glob) +#endif + + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +globfree (register glob_t *pglob) +{ + if (pglob->gl_pathv != NULL) + { + size_t i; + for (i = 0; i < pglob->gl_pathc; ++i) + if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) + free (pglob->gl_pathv[pglob->gl_offs + i]); + free (pglob->gl_pathv); + pglob->gl_pathv = NULL; + } +} +#ifdef COMPILE_GLOB64 +libc_hidden_def(globfree64) +#else +libc_hidden_def(globfree) +#endif diff --git a/libc/misc/glob/glob64-susv3.c b/libc/misc/glob/glob64-susv3.c new file mode 100644 index 0000000..f73e2c3 --- /dev/null +++ b/libc/misc/glob/glob64-susv3.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include + +#define glob_t glob64_t +#define glob(pattern, flags, errfunc, pglob) \ + glob64 (pattern, flags, errfunc, pglob) +#define globfree(pglob) globfree64 (pglob) + +#define __GLOB64 1 + +#include "glob-susv3.c" diff --git a/libc/misc/glob/glob64.c b/libc/misc/glob/glob64.c new file mode 100644 index 0000000..b84af92 --- /dev/null +++ b/libc/misc/glob/glob64.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include + +#define COMPILE_GLOB64 1 + +#include "glob.c" diff --git a/libc/misc/gnu/Makefile b/libc/misc/gnu/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/gnu/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/gnu/Makefile.in b/libc/misc/gnu/Makefile.in new file mode 100644 index 0000000..c3a98e8 --- /dev/null +++ b/libc/misc/gnu/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := obstack.c + +MISC_GNU_DIR := $(top_srcdir)libc/misc/gnu +MISC_GNU_OUT := $(top_builddir)libc/misc/gnu + +MISC_GNU_SRC := $(MISC_GNU_DIR)/obstack.c +MISC_GNU_OBJ := $(MISC_GNU_OUT)/obstack.o + +libc-y += $(MISC_GNU_OBJ) + +objclean-y += misc_gnu_clean + +misc_gnu_clean: + $(do_rm) $(addprefix $(MISC_GNU_OUT)/*., o os) diff --git a/libc/misc/gnu/obstack.c b/libc/misc/gnu/obstack.c new file mode 100644 index 0000000..2391463 --- /dev/null +++ b/libc/misc/gnu/obstack.c @@ -0,0 +1,456 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef _LIBC +# include +#ifndef __UCLIBC__ +# include +#else +# define HAVE_INTTYPES_H 1 +# define HAVE_STDINT_H 1 +# define SHLIB_COMPAT(x,y,z) 0 +# undef libc_hidden_def +# define libc_hidden_def(x) +# undef strong_alias +# define strong_alias(x,y) +#endif +#else +# include "obstack.h" +#endif + +/* NOTE BEFORE MODIFYING THIS FILE: This version number must be + incremented whenever callers compiled using an old obstack.h can no + longer properly call the functions in this obstack.c. */ +#define OBSTACK_INTERFACE_VERSION 1 + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and the installed library + supports the same library interface we do. This code is part of the GNU + C Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object + files, it is simpler to just do this in the source for each such file. */ + +#include /* Random thing to get __GNU_LIBRARY__. */ +#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +# include +# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#include + +#ifndef ELIDE_CODE + + +# if HAVE_INTTYPES_H +# include +# endif +# if HAVE_STDINT_H || defined _LIBC +# include +# endif + +/* Determine default alignment. */ +union fooround +{ + uintmax_t i; + long double d; + void *p; +}; +struct fooalign +{ + char c; + union fooround u; +}; +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. */ +enum + { + DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), + DEFAULT_ROUNDING = sizeof (union fooround) + }; + +/* When we copy a long block of data, this is the unit to do it with. + On some machines, copying successive ints does not work; + in such a case, redefine COPYING_UNIT to `long' (if that works) + or `char' as a last resort. */ +# ifndef COPYING_UNIT +# define COPYING_UNIT int +# endif + + +/* The functions allocating more room by calling `obstack_chunk_alloc' + jump to the handler pointed to by `obstack_alloc_failed_handler'. + This can be set to a user defined function which should either + abort gracefully or use longjump - but shouldn't return. This + variable by default points to the internal function + `print_and_abort'. */ +static void print_and_abort (void); +static void (*__obstack_alloc_failed_handler) (void) = print_and_abort; +weak_alias(__obstack_alloc_failed_handler,obstack_alloc_failed_handler) + +/* Exit value used when `print_and_abort' is used. */ +# include +# ifdef _LIBC +static int __obstack_exit_failure = EXIT_FAILURE; +weak_alias(__obstack_exit_failure,obstack_exit_failure) +# else +# include "exitfail.h" +# define __obstack_exit_failure exit_failure +# endif + +# ifdef _LIBC +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +/* A looong time ago (before 1994, anyway; we're not sure) this global variable + was used by non-GNU-C macros to avoid multiple evaluation. The GNU C + library still exports it because somebody might use it. */ +struct obstack *_obstack_compat; +compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); +# endif +# endif + +/* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + +# define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) + +# define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ + } while (0) + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + CHUNKFUN is the function to use to allocate chunks, + and FREEFUN the function to free them. + + Return nonzero if successful, calls obstack_alloc_failed_handler if + allocation fails. */ + +int +_obstack_begin (struct obstack *h, + int size, int alignment, + void *(*chunkfun) (long), + void (*freefun) (void *)) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*__obstack_alloc_failed_handler) (); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +int +_obstack_begin_1 (struct obstack *h, int size, int alignment, + void *(*chunkfun) (void *, long), + void (*freefun) (void *, void *), + void *arg) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*__obstack_alloc_failed_handler) (); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +void +_obstack_newchunk (struct obstack *h, int length) +{ + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; + register long new_size; + register long obj_size = h->next_free - h->object_base; + register long i; + long already; + char *object_base; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) + (*__obstack_alloc_failed_handler) (); + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Compute an aligned object_base in the new chunk */ + object_base = + __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); + + /* Move the existing object to the new chunk. + Word at a time is fast and is safe if the object + is sufficiently aligned. */ + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) + { + for (i = obj_size / sizeof (COPYING_UNIT) - 1; + i >= 0; i--) + ((COPYING_UNIT *)object_base)[i] + = ((COPYING_UNIT *)h->object_base)[i]; + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, + but that can cross a page boundary on a machine + which does not do strict alignment for COPYING_UNITS. */ + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); + } + else + already = 0; + /* Copy remaining bytes one by one. */ + for (i = already; i < obj_size; i++) + object_base[i] = h->object_base[i]; + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (! h->maybe_empty_object + && (h->object_base + == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, + h->alignment_mask))) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = object_base; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} +# ifdef _LIBC +libc_hidden_def (_obstack_newchunk) +# endif + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, void *obj); + +int +_obstack_allocated_p (struct obstack *h, void *obj) +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = (h)->chunk; + /* We use >= rather than > since the object cannot be exactly at + the beginning of the chunk but might be an empty object exactly + at the end of an adjacent chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + lp = plp; + } + return lp != 0; +} + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ + +# undef obstack_free + +void +obstack_free (struct obstack *h, void *obj) +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +# ifdef _LIBC +/* Older versions of libc used a function _obstack_free intended to be + called by non-GCC compilers. */ +strong_alias (obstack_free, _obstack_free) +# endif + +int +_obstack_memory_used (struct obstack *h) +{ + register struct _obstack_chunk* lp; + register int nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +/* Define the error handler. */ +# ifdef _LIBC +# include +# else +# include "gettext.h" +# endif +/* NLS: Disable gettext in obstack for now: */ +# undef _ +# define _(Str) (Str) +# ifndef _ +# define _(msgid) gettext (msgid) +# endif + +# if defined _LIBC && !defined __UCLIBC__ +# include +# endif + +# ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +# define __attribute__(Spec) /* empty */ +# endif +# endif + +static void +attribute_noreturn +print_and_abort (void) +{ + /* Don't change any of these strings. Yes, it would be possible to add + the newline to the string and use fputs or so. But this must not + happen because the "memory exhausted" message appears in other places + like this and the translation should be reused instead of creating + a very similar string which requires a separate translation. */ +# if defined _LIBC && !defined __UCLIBC__ + (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); +# else + fprintf (stderr, "%s\n", _("memory exhausted")); +# endif + exit (__obstack_exit_failure); +} + +#endif /* !ELIDE_CODE */ diff --git a/libc/misc/internals/Makefile b/libc/misc/internals/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/internals/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in new file mode 100644 index 0000000..230e6e7 --- /dev/null +++ b/libc/misc/internals/Makefile.in @@ -0,0 +1,39 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS) + +CSRC := tempname.c errno.c __errno_location.c __h_errno_location.c + +MISC_INTERNALS_DIR := $(top_srcdir)libc/misc/internals +MISC_INTERNALS_OUT := $(top_builddir)libc/misc/internals + +MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC)) +MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_INTERNALS_OBJ) +ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y) +libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.oS +else +libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.os +endif +libc-static-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o +libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.o +libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.o +libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.os \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.os +libc-nomulti-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o + +objclean-y += misc_internals_clean + +misc_internals_clean: + $(do_rm) $(addprefix $(MISC_INTERNALS_OUT)/*., o os oS) diff --git a/libc/misc/internals/__errno_location.c b/libc/misc/internals/__errno_location.c new file mode 100644 index 0000000..a44bf60 --- /dev/null +++ b/libc/misc/internals/__errno_location.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "internal_errno.h" + +/* psm: moved to bits/errno.h: libc_hidden_proto(__errno_location) */ +libc_hidden_proto(__errno_location) +int * weak_const_function __errno_location (void) +{ + return &errno; +} +#ifdef IS_IN_libc /* not really need, only to keep in sync w/ libc_hidden_proto */ +libc_hidden_weak(__errno_location) +#endif diff --git a/libc/misc/internals/__h_errno_location.c b/libc/misc/internals/__h_errno_location.c new file mode 100644 index 0000000..2ac2177 --- /dev/null +++ b/libc/misc/internals/__h_errno_location.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "internal_errno.h" + +libc_hidden_proto(__h_errno_location) +int * weak_const_function __h_errno_location (void) +{ + return &h_errno; +} +libc_hidden_weak(__h_errno_location) diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c new file mode 100644 index 0000000..6c0dab7 --- /dev/null +++ b/libc/misc/internals/__uClibc_main.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) Feb 2001 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * __uClibc_main is the routine to be called by all the arch-specific + * versions of crt1.S in uClibc. + * + * It is meant to handle any special initialization needed by the library + * such as setting the global variable(s) __environ (environ) and + * initializing the stdio package. Using weak symbols, the latter is + * avoided in the static library case. + */ + +#define _ERRNO_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(exit) + +#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ +/* Experimentally off - libc_hidden_proto(strrchr) */ +#endif +#ifndef __ARCH_HAS_NO_LDSO__ +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(getgid) +libc_hidden_proto(getuid) +libc_hidden_proto(getegid) +libc_hidden_proto(geteuid) +libc_hidden_proto(fstat) +libc_hidden_proto(abort) + +extern __typeof(open) __libc_open; +libc_hidden_proto(__libc_open) +extern __typeof(fcntl) __libc_fcntl; +libc_hidden_proto(__libc_fcntl) +#endif + +#ifndef SHARED +void *__libc_stack_end=NULL; + +# ifdef __UCLIBC_HAS_SSP__ +# include +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + * in thread local area. */ +# include +uintptr_t stack_chk_guard; +/* for gcc-4.1 non-TLS */ +uintptr_t __stack_chk_guard attribute_relro; +/* for gcc-3.x + Etoh ssp */ +# ifdef __UCLIBC_HAS_SSP_COMPAT__ +# ifdef __HAVE_SHARED__ +strong_alias(__stack_chk_guard,__guard) +# else +uintptr_t __guard attribute_relro; +# endif +# endif +# elif defined __UCLIBC_HAS_SSP_COMPAT__ +uintptr_t __guard attribute_relro; +# endif +# endif + +#endif /* !SHARED */ + +/* + * Prototypes. + */ +extern void weak_function _stdio_init(void) attribute_hidden; +extern int *weak_const_function __errno_location(void); +extern int *weak_const_function __h_errno_location(void); +#ifdef __UCLIBC_HAS_LOCALE__ +extern void weak_function _locale_init(void) attribute_hidden; +#endif +#ifdef __UCLIBC_HAS_THREADS__ +extern void weak_function __pthread_initialize_minimal(void); +#endif + +/* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation and finalisation + * is handled by the routines passed to __uClibc_main(). */ +#if defined (__UCLIBC_CTOR_DTOR__) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__) +extern void _dl_app_init_array(void); +extern void _dl_app_fini_array(void); +# ifndef SHARED +/* These magic symbols are provided by the linker. */ +extern void (*__preinit_array_start []) (void) attribute_hidden; +extern void (*__preinit_array_end []) (void) attribute_hidden; +extern void (*__init_array_start []) (void) attribute_hidden; +extern void (*__init_array_end []) (void) attribute_hidden; +extern void (*__fini_array_start []) (void) attribute_hidden; +extern void (*__fini_array_end []) (void) attribute_hidden; +# endif +#endif + +attribute_hidden const char *__uclibc_progname = ""; +#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ +const char *program_invocation_short_name = ""; +const char *program_invocation_name = ""; +#endif +#ifdef __UCLIBC_HAS___PROGNAME__ +weak_alias (program_invocation_short_name, __progname) +weak_alias (program_invocation_name, __progname_full) +#endif + +/* + * Declare the __environ global variable and create a strong alias environ. + * Note: Apparently we must initialize __environ to ensure that the strong + * environ symbol is also included. + */ +char **__environ = 0; +weak_alias(__environ, environ) + +/* TODO: don't export __pagesize; we cant now because libpthread uses it */ +size_t __pagesize = 0; + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#ifndef __ARCH_HAS_NO_LDSO__ +static void __check_one_fd(int fd, int mode) +{ + /* Check if the specified fd is already open */ + if (__libc_fcntl(fd, F_GETFD) == -1) + { + /* The descriptor is probably not open, so try to use /dev/null */ + int nullfd = __libc_open(_PATH_DEVNULL, mode); + /* /dev/null is major=1 minor=3. Make absolutely certain + * that is in fact the device that we have opened and not + * some other wierd file... */ + if (nullfd!=fd) + { + abort(); + } + } +} + +static int __check_suid(void) +{ + uid_t uid, euid; + gid_t gid, egid; + + uid = getuid(); + euid = geteuid(); + if (uid != euid) + return 1; + gid = getgid(); + egid = getegid(); + if (gid != egid) + return 1; + return 0; /* we are not suid */ +} +#endif + +/* __uClibc_init completely initialize uClibc so it is ready to use. + * + * On ELF systems (with a dynamic loader) this function must be called + * from the dynamic loader (see TIS and ELF Specification), so that + * constructors of shared libraries (which depend on libc) can use all + * the libc code without restriction. For this we link the shared + * version of the uClibc with -init __uClibc_init so DT_INIT for + * uClibc is the address of __uClibc_init + * + * In all other cases we call it from the main stub + * __uClibc_main. + */ + +extern void __uClibc_init(void); +libc_hidden_proto(__uClibc_init) +void __uClibc_init(void) +{ + static smallint been_there_done_that; + + if (been_there_done_that) + return; + been_there_done_that++; + + /* Setup an initial value. This may not be perfect, but is + * better than malloc using __pagesize=0 for atexit, ctors, etc. */ + __pagesize = PAGE_SIZE; + +#ifdef __UCLIBC_HAS_THREADS__ + /* Before we start initializing uClibc we have to call + * __pthread_initialize_minimal so we can use pthread_locks + * whenever they are needed. + */ + if (likely(__pthread_initialize_minimal!=NULL)) + __pthread_initialize_minimal(); +#endif + +#ifndef SHARED +# ifdef __UCLIBC_HAS_SSP__ + /* Set up the stack checker's canary. */ + stack_chk_guard = _dl_setup_stack_chk_guard(); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +# ifdef __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +# else + __stack_chk_guard = stack_chk_guard; +# if !defined __HAVE_SHARED__ && defined __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +# endif +# endif +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + /* Initialize the global locale structure. */ + if (likely(_locale_init!=NULL)) + _locale_init(); +#endif + + /* + * Initialize stdio here. In the static library case, this will + * be bypassed if not needed because of the weak alias above. + * Thus we get a nice size savings because the stdio functions + * won't be pulled into the final static binary unless used. + */ + if (likely(_stdio_init != NULL)) + _stdio_init(); + +} +libc_hidden_def(__uClibc_init) + +#ifdef __UCLIBC_CTOR_DTOR__ +void attribute_hidden (*__app_fini)(void) = NULL; +#endif + +void attribute_hidden (*__rtld_fini)(void) = NULL; + +extern void __uClibc_fini(void); +libc_hidden_proto(__uClibc_fini) +void __uClibc_fini(void) +{ +#ifdef __UCLIBC_CTOR_DTOR__ + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array finalisation is handled + * by __app_fini. */ +# ifdef SHARED + _dl_app_fini_array(); +# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + size_t i = __fini_array_end - __fini_array_start; + while (i-- > 0) + (*__fini_array_start [i]) (); +# endif + if (__app_fini != NULL) + (__app_fini)(); +#endif + if (__rtld_fini != NULL) + (__rtld_fini)(); +} +libc_hidden_def(__uClibc_fini) + +/* __uClibc_main is the new main stub for uClibc. This function is + * called from crt1 (version 0.9.28 or newer), after ALL shared libraries + * are initialized, just before we call the application's main function. + */ +void __uClibc_main(int (*main)(int, char **, char **), int argc, + char **argv, void (*app_init)(void), void (*app_fini)(void), + void (*rtld_fini)(void), void *stack_end) attribute_noreturn; +void __uClibc_main(int (*main)(int, char **, char **), int argc, + char **argv, void (*app_init)(void), void (*app_fini)(void), + void (*rtld_fini)(void), void *stack_end) +{ +#ifndef __ARCH_HAS_NO_LDSO__ + unsigned long *aux_dat; + ElfW(auxv_t) auxvt[AT_EGID + 1]; +#endif + +#ifndef SHARED + __libc_stack_end = stack_end; +#endif + + __rtld_fini = rtld_fini; + + /* The environment begins right after argv. */ + __environ = &argv[argc + 1]; + + /* If the first thing after argv is the arguments + * the the environment is empty. */ + if ((char *) __environ == *argv) { + /* Make __environ point to the NULL at argv[argc] */ + __environ = &argv[argc]; + } + +#ifndef __ARCH_HAS_NO_LDSO__ + /* Pull stuff from the ELF header when possible */ + memset(auxvt, 0x00, sizeof(auxvt)); + aux_dat = (unsigned long*)__environ; + while (*aux_dat) { + aux_dat++; + } + aux_dat++; + while (*aux_dat) { + ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; + if (auxv_entry->a_type <= AT_EGID) { + memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); + } + aux_dat += 2; + } +#endif + + /* We need to initialize uClibc. If we are dynamically linked this + * may have already been completed by the shared lib loader. We call + * __uClibc_init() regardless, to be sure the right thing happens. */ + __uClibc_init(); + +#ifndef __ARCH_HAS_NO_LDSO__ + /* Make certain getpagesize() gives the correct answer */ + __pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + + /* Prevent starting SUID binaries where the stdin. stdout, and + * stderr file descriptors are not already opened. */ + if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || + (auxvt[AT_UID].a_un.a_val != (size_t)-1 && + (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val || + auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val))) + { + __check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW); + __check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW); + __check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW); + } +#endif + + __uclibc_progname = *argv; +#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ + if (*argv != NULL) { + program_invocation_name = *argv; + program_invocation_short_name = strrchr(*argv, '/'); + if (program_invocation_short_name != NULL) + ++program_invocation_short_name; + else + program_invocation_short_name = program_invocation_name; + } +#endif + +#ifdef __UCLIBC_CTOR_DTOR__ + /* Arrange for the application's dtors to run before we exit. */ + __app_fini = app_fini; + + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled + * by __app_init. */ +# if !defined (SHARED) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + /* For dynamically linked executables the preinit array is executed by + the dynamic linker (before initializing any shared object). + For static executables, preinit happens rights before init. */ + { + const size_t size = __preinit_array_end - __preinit_array_start; + size_t i; + for (i = 0; i < size; i++) + (*__preinit_array_start [i]) (); + } +# endif + /* Run all the application's ctors now. */ + if (app_init!=NULL) { + app_init(); + } + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled + * by __app_init. */ +# ifdef SHARED + _dl_app_init_array(); +# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + { + const size_t size = __init_array_end - __init_array_start; + size_t i; + for (i = 0; i < size; i++) + (*__init_array_start [i]) (); + } +# endif +#endif + + /* Note: It is possible that any initialization done above could + * have resulted in errno being set nonzero, so set it to 0 before + * we call main. + */ + if (likely(__errno_location!=NULL)) + *(__errno_location()) = 0; + + /* Set h_errno to 0 as well */ + if (likely(__h_errno_location!=NULL)) + *(__h_errno_location()) = 0; + + /* + * Finally, invoke application's main and then exit. + */ + exit(main(argc, argv, __environ)); +} + +#if defined(__UCLIBC_HAS_THREADS__) && !defined(SHARED) +/* Weaks for internal library use only. + * + * We need to define weaks here to cover all the pthread functions that + * libc itself will use so that we aren't forced to link libc against + * libpthread. This file is only used in libc.a and since we have + * weaks here, they will be automatically overridden by libpthread.a + * if it gets linked in. + */ + +static int __pthread_return_0 (void) { return 0; } +static void __pthread_return_void (void) { return; } + +weak_alias (__pthread_return_0, __pthread_mutex_init) +weak_alias (__pthread_return_0, __pthread_mutex_lock) +weak_alias (__pthread_return_0, __pthread_mutex_trylock) +weak_alias (__pthread_return_0, __pthread_mutex_unlock) +weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) +weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +weak_alias (__pthread_return_0, __pthread_mutexattr_init) +weak_alias (__pthread_return_0, __pthread_mutexattr_destroy) +weak_alias (__pthread_return_0, __pthread_mutexattr_settype) +# endif +#endif diff --git a/libc/misc/internals/errno.c b/libc/misc/internals/errno.c new file mode 100644 index 0000000..fcf143f --- /dev/null +++ b/libc/misc/internals/errno.c @@ -0,0 +1,15 @@ +#include "internal_errno.h" + +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(errno) +libc_hidden_proto(h_errno) +#endif +int errno = 0; +int h_errno = 0; + +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_def(errno) +weak_alias(errno, _errno) +libc_hidden_def(h_errno) +weak_alias(h_errno, _h_errno) +#endif diff --git a/libc/misc/internals/internal_errno.h b/libc/misc/internals/internal_errno.h new file mode 100644 index 0000000..a93d0bf --- /dev/null +++ b/libc/misc/internals/internal_errno.h @@ -0,0 +1,18 @@ +/* + * + */ + +#include +#include +#include + +#undef errno +#undef h_errno + +extern int h_errno; +extern int errno; + +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(h_errno) +libc_hidden_proto(errno) +#endif diff --git a/libc/misc/internals/shared_flat_add_library.c b/libc/misc/internals/shared_flat_add_library.c new file mode 100644 index 0000000..f03480f --- /dev/null +++ b/libc/misc/internals/shared_flat_add_library.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines __shared_flat_add_library. If a library has + * initialistion and finalisation code, it should use this routine + * to register itself. + */ +#include "shared_flat_lib.h" + +/* The initialisation and finalisation symbols for this library. */ +extern void _init(void) attribute_hidden weak_function; +extern void _fini(void) attribute_hidden weak_function; +extern void (*__preinit_array_start[])(void) attribute_hidden; +extern void (*__preinit_array_end[])(void) attribute_hidden; +extern void (*__init_array_start[])(void) attribute_hidden; +extern void (*__init_array_end[])(void) attribute_hidden; +extern void (*__fini_array_start[])(void) attribute_hidden; +extern void (*__fini_array_end[])(void) attribute_hidden; + +/* The shared_flat_lib structure that describes this library. */ +static struct shared_flat_lib this_lib = { + 0, + 0, + __preinit_array_start, + __preinit_array_end, + __init_array_start, + __init_array_end, + __fini_array_start, + __fini_array_end, + _init, + _fini +}; + +/* Add this_lib to the end of the global list. */ +void __shared_flat_add_library(void) attribute_hidden; +void __shared_flat_add_library(void) +{ + this_lib.prev = __last_shared_lib; + if (this_lib.prev) + this_lib.prev->next = &this_lib; + else + __first_shared_lib = &this_lib; + __last_shared_lib = &this_lib; +} diff --git a/libc/misc/internals/shared_flat_initfini.c b/libc/misc/internals/shared_flat_initfini.c new file mode 100644 index 0000000..81e5383 --- /dev/null +++ b/libc/misc/internals/shared_flat_initfini.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines the main initialisation and finalisation code for + * shared flat libraries. It in turn calls the initialisation and + * finalisation code for each registered library. + */ +#include "shared_flat_lib.h" + +/* A doubly-linked list of shared libraries. Those nearer the head + * of the list should be initialised first and finalised last. */ +struct shared_flat_lib *__first_shared_lib; +struct shared_flat_lib *__last_shared_lib; + +void __shared_flat_init(void) +{ + struct shared_flat_lib *lib; + void (**start)(void); + void (**end)(void); + + for (lib = __first_shared_lib; lib; lib = lib->next) { + end = lib->preinit_array_end; + for (start = lib->preinit_array_start; start < end; start++) + (*start)(); + } + + for (lib = __first_shared_lib; lib; lib = lib->next) { + if (lib->init) + lib->init(); + + end = lib->init_array_end; + for (start = lib->init_array_start; start < end; start++) + (*start)(); + } +} + +void __shared_flat_fini(void) +{ + struct shared_flat_lib *lib; + void (**start)(void); + void (**end)(void); + + for (lib = __last_shared_lib; lib; lib = lib->prev) { + start = lib->fini_array_start; + for (end = lib->fini_array_end; end > start;) + (*--end)(); + + if (lib->fini) + lib->fini(); + } +} diff --git a/libc/misc/internals/shared_flat_lib.h b/libc/misc/internals/shared_flat_lib.h new file mode 100644 index 0000000..e012135 --- /dev/null +++ b/libc/misc/internals/shared_flat_lib.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines the shared_flat_lib structure and the global library + * list. The structure is used to provide something close to ELF-like + * initialisation and finalisation when using shared flat libraries. + */ +#ifndef __SHARED_FLAT_LIB__ +#define __SHARED_FLAT_LIB__ + +struct shared_flat_lib { + struct shared_flat_lib *prev; + struct shared_flat_lib *next; + /* .preinit_array is usually only supported for executables. + * However, the distinction between the executable and its + * shared libraries isn't as pronounced for flat files; a shared + * library is really just a part of an executable that can be + * shared with other executables. We therefore allow + * .preinit_array to be used in libraries too. */ + void (**preinit_array_start)(void); + void (**preinit_array_end)(void); + void (**init_array_start)(void); + void (**init_array_end)(void); + void (**fini_array_start)(void); + void (**fini_array_end)(void); + void (*init)(void); + void (*fini)(void); +}; + +extern struct shared_flat_lib *__first_shared_lib; +extern struct shared_flat_lib *__last_shared_lib; + +#endif diff --git a/libc/misc/internals/tempname.c b/libc/misc/internals/tempname.c new file mode 100644 index 0000000..c963eae --- /dev/null +++ b/libc/misc/internals/tempname.c @@ -0,0 +1,263 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* March 11, 2002 Manuel Novoa III + * + * Modify code to remove dependency on libgcc long long arith support funcs. + */ + +/* June 6, 2004 Erik Andersen + * + * Don't use brain damaged getpid() based randomness. + */ + +/* April 15, 2005 Mike Frysinger + * + * Use brain damaged getpid() if real random fails. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tempname.h" + +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +libc_hidden_proto(sprintf) +libc_hidden_proto(mkdir) +libc_hidden_proto(open) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(open64) +#endif +libc_hidden_proto(read) +libc_hidden_proto(close) +libc_hidden_proto(getpid) +libc_hidden_proto(stat) +libc_hidden_proto(gettimeofday) + +/* Return nonzero if DIR is an existent directory. */ +static int direxists (const char *dir) +{ + struct stat buf; + return stat(dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int attribute_hidden ___path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx /*, int try_tmpdir*/) +{ + /*const char *d; */ + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + /* Disable support for $TMPDIR */ +#if 0 + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } +#endif + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", dlen, dir, plen, pfx); + return 0; +} + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +#define NUM_LETTERS (62) + +static unsigned int fillrand(unsigned char *buf, unsigned int len) +{ + int fd; + unsigned int result = -1; + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + } + if (fd >= 0) { + result = read(fd, buf, len); + close(fd); + } + return result; +} + +static void brain_damaged_fillrand(unsigned char *buf, unsigned int len) +{ + unsigned int i, k; + struct timeval tv; + uint32_t high, low, rh; + static uint64_t value; + gettimeofday(&tv, NULL); + value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid(); + low = value & UINT32_MAX; + high = value >> 32; + for (i = 0; i < len; ++i) { + rh = high % NUM_LETTERS; + high /= NUM_LETTERS; +#define L ((UINT32_MAX % NUM_LETTERS + 1) % NUM_LETTERS) + k = (low % NUM_LETTERS) + (L * rh); +#undef L +#define H ((UINT32_MAX / NUM_LETTERS) + ((UINT32_MAX % NUM_LETTERS + 1) / NUM_LETTERS)) + low = (low / NUM_LETTERS) + (H * rh) + (k / NUM_LETTERS); +#undef H + k %= NUM_LETTERS; + buf[i] = letters[k]; + } +} + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_BIGFILE: same as __GT_FILE but use open64(). + __GT_DIR: create a directory, which will be mode 0700. + +*/ +int attribute_hidden __gen_tempname (char *tmpl, int kind) +{ + char *XXXXXX; + unsigned int i; + int fd, save_errno = errno; + unsigned char randomness[6]; + size_t len; + + len = strlen (tmpl); + /* This is where the Xs start. */ + XXXXXX = tmpl + len - 6; + if (len < 6 || strcmp (XXXXXX, "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + for (i = 0; i < TMP_MAX; ++i) { + int j; + /* Get some random data. */ + if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) { + /* if random device nodes failed us, lets use the braindamaged ver */ + brain_damaged_fillrand(randomness, sizeof(randomness)); + } + for (j = 0; j < sizeof(randomness); ++j) + XXXXXX[j] = letters[randomness[j] % NUM_LETTERS]; + + switch (kind) { + case __GT_NOCREATE: + { + struct stat st; + if (stat (tmpl, &st) < 0) { + if (errno == ENOENT) { + fd = 0; + goto restore_and_ret; + } else + /* Give up now. */ + return -1; + } else + fd = 0; + } + case __GT_FILE: + fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; +#if defined __UCLIBC_HAS_LFS__ + case __GT_BIGFILE: + fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; +#endif + case __GT_DIR: + fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + default: + fd = -1; + assert (! "invalid KIND in __gen_tempname"); + } + + if (fd >= 0) { +restore_and_ret: + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + /* Any other error will apply also to other names we might + try, and there are 2^32 or so of them, so give up now. */ + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/libc/misc/internals/tempname.h b/libc/misc/internals/tempname.h new file mode 100644 index 0000000..ac40bef --- /dev/null +++ b/libc/misc/internals/tempname.h @@ -0,0 +1,20 @@ +#ifndef __TEMPNAME_H__ +#define __TEMPNAME_H__ + +#define __need_size_t +#include + +/* Disable support for $TMPDIR */ +extern int ___path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx /*, int try_tmpdir */) attribute_hidden; +#define __path_search(tmpl, tmpl_len, dir, pfx, try_tmpdir) ___path_search(tmpl, tmpl_len, dir, pfx) + +extern int __gen_tempname (char *__tmpl, int __kind) attribute_hidden; + +/* The __kind argument to __gen_tempname may be one of: */ +#define __GT_FILE 0 /* create a file */ +#define __GT_BIGFILE 1 /* create a file, using open64 */ +#define __GT_DIR 2 /* create a directory */ +#define __GT_NOCREATE 3 /* just find a name not currently in use */ + +#endif diff --git a/libc/misc/locale/Makefile b/libc/misc/locale/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/locale/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/locale/Makefile.in b/libc/misc/locale/Makefile.in new file mode 100644 index 0000000..689bd0b --- /dev/null +++ b/libc/misc/locale/Makefile.in @@ -0,0 +1,28 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# multi source locale.c +CSRC := setlocale.c localeconv.c _locale_init.c nl_langinfo.c +ifeq ($(UCLIBC_HAS_LOCALE),y) +CSRC += newlocale.c __locale_mbrtowc_l.c +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += nl_langinfo_l.c duplocale.c freelocale.c uselocale.c __curlocale.c +endif + +MISC_LOCALE_DIR := $(top_srcdir)libc/misc/locale +MISC_LOCALE_OUT := $(top_builddir)libc/misc/locale + +MISC_LOCALE_SRC := $(patsubst %.c,$(MISC_LOCALE_DIR)/%.c,$(CSRC)) +MISC_LOCALE_OBJ := $(patsubst %.c,$(MISC_LOCALE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_LOCALE_OBJ) + +objclean-y += misc_locale_clean + +misc_locale_clean: + $(do_rm) $(addprefix $(MISC_LOCALE_OUT)/*., o os) diff --git a/libc/misc/locale/__curlocale.c b/libc/misc/locale/__curlocale.c new file mode 100644 index 0000000..aa38f43 --- /dev/null +++ b/libc/misc/locale/__curlocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___curlocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/libc/misc/locale/__locale_mbrtowc_l.c b/libc/misc/locale/__locale_mbrtowc_l.c new file mode 100644 index 0000000..ea7fbce --- /dev/null +++ b/libc/misc/locale/__locale_mbrtowc_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___locale_mbrtowc_l +#include "locale.c" diff --git a/libc/misc/locale/_locale_init.c b/libc/misc/locale/_locale_init.c new file mode 100644 index 0000000..9ced732 --- /dev/null +++ b/libc/misc/locale/_locale_init.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__locale_init +#include "locale.c" diff --git a/libc/misc/locale/duplocale.c b/libc/misc/locale/duplocale.c new file mode 100644 index 0000000..db9c7a3 --- /dev/null +++ b/libc/misc/locale/duplocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_duplocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/libc/misc/locale/freelocale.c b/libc/misc/locale/freelocale.c new file mode 100644 index 0000000..c1ef8e1 --- /dev/null +++ b/libc/misc/locale/freelocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_freelocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c new file mode 100644 index 0000000..6df88a7 --- /dev/null +++ b/libc/misc/locale/locale.c @@ -0,0 +1,1498 @@ +/* Copyright (C) 2002 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Nov. 1, 2002 + * Reworked setlocale() return values and locale arg processing to + * be more like glibc. Applications expecting to be able to + * query locale settings should now work... at the cost of almost + * doubling the size of the setlocale object code. + * Fixed a bug in the internal fixed-size-string locale specifier code. + * + * Dec 20, 2002 + * Added in collation support and updated stub nl_langinfo. + * + * Aug 1, 2003 + * Added glibc-like extended locale stuff (newlocale, duplocale, etc). + * + * Aug 18, 2003 + * Bug in duplocale... collation data wasn't copied. + * Bug in newlocale... translate 1< +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strtok_r) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +libc_hidden_proto(getenv) +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__C_ctype_toupper) +#endif +/*libc_hidden_proto(fflush)*/ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Make the link_warning()s a config option? +#endif +#endif +#undef link_warning +#define link_warning(A,B) + +#undef __LOCALE_C_ONLY +#ifndef __UCLIBC_HAS_LOCALE__ +#define __LOCALE_C_ONLY +#endif /* __UCLIBC_HAS_LOCALE__ */ + + +#ifdef __LOCALE_C_ONLY + +#include + +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Fix the __CTYPE_HAS_8_BIT_LOCALES define at the top of the file. +#warning TODO: Fix __WCHAR_ENABLED. +#endif +#endif + +/* Need to include this before locale.h and xlocale.h! */ +#include + +#undef CODESET_LIST +#define CODESET_LIST (__locale_mmap->codeset_list) + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include +#else /* __UCLIBC_HAS_XLOCALE__ */ +/* We need this internally... */ +#define __UCLIBC_HAS_XLOCALE__ 1 +#include +#include +#undef __UCLIBC_HAS_XLOCALE__ +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#include + +#define LOCALE_NAMES (__locale_mmap->locale_names5) +#define LOCALES (__locale_mmap->locales) +#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers) +#define CATEGORY_NAMES (__locale_mmap->lc_names) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: redo the MAX_LOCALE_STR stuff... +#endif +#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */ +#define MAX_LOCALE_CATEGORY_STR 32 /* TODO: Only sufficient for current case. */ +/* Note: Best if MAX_LOCALE_CATEGORY_STR is a power of 2. */ + +extern int _locale_set_l(const unsigned char *p, __locale_t base) attribute_hidden; +extern void _locale_init_l(__locale_t base) attribute_hidden; + +#endif /* __LOCALE_C_ONLY */ + +#undef LOCALE_STRING_SIZE +#define LOCALE_SELECTOR_SIZE (2 * __LC_ALL + 2) + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Create a C locale selector string. +#endif +#endif +#define C_LOCALE_SELECTOR "\x23\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" + + +#include +#include + +/**********************************************************************/ +#ifdef L_setlocale + +#ifdef __LOCALE_C_ONLY + +link_warning(setlocale,"REMINDER: The 'setlocale' function supports only C|POSIX locales.") + +static const char C_string[] = "C"; + +char *setlocale(int category, register const char *locale) +{ + return ( (((unsigned int)(category)) <= LC_ALL) + && ( (!locale) /* Request for locale category string. */ + || (!*locale) /* Implementation-defined default is C. */ + || ((*locale == 'C') && !locale[1]) + || (!strcmp(locale, "POSIX"))) ) + ? (char *) C_string /* Always in C/POSIX locale. */ + : NULL; +} + +#else /* ---------------------------------------------- __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_HAS_THREADS__ +link_warning(setlocale,"REMINDER: The 'setlocale' function is _not_ threadsafe except for simple queries.") +#endif + +#if !defined(__LOCALE_DATA_NUM_LOCALES) || (__LOCALE_DATA_NUM_LOCALES <= 1) +#error locales enabled, but not data other than for C locale! +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move posix and utf8 strings. +#endif +static const char posix[] = "POSIX"; +static const char utf8[] = "UTF-8"; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix dimensions of hr_locale. +#endif +/* Individual category strings start at hr_locale + category * MAX_LOCALE_CATEGORY. + * This holds for LC_ALL as well. + */ +static char hr_locale[(MAX_LOCALE_CATEGORY_STR * LC_ALL) + MAX_LOCALE_STR]; + +/* Experimentally off - libc_hidden_proto(stpcpy) */ +libc_hidden_proto(newlocale) + +static void update_hr_locale(const unsigned char *spec) +{ + const unsigned char *loc; + const unsigned char *s; + char *n; + int i, category, done; + + done = category = 0; + do { + s = spec + 1; + n = hr_locale + category * MAX_LOCALE_CATEGORY_STR; + + if (category == LC_ALL) { + done = 1; + for (i = 0 ; i < LC_ALL-1 ; i += 2) { + if ((s[i] != s[i+2]) || (s[i+1] != s[i+3])) { + goto SKIP; + } + } + /* All categories the same, so simplify string by using a single + * category. */ + category = LC_CTYPE; + } + + SKIP: + i = (category == LC_ALL) ? 0 : category; + s += 2*i; + + do { + if ((*s != 0xff) || (s[1] != 0xff)) { + loc = LOCALES + + __LOCALE_DATA_WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7) + + (s[1] & 0x7f)); + if (category == LC_ALL) { + n = stpcpy(n, CATEGORY_NAMES + (int) CATEGORY_NAMES[i]); + *n++ = '='; + } + if (*loc == 0) { + *n++ = 'C'; + *n = 0; + } else { + char at = 0; + memcpy(n, LOCALE_NAMES + 5*((*loc)-1), 5); + if (n[2] != '_') { + at = n[2]; + n[2] = '_'; + } + n += 5; + *n++ = '.'; + if (loc[2] == 2) { + n = stpcpy(n, utf8); + } else if (loc[2] >= 3) { + n = stpcpy(n, CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3])); + } + if (at) { + const char *q; + *n++ = '@'; + q = LOCALE_AT_MODIFIERS; + do { + if (q[1] == at) { + n = stpcpy(n, q+2); + break; + } + q += 2 + *q; + } while (*q); + } + } + *n++ = ';'; + } + s += 2; + } while (++i < category); + *--n = 0; /* Remove trailing ';' and nul-terminate. */ + + ++category; + } while (!done); +} + +char *setlocale(int category, const char *locale) +{ + if (((unsigned int)(category)) > LC_ALL) { +#if 0 + __set_errno(EINVAL); /* glibc sets errno -- SUSv3 doesn't say. */ +#endif + return NULL; /* Illegal/unsupported category. */ + } + + if (locale != NULL) { /* Not just a query... */ + if (!newlocale((1 << category), locale, __global_locale)) { + return NULL; /* Failed! */ + } + update_hr_locale(__global_locale->cur_locale); + } + + /* Either a query or a successful set, so return current locale string. */ + return hr_locale + (category * MAX_LOCALE_CATEGORY_STR); +} + +#endif /* __LOCALE_C_ONLY */ + +#endif +/**********************************************************************/ +#ifdef L_localeconv + +/* Note: We assume here that the compiler does the sane thing regarding + * placement of the fields in the struct. If necessary, we could ensure + * this usings an array of offsets but at some size cost. */ + +libc_hidden_proto(localeconv) + +#ifdef __LOCALE_C_ONLY + +link_warning(localeconv,"REMINDER: The 'localeconv' function is hardwired for C/POSIX locale only.") + +static struct lconv the_lconv; + +static const char decpt[] = "."; + +struct lconv *localeconv(void) +{ + register char *p = (char *)(&the_lconv); + + *((char **)p) = (char *) decpt; + do { + p += sizeof(char **); + *((char **)p) = (char *) (decpt+1); + } while (p < (char *) &the_lconv.negative_sign); + + p = (&the_lconv.int_frac_digits); + do { + *p = CHAR_MAX; + ++p; + } while (p <= &the_lconv.int_n_sign_posn); + + return &the_lconv; +} + +#else /* __LOCALE_C_ONLY */ + +static struct lconv the_lconv; + +struct lconv *localeconv(void) +{ + register char *p = (char *) &the_lconv; + register char **q = (char **) &(__UCLIBC_CURLOCALE_DATA).decimal_point; + + do { + *((char **)p) = *q; + p += sizeof(char **); + ++q; + } while (p < &the_lconv.int_frac_digits); + + do { + *p = **q; + ++p; + ++q; + } while (p <= &the_lconv.int_n_sign_posn); + + return &the_lconv; +} + +#endif /* __LOCALE_C_ONLY */ + +libc_hidden_def(localeconv) + +#endif +/**********************************************************************/ +#if defined(L__locale_init) && !defined(__LOCALE_C_ONLY) + +libc_hidden_proto(__C_ctype_b) +libc_hidden_proto(__C_ctype_tolower) +#ifndef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +libc_hidden_proto(__ctype_toupper) +#endif + +__uclibc_locale_t __global_locale_data; + +__locale_t __global_locale = &__global_locale_data; + +#ifdef __UCLIBC_HAS_XLOCALE__ +__locale_t __curlocale_var = &__global_locale_data; +#endif + +/*----------------------------------------------------------------------*/ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move utf8 and ascii strings. +#endif +static const char utf8[] = "UTF-8"; +static const char ascii[] = "ASCII"; + +typedef struct { + uint16_t num_base; + uint16_t num_der; + uint16_t MAX_WEIGHTS; + uint16_t num_index2weight; +#define num_index2ruleidx num_index2weight + uint16_t num_weightstr; + uint16_t num_multistart; + uint16_t num_override; + uint16_t num_ruletable; +} coldata_header_t; + +typedef struct { + uint16_t num_weights; + uint16_t num_starters; + uint16_t ii_shift; + uint16_t ti_shift; + uint16_t ii_len; + uint16_t ti_len; + uint16_t max_weight; + uint16_t num_col_base; + uint16_t max_col_index; + uint16_t undefined_idx; + uint16_t range_low; + uint16_t range_count; + uint16_t range_base_weight; + uint16_t range_rule_offset; + + uint16_t index2weight_offset; + uint16_t index2ruleidx_offset; + uint16_t multistart_offset; + uint16_t wcs2colidt_offset_low; + uint16_t wcs2colidt_offset_hi; +} coldata_base_t; + +typedef struct { + uint16_t base_idx; + uint16_t undefined_idx; + uint16_t overrides_offset; + uint16_t multistart_offset; +} coldata_der_t; + +static int init_cur_collate(int der_num, __collate_t *cur_collate) +{ + const uint16_t *__locale_collate_tbl = __locale_mmap->collate_data; + coldata_header_t *cdh; + coldata_base_t *cdb; + coldata_der_t *cdd; + const uint16_t *p; + size_t n; + uint16_t i, w; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning kill of x86-specific asserts +#endif +#if 0 + assert(sizeof(coldata_base_t) == 19*2); + assert(sizeof(coldata_der_t) == 4*2); + assert(sizeof(coldata_header_t) == 8*2); +#endif + + if (!der_num) { /* C locale... special */ + cur_collate->num_weights = 0; + return 1; + } + + --der_num; + + cdh = (coldata_header_t *) __locale_collate_tbl; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we assert here? +#endif +#if 0 + if (der_num >= cdh->num_der) { + return 0; + } +#else + assert((der_num < cdh->num_der)); +#endif + + cdd = (coldata_der_t *)(__locale_collate_tbl + + (sizeof(coldata_header_t) + + cdh->num_base * sizeof(coldata_base_t) + + der_num * sizeof(coldata_der_t) + )/2 ); + + cdb = (coldata_base_t *)(__locale_collate_tbl + + (sizeof(coldata_header_t) + + cdd->base_idx * sizeof(coldata_base_t) + )/2 ); + + memcpy(cur_collate, cdb, offsetof(coldata_base_t,index2weight_offset)); + cur_collate->undefined_idx = cdd->undefined_idx; + + cur_collate->ti_mask = (1 << cur_collate->ti_shift)-1; + cur_collate->ii_mask = (1 << cur_collate->ii_shift)-1; + +/* fflush(stdout); */ +/* fprintf(stderr,"base=%d num_col_base: %d %d\n", cdd->base_idx ,cur_collate->num_col_base, cdb->num_col_base); */ + + n = (sizeof(coldata_header_t) + cdh->num_base * sizeof(coldata_base_t) + + cdh->num_der * sizeof(coldata_der_t))/2; + +/* fprintf(stderr,"n = %d\n", n); */ + cur_collate->index2weight_tbl = __locale_collate_tbl + n + cdb->index2weight_offset; +/* fprintf(stderr,"i2w = %d\n", n + cdb->index2weight_offset); */ + n += cdh->num_index2weight; + cur_collate->index2ruleidx_tbl = __locale_collate_tbl + n + cdb->index2ruleidx_offset; +/* fprintf(stderr,"i2r = %d\n", n + cdb->index2ruleidx_offset); */ + n += cdh->num_index2ruleidx; + cur_collate->multistart_tbl = __locale_collate_tbl + n + cdd->multistart_offset; +/* fprintf(stderr,"mts = %d\n", n + cdb->multistart_offset); */ + n += cdh->num_multistart; + cur_collate->overrides_tbl = __locale_collate_tbl + n + cdd->overrides_offset; +/* fprintf(stderr,"ovr = %d\n", n + cdd->overrides_offset); */ + n += cdh->num_override; + cur_collate->ruletable = __locale_collate_tbl + n; +/* fprintf(stderr, "rtb = %d\n", n); */ + n += cdh->num_ruletable; + cur_collate->weightstr = __locale_collate_tbl + n; +/* fprintf(stderr,"wts = %d\n", n); */ + n += cdh->num_weightstr; + cur_collate->wcs2colidt_tbl = __locale_collate_tbl + n + + (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16) + + cdb->wcs2colidt_offset_low; +/* fprintf(stderr,"wcs = %lu\n", n + (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16) */ +/* + cdb->wcs2colidt_offset_low); */ + + cur_collate->MAX_WEIGHTS = cdh->MAX_WEIGHTS; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Fix the +1 by increasing max_col_index? +#warning CONSIDER: Since this collate info is dependent only on LC_COLLATE ll_cc and not on codeset, we could just globally allocate this for each in a table +#endif + + cur_collate->index2weight = calloc(2*cur_collate->max_col_index+2, + sizeof(uint16_t)); + if (!cur_collate->index2weight) { + return 0; + } + cur_collate->index2ruleidx = cur_collate->index2weight + + cur_collate->max_col_index + 1; + + memcpy(cur_collate->index2weight, cur_collate->index2weight_tbl, + cur_collate->num_col_base * sizeof(uint16_t)); + memcpy(cur_collate->index2ruleidx, cur_collate->index2ruleidx_tbl, + cur_collate->num_col_base * sizeof(uint16_t)); + + /* now do the overrides */ + p = cur_collate->overrides_tbl; + while (*p > 1) { +/* fprintf(stderr, "processing override -- count = %d\n", *p); */ + n = *p++; + w = *p++; + do { + i = *p++; +/* fprintf(stderr, " i=%d (%#x) w=%d *p=%d\n", i, i, w, *p); */ + cur_collate->index2weight[i-1] = w++; + cur_collate->index2ruleidx[i-1] = *p++; + } while (--n); + } + assert(*p == 1); + while (*++p) { + i = *p; +/* fprintf(stderr, " i=%d (%#x) w=%d *p=%d\n", i, i, p[1], p[2]); */ + cur_collate->index2weight[i-1] = *++p; + cur_collate->index2ruleidx[i-1] = *++p; + } + + + for (i=0 ; i < cur_collate->multistart_tbl[0] ; i++) { + p = cur_collate->multistart_tbl; +/* fprintf(stderr, "%2d of %2d: %d ", i, cur_collate->multistart_tbl[0], p[i]); */ + p += p[i]; + + do { + n = *p++; + do { + if (!*p) { /* found it */ +/* fprintf(stderr, "found: n=%d (%#lx) |%.*ls|\n", n, (int) *cs->s, n, cs->s); */ +/* fprintf(stderr, ": %d - single\n", n); */ + goto FOUND; + } + /* the lookup check here is safe since we're assured that *p is a valid colidex */ +/* fprintf(stderr, "lookup(%lc)==%d *p==%d\n", cs->s[n], lookup(cs->s[n]), (int) *p); */ +/* fprintf(stderr, ": %d - ", n); */ + do { +/* fprintf(stderr, "%d|", *p); */ + } while (*p++); + break; + } while (1); + } while (1); + FOUND: + continue; + } + + return 1; +} + +int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base) +{ + const char **x; + unsigned char *s = base->cur_locale + 1; + const size_t *stp; + const unsigned char *r; + const uint16_t *io; + const uint16_t *ii; + const unsigned char *d; + int row; /* locale row */ + int crow; /* category row */ + int len; + int c; + int i = 0; + __collate_t newcol; + + ++p; + + newcol.index2weight = NULL; + if ((p[2*LC_COLLATE] != s[2*LC_COLLATE]) + || (p[2*LC_COLLATE + 1] != s[2*LC_COLLATE + 1]) + ) { + row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f); + assert(row < __LOCALE_DATA_NUM_LOCALES); + if (!init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES + * row + 3 + LC_COLLATE ], + &newcol) + ) { + return 0; /* calloc failed. */ + } + free(base->collate.index2weight); + memcpy(&base->collate, &newcol, sizeof(__collate_t)); + } + + do { + if ((*p != *s) || (p[1] != s[1])) { + row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f); + assert(row < __LOCALE_DATA_NUM_LOCALES); + + *s = *p; + s[1] = p[1]; + + if ((i != LC_COLLATE) + && ((len = __locale_mmap->lc_common_item_offsets_LEN[i]) != 0) + ) { + crow = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row + + 3 + i ] + * len; + + x = (const char **)(((char *) base) + + base->category_offsets[i]); + + stp = __locale_mmap->lc_common_tbl_offsets + 4*i; + r = (const unsigned char *)( ((char *)__locale_mmap) + *stp ); + io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp ); + ii = (const uint16_t *)( ((char *)__locale_mmap) + *++stp ); + d = (const unsigned char *)( ((char *)__locale_mmap) + *++stp ); + for (c=0 ; c < len ; c++) { + *(x + c) = d + ii[ r[crow + c] + io[c] ]; + } + } + if (i == LC_CTYPE) { + c = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row + + 2 ]; /* codeset */ + if (c <= 2) { + if (c == 2) { + base->codeset = utf8; + base->encoding = __ctype_encoding_utf8; + /* TODO - fix for bcc */ + base->mb_cur_max = 6; + } else { + assert(c==1); + base->codeset = ascii; + base->encoding = __ctype_encoding_7_bit; + base->mb_cur_max = 1; + } + } else { + const __codeset_8_bit_t *c8b; + r = CODESET_LIST; + base->codeset = r + r[c -= 3]; + base->encoding = __ctype_encoding_8_bit; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: update 8 bit mb_cur_max when translit implemented! +#endif + /* TODO - update when translit implemented! */ + base->mb_cur_max = 1; + c8b = __locale_mmap->codeset_8_bit + c; +#ifdef __CTYPE_HAS_8_BIT_LOCALES + base->idx8ctype = c8b->idx8ctype; + base->idx8uplow = c8b->idx8uplow; +#ifdef __UCLIBC_HAS_WCHAR__ + base->idx8c2wc = c8b->idx8c2wc; + base->idx8wc2c = c8b->idx8wc2c; + /* translit */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* What follows is fairly bloated, but it is just a hack + * to get the 8-bit codeset ctype stuff functioning. + * All of this will be replaced in the next generation + * of locale support anyway... */ + + memcpy(base->__ctype_b_data, + __C_ctype_b - __UCLIBC_CTYPE_B_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_B_TBL_OFFSET) + * sizeof(__ctype_mask_t)); + memcpy(base->__ctype_tolower_data, + __C_ctype_tolower - __UCLIBC_CTYPE_TO_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET) + * sizeof(__ctype_touplow_t)); + memcpy(base->__ctype_toupper_data, + __C_ctype_toupper - __UCLIBC_CTYPE_TO_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET) + * sizeof(__ctype_touplow_t)); + +#define Cctype_TBL_MASK ((1 << __LOCALE_DATA_Cctype_IDX_SHIFT) - 1) +#define Cctype_IDX_OFFSET (128 >> __LOCALE_DATA_Cctype_IDX_SHIFT) + + { + int u; + __ctype_mask_t m; + + for (u=0 ; u < 128 ; u++) { +#ifdef __LOCALE_DATA_Cctype_PACKED + c = base->tbl8ctype + [ ((int)(c8b->idx8ctype + [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ]) + << (__LOCALE_DATA_Cctype_IDX_SHIFT - 1)) + + ((u & Cctype_TBL_MASK) >> 1)]; + c = (u & 1) ? (c >> 4) : (c & 0xf); +#else + c = base->tbl8ctype + [ ((int)(c8b->idx8ctype + [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ]) + << __LOCALE_DATA_Cctype_IDX_SHIFT) + + (u & Cctype_TBL_MASK) ]; +#endif + + m = base->code2flag[c]; + + base->__ctype_b_data + [128 + __UCLIBC_CTYPE_B_TBL_OFFSET + u] + = m; + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_b_data[__UCLIBC_CTYPE_B_TBL_OFFSET + + ((signed char)(128 + u))] + = m; + } +#endif + + base->__ctype_tolower_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = 128 + u; + base->__ctype_toupper_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = 128 + u; + + if (m & (_ISlower|_ISupper)) { + c = base->tbl8uplow + [ ((int)(c8b->idx8uplow + [u >> __LOCALE_DATA_Cuplow_IDX_SHIFT]) + << __LOCALE_DATA_Cuplow_IDX_SHIFT) + + ((128 + u) + & ((1 << __LOCALE_DATA_Cuplow_IDX_SHIFT) + - 1)) ]; + if (m & _ISlower) { + base->__ctype_toupper_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = (unsigned char)(128 + u + c); +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_toupper_data + [__UCLIBC_CTYPE_TO_TBL_OFFSET + + ((signed char)(128 + u))] + = (unsigned char)(128 + u + c); + } +#endif + } else { + base->__ctype_tolower_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = (unsigned char)(128 + u - c); +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_tolower_data + [__UCLIBC_CTYPE_TO_TBL_OFFSET + + ((signed char)(128 + u))] + = (unsigned char)(128 + u - c); + } +#endif + } + } + } + } + +#ifdef __UCLIBC_HAS_XLOCALE__ + base->__ctype_b = base->__ctype_b_data + + __UCLIBC_CTYPE_B_TBL_OFFSET; + base->__ctype_tolower = base->__ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; + base->__ctype_toupper = base->__ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +#else /* __UCLIBC_HAS_XLOCALE__ */ + __ctype_b = base->__ctype_b_data + + __UCLIBC_CTYPE_B_TBL_OFFSET; + __ctype_tolower = base->__ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; + __ctype_toupper = base->__ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Put the outdigit string length in the locale_mmap object. +#endif + d = base->outdigit_length; + x = &base->outdigit0_mb; + for (c = 0 ; c < 10 ; c++) { + ((unsigned char *)d)[c] = strlen(x[c]); + assert(d[c] > 0); + } + } else if (i == LC_NUMERIC) { + assert(LC_NUMERIC > LC_CTYPE); /* Need ctype initialized. */ + + base->decimal_point_len + = __locale_mbrtowc_l(&base->decimal_point_wc, + base->decimal_point, base); + assert(base->decimal_point_len > 0); + assert(base->decimal_point[base->decimal_point_len] == 0); + + if (*base->grouping) { + base->thousands_sep_len + = __locale_mbrtowc_l(&base->thousands_sep_wc, + base->thousands_sep, base); +#if 1 +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Remove hack involving grouping without a thousep char (bg_BG). +#endif + assert(base->thousands_sep_len >= 0); + if (base->thousands_sep_len == 0) { + base->grouping = base->thousands_sep; /* empty string */ + } + assert(base->thousands_sep[base->thousands_sep_len] == 0); +#else + assert(base->thousands_sep_len > 0); + assert(base->thousands_sep[base->thousands_sep_len] == 0); +#endif + } + +/* } else if (i == LC_COLLATE) { */ +/* init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES */ +/* * row + 3 + i ], */ +/* &base->collate); */ + } + } + ++i; + p += 2; + s += 2; + } while (i < LC_ALL); + + return 1; +} + +static const uint16_t __code2flag[16] = { + 0, /* unclassified = 0 */ + _ISprint|_ISgraph|_ISalnum|_ISalpha, /* alpha_nonupper_nonlower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, /* alpha_lower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower|_ISupper, /* alpha_upper_lower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, /* alpha_upper */ + _ISprint|_ISgraph|_ISalnum|_ISdigit, /* digit */ + _ISprint|_ISgraph|_ISpunct, /* punct */ + _ISprint|_ISgraph, /* graph */ + _ISprint|_ISspace, /* print_space_nonblank */ + _ISprint|_ISspace|_ISblank, /* print_space_blank */ + _ISspace, /* space_nonblank_noncntrl */ + _ISspace|_ISblank, /* space_blank_noncntrl */ + _IScntrl|_ISspace, /* cntrl_space_nonblank */ + _IScntrl|_ISspace|_ISblank, /* cntrl_space_blank */ + _IScntrl /* cntrl_nonspace */ +}; + +void attribute_hidden _locale_init_l(__locale_t base) +{ + memset(base->cur_locale, 0, LOCALE_SELECTOR_SIZE); + base->cur_locale[0] = '#'; + + memcpy(base->category_item_count, + __locale_mmap->lc_common_item_offsets_LEN, + LC_ALL); + + ++base->category_item_count[0]; /* Increment for codeset entry. */ + base->category_offsets[0] = offsetof(__uclibc_locale_t, outdigit0_mb); + base->category_offsets[1] = offsetof(__uclibc_locale_t, decimal_point); + base->category_offsets[2] = offsetof(__uclibc_locale_t, int_curr_symbol); + base->category_offsets[3] = offsetof(__uclibc_locale_t, abday_1); +/* base->category_offsets[4] = offsetof(__uclibc_locale_t, collate???); */ + base->category_offsets[5] = offsetof(__uclibc_locale_t, yesexpr); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + base->tbl8ctype + = (const unsigned char *) &__locale_mmap->tbl8ctype; + base->tbl8uplow + = (const unsigned char *) &__locale_mmap->tbl8uplow; +#ifdef __UCLIBC_HAS_WCHAR__ + base->tbl8c2wc + = (const uint16_t *) &__locale_mmap->tbl8c2wc; + base->tbl8wc2c + = (const unsigned char *) &__locale_mmap->tbl8wc2c; + /* translit */ +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __UCLIBC_HAS_WCHAR__ + base->tblwctype + = (const unsigned char *) &__locale_mmap->tblwctype; + base->tblwuplow + = (const unsigned char *) &__locale_mmap->tblwuplow; + base->tblwuplow_diff + = (const uint16_t *) &__locale_mmap->tblwuplow_diff; +/* base->tblwcomb */ +/* = (const unsigned char *) &__locale_mmap->tblwcomb; */ + /* width?? */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* Initially, set things up to use the global C ctype tables. + * This is correct for C (ASCII) and UTF-8 based locales (except tr_TR). */ +#ifdef __UCLIBC_HAS_XLOCALE__ + base->__ctype_b = __C_ctype_b; + base->__ctype_tolower = __C_ctype_tolower; + base->__ctype_toupper = __C_ctype_toupper; +#else /* __UCLIBC_HAS_XLOCALE__ */ + __ctype_b = __C_ctype_b; + __ctype_tolower = __C_ctype_tolower; + __ctype_toupper = __C_ctype_toupper; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Initialize code2flag correctly based on locale_mmap. +#endif + base->code2flag = __code2flag; + + + _locale_set_l(C_LOCALE_SELECTOR, base); +} + +void _locale_init(void) attribute_hidden; +void _locale_init(void) +{ + /* TODO: mmap the locale file */ + + /* TODO - ??? */ + _locale_init_l(__global_locale); +} + +#endif +/**********************************************************************/ +#if defined(L_nl_langinfo) || defined(L_nl_langinfo_l) + +#ifdef __LOCALE_C_ONLY + +/* We need to index 320 bytes of data, so you might initially think we + * need to store the offsets in shorts. But since the offset of the + * 64th item is 182, we'll store "offset - 2*64" for all items >= 64 + * and always calculate the data offset as "offset[i] + 2*(i & 64)". + * This allows us to pack the data offsets in an unsigned char while + * also avoiding an "if". + * + * Note: Category order is assumed to be: + * ctype, numeric, monetary, time, collate, messages, all + */ + +#define C_LC_ALL 6 + +/* Combine the data to avoid size penalty for seperate char arrays when + * compiler aligns objects. The original code is left in as documentation. */ +#define cat_start nl_data +#define C_locale_data (nl_data + C_LC_ALL + 1 + 90) + +static const unsigned char nl_data[C_LC_ALL + 1 + 90 + 320] = { +/* static const char cat_start[LC_ALL + 1] = { */ + '\x00', '\x0b', '\x0e', '\x24', '\x56', '\x56', '\x5a', +/* }; */ +/* static const char item_offset[90] = { */ + '\x00', '\x02', '\x04', '\x06', '\x08', '\x0a', '\x0c', '\x0e', + '\x10', '\x12', '\x14', '\x1a', '\x1b', '\x1b', '\x1b', '\x1b', + '\x1b', '\x1b', '\x1b', '\x1b', '\x1b', '\x1c', '\x1c', '\x1c', + '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', + '\x1c', '\x1c', '\x1c', '\x1e', '\x20', '\x24', '\x28', '\x2c', + '\x30', '\x34', '\x38', '\x3c', '\x43', '\x4a', '\x52', '\x5c', + '\x65', '\x6c', '\x75', '\x79', '\x7d', '\x81', '\x85', '\x89', + '\x8d', '\x91', '\x95', '\x99', '\x9d', '\xa1', '\xa5', '\xad', + '\x36', '\x3c', '\x42', '\x46', '\x4b', '\x50', '\x57', '\x61', + '\x69', '\x72', '\x7b', '\x7e', '\x81', '\x96', '\x9f', '\xa8', + '\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb4', '\xba', + '\xbf', '\xbf', +/* }; */ +/* static const char C_locale_data[320] = { */ + '0', '\x00', '1', '\x00', '2', '\x00', '3', '\x00', + '4', '\x00', '5', '\x00', '6', '\x00', '7', '\x00', + '8', '\x00', '9', '\x00', 'A', 'S', 'C', 'I', + 'I', '\x00', '.', '\x00', '\x7f', '\x00', '-', '\x00', + 'S', 'u', 'n', '\x00', 'M', 'o', 'n', '\x00', + 'T', 'u', 'e', '\x00', 'W', 'e', 'd', '\x00', + 'T', 'h', 'u', '\x00', 'F', 'r', 'i', '\x00', + 'S', 'a', 't', '\x00', 'S', 'u', 'n', 'd', + 'a', 'y', '\x00', 'M', 'o', 'n', 'd', 'a', + 'y', '\x00', 'T', 'u', 'e', 's', 'd', 'a', + 'y', '\x00', 'W', 'e', 'd', 'n', 'e', 's', + 'd', 'a', 'y', '\x00', 'T', 'h', 'u', 'r', + 's', 'd', 'a', 'y', '\x00', 'F', 'r', 'i', + 'd', 'a', 'y', '\x00', 'S', 'a', 't', 'u', + 'r', 'd', 'a', 'y', '\x00', 'J', 'a', 'n', + '\x00', 'F', 'e', 'b', '\x00', 'M', 'a', 'r', + '\x00', 'A', 'p', 'r', '\x00', 'M', 'a', 'y', + '\x00', 'J', 'u', 'n', '\x00', 'J', 'u', 'l', + '\x00', 'A', 'u', 'g', '\x00', 'S', 'e', 'p', + '\x00', 'O', 'c', 't', '\x00', 'N', 'o', 'v', + '\x00', 'D', 'e', 'c', '\x00', 'J', 'a', 'n', + 'u', 'a', 'r', 'y', '\x00', 'F', 'e', 'b', + 'r', 'u', 'a', 'r', 'y', '\x00', 'M', 'a', + 'r', 'c', 'h', '\x00', 'A', 'p', 'r', 'i', + 'l', '\x00', 'M', 'a', 'y', '\x00', 'J', 'u', + 'n', 'e', '\x00', 'J', 'u', 'l', 'y', '\x00', + 'A', 'u', 'g', 'u', 's', 't', '\x00', 'S', + 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', + '\x00', 'O', 'c', 't', 'o', 'b', 'e', 'r', + '\x00', 'N', 'o', 'v', 'e', 'm', 'b', 'e', + 'r', '\x00', 'D', 'e', 'c', 'e', 'm', 'b', + 'e', 'r', '\x00', 'A', 'M', '\x00', 'P', 'M', + '\x00', '%', 'a', ' ', '%', 'b', ' ', '%', + 'e', ' ', '%', 'H', ':', '%', 'M', ':', + '%', 'S', ' ', '%', 'Y', '\x00', '%', 'm', + '/', '%', 'd', '/', '%', 'y', '\x00', '%', + 'H', ':', '%', 'M', ':', '%', 'S', '\x00', + '%', 'I', ':', '%', 'M', ':', '%', 'S', + ' ', '%', 'p', '\x00', '^', '[', 'y', 'Y', + ']', '\x00', '^', '[', 'n', 'N', ']', '\x00', +}; + +libc_hidden_proto(nl_langinfo) +char *nl_langinfo(nl_item item) +{ + unsigned int c; + unsigned int i; + + if ((c = _NL_ITEM_CATEGORY(item)) < C_LC_ALL) { + if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) { +/* return (char *) C_locale_data + item_offset[i] + (i & 64); */ + return (char *) C_locale_data + nl_data[C_LC_ALL+1+i] + 2*(i & 64); + } + } + return (char *) cat_start; /* Conveniently, this is the empty string. */ +} +libc_hidden_def(nl_langinfo) + +#else /* __LOCALE_C_ONLY */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +libc_hidden_proto(nl_langinfo) + +libc_hidden_proto(nl_langinfo_l) + +char *nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __UCLIBC_CURLOCALE); +} +libc_hidden_def(nl_langinfo) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +libc_hidden_proto(__XL_NPP(nl_langinfo)) + +static const char empty[] = ""; + +char *__XL_NPP(nl_langinfo)(nl_item item __LOCALE_PARAM ) +{ + unsigned int c = _NL_ITEM_CATEGORY(item); + unsigned int i = _NL_ITEM_INDEX(item); + + if ((c < LC_ALL) && (i < __LOCALE_PTR->category_item_count[c])) { + return ((char **)(((char *) __LOCALE_PTR) + + __LOCALE_PTR->category_offsets[c]))[i]; + } + + return (char *) empty; +} +libc_hidden_def(__XL_NPP(nl_langinfo)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* __LOCALE_C_ONLY */ + +#endif +/**********************************************************************/ +#ifdef L_newlocale + +/* Experimentally off - libc_hidden_proto(stpcpy) */ +libc_hidden_proto(newlocale) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move posix and utf8 strings. +#endif +static const char posix[] = "POSIX"; +static const char utf8[] = "UTF-8"; + +static int find_locale(int category_mask, const char *p, + unsigned char *new_locale) +{ + int i; + const unsigned char *s; + uint16_t n; + unsigned char lang_cult, codeset; + +#if defined(__LOCALE_DATA_AT_MODIFIERS_LENGTH) && 1 + /* Support standard locale handling for @-modifiers. */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Fix buf size in find_locale. +#endif + char buf[18]; /* TODO: 7+{max codeset name length} */ + const char *q; + + if ((q = strchr(p,'@')) != NULL) { + if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) { + return 0; + } + /* locale name at least 5 chars long and 3rd char is '_' */ + s = LOCALE_AT_MODIFIERS; + do { + if (!strcmp(s+2, q+1)) { + break; + } + s += 2 + *s; /* TODO - fix this throughout */ + } while (*s); + if (!*s) { + return 0; + } + assert(q - p < sizeof(buf)); + memcpy(buf, p, q-p); + buf[q-p] = 0; + buf[2] = s[1]; + p = buf; + } +#endif + + lang_cult = codeset = 0; /* Assume C and default codeset. */ + if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) { + goto FIND_LOCALE; + } + + if ((strlen(p) > 5) && (p[5] == '.')) { /* Codeset in locale name? */ + /* TODO: maybe CODESET_LIST + *s ??? */ + /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */ + codeset = 2; + if (strcasecmp(utf8,p+6) != 0) {/* TODO - fix! */ + s = CODESET_LIST; + do { + ++codeset; /* Increment codeset first. */ + if (!strcmp(CODESET_LIST+*s, p+6)) { + goto FIND_LANG_CULT; + } + } while (*++s); + return 0; /* No matching codeset! */ + } + } + + FIND_LANG_CULT: /* Find language_culture number. */ + s = LOCALE_NAMES; + do { /* TODO -- do a binary search? */ + /* TODO -- fix gen_mmap!*/ + ++lang_cult; /* Increment first since C/POSIX is 0. */ + if (!strncmp(s,p,5)) { /* Found a matching locale name; */ + goto FIND_LOCALE; + } + s += 5; + } while (lang_cult < __LOCALE_DATA_NUM_LOCALE_NAMES); + return 0; /* No matching language_culture! */ + + FIND_LOCALE: /* Find locale row matching name and codeset */ + s = LOCALES; + n = 0; + do { /* TODO -- do a binary search? */ + if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) { + i = 1; + s = new_locale + 1; + do { + if (category_mask & i) { + /* Encode current locale row number. */ + ((unsigned char *) s)[0] = (n >> 7) | 0x80; + ((unsigned char *) s)[1] = (n & 0x7f) | 0x80; + } + s += 2; + i += i; + } while (i < (1 << LC_ALL)); + + return i; /* Return non-zero */ + } + s += __LOCALE_DATA_WIDTH_LOCALES; + ++n; + } while (n <= __LOCALE_DATA_NUM_LOCALES); /* We started at 1!!! */ + + return 0; /* Unsupported locale. */ +} + +static unsigned char *composite_locale(int category_mask, const char *locale, + unsigned char *new_locale) +{ + char buf[MAX_LOCALE_STR]; + char *t; + char *e; + int c; + int component_mask; + + if (!strchr(locale,'=')) { + if (!find_locale(category_mask, locale, new_locale)) { + return NULL; + } + return new_locale; + } + + if (strlen(locale) >= sizeof(buf)) { + return NULL; + } + stpcpy(buf, locale); + + component_mask = 0; + t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */ + do { + c = 0; + while (strcmp(CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) { + if (++c == LC_ALL) { /* Unknown category name! */ + return NULL; + } + } + t = strtok_r(NULL, ";", &e); + c = (1 << c); + if (component_mask & c) { /* Multiple components for one category. */ + return NULL; + } + component_mask |= c; + if ((category_mask & c) && (!t || !find_locale(c, t, new_locale))) { + return NULL; + } + } while ((t = strtok_r(NULL, "=", &e)) != NULL); + + if (category_mask & ~component_mask) { /* Category component(s) missing. */ + return NULL; + } + + return new_locale; +} + +__locale_t newlocale(int category_mask, const char *locale, __locale_t base) +{ + const unsigned char *p; + int i, j, k; + unsigned char new_selector[LOCALE_SELECTOR_SIZE]; + + if (category_mask == (1 << LC_ALL)) { + category_mask = LC_ALL_MASK; + } + + if (!locale || (((unsigned int)(category_mask)) > LC_ALL_MASK)) { + INVALID: + __set_errno(EINVAL); + return NULL; /* No locale or illegal/unsupported category. */ + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Rename cur_locale to locale_selector. +#endif + strcpy((char *) new_selector, + (base ? (char *) base->cur_locale : C_LOCALE_SELECTOR)); + + if (!*locale) { /* locale == "", so check environment. */ +#ifndef __UCLIBC_HAS_THREADS__ + static /* If no threads, then envstr can be static. */ +#endif /* __UCLIBC_HAS_THREADS__ */ + const char *envstr[4] = { "LC_ALL", NULL, "LANG", posix }; + + i = 1; + k = 0; + do { + if (category_mask & i) { + /* Note: SUSv3 doesn't define a fallback mechanism here. + * So, if LC_ALL is invalid, we do _not_ continue trying + * the other environment vars. */ + envstr[1] = CATEGORY_NAMES + CATEGORY_NAMES[k]; + j = 0; + do { + p = envstr[j]; + } while ((++j < 4) && (!(p = getenv(p)) || !*p)); + + + /* The user set something... is it valid? */ + /* Note: Since we don't support user-supplied locales and + * alternate paths, we don't need to worry about special + * handling for suid/sgid apps. */ + if (!find_locale(i, p, new_selector)) { + goto INVALID; + } + } + i += i; + } while (++k < LC_ALL); + } else if (!composite_locale(category_mask, locale, new_selector)) { + goto INVALID; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Do a compatible codeset check! +#endif + + /* If we get here, the new selector corresponds to a valid locale. */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Probably want a _locale_new func to allow for caching of locales. +#endif +#if 0 + if (base) { + _locale_set_l(new_selector, base); + } else { + base = _locale_new(new_selector); + } +#else + if (!base) { + if ((base = malloc(sizeof(__uclibc_locale_t))) == NULL) { + return base; + } + _locale_init_l(base); + } + + _locale_set_l(new_selector, base); +#endif + + return base; +} +libc_hidden_def(newlocale) + +#endif +/**********************************************************************/ +#ifdef L_duplocale + +libc_hidden_proto(duplocale) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: When we allocate ctype tables, remember to dup them. +#endif + +__locale_t duplocale(__locale_t dataset) +{ + __locale_t r; + uint16_t * i2w; + size_t n; + + assert(dataset != LC_GLOBAL_LOCALE); + + if ((r = malloc(sizeof(__uclibc_locale_t))) != NULL) { + n = 2*dataset->collate.max_col_index+2; + if ((i2w = calloc(n, sizeof(uint16_t))) + != NULL + ) { + memcpy(r, dataset, sizeof(__uclibc_locale_t)); + r->collate.index2weight = i2w; + memcpy(i2w, dataset->collate.index2weight, n * sizeof(uint16_t)); + } else { + free(r); + r = NULL; + } + } + return r; +} +libc_hidden_def(duplocale) + +#endif +/**********************************************************************/ +#ifdef L_freelocale + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: When we allocate ctype tables, remember to free them. +#endif + +void freelocale(__locale_t dataset) +{ + assert(dataset != __global_locale); + assert(dataset != LC_GLOBAL_LOCALE); + + free(dataset->collate.index2weight); /* Free collation data. */ + free(dataset); /* Free locale */ +} + +#endif +/**********************************************************************/ +#ifdef L_uselocale + +libc_hidden_proto(uselocale) +__locale_t uselocale(__locale_t dataset) +{ + __locale_t old; + + if (!dataset) { + old = __UCLIBC_CURLOCALE; + } else { + if (dataset == LC_GLOBAL_LOCALE) { + dataset = __global_locale; + } +#ifdef __UCLIBC_HAS_THREADS__ + old = __curlocale_set(dataset); +#else + old = __curlocale_var; + __curlocale_var = dataset; +#endif + } + + if (old == __global_locale) { + return LC_GLOBAL_LOCALE; + } + return old; +} +libc_hidden_def(uselocale) + +#endif +/**********************************************************************/ +#ifdef L___curlocale + +#ifdef __UCLIBC_HAS_THREADS__ + +__locale_t weak_const_function __curlocale(void) +{ + return __curlocale_var; /* This is overriden by the thread version. */ +} + +__locale_t weak_function __curlocale_set(__locale_t newloc) +{ + __locale_t oldloc = __curlocale_var; + assert(newloc != LC_GLOBAL_LOCALE); + __curlocale_var = newloc; + return oldloc; +} + +#endif + +#endif +/**********************************************************************/ +#ifdef L___locale_mbrtowc_l + +/* NOTE: This returns an int... not size_t. Also, it is not a general + * routine. It is actually a very stripped-down version of mbrtowc + * that takes a __locale_t arg. This is used by strcoll and strxfrm. + * It is also used above to generate wchar_t versions of the decimal point + * and thousands seperator. */ + + +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#warning __CTYPE_HAS_8_BIT_LOCALES not set! +#endif + +#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT +#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN + +extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) attribute_hidden; + +int attribute_hidden __locale_mbrtowc_l(wchar_t *__restrict dst, + const char *__restrict src, + __locale_t loc ) +{ +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (loc->encoding == __ctype_encoding_utf8) { + mbstate_t ps; + const char *p = src; + size_t r; + ps.__mask = 0; + r = _wchar_utf8sntowcs(dst, 1, &p, SIZE_MAX, &ps, 1); + return (r == 1) ? (p-src) : r; /* Need to return 0 if nul char. */ + } +#endif + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + assert((loc->encoding == __ctype_encoding_7_bit) || (loc->encoding == __ctype_encoding_8_bit)); +#else + assert(loc->encoding == __ctype_encoding_7_bit); +#endif + + if ((*dst = ((unsigned char)(*src))) < 0x80) { /* ASCII... */ + return (*src != 0); + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (loc->encoding == __ctype_encoding_8_bit) { + wchar_t wc = *dst - 0x80; + *dst = loc->tbl8c2wc[ + (loc->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (*dst) { + return 1; + } + } +#endif + + return -1; +} + +#endif +/**********************************************************************/ diff --git a/libc/misc/locale/localeconv.c b/libc/misc/locale/localeconv.c new file mode 100644 index 0000000..7e67fb2 --- /dev/null +++ b/libc/misc/locale/localeconv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localeconv +#include "locale.c" diff --git a/libc/misc/locale/newlocale.c b/libc/misc/locale/newlocale.c new file mode 100644 index 0000000..a986884 --- /dev/null +++ b/libc/misc/locale/newlocale.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_newlocale +#include "locale.c" diff --git a/libc/misc/locale/nl_langinfo.c b/libc/misc/locale/nl_langinfo.c new file mode 100644 index 0000000..0bc0a00 --- /dev/null +++ b/libc/misc/locale/nl_langinfo.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_nl_langinfo +#include "locale.c" diff --git a/libc/misc/locale/nl_langinfo_l.c b/libc/misc/locale/nl_langinfo_l.c new file mode 100644 index 0000000..7205cca --- /dev/null +++ b/libc/misc/locale/nl_langinfo_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_nl_langinfo_l +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/libc/misc/locale/setlocale.c b/libc/misc/locale/setlocale.c new file mode 100644 index 0000000..1eae88a --- /dev/null +++ b/libc/misc/locale/setlocale.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_setlocale +#include "locale.c" diff --git a/libc/misc/locale/uselocale.c b/libc/misc/locale/uselocale.c new file mode 100644 index 0000000..2aecc54 --- /dev/null +++ b/libc/misc/locale/uselocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_uselocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/libc/misc/mntent/.indent.pro b/libc/misc/mntent/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/mntent/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/mntent/Makefile b/libc/misc/mntent/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/mntent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/mntent/Makefile.in b/libc/misc/mntent/Makefile.in new file mode 100644 index 0000000..36cbe67 --- /dev/null +++ b/libc/misc/mntent/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := mntent.c + +MISC_MNTENT_DIR := $(top_srcdir)libc/misc/mntent +MISC_MNTENT_OUT := $(top_builddir)libc/misc/mntent + +MISC_MNTENT_SRC := $(MISC_MNTENT_DIR)/mntent.c +MISC_MNTENT_OBJ := $(MISC_MNTENT_OUT)/mntent.o + +libc-y += $(MISC_MNTENT_OBJ) + +objclean-y += misc_mntent_clean + +misc_mntent_clean: + $(do_rm) $(addprefix $(MISC_MNTENT_OUT)/*., o os) diff --git a/libc/misc/mntent/mntent.c b/libc/misc/mntent/mntent.c new file mode 100644 index 0000000..4d23aef --- /dev/null +++ b/libc/misc/mntent/mntent.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +libc_hidden_proto(getmntent_r) +libc_hidden_proto(setmntent) +libc_hidden_proto(endmntent) + +/* Experimentally off - libc_hidden_proto(strstr) */ +/* Experimentally off - libc_hidden_proto(strtok_r) */ +libc_hidden_proto(atoi) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(fseek) +libc_hidden_proto(fgets) +libc_hidden_proto(abort) +libc_hidden_proto(fprintf) + +/* Reentrant version of getmntent. */ +struct mntent *getmntent_r (FILE *filep, + struct mntent *mnt, char *buff, int bufsize) +{ + static const char sep[] = " \t\n"; + + char *cp, *ptrptr; + + if (!filep || !mnt || !buff) + return NULL; + + /* Loop on the file, skipping comment lines. - FvK 03/07/93 */ + while ((cp = fgets(buff, bufsize, filep)) != NULL) { + if (buff[0] == '#' || buff[0] == '\n') + continue; + break; + } + + /* At the EOF, the buffer should be unchanged. We should + * check the return value from fgets (). + */ + if (cp == NULL) + return NULL; + + ptrptr = 0; + mnt->mnt_fsname = strtok_r(buff, sep, &ptrptr); + if (mnt->mnt_fsname == NULL) + return NULL; + + mnt->mnt_dir = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_dir == NULL) + return NULL; + + mnt->mnt_type = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_type == NULL) + return NULL; + + mnt->mnt_opts = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_opts == NULL) + mnt->mnt_opts = ""; + + cp = strtok_r(NULL, sep, &ptrptr); + mnt->mnt_freq = (cp != NULL) ? atoi(cp) : 0; + + cp = strtok_r(NULL, sep, &ptrptr); + mnt->mnt_passno = (cp != NULL) ? atoi(cp) : 0; + + return mnt; +} +libc_hidden_def(getmntent_r) + +struct mntent *getmntent(FILE * filep) +{ + struct mntent *tmp; + static char *buff = NULL; + static struct mntent mnt; + __UCLIBC_MUTEX_LOCK(mylock); + + if (!buff) { + buff = malloc(BUFSIZ); + if (!buff) + abort(); + } + + tmp = getmntent_r(filep, &mnt, buff, BUFSIZ); + __UCLIBC_MUTEX_UNLOCK(mylock); + return(tmp); +} + +int addmntent(FILE * filep, const struct mntent *mnt) +{ + if (fseek(filep, 0, SEEK_END) < 0) + return 1; + + return (fprintf (filep, "%s %s %s %s %d %d\n", mnt->mnt_fsname, mnt->mnt_dir, + mnt->mnt_type, mnt->mnt_opts, mnt->mnt_freq, mnt->mnt_passno) < 0 ? 1 : 0); +} + +char *hasmntopt(const struct mntent *mnt, const char *opt) +{ + return strstr(mnt->mnt_opts, opt); +} + +FILE *setmntent(const char *name, const char *mode) +{ + return fopen(name, mode); +} +libc_hidden_def(setmntent) + +int endmntent(FILE * filep) +{ + if (filep != NULL) + fclose(filep); + return 1; +} +libc_hidden_def(endmntent) diff --git a/libc/misc/pthread/Makefile b/libc/misc/pthread/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/pthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/pthread/Makefile.in b/libc/misc/pthread/Makefile.in new file mode 100644 index 0000000..68e17e9 --- /dev/null +++ b/libc/misc/pthread/Makefile.in @@ -0,0 +1,17 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +MISC_PTHREAD_DIR := $(top_srcdir)libc/misc/pthread +MISC_PTHREAD_OUT := $(top_builddir)libc/misc/pthread + +libc-$(UCLIBC_HAS_THREADS) += $(MISC_PTHREAD_OUT)/unlock.o +libc-$(UCLIBC_HAS_THREADS) += $(MISC_PTHREAD_OUT)/weaks.o + +objclean-y += misc_pthread_clean + +misc_pthread_clean: + $(do_rm) $(addprefix $(MISC_PTHREAD_OUT)/*., o os oS) diff --git a/libc/misc/pthread/unlock.c b/libc/misc/pthread/unlock.c new file mode 100644 index 0000000..04de0df --- /dev/null +++ b/libc/misc/pthread/unlock.c @@ -0,0 +1,27 @@ +/* The weak pthread functions for Linux. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +void attribute_hidden __uclibc_mutex_unlock (void *arg) +{ + pthread_mutex_t *__mutex = (pthread_mutex_t *)arg; + __pthread_mutex_unlock(__mutex); +} diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c new file mode 100644 index 0000000..580c3eb --- /dev/null +++ b/libc/misc/pthread/weaks.c @@ -0,0 +1,44 @@ +/* The weak pthread functions for Linux. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +/* Weaks for internal library use only. + * + * We need to define weaks here to cover all the pthread functions that + * libc itself will use so that we aren't forced to link libc against + * libpthread. This file is only used in libc.a and since we have + * weaks here, they will be automatically overridden by libpthread.a + * if it gets linked in. + */ + +static int __pthread_return_0 (void) { return 0; } +static void __pthread_return_void (void) { return; } + +weak_alias (__pthread_return_0, __pthread_mutex_init) +weak_alias (__pthread_return_0, __pthread_mutex_lock) +weak_alias (__pthread_return_0, __pthread_mutex_trylock) +weak_alias (__pthread_return_0, __pthread_mutex_unlock) +weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) +weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +weak_alias (__pthread_return_0, __pthread_mutexattr_init) +weak_alias (__pthread_return_0, __pthread_mutexattr_destroy) +weak_alias (__pthread_return_0, __pthread_mutexattr_settype) +#endif diff --git a/libc/misc/regex/.indent.pro b/libc/misc/regex/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/regex/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/regex/Makefile b/libc/misc/regex/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/regex/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/regex/Makefile.in b/libc/misc/regex/Makefile.in new file mode 100644 index 0000000..4a2e53f --- /dev/null +++ b/libc/misc/regex/Makefile.in @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifeq ($(UCLIBC_HAS_REGEX_OLD),y) +CSRC := regex_old.c +else +CSRC := regex.c +endif + +MISC_REGEX_DIR := $(top_srcdir)libc/misc/regex +MISC_REGEX_OUT := $(top_builddir)libc/misc/regex + +MISC_REGEX_SRC := $(patsubst %.c,$(MISC_REGEX_DIR)/%.c,$(CSRC)) +MISC_REGEX_OBJ := $(patsubst %.c,$(MISC_REGEX_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_REGEX) += $(MISC_REGEX_OBJ) + +objclean-y += misc_regex_clean + +misc_regex_clean: + $(do_rm) $(addprefix $(MISC_REGEX_OUT)/*., o os) diff --git a/libc/misc/regex/_regex.h b/libc/misc/regex/_regex.h new file mode 100644 index 0000000..01bb211 --- /dev/null +++ b/libc/misc/regex/_regex.h @@ -0,0 +1,45 @@ +/* this file is copied from libc/include/regex.h */ + +#ifndef _REGEX_H +#include + +/* Document internal interfaces. */ +extern reg_syntax_t __re_set_syntax (reg_syntax_t syntax) attribute_hidden; + +extern const char *__re_compile_pattern (const char *pattern, size_t length, + struct re_pattern_buffer *buffer) attribute_hidden; + +extern int __re_compile_fastmap (struct re_pattern_buffer *buffer) attribute_hidden; + +extern int __re_search (struct re_pattern_buffer *buffer, const char *string, + int length, int start, int range, + struct re_registers *regs) attribute_hidden; + +extern int __re_search_2 + (struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop) attribute_hidden; + +extern int __re_match + (struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs) attribute_hidden; + +extern int __re_match_2 + (struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int stop) attribute_hidden; + +extern void __re_set_registers + (struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends) attribute_hidden; + +extern int __regcomp (regex_t *__preg, const char *__pattern, int __cflags) attribute_hidden; + +extern int __regexec (const regex_t *__preg, const char *__string, + size_t __nmatch, regmatch_t __pmatch[], int __eflags) attribute_hidden; + +extern size_t __regerror (int __errcode, const regex_t *__preg, + char *__errbuf, size_t __errbuf_size) attribute_hidden; + +extern void __regfree (regex_t *__preg) attribute_hidden; +#endif diff --git a/libc/misc/regex/regcomp.c b/libc/misc/regex/regcomp.c new file mode 100644 index 0000000..210ae05 --- /dev/null +++ b/libc/misc/regex/regcomp.c @@ -0,0 +1,3808 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, + size_t length, reg_syntax_t syntax); +static void re_compile_fastmap_iter (regex_t *bufp, + const re_dfastate_t *init_state, + char *fastmap); +static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); +#ifdef RE_ENABLE_I18N +static void free_charset (re_charset_t *cset); +#endif /* RE_ENABLE_I18N */ +static void free_workarea_compile (regex_t *preg); +static reg_errcode_t create_initial_state (re_dfa_t *dfa); +#ifdef RE_ENABLE_I18N +static void optimize_utf8 (re_dfa_t *dfa); +#endif +static reg_errcode_t analyze (regex_t *preg); +static reg_errcode_t preorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t postorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); +static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); +static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, + bin_tree_t *node); +static reg_errcode_t calc_first (void *extra, bin_tree_t *node); +static reg_errcode_t calc_next (void *extra, bin_tree_t *node); +static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); +static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint); +static int search_duplicated_node (const re_dfa_t *dfa, int org_node, + unsigned int constraint); +static reg_errcode_t calc_eclosure (re_dfa_t *dfa); +static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, + int node, int root); +static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); +static int fetch_number (re_string_t *input, re_token_t *token, + reg_syntax_t syntax); +static int peek_token (re_token_t *token, re_string_t *input, + reg_syntax_t syntax) internal_function; +static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, + re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, + reg_errcode_t *err); +static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token, int token_len, + re_dfa_t *dfa, + reg_syntax_t syntax, + int accept_hyphen); +static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token); +#ifdef RE_ENABLE_I18N +static reg_errcode_t build_equiv_class (bitset_t sbcset, + re_charset_t *mbcset, + int *equiv_class_alloc, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + re_charset_t *mbcset, + int *char_class_alloc, + const unsigned char *class_name, + reg_syntax_t syntax); +#else /* not RE_ENABLE_I18N */ +static reg_errcode_t build_equiv_class (bitset_t sbcset, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + const unsigned char *class_name, + reg_syntax_t syntax); +#endif /* not RE_ENABLE_I18N */ +static bin_tree_t *build_charclass_op (re_dfa_t *dfa, + RE_TRANSLATE_TYPE trans, + const unsigned char *class_name, + const unsigned char *extra, + int non_match, reg_errcode_t *err); +static bin_tree_t *create_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + re_token_type_t type); +static bin_tree_t *create_token_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + const re_token_t *token); +static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); +static void free_token (re_token_t *node); +static reg_errcode_t free_tree (void *extra, bin_tree_t *node); +static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +const char __re_error_msgid[] attribute_hidden = + { +#define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ + "\0" +#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +const size_t __re_error_msgid_idx[] attribute_hidden = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length LENGTH) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. */ + +const char * +re_compile_pattern (pattern, length, bufp) + const char *pattern; + size_t length; + struct re_pattern_buffer *bufp; +{ + reg_errcode_t ret; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub, unless RE_NO_SUB is set. */ + bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = re_compile_internal (bufp, pattern, length, re_syntax_options); + + if (!ret) + return NULL; + return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_compile_pattern, re_compile_pattern) +#endif + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (syntax) + reg_syntax_t syntax; +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_set_syntax, re_set_syntax) +#endif + +int +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + char *fastmap = bufp->fastmap; + + memset (fastmap, '\0', sizeof (char) * SBC_MAX); + re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); + if (dfa->init_state != dfa->init_state_word) + re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); + if (dfa->init_state != dfa->init_state_nl) + re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); + if (dfa->init_state != dfa->init_state_begbuf) + re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); + bufp->fastmap_accurate = 1; + return 0; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_compile_fastmap, re_compile_fastmap) +#endif + +static __inline__ void +__attribute ((always_inline)) +re_set_fastmap (char *fastmap, int icase, int ch) +{ + fastmap[ch] = 1; + if (icase) + fastmap[__tolower (ch)] = 1; +} + +/* Helper function for re_compile_fastmap. + Compile fastmap for the initial_state INIT_STATE. */ + +static void +re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + char *fastmap) +{ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + int node_cnt; + int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); + for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) + { + int node = init_state->nodes.elems[node_cnt]; + re_token_type_t type = dfa->nodes[node].type; + + if (type == CHARACTER) + { + re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); +#ifdef RE_ENABLE_I18N + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + unsigned char *buf = alloca (dfa->mb_cur_max), *p; + wchar_t wc; + mbstate_t state; + + p = buf; + *p++ = dfa->nodes[node].opr.c; + while (++node < dfa->nodes_len + && dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].mb_partial) + *p++ = dfa->nodes[node].opr.c; + memset (&state, '\0', sizeof (state)); + if (mbrtowc (&wc, (const char *) buf, p - buf, + &state) == p - buf + && (__wcrtomb ((char *) buf, towlower (wc), &state) + != (size_t) -1)) + re_set_fastmap (fastmap, 0, buf[0]); + } +#endif + } + else if (type == SIMPLE_BRACKET) + { + int i, ch; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + { + int j; + bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (w & ((bitset_word_t) 1 << j)) + re_set_fastmap (fastmap, icase, ch); + } + } +#ifdef RE_ENABLE_I18N + else if (type == COMPLEX_BRACKET) + { + int i; + re_charset_t *cset = dfa->nodes[node].opr.mbcset; + if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes + || cset->nranges || cset->nchar_classes) + { +# ifdef _LIBC + if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) + { + /* In this case we want to catch the bytes which are + the first byte of any collation elements. + e.g. In da_DK, we want to catch 'a' since "aa" + is a valid collation element, and don't catch + 'b' since 'b' is the only collation element + which starts from 'b'. */ + const int32_t *table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + for (i = 0; i < SBC_MAX; ++i) + if (table[i] < 0) + re_set_fastmap (fastmap, icase, i); + } +# else + if (dfa->mb_cur_max > 1) + for (i = 0; i < SBC_MAX; ++i) + if (__btowc (i) == WEOF) + re_set_fastmap (fastmap, icase, i); +# endif /* not _LIBC */ + } + for (i = 0; i < cset->nmbchars; ++i) + { + char buf[256]; + mbstate_t state; + memset (&state, '\0', sizeof (state)); + if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) + re_set_fastmap (fastmap, icase, *(unsigned char *) buf); + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) + != (size_t) -1) + re_set_fastmap (fastmap, 0, *(unsigned char *) buf); + } + } + } +#endif /* RE_ENABLE_I18N */ + else if (type == OP_PERIOD +#ifdef RE_ENABLE_I18N + || type == OP_UTF8_PERIOD +#endif /* RE_ENABLE_I18N */ + || type == END_OF_RE) + { + memset (fastmap, '\1', sizeof (char) * SBC_MAX); + if (type == END_OF_RE) + bufp->can_be_null = 1; + return; + } + } +} + +/* Entry point for POSIX code. */ +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' to an allocated space for the fastmap; + `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp (preg, pattern, cflags) + regex_t *__restrict preg; + const char *__restrict pattern; + int cflags; +{ + reg_errcode_t ret; + reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED + : RE_SYNTAX_POSIX_BASIC); + + preg->buffer = NULL; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = re_malloc (char, SBC_MAX); + if (BE (preg->fastmap == NULL, 0)) + return REG_ESPACE; + + syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + preg->no_sub = !!(cflags & REG_NOSUB); + preg->translate = NULL; + + ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) + ret = REG_EPAREN; + + /* We have already checked preg->fastmap != NULL. */ + if (BE (ret == REG_NOERROR, 1)) + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. This function never fails in this implementation. */ + (void) re_compile_fastmap (preg); + else + { + /* Some error occurred while compiling the expression. */ + re_free (preg->fastmap); + preg->fastmap = NULL; + } + + return (int) ret; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regcomp, regcomp) +#endif + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (errcode, preg, errbuf, errbuf_size) + int errcode; + const regex_t *__restrict preg; + char *__restrict errbuf; + size_t errbuf_size; +{ + const char *msg; + size_t msg_size; + + if (BE (errcode < 0 + || errcode >= (int) (sizeof (__re_error_msgid_idx) + / sizeof (__re_error_msgid_idx[0])), 0)) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (BE (errbuf_size != 0, 1)) + { + if (BE (msg_size > errbuf_size, 0)) + { +#if (defined HAVE_MEMPCPY || defined _LIBC) && defined __USE_GNU + *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; +#else + memcpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; +#endif + } + else + memcpy (errbuf, msg, msg_size); + } + + return msg_size; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regerror, regerror) +#endif + + +#ifdef RE_ENABLE_I18N +/* This static array is used for the map to single-byte characters when + UTF-8 is used. Otherwise we would allocate memory just to initialize + it the same all the time. UTF-8 is the preferred encoding so this is + a worthwhile optimization. */ +static const bitset_t utf8_sb_map = +{ + /* Set the first 128 bits. */ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +}; +#endif + + +static void +free_dfa_content (re_dfa_t *dfa) +{ + int i, j; + + if (dfa->nodes) + for (i = 0; i < dfa->nodes_len; ++i) + free_token (dfa->nodes + i); + re_free (dfa->nexts); + for (i = 0; i < dfa->nodes_len; ++i) + { + if (dfa->eclosures != NULL) + re_node_set_free (dfa->eclosures + i); + if (dfa->inveclosures != NULL) + re_node_set_free (dfa->inveclosures + i); + if (dfa->edests != NULL) + re_node_set_free (dfa->edests + i); + } + re_free (dfa->edests); + re_free (dfa->eclosures); + re_free (dfa->inveclosures); + re_free (dfa->nodes); + + if (dfa->state_table) + for (i = 0; i <= dfa->state_hash_mask; ++i) + { + struct re_state_table_entry *entry = dfa->state_table + i; + for (j = 0; j < entry->num; ++j) + { + re_dfastate_t *state = entry->array[j]; + free_state (state); + } + re_free (entry->array); + } + re_free (dfa->state_table); +#ifdef RE_ENABLE_I18N + if (dfa->sb_char != utf8_sb_map) + re_free (dfa->sb_char); +#endif + re_free (dfa->subexp_map); +#ifdef DEBUG + re_free (dfa->re_str); +#endif + + re_free (dfa); +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (preg) + regex_t *preg; +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + if (BE (dfa != NULL, 1)) + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + + re_free (preg->fastmap); + preg->fastmap = NULL; + + re_free (preg->translate); + preg->translate = NULL; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regfree, regfree) +#endif + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC || defined __UCLIBC__ + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +# if defined _LIBC || defined __UCLIBC__ +/* Make these definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec above without link errors. */ +weak_function +# endif +re_comp (s) + const char *s; +{ + reg_errcode_t ret; + char *fastmap; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (re_comp_buf.buffer) + { + fastmap = re_comp_buf.fastmap; + re_comp_buf.fastmap = NULL; + __regfree (&re_comp_buf); + memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); + re_comp_buf.fastmap = fastmap; + } + + if (re_comp_buf.fastmap == NULL) + { + re_comp_buf.fastmap = (char *) malloc (SBC_MAX); + if (re_comp_buf.fastmap == NULL) + return (char *) gettext (__re_error_msgid + + __re_error_msgid_idx[(int) REG_ESPACE]); + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + + ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); + + if (!ret) + return NULL; + + /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} + +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + __regfree (&re_comp_buf); +} +#endif + +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. + Compile the regular expression PATTERN, whose length is LENGTH. + SYNTAX indicate regular expression's syntax. */ + +static reg_errcode_t +re_compile_internal (regex_t *preg, const char * pattern, size_t length, + reg_syntax_t syntax) +{ + reg_errcode_t err = REG_NOERROR; + re_dfa_t *dfa; + re_string_t regexp; + + /* Initialize the pattern buffer. */ + preg->fastmap_accurate = 0; + preg->syntax = syntax; + preg->not_bol = preg->not_eol = 0; + preg->used = 0; + preg->re_nsub = 0; + preg->can_be_null = 0; + preg->regs_allocated = REGS_UNALLOCATED; + + /* Initialize the dfa. */ + dfa = (re_dfa_t *) preg->buffer; + if (BE (preg->allocated < sizeof (re_dfa_t), 0)) + { + /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. If ->buffer is NULL this + is a simple allocation. */ + dfa = re_realloc (preg->buffer, re_dfa_t, 1); + if (dfa == NULL) + return REG_ESPACE; + preg->allocated = sizeof (re_dfa_t); + preg->buffer = (unsigned char *) dfa; + } + preg->used = sizeof (re_dfa_t); + + err = init_dfa (dfa, length); + if (BE (err != REG_NOERROR, 0)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } +#ifdef DEBUG + /* Note: length+1 will not overflow since it is checked in init_dfa. */ + dfa->re_str = re_malloc (char, length + 1); + strncpy (dfa->re_str, pattern, length + 1); +#endif + + __libc_lock_init (dfa->lock); + + err = re_string_construct (®exp, pattern, length, preg->translate, + syntax & RE_ICASE, dfa); + if (BE (err != REG_NOERROR, 0)) + { + re_compile_internal_free_return: + free_workarea_compile (preg); + re_string_destruct (®exp); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } + + /* Parse the regular expression, and build a structure tree. */ + preg->re_nsub = 0; + dfa->str_tree = parse (®exp, preg, syntax, &err); + if (BE (dfa->str_tree == NULL, 0)) + goto re_compile_internal_free_return; + + /* Analyze the tree and create the nfa. */ + err = analyze (preg); + if (BE (err != REG_NOERROR, 0)) + goto re_compile_internal_free_return; + +#ifdef RE_ENABLE_I18N + /* If possible, do searching in single byte encoding to speed things up. */ + if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) + optimize_utf8 (dfa); +#endif + + /* Then create the initial state of the dfa. */ + err = create_initial_state (dfa); + + /* Release work areas. */ + free_workarea_compile (preg); + re_string_destruct (®exp); + + if (BE (err != REG_NOERROR, 0)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + } + + return err; +} + +/* Initialize DFA. We use the length of the regular expression PAT_LEN + as the initial length of some arrays. */ + +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(_stdlib_mb_cur_max) +#endif + +static reg_errcode_t +init_dfa (re_dfa_t *dfa, size_t pat_len) +{ + unsigned int table_size; +#ifndef _LIBC + char *codeset_name; +#endif + + memset (dfa, '\0', sizeof (re_dfa_t)); + + /* Force allocation of str_tree_storage the first time. */ + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + + /* Avoid overflows. */ + if (pat_len == SIZE_MAX) + return REG_ESPACE; + + dfa->nodes_alloc = pat_len + 1; + dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); + + /* table_size = 2 ^ ceil(log pat_len) */ + for (table_size = 1; ; table_size <<= 1) + if (table_size > pat_len) + break; + + dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); + dfa->state_hash_mask = table_size - 1; + +#ifdef __UCLIBC_HAS_WCHAR__ + dfa->mb_cur_max = MB_CUR_MAX; +#else + dfa->mb_cur_max = 1; +#endif +#ifdef _LIBC + if (dfa->mb_cur_max == 6 + && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) + dfa->is_utf8 = 1; + dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) + != 0); +#else +# ifdef HAVE_LANGINFO_CODESET + codeset_name = nl_langinfo (CODESET); +# else + codeset_name = getenv ("LC_ALL"); + if (codeset_name == NULL || codeset_name[0] == '\0') + codeset_name = getenv ("LC_CTYPE"); + if (codeset_name == NULL || codeset_name[0] == '\0') + codeset_name = getenv ("LANG"); + if (codeset_name == NULL) + codeset_name = ""; + else if (strchr (codeset_name, '.') != NULL) + codeset_name = strchr (codeset_name, '.') + 1; +# endif + + if (strcasecmp (codeset_name, "UTF-8") == 0 + || strcasecmp (codeset_name, "UTF8") == 0) + dfa->is_utf8 = 1; + + /* We check exhaustively in the loop below if this charset is a + superset of ASCII. */ + dfa->map_notascii = 0; +#endif + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + if (dfa->is_utf8) + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; + else + { + int i, j, ch; + + dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + if (BE (dfa->sb_char == NULL, 0)) + return REG_ESPACE; + + /* Set the bits corresponding to single byte chars. */ + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + { + wint_t wch = __btowc (ch); + if (wch != WEOF) + dfa->sb_char[i] |= (bitset_word_t) 1 << j; +# ifndef _LIBC + if (isascii (ch) && wch != ch) + dfa->map_notascii = 1; +# endif + } + } + } +#endif + + if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +/* Initialize WORD_CHAR table, which indicate which character is + "word". In this case "word" means that it is the word construction + character used by some operators like "\<", "\>", etc. */ + +static void +internal_function +init_word_char (re_dfa_t *dfa) +{ + int i, j, ch; + dfa->word_ops_used = 1; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (isalnum (ch) || ch == '_') + dfa->word_char[i] |= (bitset_word_t) 1 << j; +} + +/* Free the work area which are only used while compiling. */ + +static void +free_workarea_compile (regex_t *preg) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_storage_t *storage, *next; + for (storage = dfa->str_tree_storage; storage; storage = next) + { + next = storage->next; + re_free (storage); + } + dfa->str_tree_storage = NULL; + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + dfa->str_tree = NULL; + re_free (dfa->org_indices); + dfa->org_indices = NULL; +} + +/* Create initial states for all contexts. */ + +static reg_errcode_t +create_initial_state (re_dfa_t *dfa) +{ + int first, i; + reg_errcode_t err; + re_node_set init_nodes; + + /* Initial states have the epsilon closure of the node which is + the first node of the regular expression. */ + first = dfa->str_tree->first->node_idx; + dfa->init_node = first; + err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* The back-references which are in initial states can epsilon transit, + since in this case all of the subexpressions can be null. + Then we add epsilon closures of the nodes which are the next nodes of + the back-references. */ + if (dfa->nbackref > 0) + for (i = 0; i < init_nodes.nelem; ++i) + { + int node_idx = init_nodes.elems[i]; + re_token_type_t type = dfa->nodes[node_idx].type; + + int clexp_idx; + if (type != OP_BACK_REF) + continue; + for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) + { + re_token_t *clexp_node; + clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; + if (clexp_node->type == OP_CLOSE_SUBEXP + && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) + break; + } + if (clexp_idx == init_nodes.nelem) + continue; + + if (type == OP_BACK_REF) + { + int dest_idx = dfa->edests[node_idx].elems[0]; + if (!re_node_set_contains (&init_nodes, dest_idx)) + { + re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); + i = 0; + } + } + } + + /* It must be the first time to invoke acquire_state. */ + dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); + /* We don't check ERR here, since the initial state must not be NULL. */ + if (BE (dfa->init_state == NULL, 0)) + return err; + if (dfa->init_state->has_constraint) + { + dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_WORD); + dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_NEWLINE); + dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, + &init_nodes, + CONTEXT_NEWLINE + | CONTEXT_BEGBUF); + if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL, 0)) + return err; + } + else + dfa->init_state_word = dfa->init_state_nl + = dfa->init_state_begbuf = dfa->init_state; + + re_node_set_free (&init_nodes); + return REG_NOERROR; +} + +#ifdef RE_ENABLE_I18N +/* If it is possible to do searching in single byte encoding instead of UTF-8 + to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change + DFA nodes where needed. */ + +static void +optimize_utf8 (re_dfa_t *dfa) +{ + int node, i, mb_chars = 0, has_period = 0; + + for (node = 0; node < dfa->nodes_len; ++node) + switch (dfa->nodes[node].type) + { + case CHARACTER: + if (dfa->nodes[node].opr.c >= 0x80) + mb_chars = 1; + break; + case ANCHOR: + switch (dfa->nodes[node].opr.idx) + { + case LINE_FIRST: + case LINE_LAST: + case BUF_FIRST: + case BUF_LAST: + break; + default: + /* Word anchors etc. cannot be handled. */ + return; + } + break; + case OP_PERIOD: + has_period = 1; + break; + case OP_BACK_REF: + case OP_ALT: + case END_OF_RE: + case OP_DUP_ASTERISK: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + break; + case COMPLEX_BRACKET: + return; + case SIMPLE_BRACKET: + /* Just double check. The non-ASCII range starts at 0x80. */ + assert (0x80 % BITSET_WORD_BITS == 0); + for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) + if (dfa->nodes[node].opr.sbcset[i]) + return; + break; + default: + abort (); + } + + if (mb_chars || has_period) + for (node = 0; node < dfa->nodes_len; ++node) + { + if (dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].opr.c >= 0x80) + dfa->nodes[node].mb_partial = 0; + else if (dfa->nodes[node].type == OP_PERIOD) + dfa->nodes[node].type = OP_UTF8_PERIOD; + } + + /* The search can be in single byte locale. */ + dfa->mb_cur_max = 1; + dfa->is_utf8 = 0; + dfa->has_mb_node = dfa->nbackref > 0 || has_period; +} +#endif + +/* Analyze the structure tree, and calculate "first", "next", "edest", + "eclosure", and "inveclosure". */ + +static reg_errcode_t +analyze (regex_t *preg) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + reg_errcode_t ret; + + /* Allocate arrays. */ + dfa->nexts = re_malloc (int, dfa->nodes_alloc); + dfa->org_indices = re_malloc (int, dfa->nodes_alloc); + dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); + dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); + if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL + || dfa->eclosures == NULL, 0)) + return REG_ESPACE; + + dfa->subexp_map = re_malloc (int, preg->re_nsub); + if (dfa->subexp_map != NULL) + { + int i; + for (i = 0; i < preg->re_nsub; i++) + dfa->subexp_map[i] = i; + preorder (dfa->str_tree, optimize_subexps, dfa); + for (i = 0; i < preg->re_nsub; i++) + if (dfa->subexp_map[i] != i) + break; + if (i == preg->re_nsub) + { + free (dfa->subexp_map); + dfa->subexp_map = NULL; + } + } + + ret = postorder (dfa->str_tree, lower_subexps, preg); + if (BE (ret != REG_NOERROR, 0)) + return ret; + ret = postorder (dfa->str_tree, calc_first, dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + preorder (dfa->str_tree, calc_next, dfa); + ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + ret = calc_eclosure (dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + /* We only need this during the prune_impossible_nodes pass in regexec.c; + skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ + if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) + || dfa->nbackref) + { + dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); + if (BE (dfa->inveclosures == NULL, 0)) + return REG_ESPACE; + ret = calc_inveclosure (dfa); + } + + return ret; +} + +/* Our parse trees are very unbalanced, so we cannot use a stack to + implement parse tree visits. Instead, we use parent pointers and + some hairy code in these two functions. */ +static reg_errcode_t +postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node, *prev; + + for (node = root; ; ) + { + /* Descend down the tree, preferably to the left (or to the right + if that's the only child). */ + while (node->left || node->right) + if (node->left) + node = node->left; + else + node = node->right; + + do + { + reg_errcode_t err = fn (extra, node); + if (BE (err != REG_NOERROR, 0)) + return err; + if (node->parent == NULL) + return REG_NOERROR; + prev = node; + node = node->parent; + } + /* Go up while we have a node that is reached from the right. */ + while (node->right == prev || node->right == NULL); + node = node->right; + } +} + +static reg_errcode_t +preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node; + + for (node = root; ; ) + { + reg_errcode_t err = fn (extra, node); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* Go to the left node, or up and to the right. */ + if (node->left) + node = node->left; + else + { + bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + if (!node) + return REG_NOERROR; + } + node = node->right; + } + } +} + +/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell + re_search_internal to map the inner one's opr.idx to this one's. Adjust + backreferences as well. Requires a preorder visit. */ +static reg_errcode_t +optimize_subexps (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + + if (node->token.type == OP_BACK_REF && dfa->subexp_map) + { + int idx = node->token.opr.idx; + node->token.opr.idx = dfa->subexp_map[idx]; + dfa->used_bkref_map |= 1 << node->token.opr.idx; + } + + else if (node->token.type == SUBEXP + && node->left && node->left->token.type == SUBEXP) + { + int other_idx = node->left->token.opr.idx; + + node->left = node->left->left; + if (node->left) + node->left->parent = node; + + dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; + if (other_idx < BITSET_WORD_BITS) + dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); + } + + return REG_NOERROR; +} + +/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation + of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ +static reg_errcode_t +lower_subexps (void *extra, bin_tree_t *node) +{ + regex_t *preg = (regex_t *) extra; + reg_errcode_t err = REG_NOERROR; + + if (node->left && node->left->token.type == SUBEXP) + { + node->left = lower_subexp (&err, preg, node->left); + if (node->left) + node->left->parent = node; + } + if (node->right && node->right->token.type == SUBEXP) + { + node->right = lower_subexp (&err, preg, node->right); + if (node->right) + node->right->parent = node; + } + + return err; +} + +static bin_tree_t * +lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *body = node->left; + bin_tree_t *op, *cls, *tree1, *tree; + + if (preg->no_sub + /* We do not optimize empty subexpressions, because otherwise we may + have bad CONCAT nodes with NULL children. This is obviously not + very common, so we do not lose much. An example that triggers + this case is the sed "script" /\(\)/x. */ + && node->left != NULL + && (node->token.opr.idx >= BITSET_WORD_BITS + || !(dfa->used_bkref_map + & ((bitset_word_t) 1 << node->token.opr.idx)))) + return node->left; + + /* Convert the SUBEXP node to the concatenation of an + OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ + op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); + cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); + tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; + tree = create_tree (dfa, op, tree1, CONCAT); + if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + + op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; + op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; + return tree; +} + +/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton + nodes. Requires a postorder visit. */ +static reg_errcode_t +calc_first (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + if (node->token.type == CONCAT) + { + node->first = node->left->first; + node->node_idx = node->left->node_idx; + } + else + { + node->first = node; + node->node_idx = re_dfa_add_node (dfa, node->token); + if (BE (node->node_idx == -1, 0)) + return REG_ESPACE; + } + return REG_NOERROR; +} + +/* Pass 2: compute NEXT on the tree. Preorder visit. */ +static reg_errcode_t +calc_next (void *extra, bin_tree_t *node) +{ + switch (node->token.type) + { + case OP_DUP_ASTERISK: + node->left->next = node; + break; + case CONCAT: + node->left->next = node->right->first; + node->right->next = node->next; + break; + default: + if (node->left) + node->left->next = node->next; + if (node->right) + node->right->next = node->next; + break; + } + return REG_NOERROR; +} + +/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ +static reg_errcode_t +link_nfa_nodes (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + int idx = node->node_idx; + reg_errcode_t err = REG_NOERROR; + + switch (node->token.type) + { + case CONCAT: + break; + + case END_OF_RE: + assert (node->next == NULL); + break; + + case OP_DUP_ASTERISK: + case OP_ALT: + { + int left, right; + dfa->has_plural_match = 1; + if (node->left != NULL) + left = node->left->first->node_idx; + else + left = node->next->node_idx; + if (node->right != NULL) + right = node->right->first->node_idx; + else + right = node->next->node_idx; + assert (left > -1); + assert (right > -1); + err = re_node_set_init_2 (dfa->edests + idx, left, right); + } + break; + + case ANCHOR: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); + break; + + case OP_BACK_REF: + dfa->nexts[idx] = node->next->node_idx; + if (node->token.type == OP_BACK_REF) + re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); + break; + + default: + assert (!IS_EPSILON_NODE (node->token.type)); + dfa->nexts[idx] = node->next->node_idx; + break; + } + + return err; +} + +/* Duplicate the epsilon closure of the node ROOT_NODE. + Note that duplicated nodes have constraint INIT_CONSTRAINT in addition + to their own constraint. */ + +static reg_errcode_t +internal_function +duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, + int root_node, unsigned int init_constraint) +{ + int org_node, clone_node, ret; + unsigned int constraint = init_constraint; + for (org_node = top_org_node, clone_node = top_clone_node;;) + { + int org_dest, clone_dest; + if (dfa->nodes[org_node].type == OP_BACK_REF) + { + /* If the back reference epsilon-transit, its destination must + also have the constraint. Then duplicate the epsilon closure + of the destination of the back reference, and store it in + edests of the back reference. */ + org_dest = dfa->nexts[org_node]; + re_node_set_empty (dfa->edests + clone_node); + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + dfa->nexts[clone_node] = dfa->nexts[org_node]; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + else if (dfa->edests[org_node].nelem == 0) + { + /* In case of the node can't epsilon-transit, don't duplicate the + destination and store the original destination as the + destination of the node. */ + dfa->nexts[clone_node] = dfa->nexts[org_node]; + break; + } + else if (dfa->edests[org_node].nelem == 1) + { + /* In case of the node can epsilon-transit, and it has only one + destination. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + if (dfa->nodes[org_node].type == ANCHOR) + { + /* In case of the node has another constraint, append it. */ + if (org_node == root_node && clone_node != org_node) + { + /* ...but if the node is root_node itself, it means the + epsilon closure have a loop, then tie it to the + destination of the root_node. */ + ret = re_node_set_insert (dfa->edests + clone_node, + org_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + break; + } + constraint |= dfa->nodes[org_node].opr.ctx_type; + } + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + else /* dfa->edests[org_node].nelem == 2 */ + { + /* In case of the node can epsilon-transit, and it has two + destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* Search for a duplicated node which satisfies the constraint. */ + clone_dest = search_duplicated_node (dfa, org_dest, constraint); + if (clone_dest == -1) + { + /* There are no such a duplicated node, create a new one. */ + reg_errcode_t err; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + err = duplicate_node_closure (dfa, org_dest, clone_dest, + root_node, constraint); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + { + /* There are a duplicated node which satisfy the constraint, + use it to avoid infinite loop. */ + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + + org_dest = dfa->edests[org_node].elems[1]; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + org_node = org_dest; + clone_node = clone_dest; + } + return REG_NOERROR; +} + +/* Search for a node which is duplicated from the node ORG_NODE, and + satisfies the constraint CONSTRAINT. */ + +static int +search_duplicated_node (const re_dfa_t *dfa, int org_node, + unsigned int constraint) +{ + int idx; + for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) + { + if (org_node == dfa->org_indices[idx] + && constraint == dfa->nodes[idx].constraint) + return idx; /* Found. */ + } + return -1; /* Not found. */ +} + +/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. + Return the index of the new node, or -1 if insufficient storage is + available. */ + +static int +duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint) +{ + int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); + if (BE (dup_idx != -1, 1)) + { + dfa->nodes[dup_idx].constraint = constraint; + if (dfa->nodes[org_idx].type == ANCHOR) + dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; + dfa->nodes[dup_idx].duplicated = 1; + + /* Store the index of the original node. */ + dfa->org_indices[dup_idx] = org_idx; + } + return dup_idx; +} + +static reg_errcode_t +calc_inveclosure (re_dfa_t *dfa) +{ + int src, idx, ret; + for (idx = 0; idx < dfa->nodes_len; ++idx) + re_node_set_init_empty (dfa->inveclosures + idx); + + for (src = 0; src < dfa->nodes_len; ++src) + { + int *elems = dfa->eclosures[src].elems; + for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) + { + ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); + if (BE (ret == -1, 0)) + return REG_ESPACE; + } + } + + return REG_NOERROR; +} + +/* Calculate "eclosure" for all the node in DFA. */ + +static reg_errcode_t +calc_eclosure (re_dfa_t *dfa) +{ + int node_idx, incomplete; +#ifdef DEBUG + assert (dfa->nodes_len > 0); +#endif + incomplete = 0; + /* For each nodes, calculate epsilon closure. */ + for (node_idx = 0; ; ++node_idx) + { + reg_errcode_t err; + re_node_set eclosure_elem; + if (node_idx == dfa->nodes_len) + { + if (!incomplete) + break; + incomplete = 0; + node_idx = 0; + } + +#ifdef DEBUG + assert (dfa->eclosures[node_idx].nelem != -1); +#endif + + /* If we have already calculated, skip it. */ + if (dfa->eclosures[node_idx].nelem != 0) + continue; + /* Calculate epsilon closure of `node_idx'. */ + err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (dfa->eclosures[node_idx].nelem == 0) + { + incomplete = 1; + re_node_set_free (&eclosure_elem); + } + } + return REG_NOERROR; +} + +/* Calculate epsilon closure of NODE. */ + +static reg_errcode_t +calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) +{ + reg_errcode_t err; + unsigned int constraint; + int i, incomplete; + re_node_set eclosure; + incomplete = 0; + err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* This indicates that we are calculating this node now. + We reference this value to avoid infinite loop. */ + dfa->eclosures[node].nelem = -1; + + constraint = ((dfa->nodes[node].type == ANCHOR) + ? dfa->nodes[node].opr.ctx_type : 0); + /* If the current node has constraints, duplicate all nodes. + Since they must inherit the constraints. */ + if (constraint + && dfa->edests[node].nelem + && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) + { + err = duplicate_node_closure (dfa, node, node, node, constraint); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + /* Expand each epsilon destination nodes. */ + if (IS_EPSILON_NODE(dfa->nodes[node].type)) + for (i = 0; i < dfa->edests[node].nelem; ++i) + { + re_node_set eclosure_elem; + int edest = dfa->edests[node].elems[i]; + /* If calculating the epsilon closure of `edest' is in progress, + return intermediate result. */ + if (dfa->eclosures[edest].nelem == -1) + { + incomplete = 1; + continue; + } + /* If we haven't calculated the epsilon closure of `edest' yet, + calculate now. Otherwise use calculated epsilon closure. */ + if (dfa->eclosures[edest].nelem == 0) + { + err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + eclosure_elem = dfa->eclosures[edest]; + /* Merge the epsilon closure of `edest'. */ + re_node_set_merge (&eclosure, &eclosure_elem); + /* If the epsilon closure of `edest' is incomplete, + the epsilon closure of this node is also incomplete. */ + if (dfa->eclosures[edest].nelem == 0) + { + incomplete = 1; + re_node_set_free (&eclosure_elem); + } + } + + /* Epsilon closures include itself. */ + re_node_set_insert (&eclosure, node); + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + return REG_NOERROR; +} + +/* Functions for token which are used in the parser. */ + +/* Fetch a token from INPUT. + We must not use this function inside bracket expressions. */ + +static void +internal_function +fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) +{ + re_string_skip_bytes (input, peek_token (result, input, syntax)); +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function inside bracket expressions. */ + +static int +internal_function +peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + + c = re_string_peek_byte (input, 0); + token->opr.c = c; + + token->word_char = 0; +#ifdef RE_ENABLE_I18N + token->mb_partial = 0; + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + token->mb_partial = 1; + return 1; + } +#endif + if (c == '\\') + { + unsigned char c2; + if (re_string_cur_idx (input) + 1 >= re_string_length (input)) + { + token->type = BACK_SLASH; + return 1; + } + + c2 = re_string_peek_byte_case (input, 1); + token->opr.c = c2; + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, + re_string_cur_idx (input) + 1); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (c2) != 0; + + switch (c2) + { + case '|': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (!(syntax & RE_NO_BK_REFS)) + { + token->type = OP_BACK_REF; + token->opr.idx = c2 - '1'; + } + break; + case '<': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_FIRST; + } + break; + case '>': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_LAST; + } + break; + case 'b': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_DELIM; + } + break; + case 'B': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = NOT_WORD_DELIM; + } + break; + case 'w': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_WORD; + break; + case 'W': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTWORD; + break; + case 's': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_SPACE; + break; + case 'S': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTSPACE; + break; + case '`': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_FIRST; + } + break; + case '\'': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_LAST; + } + break; + case '(': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_CLOSE_SUBEXP; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_CLOSE_DUP_NUM; + break; + default: + break; + } + return 2; + } + + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (token->opr.c); + + switch (c) + { + case '\n': + if (syntax & RE_NEWLINE_ALT) + token->type = OP_ALT; + break; + case '|': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '*': + token->type = OP_DUP_ASTERISK; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_CLOSE_DUP_NUM; + break; + case '(': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_CLOSE_SUBEXP; + break; + case '[': + token->type = OP_OPEN_BRACKET; + break; + case '.': + token->type = OP_PERIOD; + break; + case '^': + if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && + re_string_cur_idx (input) != 0) + { + char prev = re_string_peek_byte (input, -1); + if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_FIRST; + break; + case '$': + if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && + re_string_cur_idx (input) + 1 != re_string_length (input)) + { + re_token_t next; + re_string_skip_bytes (input, 1); + peek_token (&next, input, syntax); + re_string_skip_bytes (input, -1); + if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_LAST; + break; + default: + break; + } + return 1; +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function out of bracket expressions. */ + +static int +internal_function +peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + c = re_string_peek_byte (input, 0); + token->opr.c = c; + +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + return 1; + } +#endif /* RE_ENABLE_I18N */ + + if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) + && re_string_cur_idx (input) + 1 < re_string_length (input)) + { + /* In this case, '\' escape a character. */ + unsigned char c2; + re_string_skip_bytes (input, 1); + c2 = re_string_peek_byte (input, 0); + token->opr.c = c2; + token->type = CHARACTER; + return 1; + } + if (c == '[') /* '[' is a special char in a bracket exps. */ + { + unsigned char c2; + int token_len; + if (re_string_cur_idx (input) + 1 < re_string_length (input)) + c2 = re_string_peek_byte (input, 1); + else + c2 = 0; + token->opr.c = c2; + token_len = 2; + switch (c2) + { + case '.': + token->type = OP_OPEN_COLL_ELEM; + break; + case '=': + token->type = OP_OPEN_EQUIV_CLASS; + break; + case ':': + if (syntax & RE_CHAR_CLASSES) + { + token->type = OP_OPEN_CHAR_CLASS; + break; + } + /* else fall through. */ + default: + token->type = CHARACTER; + token->opr.c = c; + token_len = 1; + break; + } + return token_len; + } + switch (c) + { + case '-': + token->type = OP_CHARSET_RANGE; + break; + case ']': + token->type = OP_CLOSE_BRACKET; + break; + case '^': + token->type = OP_NON_MATCH_LIST; + break; + default: + token->type = CHARACTER; + } + return 1; +} + +/* Functions for parser. */ + +/* Entry point of the parser. + Parse the regular expression REGEXP and return the structure tree. + If an error is occured, ERR is set by error code, and return NULL. + This function build the following tree, from regular expression : + CAT + / \ + / \ + EOR + + CAT means concatenation. + EOR means end of regular expression. */ + +static bin_tree_t * +parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, + reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree, *eor, *root; + re_token_t current_token; + dfa->syntax = syntax; + fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); + tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + eor = create_tree (dfa, NULL, NULL, END_OF_RE); + if (tree != NULL) + root = create_tree (dfa, tree, eor, CONCAT); + else + root = eor; + if (BE (eor == NULL || root == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + return root; +} + +/* This function build the following tree, from regular expression + |: + ALT + / \ + / \ + + + ALT means alternative, which represents the operator `|'. */ + +static bin_tree_t * +parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree, *branch = NULL; + tree = parse_branch (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + + while (token->type == OP_ALT) + { + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + if (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + branch = parse_branch (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && branch == NULL, 0)) + return NULL; + } + else + branch = NULL; + tree = create_tree (dfa, tree, branch, OP_ALT); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + return tree; +} + +/* This function build the following tree, from regular expression + : + CAT + / \ + / \ + + + CAT means concatenation. */ + +static bin_tree_t * +parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + bin_tree_t *tree, *exp; + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + tree = parse_expression (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + + while (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + exp = parse_expression (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && exp == NULL, 0)) + { + return NULL; + } + if (tree != NULL && exp != NULL) + { + tree = create_tree (dfa, tree, exp, CONCAT); + if (tree == NULL) + { + *err = REG_ESPACE; + return NULL; + } + } + else if (tree == NULL) + tree = exp; + /* Otherwise exp == NULL, we don't need to create new tree. */ + } + return tree; +} + +/* This function build the following tree, from regular expression a*: + * + | + a +*/ + +static bin_tree_t * +parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree; + switch (token->type) + { + case CHARACTER: + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (!re_string_eoi (regexp) + && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) + { + bin_tree_t *mbc_remain; + fetch_token (token, regexp, syntax); + mbc_remain = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree, mbc_remain, CONCAT); + if (BE (mbc_remain == NULL || tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + } +#endif + break; + case OP_OPEN_SUBEXP: + tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_OPEN_BRACKET: + tree = parse_bracket_exp (regexp, dfa, token, syntax, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_BACK_REF: + if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) + { + *err = REG_ESUBREG; + return NULL; + } + dfa->used_bkref_map |= 1 << token->opr.idx; + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + ++dfa->nbackref; + dfa->has_mb_node = 1; + break; + case OP_OPEN_DUP_NUM: + if (syntax & RE_CONTEXT_INVALID_DUP) + { + *err = REG_BADRPT; + return NULL; + } + /* FALLTHROUGH */ + case OP_DUP_ASTERISK: + case OP_DUP_PLUS: + case OP_DUP_QUESTION: + if (syntax & RE_CONTEXT_INVALID_OPS) + { + *err = REG_BADRPT; + return NULL; + } + else if (syntax & RE_CONTEXT_INDEP_OPS) + { + fetch_token (token, regexp, syntax); + return parse_expression (regexp, preg, token, syntax, nest, err); + } + /* else fall through */ + case OP_CLOSE_SUBEXP: + if ((token->type == OP_CLOSE_SUBEXP) && + !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) + { + *err = REG_ERPAREN; + return NULL; + } + /* else fall through */ + case OP_CLOSE_DUP_NUM: + /* We treat it as a normal character. */ + + /* Then we can these characters as normal characters. */ + token->type = CHARACTER; + /* mb_partial and word_char bits should be initialized already + by peek_token. */ + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + break; + case ANCHOR: + if ((token->opr.ctx_type + & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) + && dfa->word_ops_used == 0) + init_word_char (dfa); + if (token->opr.ctx_type == WORD_DELIM + || token->opr.ctx_type == NOT_WORD_DELIM) + { + bin_tree_t *tree_first, *tree_last; + if (token->opr.ctx_type == WORD_DELIM) + { + token->opr.ctx_type = WORD_FIRST; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = WORD_LAST; + } + else + { + token->opr.ctx_type = INSIDE_WORD; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = INSIDE_NOTWORD; + } + tree_last = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree_first, tree_last, OP_ALT); + if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + else + { + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + /* We must return here, since ANCHORs can't be followed + by repetition operators. + eg. RE"^*" is invalid or "", + it must not be "". */ + fetch_token (token, regexp, syntax); + return tree; + case OP_PERIOD: + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + if (dfa->mb_cur_max > 1) + dfa->has_mb_node = 1; + break; + case OP_WORD: + case OP_NOTWORD: + tree = build_charclass_op (dfa, regexp->trans, + (const unsigned char *) "alnum", + (const unsigned char *) "_", + token->type == OP_NOTWORD, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_SPACE: + case OP_NOTSPACE: + tree = build_charclass_op (dfa, regexp->trans, + (const unsigned char *) "space", + (const unsigned char *) "", + token->type == OP_NOTSPACE, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_ALT: + case END_OF_RE: + return NULL; + case BACK_SLASH: + *err = REG_EESCAPE; + return NULL; + default: + /* Must not happen? */ +#ifdef DEBUG + assert (0); +#endif + return NULL; + } + fetch_token (token, regexp, syntax); + + while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS + || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) + { + tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + /* In BRE consecutive duplications are not allowed. */ + if ((syntax & RE_CONTEXT_INVALID_DUP) + && (token->type == OP_DUP_ASTERISK + || token->type == OP_OPEN_DUP_NUM)) + { + *err = REG_BADRPT; + return NULL; + } + } + + return tree; +} + +/* This function build the following tree, from regular expression + (): + SUBEXP + | + +*/ + +static bin_tree_t * +parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree; + size_t cur_nsub; + cur_nsub = preg->re_nsub++; + + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + + /* The subexpression may be a null string. */ + if (token->type == OP_CLOSE_SUBEXP) + tree = NULL; + else + { + tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); + if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) + *err = REG_EPAREN; + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } + + if (cur_nsub <= '9' - '1') + dfa->completed_bkref_map |= 1 << cur_nsub; + + tree = create_tree (dfa, tree, NULL, SUBEXP); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + tree->token.opr.idx = cur_nsub; + return tree; +} + +/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ + +static bin_tree_t * +parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) +{ + bin_tree_t *tree = NULL, *old_tree = NULL; + int i, start, end, start_idx = re_string_cur_idx (regexp); + re_token_t start_token = *token; + + if (token->type == OP_OPEN_DUP_NUM) + { + end = 0; + start = fetch_number (regexp, token, syntax); + if (start == -1) + { + if (token->type == CHARACTER && token->opr.c == ',') + start = 0; /* We treat "{,m}" as "{0,m}". */ + else + { + *err = REG_BADBR; /* {} is invalid. */ + return NULL; + } + } + if (BE (start != -2, 1)) + { + /* We treat "{n}" as "{n,n}". */ + end = ((token->type == OP_CLOSE_DUP_NUM) ? start + : ((token->type == CHARACTER && token->opr.c == ',') + ? fetch_number (regexp, token, syntax) : -2)); + } + if (BE (start == -2 || end == -2, 0)) + { + /* Invalid sequence. */ + if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) + { + if (token->type == END_OF_RE) + *err = REG_EBRACE; + else + *err = REG_BADBR; + + return NULL; + } + + /* If the syntax bit is set, rollback. */ + re_string_set_index (regexp, start_idx); + *token = start_token; + token->type = CHARACTER; + /* mb_partial and word_char bits should be already initialized by + peek_token. */ + return elem; + } + + if (BE (end != -1 && start > end, 0)) + { + /* First number greater than second. */ + *err = REG_BADBR; + return NULL; + } + } + else + { + start = (token->type == OP_DUP_PLUS) ? 1 : 0; + end = (token->type == OP_DUP_QUESTION) ? 1 : -1; + } + + fetch_token (token, regexp, syntax); + + if (BE (elem == NULL, 0)) + return NULL; + if (BE (start == 0 && end == 0, 0)) + { + postorder (elem, free_tree, NULL); + return NULL; + } + + /* Extract "{n,m}" to "...{0,}". */ + if (BE (start > 0, 0)) + { + tree = elem; + for (i = 2; i <= start; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (BE (elem == NULL || tree == NULL, 0)) + goto parse_dup_op_espace; + } + + if (start == end) + return tree; + + /* Duplicate ELEM before it is marked optional. */ + elem = duplicate_tree (elem, dfa); + old_tree = tree; + } + else + old_tree = NULL; + + if (elem->token.type == SUBEXP) + postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); + + tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); + if (BE (tree == NULL, 0)) + goto parse_dup_op_espace; + + /* This loop is actually executed only when end != -1, + to rewrite {0,n} as ((...?)?)?... We have + already created the start+1-th copy. */ + for (i = start + 2; i <= end; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (BE (elem == NULL || tree == NULL, 0)) + goto parse_dup_op_espace; + + tree = create_tree (dfa, tree, NULL, OP_ALT); + if (BE (tree == NULL, 0)) + goto parse_dup_op_espace; + } + + if (old_tree) + tree = create_tree (dfa, old_tree, tree, CONCAT); + + return tree; + + parse_dup_op_espace: + *err = REG_ESPACE; + return NULL; +} + +/* Size of the names for collating symbol/equivalence_class/character_class. + I'm not sure, but maybe enough. */ +#define BRACKET_NAME_BUF_SIZE 32 + +#ifndef _LIBC + /* Local function for parse_bracket_exp only used in case of NOT _LIBC. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument sinse we may + update it. */ + +static reg_errcode_t +internal_function +# ifdef RE_ENABLE_I18N +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem) +# else /* not RE_ENABLE_I18N */ +build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, + bracket_elem_t *end_elem) +# endif /* not RE_ENABLE_I18N */ +{ + unsigned int start_ch, end_ch; + /* Equivalence Classes and Character Classes can't be a range start/end. */ + if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, + 0)) + return REG_ERANGE; + + /* We can handle no multi character collating elements without libc + support. */ + if (BE ((start_elem->type == COLL_SYM + && strlen ((char *) start_elem->opr.name) > 1) + || (end_elem->type == COLL_SYM + && strlen ((char *) end_elem->opr.name) > 1), 0)) + return REG_ECOLLATE; + +# ifdef RE_ENABLE_I18N + { + wchar_t wc; + wint_t start_wc; + wint_t end_wc; + wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; + + start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) + ? __btowc (start_ch) : start_elem->opr.wch); + end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) + ? __btowc (end_ch) : end_elem->opr.wch); + if (start_wc == WEOF || end_wc == WEOF) + return REG_ECOLLATE; + cmp_buf[0] = start_wc; + cmp_buf[4] = end_wc; + if (wcscoll (cmp_buf, cmp_buf + 4) > 0) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, for !_LIBC we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes + no MBCSET if dfa->mb_cur_max == 1. */ + if (mbcset) + { + /* Check the space of the arrays. */ + if (BE (*range_alloc == mbcset->nranges, 0)) + { + /* There is not enough space, need realloc. */ + wchar_t *new_array_start, *new_array_end; + int new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + /* Use realloc since mbcset->range_starts and mbcset->range_ends + are NULL if *range_alloc == 0. */ + new_array_start = re_realloc (mbcset->range_starts, wchar_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, wchar_t, + new_nranges); + + if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_wc; + mbcset->range_ends[mbcset->nranges++] = end_wc; + } + + /* Build the table for single byte characters. */ + for (wc = 0; wc < SBC_MAX; ++wc) + { + cmp_buf[2] = wc; + if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 + && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + bitset_set (sbcset, wc); + } + } +# else /* not RE_ENABLE_I18N */ + { + unsigned int ch; + start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + if (start_ch > end_ch) + return REG_ERANGE; + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ++ch) + if (start_ch <= ch && ch <= end_ch) + bitset_set (sbcset, ch); + } +# endif /* not RE_ENABLE_I18N */ + return REG_NOERROR; +} +#endif /* not _LIBC */ + +#ifndef _LIBC +/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static reg_errcode_t +internal_function +# ifdef RE_ENABLE_I18N +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + int *coll_sym_alloc, const unsigned char *name) +# else /* not RE_ENABLE_I18N */ +build_collating_symbol (bitset_t sbcset, const unsigned char *name) +# endif /* not RE_ENABLE_I18N */ +{ + size_t name_len = strlen ((const char *) name); + if (BE (name_len != 1, 0)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } +} +#endif /* not _LIBC */ + +/* This function parse bracket expression like "[abc]", "[a-c]", + "[[.a-a.]]" etc. */ + +static bin_tree_t * +parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) +{ +#ifdef _LIBC + const unsigned char *collseqmb; + const char *collseqwc; + uint32_t nrules; + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + + /* Local function for parse_bracket_exp used in _LIBC environement. + Seek the collating symbol entry correspondings to NAME. + Return the index of the symbol in the SYMB_TABLE. */ + + auto __inline__ int32_t + __attribute ((always_inline)) + seek_collating_symbol_entry (name, name_len) + const unsigned char *name; + size_t name_len; + { + int32_t hash = elem_hash ((const char *) name, name_len); + int32_t elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + int32_t second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + /* Compare the length of the name. */ + && name_len == extra[symb_table[2 * elem + 1]] + /* Compare the name. */ + && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], + name_len) == 0) + { + /* Yep, this is the entry. */ + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + return elem; + } + + /* Local function for parse_bracket_exp used in _LIBC environement. + Look up the collation sequence value of BR_ELEM. + Return the value if succeeded, UINT_MAX otherwise. */ + + auto __inline__ unsigned int + __attribute ((always_inline)) + lookup_collation_sequence_value (br_elem) + bracket_elem_t *br_elem; + { + if (br_elem->type == SB_CHAR) + { + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + return collseqmb[br_elem->opr.ch]; + else + { + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); + } + } + else if (br_elem->type == MB_CHAR) + { + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); + if (nrules != 0) + { + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len); + if (symb_table[2 * elem] != 0) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + /* Skip the byte sequence of the collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the multibyte collation sequence value. */ + idx += sizeof (unsigned int); + /* Skip the wide char sequence of the collating element. */ + idx += sizeof (unsigned int) * + (1 + *(unsigned int *) (extra + idx)); + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); + } + else if (symb_table[2 * elem] == 0 && sym_name_len == 1) + { + /* No valid character. Match it as a single byte + character. */ + return collseqmb[br_elem->opr.name[0]]; + } + } + else if (sym_name_len == 1) + return collseqmb[br_elem->opr.name[0]]; + } + return UINT_MAX; + } + + /* Local function for parse_bracket_exp used in _LIBC environement. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument sinse we may + update it. */ + + auto __inline__ reg_errcode_t + __attribute ((always_inline)) + build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) + re_charset_t *mbcset; + int *range_alloc; + bitset_t sbcset; + bracket_elem_t *start_elem, *end_elem; + { + unsigned int ch; + uint32_t start_collseq; + uint32_t end_collseq; + + /* Equivalence Classes and Character Classes can't be a range + start/end. */ + if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, + 0)) + return REG_ERANGE; + + start_collseq = lookup_collation_sequence_value (start_elem); + end_collseq = lookup_collation_sequence_value (end_elem); + /* Check start/end collation sequence values. */ + if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) + return REG_ECOLLATE; + if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ + if (nrules > 0 || dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (BE (*range_alloc == mbcset->nranges, 0)) + { + /* There is not enough space, need realloc. */ + uint32_t *new_array_start; + uint32_t *new_array_end; + int new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + new_array_start = re_realloc (mbcset->range_starts, uint32_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, uint32_t, + new_nranges); + + if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_collseq; + mbcset->range_ends[mbcset->nranges++] = end_collseq; + } + + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ch++) + { + uint32_t ch_collseq; + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + ch_collseq = collseqmb[ch]; + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) + bitset_set (sbcset, ch); + } + return REG_NOERROR; + } + + /* Local function for parse_bracket_exp used in _LIBC environement. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument sinse we may update it. */ + + auto __inline__ reg_errcode_t + __attribute ((always_inline)) + build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) + re_charset_t *mbcset; + int *coll_sym_alloc; + bitset_t sbcset; + const unsigned char *name; + { + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) + { + elem = seek_collating_symbol_entry (name, name_len); + if (symb_table[2 * elem] != 0) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } + else if (symb_table[2 * elem] == 0 && name_len == 1) + { + /* No valid character, treat it as a normal + character. */ + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + else + return REG_ECOLLATE; + + /* Got valid collation sequence, add it as a new entry. */ + /* Check the space of the arrays. */ + if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->ncoll_syms is 0. */ + int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + /* Use realloc since mbcset->coll_syms is NULL + if *alloc == 0. */ + int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, + new_coll_sym_alloc); + if (BE (new_coll_syms == NULL, 0)) + return REG_ESPACE; + mbcset->coll_syms = new_coll_syms; + *coll_sym_alloc = new_coll_sym_alloc; + } + mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + return REG_NOERROR; + } + else + { + if (BE (name_len != 1, 0)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + } + } +#endif + + re_token_t br_token; + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; + int equiv_class_alloc = 0, char_class_alloc = 0; +#endif /* not RE_ENABLE_I18N */ + int non_match = 0; + bin_tree_t *work_tree; + int token_len; + int first_round = 1; +#ifdef _LIBC + collseqmb = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules) + { + /* + if (MB_CUR_MAX > 1) + */ + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + } +#endif + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); +#ifdef RE_ENABLE_I18N + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); +#endif /* RE_ENABLE_I18N */ +#ifdef RE_ENABLE_I18N + if (BE (sbcset == NULL || mbcset == NULL, 0)) +#else + if (BE (sbcset == NULL, 0)) +#endif /* RE_ENABLE_I18N */ + { + *err = REG_ESPACE; + return NULL; + } + + token_len = peek_token_bracket (token, regexp, syntax); + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_NON_MATCH_LIST) + { +#ifdef RE_ENABLE_I18N + mbcset->non_match = 1; +#endif /* not RE_ENABLE_I18N */ + non_match = 1; + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set (sbcset, '\0'); + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + token_len = peek_token_bracket (token, regexp, syntax); + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + } + + /* We treat the first ']' as a normal character. */ + if (token->type == OP_CLOSE_BRACKET) + token->type = CHARACTER; + + while (1) + { + bracket_elem_t start_elem, end_elem; + unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; + unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; + reg_errcode_t ret; + int token_len2 = 0, is_range_exp = 0; + re_token_t token2; + + start_elem.opr.name = start_name_buf; + ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, + syntax, first_round); + if (BE (ret != REG_NOERROR, 0)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + first_round = 0; + + /* Get information about the next token. We need it in any case. */ + token_len = peek_token_bracket (token, regexp, syntax); + + /* Do not check for ranges if we know they are not allowed. */ + if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) + { + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CHARSET_RANGE) + { + re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ + token_len2 = peek_token_bracket (&token2, regexp, syntax); + if (BE (token2.type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token2.type == OP_CLOSE_BRACKET) + { + /* We treat the last '-' as a normal character. */ + re_string_skip_bytes (regexp, -token_len); + token->type = CHARACTER; + } + else + is_range_exp = 1; + } + } + + if (is_range_exp == 1) + { + end_elem.opr.name = end_name_buf; + ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, + dfa, syntax, 1); + if (BE (ret != REG_NOERROR, 0)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + + token_len = peek_token_bracket (token, regexp, syntax); + +#ifdef _LIBC + *err = build_range_exp (sbcset, mbcset, &range_alloc, + &start_elem, &end_elem); +#else +# ifdef RE_ENABLE_I18N + *err = build_range_exp (sbcset, + dfa->mb_cur_max > 1 ? mbcset : NULL, + &range_alloc, &start_elem, &end_elem); +# else + *err = build_range_exp (sbcset, &start_elem, &end_elem); +# endif +#endif /* RE_ENABLE_I18N */ + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + } + else + { + switch (start_elem.type) + { + case SB_CHAR: + bitset_set (sbcset, start_elem.opr.ch); + break; +#ifdef RE_ENABLE_I18N + case MB_CHAR: + /* Check whether the array has enough space. */ + if (BE (mbchar_alloc == mbcset->nmbchars, 0)) + { + wchar_t *new_mbchars; + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nmbchars is 0. */ + mbchar_alloc = 2 * mbcset->nmbchars + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + new_mbchars = re_realloc (mbcset->mbchars, wchar_t, + mbchar_alloc); + if (BE (new_mbchars == NULL, 0)) + goto parse_bracket_exp_espace; + mbcset->mbchars = new_mbchars; + } + mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; + break; +#endif /* RE_ENABLE_I18N */ + case EQUIV_CLASS: + *err = build_equiv_class (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &equiv_class_alloc, +#endif /* RE_ENABLE_I18N */ + start_elem.opr.name); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + case COLL_SYM: + *err = build_collating_symbol (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &coll_sym_alloc, +#endif /* RE_ENABLE_I18N */ + start_elem.opr.name); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + case CHAR_CLASS: + *err = build_charclass (regexp->trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &char_class_alloc, +#endif /* RE_ENABLE_I18N */ + start_elem.opr.name, syntax); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + default: + assert (0); + break; + } + } + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CLOSE_BRACKET) + break; + } + + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); + + if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes + || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes + || mbcset->non_match))) + { + bin_tree_t *mbc_tree; + int sbc_idx; + /* Build a tree for complex bracket. */ + dfa->has_mb_node = 1; + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (mbc_tree == NULL, 0)) + goto parse_bracket_exp_espace; + for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) + if (sbcset[sbc_idx]) + break; + /* If there are no bits set in sbcset, there is no point + of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ + if (sbc_idx < BITSET_WORDS) + { + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + + /* Then join them by ALT node. */ + work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + } + else + { + re_free (sbcset); + work_tree = mbc_tree; + } + } + else +#endif /* not RE_ENABLE_I18N */ + { +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + } + return work_tree; + + parse_bracket_exp_espace: + *err = REG_ESPACE; + parse_bracket_exp_free_return: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + return NULL; +} + +/* Parse an element in the bracket expression. */ + +static reg_errcode_t +parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token, int token_len, re_dfa_t *dfa, + reg_syntax_t syntax, int accept_hyphen) +{ +#ifdef RE_ENABLE_I18N + int cur_char_size; + cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); + if (cur_char_size > 1) + { + elem->type = MB_CHAR; + elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); + re_string_skip_bytes (regexp, cur_char_size); + return REG_NOERROR; + } +#endif /* RE_ENABLE_I18N */ + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS + || token->type == OP_OPEN_EQUIV_CLASS) + return parse_bracket_symbol (elem, regexp, token); + if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) + { + /* A '-' must only appear as anything but a range indicator before + the closing bracket. Everything else is an error. */ + re_token_t token2; + (void) peek_token_bracket (&token2, regexp, syntax); + if (token2.type != OP_CLOSE_BRACKET) + /* The actual error value is not standardized since this whole + case is undefined. But ERANGE makes good sense. */ + return REG_ERANGE; + } + elem->type = SB_CHAR; + elem->opr.ch = token->opr.c; + return REG_NOERROR; +} + +/* Parse a bracket symbol in the bracket expression. Bracket symbols are + such as [::], [..], and + [==]. */ + +static reg_errcode_t +parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token) +{ + unsigned char ch, delim = token->opr.c; + int i = 0; + if (re_string_eoi(regexp)) + return REG_EBRACK; + for (;; ++i) + { + if (i >= BRACKET_NAME_BUF_SIZE) + return REG_EBRACK; + if (token->type == OP_OPEN_CHAR_CLASS) + ch = re_string_fetch_byte_case (regexp); + else + ch = re_string_fetch_byte (regexp); + if (re_string_eoi(regexp)) + return REG_EBRACK; + if (ch == delim && re_string_peek_byte (regexp, 0) == ']') + break; + elem->opr.name[i] = ch; + } + re_string_skip_bytes (regexp, 1); + elem->opr.name[i] = '\0'; + switch (token->type) + { + case OP_OPEN_COLL_ELEM: + elem->type = COLL_SYM; + break; + case OP_OPEN_EQUIV_CLASS: + elem->type = EQUIV_CLASS; + break; + case OP_OPEN_CHAR_CLASS: + elem->type = CHAR_CLASS; + break; + default: + break; + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the equivalence class which is represented by NAME. + The result are written to MBCSET and SBCSET. + EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, + is a pointer argument sinse we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, + int *equiv_class_alloc, const unsigned char *name) +#else /* not RE_ENABLE_I18N */ +build_equiv_class (bitset_t sbcset, const unsigned char *name) +#endif /* not RE_ENABLE_I18N */ +{ +#ifdef _LIBC + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const int32_t *table, *indirect; + const unsigned char *weights, *extra, *cp; + unsigned char char_buf[2]; + int32_t idx1, idx2; + unsigned int ch; + size_t len; + /* This #include defines a local function! */ +# include + /* Calculate the index for equivalence class. */ + cp = name; + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + idx1 = findidx (&cp); + if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) + /* This isn't a valid character. */ + return REG_ECOLLATE; + + /* Build single byte matcing table for this equivalence class. */ + char_buf[1] = (unsigned char) '\0'; + len = weights[idx1]; + for (ch = 0; ch < SBC_MAX; ++ch) + { + char_buf[0] = ch; + cp = char_buf; + idx2 = findidx (&cp); +/* + idx2 = table[ch]; +*/ + if (idx2 == 0) + /* This isn't a valid character. */ + continue; + if (len == weights[idx2]) + { + int cnt = 0; + while (cnt <= len && + weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) + ++cnt; + + if (cnt > len) + bitset_set (sbcset, ch); + } + } + /* Check whether the array has enough space. */ + if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nequiv_classes is 0. */ + int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; + /* Use realloc since the array is NULL if *alloc == 0. */ + int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, + int32_t, + new_equiv_class_alloc); + if (BE (new_equiv_classes == NULL, 0)) + return REG_ESPACE; + mbcset->equiv_classes = new_equiv_classes; + *equiv_class_alloc = new_equiv_class_alloc; + } + mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; + } + else +#endif /* _LIBC */ + { + if (BE (strlen ((const char *) name) != 1, 0)) + return REG_ECOLLATE; + bitset_set (sbcset, *name); + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the character class which is represented by NAME. + The result are written to MBCSET and SBCSET. + CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, + is a pointer argument sinse we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + re_charset_t *mbcset, int *char_class_alloc, + const unsigned char *class_name, reg_syntax_t syntax) +#else /* not RE_ENABLE_I18N */ +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + const unsigned char *class_name, reg_syntax_t syntax) +#endif /* not RE_ENABLE_I18N */ +{ + int i; + const char *name = (const char *) class_name; + + /* In case of REG_ICASE "upper" and "lower" match the both of + upper and lower cases. */ + if ((syntax & RE_ICASE) + && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) + name = "alpha"; + +#ifdef RE_ENABLE_I18N + /* Check the space of the arrays. */ + if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nchar_classes is 0. */ + int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, + new_char_class_alloc); + if (BE (new_char_classes == NULL, 0)) + return REG_ESPACE; + mbcset->char_classes = new_char_classes; + *char_class_alloc = new_char_class_alloc; + } + mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); +#endif /* RE_ENABLE_I18N */ + +#define BUILD_CHARCLASS_LOOP(ctype_func) \ + do { \ + if (BE (trans != NULL, 0)) \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, trans[i]); \ + } \ + else \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, i); \ + } \ + } while (0) + + if (strcmp (name, "alnum") == 0) + BUILD_CHARCLASS_LOOP (isalnum); + else if (strcmp (name, "cntrl") == 0) + BUILD_CHARCLASS_LOOP (iscntrl); + else if (strcmp (name, "lower") == 0) + BUILD_CHARCLASS_LOOP (islower); + else if (strcmp (name, "space") == 0) + BUILD_CHARCLASS_LOOP (isspace); + else if (strcmp (name, "alpha") == 0) + BUILD_CHARCLASS_LOOP (isalpha); + else if (strcmp (name, "digit") == 0) + BUILD_CHARCLASS_LOOP (isdigit); + else if (strcmp (name, "print") == 0) + BUILD_CHARCLASS_LOOP (isprint); + else if (strcmp (name, "upper") == 0) + BUILD_CHARCLASS_LOOP (isupper); + else if (strcmp (name, "blank") == 0) + BUILD_CHARCLASS_LOOP (isblank); + else if (strcmp (name, "graph") == 0) + BUILD_CHARCLASS_LOOP (isgraph); + else if (strcmp (name, "punct") == 0) + BUILD_CHARCLASS_LOOP (ispunct); + else if (strcmp (name, "xdigit") == 0) + BUILD_CHARCLASS_LOOP (isxdigit); + else + return REG_ECTYPE; + + return REG_NOERROR; +} + +static bin_tree_t * +build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + const unsigned char *class_name, + const unsigned char *extra, int non_match, + reg_errcode_t *err) +{ + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + int alloc = 0; +#endif /* not RE_ENABLE_I18N */ + reg_errcode_t ret; + re_token_t br_token; + bin_tree_t *tree; + + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); +#ifdef RE_ENABLE_I18N + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); +#endif /* RE_ENABLE_I18N */ + +#ifdef RE_ENABLE_I18N + if (BE (sbcset == NULL || mbcset == NULL, 0)) +#else /* not RE_ENABLE_I18N */ + if (BE (sbcset == NULL, 0)) +#endif /* not RE_ENABLE_I18N */ + { + *err = REG_ESPACE; + return NULL; + } + + if (non_match) + { +#ifdef RE_ENABLE_I18N + /* + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set(cset->sbcset, '\0'); + */ + mbcset->non_match = 1; +#endif /* not RE_ENABLE_I18N */ + } + + /* We don't care the syntax in this case. */ + ret = build_charclass (trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &alloc, +#endif /* RE_ENABLE_I18N */ + class_name, 0); + + if (BE (ret != REG_NOERROR, 0)) + { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + *err = ret; + return NULL; + } + /* \w match '_' also. */ + for (; *extra; extra++) + bitset_set (sbcset, *extra); + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); +#endif + + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (tree == NULL, 0)) + goto build_word_op_espace; + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + bin_tree_t *mbc_tree; + /* Build a tree for complex bracket. */ + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + dfa->has_mb_node = 1; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (mbc_tree == NULL, 0)) + goto build_word_op_espace; + /* Then join them by ALT node. */ + tree = create_tree (dfa, tree, mbc_tree, OP_ALT); + if (BE (mbc_tree != NULL, 1)) + return tree; + } + else + { + free_charset (mbcset); + return tree; + } +#else /* not RE_ENABLE_I18N */ + return tree; +#endif /* not RE_ENABLE_I18N */ + + build_word_op_espace: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + *err = REG_ESPACE; + return NULL; +} + +/* This is intended for the expressions like "a{1,3}". + Fetch a number from `input', and return the number. + Return -1, if the number field is empty like "{,1}". + Return -2, If an error is occured. */ + +static int +fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) +{ + int num = -1; + unsigned char c; + while (1) + { + fetch_token (token, input, syntax); + c = token->opr.c; + if (BE (token->type == END_OF_RE, 0)) + return -2; + if (token->type == OP_CLOSE_DUP_NUM || c == ',') + break; + num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) + ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); + num = (num > RE_DUP_MAX) ? -2 : num; + } + return num; +} + +#ifdef RE_ENABLE_I18N +static void +free_charset (re_charset_t *cset) +{ + re_free (cset->mbchars); +# ifdef _LIBC + re_free (cset->coll_syms); + re_free (cset->equiv_classes); + re_free (cset->range_starts); + re_free (cset->range_ends); +# endif + re_free (cset->char_classes); + re_free (cset); +} +#endif /* RE_ENABLE_I18N */ + +/* Functions for binary tree operation. */ + +/* Create a tree node. */ + +static bin_tree_t * +create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + re_token_type_t type) +{ + re_token_t t; + t.type = type; + return create_token_tree (dfa, left, right, &t); +} + +static bin_tree_t * +create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + const re_token_t *token) +{ + bin_tree_t *tree; + if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) + { + bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); + + if (storage == NULL) + return NULL; + storage->next = dfa->str_tree_storage; + dfa->str_tree_storage = storage; + dfa->str_tree_storage_idx = 0; + } + tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; + + tree->parent = NULL; + tree->left = left; + tree->right = right; + tree->token = *token; + tree->token.duplicated = 0; + tree->token.opt_subexp = 0; + tree->first = NULL; + tree->next = NULL; + tree->node_idx = -1; + + if (left != NULL) + left->parent = tree; + if (right != NULL) + right->parent = tree; + return tree; +} + +/* Mark the tree SRC as an optional subexpression. + To be called from preorder or postorder. */ + +static reg_errcode_t +mark_opt_subexp (void *extra, bin_tree_t *node) +{ + int idx = (int) (long) extra; + if (node->token.type == SUBEXP && node->token.opr.idx == idx) + node->token.opt_subexp = 1; + + return REG_NOERROR; +} + +/* Free the allocated memory inside NODE. */ + +static void +free_token (re_token_t *node) +{ +#ifdef RE_ENABLE_I18N + if (node->type == COMPLEX_BRACKET && node->duplicated == 0) + free_charset (node->opr.mbcset); + else +#endif /* RE_ENABLE_I18N */ + if (node->type == SIMPLE_BRACKET && node->duplicated == 0) + re_free (node->opr.sbcset); +} + +/* Worker function for tree walking. Free the allocated memory inside NODE + and its children. */ + +static reg_errcode_t +free_tree (void *extra, bin_tree_t *node) +{ + free_token (&node->token); + return REG_NOERROR; +} + + +/* Duplicate the node SRC, and return new node. This is a preorder + visit similar to the one implemented by the generic visitor, but + we need more infrastructure to maintain two parallel trees --- so, + it's easier to duplicate. */ + +static bin_tree_t * +duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) +{ + const bin_tree_t *node; + bin_tree_t *dup_root; + bin_tree_t **p_new = &dup_root, *dup_node = root->parent; + + for (node = root; ; ) + { + /* Create a new tree and link it back to the current parent. */ + *p_new = create_token_tree (dfa, NULL, NULL, &node->token); + if (*p_new == NULL) + return NULL; + (*p_new)->parent = dup_node; + (*p_new)->token.duplicated = 1; + dup_node = *p_new; + + /* Go to the left node, or up and to the right. */ + if (node->left) + { + node = node->left; + p_new = &dup_node->left; + } + else + { + const bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + dup_node = dup_node->parent; + if (!node) + return dup_root; + } + node = node->right; + p_new = &dup_node->right; + } + } +} diff --git a/libc/misc/regex/regex.c b/libc/misc/regex/regex.c new file mode 100644 index 0000000..10229a2 --- /dev/null +++ b/libc/misc/regex/regex.c @@ -0,0 +1,152 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* uClibc addons */ +#include + +#ifdef __UCLIBC__ +#undef _LIBC +#define _REGEX_RE_COMP +#ifdef __USE_GNU +# define HAVE_MEMPCPY +#endif +#define HAVE_LANGINFO +#define HAVE_LANGINFO_CODESET +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#define RE_ENABLE_I18N +#include +#include + +#define __iswctype iswctype +#define __wcrtomb wcrtomb +#define __btowc btowc +#define __wctype wctype +libc_hidden_proto(wcscoll) +libc_hidden_proto(wcrtomb) +libc_hidden_proto(mbrtowc) +libc_hidden_proto(iswctype) +libc_hidden_proto(iswlower) +libc_hidden_proto(iswalnum) +libc_hidden_proto(towlower) +libc_hidden_proto(towupper) +libc_hidden_proto(mbsinit) +libc_hidden_proto(btowc) +libc_hidden_proto(wctype) + +#endif + +#include +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ +#define __toupper toupper +#define __tolower tolower +#endif +#define __mempcpy mempcpy +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +libc_hidden_proto(__ctype_toupper_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_toupper) +#else +libc_hidden_proto(isascii) +#endif +libc_hidden_proto(toupper) +libc_hidden_proto(tolower) +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memmove) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(getenv) +/* Experimentally off - libc_hidden_proto(strcasecmp) */ +libc_hidden_proto(abort) +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(mempcpy) */ +#endif + +#endif + +/* Make sure noone compiles this code with a C++ compiler. */ +#ifdef __cplusplus +# error "This is C code, use a C compiler" +#endif + +#if defined _LIBC || defined __UCLIBC__ +/* We have to keep the namespace clean. */ +# define regfree(preg) __regfree (preg) +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) +# define regerror(errcode, preg, errbuf, errbuf_size) \ + __regerror(errcode, preg, errbuf, errbuf_size) +# define re_set_registers(bu, re, nu, st, en) \ + __re_set_registers (bu, re, nu, st, en) +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ + __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) +# define re_match(bufp, string, size, pos, regs) \ + __re_match (bufp, string, size, pos, regs) +# define re_search(bufp, string, size, startpos, range, regs) \ + __re_search (bufp, string, size, startpos, range, regs) +# define re_compile_pattern(pattern, length, bufp) \ + __re_compile_pattern (pattern, length, bufp) +# define re_set_syntax(syntax) __re_set_syntax (syntax) +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ + __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) + +#ifndef __UCLIBC__ +# include "../locale/localeinfo.h" +#endif +#endif + +/* On some systems, limits.h sets RE_DUP_MAX to a lower value than + GNU regex allows. Include it before , which correctly + #undefs RE_DUP_MAX and sets it to the right value. */ +#include + +#ifdef __UCLIBC__ +#include "_regex.h" +#else +#include +#endif +#include "regex_internal.h" + +#include "regex_internal.c" +#include "regcomp.c" +#include "regexec.c" + +/* Binary backward compatibility. */ +#if _LIBC +# include +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) +link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") +int re_max_failures = 2000; +# endif +#endif diff --git a/libc/misc/regex/regex_internal.c b/libc/misc/regex/regex_internal.c new file mode 100644 index 0000000..11b1be7 --- /dev/null +++ b/libc/misc/regex/regex_internal.c @@ -0,0 +1,1646 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static void re_string_construct_common (const char *str, int len, + re_string_t *pstr, + RE_TRANSLATE_TYPE trans, int icase, + const re_dfa_t *dfa) internal_function; +static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int hash) internal_function; +static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int context, + unsigned int hash) internal_function; + +/* Functions for string operation. */ + +/* This function allocate the buffers. It is necessary to call + re_string_reconstruct before using the object. */ + +static reg_errcode_t +internal_function +re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, + RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + int init_buf_len; + + /* Ensure at least one character fits into the buffers. */ + if (init_len < dfa->mb_cur_max) + init_len = dfa->mb_cur_max; + init_buf_len = (len + 1 < init_len) ? len + 1: init_len; + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + ret = re_string_realloc_buffers (pstr, init_buf_len); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + pstr->word_char = dfa->word_char; + pstr->word_ops_used = dfa->word_ops_used; + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; + pstr->valid_raw_len = pstr->valid_len; + return REG_NOERROR; +} + +/* This function allocate the buffers, and initialize them. */ + +static reg_errcode_t +internal_function +re_string_construct (re_string_t *pstr, const char *str, int len, + RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + memset (pstr, '\0', sizeof (re_string_t)); + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + if (len > 0) + { + ret = re_string_realloc_buffers (pstr, len + 1); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + + if (icase) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (1) + { + ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + if (pstr->valid_raw_len >= len) + break; + if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) + break; + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif /* RE_ENABLE_I18N */ + { + if (trans != NULL) + re_string_translate_buffer (pstr); + else + { + pstr->valid_len = pstr->bufs_len; + pstr->valid_raw_len = pstr->bufs_len; + } + } + } + + return REG_NOERROR; +} + +/* Helper functions for re_string_allocate, and re_string_construct. */ + +static reg_errcode_t +internal_function +re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) +{ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); + if (BE (new_wcs == NULL, 0)) + return REG_ESPACE; + pstr->wcs = new_wcs; + if (pstr->offsets != NULL) + { + int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len); + if (BE (new_offsets == NULL, 0)) + return REG_ESPACE; + pstr->offsets = new_offsets; + } + } +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + { + unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, + new_buf_len); + if (BE (new_mbs == NULL, 0)) + return REG_ESPACE; + pstr->mbs = new_mbs; + } + pstr->bufs_len = new_buf_len; + return REG_NOERROR; +} + + +static void +internal_function +re_string_construct_common (const char *str, int len, re_string_t *pstr, + RE_TRANSLATE_TYPE trans, int icase, + const re_dfa_t *dfa) +{ + pstr->raw_mbs = (const unsigned char *) str; + pstr->len = len; + pstr->raw_len = len; + pstr->trans = trans; + pstr->icase = icase ? 1 : 0; + pstr->mbs_allocated = (trans != NULL || icase); + pstr->mb_cur_max = dfa->mb_cur_max; + pstr->is_utf8 = dfa->is_utf8; + pstr->map_notascii = dfa->map_notascii; + pstr->stop = pstr->len; + pstr->raw_stop = pstr->stop; +} + +#ifdef RE_ENABLE_I18N + +/* Build wide character buffer PSTR->WCS. + If the byte sequence of the string are: + (0), (1), (0), (1), + Then wide character buffer will be: + , WEOF , , WEOF , + We use WEOF for padding, they indicate that the position isn't + a first byte of a multibyte character. + + Note that this function assumes PSTR->VALID_LEN elements are already + built and starts from PSTR->VALID_LEN. */ + +static void +internal_function +build_wcs_buffer (re_string_t *pstr) +{ +#if defined _LIBC || defined __UCLIBC__ + unsigned char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + unsigned char buf[64]; +#endif + mbstate_t prev_st; + int byte_idx, end_idx, remain_len; + size_t mbclen; + + /* Build the buffers from pstr->valid_len to either pstr->len or + pstr->bufs_len. */ + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + for (byte_idx = pstr->valid_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + /* Apply the translation if we need. */ + if (BE (pstr->trans != NULL, 0)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; + buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; + mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (BE (mbclen == (size_t) -2, 0)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + if (BE (pstr->trans != NULL, 0)) + wc = pstr->trans[wc]; + pstr->cur_state = prev_st; + } + + /* Write wide character and padding. */ + pstr->wcs[byte_idx++] = wc; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; +} + +/* Build wide character buffer PSTR->WCS like build_wcs_buffer, + but for REG_ICASE. */ + +static reg_errcode_t +internal_function +build_wcs_upper_buffer (re_string_t *pstr) +{ + mbstate_t prev_st; + int src_idx, byte_idx, end_idx, remain_len; + size_t mbclen; +#if defined _LIBC || defined __UCLIBC__ + char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + char buf[64]; +#endif + + byte_idx = pstr->valid_len; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + /* The following optimization assumes that ASCII characters can be + mapped to wide characters with a simple cast. */ + if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) + { + while (byte_idx < end_idx) + { + wchar_t wc; + + if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) + && mbsinit (&pstr->cur_state)) + { + /* In case of a singlebyte character. */ + pstr->mbs[byte_idx] + = __toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); + /* The next step uses the assumption that wchar_t is encoded + ASCII-safe: all ASCII values can be converted like this. */ + pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; + ++byte_idx; + continue; + } + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + mbclen = mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); + if (BE (mbclen + 2 > 2, 1)) + { + wchar_t wcu = wc; + if (iswlower (wc)) + { + size_t mbcdlen; + + wcu = towupper (wc); + mbcdlen = wcrtomb (buf, wcu, &prev_st); + if (BE (mbclen == mbcdlen, 1)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else + { + src_idx = byte_idx; + goto offsets_needed; + } + } + else + memcpy (pstr->mbs + byte_idx, + pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + pstr->mbs[byte_idx] = ch; + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (BE (mbclen == (size_t) -1, 0)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; + return REG_NOERROR; + } + else + for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + offsets_needed: + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + if (BE (pstr->trans != NULL, 0)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; + buf[i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (BE (mbclen + 2 > 2, 1)) + { + wchar_t wcu = wc; + if (iswlower (wc)) + { + size_t mbcdlen; + + wcu = towupper (wc); + mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); + if (BE (mbclen == mbcdlen, 1)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else if (mbcdlen != (size_t) -1) + { + size_t i; + + if (byte_idx + mbcdlen > pstr->bufs_len) + { + pstr->cur_state = prev_st; + break; + } + + if (pstr->offsets == NULL) + { + pstr->offsets = re_malloc (int, pstr->bufs_len); + + if (pstr->offsets == NULL) + return REG_ESPACE; + } + if (!pstr->offsets_needed) + { + for (i = 0; i < (size_t) byte_idx; ++i) + pstr->offsets[i] = i; + pstr->offsets_needed = 1; + } + + memcpy (pstr->mbs + byte_idx, buf, mbcdlen); + pstr->wcs[byte_idx] = wcu; + pstr->offsets[byte_idx] = src_idx; + for (i = 1; i < mbcdlen; ++i) + { + pstr->offsets[byte_idx + i] + = src_idx + (i < mbclen ? i : mbclen - 1); + pstr->wcs[byte_idx + i] = WEOF; + } + pstr->len += mbcdlen - mbclen; + if (pstr->raw_stop > src_idx) + pstr->stop += mbcdlen - mbclen; + end_idx = (pstr->bufs_len > pstr->len) + ? pstr->len : pstr->bufs_len; + byte_idx += mbcdlen; + src_idx += mbclen; + continue; + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + + if (BE (pstr->offsets_needed != 0, 0)) + { + size_t i; + for (i = 0; i < mbclen; ++i) + pstr->offsets[byte_idx + i] = src_idx + i; + } + src_idx += mbclen; + + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; + + if (BE (pstr->trans != NULL, 0)) + ch = pstr->trans [ch]; + pstr->mbs[byte_idx] = ch; + + if (BE (pstr->offsets_needed != 0, 0)) + pstr->offsets[byte_idx] = src_idx; + ++src_idx; + + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (BE (mbclen == (size_t) -1, 0)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = src_idx; + return REG_NOERROR; +} + +/* Skip characters until the index becomes greater than NEW_RAW_IDX. + Return the index. */ + +static int +internal_function +re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) +{ + mbstate_t prev_st; + int rawbuf_idx; + size_t mbclen; + wchar_t wc = 0; + + /* Skip the characters which are not necessary to check. */ + for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; + rawbuf_idx < new_raw_idx;) + { + int remain_len; + remain_len = pstr->len - rawbuf_idx; + prev_st = pstr->cur_state; + mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, + remain_len, &pstr->cur_state); + if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + pstr->cur_state = prev_st; + } + /* Then proceed the next character. */ + rawbuf_idx += mbclen; + } + *last_wc = (wint_t) wc; + return rawbuf_idx; +} +#endif /* RE_ENABLE_I18N */ + +/* Build the buffer PSTR->MBS, and apply the translation if we need. + This function is used in case of REG_ICASE. */ + +static void +internal_function +build_upper_buffer (re_string_t *pstr) +{ + int char_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; + if (BE (pstr->trans != NULL, 0)) + ch = pstr->trans[ch]; + if (islower (ch)) + pstr->mbs[char_idx] = __toupper (ch); + else + pstr->mbs[char_idx] = ch; + } + pstr->valid_len = char_idx; + pstr->valid_raw_len = char_idx; +} + +/* Apply TRANS to the buffer in PSTR. */ + +static void +internal_function +re_string_translate_buffer (re_string_t *pstr) +{ + int buf_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; + pstr->mbs[buf_idx] = pstr->trans[ch]; + } + + pstr->valid_len = buf_idx; + pstr->valid_raw_len = buf_idx; +} + +/* This function re-construct the buffers. + Concretely, convert to wide character in case of pstr->mb_cur_max > 1, + convert to upper case in case of REG_ICASE, apply translation. */ + +static reg_errcode_t +internal_function +re_string_reconstruct (re_string_t *pstr, int idx, int eflags) +{ + int offset = idx - pstr->raw_mbs_idx; + if (BE (offset < 0, 0)) + { + /* Reset buffer. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); +#endif /* RE_ENABLE_I18N */ + pstr->len = pstr->raw_len; + pstr->stop = pstr->raw_stop; + pstr->valid_len = 0; + pstr->raw_mbs_idx = 0; + pstr->valid_raw_len = 0; + pstr->offsets_needed = 0; + pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF); + if (!pstr->mbs_allocated) + pstr->mbs = (unsigned char *) pstr->raw_mbs; + offset = idx; + } + + if (BE (offset != 0, 1)) + { + /* Are the characters which are already checked remain? */ + if (BE (offset < pstr->valid_raw_len, 1) +#ifdef RE_ENABLE_I18N + /* Handling this would enlarge the code too much. + Accept a slowdown in that case. */ + && pstr->offsets_needed == 0 +#endif + ) + { + /* Yes, move them to the front of the buffer. */ + pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); +#endif /* RE_ENABLE_I18N */ + if (BE (pstr->mbs_allocated, 0)) + memmove (pstr->mbs, pstr->mbs + offset, + pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; +#if DEBUG + assert (pstr->valid_len > 0); +#endif + } + else + { + /* No, skip all characters until IDX. */ +#ifdef RE_ENABLE_I18N + if (BE (pstr->offsets_needed, 0)) + { + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + } +#endif + pstr->valid_len = 0; + pstr->valid_raw_len = 0; +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + int wcs_idx; + wint_t wc = WEOF; + + if (pstr->is_utf8) + { + const unsigned char *raw, *p, *q, *end; + + /* Special case UTF-8. Multi-byte chars start with any + byte other than 0x80 - 0xbf. */ + raw = pstr->raw_mbs + pstr->raw_mbs_idx; + end = raw + (offset - pstr->mb_cur_max); + p = raw + offset - 1; +#ifdef _LIBC + /* We know the wchar_t encoding is UCS4, so for the simple + case, ASCII characters, skip the conversion step. */ + if (isascii (*p) && BE (pstr->trans == NULL, 1)) + { + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + pstr->valid_len = 0; + wc = (wchar_t) *p; + } + else +#endif + for (; p >= end; --p) + if ((*p & 0xc0) != 0x80) + { + mbstate_t cur_state; + wchar_t wc2; + int mlen = raw + pstr->len - p; + unsigned char buf[6]; + size_t mbclen; + + q = p; + if (BE (pstr->trans != NULL, 0)) + { + int i = mlen < 6 ? mlen : 6; + while (--i >= 0) + buf[i] = pstr->trans[p[i]]; + q = buf; + } + /* XXX Don't use mbrtowc, we know which conversion + to use (UTF-8 -> UCS4). */ + memset (&cur_state, 0, sizeof (cur_state)); + mbclen = mbrtowc (&wc2, (const char *) p, mlen, + &cur_state); + if (raw + offset - p <= mbclen + && mbclen < (size_t) -2) + { + memset (&pstr->cur_state, '\0', + sizeof (mbstate_t)); + pstr->valid_len = mbclen - (raw + offset - p); + wc = wc2; + } + break; + } + } + + if (wc == WEOF) + pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; + if (BE (pstr->valid_len, 0)) + { + for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) + pstr->wcs[wcs_idx] = WEOF; + if (pstr->mbs_allocated) + memset (pstr->mbs, 255, pstr->valid_len); + } + pstr->valid_raw_len = pstr->valid_len; + pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) + && IS_WIDE_WORD_CHAR (wc)) + ? CONTEXT_WORD + : ((IS_WIDE_NEWLINE (wc) + && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + else +#endif /* RE_ENABLE_I18N */ + { + int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; + if (pstr->trans) + c = pstr->trans[c]; + pstr->tip_context = (bitset_contain (pstr->word_char, c) + ? CONTEXT_WORD + : ((IS_NEWLINE (c) && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + } + if (!BE (pstr->mbs_allocated, 0)) + pstr->mbs += offset; + } + pstr->raw_mbs_idx = idx; + pstr->len -= offset; + pstr->stop -= offset; + + /* Then build the buffers. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + if (pstr->icase) + { + reg_errcode_t ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + else + build_wcs_buffer (pstr); + } + else +#endif /* RE_ENABLE_I18N */ + if (BE (pstr->mbs_allocated, 0)) + { + if (pstr->icase) + build_upper_buffer (pstr); + else if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + else + pstr->valid_len = pstr->len; + + pstr->cur_idx = 0; + return REG_NOERROR; +} + +static unsigned char +internal_function __attribute ((pure)) +re_string_peek_byte_case (const re_string_t *pstr, int idx) +{ + int ch, off; + + /* Handle the common (easiest) cases first. */ + if (BE (!pstr->mbs_allocated, 1)) + return re_string_peek_byte (pstr, idx); + +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1 + && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) + return re_string_peek_byte (pstr, idx); +#endif + + off = pstr->cur_idx + idx; +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + off = pstr->offsets[off]; +#endif + + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + +#ifdef RE_ENABLE_I18N + /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I + this function returns CAPITAL LETTER I instead of first byte of + DOTLESS SMALL LETTER I. The latter would confuse the parser, + since peek_byte_case doesn't advance cur_idx in any way. */ + if (pstr->offsets_needed && !isascii (ch)) + return re_string_peek_byte (pstr, idx); +#endif + + return ch; +} + +static unsigned char +internal_function __attribute ((pure)) +re_string_fetch_byte_case (re_string_t *pstr) +{ + if (BE (!pstr->mbs_allocated, 1)) + return re_string_fetch_byte (pstr); + +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + { + int off, ch; + + /* For tr_TR.UTF-8 [[:islower:]] there is + [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip + in that case the whole multi-byte character and return + the original letter. On the other side, with + [[: DOTLESS SMALL LETTER I return [[:I, as doing + anything else would complicate things too much. */ + + if (!re_string_first_byte (pstr, pstr->cur_idx)) + return re_string_fetch_byte (pstr); + + off = pstr->offsets[pstr->cur_idx]; + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + + if (! isascii (ch)) + return re_string_fetch_byte (pstr); + + re_string_skip_bytes (pstr, + re_string_char_size_at (pstr, pstr->cur_idx)); + return ch; + } +#endif + + return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; +} + +static void +internal_function +re_string_destruct (re_string_t *pstr) +{ +#ifdef RE_ENABLE_I18N + re_free (pstr->wcs); + re_free (pstr->offsets); +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + re_free (pstr->mbs); +} + +/* Return the context at IDX in INPUT. */ + +static unsigned int +internal_function +re_string_context_at (const re_string_t *input, int idx, int eflags) +{ + int c; + if (BE (idx < 0, 0)) + /* In this case, we use the value stored in input->tip_context, + since we can't know the character in input->mbs[-1] here. */ + return input->tip_context; + if (BE (idx == input->len, 0)) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc; + int wc_idx = idx; + while(input->wcs[wc_idx] == WEOF) + { +#ifdef DEBUG + /* It must not happen. */ + assert (wc_idx >= 0); +#endif + --wc_idx; + if (wc_idx < 0) + return input->tip_context; + } + wc = input->wcs[wc_idx]; + if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) + return CONTEXT_WORD; + return (IS_WIDE_NEWLINE (wc) && input->newline_anchor + ? CONTEXT_NEWLINE : 0); + } + else +#endif + { + c = re_string_byte_at (input, idx); + if (bitset_contain (input->word_char, c)) + return CONTEXT_WORD; + return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; + } +} + +/* Functions for set operation. */ + +static reg_errcode_t +internal_function +re_node_set_alloc (re_node_set *set, int size) +{ + set->alloc = size; + set->nelem = 0; + set->elems = re_malloc (int, size); /* can be NULL if size == 0 + (see re_node_set_init_empty(set)) */ + if (BE (set->elems == NULL && size != 0, 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_1 (re_node_set *set, int elem) +{ + set->alloc = 1; + set->nelem = 1; + set->elems = re_malloc (int, 1); + if (BE (set->elems == NULL, 0)) + { + set->alloc = set->nelem = 0; + return REG_ESPACE; + } + set->elems[0] = elem; + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_2 (re_node_set *set, int elem1, int elem2) +{ + set->alloc = 2; + set->elems = re_malloc (int, 2); + if (BE (set->elems == NULL, 0)) + return REG_ESPACE; + if (elem1 == elem2) + { + set->nelem = 1; + set->elems[0] = elem1; + } + else + { + set->nelem = 2; + if (elem1 < elem2) + { + set->elems[0] = elem1; + set->elems[1] = elem2; + } + else + { + set->elems[0] = elem2; + set->elems[1] = elem1; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_copy (re_node_set *dest, const re_node_set *src) +{ + dest->nelem = src->nelem; + if (src->nelem > 0) + { + dest->alloc = dest->nelem; + dest->elems = re_malloc (int, dest->alloc); + if (BE (dest->elems == NULL, 0)) + { + dest->alloc = dest->nelem = 0; + return REG_ESPACE; + } + memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); + } + else + re_node_set_init_empty (dest); + return REG_NOERROR; +} + +/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. + Note: We assume dest->elems is NULL, when dest->alloc is 0. */ + +static reg_errcode_t +internal_function +re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + int i1, i2, is, id, delta, sbase; + if (src1->nelem == 0 || src2->nelem == 0) + return REG_NOERROR; + + /* We need dest->nelem + 2 * elems_in_intersection; this is a + conservative estimate. */ + if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) + { + int new_alloc = src1->nelem + src2->nelem + dest->alloc; + int *new_elems = re_realloc (dest->elems, int, new_alloc); + if (BE (new_elems == NULL, 0)) + return REG_ESPACE; + dest->elems = new_elems; + dest->alloc = new_alloc; + } + + /* Find the items in the intersection of SRC1 and SRC2, and copy + into the top of DEST those that are not already in DEST itself. */ + sbase = dest->nelem + src1->nelem + src2->nelem; + i1 = src1->nelem - 1; + i2 = src2->nelem - 1; + id = dest->nelem - 1; + for (;;) + { + if (src1->elems[i1] == src2->elems[i2]) + { + /* Try to find the item in DEST. Maybe we could binary search? */ + while (id >= 0 && dest->elems[id] > src1->elems[i1]) + --id; + + if (id < 0 || dest->elems[id] != src1->elems[i1]) + dest->elems[--sbase] = src1->elems[i1]; + + if (--i1 < 0 || --i2 < 0) + break; + } + + /* Lower the highest of the two items. */ + else if (src1->elems[i1] < src2->elems[i2]) + { + if (--i2 < 0) + break; + } + else + { + if (--i1 < 0) + break; + } + } + + id = dest->nelem - 1; + is = dest->nelem + src1->nelem + src2->nelem - 1; + delta = is - sbase + 1; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place; this is more or + less the same loop that is in re_node_set_merge. */ + dest->nelem += delta; + if (delta > 0 && id >= 0) + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + break; + } + } + + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); + + return REG_NOERROR; +} + +/* Calculate the union set of the sets SRC1 and SRC2. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +internal_function +re_node_set_init_union (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + int i1, i2, id; + if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) + { + dest->alloc = src1->nelem + src2->nelem; + dest->elems = re_malloc (int, dest->alloc); + if (BE (dest->elems == NULL, 0)) + return REG_ESPACE; + } + else + { + if (src1 != NULL && src1->nelem > 0) + return re_node_set_init_copy (dest, src1); + else if (src2 != NULL && src2->nelem > 0) + return re_node_set_init_copy (dest, src2); + else + re_node_set_init_empty (dest); + return REG_NOERROR; + } + for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) + { + if (src1->elems[i1] > src2->elems[i2]) + { + dest->elems[id++] = src2->elems[i2++]; + continue; + } + if (src1->elems[i1] == src2->elems[i2]) + ++i2; + dest->elems[id++] = src1->elems[i1++]; + } + if (i1 < src1->nelem) + { + memcpy (dest->elems + id, src1->elems + i1, + (src1->nelem - i1) * sizeof (int)); + id += src1->nelem - i1; + } + else if (i2 < src2->nelem) + { + memcpy (dest->elems + id, src2->elems + i2, + (src2->nelem - i2) * sizeof (int)); + id += src2->nelem - i2; + } + dest->nelem = id; + return REG_NOERROR; +} + +/* Calculate the union set of the sets DEST and SRC. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +internal_function +re_node_set_merge (re_node_set *dest, const re_node_set *src) +{ + int is, id, sbase, delta; + if (src == NULL || src->nelem == 0) + return REG_NOERROR; + if (dest->alloc < 2 * src->nelem + dest->nelem) + { + int new_alloc = 2 * (src->nelem + dest->alloc); + int *new_buffer = re_realloc (dest->elems, int, new_alloc); + if (BE (new_buffer == NULL, 0)) + return REG_ESPACE; + dest->elems = new_buffer; + dest->alloc = new_alloc; + } + + if (BE (dest->nelem == 0, 0)) + { + dest->nelem = src->nelem; + memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); + return REG_NOERROR; + } + + /* Copy into the top of DEST the items of SRC that are not + found in DEST. Maybe we could binary search in DEST? */ + for (sbase = dest->nelem + 2 * src->nelem, + is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) + { + if (dest->elems[id] == src->elems[is]) + is--, id--; + else if (dest->elems[id] < src->elems[is]) + dest->elems[--sbase] = src->elems[is--]; + else /* if (dest->elems[id] > src->elems[is]) */ + --id; + } + + if (is >= 0) + { + /* If DEST is exhausted, the remaining items of SRC must be unique. */ + sbase -= is + 1; + memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); + } + + id = dest->nelem - 1; + is = dest->nelem + 2 * src->nelem - 1; + delta = is - sbase + 1; + if (delta == 0) + return REG_NOERROR; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place. */ + dest->nelem += delta; + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + { + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, + delta * sizeof (int)); + break; + } + } + } + + return REG_NOERROR; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have ELEM. + return -1 if an error is occured, return 1 otherwise. */ + +static int +internal_function +re_node_set_insert (re_node_set *set, int elem) +{ + int idx; + /* In case the set is empty. */ + if (set->alloc == 0) + { + if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) + return 1; + else + return -1; + } + + if (BE (set->nelem, 0) == 0) + { + /* We already guaranteed above that set->alloc != 0. */ + set->elems[0] = elem; + ++set->nelem; + return 1; + } + + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + int *new_elems; + set->alloc = set->alloc * 2; + new_elems = re_realloc (set->elems, int, set->alloc); + if (BE (new_elems == NULL, 0)) + return -1; + set->elems = new_elems; + } + + /* Move the elements which follows the new element. Test the + first element separately to skip a check in the inner loop. */ + if (elem < set->elems[0]) + { + idx = 0; + for (idx = set->nelem; idx > 0; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + else + { + for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + + /* Insert the new element. */ + set->elems[idx] = elem; + ++set->nelem; + return 1; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have any element greater than or equal to ELEM. + Return -1 if an error is occured, return 1 otherwise. */ + +static int +internal_function +re_node_set_insert_last (re_node_set *set, int elem) +{ + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + int *new_elems; + set->alloc = (set->alloc + 1) * 2; + new_elems = re_realloc (set->elems, int, set->alloc); + if (BE (new_elems == NULL, 0)) + return -1; + set->elems = new_elems; + } + + /* Insert the new element. */ + set->elems[set->nelem++] = elem; + return 1; +} + +/* Compare two node sets SET1 and SET2. + return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ + +static int +internal_function __attribute ((pure)) +re_node_set_compare (const re_node_set *set1, const re_node_set *set2) +{ + int i; + if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) + return 0; + for (i = set1->nelem ; --i >= 0 ; ) + if (set1->elems[i] != set2->elems[i]) + return 0; + return 1; +} + +/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ + +static int +internal_function __attribute ((pure)) +re_node_set_contains (const re_node_set *set, int elem) +{ + unsigned int idx, right, mid; + if (set->nelem <= 0) + return 0; + + /* Binary search the element. */ + idx = 0; + right = set->nelem - 1; + while (idx < right) + { + mid = (idx + right) / 2; + if (set->elems[mid] < elem) + idx = mid + 1; + else + right = mid; + } + return set->elems[idx] == elem ? idx + 1 : 0; +} + +static void +internal_function +re_node_set_remove_at (re_node_set *set, int idx) +{ + if (idx < 0 || idx >= set->nelem) + return; + --set->nelem; + for (; idx < set->nelem; idx++) + set->elems[idx] = set->elems[idx + 1]; +} + + +/* Add the token TOKEN to dfa->nodes, and return the index of the token. + Or return -1, if an error will be occured. */ + +static int +internal_function +re_dfa_add_node (re_dfa_t *dfa, re_token_t token) +{ +#ifdef RE_ENABLE_I18N + int type = token.type; +#endif + if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) + { + size_t new_nodes_alloc = dfa->nodes_alloc * 2; + int *new_nexts, *new_indices; + re_node_set *new_edests, *new_eclosures; + re_token_t *new_nodes; + + /* Avoid overflows. */ + if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) + return -1; + + new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); + if (BE (new_nodes == NULL, 0)) + return -1; + dfa->nodes = new_nodes; + new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); + new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); + new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); + new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); + if (BE (new_nexts == NULL || new_indices == NULL + || new_edests == NULL || new_eclosures == NULL, 0)) + return -1; + dfa->nexts = new_nexts; + dfa->org_indices = new_indices; + dfa->edests = new_edests; + dfa->eclosures = new_eclosures; + dfa->nodes_alloc = new_nodes_alloc; + } + dfa->nodes[dfa->nodes_len] = token; + dfa->nodes[dfa->nodes_len].constraint = 0; +#ifdef RE_ENABLE_I18N + dfa->nodes[dfa->nodes_len].accept_mb = + (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; +#endif + dfa->nexts[dfa->nodes_len] = -1; + re_node_set_init_empty (dfa->edests + dfa->nodes_len); + re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); + return dfa->nodes_len++; +} + +static __inline__ unsigned int +internal_function +calc_state_hash (const re_node_set *nodes, unsigned int context) +{ + unsigned int hash = nodes->nelem + context; + int i; + for (i = 0 ; i < nodes->nelem ; i++) + hash += nodes->elems[i]; + return hash; +} + +/* Search for the state whose node_set is equivalent to NODES. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +internal_function +re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes) +{ + unsigned int hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + int i; + if (BE (nodes->nelem == 0, 0)) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, 0); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (hash != state->hash) + continue; + if (re_node_set_compare (&state->nodes, nodes)) + return state; + } + + /* There are no appropriate state in the dfa, create the new one. */ + new_state = create_ci_newstate (dfa, nodes, hash); + if (BE (new_state == NULL, 0)) + *err = REG_ESPACE; + + return new_state; +} + +/* Search for the state whose node_set is equivalent to NODES and + whose context is equivalent to CONTEXT. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +internal_function +re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes, unsigned int context) +{ + unsigned int hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + int i; + if (nodes->nelem == 0) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, context); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (state->hash == hash + && state->context == context + && re_node_set_compare (state->entrance_nodes, nodes)) + return state; + } + /* There are no appropriate state in `dfa', create the new one. */ + new_state = create_cd_newstate (dfa, nodes, context, hash); + if (BE (new_state == NULL, 0)) + *err = REG_ESPACE; + + return new_state; +} + +/* Finish initialization of the new state NEWSTATE, and using its hash value + HASH put in the appropriate bucket of DFA's state table. Return value + indicates the error code if failed. */ + +static reg_errcode_t +register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, + unsigned int hash) +{ + struct re_state_table_entry *spot; + reg_errcode_t err; + int i; + + newstate->hash = hash; + err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); + if (BE (err != REG_NOERROR, 0)) + return REG_ESPACE; + for (i = 0; i < newstate->nodes.nelem; i++) + { + int elem = newstate->nodes.elems[i]; + if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) + re_node_set_insert_last (&newstate->non_eps_nodes, elem); + } + + spot = dfa->state_table + (hash & dfa->state_hash_mask); + if (BE (spot->alloc <= spot->num, 0)) + { + int new_alloc = 2 * spot->num + 2; + re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, + new_alloc); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + spot->array = new_array; + spot->alloc = new_alloc; + } + spot->array[spot->num++] = newstate; + return REG_NOERROR; +} + +static void +free_state (re_dfastate_t *state) +{ + re_node_set_free (&state->non_eps_nodes); + re_node_set_free (&state->inveclosure); + if (state->entrance_nodes != &state->nodes) + { + re_node_set_free (state->entrance_nodes); + re_free (state->entrance_nodes); + } + re_node_set_free (&state->nodes); + re_free (state->word_trtable); + re_free (state->trtable); + re_free (state); +} + +/* Create the new state which is independ of contexts. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +internal_function +create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int hash) +{ + int i; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (BE (newstate == NULL, 0)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_free (newstate); + return NULL; + } + + newstate->entrance_nodes = &newstate->nodes; + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + if (type == CHARACTER && !node->constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif /* RE_ENABLE_I18N */ + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR || node->constraint) + newstate->has_constraint = 1; + } + err = register_state (dfa, newstate, hash); + if (BE (err != REG_NOERROR, 0)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} + +/* Create the new state which is depend on the context CONTEXT. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +internal_function +create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int context, unsigned int hash) +{ + int i, nctx_nodes = 0; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (BE (newstate == NULL, 0)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_free (newstate); + return NULL; + } + + newstate->context = context; + newstate->entrance_nodes = &newstate->nodes; + + for (i = 0 ; i < nodes->nelem ; i++) + { + unsigned int constraint = 0; + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + if (node->constraint) + constraint = node->constraint; + + if (type == CHARACTER && !constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif /* RE_ENABLE_I18N */ + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR) + constraint = node->opr.ctx_type; + + if (constraint) + { + if (newstate->entrance_nodes == &newstate->nodes) + { + newstate->entrance_nodes = re_malloc (re_node_set, 1); + if (BE (newstate->entrance_nodes == NULL, 0)) + { + free_state (newstate); + return NULL; + } + re_node_set_init_copy (newstate->entrance_nodes, nodes); + nctx_nodes = 0; + newstate->has_constraint = 1; + } + + if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) + { + re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); + ++nctx_nodes; + } + } + } + err = register_state (dfa, newstate, hash); + if (BE (err != REG_NOERROR, 0)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} diff --git a/libc/misc/regex/regex_internal.h b/libc/misc/regex/regex_internal.h new file mode 100644 index 0000000..725e33a --- /dev/null +++ b/libc/misc/regex/regex_internal.h @@ -0,0 +1,761 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEX_INTERNAL_H +#define _REGEX_INTERNAL_H 1 + +#include +#include +#include +#include +#include + +#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC +# include +libc_hidden_proto(nl_langinfo) +#endif +#if defined HAVE_LOCALE_H || defined _LIBC +# include +#endif +#if defined HAVE_WCHAR_H || defined _LIBC +# include +#endif /* HAVE_WCHAR_H || _LIBC */ +#if defined HAVE_WCTYPE_H || defined _LIBC +# include +#endif /* HAVE_WCTYPE_H || _LIBC */ +#if defined HAVE_STDBOOL_H || defined _LIBC +# include +#endif /* HAVE_STDBOOL_H || _LIBC */ +#if defined HAVE_STDINT_H || defined _LIBC +# include +#endif /* HAVE_STDINT_H || _LIBC */ +#if defined _LIBC +# include +#else +# define __libc_lock_define(CLASS,NAME) +# define __libc_lock_init(NAME) do { } while (0) +# define __libc_lock_lock(NAME) do { } while (0) +# define __libc_lock_unlock(NAME) do { } while (0) +#endif + +/* In case that the system doesn't have isblank(). */ +#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank && !defined __UCLIBC__ +# define isblank(ch) ((ch) == ' ' || (ch) == '\t') +#endif + +#if defined _LIBC && !defined __UCLIBC__ +# ifndef _RE_DEFINE_LOCALE_FUNCTIONS +# define _RE_DEFINE_LOCALE_FUNCTIONS 1 +# include +# include +# include +# endif +#endif + +/* This is for other GNU distributions with internationalized messages. */ +#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC +# include +# ifdef _LIBC +# undef gettext +# define gettext(msgid) \ + INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) +# endif +#else +# define gettext(msgid) (msgid) +#endif + +#ifndef gettext_noop +/* This define is so xgettext can find the internationalizable + strings. */ +# define gettext_noop(String) String +#endif + +#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC +# define RE_ENABLE_I18N +#endif + +#if __GNUC__ >= 3 +# define BE(expr, val) __builtin_expect (expr, val) +#else +# define BE(expr, val) (expr) +# define inline +#endif + +/* Number of single byte character. */ +#define SBC_MAX 256 + +#define COLL_ELEM_LEN_MAX 8 + +/* The character which represents newline. */ +#define NEWLINE_CHAR '\n' +#define WIDE_NEWLINE_CHAR L'\n' + +/* Rename to standard API for using out of glibc. */ +#if !defined _LIBC && !defined __UCLIBC__ +# define __wctype wctype +# define __iswctype iswctype +# define __btowc btowc +# define __mempcpy mempcpy +# define __wcrtomb wcrtomb +# define __regfree regfree +# define attribute_hidden +#endif /* not _LIBC */ + +#ifdef __GNUC__ +# define __attribute(arg) __attribute__ (arg) +#else +# define __attribute(arg) +#endif + +extern const char __re_error_msgid[] attribute_hidden; +extern const size_t __re_error_msgid_idx[] attribute_hidden; + +/* An integer used to represent a set of bits. It must be unsigned, + and must be at least as wide as unsigned int. */ +typedef unsigned long int bitset_word_t; +/* All bits set in a bitset_word_t. */ +#define BITSET_WORD_MAX ULONG_MAX +/* Number of bits in a bitset_word_t. */ +#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT) +/* Number of bitset_word_t in a bit_set. */ +#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS) +typedef bitset_word_t bitset_t[BITSET_WORDS]; +typedef bitset_word_t *re_bitset_ptr_t; +typedef const bitset_word_t *re_const_bitset_ptr_t; + +#define bitset_set(set,i) \ + (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS) +#define bitset_clear(set,i) \ + (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS)) +#define bitset_contain(set,i) \ + (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS)) +#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t)) +#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t)) +#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t)) + +#define PREV_WORD_CONSTRAINT 0x0001 +#define PREV_NOTWORD_CONSTRAINT 0x0002 +#define NEXT_WORD_CONSTRAINT 0x0004 +#define NEXT_NOTWORD_CONSTRAINT 0x0008 +#define PREV_NEWLINE_CONSTRAINT 0x0010 +#define NEXT_NEWLINE_CONSTRAINT 0x0020 +#define PREV_BEGBUF_CONSTRAINT 0x0040 +#define NEXT_ENDBUF_CONSTRAINT 0x0080 +#define WORD_DELIM_CONSTRAINT 0x0100 +#define NOT_WORD_DELIM_CONSTRAINT 0x0200 + +typedef enum +{ + INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + LINE_FIRST = PREV_NEWLINE_CONSTRAINT, + LINE_LAST = NEXT_NEWLINE_CONSTRAINT, + BUF_FIRST = PREV_BEGBUF_CONSTRAINT, + BUF_LAST = NEXT_ENDBUF_CONSTRAINT, + WORD_DELIM = WORD_DELIM_CONSTRAINT, + NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT +} re_context_type; + +typedef struct +{ + int alloc; + int nelem; + int *elems; +} re_node_set; + +typedef enum +{ + NON_TYPE = 0, + + /* Node type, These are used by token, node, tree. */ + CHARACTER = 1, + END_OF_RE = 2, + SIMPLE_BRACKET = 3, + OP_BACK_REF = 4, + OP_PERIOD = 5, +#ifdef RE_ENABLE_I18N + COMPLEX_BRACKET = 6, + OP_UTF8_PERIOD = 7, +#endif /* RE_ENABLE_I18N */ + + /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used + when the debugger shows values of this enum type. */ +#define EPSILON_BIT 8 + OP_OPEN_SUBEXP = EPSILON_BIT | 0, + OP_CLOSE_SUBEXP = EPSILON_BIT | 1, + OP_ALT = EPSILON_BIT | 2, + OP_DUP_ASTERISK = EPSILON_BIT | 3, + ANCHOR = EPSILON_BIT | 4, + + /* Tree type, these are used only by tree. */ + CONCAT = 16, + SUBEXP = 17, + + /* Token type, these are used only by token. */ + OP_DUP_PLUS = 18, + OP_DUP_QUESTION, + OP_OPEN_BRACKET, + OP_CLOSE_BRACKET, + OP_CHARSET_RANGE, + OP_OPEN_DUP_NUM, + OP_CLOSE_DUP_NUM, + OP_NON_MATCH_LIST, + OP_OPEN_COLL_ELEM, + OP_CLOSE_COLL_ELEM, + OP_OPEN_EQUIV_CLASS, + OP_CLOSE_EQUIV_CLASS, + OP_OPEN_CHAR_CLASS, + OP_CLOSE_CHAR_CLASS, + OP_WORD, + OP_NOTWORD, + OP_SPACE, + OP_NOTSPACE, + BACK_SLASH + +} re_token_type_t; + +#ifdef RE_ENABLE_I18N +typedef struct +{ + /* Multibyte characters. */ + wchar_t *mbchars; + + /* Collating symbols. */ +# ifdef _LIBC + int32_t *coll_syms; +# endif + + /* Equivalence classes. */ +# ifdef _LIBC + int32_t *equiv_classes; +# endif + + /* Range expressions. */ +# ifdef _LIBC + uint32_t *range_starts; + uint32_t *range_ends; +# else /* not _LIBC */ + wchar_t *range_starts; + wchar_t *range_ends; +# endif /* not _LIBC */ + + /* Character classes. */ + wctype_t *char_classes; + + /* If this character set is the non-matching list. */ + unsigned int non_match : 1; + + /* # of multibyte characters. */ + int nmbchars; + + /* # of collating symbols. */ + int ncoll_syms; + + /* # of equivalence classes. */ + int nequiv_classes; + + /* # of range expressions. */ + int nranges; + + /* # of character classes. */ + int nchar_classes; +} re_charset_t; +#endif /* RE_ENABLE_I18N */ + +typedef struct +{ + union + { + unsigned char c; /* for CHARACTER */ + re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; /* for COMPLEX_BRACKET */ +#endif /* RE_ENABLE_I18N */ + int idx; /* for BACK_REF */ + re_context_type ctx_type; /* for ANCHOR */ + } opr; +#if __GNUC__ >= 2 + re_token_type_t type : 8; +#else + re_token_type_t type; +#endif + unsigned int constraint : 10; /* context constraint */ + unsigned int duplicated : 1; + unsigned int opt_subexp : 1; +#ifdef RE_ENABLE_I18N + unsigned int accept_mb : 1; + /* These 2 bits can be moved into the union if needed (e.g. if running out + of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ + unsigned int mb_partial : 1; +#endif + unsigned int word_char : 1; +} re_token_t; + +#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) + +struct re_string_t +{ + /* Indicate the raw buffer which is the original string passed as an + argument of regexec(), re_search(), etc.. */ + const unsigned char *raw_mbs; + /* Store the multibyte string. In case of "case insensitive mode" like + REG_ICASE, upper cases of the string are stored, otherwise MBS points + the same address that RAW_MBS points. */ + unsigned char *mbs; +#ifdef RE_ENABLE_I18N + /* Store the wide character string which is corresponding to MBS. */ + wint_t *wcs; + int *offsets; + mbstate_t cur_state; +#endif + /* Index in RAW_MBS. Each character mbs[i] corresponds to + raw_mbs[raw_mbs_idx + i]. */ + int raw_mbs_idx; + /* The length of the valid characters in the buffers. */ + int valid_len; + /* The corresponding number of bytes in raw_mbs array. */ + int valid_raw_len; + /* The length of the buffers MBS and WCS. */ + int bufs_len; + /* The index in MBS, which is updated by re_string_fetch_byte. */ + int cur_idx; + /* length of RAW_MBS array. */ + int raw_len; + /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ + int len; + /* End of the buffer may be shorter than its length in the cases such + as re_match_2, re_search_2. Then, we use STOP for end of the buffer + instead of LEN. */ + int raw_stop; + /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ + int stop; + + /* The context of mbs[0]. We store the context independently, since + the context of mbs[0] may be different from raw_mbs[0], which is + the beginning of the input string. */ + unsigned int tip_context; + /* The translation passed as a part of an argument of re_compile_pattern. */ + RE_TRANSLATE_TYPE trans; + /* Copy of re_dfa_t's word_char. */ + re_const_bitset_ptr_t word_char; + /* 1 if REG_ICASE. */ + unsigned char icase; + unsigned char is_utf8; + unsigned char map_notascii; + unsigned char mbs_allocated; + unsigned char offsets_needed; + unsigned char newline_anchor; + unsigned char word_ops_used; + int mb_cur_max; +}; +typedef struct re_string_t re_string_t; + + +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + +#if !defined _LIBC && !defined __UCLIBC__ +# ifdef __i386__ +# define internal_function __attribute ((regparm (3), stdcall)) +# else +# define internal_function +# endif +#endif + +static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, + int new_buf_len) + internal_function; +#ifdef RE_ENABLE_I18N +static void build_wcs_buffer (re_string_t *pstr) internal_function; +static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) internal_function; +#endif /* RE_ENABLE_I18N */ +static void build_upper_buffer (re_string_t *pstr) internal_function; +static void re_string_translate_buffer (re_string_t *pstr) internal_function; +static unsigned int re_string_context_at (const re_string_t *input, int idx, + int eflags) + internal_function __attribute ((pure)); +#define re_string_peek_byte(pstr, offset) \ + ((pstr)->mbs[(pstr)->cur_idx + offset]) +#define re_string_fetch_byte(pstr) \ + ((pstr)->mbs[(pstr)->cur_idx++]) +#define re_string_first_byte(pstr, idx) \ + ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) +#define re_string_is_single_byte_char(pstr, idx) \ + ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ + || (pstr)->wcs[(idx) + 1] != WEOF)) +#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) +#define re_string_cur_idx(pstr) ((pstr)->cur_idx) +#define re_string_get_buffer(pstr) ((pstr)->mbs) +#define re_string_length(pstr) ((pstr)->len) +#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) +#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) +#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) + +#include + +#ifndef _LIBC +# if HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. */ +# define __libc_use_alloca(n) ((n) < 4032) +# else +/* alloca is implemented with malloc, so just use malloc. */ +# define __libc_use_alloca(n) 0 +# endif +#endif + +#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +#define re_free(p) free (p) + +struct bin_tree_t +{ + struct bin_tree_t *parent; + struct bin_tree_t *left; + struct bin_tree_t *right; + struct bin_tree_t *first; + struct bin_tree_t *next; + + re_token_t token; + + /* `node_idx' is the index in dfa->nodes, if `type' == 0. + Otherwise `type' indicate the type of this node. */ + int node_idx; +}; +typedef struct bin_tree_t bin_tree_t; + +#define BIN_TREE_STORAGE_SIZE \ + ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) + +struct bin_tree_storage_t +{ + struct bin_tree_storage_t *next; + bin_tree_t data[BIN_TREE_STORAGE_SIZE]; +}; +typedef struct bin_tree_storage_t bin_tree_storage_t; + +#define CONTEXT_WORD 1 +#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) +#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) +#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) + +#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) +#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) +#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) +#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) +#define IS_ORDINARY_CONTEXT(c) ((c) == 0) + +#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') +#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) +#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') +#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) + +#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ + ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ + || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) + +#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ + ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ + || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) + +struct re_dfastate_t +{ + unsigned int hash; + re_node_set nodes; + re_node_set non_eps_nodes; + re_node_set inveclosure; + re_node_set *entrance_nodes; + struct re_dfastate_t **trtable, **word_trtable; + unsigned int context : 4; + unsigned int halt : 1; + /* If this state can accept `multi byte'. + Note that we refer to multibyte characters, and multi character + collating elements as `multi byte'. */ + unsigned int accept_mb : 1; + /* If this state has backreference node(s). */ + unsigned int has_backref : 1; + unsigned int has_constraint : 1; +}; +typedef struct re_dfastate_t re_dfastate_t; + +struct re_state_table_entry +{ + int num; + int alloc; + re_dfastate_t **array; +}; + +/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ + +typedef struct +{ + int next_idx; + int alloc; + re_dfastate_t **array; +} state_array_t; + +/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ + +typedef struct +{ + int node; + int str_idx; /* The position NODE match at. */ + state_array_t path; +} re_sub_match_last_t; + +/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. + And information about the node, whose type is OP_CLOSE_SUBEXP, + corresponding to NODE is stored in LASTS. */ + +typedef struct +{ + int str_idx; + int node; + state_array_t *path; + int alasts; /* Allocation size of LASTS. */ + int nlasts; /* The number of LASTS. */ + re_sub_match_last_t **lasts; +} re_sub_match_top_t; + +struct re_backref_cache_entry +{ + int node; + int str_idx; + int subexp_from; + int subexp_to; + char more; + char unused; + unsigned short int eps_reachable_subexps_map; +}; + +typedef struct +{ + /* The string object corresponding to the input string. */ + re_string_t input; +#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) + const re_dfa_t *const dfa; +#else + const re_dfa_t *dfa; +#endif + /* EFLAGS of the argument of regexec. */ + int eflags; + /* Where the matching ends. */ + int match_last; + int last_node; + /* The state log used by the matcher. */ + re_dfastate_t **state_log; + int state_log_top; + /* Back reference cache. */ + int nbkref_ents; + int abkref_ents; + struct re_backref_cache_entry *bkref_ents; + int max_mb_elem_len; + int nsub_tops; + int asub_tops; + re_sub_match_top_t **sub_tops; +} re_match_context_t; + +typedef struct +{ + re_dfastate_t **sifted_states; + re_dfastate_t **limited_states; + int last_node; + int last_str_idx; + re_node_set limits; +} re_sift_context_t; + +struct re_fail_stack_ent_t +{ + int idx; + int node; + regmatch_t *regs; + re_node_set eps_via_nodes; +}; + +struct re_fail_stack_t +{ + int num; + int alloc; + struct re_fail_stack_ent_t *stack; +}; + +struct re_dfa_t +{ + re_token_t *nodes; + size_t nodes_alloc; + size_t nodes_len; + int *nexts; + int *org_indices; + re_node_set *edests; + re_node_set *eclosures; + re_node_set *inveclosures; + struct re_state_table_entry *state_table; + re_dfastate_t *init_state; + re_dfastate_t *init_state_word; + re_dfastate_t *init_state_nl; + re_dfastate_t *init_state_begbuf; + bin_tree_t *str_tree; + bin_tree_storage_t *str_tree_storage; + re_bitset_ptr_t sb_char; + int str_tree_storage_idx; + + /* number of subexpressions `re_nsub' is in regex_t. */ + unsigned int state_hash_mask; + int init_node; + int nbackref; /* The number of backreference in this dfa. */ + + /* Bitmap expressing which backreference is used. */ + bitset_word_t used_bkref_map; + bitset_word_t completed_bkref_map; + + unsigned int has_plural_match : 1; + /* If this dfa has "multibyte node", which is a backreference or + a node which can accept multibyte character or multi character + collating element. */ + unsigned int has_mb_node : 1; + unsigned int is_utf8 : 1; + unsigned int map_notascii : 1; + unsigned int word_ops_used : 1; + int mb_cur_max; + bitset_t word_char; + reg_syntax_t syntax; + int *subexp_map; +#ifdef DEBUG + char* re_str; +#endif + __libc_lock_define (, lock) +}; + +#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) +#define re_node_set_remove(set,id) \ + (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) +#define re_node_set_empty(p) ((p)->nelem = 0) +#define re_node_set_free(set) re_free ((set)->elems) + + +typedef enum +{ + SB_CHAR, + MB_CHAR, + EQUIV_CLASS, + COLL_SYM, + CHAR_CLASS +} bracket_elem_type; + +typedef struct +{ + bracket_elem_type type; + union + { + unsigned char ch; + unsigned char *name; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t wch; +#endif + } opr; +} bracket_elem_t; + + +/* Inline functions for bitset operation. */ +static __inline__ void +bitset_not (bitset_t set) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + set[bitset_i] = ~set[bitset_i]; +} + +static __inline__ void +bitset_merge (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] |= src[bitset_i]; +} + +static __inline__ void +bitset_mask (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] &= src[bitset_i]; +} + +#ifdef RE_ENABLE_I18N +/* Inline functions for re_string. */ +static __inline__ int +internal_function __attribute ((pure)) +re_string_char_size_at (const re_string_t *pstr, int idx) +{ + int byte_idx; + if (pstr->mb_cur_max == 1) + return 1; + for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) + if (pstr->wcs[idx + byte_idx] != WEOF) + break; + return byte_idx; +} + +static __inline__ wint_t +internal_function __attribute ((pure)) +re_string_wchar_at (const re_string_t *pstr, int idx) +{ + if (pstr->mb_cur_max == 1) + return (wint_t) pstr->mbs[idx]; + return (wint_t) pstr->wcs[idx]; +} + +static int +internal_function __attribute ((pure)) +re_string_elem_size_at (const re_string_t *pstr, int idx) +{ +# ifdef _LIBC + const unsigned char *p, *extra; + const int32_t *table, *indirect; + int32_t tmp; +# include + uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + + if (nrules != 0) + { + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + p = pstr->mbs + idx; + tmp = findidx (&p); + return p - pstr->mbs - idx; + } + else +# endif /* _LIBC */ + return 1; +} +#endif /* RE_ENABLE_I18N */ + +#endif /* _REGEX_INTERNAL_H */ diff --git a/libc/misc/regex/regex_old.c b/libc/misc/regex/regex_old.c new file mode 100644 index 0000000..a8a8cc7 --- /dev/null +++ b/libc/misc/regex/regex_old.c @@ -0,0 +1,8361 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P1003.2/D11.2, except for some of the + internationalization features.) + Copyright (C) 1993-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* To exclude some unwanted junk.... */ +#undef emacs +#include +#ifdef __UCLIBC__ +# undef _LIBC +# define _REGEX_RE_COMP +# ifdef __USE_GNU +# define HAVE_MEMPCPY +# endif +# define STDC_HEADERS +# define RE_TRANSLATE_TYPE char * +#endif +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(printf) +libc_hidden_proto(abort) +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(mempcpy) */ +#endif + +/* AIX requires this to be the first thing in the file. */ +#if defined _AIX && !defined REGEX_MALLOC + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef INSIDE_RECURSION + +# if defined STDC_HEADERS && !defined emacs +# include +# else +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +# include +# endif + + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +#if defined __UCLIBC_HAS_WCHAR__ +# define WIDE_CHAR_SUPPORT 1 +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +libc_hidden_proto(wcslen) +libc_hidden_proto(mbrtowc) +libc_hidden_proto(wcrtomb) +libc_hidden_proto(wcscoll) +libc_hidden_proto(wctype) +libc_hidden_proto(iswctype) +libc_hidden_proto(iswalnum) +libc_hidden_proto(btowc) + +# endif + +# if defined _LIBC || defined __UCLIBC__ +/* We have to keep the namespace clean. */ +# define regfree(preg) __regfree (preg) +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) +# define regerror(errcode, preg, errbuf, errbuf_size) \ + __regerror(errcode, preg, errbuf, errbuf_size) +# define re_set_registers(bu, re, nu, st, en) \ + __re_set_registers (bu, re, nu, st, en) +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ + __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) +# define re_match(bufp, string, size, pos, regs) \ + __re_match (bufp, string, size, pos, regs) +# define re_search(bufp, string, size, startpos, range, regs) \ + __re_search (bufp, string, size, startpos, range, regs) +# define re_compile_pattern(pattern, length, bufp) \ + __re_compile_pattern (pattern, length, bufp) +# define re_set_syntax(syntax) __re_set_syntax (syntax) +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ + __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) + +# ifndef __UCLIBC__ +# define btowc __btowc + +/* We are also using some library internals. */ +# include +# include +# include +# include +# endif +# endif + +/* This is for other GNU distributions with internationalized messages. */ +# if HAVE_LIBINTL_H || defined _LIBC +# include +# ifdef _LIBC +# undef gettext +# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) +# endif +# else +# define gettext(msgid) (msgid) +# endif + +# ifndef gettext_noop +/* This define is so xgettext can find the internationalizable + strings. */ +# define gettext_noop(String) String +# endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +# ifdef emacs + +# include "lisp.h" +# include "buffer.h" +# include "syntax.h" + +# else /* not emacs */ + +/* If we are not linking with Emacs proper, + we can't use the relocating allocator + even if config.h says that we can. */ +# undef REL_ALLOC + +# if defined STDC_HEADERS || defined _LIBC +# include +# else +char *malloc (); +char *realloc (); +# endif + +/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. + If nothing else has been done, use the method below. */ +# ifdef INHIBIT_STRING_HEADER +# if !(defined HAVE_BZERO && defined HAVE_BCOPY) +# if !defined bzero && !defined bcopy +# undef INHIBIT_STRING_HEADER +# endif +# endif +# endif + +/* This is the normal way of making sure we have a bcopy and a bzero. + This is used in most programs--a few other programs avoid this + by defining INHIBIT_STRING_HEADER. */ +# ifndef INHIBIT_STRING_HEADER +# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC +# include +# ifndef bzero +# ifndef _LIBC +# define bzero(s, n) (memset (s, '\0', n), (s)) +# else +# define bzero(s, n) __bzero (s, n) +# endif +# endif +# else +# include +# ifndef memcmp +# define memcmp(s1, s2, n) bcmp (s1, s2, n) +# endif +# ifndef memcpy +# define memcpy(d, s, n) (bcopy (s, d, n), (d)) +# endif +# endif +# endif + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +# ifndef Sword +# define Sword 1 +# endif + +# ifdef SWITCH_ENUM_BUG +# define SWITCH_ENUM_CAST(x) ((int)(x)) +# else +# define SWITCH_ENUM_CAST(x) (x) +# endif + +# endif /* not emacs */ + +# if defined _LIBC || HAVE_LIMITS_H +# include +# endif + +# ifndef MB_LEN_MAX +# define MB_LEN_MAX 1 +# endif + +/* Get the interface, including the syntax bits. */ +# ifdef __UCLIBC__ +# include "_regex.h" +# endif +# include + +/* isalpha etc. are used for the character classes. */ +# include + +/* Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." + Solaris defines some of these symbols so we must undefine them first. */ + +# undef ISASCII +# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# undef ISPRINT +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# ifdef _tolower +# define TOLOWER(c) _tolower(c) +# else +# define TOLOWER(c) __tolower(c) +# endif + +# ifndef NULL +# define NULL (void *)0 +# endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +# undef SIGN_EXTEND_CHAR +# if __STDC__ +# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +# else /* not __STDC__ */ +/* As in Harbison and Steele. */ +# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +# endif + +# ifndef emacs +/* How many characters in the character set. */ +# define CHAR_SET_SIZE 256 + +# ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +# else /* not SYNTAX_TABLE */ + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void init_syntax_once (void); + +static void +init_syntax_once (void) +{ + register int c; + static int done = 0; + + if (done) + return; + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 0; c < CHAR_SET_SIZE; ++c) + if (ISALNUM (c)) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +# endif /* not SYNTAX_TABLE */ + +# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] + +# endif /* emacs */ + +/* Integer type for pointers. */ +# if !defined _LIBC && !defined __intptr_t_defined +typedef unsigned long int uintptr_t; +# endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +# ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE malloc +# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE free + +# else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +# ifndef alloca + +/* Make alloca work the best possible way. */ +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else /* not __GNUC__ */ +# if HAVE_ALLOCA_H +# include +# endif /* HAVE_ALLOCA_H */ +# endif /* not __GNUC__ */ + +# endif /* not alloca */ + +# define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +# define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + memcpy (destination, source, osize)) + +/* No need to do anything to free, after alloca. */ +# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ + +# endif /* not REGEX_MALLOC */ + +/* Define how to allocate the failure stack. */ + +# if defined REL_ALLOC && defined REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK(size) \ + r_alloc (&failure_stack_ptr, (size)) +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + r_re_alloc (&failure_stack_ptr, (nsize)) +# define REGEX_FREE_STACK(ptr) \ + r_alloc_free (&failure_stack_ptr) + +# else /* not using relocating allocator */ + +# ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK malloc +# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE_STACK free + +# else /* not REGEX_MALLOC */ + +# define REGEX_ALLOCATE_STACK alloca + +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + REGEX_REALLOCATE (source, osize, nsize) +/* No need to explicitly free anything. */ +# define REGEX_FREE_STACK(arg) + +# endif /* not REGEX_MALLOC */ +# endif /* not using relocating allocator */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +# define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +# define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) +# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +# define BYTEWIDTH 8 /* In bits. */ + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# undef MAX +# undef MIN +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +# define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +# define false 0 +# define true 1 + +static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + +static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop); +static int byte_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); + +#ifdef MBS_SUPPORT +static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + + +static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + wchar_t *string1, int size1, + wchar_t *string2, int size2, + int *mbs_offset1, int *mbs_offset2); +static int wcs_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); +#endif + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. */ + +typedef enum +{ + no_op = 0, + + /* Succeed right away--no more backtracking. */ + succeed, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn, + +# ifdef MBS_SUPPORT + /* Same as exactn, but contains binary data. */ + exactn_bin, +# endif + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + /* ifdef MBS_SUPPORT, following element is length of character + classes, length of collating symbols, length of equivalence + classes, length of character ranges, and length of characters. + Next, character class element, collating symbols elements, + equivalence class elements, range elements, and character + elements follow. + See regex_compile function. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +# ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +# endif /* emacs */ +} re_opcode_t; +#endif /* not INSIDE_RECURSION */ + + +#ifdef BYTE +# define CHAR_T char +# define UCHAR_T unsigned char +# define COMPILED_BUFFER_VAR bufp->buffer +# define OFFSET_ADDRESS_SIZE 2 +# define PREFIX(name) byte_##name +# define ARG_PREFIX(name) name +# define PUT_CHAR(c) putchar (c) +#else +# ifdef WCHAR +# define CHAR_T wchar_t +# define UCHAR_T wchar_t +# define COMPILED_BUFFER_VAR wc_buffer +# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ +# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) +# define PREFIX(name) wcs_##name +# define ARG_PREFIX(name) c##name +/* Should we use wide stream?? */ +# define PUT_CHAR(c) printf ("%C", c); +# define TRUE 1 +# define FALSE 0 +# else +# ifdef MBS_SUPPORT +# define WCHAR +# define INSIDE_RECURSION +# include "regex_old.c" +# undef INSIDE_RECURSION +# endif +# define BYTE +# define INSIDE_RECURSION +# include "regex_old.c" +# undef INSIDE_RECURSION +# endif +#endif + +#ifdef INSIDE_RECURSION +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# ifdef WCHAR +# define STORE_NUMBER(destination, number) \ + do { \ + *(destination) = (UCHAR_T)(number); \ + } while (0) +# else /* BYTE */ +# define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) +# endif /* WCHAR */ + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += OFFSET_ADDRESS_SIZE; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# ifdef WCHAR +# define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source); \ + } while (0) +# else /* BYTE */ +# define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) +# endif + +# ifdef DEBUG +static void PREFIX(extract_number) (int *dest, UCHAR_T *source) +{ +# ifdef WCHAR + *dest = *source; +# else /* BYTE */ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +# endif +} + +# ifndef EXTRACT_MACROS /* To debug the macros. */ +# undef EXTRACT_NUMBER +# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) +# endif /* not EXTRACT_MACROS */ + +# endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +# define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += OFFSET_ADDRESS_SIZE; \ + } while (0) + +# ifdef DEBUG +static void PREFIX(extract_number_and_incr) (int *destination, + UCHAR_T **source) +{ + PREFIX(extract_number) (destination, *source); + *source += OFFSET_ADDRESS_SIZE; +} + +# ifndef EXTRACT_MACROS +# undef EXTRACT_NUMBER_AND_INCR +# define EXTRACT_NUMBER_AND_INCR(dest, src) \ + PREFIX(extract_number_and_incr) (&dest, &src) +# endif /* not EXTRACT_MACROS */ + +# endif /* DEBUG */ + + + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +# ifdef DEBUG + +# ifndef DEFINED_ONCE + +/* We use standard I/O for debugging. */ +# include + +/* It is useful to test things that ``must'' be true when debugging. */ +# include + +static smallint debug; + +# define DEBUG_STATEMENT(e) e +# define DEBUG_PRINT1(x) if (debug) printf (x) +# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ + +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) PREFIX(print_partial_compiled_pattern) (s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) + + +/* Print the fastmap in human-readable form. */ + +# ifndef DEFINED_ONCE +void +print_fastmap (char *fastmap) +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + putchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + putchar (i - 1); + } + } + } + putchar ('\n'); +} +# endif /* not DEFINED_ONCE */ + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) +{ + int mcnt, mcnt2; + UCHAR_T *p1; + UCHAR_T *p = start; + UCHAR_T *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { +# ifdef _LIBC + printf ("%td:\t", p - start); +# else + printf ("%ld:\t", (long int) (p - start)); +# endif + + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + PUT_CHAR (*p++); + } + while (--mcnt); + break; + +# ifdef MBS_SUPPORT + case exactn_bin: + mcnt = *p++; + printf ("/exactn_bin/%d", mcnt); + do + { + printf("/%lx", (long int) *p++); + } + while (--mcnt); + break; +# endif /* MBS_SUPPORT */ + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); + break; + + case duplicate: + printf ("/duplicate/%ld", (long int) *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { +# ifdef WCHAR + int i, length; + wchar_t *workp = p; + printf ("/charset [%s", + (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); + p += 5; + length = *workp++; /* the length of char_classes */ + for (i=0 ; ibuffer; + + PREFIX(print_partial_compiled_pattern) (buffer, buffer + + bufp->used / sizeof(UCHAR_T)); + printf ("%ld bytes used/%ld bytes allocated.\n", + bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + +# ifdef _LIBC + printf ("re_nsub: %Zd\t", bufp->re_nsub); +# else + printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); +# endif + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %lx\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +PREFIX(print_double_string) ( + const CHAR_T *where, + const CHAR_T *string1, + int size1, + const CHAR_T *string2, + int size2) +{ + int this_char; + + if (where == NULL) + printf ("(null)"); + else + { + int cnt; + + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + PUT_CHAR (string1[this_char]); + + where = string2; + } + + cnt = 0; + for (this_char = where - string2; this_char < size2; this_char++) + { + PUT_CHAR (string2[this_char]); + if (++cnt > 100) + { + fputs ("...", stdout); + break; + } + } + } +} + +# ifndef DEFINED_ONCE +void +printchar (int c) +{ + putc (c, stderr); +} +# endif + +# else /* not DEBUG */ + +# ifndef DEFINED_ONCE +# undef assert +# define assert(e) + +# define DEBUG_STATEMENT(e) +# define DEBUG_PRINT1(x) +# define DEBUG_PRINT2(x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +# endif /* not DEBUG */ + + + +# ifdef WCHAR +/* This convert a multibyte string to a wide character string. + And write their correspondances to offset_buffer(see below) + and write whether each wchar_t is binary data to is_binary. + This assume invalid multibyte sequences as binary data. + We assume offset_buffer and is_binary is already allocated + enough space. */ + +static size_t +convert_mbs_to_wcs ( + CHAR_T *dest, + const unsigned char* src, + size_t len, /* the length of multibyte string. */ + + /* It hold correspondances between src(char string) and + dest(wchar_t string) for optimization. + e.g. src = "xxxyzz" + dest = {'X', 'Y', 'Z'} + (each "xxx", "y" and "zz" represent one multibyte character + corresponding to 'X', 'Y' and 'Z'.) + offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} + = {0, 3, 4, 6} + */ + int *offset_buffer, + char *is_binary) +{ + wchar_t *pdest = dest; + const unsigned char *psrc = src; + size_t wc_count = 0; + + mbstate_t mbs; + int i, consumed; + size_t mb_remain = len; + size_t mb_count = 0; + + /* Initialize the conversion state. */ + memset (&mbs, 0, sizeof (mbstate_t)); + + offset_buffer[0] = 0; + for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, + psrc += consumed) + { +#ifdef _LIBC + consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs); +#else + consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); +#endif + + if (consumed <= 0) + /* failed to convert. maybe src contains binary data. + So we consume 1 byte manualy. */ + { + *pdest = *psrc; + consumed = 1; + is_binary[wc_count] = TRUE; + } + else + is_binary[wc_count] = FALSE; + /* In sjis encoding, we use yen sign as escape character in + place of reverse solidus. So we convert 0x5c(yen sign in + sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse + solidus in UCS2). */ + if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) + *pdest = (wchar_t) *psrc; + + offset_buffer[wc_count + 1] = mb_count += consumed; + } + + /* Fill remain of the buffer with sentinel. */ + for (i = wc_count + 1 ; i <= len ; i++) + offset_buffer[i] = mb_count + 1; + + return wc_count; +} + +# endif /* WCHAR */ + +#else /* not INSIDE_RECURSION */ + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (reg_syntax_t syntax) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; +# ifdef DEBUG + if (syntax & RE_DEBUG) + debug = 1; + else if (debug) /* was on but now is not */ + debug = 0; +# endif /* DEBUG */ + return ret; +} +# if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_set_syntax, re_set_syntax) +# endif + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +static const char re_error_msgid[] = + { +# define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +# define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +# define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +# define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +# define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +# define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ + "\0" +# define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +# define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +# define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +# define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +# define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +# define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +# define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +# define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +# define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +static const size_t re_error_msgid_idx[] = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +#endif /* INSIDE_RECURSION */ + +#ifndef DEFINED_ONCE +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs + processes input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +# define MATCH_MAY_ALLOCATE + +/* When using GNU C, we are not REALLY using the C alloca, no matter + what config.h may say. So don't take precautions for it. */ +# ifdef __GNUC__ +# undef C_ALLOCA +# endif + +/* The match routines may not allocate if (1) they would do it with malloc + and (2) it's not safe for them to use malloc. + Note that if REL_ALLOC is defined, matching would not use malloc for the + failure stack, but we would still use it for the register vectors; + so REL_ALLOC should not affect this. */ +# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs +# undef MATCH_MAY_ALLOCATE +# endif +#endif /* not DEFINED_ONCE */ + +#ifdef INSIDE_RECURSION +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE_STACK. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +# ifndef INIT_FAILURE_ALLOC +# define INIT_FAILURE_ALLOC 5 +# endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_ITEMS items each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ + +# ifdef INT_IS_16BIT + +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +long int re_max_failures = 4000; +# else +long int re_max_failures = 2000; +# endif +# endif + +union PREFIX(fail_stack_elt) +{ + UCHAR_T *pointer; + long int integer; +}; + +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); + +typedef struct +{ + PREFIX(fail_stack_elt_t) *stack; + unsigned long int size; + unsigned long int avail; /* Offset of next open position. */ +} PREFIX(fail_stack_type); + +# else /* not INT_IS_16BIT */ + +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +int re_max_failures = 4000; +# else +int re_max_failures = 2000; +# endif +# endif + +union PREFIX(fail_stack_elt) +{ + UCHAR_T *pointer; + int integer; +}; + +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); + +typedef struct +{ + PREFIX(fail_stack_elt_t) *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} PREFIX(fail_stack_type); + +# endif /* INT_IS_16BIT */ + +# ifndef DEFINED_ONCE +# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +# endif + + +/* Define macros to initialize and free the failure stack. + Do `return -2' if the alloc fails. */ + +# ifdef MATCH_MAY_ALLOCATE +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) +# else +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() +# endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE_STACK requires `destination' be declared. */ + +# define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ + ? 0 \ + : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ + REGEX_REALLOCATE_STACK ((fail_stack).stack, \ + (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ + ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push pointer POINTER on FAIL_STACK. + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ + ? 0 \ + : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ + 1)) + +/* Push a pointer value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_POINTER(item) \ + fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) + +/* This pushes an integer-valued item onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_INT(item) \ + fail_stack.stack[fail_stack.avail++].integer = (item) + +/* Push a fail_stack_elt_t value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_ELT(item) \ + fail_stack.stack[fail_stack.avail++] = (item) + +/* These three POP... operations complement the three PUSH... operations. + All assume that `fail_stack' is nonempty. */ +# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer +# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer +# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +# ifdef DEBUG +# define DEBUG_PUSH PUSH_FAILURE_INT +# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () +# else +# define DEBUG_PUSH(item) +# define DEBUG_POP(item_addr) +# endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' + be declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + /* Can't be int, since there is not a shred of a guarantee that int \ + is wide enough to hold a value of something to which pointer can \ + be assigned */ \ + active_reg_t this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + if (1) \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + PUSH_FAILURE_POINTER (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + PUSH_FAILURE_POINTER (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: %p\n ", \ + reg_info[this_reg].word.pointer); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ELT (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ + PUSH_FAILURE_INT (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ + PUSH_FAILURE_INT (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_POINTER (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_POINTER (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +# ifndef DEFINED_ONCE +/* This is the number of items that are pushed and popped on the stack + for each register. */ +# define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +# ifdef DEBUG +# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +# else +# define NUM_NONREG_ITEMS 4 +# endif + +/* We push at most this many items on the stack. */ +/* We used to use (num_regs - 1), which is the number of registers + this regexp will save; but that was changed to 5 + to avoid stack overflow for a regexp with lots of parens. */ +# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +# define NUM_FAILURE_ITEMS \ + (((0 \ + ? 0 : highest_active_reg - lowest_active_reg + 1) \ + * NUM_REG_ITEMS) \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) +# endif /* not DEFINED_ONCE */ + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ +# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (unsigned failure_id;) \ + active_reg_t this_reg; \ + const UCHAR_T *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_POINTER (); \ + if (string_temp != NULL) \ + str = (const CHAR_T *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string %p: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ + \ + low_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ + \ + if (1) \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ELT (); \ + DEBUG_PRINT2 (" info: %p\n", \ + reg_info[this_reg].word.pointer); \ + \ + regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + } \ + else \ + { \ + for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ + { \ + reg_info[this_reg].word.integer = 0; \ + regend[this_reg] = 0; \ + regstart[this_reg] = 0; \ + } \ + highest_active_reg = high_reg; \ + } \ + \ + set_regs_matched_done = 0; \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + +/* Structure for per-register (a.k.a. per-group) information. + Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ + + +/* Declarations and macros for re_match_2. */ + +typedef union +{ + PREFIX(fail_stack_elt_t) word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +# define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} PREFIX(register_info_type); + +# ifndef DEFINED_ONCE +# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +# define IS_ACTIVE(R) ((R).bits.is_active) +# define MATCHED_SOMETHING(R) ((R).bits.matched_something) +# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +# define SET_REGS_MATCHED() \ + do \ + { \ + if (!set_regs_matched_done) \ + { \ + active_reg_t r; \ + set_regs_matched_done = 1; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + } \ + while (0) +# endif /* not DEFINED_ONCE */ + +/* Registers are set to a sentinel when they haven't yet matched. */ +static CHAR_T PREFIX(reg_unset_dummy); +# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) +# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + +/* Subroutine declarations and macros for regex_compile. */ +static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); +static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2); +static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, + int arg, UCHAR_T *end); +static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2, UCHAR_T *end); +static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, + const CHAR_T *p, + reg_syntax_t syntax); +static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, + const CHAR_T *pend, + reg_syntax_t syntax); +# ifdef WCHAR +static reg_errcode_t wcs_compile_range (CHAR_T range_start, + const CHAR_T **p_ptr, + const CHAR_T *pend, + char *translate, + reg_syntax_t syntax, + UCHAR_T *b, + CHAR_T *char_set); +static void insert_space (int num, CHAR_T *loc, CHAR_T *end); +# else /* BYTE */ +static reg_errcode_t byte_compile_range (unsigned int range_start, + const char **p_ptr, + const char *pend, + char *translate, + reg_syntax_t syntax, + unsigned char *b); +# endif /* WCHAR */ + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ +# ifndef PATFETCH +# ifdef WCHAR +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (UCHAR_T) *p++; \ + if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ + } while (0) +# else /* BYTE */ +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = (unsigned char) translate[c]; \ + } while (0) +# endif /* WCHAR */ +# endif + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +# define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (UCHAR_T) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +# define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ + +# ifndef TRANSLATE +# ifdef WCHAR +# define TRANSLATE(d) \ + ((translate && ((UCHAR_T) (d)) <= 0xff) \ + ? (char) translate[(unsigned char) (d)] : (d)) +# else /* BYTE */ +# define TRANSLATE(d) \ + (translate ? (char) translate[(unsigned char) (d)] : (d)) +# endif /* WCHAR */ +# endif + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) + +/* Make sure we have at least N more bytes of space in buffer. */ +# ifdef WCHAR +# define GET_BUFFER_SPACE(n) \ + while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ + + (n)*sizeof(CHAR_T)) > bufp->allocated) \ + EXTEND_BUFFER () +# else /* BYTE */ +# define GET_BUFFER_SPACE(n) \ + while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ + EXTEND_BUFFER () +# endif /* WCHAR */ + +/* Make sure we have one more byte of buffer space and then add C to it. */ +# define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (UCHAR_T) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +# define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +# define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ + *b++ = (UCHAR_T) (c3); \ + } while (0) + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +# define STORE_JUMP(op, loc, to) \ + PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) + +/* Likewise, for a two-argument jump. */ +# define STORE_JUMP2(op, loc, to, arg) \ + PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +# define INSERT_JUMP(op, loc, to) \ + PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +# define INSERT_JUMP2(op, loc, to, arg) \ + PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ + arg, b) + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +/* Any other compiler which, like MSC, has allocation limit below 2^16 + bytes will have to use approach similar to what was done below for + MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up + reallocating to 0 bytes. Such thing is not going to work too well. + You have been warned!! */ +# ifndef DEFINED_ONCE +# if defined _MSC_VER && !defined WIN32 +/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. + The REALLOC define eliminates a flurry of conversion warnings, + but is not required. */ +# define MAX_BUF_SIZE 65500L +# define REALLOC(p,s) realloc ((p), (size_t) (s)) +# else +# define MAX_BUF_SIZE (1L << 16) +# define REALLOC(p,s) realloc ((p), (s)) +# endif + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +# if __BOUNDED_POINTERS__ +# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) +# define MOVE_BUFFER_POINTER(P) \ + (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) +# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ + else \ + { \ + SET_HIGH_BOUND (b); \ + SET_HIGH_BOUND (begalt); \ + if (fixup_alt_jump) \ + SET_HIGH_BOUND (fixup_alt_jump); \ + if (laststart) \ + SET_HIGH_BOUND (laststart); \ + if (pending_exact) \ + SET_HIGH_BOUND (pending_exact); \ + } +# else +# define MOVE_BUFFER_POINTER(P) (P) += incr +# define ELSE_EXTEND_BUFFER_HIGH_BOUND +# endif +# endif /* not DEFINED_ONCE */ + +# ifdef WCHAR +# define EXTEND_BUFFER() \ + do { \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ + int wchar_count; \ + if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + /* How many characters the new buffer can have? */ \ + wchar_count = bufp->allocated / sizeof(UCHAR_T); \ + if (wchar_count == 0) wchar_count = 1; \ + /* Truncate the buffer to CHAR_T align. */ \ + bufp->allocated = wchar_count * sizeof(UCHAR_T); \ + RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ + bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ + if (COMPILED_BUFFER_VAR == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != COMPILED_BUFFER_VAR) \ + { \ + int incr = COMPILED_BUFFER_VAR - old_buffer; \ + MOVE_BUFFER_POINTER (b); \ + MOVE_BUFFER_POINTER (begalt); \ + if (fixup_alt_jump) \ + MOVE_BUFFER_POINTER (fixup_alt_jump); \ + if (laststart) \ + MOVE_BUFFER_POINTER (laststart); \ + if (pending_exact) \ + MOVE_BUFFER_POINTER (pending_exact); \ + } \ + ELSE_EXTEND_BUFFER_HIGH_BOUND \ + } while (0) +# else /* BYTE */ +# define EXTEND_BUFFER() \ + do { \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ + bufp->allocated); \ + if (COMPILED_BUFFER_VAR == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != COMPILED_BUFFER_VAR) \ + { \ + int incr = COMPILED_BUFFER_VAR - old_buffer; \ + MOVE_BUFFER_POINTER (b); \ + MOVE_BUFFER_POINTER (begalt); \ + if (fixup_alt_jump) \ + MOVE_BUFFER_POINTER (fixup_alt_jump); \ + if (laststart) \ + MOVE_BUFFER_POINTER (laststart); \ + if (pending_exact) \ + MOVE_BUFFER_POINTER (pending_exact); \ + } \ + ELSE_EXTEND_BUFFER_HIGH_BOUND \ + } while (0) +# endif /* WCHAR */ + +# ifndef DEFINED_ONCE +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +# define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +/* int may be not enough when sizeof(int) == 2. */ +typedef long pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +# define INIT_COMPILE_STACK_SIZE 32 + +# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + +# endif /* not DEFINED_ONCE */ + +/* Set the bit for character C in a list. */ +# ifndef DEFINED_ONCE +# define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) +# endif /* DEFINED_ONCE */ + +/* Get the next unsigned number in the uncompiled pattern. */ +# define GET_UNSIGNED_NUMBER(num) \ + { \ + while (p != pend) \ + { \ + PATFETCH (c); \ + if (c < '0' || c > '9') \ + break; \ + if (num <= RE_DUP_MAX) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + } \ + } \ + } + +# ifndef DEFINED_ONCE +# if defined _LIBC || WIDE_CHAR_SUPPORT +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif +# endif /* DEFINED_ONCE */ + +# ifndef MATCH_MAY_ALLOCATE + +/* If we cannot allocate large objects within re_match_2_internal, + we make the fail stack and register vectors global. + The fail stack, we grow to the maximum size when a regexp + is compiled. + The register vectors, we adjust in size each time we + compile a regexp, according to the number of registers it needs. */ + +static PREFIX(fail_stack_type) fail_stack; + +/* Size with which the following vectors are currently allocated. + That is so we can make them bigger as needed, + but never make them smaller. */ +# ifdef DEFINED_ONCE +static int regs_allocated_size; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static const char **reg_dummy; +# endif /* DEFINED_ONCE */ + +static PREFIX(register_info_type) *PREFIX(reg_info); +static PREFIX(register_info_type) *PREFIX(reg_info_dummy); + +/* Make the register vectors big enough for NUM_REGS registers, + but don't make them smaller. */ + +static void +PREFIX(regex_grow_registers) (int num_regs) +{ + if (num_regs > regs_allocated_size) + { + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); + + regs_allocated_size = num_regs; + } +} + +# endif /* not MATCH_MAY_ALLOCATE */ + +# ifndef DEFINED_ONCE +static boolean group_in_compile_stack (compile_stack_type + compile_stack, + regnum_t regnum); +# endif /* not DEFINED_ONCE */ + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +/* Return, freeing storage we allocated. */ +# ifdef WCHAR +# define FREE_STACK_RETURN(value) \ + return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) +# else +# define FREE_STACK_RETURN(value) \ + return (free (compile_stack.stack), value) +# endif /* WCHAR */ + +static reg_errcode_t +PREFIX(regex_compile) ( + const char *ARG_PREFIX(pattern), + size_t ARG_PREFIX(size), + reg_syntax_t syntax, + struct re_pattern_buffer *bufp) +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register UCHAR_T c, c1; + +#ifdef WCHAR + /* A temporary space to keep wchar_t pattern and compiled pattern. */ + CHAR_T *pattern, *COMPILED_BUFFER_VAR; + size_t size; + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset = NULL; + /* It hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; + /* A flag whether exactn is handling binary data or not. */ + char is_exactn_bin = FALSE; +#endif /* WCHAR */ + + /* A random temporary spot in PATTERN. */ + const CHAR_T *p1; + + /* Points to the end of the buffer, where we should append. */ + register UCHAR_T *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ +#ifdef WCHAR + const CHAR_T *p; + const CHAR_T *pend; +#else /* BYTE */ + const CHAR_T *p = pattern; + const CHAR_T *pend = pattern + size; +#endif /* WCHAR */ + + /* How to translate the characters in the pattern. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + UCHAR_T *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + UCHAR_T *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + UCHAR_T *begalt; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + UCHAR_T *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef WCHAR + /* Initialize the wchar_t PATTERN and offset_buffer. */ + p = pend = pattern = TALLOC(csize + 1, CHAR_T); + mbs_offset = TALLOC(csize + 1, int); + is_binary = TALLOC(csize + 1, char); + if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) + { + free(pattern); + free(mbs_offset); + free(is_binary); + return REG_ESPACE; + } + pattern[csize] = L'\0'; /* sentinel */ + size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); + pend = p + size; + if (size < 0) + { + free(pattern); + free(mbs_offset); + free(is_binary); + return REG_BADPAT; + } +#endif + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + PUT_CHAR (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + { +#ifdef WCHAR + free(pattern); + free(mbs_offset); + free(is_binary); +#endif + return REG_ESPACE; + } + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined emacs && !defined SYNTAX_TABLE + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. */ +#ifdef WCHAR + /* Free bufp->buffer and allocate an array for wchar_t pattern + buffer. */ + free(bufp->buffer); + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), + UCHAR_T); +#else + RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); +#endif /* WCHAR */ + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), + UCHAR_T); + } + + if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); +#ifdef WCHAR + bufp->buffer = (char*)COMPILED_BUFFER_VAR; +#endif /* WCHAR */ + bufp->allocated = INIT_BUF_SIZE; + } +#ifdef WCHAR + else + COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; +#endif + + begalt = b = COMPILED_BUFFER_VAR; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || PREFIX(at_begline_loc_p) (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || PREFIX(at_endline_loc_p) (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - + (1 + OFFSET_ADDRESS_SIZE)); + + /* We've added more stuff to the buffer. */ + b += 1 + OFFSET_ADDRESS_SIZE; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of + 'b + 3'. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 1 + OFFSET_ADDRESS_SIZE); + pending_exact = 0; + b += 1 + OFFSET_ADDRESS_SIZE; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + + 2 + 2 * OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; +#ifdef WCHAR + CHAR_T range_start = 0xffffffff; +#else + unsigned int range_start = 0xffffffff; +#endif + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + +#ifdef WCHAR + /* We assume a charset(_not) structure as a wchar_t array. + charset[0] = (re_opcode_t) charset(_not) + charset[1] = l (= length of char_classes) + charset[2] = m (= length of collating_symbols) + charset[3] = n (= length of equivalence_classes) + charset[4] = o (= length of char_ranges) + charset[5] = p (= length of chars) + + charset[6] = char_class (wctype_t) + charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) + ... + charset[l+5] = char_class (wctype_t) + + charset[l+6] = collating_symbol (wchar_t) + ... + charset[l+m+5] = collating_symbol (wchar_t) + ifdef _LIBC we use the index if + _NL_COLLATE_SYMB_EXTRAMB instead of + wchar_t string. + + charset[l+m+6] = equivalence_classes (wchar_t) + ... + charset[l+m+n+5] = equivalence_classes (wchar_t) + ifdef _LIBC we use the index in + _NL_COLLATE_WEIGHT instead of + wchar_t string. + + charset[l+m+n+6] = range_start + charset[l+m+n+7] = range_end + ... + charset[l+m+n+2o+4] = range_start + charset[l+m+n+2o+5] = range_end + ifdef _LIBC we use the value looked up + in _NL_COLLATE_COLLSEQ instead of + wchar_t character. + + charset[l+m+n+2o+6] = char + ... + charset[l+m+n+2o+p+5] = char + + */ + + /* We need at least 6 spaces: the opcode, the length of + char_classes, the length of collating_symbols, the length of + equivalence_classes, the length of char_ranges, the length of + chars. */ + GET_BUFFER_SPACE (6); + + /* Save b as laststart. And We use laststart as the pointer + to the first element of the charset here. + In other words, laststart[i] indicates charset[i]. */ + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Push the length of char_classes, the length of + collating_symbols, the length of equivalence_classes, the + length of char_ranges and the length of chars. */ + BUF_PUSH_3 (0, 0, 0); + BUF_PUSH_2 (0, 0); + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-6] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + { + BUF_PUSH('\n'); + laststart[5]++; /* Update the length of characters */ + } + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + BUF_PUSH(c1); + laststart[5]++; /* Update the length of chars */ + range_start = c1; + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret; + /* Allocate the space for range_start and range_end. */ + GET_BUFFER_SPACE (2); + /* Update the pointer to indicate end of buffer. */ + b += 2; + ret = wcs_compile_range (range_start, &p, pend, translate, + syntax, b, laststart); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + /* Allocate the space for range_start and range_end. */ + GET_BUFFER_SPACE (2); + /* Update the pointer to indicate end of buffer. */ + b += 2; + ret = wcs_compile_range (c, &p, pend, translate, syntax, b, + laststart); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + /* See if we're at the beginning of a possible character + class. */ + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == ':' && *p == ']') || p == pend) + break; + if (c1 < CHAR_CLASS_MAX_LENGTH) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and `:]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but store them as character). */ + if (c == ':' && *p == ']') + { + wctype_t wt; + uintptr_t alignedp; + + /* Query the character class as wctype_t. */ + wt = IS_CHAR_CLASS (str); + if (wt == 0) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + /* Allocate the space for character class. */ + GET_BUFFER_SPACE(CHAR_CLASS_SIZE); + /* Update the pointer to indicate end of buffer. */ + b += CHAR_CLASS_SIZE; + /* Move data which follow character classes + not to violate the data. */ + insert_space(CHAR_CLASS_SIZE, + laststart + 6 + laststart[1], + b - 1); + alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) + + __alignof__(wctype_t) - 1) + & ~(uintptr_t)(__alignof__(wctype_t) - 1); + /* Store the character class. */ + *((wctype_t*)alignedp) = wt; + /* Update length of char_classes */ + laststart[1] += CHAR_CLASS_SIZE; + + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + BUF_PUSH ('['); + BUF_PUSH (':'); + laststart[5] += 2; /* Update the length of characters */ + range_start = ':'; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' + || *p == '.')) + { + CHAR_T str[128]; /* Should be large enough. */ + CHAR_T delim = *p; /* '=' or '.' */ +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[=' or '[[.'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == delim && *p == ']') || p == pend) + break; + if (c1 < sizeof (str) - 1) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == delim && *p == ']' && str[0] != '\0') + { + unsigned int i, offset; + /* If we have no collation data we use the default + collation in which each character is in a class + by itself. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ + + /* If not defined _LIBC, we push the name and + `\0' for the sake of matching performance. */ + int datasize = c1 + 1; + +# ifdef _LIBC + int32_t idx = 0; + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + } +# ifdef _LIBC + else + { + const int32_t *table; + const int32_t *weights; + const int32_t *extra; + const int32_t *indirect; + wint_t *cp; + + /* This #include defines a local function! */ +# include + + if(delim == '=') + { + /* We push the index for equivalence class. */ + cp = (wint_t*)str; + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTWC); + + idx = findidx ((const wint_t**)&cp); + if (idx == 0 || cp < (wint_t*) str + c1) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + str[0] = (wchar_t)idx; + } + else /* delim == '.' */ + { + /* We push collation sequence value + for collating symbol. */ + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + char char_str[c1]; + + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (i = 0; i < c1; ++i) + char_str[i] = str[i]; + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (char_str, c1); + + idx = 0; + elem = hash % table_size; + second = hash % (table_size - 2); + while (symb_table[2 * elem] != 0) + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && c1 == extra[symb_table[2 * elem + 1]] + && memcmp (char_str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + + if (symb_table[2 * elem] != 0) + { + /* Compute the index of the byte sequence + in the table. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + str[0] = (wchar_t) idx + 4; + } + else if (symb_table[2 * elem] == 0 && c1 == 1) + { + /* No valid character. Match it as a + single byte character. */ + had_char_class = false; + BUF_PUSH(str[0]); + /* Update the length of characters */ + laststart[5]++; + range_start = str[0]; + + /* Throw away the ] at the end of the + collating symbol. */ + PATFETCH (c); + /* exit from the switch block. */ + continue; + } + else + FREE_STACK_RETURN (REG_ECOLLATE); + } + datasize = 1; + } +# endif + /* Throw away the ] at the end of the equivalence + class (or collating symbol). */ + PATFETCH (c); + + /* Allocate the space for the equivalence class + (or collating symbol) (and '\0' if needed). */ + GET_BUFFER_SPACE(datasize); + /* Update the pointer to indicate end of buffer. */ + b += datasize; + + if (delim == '=') + { /* equivalence class */ + /* Calculate the offset of char_ranges, + which is next to equivalence_classes. */ + offset = laststart[1] + laststart[2] + + laststart[3] +6; + /* Insert space. */ + insert_space(datasize, laststart + offset, b - 1); + + /* Write the equivalence_class and \0. */ + for (i = 0 ; i < datasize ; i++) + laststart[offset + i] = str[i]; + + /* Update the length of equivalence_classes. */ + laststart[3] += datasize; + had_char_class = true; + } + else /* delim == '.' */ + { /* collating symbol */ + /* Calculate the offset of the equivalence_classes, + which is next to collating_symbols. */ + offset = laststart[1] + laststart[2] + 6; + /* Insert space and write the collationg_symbol + and \0. */ + insert_space(datasize, laststart + offset, b-1); + for (i = 0 ; i < datasize ; i++) + laststart[offset + i] = str[i]; + + /* In re_match_2_internal if range_start < -1, we + assume -range_start is the offset of the + collating symbol which is specified as + the character of the range start. So we assign + -(laststart[1] + laststart[2] + 6) to + range_start. */ + range_start = -(laststart[1] + laststart[2] + 6); + /* Update the length of collating_symbol. */ + laststart[2] += datasize; + had_char_class = false; + } + } + else + { + c1++; + while (c1--) + PATUNFETCH; + BUF_PUSH ('['); + BUF_PUSH (delim); + laststart[5] += 2; /* Update the length of characters */ + range_start = delim; + had_char_class = false; + } + } + else + { + had_char_class = false; + BUF_PUSH(c); + laststart[5]++; /* Update the length of characters */ + range_start = c; + } + } + +#else /* BYTE */ + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + SET_LIST_BIT (c1); + range_start = c1; + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = byte_compile_range (range_start, &p, pend, translate, + syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = byte_compile_range (c, &p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == ':' && *p == ']') || p == pend) + break; +#if CHAR_CLASS_MAX_LENGTH != 256 + if (c1 < CHAR_CLASS_MAX_LENGTH) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; +#else + str[c1++] = c; +#endif + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and `:]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { +# if defined _LIBC || WIDE_CHAR_SUPPORT + boolean is_lower = STREQ (str, "lower"); + boolean is_upper = STREQ (str, "upper"); + wctype_t wt; + int ch; + + wt = IS_CHAR_CLASS (str); + if (wt == 0) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) + { +# ifdef _LIBC + if (__iswctype (__btowc (ch), wt)) + SET_LIST_BIT (ch); +# else + if (iswctype (btowc (ch), wt)) + SET_LIST_BIT (ch); +# endif + + if (translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + + had_char_class = true; +# else + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + /* This was split into 3 if's to + avoid an arbitrary limit in some compiler. */ + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch))) + SET_LIST_BIT (ch); + if ( (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch))) + SET_LIST_BIT (ch); + if ( (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + if ( translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; +# endif /* libc || wctype.h */ + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + range_start = ':'; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') + { + unsigned char str[MB_LEN_MAX + 1]; +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[='. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == '=' && *p == ']') || p == pend) + break; + if (c1 < MB_LEN_MAX) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == '=' && *p == ']' && str[0] != '\0') + { + /* If we have no collation data we use the default + collation in which each character is in a class + by itself. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ +# ifdef _LIBC + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Set the bit for the character. */ + SET_LIST_BIT (str[0]); + } +# ifdef _LIBC + else + { + /* Try to match the byte sequence in `str' against + those known to the collate implementation. + First find out whether the bytes in `str' are + actually from exactly one character. */ + const int32_t *table; + const unsigned char *weights; + const unsigned char *extra; + const int32_t *indirect; + int32_t idx; + const unsigned char *cp = str; + int ch; + + /* This #include defines a local function! */ +# include + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + + idx = findidx (&cp); + if (idx == 0 || cp < str + c1) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Now we have to go throught the whole table + and find all characters which have the same + first level weight. + + XXX Note that this is not entirely correct. + we would have to match multibyte sequences + but this is not possible with the current + implementation. */ + for (ch = 1; ch < 256; ++ch) + /* XXX This test would have to be changed if we + would allow matching multibyte sequences. */ + if (table[ch] > 0) + { + int32_t idx2 = table[ch]; + size_t len = weights[idx2]; + + /* Test whether the lenghts match. */ + if (weights[idx] == len) + { + /* They do. New compare the bytes of + the weight. */ + size_t cnt = 0; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + /* They match. Mark the character as + acceptable. */ + SET_LIST_BIT (ch); + } + } + } +# endif + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT ('='); + range_start = '='; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') + { + unsigned char str[128]; /* Should be large enough. */ +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[.'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == '.' && *p == ']') || p == pend) + break; + if (c1 < sizeof (str)) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == '.' && *p == ']' && str[0] != '\0') + { + /* If we have no collation data we use the default + collation in which each character is the name + for its own class which contains only the one + character. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ +# ifdef _LIBC + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Set the bit for the character. */ + SET_LIST_BIT (str[0]); + range_start = ((const unsigned char *) str)[0]; + } +# ifdef _LIBC + else + { + /* Try to match the byte sequence in `str' against + those known to the collate implementation. + First find out whether the bytes in `str' are + actually from exactly one character. */ + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + second = hash % (table_size - 2); + while (symb_table[2 * elem] != 0) + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && c1 == extra[symb_table[2 * elem + 1]] + && memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], + c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + + if (symb_table[2 * elem] == 0) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Now add the multibyte character(s) we found + to the accept list. + + XXX Note that this is not entirely correct. + we would have to match multibyte sequences + but this is not possible with the current + implementation. Also, we have to match + collating symbols, which expand to more than + one file, as a whole and not allow the + individual bytes. */ + c1 = extra[idx++]; + if (c1 == 1) + range_start = extra[idx]; + while (c1-- > 0) + { + SET_LIST_BIT (extra[idx]); + ++idx; + } + } +# endif + had_char_class = false; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT ('.'); + range_start = '.'; + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + range_start = c; + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; +#endif /* WCHAR */ + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b + - COMPILED_BUFFER_VAR + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + UCHAR_T *inner_group_loc + = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (on_failure_jump, begalt, + b + 2 + 2 * OFFSET_ADDRESS_SIZE); + pending_exact = 0; + b += 1 + OFFSET_ADDRESS_SIZE; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || (syntax & RE_NO_BK_BRACES)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + /* Place in the uncompiled pattern (i.e., just after + the '{') to go back to if the interval is invalid. */ + const CHAR_T *beg_interval = p; + + if (p == pend) + goto invalid_interval; + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) + upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (! (0 <= lower_bound && lower_bound <= upper_bound)) + goto invalid_interval; + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\' || p == pend) + goto invalid_interval; + PATFETCH (c); + } + + if (c != '}') + goto invalid_interval; + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS + && !(syntax & RE_INVALID_INTERVAL_ORD)) + FREE_STACK_RETURN (REG_BADRPT); + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* We just parsed a valid interval. */ + + if (RE_DUP_MAX < upper_bound) + FREE_STACK_RETURN (REG_BADBR); + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' + instead of 'b + 3'. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (jump, laststart, b + 1 + + OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at + set_number_at + succeed_n + + jump_n + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + + (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 1 + 2 * OFFSET_ADDRESS_SIZE + + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) + , lower_bound); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' + is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' + of the following `succeed_n'. */ + PREFIX(insert_op2) (set_number_at, laststart, 1 + + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + + 2 * OFFSET_ADDRESS_SIZE + 1, + upper_bound - 1); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + PREFIX(insert_op2) (set_number_at, laststart, + b - laststart, + upper_bound - 1, b); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + } + } + pending_exact = 0; + break; + + invalid_interval: + if (!(syntax & RE_INVALID_INTERVAL_ORD)) + FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); + unfetch_interval: + /* Match the characters as literals. */ + p = beg_interval; + c = '{'; + if (syntax & RE_NO_BK_BRACES) + goto normal_char; + else + goto normal_backslash; + } + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbeg); + break; + + case '>': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordend); + break; + + case 'b': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbound); + break; + + case 'B': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (notwordbound); + break; + + case '`': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (begbuf); + break; + + case '\'': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (endbuf); + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (syntax & RE_NO_BK_REFS) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + FREE_STACK_RETURN (REG_ESUBREG); + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, (regnum_t) c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact +#ifdef WCHAR + /* If last exactn handle binary(or character) and + new exactn handle character(or binary). */ + || is_exactn_bin != is_binary[p - 1 - pattern] +#endif /* WCHAR */ + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + +#ifdef WCHAR + /* Is this exactn binary data or character? */ + is_exactn_bin = is_binary[p - 1 - pattern]; + if (is_exactn_bin) + BUF_PUSH_2 (exactn_bin, 0); + else + BUF_PUSH_2 (exactn, 0); +#else + BUF_PUSH_2 (exactn, 0); +#endif /* WCHAR */ + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + FREE_STACK_RETURN (REG_EPAREN); + + /* If we don't want backtracking, force success + the first time we reach the end of the compiled pattern. */ + if (syntax & RE_NO_POSIX_BACKTRACKING) + BUF_PUSH (succeed); + +#ifdef WCHAR + free (pattern); + free (mbs_offset); + free (is_binary); +#endif + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ +#ifdef WCHAR + bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; +#else + bufp->used = b - bufp->buffer; +#endif + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: \n"); + PREFIX(print_compiled_pattern) (bufp); + } +#endif /* DEBUG */ + +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) + { + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + +# ifdef emacs + if (! fail_stack.stack) + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t))); + else + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, + (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t)))); +# else /* not emacs */ + if (! fail_stack.stack) + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t))); + else + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t)))); +# endif /* not emacs */ + } + + PREFIX(regex_grow_registers) (num_regs); + } +#endif /* not MATCH_MAY_ALLOCATE */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(store_op1) ( + re_opcode_t op, + UCHAR_T *loc, + int arg) +{ + *loc = (UCHAR_T) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(store_op2) ( + re_opcode_t op, + UCHAR_T *loc, + int arg1, int arg2) +{ + *loc = (UCHAR_T) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(insert_op1) ( + re_opcode_t op, + UCHAR_T *loc, + int arg, + UCHAR_T *end) +{ + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; + + while (pfrom != loc) + *--pto = *--pfrom; + + PREFIX(store_op1) (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(insert_op2) ( + re_opcode_t op, + UCHAR_T *loc, + int arg1, int arg2, + UCHAR_T *end) +{ + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; + + while (pfrom != loc) + *--pto = *--pfrom; + + PREFIX(store_op2) (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +PREFIX(at_begline_loc_p) ( + const CHAR_T *pattern, const CHAR_T *p, + reg_syntax_t syntax) +{ + const CHAR_T *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +PREFIX(at_endline_loc_p) ( + const CHAR_T *p, const CHAR_T *pend, + reg_syntax_t syntax) +{ + const CHAR_T *next = p; + boolean next_backslash = *next == '\\'; + const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + +#else /* not INSIDE_RECURSION */ + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack ( + compile_stack_type compile_stack, + regnum_t regnum) +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef WCHAR +/* This insert space, which size is "num", into the pattern at "loc". + "end" must point the end of the allocated buffer. */ +static void +insert_space ( + int num, + CHAR_T *loc, + CHAR_T *end) +{ + register CHAR_T *pto = end; + register CHAR_T *pfrom = end - num; + + while (pfrom >= loc) + *pto-- = *pfrom--; +} +#endif /* WCHAR */ + +#ifdef WCHAR +static reg_errcode_t +wcs_compile_range ( + CHAR_T range_start_char, + const CHAR_T **p_ptr, const CHAR_T *pend, + RE_TRANSLATE_TYPE translate, + reg_syntax_t syntax, + CHAR_T *b, CHAR_T *char_set) +{ + const CHAR_T *p = *p_ptr; + CHAR_T range_start, range_end; + reg_errcode_t ret; +# ifdef _LIBC + uint32_t nrules; + uint32_t start_val, end_val; +# endif + if (p == pend) + return REG_ERANGE; + +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, + _NL_COLLATE_COLLSEQWC); + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + + if (range_start_char < -1) + { + /* range_start is a collating symbol. */ + int32_t *wextra; + /* Retreive the index and get collation sequence value. */ + wextra = (int32_t*)(extra + char_set[-range_start_char]); + start_val = wextra[1 + *wextra]; + } + else + start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); + + end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); + + /* Report an error if the range is empty and the syntax prohibits + this. */ + ret = ((syntax & RE_NO_EMPTY_RANGES) + && (start_val > end_val))? REG_ERANGE : REG_NOERROR; + + /* Insert space to the end of the char_ranges. */ + insert_space(2, b - char_set[5] - 2, b - 1); + *(b - char_set[5] - 2) = (wchar_t)start_val; + *(b - char_set[5] - 1) = (wchar_t)end_val; + char_set[4]++; /* ranges_index */ + } + else +# endif + { + range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): + range_start_char; + range_end = TRANSLATE (p[0]); + /* Report an error if the range is empty and the syntax prohibits + this. */ + ret = ((syntax & RE_NO_EMPTY_RANGES) + && (range_start > range_end))? REG_ERANGE : REG_NOERROR; + + /* Insert space to the end of the char_ranges. */ + insert_space(2, b - char_set[5] - 2, b - 1); + *(b - char_set[5] - 2) = range_start; + *(b - char_set[5] - 1) = range_end; + char_set[4]++; /* ranges_index */ + } + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + return ret; +} +#else /* BYTE */ +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +byte_compile_range ( + unsigned int range_start_char, + const char **p_ptr, const char *pend, + RE_TRANSLATE_TYPE translate, + reg_syntax_t syntax, + unsigned char *b) +{ + unsigned this_char; + const char *p = *p_ptr; + reg_errcode_t ret; +# if _LIBC + const unsigned char *collseq; + unsigned int start_colseq; + unsigned int end_colseq; +# else + unsigned end_char; +# endif + + if (p == pend) + return REG_ERANGE; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* Report an error if the range is empty and the syntax prohibits this. */ + ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + +# if _LIBC + collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_COLLSEQMB); + + start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; + end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; + for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) + { + unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; + + if (start_colseq <= this_colseq && this_colseq <= end_colseq) + { + SET_LIST_BIT (TRANSLATE (this_char)); + ret = REG_NOERROR; + } + } +# else + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- we would otherwise go into an infinite loop, since all + characters <= 0xff. */ + range_start_char = TRANSLATE (range_start_char); + /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, + and some compilers cast it to int implicitly, so following for_loop + may fall to (almost) infinite loop. + e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. + To avoid this, we cast p[0] to unsigned int and truncate it. */ + end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); + + for (this_char = range_start_char; this_char <= end_char; ++this_char) + { + SET_LIST_BIT (TRANSLATE (this_char)); + ret = REG_NOERROR; + } +# endif + + return ret; +} +#endif /* WCHAR */ + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +#ifdef WCHAR +/* local function for re_compile_fastmap. + truncate wchar_t character to char. */ +static unsigned char truncate_wchar (CHAR_T c) +{ + unsigned char buf[MB_CUR_MAX]; + mbstate_t state; + int retval; + memset (&state, '\0', sizeof (state)); +# ifdef _LIBC + retval = __wcrtomb (buf, c, &state); +# else + retval = wcrtomb (buf, c, &state); +# endif + return retval > 0 ? buf[0] : (unsigned char) c; +} +#endif /* WCHAR */ + +static int +PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) +{ + int j, k; +#ifdef MATCH_MAY_ALLOCATE + PREFIX(fail_stack_type) fail_stack; +#endif +#ifndef REGEX_MALLOC + char *destination; +#endif + + register char *fastmap = bufp->fastmap; + +#ifdef WCHAR + /* We need to cast pattern to (wchar_t*), because we casted this compiled + pattern to (char*) in regex_compile. */ + UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; + register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); +#else /* BYTE */ + UCHAR_T *pattern = bufp->buffer; + register UCHAR_T *pend = pattern + bufp->used; +#endif /* WCHAR */ + UCHAR_T *p = pattern; + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (1) + { + if (p == pend || *p == succeed) + { + /* We have reached the (effective) end of pattern. */ + if (!FAIL_STACK_EMPTY ()) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail].pointer; + + continue; + } + else + break; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + goto done; + + + /* Following are the cases which match a character. These end + with `break'. */ + +#ifdef WCHAR + case exactn: + fastmap[truncate_wchar(p[1])] = 1; + break; +#else /* BYTE */ + case exactn: + fastmap[p[1]] = 1; + break; +#endif /* WCHAR */ +#ifdef MBS_SUPPORT + case exactn_bin: + fastmap[p[1]] = 1; + break; +#endif + +#ifdef WCHAR + /* It is hard to distinguish fastmap from (multi byte) characters + which depends on current locale. */ + case charset: + case charset_not: + case wordchar: + case notwordchar: + bufp->can_be_null = 1; + goto done; +#else /* BYTE */ + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; +#endif /* WCHAR */ + + case anychar: + { + int fastmap_newline = fastmap['\n']; + + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = fastmap_newline; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + goto done; + + /* Otherwise, have to check alternative paths. */ + break; + } + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1].pointer == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + { + RESET_FAIL_STACK (); + return -2; + } + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += OFFSET_ADDRESS_SIZE; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 2 * OFFSET_ADDRESS_SIZE; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 2 * OFFSET_ADDRESS_SIZE; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + + done: + RESET_FAIL_STACK (); + return 0; +} + +#else /* not INSIDE_RECURSION */ + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_compile_fastmap(bufp); + else +# endif + return byte_re_compile_fastmap(bufp); +} /* re_compile_fastmap */ +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_compile_fastmap, re_compile_fastmap) +#endif + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers ( + struct re_pattern_buffer *bufp, + struct re_registers *regs, + unsigned num_regs, + regoff_t *starts, regoff_t *ends) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t *) 0; + } +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_set_registers, re_set_registers) +#endif + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search ( + struct re_pattern_buffer *bufp, + const char *string, + int size, int startpos, int range, + struct re_registers *regs) +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_search, re_search) +#endif + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, + int range, + struct re_registers *regs, + int stop) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); + else +# endif + return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); +} /* re_search_2 */ +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_search_2, re_search_2) +#endif + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef MATCH_MAY_ALLOCATE +# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL +#else +# define FREE_VAR(var) free (var); var = NULL +#endif + +#ifdef WCHAR +# define MAX_ALLOCA_SIZE 2000 + +# define FREE_WCS_BUFFERS() \ + do { \ + if (size1 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string1); \ + free (mbs_offset1); \ + } \ + else \ + { \ + FREE_VAR (wcs_string1); \ + FREE_VAR (mbs_offset1); \ + } \ + if (size2 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string2); \ + free (mbs_offset2); \ + } \ + else \ + { \ + FREE_VAR (wcs_string2); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) + +#endif + + +static int +PREFIX(re_search_2) ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, + int range, + struct re_registers *regs, + int stop) +{ + int val; + register char *fastmap = bufp->fastmap; + register RE_TRANSLATE_TYPE translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; +#ifdef WCHAR + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ + wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ + int wcs_size1 = 0, wcs_size2 = 0; + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset1 = NULL, *mbs_offset2 = NULL; + /* They hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; +#endif /* WCHAR */ + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. + Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ + if (endpos < 0) + range = 0 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && range > 0 + && ((re_opcode_t) bufp->buffer[0] == begbuf + /* `begline' is like `begbuf' if it cannot match at newlines. */ + || ((re_opcode_t) bufp->buffer[0] == begline + && !bufp->newline_anchor))) + { + if (startpos > 0) + return -1; + else + range = 1; + } + +#ifdef emacs + /* In a forward search for something that starts with \=. + don't keep searching past point. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) + { + range = PT - startpos; + if (range <= 0) + return -1; + } +#endif /* emacs */ + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + +#ifdef WCHAR + /* Allocate wchar_t array for wcs_string1 and wcs_string2 and + fill them with converted string. */ + if (size1 != 0) + { + if (size1 > MAX_ALLOCA_SIZE) + { + wcs_string1 = TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = TALLOC (size1 + 1, int); + is_binary = TALLOC (size1 + 1, char); + } + else + { + wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (size1 + 1, int); + is_binary = REGEX_TALLOC (size1 + 1, char); + } + if (!wcs_string1 || !mbs_offset1 || !is_binary) + { + if (size1 > MAX_ALLOCA_SIZE) + { + free (wcs_string1); + free (mbs_offset1); + free (is_binary); + } + else + { + FREE_VAR (wcs_string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + } + return -2; + } + wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, + mbs_offset1, is_binary); + wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ + if (size1 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + } + if (size2 != 0) + { + if (size2 > MAX_ALLOCA_SIZE) + { + wcs_string2 = TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = TALLOC (size2 + 1, int); + is_binary = TALLOC (size2 + 1, char); + } + else + { + wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (size2 + 1, int); + is_binary = REGEX_TALLOC (size2 + 1, char); + } + if (!wcs_string2 || !mbs_offset2 || !is_binary) + { + FREE_WCS_BUFFERS (); + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + return -2; + } + wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, + mbs_offset2, is_binary); + wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + } +#endif /* WCHAR */ + + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register CHAR_T c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -1; + } + +#ifdef WCHAR + val = wcs_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop, + wcs_string1, wcs_size1, + wcs_string2, wcs_size2, + mbs_offset1, mbs_offset2); +#else /* BYTE */ + val = byte_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop); +#endif /* BYTE */ + +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + + if (val >= 0) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return startpos; + } + + if (val == -2) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -2; + } + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -1; +} + +#ifdef WCHAR +/* This converts PTR, a pointer into one of the search wchar_t strings + `string1' and `string2' into an multibyte string offset from the + beginning of that string. We use mbs_offset to optimize. + See convert_mbs_to_wcs. */ +# define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ + : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ + + csize1))) +#else /* BYTE */ +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +# define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) +#endif /* WCHAR */ + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#ifdef WCHAR +/* Use internationalized API instead of SYNTAX. */ +# define WORDCHAR_P(d) \ + (iswalnum ((wint_t)((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ + || ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') +#else /* BYTE */ +# define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) +#endif /* WCHAR */ + +/* Disabled due to a compiler bug -- see comment at case wordbound */ +#if 0 +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) +#endif + +/* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE +# ifdef WCHAR +# define FREE_VARIABLES() \ + do { \ + REGEX_FREE_STACK (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) +# else /* BYTE */ +# define FREE_VARIABLES() \ + do { \ + REGEX_FREE_STACK (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +# endif /* WCHAR */ +#else +# ifdef WCHAR +# define FREE_VARIABLES() \ + do { \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) +# else /* BYTE */ +# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ +# endif /* WCHAR */ +#endif /* not MATCH_MAY_ALLOCATE */ + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +#else /* not INSIDE_RECURSION */ +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match ( + struct re_pattern_buffer *bufp, + const char *string, + int size, int pos, + struct re_registers *regs) +{ + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size); +# ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +# endif + return result; +} +# if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_match, re_match) +# endif +#endif /* not emacs */ + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION +static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, + int len, char *translate); +#else /* not INSIDE_RECURSION */ + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop) +{ + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop); + +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + return result; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_match_2, re_match_2) +#endif + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef WCHAR +static int count_mbs_length (int *, int); + +/* This check the substring (from 0, to length) of the multibyte string, + to which offset_buffer correspond. And count how many wchar_t_characters + the substring occupy. We use offset_buffer to optimization. + See convert_mbs_to_wcs. */ + +static int +count_mbs_length( + int *offset_buffer, + int length) +{ + int upper, lower; + + /* Check whether the size is valid. */ + if (length < 0) + return -1; + + if (offset_buffer == NULL) + return 0; + + /* If there are no multibyte character, offset_buffer[i] == i. + Optmize for this case. */ + if (offset_buffer[length] == length) + return length; + + /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ + upper = length; + lower = 0; + + while (true) + { + int middle = (lower + upper) / 2; + if (middle == lower || middle == upper) + break; + if (offset_buffer[middle] > length) + upper = middle; + else if (offset_buffer[middle] < length) + lower = middle; + else + return middle; + } + + return -1; +} +#endif /* WCHAR */ + +/* This is a separate function so that we can force an alloca cleanup + afterwards. */ +#ifdef WCHAR +static int +wcs_re_match_2_internal ( + struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + /* string1 == string2 == NULL means string1/2, size1/2 and + mbs_offset1/2 need seting up in this function. */ + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ + wchar_t *string1, int size1, + wchar_t *string2, int size2, + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset1, int *mbs_offset2) +#else /* BYTE */ +static int +byte_re_match_2_internal ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop) +#endif /* BYTE */ +{ + /* General temporaries. */ + int mcnt; + UCHAR_T *p1; +#ifdef WCHAR + /* They hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; + /* If true, we can't free string1/2, mbs_offset1/2. */ + int cant_free_wcs_buf = 1; +#endif /* WCHAR */ + + /* Just past the end of the corresponding string. */ + const CHAR_T *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const CHAR_T *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const CHAR_T *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ +#ifdef WCHAR + UCHAR_T *pattern, *p; + register UCHAR_T *pend; +#else /* BYTE */ + UCHAR_T *p = bufp->buffer; + register UCHAR_T *pend = p + bufp->used; +#endif /* WCHAR */ + + /* Mark the opcode just after a start_memory, so we can test for an + empty subpattern when we get to the stop_memory. */ + UCHAR_T *just_past_start_mem = 0; + + /* We use this to map every character in the string. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + PREFIX(fail_stack_type) fail_stack; +#endif +#ifdef DEBUG + static unsigned failure_id; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + size_t num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; + active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **regstart, **regend; +#endif + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **old_regstart, **old_regend; +#endif + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + PREFIX(register_info_type) *reg_info; +#endif + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **best_regstart, **best_regend; +#endif + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const CHAR_T *match_end = NULL; + + /* This helps SET_REGS_MATCHED avoid doing redundant work. */ + int set_regs_matched_done = 0; + + /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **reg_dummy; + PREFIX(register_info_type) *reg_info_dummy; +#endif + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + +#ifdef MATCH_MAY_ALLOCATE + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + regend = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); + reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; + } +#endif /* MATCH_MAY_ALLOCATE */ + + /* The starting position is bogus. */ +#ifdef WCHAR + if (pos < 0 || pos > csize1 + csize2) +#else /* BYTE */ + if (pos < 0 || pos > size1 + size2) +#endif + { + FREE_VARIABLES (); + return -1; + } + +#ifdef WCHAR + /* Allocate wchar_t array for string1 and string2 and + fill them with converted string. */ + if (string1 == NULL && string2 == NULL) + { + /* We need seting up buffers here. */ + + /* We must free wcs buffers in this function. */ + cant_free_wcs_buf = 0; + + if (csize1 != 0) + { + string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); + is_binary = REGEX_TALLOC (csize1 + 1, char); + if (!string1 || !mbs_offset1 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + return -2; + } + } + if (csize2 != 0) + { + string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); + is_binary = REGEX_TALLOC (csize2 + 1, char); + if (!string2 || !mbs_offset2 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (string2); + FREE_VAR (mbs_offset2); + FREE_VAR (is_binary); + return -2; + } + size2 = convert_mbs_to_wcs(string2, cstring2, csize2, + mbs_offset2, is_binary); + string2[size2] = L'\0'; /* for a sentinel */ + FREE_VAR (is_binary); + } + } + + /* We need to cast pattern to (wchar_t*), because we casted this compiled + pattern to (char*) in regex_compile. */ + p = pattern = (CHAR_T*)bufp->buffer; + pend = (CHAR_T*)(bufp->buffer + bufp->used); + +#endif /* WCHAR */ + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; +#ifdef WCHAR + mbs_offset2 = mbs_offset1; + csize2 = csize1; + mbs_offset1 = NULL; + csize1 = 0; +#endif + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ +#ifdef WCHAR + if (stop <= csize1) + { + mcnt = count_mbs_length(mbs_offset1, stop); + end_match_1 = string1 + mcnt; + end_match_2 = string2; + } + else + { + if (stop > csize1 + csize2) + stop = csize1 + csize2; + end_match_1 = end1; + mcnt = count_mbs_length(mbs_offset2, stop-csize1); + end_match_2 = string2 + mcnt; + } + if (mcnt < 0) + { /* count_mbs_length return error. */ + FREE_VARIABLES (); + return -1; + } +#else + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } +#endif /* WCHAR */ + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ +#ifdef WCHAR + if (size1 > 0 && pos <= csize1) + { + mcnt = count_mbs_length(mbs_offset1, pos); + d = string1 + mcnt; + dend = end_match_1; + } + else + { + mcnt = count_mbs_length(mbs_offset2, pos-csize1); + d = string2 + mcnt; + dend = end_match_2; + } + + if (mcnt < 0) + { /* count_mbs_length return error. */ + FREE_VARIABLES (); + return -1; + } +#else + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } +#endif /* WCHAR */ + + DEBUG_PRINT1 ("The compiled pattern is:\n"); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + /* 1 if this match ends in the same string (string1 or string2) + as the best previous match. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + /* 1 if this match is the best seen so far. */ + boolean best_match_p; + + /* AIX compiler got confused when this was combined + with the previous declaration. */ + if (same_str_p) + best_match_p = d > match_end; + else + best_match_p = !MATCHING_IN_FIRST_STRING; + + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + + /* If exceeds best match so far, save it. */ + if (!best_regs_set || best_match_p) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. And if + last match is real best match, don't restore second + best one. */ + else if (best_regs_set && !best_match_p) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + succeed_label: + DEBUG_PRINT1 ("Accepting match.\n"); + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ + regs->num_regs = MAX (RE_NREGS, num_regs + 1); + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + } + } + else + { + /* These braces fend off a "empty body in an else-statement" + warning under GCC when assert expands to nothing. */ + assert (bufp->regs_allocated == REGS_FIXED); + } + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; +#ifdef WCHAR + if (MATCHING_IN_FIRST_STRING) + regs->end[0] = mbs_offset1 != NULL ? + mbs_offset1[d-string1] : 0; + else + regs->end[0] = csize1 + (mbs_offset2 != NULL ? + mbs_offset2[d-string2] : 0); +#else + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); +#endif /* WCHAR */ + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); + mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + +#ifdef WCHAR + if (MATCHING_IN_FIRST_STRING) + mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; + else + mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + + csize1; + mcnt -= pos; +#else + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); +#endif /* WCHAR */ + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + FREE_VARIABLES (); + return mcnt; + } + + /* Otherwise match next pattern command. */ + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + case succeed: + DEBUG_PRINT1 ("EXECUTING succeed.\n"); + goto succeed_label; + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: +#ifdef MBS_SUPPORT + case exactn_bin: +#endif + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); +#ifdef WCHAR + if (*d <= 0xff) + { + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) + goto fail; + } + else + { + if (*d++ != (CHAR_T) *p++) + goto fail; + } +#else + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) + goto fail; +#endif /* WCHAR */ + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (CHAR_T) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); + d++; + break; + + + case charset: + case charset_not: + { + register UCHAR_T c; +#ifdef WCHAR + unsigned int i, char_class_length, coll_symbol_length, + equiv_class_length, ranges_length, chars_length, length; + CHAR_T *workp, *workp2, *charset_top; +#define WORK_BUFFER_SIZE 128 + CHAR_T str_buf[WORK_BUFFER_SIZE]; +# ifdef _LIBC + uint32_t nrules; +# endif /* _LIBC */ +#endif /* WCHAR */ + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ +#ifdef WCHAR +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif /* _LIBC */ + charset_top = p - 1; + char_class_length = *p++; + coll_symbol_length = *p++; + equiv_class_length = *p++; + ranges_length = *p++; + chars_length = *p++; + /* p points charset[6], so the address of the next instruction + (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], + where l=length of char_classes, m=length of collating_symbol, + n=equivalence_class, o=length of char_range, + p'=length of character. */ + workp = p; + /* Update p to indicate the next instruction. */ + p += char_class_length + coll_symbol_length+ equiv_class_length + + 2*ranges_length + chars_length; + + /* match with char_class? */ + for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) + { + wctype_t wctype; + uintptr_t alignedp = ((uintptr_t)workp + + __alignof__(wctype_t) - 1) + & ~(uintptr_t)(__alignof__(wctype_t) - 1); + wctype = *((wctype_t*)alignedp); + workp += CHAR_CLASS_SIZE; +# ifdef _LIBC + if (__iswctype((wint_t)c, wctype)) + goto char_set_matched; +# else + if (iswctype((wint_t)c, wctype)) + goto char_set_matched; +# endif + } + + /* match with collating_symbol? */ +# ifdef _LIBC + if (nrules != 0) + { + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + + for (workp2 = workp + coll_symbol_length ; workp < workp2 ; + workp++) + { + int32_t *wextra; + wextra = (int32_t*)(extra + *workp++); + for (i = 0; i < *wextra; ++i) + if (TRANSLATE(d[i]) != wextra[1 + i]) + break; + + if (i == *wextra) + { + /* Update d, however d will be incremented at + char_set_matched:, we decrement d here. */ + d += i - 1; + goto char_set_matched; + } + } + } + else /* (nrules == 0) */ +# endif + /* If we can't look up collation data, we use wcscoll + instead. */ + { + for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) + { + const CHAR_T *backup_d = d, *backup_dend = dend; +# ifdef _LIBC + length = __wcslen (workp); +# else + length = wcslen (workp); +# endif + + /* If wcscoll(the collating symbol, whole string) > 0, + any substring of the string never match with the + collating symbol. */ +# ifdef _LIBC + if (__wcscoll (workp, d) > 0) +# else + if (wcscoll (workp, d) > 0) +# endif + { + workp += length + 1; + continue; + } + + /* First, we compare the collating symbol with + the first character of the string. + If it don't match, we add the next character to + the compare buffer in turn. */ + for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) + { + int match; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + + /* add next character to the compare buffer. */ + str_buf[i] = TRANSLATE(*d); + str_buf[i+1] = '\0'; + +# ifdef _LIBC + match = __wcscoll (workp, str_buf); +# else + match = wcscoll (workp, str_buf); +# endif + if (match == 0) + goto char_set_matched; + + if (match < 0) + /* (str_buf > workp) indicate (str_buf + X > workp), + because for all X (str_buf + X > str_buf). + So we don't need continue this loop. */ + break; + + /* Otherwise(str_buf < workp), + (str_buf+next_character) may equals (workp). + So we continue this loop. */ + } + /* not matched */ + d = backup_d; + dend = backup_dend; + workp += length + 1; + } + } + /* match with equivalence_class? */ +# ifdef _LIBC + if (nrules != 0) + { + const CHAR_T *backup_d = d, *backup_dend = dend; + /* Try to match the equivalence class against + those known to the collate implementation. */ + const int32_t *table; + const int32_t *weights; + const int32_t *extra; + const int32_t *indirect; + int32_t idx, idx2; + wint_t *cp; + size_t len; + + /* This #include defines a local function! */ +# include + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); + + /* Write 1 collating element to str_buf, and + get its index. */ + idx2 = 0; + + for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) + { + cp = (wint_t*)str_buf; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + str_buf[i] = TRANSLATE(*(d+i)); + str_buf[i+1] = '\0'; /* sentinel */ + idx2 = findidx ((const wint_t**)&cp); + } + + /* Update d, however d will be incremented at + char_set_matched:, we decrement d here. */ + d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); + if (d >= dend) + { + if (dend == end_match_2) + d = dend; + else + { + d = string2; + dend = end_match_2; + } + } + + len = weights[idx2]; + + for (workp2 = workp + equiv_class_length ; workp < workp2 ; + workp++) + { + idx = (int32_t)*workp; + /* We already checked idx != 0 in regex_compile. */ + + if (idx2 != 0 && len == weights[idx]) + { + int cnt = 0; + while (cnt < len && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto char_set_matched; + } + } + /* not matched */ + d = backup_d; + dend = backup_dend; + } + else /* (nrules == 0) */ +# endif + /* If we can't look up collation data, we use wcscoll + instead. */ + { + for (workp2 = workp + equiv_class_length ; workp < workp2 ;) + { + const CHAR_T *backup_d = d, *backup_dend = dend; +# ifdef _LIBC + length = __wcslen (workp); +# else + length = wcslen (workp); +# endif + + /* If wcscoll(the collating symbol, whole string) > 0, + any substring of the string never match with the + collating symbol. */ +# ifdef _LIBC + if (__wcscoll (workp, d) > 0) +# else + if (wcscoll (workp, d) > 0) +# endif + { + workp += length + 1; + break; + } + + /* First, we compare the equivalence class with + the first character of the string. + If it don't match, we add the next character to + the compare buffer in turn. */ + for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) + { + int match; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + + /* add next character to the compare buffer. */ + str_buf[i] = TRANSLATE(*d); + str_buf[i+1] = '\0'; + +# ifdef _LIBC + match = __wcscoll (workp, str_buf); +# else + match = wcscoll (workp, str_buf); +# endif + + if (match == 0) + goto char_set_matched; + + if (match < 0) + /* (str_buf > workp) indicate (str_buf + X > workp), + because for all X (str_buf + X > str_buf). + So we don't need continue this loop. */ + break; + + /* Otherwise(str_buf < workp), + (str_buf+next_character) may equals (workp). + So we continue this loop. */ + } + /* not matched */ + d = backup_d; + dend = backup_dend; + workp += length + 1; + } + } + + /* match with char_range? */ +# ifdef _LIBC + if (nrules != 0) + { + uint32_t collseqval; + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); + + collseqval = collseq_table_lookup (collseq, c); + + for (; workp < p - chars_length ;) + { + uint32_t start_val, end_val; + + /* We already compute the collation sequence value + of the characters (or collating symbols). */ + start_val = (uint32_t) *workp++; /* range_start */ + end_val = (uint32_t) *workp++; /* range_end */ + + if (start_val <= collseqval && collseqval <= end_val) + goto char_set_matched; + } + } + else +# endif + { + /* We set range_start_char at str_buf[0], range_end_char + at str_buf[4], and compared char at str_buf[2]. */ + str_buf[1] = 0; + str_buf[2] = c; + str_buf[3] = 0; + str_buf[5] = 0; + for (; workp < p - chars_length ;) + { + wchar_t *range_start_char, *range_end_char; + + /* match if (range_start_char <= c <= range_end_char). */ + + /* If range_start(or end) < 0, we assume -range_start(end) + is the offset of the collating symbol which is specified + as the character of the range start(end). */ + + /* range_start */ + if (*workp < 0) + range_start_char = charset_top - (*workp++); + else + { + str_buf[0] = *workp++; + range_start_char = str_buf; + } + + /* range_end */ + if (*workp < 0) + range_end_char = charset_top - (*workp++); + else + { + str_buf[4] = *workp++; + range_end_char = str_buf + 4; + } + +# ifdef _LIBC + if (__wcscoll (range_start_char, str_buf+2) <= 0 + && __wcscoll (str_buf+2, range_end_char) <= 0) +# else + if (wcscoll (range_start_char, str_buf+2) <= 0 + && wcscoll (str_buf+2, range_end_char) <= 0) +# endif + goto char_set_matched; + } + } + + /* match with char? */ + for (; workp < p ; workp++) + if (c == *workp) + goto char_set_matched; + + not = !not; + + char_set_matched: + if (not) goto fail; +#else + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; +#undef WORK_BUFFER_SIZE +#endif /* WCHAR */ + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", + (long int) *p, (long int) p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + just_past_start_mem = p; + + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", + (long int) *p, (long int) p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + UCHAR_T r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || just_past_start_mem == p - 1) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += OFFSET_ADDRESS_SIZE; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory + && p1[2+OFFSET_ADDRESS_SIZE] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); + r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if (old_regend[r] >= regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \ has been turned into a `duplicate' command which is + followed by the numeric value of as the register number. */ + case duplicate: + { + register const CHAR_T *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) + : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) + goto fail; + d += mcnt, d2 += mcnt; + + /* Do this because we've match some characters. */ + SET_REGS_MATCHED (); + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); +#endif + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); +#endif + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(zz\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register UCHAR_T *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) + pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn +#ifdef MBS_SUPPORT + || (re_opcode_t) *p2 == exactn_bin +#endif + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register UCHAR_T c + = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; + + if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn +#ifdef MBS_SUPPORT + || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin +#endif + ) && p1[3+OFFSET_ADDRESS_SIZE] != c) + { + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) + pop_failure_jump; +#ifdef WCHAR + DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", + (wint_t) c, + (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); +#else + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + (char) c, + (char) p1[3+OFFSET_ADDRESS_SIZE]); +#endif + } + +#ifndef WCHAR + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } +#endif /* not WCHAR */ + } +#ifndef WCHAR + else if ((re_opcode_t) *p2 == charset) + { + /* We win if the first character of the loop is not part + of the charset. */ + if ((re_opcode_t) p1[3] == exactn + && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] + && (p2[2 + p1[5] / BYTEWIDTH] + & (1 << (p1[5] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < (int) p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < (int) p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; + idx < (int) p2[1] && idx < (int) p1[4]; + idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } +#endif /* not WCHAR */ + } + p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (UCHAR_T) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + active_reg_t dummy_low_reg, dummy_high_reg; + UCHAR_T *pdummy = NULL; + const CHAR_T *sdummy = NULL; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + unconditional_jump: +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + /* Note fall through. */ + + /* Unconditionally jump (without popping any failure points). */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ +#ifdef _LIBC + DEBUG_PRINT2 ("(to %p).\n", p); +#else + DEBUG_PRINT2 ("(to 0x%x).\n", p); +#endif + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += OFFSET_ADDRESS_SIZE; + STORE_NUMBER_AND_INCR (p, mcnt); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE + , mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE + , mcnt); +#endif + } + else if (mcnt == 0) + { +#ifdef _LIBC + DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", + p + OFFSET_ADDRESS_SIZE); +#else + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", + p + OFFSET_ADDRESS_SIZE); +#endif /* _LIBC */ + +#ifdef WCHAR + p[1] = (UCHAR_T) no_op; +#else + p[2] = (UCHAR_T) no_op; + p[3] = (UCHAR_T) no_op; +#endif /* WCHAR */ + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); + +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, + mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, + mcnt); +#endif /* _LIBC */ + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 2 * OFFSET_ADDRESS_SIZE; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); +#endif + STORE_NUMBER (p1, mcnt); + break; + } + +#if 0 + /* The DEC Alpha C compiler 3.x generates incorrect code for the + test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of + AT_WORD_BOUNDARY, so this code is disabled. Expanding the + macro and introducing temporary variables works around the bug. */ + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; +#else + case wordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + break; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + break; + goto fail; + } + + case notwordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + goto fail; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + goto fail; + break; + } +#endif + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (!AT_STRINGS_END (d) && WORDCHAR_P (d) + && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) + break; + goto fail; + +#ifdef emacs + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +PREFIX(group_match_null_string_p) ( + UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + /* Point to after the args to the start_memory. */ + UCHAR_T *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == + jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - + (1 + OFFSET_ADDRESS_SIZE), + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != + jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 1 + OFFSET_ADDRESS_SIZE; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); + + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +PREFIX(alt_match_null_string_p) ( + UCHAR_T *p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + UCHAR_T *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +PREFIX(common_op_match_null_string_p) ( + UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + boolean ret; + int reg_no; + UCHAR_T *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += OFFSET_ADDRESS_SIZE; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 2 * OFFSET_ADDRESS_SIZE; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 2 * OFFSET_ADDRESS_SIZE; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +PREFIX(bcmp_translate) ( + const CHAR_T *s1, const CHAR_T *s2, + register int len, + RE_TRANSLATE_TYPE translate) +{ + register const UCHAR_T *p1 = (const UCHAR_T *) s1; + register const UCHAR_T *p2 = (const UCHAR_T *) s2; + while (len) + { +#ifdef WCHAR + if (((*p1<=0xff)?translate[*p1++]:*p1++) + != ((*p2<=0xff)?translate[*p2++]:*p2++)) + return 1; +#else /* BYTE */ + if (translate[*p1++] != translate[*p2++]) return 1; +#endif /* WCHAR */ + len--; + } + return 0; +} + + +#else /* not INSIDE_RECURSION */ + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern ( + const char *pattern, + size_t length, + struct re_pattern_buffer *bufp) +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); + else +# endif + ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); + + if (!ret) + return NULL; + return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_compile_pattern, re_compile_pattern) +#endif + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +#ifdef _LIBC +/* Make these definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec below without link errors. */ +weak_function +#endif +re_comp (const char *s) +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return (char *) gettext (re_error_msgid + + re_error_msgid_idx[(int) REG_ESPACE]); + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return (char *) gettext (re_error_msgid + + re_error_msgid_idx[(int) REG_ESPACE]); + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + else +# endif + ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + if (!ret) + return NULL; + + /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); +} + + +int +#if defined _LIBC || defined __UCLIBC__ +weak_function +#endif +re_exec (const char *s) +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} + +#endif /* _REGEX_RE_COMP */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' to an allocated space for the fastmap; + `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp ( + regex_t *preg, + const char *pattern, + int cflags) +{ + reg_errcode_t ret; + reg_syntax_t syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = (char *) malloc (1 << BYTEWIDTH); + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate + = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE + * sizeof (*(RE_TRANSLATE_TYPE)0)); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; + } + else + preg->translate = NULL; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + + preg->no_sub = !!(cflags & REG_NOSUB); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); + else +# endif + ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) ret = REG_EPAREN; + + if (ret == REG_NOERROR && preg->fastmap) + { + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. */ + if (re_compile_fastmap (preg) == -2) + { + /* Some error occurred while computing the fastmap, just forget + about it. */ + free (preg->fastmap); + preg->fastmap = NULL; + } + } + + return (int) ret; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regcomp, regcomp) +#endif + + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec ( + const regex_t *preg, + const char *string, + size_t nmatch, + regmatch_t pmatch[], + int eflags) +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + private_preg = *preg; + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch * 2, regoff_t); + if (regs.start == NULL) + return (int) REG_NOMATCH; + regs.end = regs.start + nmatch; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regexec, regexec) +#endif + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror ( + int errcode, + const regex_t *preg, + char *errbuf, + size_t errbuf_size) +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (int) (sizeof (re_error_msgid_idx) + / sizeof (re_error_msgid_idx[0]))) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { +#if (defined HAVE_MEMPCPY || defined _LIBC) && defined __USE_GNU + *((char *) mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; +#else + memcpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; +#endif + } + else + memcpy (errbuf, msg, msg_size); + } + + return msg_size; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regerror, regerror) +#endif + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (regex_t *preg) +{ + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + free (preg->translate); + preg->translate = NULL; +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__regfree, regfree) +#endif + +#endif /* not emacs */ + +#endif /* not INSIDE_RECURSION */ + + +#undef STORE_NUMBER +#undef STORE_NUMBER_AND_INCR +#undef EXTRACT_NUMBER +#undef EXTRACT_NUMBER_AND_INCR + +#undef DEBUG_PRINT_COMPILED_PATTERN +#undef DEBUG_PRINT_DOUBLE_STRING + +#undef INIT_FAIL_STACK +#undef RESET_FAIL_STACK +#undef DOUBLE_FAIL_STACK +#undef PUSH_PATTERN_OP +#undef PUSH_FAILURE_POINTER +#undef PUSH_FAILURE_INT +#undef PUSH_FAILURE_ELT +#undef POP_FAILURE_POINTER +#undef POP_FAILURE_INT +#undef POP_FAILURE_ELT +#undef DEBUG_PUSH +#undef DEBUG_POP +#undef PUSH_FAILURE_POINT +#undef POP_FAILURE_POINT + +#undef REG_UNSET_VALUE +#undef REG_UNSET + +#undef PATFETCH +#undef PATFETCH_RAW +#undef PATUNFETCH +#undef TRANSLATE + +#undef INIT_BUF_SIZE +#undef GET_BUFFER_SPACE +#undef BUF_PUSH +#undef BUF_PUSH_2 +#undef BUF_PUSH_3 +#undef STORE_JUMP +#undef STORE_JUMP2 +#undef INSERT_JUMP +#undef INSERT_JUMP2 +#undef EXTEND_BUFFER +#undef GET_UNSIGNED_NUMBER +#undef FREE_STACK_RETURN + +# undef POINTER_TO_OFFSET +# undef MATCHING_IN_FRST_STRING +# undef PREFETCH +# undef AT_STRINGS_BEG +# undef AT_STRINGS_END +# undef WORDCHAR_P +# undef FREE_VAR +# undef FREE_VARIABLES +# undef NO_HIGHEST_ACTIVE_REG +# undef NO_LOWEST_ACTIVE_REG + +# undef CHAR_T +# undef UCHAR_T +# undef COMPILED_BUFFER_VAR +# undef OFFSET_ADDRESS_SIZE +# undef CHAR_CLASS_SIZE +# undef PREFIX +# undef ARG_PREFIX +# undef PUT_CHAR +# undef BYTE +# undef WCHAR + +# define DEFINED_ONCE diff --git a/libc/misc/regex/regexec.c b/libc/misc/regex/regexec.c new file mode 100644 index 0000000..587e6af --- /dev/null +++ b/libc/misc/regex/regexec.c @@ -0,0 +1,4337 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, + int n) internal_function; +static void match_ctx_clean (re_match_context_t *mctx) internal_function; +static void match_ctx_free (re_match_context_t *cache) internal_function; +static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, + int str_idx, int from, int to) + internal_function; +static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) + internal_function; +static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, + int str_idx) internal_function; +static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, + int node, int str_idx) + internal_function; +static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, int last_node, + int last_str_idx) + internal_function; +static reg_errcode_t re_search_internal (const regex_t *preg, + const char *string, int length, + int start, int range, int stop, + size_t nmatch, regmatch_t pmatch[], + int eflags) internal_function; +static int re_search_2_stub (struct re_pattern_buffer *bufp, + const char *string1, int length1, + const char *string2, int length2, + int start, int range, struct re_registers *regs, + int stop, int ret_len) internal_function; +static int re_search_stub (struct re_pattern_buffer *bufp, + const char *string, int length, int start, + int range, int stop, struct re_registers *regs, + int ret_len) internal_function; +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + int nregs, int regs_allocated) internal_function; +static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) + internal_function; +static int check_matching (re_match_context_t *mctx, int fl_longest_match, + int *p_match_first) internal_function; +static int check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, int idx) + internal_function; +static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, int cur_node, + int cur_idx, int nmatch) internal_function; +static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, + int str_idx, int dest_node, int nregs, + regmatch_t *regs, + re_node_set *eps_via_nodes) + internal_function; +static reg_errcode_t set_regs (const regex_t *preg, + const re_match_context_t *mctx, + size_t nmatch, regmatch_t *pmatch, + int fl_backtrack) internal_function; +static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) + internal_function; + +#ifdef RE_ENABLE_I18N +static int sift_states_iter_mb (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int node_idx, int str_idx, int max_str_idx) + internal_function; +#endif /* RE_ENABLE_I18N */ +static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, + re_sift_context_t *sctx) + internal_function; +static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, + re_sift_context_t *sctx, int str_idx, + re_node_set *cur_dest) + internal_function; +static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int str_idx, + re_node_set *dest_nodes) + internal_function; +static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates) + internal_function; +static int check_dst_limits (const re_match_context_t *mctx, + re_node_set *limits, + int dst_node, int dst_idx, int src_node, + int src_idx) internal_function; +static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, + int boundaries, int subexp_idx, + int from_node, int bkref_idx) + internal_function; +static int check_dst_limits_calc_pos (const re_match_context_t *mctx, + int limit, int subexp_idx, + int node, int str_idx, + int bkref_idx) internal_function; +static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates, + re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, + int str_idx) internal_function; +static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int str_idx, const re_node_set *candidates) + internal_function; +static reg_errcode_t merge_state_array (const re_dfa_t *dfa, + re_dfastate_t **dst, + re_dfastate_t **src, int num) + internal_function; +static re_dfastate_t *find_recover_state (reg_errcode_t *err, + re_match_context_t *mctx) internal_function; +static re_dfastate_t *transit_state (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *state) internal_function; +static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *next_state) + internal_function; +static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, + re_node_set *cur_nodes, + int str_idx) internal_function; +#if 0 +static re_dfastate_t *transit_state_sb (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *pstate) + internal_function; +#endif +#ifdef RE_ENABLE_I18N +static reg_errcode_t transit_state_mb (re_match_context_t *mctx, + re_dfastate_t *pstate) + internal_function; +#endif /* RE_ENABLE_I18N */ +static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, + const re_node_set *nodes) + internal_function; +static reg_errcode_t get_subexp (re_match_context_t *mctx, + int bkref_node, int bkref_str_idx) + internal_function; +static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, + const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, + int bkref_node, int bkref_str) + internal_function; +static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + int subexp_idx, int type) internal_function; +static reg_errcode_t check_arrival (re_match_context_t *mctx, + state_array_t *path, int top_node, + int top_str, int last_node, int last_str, + int type) internal_function; +static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, + int str_idx, + re_node_set *cur_nodes, + re_node_set *next_nodes) + internal_function; +static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, + re_node_set *cur_nodes, + int ex_subexp, int type) + internal_function; +static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, + re_node_set *dst_nodes, + int target, int ex_subexp, + int type) internal_function; +static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, + re_node_set *cur_nodes, int cur_str, + int subexp_num, int type) + internal_function; +static int build_trtable (const re_dfa_t *dfa, + re_dfastate_t *state) internal_function; +#ifdef RE_ENABLE_I18N +static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + const re_string_t *input, int idx) + internal_function; +# ifdef _LIBC +static unsigned int find_collation_sequence_value (const unsigned char *mbs, + size_t name_len) + internal_function; +# endif /* _LIBC */ +#endif /* RE_ENABLE_I18N */ +static int group_nodes_into_DFAstates (const re_dfa_t *dfa, + const re_dfastate_t *state, + re_node_set *states_node, + bitset_t *states_ch) internal_function; +static int check_node_accept (const re_match_context_t *mctx, + const re_token_t *node, int idx) + internal_function; +static reg_errcode_t extend_buffers (re_match_context_t *mctx) + internal_function; + +/* Entry point for POSIX code. */ + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec (preg, string, nmatch, pmatch, eflags) + const regex_t *__restrict preg; + const char *__restrict string; + size_t nmatch; + regmatch_t pmatch[]; + int eflags; +{ + reg_errcode_t err; + int start, length; +#ifndef __UCLIBC__ /* libc_lock_lock does not exist */ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; +#endif + + if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) + return REG_BADPAT; + + if (eflags & REG_STARTEND) + { + start = pmatch[0].rm_so; + length = pmatch[0].rm_eo; + } + else + { + start = 0; + length = strlen (string); + } + + __libc_lock_lock (dfa->lock); + if (preg->no_sub) + err = re_search_internal (preg, string, length, start, length - start, + length, 0, NULL, eflags); + else + err = re_search_internal (preg, string, length, start, length - start, + length, nmatch, pmatch, eflags); + __libc_lock_unlock (dfa->lock); + return err != REG_NOERROR; +} + +#ifdef _LIBC +# include +versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +__typeof__ (__regexec) __compat_regexec; + +int +attribute_compat_text_section +__compat_regexec (const regex_t *__restrict preg, + const char *__restrict string, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ + return regexec (preg, string, nmatch, pmatch, + eflags & (REG_NOTBOL | REG_NOTEOL)); +} +compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); +# endif +#elif defined __UCLIBC__ +strong_alias(__regexec,regexec) +#endif + +/* Entry points for GNU code. */ + +/* re_match, re_search, re_match_2, re_search_2 + + The former two functions operate on STRING with length LENGTH, + while the later two operate on concatenation of STRING1 and STRING2 + with lengths LENGTH1 and LENGTH2, respectively. + + re_match() matches the compiled pattern in BUFP against the string, + starting at index START. + + re_search() first tries matching at index START, then it tries to match + starting from index START + 1, and so on. The last start position tried + is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same + way as re_match().) + + The parameter STOP of re_{match,search}_2 specifies that no match exceeding + the first STOP characters of the concatenation of the strings should be + concerned. + + If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match + and all groups is stroed in REGS. (For the "_2" variants, the offsets are + computed relative to the concatenation, not relative to the individual + strings.) + + On success, re_match* functions return the length of the match, re_search* + return the position of the start of the match. Return value -1 means no + match was found and -2 indicates an internal error. */ + +int +re_match (bufp, string, length, start, regs) + struct re_pattern_buffer *bufp; + const char *string; + int length, start; + struct re_registers *regs; +{ + return re_search_stub (bufp, string, length, start, 0, length, regs, 1); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_match, re_match) +#endif + +int +re_search (bufp, string, length, start, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int length, start, range; + struct re_registers *regs; +{ + return re_search_stub (bufp, string, length, start, range, length, regs, 0); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_search, re_search) +#endif + +int +re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int length1, length2, start, stop; + struct re_registers *regs; +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, 0, regs, stop, 1); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_match_2, re_match_2) +#endif + +int +re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int length1, length2, start, range, stop; + struct re_registers *regs; +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, range, regs, stop, 0); +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_search_2, re_search_2) +#endif + +static int +re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, + stop, ret_len) + struct re_pattern_buffer *bufp; + const char *string1, *string2; + int length1, length2, start, range, stop, ret_len; + struct re_registers *regs; +{ + const char *str; + int rval; + int len = length1 + length2; + int free_str = 0; + + if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) + return -2; + + /* Concatenate the strings. */ + if (length2 > 0) + if (length1 > 0) + { + char *s = re_malloc (char, len); + + if (BE (s == NULL, 0)) + return -2; +#if (defined _LIBC || defined __UCLIBC__) && defined __USE_GNU + memcpy (__mempcpy (s, string1, length1), string2, length2); +#else + memcpy (s, string1, length1); + memcpy (s + length1, string2, length2); +#endif + str = s; + free_str = 1; + } + else + str = string2; + else + str = string1; + + rval = re_search_stub (bufp, str, len, start, range, stop, regs, + ret_len); + if (free_str) + re_free ((char *) str); + return rval; +} + +/* The parameters have the same meaning as those of re_search. + Additional parameters: + If RET_LEN is nonzero the length of the match is returned (re_match style); + otherwise the position of the match is returned. */ + +static int +re_search_stub (bufp, string, length, start, range, stop, regs, ret_len) + struct re_pattern_buffer *bufp; + const char *string; + int length, start, range, stop, ret_len; + struct re_registers *regs; +{ + reg_errcode_t result; + regmatch_t *pmatch; + int nregs, rval; + int eflags = 0; +#ifndef __UCLIBC__ /* libc_lock_lock does not exist */ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; +#endif + + /* Check for out-of-range. */ + if (BE (start < 0 || start > length, 0)) + return -1; + if (BE (start + range > length, 0)) + range = length - start; + else if (BE (start + range < 0, 0)) + range = -start; + + __libc_lock_lock (dfa->lock); + + eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; + eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; + + /* Compile fastmap if we haven't yet. */ + if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) + re_compile_fastmap (bufp); + + if (BE (bufp->no_sub, 0)) + regs = NULL; + + /* We need at least 1 register. */ + if (regs == NULL) + nregs = 1; + else if (BE (bufp->regs_allocated == REGS_FIXED && + regs->num_regs < bufp->re_nsub + 1, 0)) + { + nregs = regs->num_regs; + if (BE (nregs < 1, 0)) + { + /* Nothing can be copied to regs. */ + regs = NULL; + nregs = 1; + } + } + else + nregs = bufp->re_nsub + 1; + pmatch = re_malloc (regmatch_t, nregs); + if (BE (pmatch == NULL, 0)) + { + rval = -2; + goto out; + } + + result = re_search_internal (bufp, string, length, start, range, stop, + nregs, pmatch, eflags); + + rval = 0; + + /* I hope we needn't fill ther regs with -1's when no match was found. */ + if (result != REG_NOERROR) + rval = -1; + else if (regs != NULL) + { + /* If caller wants register contents data back, copy them. */ + bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, + bufp->regs_allocated); + if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) + rval = -2; + } + + if (BE (rval == 0, 1)) + { + if (ret_len) + { + assert (pmatch[0].rm_so == start); + rval = pmatch[0].rm_eo - start; + } + else + rval = pmatch[0].rm_so; + } + re_free (pmatch); + out: + __libc_lock_unlock (dfa->lock); + return rval; +} + +static unsigned +re_copy_regs (regs, pmatch, nregs, regs_allocated) + struct re_registers *regs; + regmatch_t *pmatch; + int nregs, regs_allocated; +{ + int rval = REGS_REALLOCATE; + int i; + int need_regs = nregs + 1; + /* We need one extra element beyond `num_regs' for the `-1' marker GNU code + uses. */ + + /* Have the register data arrays been allocated? */ + if (regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. */ + regs->start = re_malloc (regoff_t, need_regs); + regs->end = re_malloc (regoff_t, need_regs); + if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) + return REGS_UNALLOCATED; + regs->num_regs = need_regs; + } + else if (regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (BE (need_regs > regs->num_regs, 0)) + { + regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); + regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); + if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) + return REGS_UNALLOCATED; + regs->start = new_start; + regs->end = new_end; + regs->num_regs = need_regs; + } + } + else + { + assert (regs_allocated == REGS_FIXED); + /* This function may not be called with REGS_FIXED and nregs too big. */ + assert (regs->num_regs >= nregs); + rval = REGS_FIXED; + } + + /* Copy the regs. */ + for (i = 0; i < nregs; ++i) + { + regs->start[i] = pmatch[i].rm_so; + regs->end[i] = pmatch[i].rm_eo; + } + for ( ; i < regs->num_regs; ++i) + regs->start[i] = regs->end[i] = -1; + + return rval; +} + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers (bufp, regs, num_regs, starts, ends) + struct re_pattern_buffer *bufp; + struct re_registers *regs; + unsigned num_regs; + regoff_t *starts, *ends; +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t *) 0; + } +} +#if defined _LIBC || defined __UCLIBC__ +strong_alias(__re_set_registers, re_set_registers) +#endif + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC || defined __UCLIBC__ +int +# if defined _LIBC || defined __UCLIBC__ +weak_function +# endif +re_exec (s) + const char *s; +{ + return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); +} +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. */ + +/* Searches for a compiled pattern PREG in the string STRING, whose + length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same + mingings with regexec. START, and RANGE have the same meanings + with re_search. + Return REG_NOERROR if we find a match, and REG_NOMATCH if not, + otherwise return the error code. + Note: We assume front end functions already check ranges. + (START + RANGE >= 0 && START + RANGE <= LENGTH) */ + +static reg_errcode_t +re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, + eflags) + const regex_t *preg; + const char *string; + int length, start, range, stop, eflags; + size_t nmatch; + regmatch_t pmatch[]; +{ + reg_errcode_t err; + const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + int left_lim, right_lim, incr; + int fl_longest_match, match_first, match_kind, match_last = -1; + int extra_nmatch; + int sb, ch; +#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) + re_match_context_t mctx = { .dfa = dfa }; +#else + re_match_context_t mctx; +#endif + char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate + && range && !preg->can_be_null) ? preg->fastmap : NULL; + RE_TRANSLATE_TYPE t = preg->translate; + +#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) + memset (&mctx, '\0', sizeof (re_match_context_t)); + mctx.dfa = dfa; +#endif + + extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; + nmatch -= extra_nmatch; + + /* Check if the DFA haven't been compiled. */ + if (BE (preg->used == 0 || dfa->init_state == NULL + || dfa->init_state_word == NULL || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL, 0)) + return REG_NOMATCH; + +#ifdef DEBUG + /* We assume front-end functions already check them. */ + assert (start + range >= 0 && start + range <= length); +#endif + + /* If initial states with non-begbuf contexts have no elements, + the regex must be anchored. If preg->newline_anchor is set, + we'll never use init_state_nl, so do not check it. */ + if (dfa->init_state->nodes.nelem == 0 + && dfa->init_state_word->nodes.nelem == 0 + && (dfa->init_state_nl->nodes.nelem == 0 + || !preg->newline_anchor)) + { + if (start != 0 && start + range != 0) + return REG_NOMATCH; + start = range = 0; + } + + /* We must check the longest matching, if nmatch > 0. */ + fl_longest_match = (nmatch != 0 || dfa->nbackref); + + err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, + preg->translate, preg->syntax & RE_ICASE, dfa); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + mctx.input.stop = stop; + mctx.input.raw_stop = stop; + mctx.input.newline_anchor = preg->newline_anchor; + + err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* We will log all the DFA states through which the dfa pass, + if nmatch > 1, or this dfa has "multibyte node", which is a + back-reference or a node which can accept multibyte character or + multi character collating element. */ + if (nmatch > 1 || dfa->has_mb_node) + { + mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); + if (BE (mctx.state_log == NULL, 0)) + { + err = REG_ESPACE; + goto free_return; + } + } + else + mctx.state_log = NULL; + + match_first = start; + mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF; + + /* Check incrementally whether of not the input string match. */ + incr = (range < 0) ? -1 : 1; + left_lim = (range < 0) ? start + range : start; + right_lim = (range < 0) ? start : start + range; + sb = dfa->mb_cur_max == 1; + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) + | (range >= 0 ? 2 : 0) + | (t != NULL ? 1 : 0)) + : 8); + + for (;; match_first += incr) + { + err = REG_NOMATCH; + if (match_first < left_lim || right_lim < match_first) + goto free_return; + + /* Advance as rapidly as possible through the string, until we + find a plausible place to start matching. This may be done + with varying efficiency, so there are various possibilities: + only the most common of them are specialized, in order to + save on code size. We use a switch statement for speed. */ + switch (match_kind) + { + case 8: + /* No fastmap. */ + break; + + case 7: + /* Fastmap with single-byte translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[t[(unsigned char) string[match_first]]]) + ++match_first; + goto forward_match_found_start_or_reached_end; + + case 6: + /* Fastmap without translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[(unsigned char) string[match_first]]) + ++match_first; + + forward_match_found_start_or_reached_end: + if (BE (match_first == right_lim, 0)) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (!fastmap[t ? t[ch] : ch]) + goto free_return; + } + break; + + case 4: + case 5: + /* Fastmap without multi-byte translation, match backwards. */ + while (match_first >= left_lim) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (fastmap[t ? t[ch] : ch]) + break; + --match_first; + } + if (match_first < left_lim) + goto free_return; + break; + + default: + /* In this case, we can't determine easily the current byte, + since it might be a component byte of a multibyte + character. Then we use the constructed buffer instead. */ + for (;;) + { + /* If MATCH_FIRST is out of the valid range, reconstruct the + buffers. */ + unsigned int offset = match_first - mctx.input.raw_mbs_idx; + if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) + { + err = re_string_reconstruct (&mctx.input, match_first, + eflags); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + offset = match_first - mctx.input.raw_mbs_idx; + } + /* If MATCH_FIRST is out of the buffer, leave it as '\0'. + Note that MATCH_FIRST must not be smaller than 0. */ + ch = (match_first >= length + ? 0 : re_string_byte_at (&mctx.input, offset)); + if (fastmap[ch]) + break; + match_first += incr; + if (match_first < left_lim || match_first > right_lim) + { + err = REG_NOMATCH; + goto free_return; + } + } + break; + } + + /* Reconstruct the buffers so that the matcher can assume that + the matching starts from the beginning of the buffer. */ + err = re_string_reconstruct (&mctx.input, match_first, eflags); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + +#ifdef RE_ENABLE_I18N + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ + if (!sb && !re_string_first_byte (&mctx.input, 0)) + continue; +#endif + + /* It seems to be appropriate one, then use the matcher. */ + /* We assume that the matching starts from 0. */ + mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; + match_last = check_matching (&mctx, fl_longest_match, + range >= 0 ? &match_first : NULL); + if (match_last != -1) + { + if (BE (match_last == -2, 0)) + { + err = REG_ESPACE; + goto free_return; + } + else + { + mctx.match_last = match_last; + if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) + { + re_dfastate_t *pstate = mctx.state_log[match_last]; + mctx.last_node = check_halt_state_context (&mctx, pstate, + match_last); + } + if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) + || dfa->nbackref) + { + err = prune_impossible_nodes (&mctx); + if (err == REG_NOERROR) + break; + if (BE (err != REG_NOMATCH, 0)) + goto free_return; + match_last = -1; + } + else + break; /* We found a match. */ + } + } + + match_ctx_clean (&mctx); + } + +#ifdef DEBUG + assert (match_last != -1); + assert (err == REG_NOERROR); +#endif + + /* Set pmatch[] if we need. */ + if (nmatch > 0) + { + int reg_idx; + + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + + /* Set the points where matching start/end. */ + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; + + if (!preg->no_sub && nmatch > 1) + { + err = set_regs (preg, &mctx, nmatch, pmatch, + dfa->has_plural_match && dfa->nbackref > 0); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + + /* At last, add the offset to the each registers, since we slided + the buffers so that we could assume that the matching starts + from 0. */ + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so != -1) + { +#ifdef RE_ENABLE_I18N + if (BE (mctx.input.offsets_needed != 0, 0)) + { + pmatch[reg_idx].rm_so = + (pmatch[reg_idx].rm_so == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_so]); + pmatch[reg_idx].rm_eo = + (pmatch[reg_idx].rm_eo == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_eo]); + } +#else + assert (mctx.input.offsets_needed == 0); +#endif + pmatch[reg_idx].rm_so += match_first; + pmatch[reg_idx].rm_eo += match_first; + } + for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) + { + pmatch[nmatch + reg_idx].rm_so = -1; + pmatch[nmatch + reg_idx].rm_eo = -1; + } + + if (dfa->subexp_map) + for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) + if (dfa->subexp_map[reg_idx] != reg_idx) + { + pmatch[reg_idx + 1].rm_so + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; + pmatch[reg_idx + 1].rm_eo + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; + } + } + + free_return: + re_free (mctx.state_log); + if (dfa->nbackref) + match_ctx_free (&mctx); + re_string_destruct (&mctx.input); + return err; +} + +static reg_errcode_t +prune_impossible_nodes (mctx) + re_match_context_t *mctx; +{ + const re_dfa_t *const dfa = mctx->dfa; + int halt_node, match_last; + reg_errcode_t ret; + re_dfastate_t **sifted_states; + re_dfastate_t **lim_states = NULL; + re_sift_context_t sctx; +#ifdef DEBUG + assert (mctx->state_log != NULL); +#endif + match_last = mctx->match_last; + halt_node = mctx->last_node; + sifted_states = re_malloc (re_dfastate_t *, match_last + 1); + if (BE (sifted_states == NULL, 0)) + { + ret = REG_ESPACE; + goto free_return; + } + if (dfa->nbackref) + { + lim_states = re_malloc (re_dfastate_t *, match_last + 1); + if (BE (lim_states == NULL, 0)) + { + ret = REG_ESPACE; + goto free_return; + } + while (1) + { + memset (lim_states, '\0', + sizeof (re_dfastate_t *) * (match_last + 1)); + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, + match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + if (sifted_states[0] != NULL || lim_states[0] != NULL) + break; + do + { + --match_last; + if (match_last < 0) + { + ret = REG_NOMATCH; + goto free_return; + } + } while (mctx->state_log[match_last] == NULL + || !mctx->state_log[match_last]->halt); + halt_node = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + } + ret = merge_state_array (dfa, sifted_states, lim_states, + match_last + 1); + re_free (lim_states); + lim_states = NULL; + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + } + else + { + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + } + re_free (mctx->state_log); + mctx->state_log = sifted_states; + sifted_states = NULL; + mctx->last_node = halt_node; + mctx->match_last = match_last; + ret = REG_NOERROR; + free_return: + re_free (sifted_states); + re_free (lim_states); + return ret; +} + +/* Acquire an initial state and return it. + We must select appropriate initial state depending on the context, + since initial states may have constraints like "\<", "^", etc.. */ + +static __inline__ re_dfastate_t * +__attribute ((always_inline)) internal_function +acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, + int idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + if (dfa->init_state->has_constraint) + { + unsigned int context; + context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return dfa->init_state_word; + else if (IS_ORDINARY_CONTEXT (context)) + return dfa->init_state; + else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_begbuf; + else if (IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_nl; + else if (IS_BEGBUF_CONTEXT (context)) + { + /* It is relatively rare case, then calculate on demand. */ + return re_acquire_state_context (err, dfa, + dfa->init_state->entrance_nodes, + context); + } + else + /* Must not happen? */ + return dfa->init_state; + } + else + return dfa->init_state; +} + +/* Check whether the regular expression match input string INPUT or not, + and return the index where the matching end, return -1 if not match, + or return -2 in case of an error. + FL_LONGEST_MATCH means we want the POSIX longest matching. + If P_MATCH_FIRST is not NULL, and the match fails, it is set to the + next place where we may want to try matching. + Note that the matcher assume that the maching starts from the current + index of the buffer. */ + +static int +internal_function +check_matching (re_match_context_t *mctx, int fl_longest_match, + int *p_match_first) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int match = 0; + int match_last = -1; + int cur_str_idx = re_string_cur_idx (&mctx->input); + re_dfastate_t *cur_state; + int at_init_state = p_match_first != NULL; + int next_start_idx = cur_str_idx; + + err = REG_NOERROR; + cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); + /* An initial state must not be NULL (invalid). */ + if (BE (cur_state == NULL, 0)) + { + assert (err == REG_ESPACE); + return -2; + } + + if (mctx->state_log != NULL) + { + mctx->state_log[cur_str_idx] = cur_state; + + /* Check OP_OPEN_SUBEXP in the initial state in case that we use them + later. E.g. Processing back references. */ + if (BE (dfa->nbackref, 0)) + { + at_init_state = 0; + err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (cur_state->has_backref) + { + err = transit_state_bkref (mctx, &cur_state->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + } + + /* If the RE accepts NULL string. */ + if (BE (cur_state->halt, 0)) + { + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, cur_str_idx)) + { + if (!fl_longest_match) + return cur_str_idx; + else + { + match_last = cur_str_idx; + match = 1; + } + } + } + + while (!re_string_eoi (&mctx->input)) + { + re_dfastate_t *old_state = cur_state; + int next_char_idx = re_string_cur_idx (&mctx->input) + 1; + + if (BE (next_char_idx >= mctx->input.bufs_len, 0) + || (BE (next_char_idx >= mctx->input.valid_len, 0) + && mctx->input.valid_len < mctx->input.len)) + { + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + { + assert (err == REG_ESPACE); + return -2; + } + } + + cur_state = transit_state (&err, mctx, cur_state); + if (mctx->state_log != NULL) + cur_state = merge_state_with_log (&err, mctx, cur_state); + + if (cur_state == NULL) + { + /* Reached the invalid state or an error. Try to recover a valid + state using the state log, if available and if we have not + already found a valid (even if not the longest) match. */ + if (BE (err != REG_NOERROR, 0)) + return -2; + + if (mctx->state_log == NULL + || (match && !fl_longest_match) + || (cur_state = find_recover_state (&err, mctx)) == NULL) + break; + } + + if (BE (at_init_state, 0)) + { + if (old_state == cur_state) + next_start_idx = next_char_idx; + else + at_init_state = 0; + } + + if (cur_state->halt) + { + /* Reached a halt state. + Check the halt state can satisfy the current context. */ + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, + re_string_cur_idx (&mctx->input))) + { + /* We found an appropriate halt state. */ + match_last = re_string_cur_idx (&mctx->input); + match = 1; + + /* We found a match, do not modify match_first below. */ + p_match_first = NULL; + if (!fl_longest_match) + break; + } + } + } + + if (p_match_first) + *p_match_first += next_start_idx; + + return match_last; +} + +/* Check NODE match the current context. */ + +static int +internal_function +check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) +{ + re_token_type_t type = dfa->nodes[node].type; + unsigned int constraint = dfa->nodes[node].constraint; + if (type != END_OF_RE) + return 0; + if (!constraint) + return 1; + if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) + return 0; + return 1; +} + +/* Check the halt state STATE match the current context. + Return 0 if not match, if the node, STATE has, is a halt node and + match the context, return the node. */ + +static int +internal_function +check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, int idx) +{ + int i; + unsigned int context; +#ifdef DEBUG + assert (state->halt); +#endif + context = re_string_context_at (&mctx->input, idx, mctx->eflags); + for (i = 0; i < state->nodes.nelem; ++i) + if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) + return state->nodes.elems[i]; + return 0; +} + +/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA + corresponding to the DFA). + Return the destination node, and update EPS_VIA_NODES, return -1 in case + of errors. */ + +static int +internal_function +proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, + int *pidx, int node, re_node_set *eps_via_nodes, + struct re_fail_stack_t *fs) +{ + const re_dfa_t *const dfa = mctx->dfa; + int i, err; + if (IS_EPSILON_NODE (dfa->nodes[node].type)) + { + re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; + re_node_set *edests = &dfa->edests[node]; + int dest_node; + err = re_node_set_insert (eps_via_nodes, node); + if (BE (err < 0, 0)) + return -2; + /* Pick up a valid destination, or return -1 if none is found. */ + for (dest_node = -1, i = 0; i < edests->nelem; ++i) + { + int candidate = edests->elems[i]; + if (!re_node_set_contains (cur_nodes, candidate)) + continue; + if (dest_node == -1) + dest_node = candidate; + + else + { + /* In order to avoid infinite loop like "(a*)*", return the second + epsilon-transition if the first was already considered. */ + if (re_node_set_contains (eps_via_nodes, dest_node)) + return candidate; + + /* Otherwise, push the second epsilon-transition on the fail stack. */ + else if (fs != NULL + && push_fail_stack (fs, *pidx, candidate, nregs, regs, + eps_via_nodes)) + return -2; + + /* We know we are going to exit. */ + break; + } + } + return dest_node; + } + else + { + int naccepted = 0; + re_token_type_t type = dfa->nodes[node].type; + +#ifdef RE_ENABLE_I18N + if (dfa->nodes[node].accept_mb) + naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); + else +#endif /* RE_ENABLE_I18N */ + if (type == OP_BACK_REF) + { + int subexp_idx = dfa->nodes[node].opr.idx + 1; + naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; + if (fs != NULL) + { + if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) + return -1; + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); + if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, + naccepted) != 0) + return -1; + } + } + + if (naccepted == 0) + { + int dest_node; + err = re_node_set_insert (eps_via_nodes, node); + if (BE (err < 0, 0)) + return -2; + dest_node = dfa->edests[node].elems[0]; + if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node)) + return dest_node; + } + } + + if (naccepted != 0 + || check_node_accept (mctx, dfa->nodes + node, *pidx)) + { + int dest_node = dfa->nexts[node]; + *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; + if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL + || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node))) + return -1; + re_node_set_empty (eps_via_nodes); + return dest_node; + } + } + return -1; +} + +static reg_errcode_t +internal_function +push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, + int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) +{ + reg_errcode_t err; + int num = fs->num++; + if (fs->num == fs->alloc) + { + struct re_fail_stack_ent_t *new_array; + new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) + * fs->alloc * 2)); + if (new_array == NULL) + return REG_ESPACE; + fs->alloc *= 2; + fs->stack = new_array; + } + fs->stack[num].idx = str_idx; + fs->stack[num].node = dest_node; + fs->stack[num].regs = re_malloc (regmatch_t, nregs); + if (fs->stack[num].regs == NULL) + return REG_ESPACE; + memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); + err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); + return err; +} + +static int +internal_function +pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, + regmatch_t *regs, re_node_set *eps_via_nodes) +{ + int num = --fs->num; + assert (num >= 0); + *pidx = fs->stack[num].idx; + memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); + re_node_set_free (eps_via_nodes); + re_free (fs->stack[num].regs); + *eps_via_nodes = fs->stack[num].eps_via_nodes; + return fs->stack[num].node; +} + +/* Set the positions where the subexpressions are starts/ends to registers + PMATCH. + Note: We assume that pmatch[0] is already set, and + pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ + +static reg_errcode_t +internal_function +set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + regmatch_t *pmatch, int fl_backtrack) +{ + const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + int idx, cur_node; + re_node_set eps_via_nodes; + struct re_fail_stack_t *fs; + struct re_fail_stack_t fs_body = { 0, 2, NULL }; + regmatch_t *prev_idx_match; + int prev_idx_match_malloced = 0; + +#ifdef DEBUG + assert (nmatch > 1); + assert (mctx->state_log != NULL); +#endif + if (fl_backtrack) + { + fs = &fs_body; + fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); + if (fs->stack == NULL) + return REG_ESPACE; + } + else + fs = NULL; + + cur_node = dfa->init_node; + re_node_set_init_empty (&eps_via_nodes); + + if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) + prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); + else + { + prev_idx_match = re_malloc (regmatch_t, nmatch); + if (prev_idx_match == NULL) + { + free_fail_stack_return (fs); + return REG_ESPACE; + } + prev_idx_match_malloced = 1; + } + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + + for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) + { + update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); + + if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) + { + int reg_idx; + if (fs) + { + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) + break; + if (reg_idx == nmatch) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); + } + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + } + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOERROR; + } + } + + /* Proceed to next node. */ + cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, + &eps_via_nodes, fs); + + if (BE (cur_node < 0, 0)) + { + if (BE (cur_node == -2, 0)) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + free_fail_stack_return (fs); + return REG_ESPACE; + } + if (fs) + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOMATCH; + } + } + } + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); +} + +static reg_errcode_t +internal_function +free_fail_stack_return (struct re_fail_stack_t *fs) +{ + if (fs) + { + int fs_idx; + for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) + { + re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); + re_free (fs->stack[fs_idx].regs); + } + re_free (fs->stack); + } + return REG_NOERROR; +} + +static void +internal_function +update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) +{ + int type = dfa->nodes[cur_node].type; + if (type == OP_OPEN_SUBEXP) + { + int reg_num = dfa->nodes[cur_node].opr.idx + 1; + + /* We are at the first node of this sub expression. */ + if (reg_num < nmatch) + { + pmatch[reg_num].rm_so = cur_idx; + pmatch[reg_num].rm_eo = -1; + } + } + else if (type == OP_CLOSE_SUBEXP) + { + int reg_num = dfa->nodes[cur_node].opr.idx + 1; + if (reg_num < nmatch) + { + /* We are at the last node of this sub expression. */ + if (pmatch[reg_num].rm_so < cur_idx) + { + pmatch[reg_num].rm_eo = cur_idx; + /* This is a non-empty match or we are not inside an optional + subexpression. Accept this right away. */ + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + } + else + { + if (dfa->nodes[cur_node].opt_subexp + && prev_idx_match[reg_num].rm_so != -1) + /* We transited through an empty match for an optional + subexpression, like (a?)*, and this is not the subexp's + first match. Copy back the old content of the registers + so that matches of an inner subexpression are undone as + well, like in ((a?))*. */ + memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); + else + /* We completed a subexpression, but it may be part of + an optional one, so do not update PREV_IDX_MATCH. */ + pmatch[reg_num].rm_eo = cur_idx; + } + } + } +} + +/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 + and sift the nodes in each states according to the following rules. + Updated state_log will be wrote to STATE_LOG. + + Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... + 1. When STR_IDX == MATCH_LAST(the last index in the state_log): + If `a' isn't the LAST_NODE and `a' can't epsilon transit to + the LAST_NODE, we throw away the node `a'. + 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts + string `s' and transit to `b': + i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw + away the node `a'. + ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is + thrown away, we throw away the node `a'. + 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the + node `a'. + ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, + we throw away the node `a'. */ + +#define STATE_NODE_CONTAINS(state,node) \ + ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) + +static reg_errcode_t +internal_function +sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) +{ + reg_errcode_t err; + int null_cnt = 0; + int str_idx = sctx->last_str_idx; + re_node_set cur_dest; + +#ifdef DEBUG + assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); +#endif + + /* Build sifted state_log[str_idx]. It has the nodes which can epsilon + transit to the last_node and the last_node itself. */ + err = re_node_set_init_1 (&cur_dest, sctx->last_node); + if (BE (err != REG_NOERROR, 0)) + return err; + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* Then check each states in the state_log. */ + while (str_idx > 0) + { + /* Update counters. */ + null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; + if (null_cnt > mctx->max_mb_elem_len) + { + memset (sctx->sifted_states, '\0', + sizeof (re_dfastate_t *) * str_idx); + re_node_set_free (&cur_dest); + return REG_NOERROR; + } + re_node_set_empty (&cur_dest); + --str_idx; + + if (mctx->state_log[str_idx]) + { + err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + + /* Add all the nodes which satisfy the following conditions: + - It can epsilon transit to a node in CUR_DEST. + - It is in CUR_SRC. + And update state_log. */ + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + err = REG_NOERROR; + free_return: + re_node_set_free (&cur_dest); + return err; +} + +static reg_errcode_t +internal_function +build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, + int str_idx, re_node_set *cur_dest) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; + int i; + + /* Then build the next sifted state. + We build the next sifted state on `cur_dest', and update + `sifted_states[str_idx]' with `cur_dest'. + Note: + `cur_dest' is the sifted state from `state_log[str_idx + 1]'. + `cur_src' points the node_set of the old `state_log[str_idx]' + (with the epsilon nodes pre-filtered out). */ + for (i = 0; i < cur_src->nelem; i++) + { + int prev_node = cur_src->elems[i]; + int naccepted = 0; + int ret; + +#ifdef DEBUG + re_token_type_t type = dfa->nodes[prev_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept `multi byte'. */ + if (dfa->nodes[prev_node].accept_mb) + naccepted = sift_states_iter_mb (mctx, sctx, prev_node, + str_idx, sctx->last_str_idx); +#endif /* RE_ENABLE_I18N */ + + /* We don't check backreferences here. + See update_cur_sifted_state(). */ + if (!naccepted + && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) + && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], + dfa->nexts[prev_node])) + naccepted = 1; + + if (naccepted == 0) + continue; + + if (sctx->limits.nelem) + { + int to_idx = str_idx + naccepted; + if (check_dst_limits (mctx, &sctx->limits, + dfa->nexts[prev_node], to_idx, + prev_node, str_idx)) + continue; + } + ret = re_node_set_insert (cur_dest, prev_node); + if (BE (ret == -1, 0)) + return REG_ESPACE; + } + + return REG_NOERROR; +} + +/* Helper functions. */ + +static reg_errcode_t +internal_function +clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) +{ + int top = mctx->state_log_top; + + if (next_state_log_idx >= mctx->input.bufs_len + || (next_state_log_idx >= mctx->input.valid_len + && mctx->input.valid_len < mctx->input.len)) + { + reg_errcode_t err; + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (top < next_state_log_idx) + { + memset (mctx->state_log + top + 1, '\0', + sizeof (re_dfastate_t *) * (next_state_log_idx - top)); + mctx->state_log_top = next_state_log_idx; + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, + re_dfastate_t **src, int num) +{ + int st_idx; + reg_errcode_t err; + for (st_idx = 0; st_idx < num; ++st_idx) + { + if (dst[st_idx] == NULL) + dst[st_idx] = src[st_idx]; + else if (src[st_idx] != NULL) + { + re_node_set merged_set; + err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, + &src[st_idx]->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); + re_node_set_free (&merged_set); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, int str_idx, + re_node_set *dest_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + const re_node_set *candidates; + candidates = ((mctx->state_log[str_idx] == NULL) ? NULL + : &mctx->state_log[str_idx]->nodes); + + if (dest_nodes->nelem == 0) + sctx->sifted_states[str_idx] = NULL; + else + { + if (candidates) + { + /* At first, add the nodes which can epsilon transit to a node in + DEST_NODE. */ + err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* Then, check the limitations in the current sift_context. */ + if (sctx->limits.nelem) + { + err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, + mctx->bkref_ents, str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + + sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (candidates && mctx->state_log[str_idx]->has_backref) + { + err = sift_states_bkref (mctx, sctx, str_idx, candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + reg_errcode_t err = REG_NOERROR; + int i; + + re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (!state->inveclosure.alloc) + { + err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); + if (BE (err != REG_NOERROR, 0)) + return REG_ESPACE; + for (i = 0; i < dest_nodes->nelem; i++) + re_node_set_merge (&state->inveclosure, + dfa->inveclosures + dest_nodes->elems[i]); + } + return re_node_set_add_intersect (dest_nodes, candidates, + &state->inveclosure); +} + +static reg_errcode_t +internal_function +sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + int ecl_idx; + reg_errcode_t err; + re_node_set *inv_eclosure = dfa->inveclosures + node; + re_node_set except_nodes; + re_node_set_init_empty (&except_nodes); + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + int cur_node = inv_eclosure->elems[ecl_idx]; + if (cur_node == node) + continue; + if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) + { + int edst1 = dfa->edests[cur_node].elems[0]; + int edst2 = ((dfa->edests[cur_node].nelem > 1) + ? dfa->edests[cur_node].elems[1] : -1); + if ((!re_node_set_contains (inv_eclosure, edst1) + && re_node_set_contains (dest_nodes, edst1)) + || (edst2 > 0 + && !re_node_set_contains (inv_eclosure, edst2) + && re_node_set_contains (dest_nodes, edst2))) + { + err = re_node_set_add_intersect (&except_nodes, candidates, + dfa->inveclosures + cur_node); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&except_nodes); + return err; + } + } + } + } + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + int cur_node = inv_eclosure->elems[ecl_idx]; + if (!re_node_set_contains (&except_nodes, cur_node)) + { + int idx = re_node_set_contains (dest_nodes, cur_node) - 1; + re_node_set_remove_at (dest_nodes, idx); + } + } + re_node_set_free (&except_nodes); + return REG_NOERROR; +} + +static int +internal_function +check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, + int dst_node, int dst_idx, int src_node, int src_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int lim_idx, src_pos, dst_pos; + + int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); + int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + int subexp_idx; + struct re_backref_cache_entry *ent; + ent = mctx->bkref_ents + limits->elems[lim_idx]; + subexp_idx = dfa->nodes[ent->node].opr.idx; + + dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, dst_node, dst_idx, + dst_bkref_idx); + src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, src_node, src_idx, + src_bkref_idx); + + /* In case of: + ( ) + ( ) + ( ) */ + if (src_pos == dst_pos) + continue; /* This is unrelated limitation. */ + else + return 1; + } + return 0; +} + +static int +internal_function +check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, + int subexp_idx, int from_node, int bkref_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *eclosures = dfa->eclosures + from_node; + int node_idx; + + /* Else, we are on the boundary: examine the nodes on the epsilon + closure. */ + for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) + { + int node = eclosures->elems[node_idx]; + switch (dfa->nodes[node].type) + { + case OP_BACK_REF: + if (bkref_idx != -1) + { + struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; + do + { + int dst, cpos; + + if (ent->node != node) + continue; + + if (subexp_idx < BITSET_WORD_BITS + && !(ent->eps_reachable_subexps_map + & ((bitset_word_t) 1 << subexp_idx))) + continue; + + /* Recurse trying to reach the OP_OPEN_SUBEXP and + OP_CLOSE_SUBEXP cases below. But, if the + destination node is the same node as the source + node, don't recurse because it would cause an + infinite loop: a regex that exhibits this behavior + is ()\1*\1* */ + dst = dfa->edests[node].elems[0]; + if (dst == from_node) + { + if (boundaries & 1) + return -1; + else /* if (boundaries & 2) */ + return 0; + } + + cpos = + check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + dst, bkref_idx); + if (cpos == -1 /* && (boundaries & 1) */) + return -1; + if (cpos == 0 && (boundaries & 2)) + return 0; + + if (subexp_idx < BITSET_WORD_BITS) + ent->eps_reachable_subexps_map + &= ~((bitset_word_t) 1 << subexp_idx); + } + while (ent++->more); + } + break; + + case OP_OPEN_SUBEXP: + if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) + return -1; + break; + + case OP_CLOSE_SUBEXP: + if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) + return 0; + break; + + default: + break; + } + } + + return (boundaries & 2) ? 1 : 0; +} + +static int +internal_function +check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, + int subexp_idx, int from_node, int str_idx, + int bkref_idx) +{ + struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + int boundaries; + + /* If we are outside the range of the subexpression, return -1 or 1. */ + if (str_idx < lim->subexp_from) + return -1; + + if (lim->subexp_to < str_idx) + return 1; + + /* If we are within the subexpression, return 0. */ + boundaries = (str_idx == lim->subexp_from); + boundaries |= (str_idx == lim->subexp_to) << 1; + if (boundaries == 0) + return 0; + + /* Else, examine epsilon closure. */ + return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + from_node, bkref_idx); +} + +/* Check the limitations of sub expressions LIMITS, and remove the nodes + which are against limitations from DEST_NODES. */ + +static reg_errcode_t +internal_function +check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates, re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, int str_idx) +{ + reg_errcode_t err; + int node_idx, lim_idx; + + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + int subexp_idx; + struct re_backref_cache_entry *ent; + ent = bkref_ents + limits->elems[lim_idx]; + + if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) + continue; /* This is unrelated limitation. */ + + subexp_idx = dfa->nodes[ent->node].opr.idx; + if (ent->subexp_to == str_idx) + { + int ops_node = -1; + int cls_node = -1; + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_OPEN_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + ops_node = node; + else if (type == OP_CLOSE_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + cls_node = node; + } + + /* Check the limitation of the open subexpression. */ + /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ + if (ops_node >= 0) + { + err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + /* Check the limitation of the close subexpression. */ + if (cls_node >= 0) + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + if (!re_node_set_contains (dfa->inveclosures + node, + cls_node) + && !re_node_set_contains (dfa->eclosures + node, + cls_node)) + { + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + --node_idx; + } + } + } + else /* (ent->subexp_to != str_idx) */ + { + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) + { + if (subexp_idx != dfa->nodes[node].opr.idx) + continue; + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, + int str_idx, const re_node_set *candidates) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int node_idx, node; + re_sift_context_t local_sctx; + int first_idx = search_cur_bkref_entry (mctx, str_idx); + + if (first_idx == -1) + return REG_NOERROR; + + local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ + + for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) + { + int enabled_idx; + re_token_type_t type; + struct re_backref_cache_entry *entry; + node = candidates->elems[node_idx]; + type = dfa->nodes[node].type; + /* Avoid infinite loop for the REs like "()\1+". */ + if (node == sctx->last_node && str_idx == sctx->last_str_idx) + continue; + if (type != OP_BACK_REF) + continue; + + entry = mctx->bkref_ents + first_idx; + enabled_idx = first_idx; + do + { + int subexp_len; + int to_idx; + int dst_node; + int ret; + re_dfastate_t *cur_state; + + if (entry->node != node) + continue; + subexp_len = entry->subexp_to - entry->subexp_from; + to_idx = str_idx + subexp_len; + dst_node = (subexp_len ? dfa->nexts[node] + : dfa->edests[node].elems[0]); + + if (to_idx > sctx->last_str_idx + || sctx->sifted_states[to_idx] == NULL + || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) + || check_dst_limits (mctx, &sctx->limits, node, + str_idx, dst_node, to_idx)) + continue; + + if (local_sctx.sifted_states == NULL) + { + local_sctx = *sctx; + err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + local_sctx.last_node = node; + local_sctx.last_str_idx = str_idx; + ret = re_node_set_insert (&local_sctx.limits, enabled_idx); + if (BE (ret < 0, 0)) + { + err = REG_ESPACE; + goto free_return; + } + cur_state = local_sctx.sifted_states[str_idx]; + err = sift_states_backward (mctx, &local_sctx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + if (sctx->limited_states != NULL) + { + err = merge_state_array (dfa, sctx->limited_states, + local_sctx.sifted_states, + str_idx + 1); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + local_sctx.sifted_states[str_idx] = cur_state; + re_node_set_remove (&local_sctx.limits, enabled_idx); + + /* mctx->bkref_ents may have changed, reload the pointer. */ + entry = mctx->bkref_ents + enabled_idx; + } + while (enabled_idx++, entry++->more); + } + err = REG_NOERROR; + free_return: + if (local_sctx.sifted_states != NULL) + { + re_node_set_free (&local_sctx.limits); + } + + return err; +} + + +#ifdef RE_ENABLE_I18N +static int +internal_function +sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, + int node_idx, int str_idx, int max_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int naccepted; + /* Check the node can accept `multi byte'. */ + naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); + if (naccepted > 0 && str_idx + naccepted <= max_str_idx && + !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], + dfa->nexts[node_idx])) + /* The node can't accept the `multi byte', or the + destination was already thrown away, then the node + could't accept the current input `multi byte'. */ + naccepted = 0; + /* Otherwise, it is sure that the node could accept + `naccepted' bytes input. */ + return naccepted; +} +#endif /* RE_ENABLE_I18N */ + + +/* Functions for state transition. */ + +/* Return the next state to which the current state STATE will transit by + accepting the current input byte, and update STATE_LOG if necessary. + If STATE can accept a multibyte char/collating element/back reference + update the destination of STATE_LOG. */ + +static re_dfastate_t * +internal_function +transit_state (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + re_dfastate_t **trtable; + unsigned char ch; + +#ifdef RE_ENABLE_I18N + /* If the current state can accept multibyte. */ + if (BE (state->accept_mb, 0)) + { + *err = transit_state_mb (mctx, state); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } +#endif /* RE_ENABLE_I18N */ + + /* Then decide the next state with the single byte. */ +#if 0 + if (0) + /* don't use transition table */ + return transit_state_sb (err, mctx, state); +#endif + + /* Use transition table */ + ch = re_string_fetch_byte (&mctx->input); + for (;;) + { + trtable = state->trtable; + if (BE (trtable != NULL, 1)) + return trtable[ch]; + + trtable = state->word_trtable; + if (BE (trtable != NULL, 1)) + { + unsigned int context; + context + = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return trtable[ch + SBC_MAX]; + else + return trtable[ch]; + } + + if (!build_trtable (mctx->dfa, state)) + { + *err = REG_ESPACE; + return NULL; + } + + /* Retry, we now have a transition table. */ + } +} + +/* Update the state_log if we need */ +re_dfastate_t * +internal_function +merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *next_state) +{ + const re_dfa_t *const dfa = mctx->dfa; + int cur_idx = re_string_cur_idx (&mctx->input); + + if (cur_idx > mctx->state_log_top) + { + mctx->state_log[cur_idx] = next_state; + mctx->state_log_top = cur_idx; + } + else if (mctx->state_log[cur_idx] == 0) + { + mctx->state_log[cur_idx] = next_state; + } + else + { + re_dfastate_t *pstate; + unsigned int context; + re_node_set next_nodes, *log_nodes, *table_nodes = NULL; + /* If (state_log[cur_idx] != 0), it implies that cur_idx is + the destination of a multibyte char/collating element/ + back reference. Then the next state is the union set of + these destinations and the results of the transition table. */ + pstate = mctx->state_log[cur_idx]; + log_nodes = pstate->entrance_nodes; + if (next_state != NULL) + { + table_nodes = next_state->entrance_nodes; + *err = re_node_set_init_union (&next_nodes, table_nodes, + log_nodes); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } + else + next_nodes = *log_nodes; + /* Note: We already add the nodes of the initial state, + then we don't need to add them here. */ + + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + next_state = mctx->state_log[cur_idx] + = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + if (table_nodes != NULL) + re_node_set_free (&next_nodes); + } + + if (BE (dfa->nbackref, 0) && next_state != NULL) + { + /* Check OP_OPEN_SUBEXP in the current state in case that we use them + later. We must check them here, since the back references in the + next state might use them. */ + *err = check_subexp_matching_top (mctx, &next_state->nodes, + cur_idx); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + + /* If the next state has back references. */ + if (next_state->has_backref) + { + *err = transit_state_bkref (mctx, &next_state->nodes); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + next_state = mctx->state_log[cur_idx]; + } + } + + return next_state; +} + +/* Skip bytes in the input that correspond to part of a + multi-byte match, then look in the log for a state + from which to restart matching. */ +re_dfastate_t * +internal_function +find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) +{ + re_dfastate_t *cur_state; + do + { + int max = mctx->state_log_top; + int cur_str_idx = re_string_cur_idx (&mctx->input); + + do + { + if (++cur_str_idx > max) + return NULL; + re_string_skip_bytes (&mctx->input, 1); + } + while (mctx->state_log[cur_str_idx] == NULL); + + cur_state = merge_state_with_log (err, mctx, NULL); + } + while (*err == REG_NOERROR && cur_state == NULL); + return cur_state; +} + +/* Helper functions for transit_state. */ + +/* From the node set CUR_NODES, pick up the nodes whose types are + OP_OPEN_SUBEXP and which have corresponding back references in the regular + expression. And register them to use them later for evaluating the + correspoding back references. */ + +static reg_errcode_t +internal_function +check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, + int str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int node_idx; + reg_errcode_t err; + + /* TODO: This isn't efficient. + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) + { + int node = cur_nodes->elems[node_idx]; + if (dfa->nodes[node].type == OP_OPEN_SUBEXP + && dfa->nodes[node].opr.idx < BITSET_WORD_BITS + && (dfa->used_bkref_map + & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) + { + err = match_ctx_add_subtop (mctx, node, str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + return REG_NOERROR; +} + +#if 0 +/* Return the next state to which the current state STATE will transit by + accepting the current input byte. */ + +static re_dfastate_t * +transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + const re_dfa_t *const dfa = mctx->dfa; + re_node_set next_nodes; + re_dfastate_t *next_state; + int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); + unsigned int context; + + *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) + { + int cur_node = state->nodes.elems[node_cnt]; + if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) + { + *err = re_node_set_merge (&next_nodes, + dfa->eclosures + dfa->nexts[cur_node]); + if (BE (*err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return NULL; + } + } + } + context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); + next_state = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + re_node_set_free (&next_nodes); + re_string_skip_bytes (&mctx->input, 1); + return next_state; +} +#endif + +#ifdef RE_ENABLE_I18N +static reg_errcode_t +internal_function +transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int i; + + for (i = 0; i < pstate->nodes.nelem; ++i) + { + re_node_set dest_nodes, *new_nodes; + int cur_node_idx = pstate->nodes.elems[i]; + int naccepted, dest_idx; + unsigned int context; + re_dfastate_t *dest_state; + + if (!dfa->nodes[cur_node_idx].accept_mb) + continue; + + if (dfa->nodes[cur_node_idx].constraint) + { + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input), + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, + context)) + continue; + } + + /* How many bytes the node can accept? */ + naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, + re_string_cur_idx (&mctx->input)); + if (naccepted == 0) + continue; + + /* The node can accepts `naccepted' bytes. */ + dest_idx = re_string_cur_idx (&mctx->input) + naccepted; + mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted + : mctx->max_mb_elem_len); + err = clean_state_log_if_needed (mctx, dest_idx); + if (BE (err != REG_NOERROR, 0)) + return err; +#ifdef DEBUG + assert (dfa->nexts[cur_node_idx] != -1); +#endif + new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; + + dest_state = mctx->state_log[dest_idx]; + if (dest_state == NULL) + dest_nodes = *new_nodes; + else + { + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, new_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + context = re_string_context_at (&mctx->input, dest_idx - 1, + mctx->eflags); + mctx->state_log[dest_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + if (dest_state != NULL) + re_node_set_free (&dest_nodes); + if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) + return err; + } + return REG_NOERROR; +} +#endif /* RE_ENABLE_I18N */ + +static reg_errcode_t +internal_function +transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int i; + int cur_str_idx = re_string_cur_idx (&mctx->input); + + for (i = 0; i < nodes->nelem; ++i) + { + int dest_str_idx, prev_nelem, bkc_idx; + int node_idx = nodes->elems[i]; + unsigned int context; + const re_token_t *node = dfa->nodes + node_idx; + re_node_set *new_dest_nodes; + + /* Check whether `node' is a backreference or not. */ + if (node->type != OP_BACK_REF) + continue; + + if (node->constraint) + { + context = re_string_context_at (&mctx->input, cur_str_idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + continue; + } + + /* `node' is a backreference. + Check the substring which the substring matched. */ + bkc_idx = mctx->nbkref_ents; + err = get_subexp (mctx, node_idx, cur_str_idx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* And add the epsilon closures (which is `new_dest_nodes') of + the backreference to appropriate state_log. */ +#ifdef DEBUG + assert (dfa->nexts[node_idx] != -1); +#endif + for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) + { + int subexp_len; + re_dfastate_t *dest_state; + struct re_backref_cache_entry *bkref_ent; + bkref_ent = mctx->bkref_ents + bkc_idx; + if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) + continue; + subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; + new_dest_nodes = (subexp_len == 0 + ? dfa->eclosures + dfa->edests[node_idx].elems[0] + : dfa->eclosures + dfa->nexts[node_idx]); + dest_str_idx = (cur_str_idx + bkref_ent->subexp_to + - bkref_ent->subexp_from); + context = re_string_context_at (&mctx->input, dest_str_idx - 1, + mctx->eflags); + dest_state = mctx->state_log[dest_str_idx]; + prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 + : mctx->state_log[cur_str_idx]->nodes.nelem); + /* Add `new_dest_node' to state_log. */ + if (dest_state == NULL) + { + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, new_dest_nodes, + context); + if (BE (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR, 0)) + goto free_return; + } + else + { + re_node_set dest_nodes; + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, + new_dest_nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&dest_nodes); + goto free_return; + } + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + re_node_set_free (&dest_nodes); + if (BE (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR, 0)) + goto free_return; + } + /* We need to check recursively if the backreference can epsilon + transit. */ + if (subexp_len == 0 + && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) + { + err = check_subexp_matching_top (mctx, new_dest_nodes, + cur_str_idx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + err = transit_state_bkref (mctx, new_dest_nodes); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + } + } + err = REG_NOERROR; + free_return: + return err; +} + +/* Enumerate all the candidates which the backreference BKREF_NODE can match + at BKREF_STR_IDX, and register them by match_ctx_add_entry(). + Note that we might collect inappropriate candidates here. + However, the cost of checking them strictly here is too high, then we + delay these checking for prune_impossible_nodes(). */ + +static reg_errcode_t +internal_function +get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int subexp_num, sub_top_idx; + const char *buf = (const char *) re_string_get_buffer (&mctx->input); + /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ + int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); + if (cache_idx != -1) + { + const struct re_backref_cache_entry *entry + = mctx->bkref_ents + cache_idx; + do + if (entry->node == bkref_node) + return REG_NOERROR; /* We already checked it. */ + while (entry++->more); + } + + subexp_num = dfa->nodes[bkref_node].opr.idx; + + /* For each sub expression */ + for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) + { + reg_errcode_t err; + re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; + re_sub_match_last_t *sub_last; + int sub_last_idx, sl_str, bkref_str_off; + + if (dfa->nodes[sub_top->node].opr.idx != subexp_num) + continue; /* It isn't related. */ + + sl_str = sub_top->str_idx; + bkref_str_off = bkref_str_idx; + /* At first, check the last node of sub expressions we already + evaluated. */ + for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) + { + int sl_str_diff; + sub_last = sub_top->lasts[sub_last_idx]; + sl_str_diff = sub_last->str_idx - sl_str; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_diff > 0) + { + if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) + { + /* Not enough chars for a successful match. */ + if (bkref_str_off + sl_str_diff > mctx->input.len) + break; + + err = clean_state_log_if_needed (mctx, + bkref_str_off + + sl_str_diff); + if (BE (err != REG_NOERROR, 0)) + return err; + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) + /* We don't need to search this sub expression any more. */ + break; + } + bkref_str_off += sl_str_diff; + sl_str += sl_str_diff; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + + /* Reload buf, since the preceding call might have reallocated + the buffer. */ + buf = (const char *) re_string_get_buffer (&mctx->input); + + if (err == REG_NOMATCH) + continue; + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (sub_last_idx < sub_top->nlasts) + continue; + if (sub_last_idx > 0) + ++sl_str; + /* Then, search for the other last nodes of the sub expression. */ + for (; sl_str <= bkref_str_idx; ++sl_str) + { + int cls_node, sl_str_off; + const re_node_set *nodes; + sl_str_off = sl_str - sub_top->str_idx; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_off > 0) + { + if (BE (bkref_str_off >= mctx->input.valid_len, 0)) + { + /* If we are at the end of the input, we cannot match. */ + if (bkref_str_off >= mctx->input.len) + break; + + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + return err; + + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (buf [bkref_str_off++] != buf[sl_str - 1]) + break; /* We don't need to search this sub expression + any more. */ + } + if (mctx->state_log[sl_str] == NULL) + continue; + /* Does this state have a ')' of the sub expression? */ + nodes = &mctx->state_log[sl_str]->nodes; + cls_node = find_subexp_node (dfa, nodes, subexp_num, + OP_CLOSE_SUBEXP); + if (cls_node == -1) + continue; /* No. */ + if (sub_top->path == NULL) + { + sub_top->path = calloc (sizeof (state_array_t), + sl_str - sub_top->str_idx + 1); + if (sub_top->path == NULL) + return REG_ESPACE; + } + /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node + in the current context? */ + err = check_arrival (mctx, sub_top->path, sub_top->node, + sub_top->str_idx, cls_node, sl_str, + OP_CLOSE_SUBEXP); + if (err == REG_NOMATCH) + continue; + if (BE (err != REG_NOERROR, 0)) + return err; + sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); + if (BE (sub_last == NULL, 0)) + return REG_ESPACE; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + if (err == REG_NOMATCH) + continue; + } + } + return REG_NOERROR; +} + +/* Helper functions for get_subexp(). */ + +/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. + If it can arrive, register the sub expression expressed with SUB_TOP + and SUB_LAST. */ + +static reg_errcode_t +internal_function +get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) +{ + reg_errcode_t err; + int to_idx; + /* Can the subexpression arrive the back reference? */ + err = check_arrival (mctx, &sub_last->path, sub_last->node, + sub_last->str_idx, bkref_node, bkref_str, + OP_OPEN_SUBEXP); + if (err != REG_NOERROR) + return err; + err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, + sub_last->str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; + return clean_state_log_if_needed (mctx, to_idx); +} + +/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. + Search '(' if FL_OPEN, or search ')' otherwise. + TODO: This function isn't efficient... + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + +static int +internal_function +find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + int subexp_idx, int type) +{ + int cls_idx; + for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) + { + int cls_node = nodes->elems[cls_idx]; + const re_token_t *node = dfa->nodes + cls_node; + if (node->type == type + && node->opr.idx == subexp_idx) + return cls_node; + } + return -1; +} + +/* Check whether the node TOP_NODE at TOP_STR can arrive to the node + LAST_NODE at LAST_STR. We record the path onto PATH since it will be + heavily reused. + Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ + +static reg_errcode_t +internal_function +check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, + int top_str, int last_node, int last_str, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + int subexp_num, backup_cur_idx, str_idx, null_cnt; + re_dfastate_t *cur_state = NULL; + re_node_set *cur_nodes, next_nodes; + re_dfastate_t **backup_state_log; + unsigned int context; + + subexp_num = dfa->nodes[top_node].opr.idx; + /* Extend the buffer if we need. */ + if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) + { + re_dfastate_t **new_array; + int old_alloc = path->alloc; + path->alloc += last_str + mctx->max_mb_elem_len + 1; + new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); + if (BE (new_array == NULL, 0)) + { + path->alloc = old_alloc; + return REG_ESPACE; + } + path->array = new_array; + memset (new_array + old_alloc, '\0', + sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); + } + + str_idx = path->next_idx ?: top_str; + + /* Temporary modify MCTX. */ + backup_state_log = mctx->state_log; + backup_cur_idx = mctx->input.cur_idx; + mctx->state_log = path->array; + mctx->input.cur_idx = str_idx; + + /* Setup initial node set. */ + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + if (str_idx == top_str) + { + err = re_node_set_init_1 (&next_nodes, top_node); + if (BE (err != REG_NOERROR, 0)) + return err; + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + else + { + cur_state = mctx->state_log[str_idx]; + if (cur_state && cur_state->has_backref) + { + err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + re_node_set_init_empty (&next_nodes); + } + if (str_idx == top_str || (cur_state && cur_state->has_backref)) + { + if (next_nodes.nelem) + { + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (BE (cur_state == NULL && err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + } + + for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) + { + re_node_set_empty (&next_nodes); + if (mctx->state_log[str_idx + 1]) + { + err = re_node_set_merge (&next_nodes, + &mctx->state_log[str_idx + 1]->nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + if (cur_state) + { + err = check_arrival_add_next_nodes (mctx, str_idx, + &cur_state->non_eps_nodes, + &next_nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + ++str_idx; + if (next_nodes.nelem) + { + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (BE (cur_state == NULL && err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + null_cnt = cur_state == NULL ? null_cnt + 1 : 0; + } + re_node_set_free (&next_nodes); + cur_nodes = (mctx->state_log[last_str] == NULL ? NULL + : &mctx->state_log[last_str]->nodes); + path->next_idx = str_idx; + + /* Fix MCTX. */ + mctx->state_log = backup_state_log; + mctx->input.cur_idx = backup_cur_idx; + + /* Then check the current node set has the node LAST_NODE. */ + if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) + return REG_NOERROR; + + return REG_NOMATCH; +} + +/* Helper functions for check_arrival. */ + +/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them + to NEXT_NODES. + TODO: This function is similar to the functions transit_state*(), + however this function has many additional works. + Can't we unify them? */ + +static reg_errcode_t +internal_function +check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, + re_node_set *cur_nodes, re_node_set *next_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + int result; + int cur_idx; +#ifdef RE_ENABLE_I18N + reg_errcode_t err = REG_NOERROR; +#endif + re_node_set union_set; + re_node_set_init_empty (&union_set); + for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) + { + int naccepted = 0; + int cur_node = cur_nodes->elems[cur_idx]; +#ifdef DEBUG + re_token_type_t type = dfa->nodes[cur_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept `multi byte'. */ + if (dfa->nodes[cur_node].accept_mb) + { + naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, + str_idx); + if (naccepted > 1) + { + re_dfastate_t *dest_state; + int next_node = dfa->nexts[cur_node]; + int next_idx = str_idx + naccepted; + dest_state = mctx->state_log[next_idx]; + re_node_set_empty (&union_set); + if (dest_state) + { + err = re_node_set_merge (&union_set, &dest_state->nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&union_set); + return err; + } + } + result = re_node_set_insert (&union_set, next_node); + if (BE (result < 0, 0)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + mctx->state_log[next_idx] = re_acquire_state (&err, dfa, + &union_set); + if (BE (mctx->state_log[next_idx] == NULL + && err != REG_NOERROR, 0)) + { + re_node_set_free (&union_set); + return err; + } + } + } +#endif /* RE_ENABLE_I18N */ + if (naccepted + || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) + { + result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); + if (BE (result < 0, 0)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + } + } + re_node_set_free (&union_set); + return REG_NOERROR; +} + +/* For all the nodes in CUR_NODES, add the epsilon closures of them to + CUR_NODES, however exclude the nodes which are: + - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. + - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. +*/ + +static reg_errcode_t +internal_function +check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, + int ex_subexp, int type) +{ + reg_errcode_t err; + int idx, outside_node; + re_node_set new_nodes; +#ifdef DEBUG + assert (cur_nodes->nelem); +#endif + err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); + if (BE (err != REG_NOERROR, 0)) + return err; + /* Create a new node set NEW_NODES with the nodes which are epsilon + closures of the node in CUR_NODES. */ + + for (idx = 0; idx < cur_nodes->nelem; ++idx) + { + int cur_node = cur_nodes->elems[idx]; + const re_node_set *eclosure = dfa->eclosures + cur_node; + outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); + if (outside_node == -1) + { + /* There are no problematic nodes, just merge them. */ + err = re_node_set_merge (&new_nodes, eclosure); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&new_nodes); + return err; + } + } + else + { + /* There are problematic nodes, re-calculate incrementally. */ + err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, + ex_subexp, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&new_nodes); + return err; + } + } + } + re_node_set_free (cur_nodes); + *cur_nodes = new_nodes; + return REG_NOERROR; +} + +/* Helper function for check_arrival_expand_ecl. + Check incrementally the epsilon closure of TARGET, and if it isn't + problematic append it to DST_NODES. */ + +static reg_errcode_t +internal_function +check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, + int target, int ex_subexp, int type) +{ + int cur_node; + for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) + { + int err; + + if (dfa->nodes[cur_node].type == type + && dfa->nodes[cur_node].opr.idx == ex_subexp) + { + if (type == OP_CLOSE_SUBEXP) + { + err = re_node_set_insert (dst_nodes, cur_node); + if (BE (err == -1, 0)) + return REG_ESPACE; + } + break; + } + err = re_node_set_insert (dst_nodes, cur_node); + if (BE (err == -1, 0)) + return REG_ESPACE; + if (dfa->edests[cur_node].nelem == 0) + break; + if (dfa->edests[cur_node].nelem == 2) + { + err = check_arrival_expand_ecl_sub (dfa, dst_nodes, + dfa->edests[cur_node].elems[1], + ex_subexp, type); + if (BE (err != REG_NOERROR, 0)) + return err; + } + cur_node = dfa->edests[cur_node].elems[0]; + } + return REG_NOERROR; +} + + +/* For all the back references in the current state, calculate the + destination of the back references by the appropriate entry + in MCTX->BKREF_ENTS. */ + +static reg_errcode_t +internal_function +expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, + int cur_str, int subexp_num, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); + struct re_backref_cache_entry *ent; + + if (cache_idx_start == -1) + return REG_NOERROR; + + restart: + ent = mctx->bkref_ents + cache_idx_start; + do + { + int to_idx, next_node; + + /* Is this entry ENT is appropriate? */ + if (!re_node_set_contains (cur_nodes, ent->node)) + continue; /* No. */ + + to_idx = cur_str + ent->subexp_to - ent->subexp_from; + /* Calculate the destination of the back reference, and append it + to MCTX->STATE_LOG. */ + if (to_idx == cur_str) + { + /* The backreference did epsilon transit, we must re-check all the + node in the current state. */ + re_node_set new_dests; + reg_errcode_t err2, err3; + next_node = dfa->edests[ent->node].elems[0]; + if (re_node_set_contains (cur_nodes, next_node)) + continue; + err = re_node_set_init_1 (&new_dests, next_node); + err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); + err3 = re_node_set_merge (cur_nodes, &new_dests); + re_node_set_free (&new_dests); + if (BE (err != REG_NOERROR || err2 != REG_NOERROR + || err3 != REG_NOERROR, 0)) + { + err = (err != REG_NOERROR ? err + : (err2 != REG_NOERROR ? err2 : err3)); + return err; + } + /* TODO: It is still inefficient... */ + goto restart; + } + else + { + re_node_set union_set; + next_node = dfa->nexts[ent->node]; + if (mctx->state_log[to_idx]) + { + int ret; + if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, + next_node)) + continue; + err = re_node_set_init_copy (&union_set, + &mctx->state_log[to_idx]->nodes); + ret = re_node_set_insert (&union_set, next_node); + if (BE (err != REG_NOERROR || ret < 0, 0)) + { + re_node_set_free (&union_set); + err = err != REG_NOERROR ? err : REG_ESPACE; + return err; + } + } + else + { + err = re_node_set_init_1 (&union_set, next_node); + if (BE (err != REG_NOERROR, 0)) + return err; + } + mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); + re_node_set_free (&union_set); + if (BE (mctx->state_log[to_idx] == NULL + && err != REG_NOERROR, 0)) + return err; + } + } + while (ent++->more); + return REG_NOERROR; +} + +/* Build transition table for the state. + Return 1 if succeeded, otherwise return NULL. */ + +static int +internal_function +build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) +{ + reg_errcode_t err; + int i, j, ch, need_word_trtable = 0; + bitset_word_t elem, mask; + bool dests_node_malloced = false; + bool dest_states_malloced = false; + int ndests; /* Number of the destination states from `state'. */ + re_dfastate_t **trtable; + re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; + re_node_set follows, *dests_node; + bitset_t *dests_ch; + bitset_t acceptable; + + struct dests_alloc + { + re_node_set dests_node[SBC_MAX]; + bitset_t dests_ch[SBC_MAX]; + } *dests_alloc; + + /* We build DFA states which corresponds to the destination nodes + from `state'. `dests_node[i]' represents the nodes which i-th + destination state contains, and `dests_ch[i]' represents the + characters which i-th destination state accepts. */ + if (__libc_use_alloca (sizeof (struct dests_alloc))) + dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); + else + { + dests_alloc = re_malloc (struct dests_alloc, 1); + if (BE (dests_alloc == NULL, 0)) + return 0; + dests_node_malloced = true; + } + dests_node = dests_alloc->dests_node; + dests_ch = dests_alloc->dests_ch; + + /* Initialize transiton table. */ + state->word_trtable = state->trtable = NULL; + + /* At first, group all nodes belonging to `state' into several + destinations. */ + ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); + if (BE (ndests <= 0, 0)) + { + if (dests_node_malloced) + free (dests_alloc); + /* Return 0 in case of an error, 1 otherwise. */ + if (ndests == 0) + { + state->trtable = (re_dfastate_t **) + calloc (sizeof (re_dfastate_t *), SBC_MAX); + return 1; + } + return 0; + } + + err = re_node_set_alloc (&follows, ndests + 1); + if (BE (err != REG_NOERROR, 0)) + goto out_free; + + if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX + + ndests * 3 * sizeof (re_dfastate_t *))) + dest_states = (re_dfastate_t **) + alloca (ndests * 3 * sizeof (re_dfastate_t *)); + else + { + dest_states = (re_dfastate_t **) + malloc (ndests * 3 * sizeof (re_dfastate_t *)); + if (BE (dest_states == NULL, 0)) + { +out_free: + if (dest_states_malloced) + free (dest_states); + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + if (dests_node_malloced) + free (dests_alloc); + return 0; + } + dest_states_malloced = true; + } + dest_states_word = dest_states + ndests; + dest_states_nl = dest_states_word + ndests; + bitset_empty (acceptable); + + /* Then build the states for all destinations. */ + for (i = 0; i < ndests; ++i) + { + int next_node; + re_node_set_empty (&follows); + /* Merge the follows of this destination states. */ + for (j = 0; j < dests_node[i].nelem; ++j) + { + next_node = dfa->nexts[dests_node[i].elems[j]]; + if (next_node != -1) + { + err = re_node_set_merge (&follows, dfa->eclosures + next_node); + if (BE (err != REG_NOERROR, 0)) + goto out_free; + } + } + dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); + if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + /* If the new state has context constraint, + build appropriate states for these contexts. */ + if (dest_states[i]->has_constraint) + { + dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_WORD); + if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + + if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) + need_word_trtable = 1; + + dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_NEWLINE); + if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + } + else + { + dest_states_word[i] = dest_states[i]; + dest_states_nl[i] = dest_states[i]; + } + bitset_merge (acceptable, dests_ch[i]); + } + + if (!BE (need_word_trtable, 0)) + { + /* We don't care about whether the following character is a word + character, or we are in a single-byte character set so we can + discern by looking at the character code: allocate a + 256-entry transition table. */ + trtable = state->trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (BE (trtable == NULL, 0)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (BE (elem & 1, 0)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + if (dfa->word_char[i] & mask) + trtable[ch] = dest_states_word[j]; + else + trtable[ch] = dest_states[j]; + } + } + else + { + /* We care about whether the following character is a word + character, and we are in a multi-byte character set: discern + by looking at the character code: build two 256-entry + transition tables, one starting at trtable[0] and one + starting at trtable[SBC_MAX]. */ + trtable = state->word_trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); + if (BE (trtable == NULL, 0)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (BE (elem & 1, 0)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + trtable[ch] = dest_states[j]; + trtable[ch + SBC_MAX] = dest_states_word[j]; + } + } + + /* new line */ + if (bitset_contain (acceptable, NEWLINE_CHAR)) + { + /* The current state accepts newline character. */ + for (j = 0; j < ndests; ++j) + if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) + { + /* k-th destination accepts newline character. */ + trtable[NEWLINE_CHAR] = dest_states_nl[j]; + if (need_word_trtable) + trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; + /* There must be only one destination which accepts + newline. See group_nodes_into_DFAstates. */ + break; + } + } + + if (dest_states_malloced) + free (dest_states); + + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + + if (dests_node_malloced) + free (dests_alloc); + + return 1; +} + +/* Group all nodes belonging to STATE into several destinations. + Then for all destinations, set the nodes belonging to the destination + to DESTS_NODE[i] and set the characters accepted by the destination + to DEST_CH[i]. This function return the number of destinations. */ + +static int +internal_function +group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + re_node_set *dests_node, bitset_t *dests_ch) +{ + reg_errcode_t err; + int result; + int i, j, k; + int ndests; /* Number of the destinations from `state'. */ + bitset_t accepts; /* Characters a node can accept. */ + const re_node_set *cur_nodes = &state->nodes; + bitset_empty (accepts); + ndests = 0; + + /* For all the nodes belonging to `state', */ + for (i = 0; i < cur_nodes->nelem; ++i) + { + re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + /* Enumerate all single byte character this node can accept. */ + if (type == CHARACTER) + bitset_set (accepts, node->opr.c); + else if (type == SIMPLE_BRACKET) + { + bitset_merge (accepts, node->opr.sbcset); + } + else if (type == OP_PERIOD) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + bitset_merge (accepts, dfa->sb_char); + else +#endif + bitset_set_all (accepts); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#ifdef RE_ENABLE_I18N + else if (type == OP_UTF8_PERIOD) + { + memset (accepts, '\xff', sizeof (bitset_t) / 2); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#endif + else + continue; + + /* Check the `accepts' and sift the characters which are not + match it the context. */ + if (constraint) + { + if (constraint & NEXT_NEWLINE_CONSTRAINT) + { + bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); + bitset_empty (accepts); + if (accepts_newline) + bitset_set (accepts, NEWLINE_CHAR); + else + continue; + } + if (constraint & NEXT_ENDBUF_CONSTRAINT) + { + bitset_empty (accepts); + continue; + } + + if (constraint & NEXT_WORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && !node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= dfa->word_char[j]); + if (!any_set) + continue; + } + if (constraint & NEXT_NOTWORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~dfa->word_char[j]); + if (!any_set) + continue; + } + } + + /* Then divide `accepts' into DFA states, or create a new + state. Above, we make sure that accepts is not empty. */ + for (j = 0; j < ndests; ++j) + { + bitset_t intersec; /* Intersection sets, see below. */ + bitset_t remains; + /* Flags, see below. */ + bitset_word_t has_intersec, not_subset, not_consumed; + + /* Optimization, skip if this state doesn't accept the character. */ + if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) + continue; + + /* Enumerate the intersection set of this state and `accepts'. */ + has_intersec = 0; + for (k = 0; k < BITSET_WORDS; ++k) + has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; + /* And skip if the intersection set is empty. */ + if (!has_intersec) + continue; + + /* Then check if this state is a subset of `accepts'. */ + not_subset = not_consumed = 0; + for (k = 0; k < BITSET_WORDS; ++k) + { + not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; + not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; + } + + /* If this state isn't a subset of `accepts', create a + new group state, which has the `remains'. */ + if (not_subset) + { + bitset_copy (dests_ch[ndests], remains); + bitset_copy (dests_ch[j], intersec); + err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); + if (BE (err != REG_NOERROR, 0)) + goto error_return; + ++ndests; + } + + /* Put the position in the current group. */ + result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); + if (BE (result < 0, 0)) + goto error_return; + + /* If all characters are consumed, go to next node. */ + if (!not_consumed) + break; + } + /* Some characters remain, create a new group. */ + if (j == ndests) + { + bitset_copy (dests_ch[ndests], accepts); + err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); + if (BE (err != REG_NOERROR, 0)) + goto error_return; + ++ndests; + bitset_empty (accepts); + } + } + return ndests; + error_return: + for (j = 0; j < ndests; ++j) + re_node_set_free (dests_node + j); + return -1; +} + +#ifdef RE_ENABLE_I18N +/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. + Return the number of the bytes the node accepts. + STR_IDX is the current index of the input string. + + This function handles the nodes which can accept one character, or + one collating element like '.', '[a-z]', opposite to the other nodes + can only accept one byte. */ + +static int +internal_function +check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + const re_string_t *input, int str_idx) +{ + const re_token_t *node = dfa->nodes + node_idx; + int char_len, elem_len; + int i; + + if (BE (node->type == OP_UTF8_PERIOD, 0)) + { + unsigned char c = re_string_byte_at (input, str_idx), d; + if (BE (c < 0xc2, 1)) + return 0; + + if (str_idx + 2 > input->len) + return 0; + + d = re_string_byte_at (input, str_idx + 1); + if (c < 0xe0) + return (d < 0x80 || d > 0xbf) ? 0 : 2; + else if (c < 0xf0) + { + char_len = 3; + if (c == 0xe0 && d < 0xa0) + return 0; + } + else if (c < 0xf8) + { + char_len = 4; + if (c == 0xf0 && d < 0x90) + return 0; + } + else if (c < 0xfc) + { + char_len = 5; + if (c == 0xf8 && d < 0x88) + return 0; + } + else if (c < 0xfe) + { + char_len = 6; + if (c == 0xfc && d < 0x84) + return 0; + } + else + return 0; + + if (str_idx + char_len > input->len) + return 0; + + for (i = 1; i < char_len; ++i) + { + d = re_string_byte_at (input, str_idx + i); + if (d < 0x80 || d > 0xbf) + return 0; + } + return char_len; + } + + char_len = re_string_char_size_at (input, str_idx); + if (node->type == OP_PERIOD) + { + if (char_len <= 1) + return 0; + /* FIXME: I don't think this if is needed, as both '\n' + and '\0' are char_len == 1. */ + /* '.' accepts any one character except the following two cases. */ + if ((!(dfa->syntax & RE_DOT_NEWLINE) && + re_string_byte_at (input, str_idx) == '\n') || + ((dfa->syntax & RE_DOT_NOT_NULL) && + re_string_byte_at (input, str_idx) == '\0')) + return 0; + return char_len; + } + + elem_len = re_string_elem_size_at (input, str_idx); + if ((elem_len <= 1 && char_len <= 1) || char_len == 0) + return 0; + + if (node->type == COMPLEX_BRACKET) + { + const re_charset_t *cset = node->opr.mbcset; +# ifdef _LIBC + const unsigned char *pin + = ((const unsigned char *) re_string_get_buffer (input) + str_idx); + int j; + uint32_t nrules; +# endif /* _LIBC */ + int match_len = 0; + wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) + ? re_string_wchar_at (input, str_idx) : 0); + + /* match with multibyte character? */ + for (i = 0; i < cset->nmbchars; ++i) + if (wc == cset->mbchars[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + /* match with character_class? */ + for (i = 0; i < cset->nchar_classes; ++i) + { + wctype_t wt = cset->char_classes[i]; + if (__iswctype (wc, wt)) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + unsigned int in_collseq = 0; + const int32_t *table, *indirect; + const unsigned char *weights, *extra; + const char *collseqwc; + int32_t idx; + /* This #include defines a local function! */ +# include + + /* match with collating_symbol? */ + if (cset->ncoll_syms) + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + for (i = 0; i < cset->ncoll_syms; ++i) + { + const unsigned char *coll_sym = extra + cset->coll_syms[i]; + /* Compare the length of input collating element and + the length of current collating element. */ + if (*coll_sym != elem_len) + continue; + /* Compare each bytes. */ + for (j = 0; j < *coll_sym; j++) + if (pin[j] != coll_sym[1 + j]) + break; + if (j == *coll_sym) + { + /* Match if every bytes is equal. */ + match_len = j; + goto check_node_accept_bytes_match; + } + } + + if (cset->nranges) + { + if (elem_len <= char_len) + { + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + in_collseq = __collseq_table_lookup (collseqwc, wc); + } + else + in_collseq = find_collation_sequence_value (pin, elem_len); + } + /* match with range expression? */ + for (i = 0; i < cset->nranges; ++i) + if (cset->range_starts[i] <= in_collseq + && in_collseq <= cset->range_ends[i]) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + + /* match with equivalence_class? */ + if (cset->nequiv_classes) + { + const unsigned char *cp = pin; + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + idx = findidx (&cp); + if (idx > 0) + for (i = 0; i < cset->nequiv_classes; ++i) + { + int32_t equiv_class_idx = cset->equiv_classes[i]; + size_t weight_len = weights[idx]; + if (weight_len == weights[equiv_class_idx]) + { + int cnt = 0; + while (cnt <= weight_len + && (weights[equiv_class_idx + 1 + cnt] + == weights[idx + 1 + cnt])) + ++cnt; + if (cnt > weight_len) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + } + } + } + } + else +# endif /* _LIBC */ + { + /* match with range expression? */ +#if __GNUC__ >= 2 + wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; +#else + wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; + cmp_buf[2] = wc; +#endif + for (i = 0; i < cset->nranges; ++i) + { + cmp_buf[0] = cset->range_starts[i]; + cmp_buf[4] = cset->range_ends[i]; + if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 + && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + } + check_node_accept_bytes_match: + if (!cset->non_match) + return match_len; + else + { + if (match_len > 0) + return 0; + else + return (elem_len > char_len) ? elem_len : char_len; + } + } + return 0; +} + +# ifdef _LIBC +static unsigned int +internal_function +find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) +{ + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules == 0) + { + if (mbs_len == 1) + { + /* No valid character. Match it as a single byte character. */ + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + return collseq[mbs[0]]; + } + return UINT_MAX; + } + else + { + int32_t idx; + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + int32_t extrasize = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; + + for (idx = 0; idx < extrasize;) + { + int mbs_cnt, found = 0; + int32_t elem_mbs_len; + /* Skip the name of collating element name. */ + idx = idx + extra[idx] + 1; + elem_mbs_len = extra[idx++]; + if (mbs_len == elem_mbs_len) + { + for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) + if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) + break; + if (mbs_cnt == elem_mbs_len) + /* Found the entry. */ + found = 1; + } + /* Skip the byte sequence of the collating element. */ + idx += elem_mbs_len; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + /* Skip the wide char sequence of the collating element. */ + idx = idx + sizeof (uint32_t) * (extra[idx] + 1); + /* If we found the entry, return the sequence value. */ + if (found) + return *(uint32_t *) (extra + idx); + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + } + return UINT_MAX; + } +} +# endif /* _LIBC */ +#endif /* RE_ENABLE_I18N */ + +/* Check whether the node accepts the byte which is IDX-th + byte of the INPUT. */ + +static int +internal_function +check_node_accept (const re_match_context_t *mctx, const re_token_t *node, + int idx) +{ + unsigned char ch; + ch = re_string_byte_at (&mctx->input, idx); + switch (node->type) + { + case CHARACTER: + if (node->opr.c != ch) + return 0; + break; + + case SIMPLE_BRACKET: + if (!bitset_contain (node->opr.sbcset, ch)) + return 0; + break; + +#ifdef RE_ENABLE_I18N + case OP_UTF8_PERIOD: + if (ch >= 0x80) + return 0; + /* FALLTHROUGH */ +#endif + case OP_PERIOD: + if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) + || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) + return 0; + break; + + default: + return 0; + } + + if (node->constraint) + { + /* The node has constraints. Check whether the current context + satisfies the constraints. */ + unsigned int context = re_string_context_at (&mctx->input, idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + return 0; + } + + return 1; +} + +/* Extend the buffers, if the buffers have run out. */ + +static reg_errcode_t +internal_function +extend_buffers (re_match_context_t *mctx) +{ + reg_errcode_t ret; + re_string_t *pstr = &mctx->input; + + /* Double the lengthes of the buffers. */ + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + if (mctx->state_log != NULL) + { + /* And double the length of state_log. */ + /* XXX We have no indication of the size of this buffer. If this + allocation fail we have no indication that the state_log array + does not have the right size. */ + re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, + pstr->bufs_len + 1); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + mctx->state_log = new_array; + } + + /* Then reconstruct the buffers. */ + if (pstr->icase) + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif /* RE_ENABLE_I18N */ + { + if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + } + return REG_NOERROR; +} + + +/* Functions for matching context. */ + +/* Initialize MCTX. */ + +static reg_errcode_t +internal_function +match_ctx_init (re_match_context_t *mctx, int eflags, int n) +{ + mctx->eflags = eflags; + mctx->match_last = -1; + if (n > 0) + { + mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); + mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); + if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) + return REG_ESPACE; + } + /* Already zero-ed by the caller. + else + mctx->bkref_ents = NULL; + mctx->nbkref_ents = 0; + mctx->nsub_tops = 0; */ + mctx->abkref_ents = n; + mctx->max_mb_elem_len = 1; + mctx->asub_tops = n; + return REG_NOERROR; +} + +/* Clean the entries which depend on the current input in MCTX. + This function must be invoked when the matcher changes the start index + of the input, or changes the input string. */ + +static void +internal_function +match_ctx_clean (re_match_context_t *mctx) +{ + int st_idx; + for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) + { + int sl_idx; + re_sub_match_top_t *top = mctx->sub_tops[st_idx]; + for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) + { + re_sub_match_last_t *last = top->lasts[sl_idx]; + re_free (last->path.array); + re_free (last); + } + re_free (top->lasts); + if (top->path) + { + re_free (top->path->array); + re_free (top->path); + } + free (top); + } + + mctx->nsub_tops = 0; + mctx->nbkref_ents = 0; +} + +/* Free all the memory associated with MCTX. */ + +static void +internal_function +match_ctx_free (re_match_context_t *mctx) +{ + /* First, free all the memory associated with MCTX->SUB_TOPS. */ + match_ctx_clean (mctx); + re_free (mctx->sub_tops); + re_free (mctx->bkref_ents); +} + +/* Add a new backreference entry to MCTX. + Note that we assume that caller never call this function with duplicate + entry, and call with STR_IDX which isn't smaller than any existing entry. +*/ + +static reg_errcode_t +internal_function +match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, + int to) +{ + if (mctx->nbkref_ents >= mctx->abkref_ents) + { + struct re_backref_cache_entry* new_entry; + new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, + mctx->abkref_ents * 2); + if (BE (new_entry == NULL, 0)) + { + re_free (mctx->bkref_ents); + return REG_ESPACE; + } + mctx->bkref_ents = new_entry; + memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', + sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); + mctx->abkref_ents *= 2; + } + if (mctx->nbkref_ents > 0 + && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) + mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; + + mctx->bkref_ents[mctx->nbkref_ents].node = node; + mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; + mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; + mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; + + /* This is a cache that saves negative results of check_dst_limits_calc_pos. + If bit N is clear, means that this entry won't epsilon-transition to + an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If + it is set, check_dst_limits_calc_pos_1 will recurse and try to find one + such node. + + A backreference does not epsilon-transition unless it is empty, so set + to all zeros if FROM != TO. */ + mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map + = (from == to ? ~0 : 0); + + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; + if (mctx->max_mb_elem_len < to - from) + mctx->max_mb_elem_len = to - from; + return REG_NOERROR; +} + +/* Search for the first entry which has the same str_idx, or -1 if none is + found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ + +static int +internal_function +search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) +{ + int left, right, mid, last; + last = right = mctx->nbkref_ents; + for (left = 0; left < right;) + { + mid = (left + right) / 2; + if (mctx->bkref_ents[mid].str_idx < str_idx) + left = mid + 1; + else + right = mid; + } + if (left < last && mctx->bkref_ents[left].str_idx == str_idx) + return left; + else + return -1; +} + +/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches + at STR_IDX. */ + +static reg_errcode_t +internal_function +match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) +{ +#ifdef DEBUG + assert (mctx->sub_tops != NULL); + assert (mctx->asub_tops > 0); +#endif + if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) + { + int new_asub_tops = mctx->asub_tops * 2; + re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, + re_sub_match_top_t *, + new_asub_tops); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + mctx->sub_tops = new_array; + mctx->asub_tops = new_asub_tops; + } + mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); + if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) + return REG_ESPACE; + mctx->sub_tops[mctx->nsub_tops]->node = node; + mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; + return REG_NOERROR; +} + +/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches + at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ + +static re_sub_match_last_t * +internal_function +match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) +{ + re_sub_match_last_t *new_entry; + if (BE (subtop->nlasts == subtop->alasts, 0)) + { + int new_alasts = 2 * subtop->alasts + 1; + re_sub_match_last_t **new_array = re_realloc (subtop->lasts, + re_sub_match_last_t *, + new_alasts); + if (BE (new_array == NULL, 0)) + return NULL; + subtop->lasts = new_array; + subtop->alasts = new_alasts; + } + new_entry = calloc (1, sizeof (re_sub_match_last_t)); + if (BE (new_entry != NULL, 1)) + { + subtop->lasts[subtop->nlasts] = new_entry; + new_entry->node = node; + new_entry->str_idx = str_idx; + ++subtop->nlasts; + } + return new_entry; +} + +static void +internal_function +sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, int last_node, int last_str_idx) +{ + sctx->sifted_states = sifted_sts; + sctx->limited_states = limited_sts; + sctx->last_node = last_node; + sctx->last_str_idx = last_str_idx; + re_node_set_init_empty (&sctx->limits); +} diff --git a/libc/misc/search/Makefile b/libc/misc/search/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/search/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/search/Makefile.in b/libc/misc/search/Makefile.in new file mode 100644 index 0000000..495c3cf --- /dev/null +++ b/libc/misc/search/Makefile.in @@ -0,0 +1,33 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := hsearch.c + +# multi source _tsearch.c +CSRC += tsearch.c tfind.c tdelete.c twalk.c tdestroy.c + +# multi source _lsearch.c +CSRC += lfind.c lsearch.c + +# multi source insremque.c +CSRC += insque.c remque.c + +# multi source _hsearch_r.c +CSRC += hcreate_r.c hdestroy_r.c hsearch_r.c + +MISC_SEARCH_DIR := $(top_srcdir)libc/misc/search +MISC_SEARCH_OUT := $(top_builddir)libc/misc/search + +MISC_SEARCH_SRC := $(patsubst %.c,$(MISC_SEARCH_DIR)/%.c,$(CSRC)) +MISC_SEARCH_OBJ := $(patsubst %.c,$(MISC_SEARCH_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_SEARCH_OBJ) + +objclean-y += misc_search_clean + +misc_search_clean: + $(do_rm) $(addprefix $(MISC_SEARCH_OUT)/*., o os) diff --git a/libc/misc/search/_hsearch_r.c b/libc/misc/search/_hsearch_r.c new file mode 100644 index 0000000..c9c4a9c --- /dev/null +++ b/libc/misc/search/_hsearch_r.c @@ -0,0 +1,231 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1993. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include + + +/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 + [Knuth] The Art of Computer Programming, part 3 (6.4) */ + + +/* The reentrant version has no static variables to maintain the state. + Instead the interface of all functions is extended to take an argument + which describes the current status. */ +typedef struct _ENTRY +{ + unsigned int used; + ENTRY entry; +} +_ENTRY; + + +#ifdef L_hcreate_r + +/* For the used double hash method the table size has to be a prime. To + correct the user given table size we need a prime test. This trivial + algorithm is adequate because + a) the code is (most probably) called a few times per program run and + b) the number is small because the table must fit in the core */ +static int isprime (unsigned int number) +{ + /* no even number will be passed */ + unsigned int div = 3; + + while (div * div < number && number % div != 0) + div += 2; + + return number % div != 0; +} + + +/* Before using the hash table we must allocate memory for it. + Test for an existing table are done. We allocate one element + more as the found prime number says. This is done for more effective + indexing as explained in the comment for the hsearch function. + The contents of the table is zeroed, especially the field used + becomes zero. */ +libc_hidden_proto(hcreate_r) +int hcreate_r (size_t nel, struct hsearch_data *htab) +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return 0; + } + + /* There is still another table active. Return with error. */ + if (htab->table != NULL) + return 0; + + /* Change nel to the first prime number not smaller as nel. */ + nel |= 1; /* make odd */ + while (!isprime (nel)) + nel += 2; + + htab->size = nel; + htab->filled = 0; + + /* allocate memory and zero out */ + htab->table = (_ENTRY *) calloc (htab->size + 1, sizeof (_ENTRY)); + if (htab->table == NULL) + return 0; + + /* everything went alright */ + return 1; +} +libc_hidden_def(hcreate_r) +#endif + +#ifdef L_hdestroy_r +/* After using the hash table it has to be destroyed. The used memory can + be freed and the local static variable can be marked as not used. */ +libc_hidden_proto(hdestroy_r) +void hdestroy_r (struct hsearch_data *htab) +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return; + } + + /* free used memory */ + free (htab->table); + + /* the sign for an existing table is an value != NULL in htable */ + htab->table = NULL; +} +libc_hidden_def(hdestroy_r) +#endif + +#ifdef L_hsearch_r +/* This is the search function. It uses double hashing with open addressing. + The argument item.key has to be a pointer to an zero terminated, most + probably strings of chars. The function for generating a number of the + strings is simple but fast. It can be replaced by a more complex function + like ajw (see [Aho,Sethi,Ullman]) if the needs are shown. + + We use an trick to speed up the lookup. The table is created by hcreate + with one more element available. This enables us to use the index zero + special. This index will never be used because we store the first hash + index in the field used where zero means not used. Every other value + means used. The used field can be used as a first fast comparison for + equality of the stored and the parameter value. This helps to prevent + unnecessary expensive calls of strcmp. */ + +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ + +libc_hidden_proto(hsearch_r) +int hsearch_r (ENTRY item, ACTION action, ENTRY **retval, + struct hsearch_data *htab) +{ + unsigned int hval; + unsigned int count; + unsigned int len = strlen (item.key); + unsigned int idx; + + /* Compute an value for the given string. Perhaps use a better method. */ + hval = len; + count = len; + while (count-- > 0) + { + hval <<= 4; + hval += item.key[count]; + } + + /* First hash function: simply take the modul but prevent zero. */ + hval %= htab->size; + if (hval == 0) + ++hval; + + /* The first index tried. */ + idx = hval; + + if (htab->table[idx].used) + { + /* Further action might be required according to the action value. */ + unsigned hval2; + + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + + /* Second hash function, as suggested in [Knuth] */ + hval2 = 1 + hval % (htab->size - 2); + + do + { + /* Because SIZE is prime this guarantees to step through all + available indeces. */ + if (idx <= hval2) + idx = htab->size + idx - hval2; + else + idx -= hval2; + + /* If we visited all entries leave the loop unsuccessfully. */ + if (idx == hval) + break; + + /* If entry is found use it. */ + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + } + while (htab->table[idx].used); + } + + /* An empty bucket has been found. */ + if (action == ENTER) + { + /* If table is full and another entry should be entered return + with error. */ + if (htab->filled == htab->size) + { + __set_errno (ENOMEM); + *retval = NULL; + return 0; + } + + htab->table[idx].used = hval; + htab->table[idx].entry = item; + + ++htab->filled; + + *retval = &htab->table[idx].entry; + return 1; + } + + __set_errno (ESRCH); + *retval = NULL; + return 0; +} +libc_hidden_def(hsearch_r) +#endif diff --git a/libc/misc/search/_lsearch.c b/libc/misc/search/_lsearch.c new file mode 100644 index 0000000..e446489 --- /dev/null +++ b/libc/misc/search/_lsearch.c @@ -0,0 +1,51 @@ +/* + * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath) + * + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + */ + +#include +#include +#include + +libc_hidden_proto(lfind) + +#ifdef L_lfind + +void *lfind(const void *key, const void *base, size_t *nmemb, + size_t size, int (*compar)(const void *, const void *)) +{ + register int n = *nmemb; + + while (n--) { + if ((*compar) (key, base) == 0) + return ((void*)base); + base += size; + } + return (NULL); +} +libc_hidden_def(lfind) + +#endif + +#ifdef L_lsearch + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +void *lsearch(const void *key, void *base, size_t *nmemb, + size_t size, int (*compar)(const void *, const void *)) +{ + register char *p; + + if ((p = lfind(key, base, nmemb, size, compar)) == NULL) { + p = memcpy((base + (size * (*nmemb))), key, size); + ++(*nmemb); + } + return (p); +} + +#endif diff --git a/libc/misc/search/_tsearch.c b/libc/misc/search/_tsearch.c new file mode 100644 index 0000000..3d43aa5 --- /dev/null +++ b/libc/misc/search/_tsearch.c @@ -0,0 +1,223 @@ +/* Copyright (C) 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ +/*LINTLIBRARY*/ + +#include +#include + +/* This routine is not very bad. It makes many assumptions about + * the compiler. It assumpts that the first field in node must be + * the "key" field, which points to the datum. It is a very trick + * stuff. H.J. + */ + +typedef struct node_t +{ + void *key; + struct node_t *left, *right; +} node; + +#ifdef L_tsearch +/* find or insert datum into search tree. +char *key; key to be located +register node **rootp; address of tree root +int (*compar)(); ordering function +*/ + +libc_hidden_proto(tsearch) +void *tsearch(__const void *key, void **vrootp, __compar_fn_t compar) +{ + register node *q; + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0) + return ((struct node_t *)0); + while (*rootp != (struct node_t *)0) /* Knuth's T1: */ + { + int r; + + if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ + return (*rootp); /* we found it! */ + rootp = (r < 0) ? + &(*rootp)->left : /* T3: follow left branch */ + &(*rootp)->right; /* T4: follow right branch */ + } + q = (node *) malloc(sizeof(node)); /* T5: key not found */ + if (q != (struct node_t *)0) /* make new node */ + { + *rootp = q; /* link new node to old */ + q->key = (void *)key; /* initialize new node */ + q->left = q->right = (struct node_t *)0; + } + return (q); +} +libc_hidden_def(tsearch) +#endif + +#ifdef L_tfind +libc_hidden_proto(tfind) +void *tfind(__const void *key, void * __const *vrootp, __compar_fn_t compar) +{ + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0) + return ((struct node_t *)0); + while (*rootp != (struct node_t *)0) /* Knuth's T1: */ + { + int r; + + if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ + return (*rootp); /* we found it! */ + rootp = (r < 0) ? + &(*rootp)->left : /* T3: follow left branch */ + &(*rootp)->right; /* T4: follow right branch */ + } + return NULL; +} +libc_hidden_def(tfind) +#endif + +#ifdef L_tdelete +/* delete node with given key +char *key; key to be deleted +register node **rootp; address of the root of tree +int (*compar)(); comparison function +*/ +void *tdelete(__const void *key, void ** vrootp, __compar_fn_t compar) +{ + node *p; + register node *q; + register node *r; + int cmp; + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0) + return ((struct node_t *)0); + while ((cmp = (*compar)(key, (*rootp)->key)) != 0) + { + p = *rootp; + rootp = (cmp < 0) ? + &(*rootp)->left : /* follow left branch */ + &(*rootp)->right; /* follow right branch */ + if (*rootp == (struct node_t *)0) + return ((struct node_t *)0); /* key not found */ + } + r = (*rootp)->right; /* D1: */ + if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */ + q = r; + else if (r != (struct node_t *)0) /* Right link is null? */ + { + if (r->left == (struct node_t *)0) /* D2: Find successor */ + { + r->left = q; + q = r; + } + else + { /* D3: Find (struct node_t *)0 link */ + for (q = r->left; q->left != (struct node_t *)0; q = r->left) + r = q; + r->left = q->right; + q->left = (*rootp)->left; + q->right = (*rootp)->right; + } + } + free((struct node_t *) *rootp); /* D4: Free node */ + *rootp = q; /* link parent to new node */ + return(p); +} +#endif + +#ifdef L_twalk +/* Walk the nodes of a tree +register node *root; Root of the tree to be walked +register void (*action)(); Function to be called at each node +register int level; +*/ +static void trecurse(__const void *vroot, __action_fn_t action, int level) +{ + register node *root = (node *) vroot; + + if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0) + (*action)(root, leaf, level); + else + { + (*action)(root, preorder, level); + if (root->left != (struct node_t *)0) + trecurse(root->left, action, level + 1); + (*action)(root, postorder, level); + if (root->right != (struct node_t *)0) + trecurse(root->right, action, level + 1); + (*action)(root, endorder, level); + } +} + +/* void twalk(root, action) Walk the nodes of a tree +node *root; Root of the tree to be walked +void (*action)(); Function to be called at each node +PTR +*/ +void twalk(__const void *vroot, __action_fn_t action) +{ + register __const node *root = (node *) vroot; + + if (root != (node *)0 && action != (__action_fn_t) 0) + trecurse(root, action, 0); +} +#endif + +#ifdef __USE_GNU +#ifdef L_tdestroy +/* The standardized functions miss an important functionality: the + tree cannot be removed easily. We provide a function to do this. */ +static void +internal_function +tdestroy_recurse (node *root, __free_fn_t freefct) +{ + if (root->left != NULL) + tdestroy_recurse (root->left, freefct); + if (root->right != NULL) + tdestroy_recurse (root->right, freefct); + (*freefct) ((void *) root->key); + /* Free the node itself. */ + free (root); +} + +libc_hidden_proto(tdestroy) +void tdestroy (void *vroot, __free_fn_t freefct) +{ + node *root = (node *) vroot; + if (root != NULL) { + tdestroy_recurse (root, freefct); + } +} +libc_hidden_def(tdestroy) +#endif +#endif + +/* tsearch.c ends here */ diff --git a/libc/misc/search/hcreate_r.c b/libc/misc/search/hcreate_r.c new file mode 100644 index 0000000..b62991e --- /dev/null +++ b/libc/misc/search/hcreate_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hcreate_r +#include "_hsearch_r.c" diff --git a/libc/misc/search/hdestroy_r.c b/libc/misc/search/hdestroy_r.c new file mode 100644 index 0000000..98e1ddb --- /dev/null +++ b/libc/misc/search/hdestroy_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hdestroy_r +#include "_hsearch_r.c" diff --git a/libc/misc/search/hsearch.c b/libc/misc/search/hsearch.c new file mode 100644 index 0000000..b1228e2 --- /dev/null +++ b/libc/misc/search/hsearch.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Ulrich Drepper + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(hdestroy_r) +libc_hidden_proto(hsearch_r) +libc_hidden_proto(hcreate_r) + +/* The non-reentrant version use a global space for storing the table. */ +static struct hsearch_data htab; + + +/* Define the non-reentrant function using the reentrant counterparts. */ +ENTRY *hsearch (ENTRY item, ACTION action) +{ + ENTRY *result; + + (void) hsearch_r (item, action, &result, &htab); + + return result; +} + + +int hcreate (size_t nel) +{ + return hcreate_r (nel, &htab); +} + + +/* void __hdestroy (void) */ +void hdestroy (void) +{ + hdestroy_r (&htab); +} + +/* Make sure the table is freed if we want to free everything before + exiting. */ +/* text_set_element (__libc_subfreeres, __hdestroy); */ diff --git a/libc/misc/search/hsearch_r.c b/libc/misc/search/hsearch_r.c new file mode 100644 index 0000000..48bdf2d --- /dev/null +++ b/libc/misc/search/hsearch_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hsearch_r +#include "_hsearch_r.c" diff --git a/libc/misc/search/insque.c b/libc/misc/search/insque.c new file mode 100644 index 0000000..fc5bf80 --- /dev/null +++ b/libc/misc/search/insque.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_insque +#include "insremque.c" diff --git a/libc/misc/search/insremque.c b/libc/misc/search/insremque.c new file mode 100644 index 0000000..32edf7a --- /dev/null +++ b/libc/misc/search/insremque.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#ifdef L_insque + +/* Insert ELEM into a doubly-linked list, after PREV. */ + +void +insque (void *elem, void *prev) +{ + struct qelem *next = ((struct qelem *) prev)->q_forw; + ((struct qelem *) prev)->q_forw = (struct qelem *) elem; + if (next != NULL) + next->q_back = (struct qelem *) elem; + ((struct qelem *) elem)->q_forw = next; + ((struct qelem *) elem)->q_back = (struct qelem *) prev; +} + +#endif + +#ifdef L_remque +/* Unlink ELEM from the doubly-linked list that it is in. */ + +void +remque (void *elem) +{ + struct qelem *next = ((struct qelem *) elem)->q_forw; + struct qelem *prev = ((struct qelem *) elem)->q_back; + if (next != NULL) + next->q_back = prev; + if (prev != NULL) + prev->q_forw = (struct qelem *) next; +} + +#endif diff --git a/libc/misc/search/lfind.c b/libc/misc/search/lfind.c new file mode 100644 index 0000000..66111c5 --- /dev/null +++ b/libc/misc/search/lfind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lfind +#include "_lsearch.c" diff --git a/libc/misc/search/lsearch.c b/libc/misc/search/lsearch.c new file mode 100644 index 0000000..1e63297 --- /dev/null +++ b/libc/misc/search/lsearch.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lsearch +#include "_lsearch.c" diff --git a/libc/misc/search/remque.c b/libc/misc/search/remque.c new file mode 100644 index 0000000..bab6985 --- /dev/null +++ b/libc/misc/search/remque.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_remque +#include "insremque.c" diff --git a/libc/misc/search/tdelete.c b/libc/misc/search/tdelete.c new file mode 100644 index 0000000..33d9fe8 --- /dev/null +++ b/libc/misc/search/tdelete.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tdelete +#include "_tsearch.c" diff --git a/libc/misc/search/tdestroy.c b/libc/misc/search/tdestroy.c new file mode 100644 index 0000000..3e397ea --- /dev/null +++ b/libc/misc/search/tdestroy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tdestroy +#include "_tsearch.c" diff --git a/libc/misc/search/tfind.c b/libc/misc/search/tfind.c new file mode 100644 index 0000000..e5a3161 --- /dev/null +++ b/libc/misc/search/tfind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tfind +#include "_tsearch.c" diff --git a/libc/misc/search/tsearch.c b/libc/misc/search/tsearch.c new file mode 100644 index 0000000..8984fc1 --- /dev/null +++ b/libc/misc/search/tsearch.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tsearch +#include "_tsearch.c" diff --git a/libc/misc/search/twalk.c b/libc/misc/search/twalk.c new file mode 100644 index 0000000..f36d341 --- /dev/null +++ b/libc/misc/search/twalk.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_twalk +#include "_tsearch.c" diff --git a/libc/misc/statfs/Makefile b/libc/misc/statfs/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/statfs/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/statfs/Makefile.in b/libc/misc/statfs/Makefile.in new file mode 100644 index 0000000..1c4fa83 --- /dev/null +++ b/libc/misc/statfs/Makefile.in @@ -0,0 +1,29 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := statvfs.c fstatvfs.c +ifeq ($(UCLIBC_HAS_LFS),y) +ifeq ($(UCLIBC_LINUX_SPECIFIC),y) +CSRC += fstatfs64.c statfs64.c +endif +CSRC += statvfs64.c fstatvfs64.c +endif + +MISC_STATFS_DIR := $(top_srcdir)libc/misc/statfs +MISC_STATFS_OUT := $(top_builddir)libc/misc/statfs + +MISC_STATFS_SRC := $(patsubst %.c,$(MISC_STATFS_DIR)/%.c,$(CSRC)) +MISC_STATFS_OBJ := $(patsubst %.c,$(MISC_STATFS_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_STATFS_OBJ) + +libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_STATFS_OUT)/statvfs64.o $(MISC_STATFS_OUT)/fstatvfs64.o + +objclean-y += misc_statfs_clean + +misc_statfs_clean: + $(do_rm) $(addprefix $(MISC_STATFS_OUT)/*., o os oS) diff --git a/libc/misc/statfs/fstatfs64.c b/libc/misc/statfs/fstatfs64.c new file mode 100644 index 0000000..a7f94b1 --- /dev/null +++ b/libc/misc/statfs/fstatfs64.c @@ -0,0 +1,53 @@ +/* Return information about the filesystem on which FD resides. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(fstatfs) + +/* Return information about the filesystem on which FD resides. */ +libc_hidden_proto(fstatfs64) +int fstatfs64 (int fd, struct statfs64 *buf) +{ + struct statfs buf32; + + if (fstatfs (fd, &buf32) < 0) + return -1; + + buf->f_type = buf32.f_type; + buf->f_bsize = buf32.f_bsize; + buf->f_blocks = buf32.f_blocks; + buf->f_bfree = buf32.f_bfree; + buf->f_bavail = buf32.f_bavail; + buf->f_files = buf32.f_files; + buf->f_ffree = buf32.f_ffree; + buf->f_fsid = buf32.f_fsid; + buf->f_namelen = buf32.f_namelen; + memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare)); + + return 0; +} +libc_hidden_def(fstatfs64) diff --git a/libc/misc/statfs/fstatvfs.c b/libc/misc/statfs/fstatvfs.c new file mode 100644 index 0000000..e21235e --- /dev/null +++ b/libc/misc/statfs/fstatvfs.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strsep) */ +libc_hidden_proto(setmntent) +libc_hidden_proto(getmntent_r) +libc_hidden_proto(endmntent) + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs; +libc_hidden_proto(__libc_fstatfs) +libc_hidden_proto(fstat) +libc_hidden_proto(stat) + +int fstatvfs (int fd, struct statvfs *buf) +{ + struct statfs fsbuf; + struct stat st; + + /* Get as much information as possible from the system. */ + if (__libc_fstatfs (fd, &fsbuf) < 0) + return -1; + +#define STAT(st) fstat (fd, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} diff --git a/libc/misc/statfs/fstatvfs64.c b/libc/misc/statfs/fstatvfs64.c new file mode 100644 index 0000000..2d44e42 --- /dev/null +++ b/libc/misc/statfs/fstatvfs64.c @@ -0,0 +1,80 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strsep) */ +libc_hidden_proto(setmntent) +libc_hidden_proto(getmntent_r) +libc_hidden_proto(endmntent) + +#undef stat +#define stat stat64 +#if defined __UCLIBC_LINUX_SPECIFIC__ +libc_hidden_proto(fstatfs64) +libc_hidden_proto(fstat64) +#endif +libc_hidden_proto(stat64) + +int fstatvfs64 (int fd, struct statvfs64 *buf) +{ + struct statfs64 fsbuf; + struct stat64 st; +#if !defined __UCLIBC_LINUX_SPECIFIC__ + int ret; + struct statvfs buf32; + + ret = fstatvfs (fd, &buf32); + if (ret == 0) { + fsbuf.f_bsize = buf32.f_bsize; + fsbuf.f_frsize = buf32.f_frsize; + fsbuf.f_blocks = buf32.f_blocks; + fsbuf.f_bfree = buf32.f_bfree; + fsbuf.f_bavail = buf32.f_bavail; + fsbuf.f_files = buf32.f_files; + fsbuf.f_ffree = buf32.f_ffree; + if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid)) + memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid)); + /* and if not, then you could approximate or whatever.. */ + fsbuf.f_namelen = buf32.f_namemax; + } else + return ret; +#else + /* Get as much information as possible from the system. */ + if (fstatfs64 (fd, &fsbuf) < 0) + return -1; +#endif +#define STAT(st) fstat64 (fd, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} diff --git a/libc/misc/statfs/internal_statvfs.c b/libc/misc/statfs/internal_statvfs.c new file mode 100644 index 0000000..6075e9c --- /dev/null +++ b/libc/misc/statfs/internal_statvfs.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Now fill in the fields we have information for. */ + buf->f_bsize = fsbuf.f_bsize; + /* Linux does not support f_frsize, so set it to the full block size. */ + buf->f_frsize = fsbuf.f_bsize; + buf->f_blocks = fsbuf.f_blocks; + buf->f_bfree = fsbuf.f_bfree; + buf->f_bavail = fsbuf.f_bavail; + buf->f_files = fsbuf.f_files; + buf->f_ffree = fsbuf.f_ffree; + if (sizeof (buf->f_fsid) == sizeof (fsbuf.f_fsid)) + buf->f_fsid = (fsbuf.f_fsid.__val[0] + | ((unsigned long int) fsbuf.f_fsid.__val[1] + << (8 * (sizeof (buf->f_fsid) + - sizeof (fsbuf.f_fsid.__val[0]))))); + else + /* We cannot help here. The statvfs element is not large enough to + contain both words of the statfs f_fsid field. */ + buf->f_fsid = fsbuf.f_fsid.__val[0]; +#ifdef _STATVFSBUF_F_UNUSED + buf->__f_unused = 0; +#endif + buf->f_namemax = fsbuf.f_namelen; + memset (buf->__f_spare, '\0', 6 * sizeof (int)); + + /* What remains to do is to fill the fields f_favail and f_flag. */ + + /* XXX I have no idea how to compute f_favail. Any idea??? */ + buf->f_favail = buf->f_ffree; + + /* Determining the flags is tricky. We have to read /proc/mounts or + the /etc/mtab file and search for the entry which matches the given + file. The way we can test for matching filesystem is using the + device number. */ + buf->f_flag = 0; + if (STAT (&st) >= 0) + { + int save_errno = errno; + struct mntent mntbuf; + FILE *mtab; + + mtab = setmntent ("/proc/mounts", "r"); + if (mtab == NULL) + mtab = setmntent (_PATH_MOUNTED, "r"); + + if (mtab != NULL) + { + char tmpbuf[1024]; + + while (getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf))) + { + struct stat fsst; + + /* Find out about the device the current entry is for. */ + if (stat (mntbuf.mnt_dir, &fsst) >= 0 + && st.st_dev == fsst.st_dev) + { + /* Bingo, we found the entry for the device FD is on. + Now interpret the option string. */ + char *cp = mntbuf.mnt_opts; + char *opt; + + while ((opt = strsep (&cp, ",")) != NULL) + if (strcmp (opt, "ro") == 0) + buf->f_flag |= ST_RDONLY; + else if (strcmp (opt, "nosuid") == 0) + buf->f_flag |= ST_NOSUID; +#ifdef __USE_GNU + else if (strcmp (opt, "noexec") == 0) + buf->f_flag |= ST_NOEXEC; + else if (strcmp (opt, "nodev") == 0) + buf->f_flag |= ST_NODEV; + else if (strcmp (opt, "sync") == 0) + buf->f_flag |= ST_SYNCHRONOUS; + else if (strcmp (opt, "mand") == 0) + buf->f_flag |= ST_MANDLOCK; + else if (strcmp (opt, "noatime") == 0) + buf->f_flag |= ST_NOATIME; + else if (strcmp (opt, "nodiratime") == 0) + buf->f_flag |= ST_NODIRATIME; +#endif + + /* We can stop looking for more entries. */ + break; + } + } + + /* Close the file. */ + endmntent (mtab); + } + + __set_errno (save_errno); + } diff --git a/libc/misc/statfs/statfs64.c b/libc/misc/statfs/statfs64.c new file mode 100644 index 0000000..18ce33b --- /dev/null +++ b/libc/misc/statfs/statfs64.c @@ -0,0 +1,52 @@ +/* Return information about the filesystem on which FILE resides. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(statfs) + +/* Return information about the filesystem on which FILE resides. */ +libc_hidden_proto(statfs64) +int statfs64 (const char *file, struct statfs64 *buf) +{ + struct statfs buf32; + + if (statfs (file, &buf32) < 0) + return -1; + + buf->f_type = buf32.f_type; + buf->f_bsize = buf32.f_bsize; + buf->f_blocks = buf32.f_blocks; + buf->f_bfree = buf32.f_bfree; + buf->f_bavail = buf32.f_bavail; + buf->f_files = buf32.f_files; + buf->f_ffree = buf32.f_ffree; + buf->f_fsid = buf32.f_fsid; + buf->f_namelen = buf32.f_namelen; + memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare)); + + return 0; +} +libc_hidden_def(statfs64) diff --git a/libc/misc/statfs/statvfs.c b/libc/misc/statfs/statvfs.c new file mode 100644 index 0000000..5085a2a --- /dev/null +++ b/libc/misc/statfs/statvfs.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strsep) */ +libc_hidden_proto(setmntent) +libc_hidden_proto(getmntent_r) +libc_hidden_proto(endmntent) + +extern __typeof(statfs) __libc_statfs; +libc_hidden_proto(__libc_statfs) +libc_hidden_proto(stat) + +libc_hidden_proto(statvfs) +int statvfs (const char *file, struct statvfs *buf) +{ + struct statfs fsbuf; + struct stat st; + + /* Get as much information as possible from the system. */ + if (__libc_statfs (file, &fsbuf) < 0) + return -1; + +#define STAT(st) stat (file, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} +libc_hidden_def(statvfs) diff --git a/libc/misc/statfs/statvfs64.c b/libc/misc/statfs/statvfs64.c new file mode 100644 index 0000000..008ba78 --- /dev/null +++ b/libc/misc/statfs/statvfs64.c @@ -0,0 +1,80 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strsep) */ +libc_hidden_proto(setmntent) +libc_hidden_proto(getmntent_r) +libc_hidden_proto(endmntent) + +#undef stat +#define stat stat64 +#if defined __UCLIBC_LINUX_SPECIFIC__ +libc_hidden_proto(statfs64) +#else +libc_hidden_proto(statvfs) +#endif +libc_hidden_proto(stat64) + +int statvfs64 (const char *file, struct statvfs64 *buf) +{ + struct statfs64 fsbuf; + struct stat64 st; +#if !defined __UCLIBC_LINUX_SPECIFIC__ + int ret; + struct statvfs buf32; + + ret = statvfs (file, &buf32); + if (ret == 0) { + fsbuf.f_bsize = buf32.f_bsize; + fsbuf.f_frsize = buf32.f_frsize; + fsbuf.f_blocks = buf32.f_blocks; + fsbuf.f_bfree = buf32.f_bfree; + fsbuf.f_bavail = buf32.f_bavail; + fsbuf.f_files = buf32.f_files; + fsbuf.f_ffree = buf32.f_ffree; + if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid)) + memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid)); + /* and if not, then you could approximate or whatever.. */ + fsbuf.f_namelen = buf32.f_namemax; + } else + return ret; +#else + /* Get as much information as possible from the system. */ + if (statfs64 (file, &fsbuf) < 0) + return -1; +#endif +#define STAT(st) stat (file, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} diff --git a/libc/misc/syslog/Makefile b/libc/misc/syslog/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/syslog/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/syslog/Makefile.in b/libc/misc/syslog/Makefile.in new file mode 100644 index 0000000..90c18e6 --- /dev/null +++ b/libc/misc/syslog/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := syslog.c + +MISC_SYSLOG_DIR := $(top_srcdir)libc/misc/syslog +MISC_SYSLOG_OUT := $(top_builddir)libc/misc/syslog + +MISC_SYSLOG_SRC := $(patsubst %.c,$(MISC_SYSLOG_DIR)/%.c,$(CSRC)) +MISC_SYSLOG_OBJ := $(patsubst %.c,$(MISC_SYSLOG_OUT)/%.o,$(CSRC)) + +ifeq ($(UCLIBC_HAS_SYSLOG),y) +libc-y += $(MISC_SYSLOG_OBJ) +endif + +objclean-y += misc_syslog_clean + +misc_syslog_clean: + $(do_rm) $(addprefix $(MISC_SYSLOG_OUT)/*., o os) diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c new file mode 100644 index 0000000..c90703a --- /dev/null +++ b/libc/misc/syslog/syslog.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * SYSLOG -- print message on log file + * + * This routine looks a lot like printf, except that it outputs to the + * log file instead of the standard output. Also: + * adds a timestamp, + * prints the module name in front of the message, + * has some other formatting types (or will sometime), + * adds a newline on the end of the message. + * + * The output of this routine is intended to be read by syslogd(8). + * + * Author: Eric Allman + * Modified to use UNIX domain IPC by Ralph Campbell + * Patched March 12, 1996 by A. Ian Vogelesang + * - to correct the handling of message & format string truncation, + * - to visibly tag truncated records to facilitate + * investigation of such Bad Things with grep, and, + * - to correct the handling of case where "write" + * returns after writing only part of the message. + * Rewritten by Martin Mares on May 14, 1997 + * - better buffer overrun checks. + * - special handling of "%m" removed as we use GNU sprintf which handles + * it automatically. + * - Major code cleanup. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(openlog) +libc_hidden_proto(syslog) +libc_hidden_proto(vsyslog) +libc_hidden_proto(closelog) + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memmove) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(open) +libc_hidden_proto(fcntl) +libc_hidden_proto(socket) +libc_hidden_proto(close) +libc_hidden_proto(write) +libc_hidden_proto(getpid) +libc_hidden_proto(ctime) +libc_hidden_proto(sigaction) +libc_hidden_proto(sigemptyset) +libc_hidden_proto(connect) +libc_hidden_proto(sprintf) +libc_hidden_proto(vsnprintf) +/* Experimentally off - libc_hidden_proto(time) */ + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + +static int LogFile = -1; /* fd for log */ +static smalluint connected; /* have done connect */ +/* all bits in option argument for openlog() fit in 8 bits */ +static smalluint LogStat = 0; /* status bits, set by openlog() */ +static const char *LogTag = "syslog"; /* string to tag the entry with */ +/* this fits in 8 bits too (LOG_LOCAL7 = 23<<3 = 184), + * but NB: LOG_FACMASK is bigger (= 0x03f8 = 127<<3) for some strange reason. + * Oh well. */ +static int LogFacility = LOG_USER;/* default facility code */ +/* bits mask of priorities (eight prios - 8 bits is enough) */ +static smalluint LogMask = 0xff; /* mask of priorities to be logged */ +/* AF_UNIX address of local logger (we use struct sockaddr + * instead of struct sockaddr_un since "/dev/log" is small enough) */ +static const struct sockaddr SyslogAddr = { + .sa_family = AF_UNIX, /* sa_family_t (usually a short) */ + .sa_data = _PATH_LOG /* char [14] */ +}; + +static void +closelog_intern(int sig) +{ + /* mylock must be held by the caller */ + if (LogFile != -1) { + (void) close(LogFile); + } + LogFile = -1; + connected = 0; + if (sig == 0) { /* called from closelog()? - reset to defaults */ + LogStat = 0; + LogTag = "syslog"; + LogFacility = LOG_USER; + LogMask = 0xff; + } +} + +/* + * OPENLOG -- open system log + */ +void +openlog(const char *ident, int logstat, int logfac) +{ + int logType = SOCK_DGRAM; + + __UCLIBC_MUTEX_LOCK(mylock); + + if (ident != NULL) + LogTag = ident; + LogStat = logstat; + if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) + LogFacility = logfac; + if (LogFile == -1) { +retry: + if (LogStat & LOG_NDELAY) { + if ((LogFile = socket(AF_UNIX, logType, 0)) == -1) { + goto DONE; + } + fcntl(LogFile, F_SETFD, 1); /* 1 == FD_CLOEXEC */ + /* We don't want to block if e.g. syslogd is SIGSTOPed */ + fcntl(LogFile, F_SETFL, O_NONBLOCK | fcntl(LogFile, F_GETFL)); + } + } + + if (LogFile != -1 && !connected) { + if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) { + connected = 1; + } else { + if (LogFile != -1) { + close(LogFile); + LogFile = -1; + } + if (logType == SOCK_DGRAM) { + logType = SOCK_STREAM; + goto retry; + } + } + } + +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(openlog) + +/* + * syslog, vsyslog -- + * print message on log file; output is intended for syslogd(8). + */ +void +vsyslog(int pri, const char *fmt, va_list ap) +{ + register char *p; + char *last_chr, *head_end, *end, *stdp; + time_t now; + int fd, saved_errno; + int rc; + char tbuf[1024]; /* syslogd is unable to handle longer messages */ + struct sigaction action, oldaction; + + memset(&action, 0, sizeof(action)); + action.sa_handler = closelog_intern; + sigemptyset(&action.sa_mask); /* TODO: memset already zeroed it out! */ + /* Only two errors are possible for sigaction: + * EFAULT (bad address of &oldaction) and EINVAL (invalid signo) + * none of which can happen here. */ + /*int sigpipe =*/ sigaction(SIGPIPE, &action, &oldaction); + + saved_errno = errno; + + __UCLIBC_MUTEX_LOCK(mylock); + + /* See if we should just throw out this message. */ + if (!(LogMask & LOG_MASK(LOG_PRI(pri))) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) + goto getout; + if (LogFile < 0 || !connected) + openlog(LogTag, LogStat | LOG_NDELAY, 0); + + /* Set default facility if none specified. */ + if ((pri & LOG_FACMASK) == 0) + pri |= LogFacility; + + /* Build the message. We know the starting part of the message can take + * no longer than 64 characters plus length of the LogTag. So it's + * safe to test only LogTag and use normal sprintf everywhere else. + */ + (void)time(&now); + stdp = p = tbuf + sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); + if (LogTag) { + if (strlen(LogTag) < sizeof(tbuf) - 64) + p += sprintf(p, "%s", LogTag); + else + p += sprintf(p, ""); + } + if (LogStat & LOG_PID) + p += sprintf(p, "[%d]", getpid()); + if (LogTag) { + *p++ = ':'; + *p++ = ' '; + } + head_end = p; + + /* We format the rest of the message. If the buffer becomes full, we mark + * the message as truncated. Note that we require at least 2 free bytes + * in the buffer as we might want to add "\r\n" there. + */ + + end = tbuf + sizeof(tbuf) - 1; + __set_errno(saved_errno); + p += vsnprintf(p, end - p, fmt, ap); + if (p >= end || p < head_end) { /* Returned -1 in case of error... */ + static const char truncate_msg[12] = "[truncated] "; /* no NUL! */ + memmove(head_end + sizeof(truncate_msg), head_end, + end - head_end - sizeof(truncate_msg)); + memcpy(head_end, truncate_msg, sizeof(truncate_msg)); + if (p < head_end) { + while (p < end && *p) { + p++; + } + } + else { + p = end - 1; + } + + } + last_chr = p; + + /* Output to stderr if requested. */ + if (LogStat & LOG_PERROR) { + *last_chr = '\n'; + (void)write(STDERR_FILENO, stdp, last_chr - stdp + 1); + } + + /* Output the message to the local logger using NUL as a message delimiter. */ + p = tbuf; + *last_chr = 0; + if (LogFile >= 0) { + do { + rc = write(LogFile, p, last_chr + 1 - p); + if (rc < 0) { + /* I don't think looping forever on EAGAIN is a good idea. + * Imagine that syslogd is SIGSTOPed... */ + if (/* (errno != EAGAIN) && */ (errno != EINTR)) { + closelog_intern(1); /* 1: do not reset LogXXX globals to default */ + goto write_err; + } + rc = 0; + } + p += rc; + } while (p <= last_chr); + goto getout; + } + + write_err: + /* + * Output the message to the console; don't worry about blocking, + * if console blocks everything will. Make sure the error reported + * is the one from the syslogd failure. + */ + /* should mode be O_WRONLY | O_NOCTTY? -- Uli */ + /* yes, but in Linux "/dev/console" never becomes ctty anyway -- vda */ + if ((LogStat & LOG_CONS) && + (fd = open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY)) >= 0) { + p = strchr(tbuf, '>') + 1; + last_chr[0] = '\r'; + last_chr[1] = '\n'; + (void)write(fd, p, last_chr - p + 2); + (void)close(fd); + } + +getout: + __UCLIBC_MUTEX_UNLOCK(mylock); + /*if (sigpipe == 0)*/ + sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL); +} +libc_hidden_def(vsyslog) + +void +syslog(int pri, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(pri, fmt, ap); + va_end(ap); +} +libc_hidden_def(syslog) + +/* + * CLOSELOG -- close the system log + */ +void +closelog(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + closelog_intern(0); /* 0: reset LogXXX globals to default */ + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(closelog) + +/* setlogmask -- set the log mask level */ +int setlogmask(int pmask) +{ + int omask; + + omask = LogMask; + if (pmask != 0) { + __UCLIBC_MUTEX_LOCK(mylock); + LogMask = pmask; + __UCLIBC_MUTEX_UNLOCK(mylock); + } + return omask; +} diff --git a/libc/misc/sysvipc/.indent.pro b/libc/misc/sysvipc/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/sysvipc/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/sysvipc/Makefile b/libc/misc/sysvipc/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/sysvipc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/sysvipc/Makefile.in b/libc/misc/sysvipc/Makefile.in new file mode 100644 index 0000000..c3807c0 --- /dev/null +++ b/libc/misc/sysvipc/Makefile.in @@ -0,0 +1,30 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := ftok.c __syscall_ipc.c + +# multi source sem.c +CSRC += semget.c semctl.c semop.c semtimedop.c + +# multi source shm.c +CSRC += shmat.c shmctl.c shmdt.c shmget.c + +# multi source msgq.c +CSRC += msgctl.c msgget.c msgrcv.c msgsnd.c + +MISC_SYSVIPC_DIR := $(top_srcdir)libc/misc/sysvipc +MISC_SYSVIPC_OUT := $(top_builddir)libc/misc/sysvipc + +MISC_SYSVIPC_SRC := $(patsubst %.c,$(MISC_SYSVIPC_DIR)/%.c,$(CSRC)) +MISC_SYSVIPC_OBJ := $(patsubst %.c,$(MISC_SYSVIPC_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_SYSVIPC_OBJ) + +objclean-y += misc_sysvipc_clean + +misc_sysvipc_clean: + $(do_rm) $(addprefix $(MISC_SYSVIPC_OUT)/*., o os) diff --git a/libc/misc/sysvipc/__syscall_ipc.c b/libc/misc/sysvipc/__syscall_ipc.c new file mode 100644 index 0000000..304a42c --- /dev/null +++ b/libc/misc/sysvipc/__syscall_ipc.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_ipc() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_ipc +#define __NR___syscall_ipc __NR_ipc +#include "ipc.h" +_syscall6(int, __syscall_ipc, unsigned int, call, long, first, long, second, long, + third, void *, ptr, void *, fifth) +#endif diff --git a/libc/misc/sysvipc/ftok.c b/libc/misc/sysvipc/ftok.c new file mode 100644 index 0000000..12627ca --- /dev/null +++ b/libc/misc/sysvipc/ftok.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +libc_hidden_proto(stat) + +key_t ftok (const char *pathname, int proj_id) +{ + struct stat st; + key_t key; + + if (stat(pathname, &st) < 0) + return (key_t) -1; + + key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) + | ((proj_id & 0xff) << 24)); + + return key; +} diff --git a/libc/misc/sysvipc/ipc.h b/libc/misc/sysvipc/ipc.h new file mode 100644 index 0000000..339d136 --- /dev/null +++ b/libc/misc/sysvipc/ipc.h @@ -0,0 +1,35 @@ +#ifndef IPC_H +#define IPC_H +#include +#include + +#if __WORDSIZE == 32 || defined __alpha__ || defined __mips__ +# define __IPC_64 0x100 +#else +# define __IPC_64 0x0 +#endif + +#ifdef __NR_ipc + +/* The actual system call: all functions are multiplexed by this. */ +extern int __syscall_ipc (unsigned int __call, long __first, long __second, + long __third, void *__ptr, void *__fifth) attribute_hidden; + + +/* The codes for the functions to use the multiplexer `__syscall_ipc'. */ +#define IPCOP_semop 1 +#define IPCOP_semget 2 +#define IPCOP_semctl 3 +#define IPCOP_semtimedop 4 +#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 + +#endif + +#endif /* IPC_H */ diff --git a/libc/misc/sysvipc/msgctl.c b/libc/misc/sysvipc/msgctl.c new file mode 100644 index 0000000..480a54c --- /dev/null +++ b/libc/misc/sysvipc/msgctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgctl +#include "msgq.c" diff --git a/libc/misc/sysvipc/msgget.c b/libc/misc/sysvipc/msgget.c new file mode 100644 index 0000000..f7e54d5 --- /dev/null +++ b/libc/misc/sysvipc/msgget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgget +#include "msgq.c" diff --git a/libc/misc/sysvipc/msgq.c b/libc/misc/sysvipc/msgq.c new file mode 100644 index 0000000..e43a9ed --- /dev/null +++ b/libc/misc/sysvipc/msgq.c @@ -0,0 +1,73 @@ +#include +#include +#include "ipc.h" + + +#ifdef L_msgctl + +#ifdef __NR_msgctl +#define __NR___libc_msgctl __NR_msgctl +static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msqid_ds *, buf); +#endif +/* Message queue control operation. */ +int msgctl(int msqid, int cmd, struct msqid_ds *buf) +{ +#ifdef __NR_msgctl + return __libc_msgctl(msqid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0); +#endif +} +#endif + + +#ifdef L_msgget +#ifdef __NR_msgget +_syscall2(int, msgget, key_t, key, int, msgflg) +#else +/* Get messages queue. */ +int msgget (key_t key, int msgflg) +{ + return __syscall_ipc(IPCOP_msgget ,key ,msgflg ,0 ,0, 0); +} +#endif +#endif + + +struct new_msg_buf{ + struct msgbuf * oldmsg; + long int r_msgtyp; /* the fifth arg of __syscall_ipc */ +}; +/* Receive message from message queue. */ + + +#ifdef L_msgrcv +#ifdef __NR_msgrcv +_syscall5(int, msgrcv, int, msqid, void *, msgp, size_t, msgsz, long int, msgtyp, int, msgflg) +#else +int msgrcv (int msqid, void *msgp, size_t msgsz, + long int msgtyp, int msgflg) +{ + struct new_msg_buf temp; + + temp.r_msgtyp = msgtyp; + temp.oldmsg = msgp; + return __syscall_ipc(IPCOP_msgrcv ,msqid ,msgsz ,msgflg ,&temp, 0); +} +#endif +#endif + + + +#ifdef L_msgsnd +#ifdef __NR_msgsnd +_syscall4(int, msgsnd, int, msqid, const void *, msgp, size_t, msgsz, int, msgflg) +#else +/* Send message to message queue. */ +int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg) +{ + return __syscall_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, (void *)msgp, 0); +} +#endif +#endif + diff --git a/libc/misc/sysvipc/msgrcv.c b/libc/misc/sysvipc/msgrcv.c new file mode 100644 index 0000000..a85e52a --- /dev/null +++ b/libc/misc/sysvipc/msgrcv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgrcv +#include "msgq.c" diff --git a/libc/misc/sysvipc/msgsnd.c b/libc/misc/sysvipc/msgsnd.c new file mode 100644 index 0000000..9f09d1f --- /dev/null +++ b/libc/misc/sysvipc/msgsnd.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgsnd +#include "msgq.c" diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c new file mode 100644 index 0000000..96d6a6e --- /dev/null +++ b/libc/misc/sysvipc/sem.c @@ -0,0 +1,105 @@ +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include /* for NULL */ + +#include "ipc.h" + + +#ifdef L_semctl +/* Return identifier for array of NSEMS semaphores associated with + KEY. */ +#include +/* arg for semctl system calls. */ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + unsigned short *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ + void *__pad; +}; + + +#ifdef __NR_semctl +#define __NR___semctl __NR_semctl +static __inline__ _syscall4(int, __semctl, int, semid, int, semnum, int, cmd, void *, arg); +#endif + +int semctl(int semid, int semnum, int cmd, ...) +{ + union semun arg; + va_list ap; + + /* Get the argument. */ + va_start (ap, cmd); + arg = va_arg (ap, union semun); + va_end (ap); +#ifdef __NR_semctl + return __semctl(semid, semnum, cmd | __IPC_64, arg.__pad); +#else + return __syscall_ipc(IPCOP_semctl, semid, semnum, cmd|__IPC_64, &arg, NULL); +#endif +} +#endif + +#ifdef L_semget +#ifdef __NR_semget +_syscall3(int, semget, key_t, key, int, nsems, int, semflg) + +#else +/* Return identifier for array of NSEMS semaphores associated + * with KEY. */ +int semget (key_t key, int nsems, int semflg) +{ + return __syscall_ipc(IPCOP_semget, key, nsems, semflg, NULL, 0); +} +#endif +#endif + +#ifdef L_semop + +#ifdef __NR_semop +_syscall3(int, semop, int, semid, struct sembuf *, sops, size_t, nsops) + +#else +/* Perform user-defined atomical operation of array of semaphores. */ +int semop (int semid, struct sembuf *sops, size_t nsops) +{ + return __syscall_ipc(IPCOP_semop, semid, (int) nsops, 0, sops, NULL); +} +#endif +#endif + +#ifdef L_semtimedop + +#ifdef __NR_semtimedop +_syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) + +#else + +int semtimedop(int semid, struct sembuf *sops, size_t nsops, + const struct timespec *timeout) +{ + return __syscall_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, timeout); +} +#endif +#endif diff --git a/libc/misc/sysvipc/semctl.c b/libc/misc/sysvipc/semctl.c new file mode 100644 index 0000000..df62a76 --- /dev/null +++ b/libc/misc/sysvipc/semctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semctl +#include "sem.c" diff --git a/libc/misc/sysvipc/semget.c b/libc/misc/sysvipc/semget.c new file mode 100644 index 0000000..94d0b5d --- /dev/null +++ b/libc/misc/sysvipc/semget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semget +#include "sem.c" diff --git a/libc/misc/sysvipc/semop.c b/libc/misc/sysvipc/semop.c new file mode 100644 index 0000000..0c67f62 --- /dev/null +++ b/libc/misc/sysvipc/semop.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semop +#include "sem.c" diff --git a/libc/misc/sysvipc/semtimedop.c b/libc/misc/sysvipc/semtimedop.c new file mode 100644 index 0000000..ecd0438 --- /dev/null +++ b/libc/misc/sysvipc/semtimedop.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semtimedop +#include "sem.c" diff --git a/libc/misc/sysvipc/shm.c b/libc/misc/sysvipc/shm.c new file mode 100644 index 0000000..9d71161 --- /dev/null +++ b/libc/misc/sysvipc/shm.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* SHMLBA uses it on most of the archs (not mips) */ +#define __getpagesize getpagesize + +#include +#include +#include +#include +#include "ipc.h" + +#ifdef L_shmat +/* Attach the shared memory segment associated with SHMID to the data + segment of the calling process. SHMADDR and SHMFLG determine how + and where the segment is attached. */ +#if defined(__NR_osf_shmat) +# define __NR_shmat __NR_osf_shmat +#endif +#ifdef __NR_shmat +_syscall3(void *, shmat, int, shmid, const void *,shmaddr, int, shmflg) +#else +/* psm: don't remove this, else mips will fail */ +#include +libc_hidden_proto(getpagesize) + +void * shmat (int shmid, const void *shmaddr, int shmflg) +{ + int retval; + unsigned long raddr; + + retval = __syscall_ipc(IPCOP_shmat, shmid, shmflg, (int) &raddr, (void *) shmaddr, 0); + return ((unsigned long int) retval > -(unsigned long int) SHMLBA + ? (void *) retval : (void *) raddr); +} +#endif +#endif + +#ifdef L_shmctl +/* Provide operations to control over shared memory segments. */ +#ifdef __NR_shmctl +#define __NR___libc_shmctl __NR_shmctl +static __inline__ _syscall3(int, __libc_shmctl, int, shmid, int, cmd, struct shmid_ds *, buf); +#endif +int shmctl(int shmid, int cmd, struct shmid_ds *buf) +{ +#ifdef __NR_shmctl + return __libc_shmctl(shmid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0); +#endif +} +#endif + + +#ifdef L_shmdt +/* Detach shared memory segment starting at address specified by SHMADDR + from the caller's data segment. */ +#ifdef __NR_shmdt +_syscall1(int, shmdt, const void *, shmaddr) +#else +int shmdt (const void *shmaddr) +{ + return __syscall_ipc(IPCOP_shmdt, 0, 0, 0, (void *) shmaddr, 0); +} +#endif +#endif + +#ifdef L_shmget +/* Return an identifier for an shared memory segment of at least size SIZE + which is associated with KEY. */ +#ifdef __NR_shmget +_syscall3(int, shmget, key_t, key, size_t, size, int, shmflg) +#else +int shmget (key_t key, size_t size, int shmflg) +{ + return __syscall_ipc(IPCOP_shmget, key, size, shmflg, NULL, 0); +} +#endif +#endif diff --git a/libc/misc/sysvipc/shmat.c b/libc/misc/sysvipc/shmat.c new file mode 100644 index 0000000..d6cd22a --- /dev/null +++ b/libc/misc/sysvipc/shmat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmat +#include "shm.c" diff --git a/libc/misc/sysvipc/shmctl.c b/libc/misc/sysvipc/shmctl.c new file mode 100644 index 0000000..90fab5a --- /dev/null +++ b/libc/misc/sysvipc/shmctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmctl +#include "shm.c" diff --git a/libc/misc/sysvipc/shmdt.c b/libc/misc/sysvipc/shmdt.c new file mode 100644 index 0000000..0783341 --- /dev/null +++ b/libc/misc/sysvipc/shmdt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmdt +#include "shm.c" diff --git a/libc/misc/sysvipc/shmget.c b/libc/misc/sysvipc/shmget.c new file mode 100644 index 0000000..4778e36 --- /dev/null +++ b/libc/misc/sysvipc/shmget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmget +#include "shm.c" diff --git a/libc/misc/time/.indent.pro b/libc/misc/time/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/misc/time/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/misc/time/Makefile b/libc/misc/time/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/time/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/time/Makefile.in b/libc/misc/time/Makefile.in new file mode 100644 index 0000000..4193487 --- /dev/null +++ b/libc/misc/time/Makefile.in @@ -0,0 +1,41 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := adjtime.c +ifeq ($(UCLIBC_SUSV3_LEGACY),y) +CSRC += ftime.c +endif +# multi source time.c +CSRC += asctime.c asctime_r.c clock.c ctime.c ctime_r.c gmtime.c gmtime_r.c \ + localtime.c localtime_r.c mktime.c strftime.c strptime.c tzset.c \ + _time_t2tm.c __time_tm.c _time_mktime.c dysize.c timegm.c \ + _time_mktime_tzi.c _time_localtime_tzi.c +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += difftime.c +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += strftime_l.c strptime_l.c +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += wcsftime.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += wcsftime_l.c +endif +endif + +MISC_TIME_DIR := $(top_srcdir)libc/misc/time +MISC_TIME_OUT := $(top_builddir)libc/misc/time + +MISC_TIME_SRC := $(patsubst %.c,$(MISC_TIME_DIR)/%.c,$(CSRC)) +MISC_TIME_OBJ := $(patsubst %.c,$(MISC_TIME_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_TIME_OBJ) + +objclean-y += misc_time_clean + +misc_time_clean: + $(do_rm) $(addprefix $(MISC_TIME_OUT)/*., o os) diff --git a/libc/misc/time/__time_tm.c b/libc/misc/time/__time_tm.c new file mode 100644 index 0000000..59b7d8a --- /dev/null +++ b/libc/misc/time/__time_tm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___time_tm +#include "time.c" diff --git a/libc/misc/time/_time_localtime_tzi.c b/libc/misc/time/_time_localtime_tzi.c new file mode 100644 index 0000000..32728a4 --- /dev/null +++ b/libc/misc/time/_time_localtime_tzi.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_localtime_tzi +#include "time.c" diff --git a/libc/misc/time/_time_mktime.c b/libc/misc/time/_time_mktime.c new file mode 100644 index 0000000..1fd9200 --- /dev/null +++ b/libc/misc/time/_time_mktime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_mktime +#include "time.c" diff --git a/libc/misc/time/_time_mktime_tzi.c b/libc/misc/time/_time_mktime_tzi.c new file mode 100644 index 0000000..543893e --- /dev/null +++ b/libc/misc/time/_time_mktime_tzi.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_mktime_tzi +#include "time.c" diff --git a/libc/misc/time/_time_t2tm.c b/libc/misc/time/_time_t2tm.c new file mode 100644 index 0000000..903651f --- /dev/null +++ b/libc/misc/time/_time_t2tm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_t2tm +#include "time.c" diff --git a/libc/misc/time/adjtime.c b/libc/misc/time/adjtime.c new file mode 100644 index 0000000..cfa9433 --- /dev/null +++ b/libc/misc/time/adjtime.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(adjtimex) + +#define MAX_SEC (LONG_MAX / 1000000L - 2) +#define MIN_SEC (LONG_MIN / 1000000L + 2) + +#ifndef MOD_OFFSET +#define modes mode +#endif + +int +adjtime(const struct timeval * itv, struct timeval * otv) +{ + struct timex tntx; + + if (itv) + { + struct timeval tmp; + + /* We will do some check here. */ + tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L; + tmp.tv_usec = itv->tv_usec % 1000000L; + if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC) + { + __set_errno(EINVAL); + return -1; + } + tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L; + tntx.modes = ADJ_OFFSET_SINGLESHOT; + } + else + { + tntx.modes = 0; + } + if (adjtimex(&tntx) < 0) return -1; + if (otv) { + if (tntx.offset < 0) + { + otv->tv_usec = -(-tntx.offset % 1000000); + otv->tv_sec = -(-tntx.offset / 1000000); + } + else + { + otv->tv_usec = tntx.offset % 1000000; + otv->tv_sec = tntx.offset / 1000000; + } + } + return 0; +} diff --git a/libc/misc/time/asctime.c b/libc/misc/time/asctime.c new file mode 100644 index 0000000..d80c017 --- /dev/null +++ b/libc/misc/time/asctime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_asctime +#include "time.c" diff --git a/libc/misc/time/asctime_r.c b/libc/misc/time/asctime_r.c new file mode 100644 index 0000000..aec38b1 --- /dev/null +++ b/libc/misc/time/asctime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_asctime_r +#include "time.c" diff --git a/libc/misc/time/clock.c b/libc/misc/time/clock.c new file mode 100644 index 0000000..9cc4254 --- /dev/null +++ b/libc/misc/time/clock.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_clock +#include "time.c" diff --git a/libc/misc/time/ctime.c b/libc/misc/time/ctime.c new file mode 100644 index 0000000..4bd09a8 --- /dev/null +++ b/libc/misc/time/ctime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ctime +#include "time.c" diff --git a/libc/misc/time/ctime_r.c b/libc/misc/time/ctime_r.c new file mode 100644 index 0000000..c03f5c9 --- /dev/null +++ b/libc/misc/time/ctime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ctime_r +#include "time.c" diff --git a/libc/misc/time/difftime.c b/libc/misc/time/difftime.c new file mode 100644 index 0000000..4bcec2c --- /dev/null +++ b/libc/misc/time/difftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_difftime +#include "time.c" diff --git a/libc/misc/time/dysize.c b/libc/misc/time/dysize.c new file mode 100644 index 0000000..b1bf84b --- /dev/null +++ b/libc/misc/time/dysize.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_dysize +#include "time.c" diff --git a/libc/misc/time/ftime.c b/libc/misc/time/ftime.c new file mode 100644 index 0000000..49c137c --- /dev/null +++ b/libc/misc/time/ftime.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libc_hidden_proto(gettimeofday) + +int ftime(struct timeb *timebuf) +{ + struct timeval tv; + struct timezone tz; + + if (gettimeofday (&tv, &tz) < 0) + return -1; + + timebuf->time = tv.tv_sec; + timebuf->millitm = (tv.tv_usec + 999) / 1000; + timebuf->timezone = tz.tz_minuteswest; + timebuf->dstflag = tz.tz_dsttime; + return 0; +} diff --git a/libc/misc/time/gmtime.c b/libc/misc/time/gmtime.c new file mode 100644 index 0000000..24a512c --- /dev/null +++ b/libc/misc/time/gmtime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gmtime +#include "time.c" diff --git a/libc/misc/time/gmtime_r.c b/libc/misc/time/gmtime_r.c new file mode 100644 index 0000000..8677dd2 --- /dev/null +++ b/libc/misc/time/gmtime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gmtime_r +#include "time.c" diff --git a/libc/misc/time/localtime.c b/libc/misc/time/localtime.c new file mode 100644 index 0000000..e4bffbd --- /dev/null +++ b/libc/misc/time/localtime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localtime +#include "time.c" diff --git a/libc/misc/time/localtime_r.c b/libc/misc/time/localtime_r.c new file mode 100644 index 0000000..5351834 --- /dev/null +++ b/libc/misc/time/localtime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localtime_r +#include "time.c" diff --git a/libc/misc/time/mktime.c b/libc/misc/time/mktime.c new file mode 100644 index 0000000..2b2c8e4 --- /dev/null +++ b/libc/misc/time/mktime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mktime +#include "time.c" diff --git a/libc/misc/time/strftime.c b/libc/misc/time/strftime.c new file mode 100644 index 0000000..2eb827d --- /dev/null +++ b/libc/misc/time/strftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strftime +#include "time.c" diff --git a/libc/misc/time/strftime_l.c b/libc/misc/time/strftime_l.c new file mode 100644 index 0000000..e1d34ad --- /dev/null +++ b/libc/misc/time/strftime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strftime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/libc/misc/time/strptime.c b/libc/misc/time/strptime.c new file mode 100644 index 0000000..771633f --- /dev/null +++ b/libc/misc/time/strptime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strptime +#include "time.c" diff --git a/libc/misc/time/strptime_l.c b/libc/misc/time/strptime_l.c new file mode 100644 index 0000000..16ee7e1 --- /dev/null +++ b/libc/misc/time/strptime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strptime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c new file mode 100644 index 0000000..97fbad5 --- /dev/null +++ b/libc/misc/time/time.c @@ -0,0 +1,2454 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +/* June 15, 2002 Initial Notes: + * + * Note: It is assumed throught that time_t is either long or unsigned long. + * Similarly, clock_t is assumed to be long int. + * + * Warning: Assumptions are made about the layout of struct tm! It is + * assumed that the initial fields of struct tm are (in order): + * tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday + * + * Reached the inital goal of supporting the ANSI/ISO C99 time functions + * as well as SUSv3's strptime. All timezone info is obtained from the + * TZ env variable. + * + * Differences from glibc worth noting: + * + * Leap seconds are not considered here. + * + * glibc stores additional timezone info the struct tm, whereas we don't. + * + * Alternate digits and era handling are not currently implemented. + * The modifiers are accepted, and tested for validity with the following + * specifier, but are ignored otherwise. + * + * strftime does not implement glibc extension modifiers or widths for + * conversion specifiers. However it does implement the glibc + * extension specifiers %l, %k, and %s. It also recognizes %P, but + * treats it as a synonym for %p; i.e. doesn't convert to lower case. + * + * strptime implements the glibc extension specifiers. However, it follows + * SUSv3 in requiring at least one non-alphanumeric char between + * conversion specifiers. Also, strptime only sets struct tm fields + * for which format specifiers appear and does not try to infer other + * fields (such as wday) as glibc's version does. + * + * TODO - Since glibc's %l and %k can space-pad their output in strftime, + * it might be reasonable to eat whitespace first for those specifiers. + * This could be done by pushing " %I" and " %H" respectively so that + * leading whitespace is consumed. This is really only an issue if %l + * or %k occurs at the start of the format string. + * + * TODO - Implement getdate? tzfile? struct tm extensions? + * + * TODO - Rework _time_mktime to remove the dependency on long long. + */ + +/* Oct 28, 2002 + * + * Fixed allowed char check for std and dst TZ fields. + * + * Added several options concerned with timezone support. The names will + * probably change once Erik gets the new config system in place. + * + * Defining __TIME_TZ_FILE causes tzset() to attempt to read the TZ value + * from the file /etc/TZ if the TZ env variable isn't set. The file contents + * must be the intended value of TZ, followed by a newline. No other chars, + * spacing, etc is allowed. As an example, an easy way for me to init + * /etc/TZ appropriately would be: echo CST6CDT > /etc/TZ + * + * Defining __TIME_TZ_FILE_ONCE will cause all further accesses of /etc/TZ + * to be skipped once a legal value has been read. + * + * Defining __TIME_TZ_OPT_SPEED will cause a tzset() to keep a copy of the + * last TZ setting string and do a "fast out" if the current string is the + * same. + * + * Nov 21, 2002 Fix an error return case in _time_mktime. + * + * Nov 26, 2002 Fix bug in setting daylight and timezone when no (valid) TZ. + * Bug reported by Arne Bernin in regards to freeswan. + * + * July 27, 2003 Adjust the struct tm extension field support. + * Change __tm_zone back to a ptr and add the __tm_tzname[] buffer for + * __tm_zone to point to. This gets around complaints from g++. + * Who knows... it might even fix the PPC timezone init problem. + * + * July 29, 2003 Fix a bug in mktime behavior when tm_isdst was -1. + * Bug reported by "Sid Wade" in regards to busybox. + * + * NOTE: uClibc mktime behavior is different than glibc's when + * the struct tm has tm_isdst == -1 and also had fields outside of + * the normal ranges. + * + * Apparently, glibc examines (at least) tm_sec and guesses the app's + * intention of assuming increasing or decreasing time when entering an + * ambiguous time period at the dst<->st boundaries. + * + * The uClibc behavior is to always normalize the struct tm and then + * try to determing the dst setting. + * + * As long as tm_isdst != -1 or the time specifiec by struct tm is + * unambiguous (not falling in the dst<->st transition region) both + * uClibc and glibc should produce the same result for mktime. + * + * Oct 31, 2003 Kill the seperate __tm_zone and __tm_tzname[] and which + * doesn't work if you want the memcpy the struct. Sigh... I didn't + * think about that. So now, when the extensions are enabled, we + * malloc space when necessary and keep the timezone names in a linked + * list. + * + * Fix a dst-related bug which resulted in use of uninitialized data. + * + * Nov 15, 2003 I forgot to update the thread locking in the last dst fix. + * + * Dec 14, 2003 Fix some dst issues in _time_mktime(). + * Normalize the tm_isdst value to -1, 0, or 1. + * If no dst for this timezone, then reset tm_isdst to 0. + * + * May 7, 2004 + * Change clock() to allow wrapping. + * Add timegm() function. + * Make lookup_tzname() static (as it should have been). + * Have strftime() get timezone information from the passed struct + * for the %z and %Z conversions when using struct tm extensions. + * + * Jul 24, 2004 + * Fix 2 bugs in strftime related to glibc struct tm extensions. + * 1) Need to negate tm_gmtoff field value when used. (bug 336). + * 2) Deal with NULL ptr case for tm_zone field, which was causing + * segfaults in both the NIST/PCTS tests and the Python 2.4.1 + * self-test suite. + * NOTE: We set uninitialized timezone names to "???", and this + * differs (intentionally) from glibc's behavior. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif + +libc_hidden_proto(asctime) +libc_hidden_proto(asctime_r) +libc_hidden_proto(ctime) +libc_hidden_proto(localtime) +libc_hidden_proto(localtime_r) + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +/* libc_hidden_proto(sprintf) */ +libc_hidden_proto(open) +libc_hidden_proto(read) +libc_hidden_proto(close) +libc_hidden_proto(getenv) +libc_hidden_proto(tzset) +libc_hidden_proto(gettimeofday) +/* Experimentally off - libc_hidden_proto(strncasecmp) */ +libc_hidden_proto(strtol) +libc_hidden_proto(strtoul) +libc_hidden_proto(nl_langinfo) + +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Experimentally off - libc_hidden_proto(strncasecmp_l) */ +libc_hidden_proto(strtol_l) +libc_hidden_proto(strtoul_l) +libc_hidden_proto(nl_langinfo_l) +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +#ifndef __isleap +#define __isleap(y) ( !((y) % 4) && ( ((y) % 100) || !((y) % 400) ) ) +#endif + +#ifndef TZNAME_MAX +#define TZNAME_MAX _POSIX_TZNAME_MAX +#endif + +#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \ + defined(L__time_mktime) || defined(L__time_mktime_tzi) || \ + ((defined(L_strftime) || defined(L_strftime_l)) && \ + defined(__UCLIBC_HAS_XLOCALE__)) + +void _time_tzset(int use_old_rules) attribute_hidden; + +#ifndef L__time_mktime + + /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */ + +static const time_t new_rule_starts = 1167609600; + +#endif +#endif + +/**********************************************************************/ +/* The era code is currently unfinished. */ +/* #define ENABLE_ERA_CODE */ + +#define TZ_BUFLEN (2*TZNAME_MAX + 56) + +#ifdef __UCLIBC_HAS_TZ_FILE__ + +#include +#include "paths.h" +/* ":+hh:mm:ss+hh:mm:ss,Mmm.w.d/hh:mm:ss,Mmm.w.d/hh:mm:ss" + nul */ +/* 1 + 2*(1+TZNAME_MAX+1 + 9 + 7 + 9) + 1 = 2*TZNAME_MAX + 56 */ + +#else /* __UCLIBC_HAS_TZ_FILE__ */ + +/* Probably no longer needed. */ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ + +#endif /* __UCLIBC_HAS_TZ_FILE__ */ + +/**********************************************************************/ + +extern struct tm __time_tm attribute_hidden; + +typedef struct { + long gmt_offset; + long dst_offset; + short day; /* for J or normal */ + short week; + short month; + short rule_type; /* J, M, \0 */ + char tzname[TZNAME_MAX+1]; +} rule_struct; + +__UCLIBC_MUTEX_EXTERN(_time_tzlock); + +extern rule_struct _time_tzinfo[2] attribute_hidden; + +extern struct tm *_time_t2tm(const time_t *__restrict timer, + int offset, struct tm *__restrict result) attribute_hidden; + +extern time_t _time_mktime(struct tm *timeptr, int store_on_success) attribute_hidden; + +extern struct tm *__time_localtime_tzi(const time_t *__restrict timer, + struct tm *__restrict result, + rule_struct *tzi) attribute_hidden; + +extern time_t _time_mktime_tzi(struct tm *timeptr, int store_on_success, + rule_struct *tzi) attribute_hidden; + +/**********************************************************************/ +#ifdef L_asctime + +static char __time_str[26]; + +char *asctime(const struct tm *ptm) +{ + return asctime_r(ptm, __time_str); +} +libc_hidden_def(asctime) + +#endif +/**********************************************************************/ +#ifdef L_asctime_r + +/* Strictly speaking, this implementation isn't correct. ANSI/ISO specifies + * that the implementation of asctime() be equivalent to + * + * char *asctime(const struct tm *timeptr) + * { + * static char wday_name[7][3] = { + * "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + * }; + * static char mon_name[12][3] = { + * "Jan", "Feb", "Mar", "Apr", "May", "Jun", + * "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + * }; + * static char result[26]; + * + * sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", + * wday_name[timeptr->tm_wday], + * mon_name[timeptr->tm_mon], + * timeptr->tm_mday, timeptr->tm_hour, + * timeptr->tm_min, timeptr->tm_sec, + * 1900 + timeptr->tm_year); + * return result; + * } + * + * but the above is either inherently unsafe, or carries with it the implicit + * assumption that all fields of timeptr fall within their usual ranges, and + * that the tm_year value falls in the range [-2899,8099] to avoid overflowing + * the static buffer. + * + * If we take the implicit assumption as given, then the implementation below + * is still incorrect for tm_year values < -900, as there will be either + * 0-padding and/or a missing negative sign for the year conversion . But given + * the ususal use of asctime(), I think it isn't unreasonable to restrict correct + * operation to the domain of years between 1000 and 9999. + */ + +/* This is generally a good thing, but if you're _sure_ any data passed will be + * in range, you can #undef this. */ +#define SAFE_ASCTIME_R 1 + +static const unsigned char at_data[] = { + 'S', 'u', 'n', 'M', 'o', 'n', 'T', 'u', 'e', 'W', 'e', 'd', + 'T', 'h', 'u', 'F', 'r', 'i', 'S', 'a', 't', + + 'J', 'a', 'n', 'F', 'e', 'b', 'M', 'a', 'r', 'A', 'p', 'r', + 'M', 'a', 'y', 'J', 'u', 'n', 'J', 'u', 'l', 'A', 'u', 'g', + 'S', 'e', 'p', 'O', 'c', 't', 'N', 'o', 'v', 'D', 'e', 'c', + +#ifdef SAFE_ASCTIME_R + '?', '?', '?', +#endif + ' ', '?', '?', '?', + ' ', '0', + offsetof(struct tm, tm_mday), + ' ', '0', + offsetof(struct tm, tm_hour), + ':', '0', + offsetof(struct tm, tm_min), + ':', '0', + offsetof(struct tm, tm_sec), + ' ', '?', '?', '?', '?', '\n', 0 +}; + +char *asctime_r(register const struct tm *__restrict ptm, + register char *__restrict buffer) +{ + int tmp; + + assert(ptm); + assert(buffer); + +#ifdef SAFE_ASCTIME_R + memcpy(buffer, at_data + 3*(7 + 12), sizeof(at_data) - 3*(7 + 12)); + + if (((unsigned int)(ptm->tm_wday)) <= 6) { + memcpy(buffer, at_data + 3 * ptm->tm_wday, 3); + } + + if (((unsigned int)(ptm->tm_mon)) <= 11) { + memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3); + } +#else + assert(((unsigned int)(ptm->tm_wday)) <= 6); + assert(((unsigned int)(ptm->tm_mon)) <= 11); + + memcpy(buffer, at_data + 3*(7 + 12) - 3, sizeof(at_data) + 3 - 3*(7 + 12)); + + memcpy(buffer, at_data + 3 * ptm->tm_wday, 3); + memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3); +#endif + +#ifdef SAFE_ASCTIME_R + buffer += 19; + tmp = ptm->tm_year + 1900; + if (((unsigned int) tmp) < 10000) { + buffer += 4; + do { + *buffer = '0' + (tmp % 10); + tmp /= 10; + } while (*--buffer == '?'); + } +/* Not sure if we should even bother ... + } else { + __set_errno(EOVERFLOW); + return NULL; + } +*/ +#else /* SAFE_ASCTIME_R */ + buffer += 23; + tmp = ptm->tm_year + 1900; + assert( ((unsigned int) tmp) < 10000 ); +/* Not sure if we should even bother ... + if ( ((unsigned int) tmp) >= 10000 ) { + __set_errno(EOVERFLOW); + return NULL; + } +*/ + do { + *buffer = '0' + (tmp % 10); + tmp /= 10; + } while (*--buffer == '?'); +#endif /* SAFE_ASCTIME_R */ + + do { + --buffer; + tmp = *((int *)(((const char *) ptm) + (int) *buffer)); +#ifdef SAFE_ASCTIME_R + if (((unsigned int) tmp) >= 100) { /* Just check 2 digit non-neg. */ + buffer[-1] = *buffer = '?'; + } else +#else /* SAFE_ASCTIME_R */ + assert(((unsigned int) tmp) < 100); /* Just check 2 digit non-neg. */ +#endif /* SAFE_ASCTIME_R */ + { + *buffer = '0' + (tmp % 10); +#ifdef __BCC__ + buffer[-1] = '0' + (tmp/10); +#else /* __BCC__ */ + buffer[-1] += (tmp/10); +#endif /* __BCC__ */ + } + } while ((buffer -= 2)[-2] == '0'); + + if (*++buffer == '0') { /* Space-pad day of month. */ + *buffer = ' '; + } + + return buffer - 8; +} +libc_hidden_def(asctime_r) + +#endif +/**********************************************************************/ +#ifdef L_clock + +#include + +libc_hidden_proto(times) + +#ifndef __BCC__ +#if CLOCKS_PER_SEC != 1000000L +#error unexpected value for CLOCKS_PER_SEC! +#endif +#endif + +#ifdef __UCLIBC_CLK_TCK_CONST +# if __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC +# error __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC! +# elif __UCLIBC_CLK_TCK_CONST < 1 +# error __UCLIBC_CLK_TCK_CONST < 1! +# endif +#endif + +/* Note: SUSv3 notes + * + * On XSI-conformant systems, CLOCKS_PER_SEC is defined to be one million. + * + * The value returned by clock() may wrap around on some implementations. + * For example, on a machine with 32-bit values for clock_t, it wraps + * after 2147 seconds. + * + * This implies that we should bitwise and with LONG_MAX. + */ + +clock_t clock(void) +{ + struct tms xtms; + unsigned long t; + + times(&xtms); + + t = ((unsigned long) xtms.tms_utime) + xtms.tms_stime; + +#ifndef __UCLIBC_CLK_TCK_CONST + +# error __UCLIBC_CLK_TCK_CONST not defined! + +#elif ((CLOCKS_PER_SEC % __UCLIBC_CLK_TCK_CONST) == 0) + + /* CLOCKS_PER_SEC == k * __UCLIBC_CLK_TCK_CONST for some integer k >= 1. */ + return ((t * (CLOCKS_PER_SEC/__UCLIBC_CLK_TCK_CONST)) & LONG_MAX); + +#else + + /* Unlike the previous case, the scaling factor is not an integer. + * So when tms_utime, tms_stime, or their sum wraps, some of the + * "visible" bits in the return value are affected. Nothing we + * can really do about this though other than handle tms_utime and + * tms_stime seperately and then sum. But since that doesn't really + * buy us much, we don't bother. */ + + return ((((t / __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC) + + ((((t % __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC) + / __UCLIBC_CLK_TCK_CONST)) + ) & LONG_MAX); + +#endif +} + +#endif +/**********************************************************************/ +#ifdef L_ctime + +char *ctime(const time_t *t) +{ + /* ANSI/ISO/SUSv3 say that ctime is equivalent to the following. */ + return asctime(localtime(t)); +} +libc_hidden_def(ctime) +#endif +/**********************************************************************/ +#ifdef L_ctime_r + +char *ctime_r(const time_t *t, char *buf) +{ + struct tm xtm; + + return asctime_r(localtime_r(t, &xtm), buf); +} + +#endif +/**********************************************************************/ +#ifdef L_difftime + +#include + +#if FLT_RADIX != 2 +#error difftime implementation assumptions violated for you arch! +#endif + +double difftime(time_t time1, time_t time0) +{ +#if (LONG_MAX >> DBL_MANT_DIG) == 0 + + /* time_t fits in the mantissa of a double. */ + return (double)time1 - (double)time0; + +#elif ((LONG_MAX >> DBL_MANT_DIG) >> DBL_MANT_DIG) == 0 + + /* time_t can overflow the mantissa of a double. */ + time_t t1, t0, d; + + d = ((time_t) 1) << DBL_MANT_DIG; + t1 = time1 / d; + time1 -= (t1 * d); + t0 = time0 / d; + time0 -= (t0*d); + + /* Since FLT_RADIX==2 and d is a power of 2, the only possible + * rounding error in the expression below would occur from the + * addition. */ + return (((double) t1) - t0) * d + (((double) time1) - time0); + +#else +#error difftime needs special implementation on your arch. +#endif +} + +#endif +/**********************************************************************/ +#ifdef L_gmtime + +struct tm *gmtime(const time_t *timer) +{ + register struct tm *ptm = &__time_tm; + + _time_t2tm(timer, 0, ptm); /* Can return NULL... */ + + return ptm; +} + +#endif +/**********************************************************************/ +#ifdef L_gmtime_r + +struct tm *gmtime_r(const time_t *__restrict timer, + struct tm *__restrict result) +{ + return _time_t2tm(timer, 0, result); +} + +#endif +/**********************************************************************/ +#ifdef L_localtime + +struct tm *localtime(const time_t *timer) +{ + register struct tm *ptm = &__time_tm; + + /* In this implementation, tzset() is called by localtime_r(). */ + + localtime_r(timer, ptm); /* Can return NULL... */ + + return ptm; +} +libc_hidden_def(localtime) + +#endif +/**********************************************************************/ +#ifdef L_localtime_r + +struct tm *localtime_r(register const time_t *__restrict timer, + register struct tm *__restrict result) +{ + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + _time_tzset(*timer < new_rule_starts); + + __time_localtime_tzi(timer, result, _time_tzinfo); + + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return result; +} +libc_hidden_def(localtime_r) + +#endif +/**********************************************************************/ +#ifdef L__time_localtime_tzi + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +/* Experimentally off - libc_hidden_proto(strnlen) */ + +struct ll_tzname_item; + +typedef struct ll_tzname_item { + struct ll_tzname_item *next; + char tzname[TZNAME_MAX+1]; +} ll_tzname_item_t; + +static ll_tzname_item_t ll_tzname[] = { + { ll_tzname + 1, "UTC" }, /* Always 1st. */ + { NULL, "???" } /* Always 2nd. (invalid or out-of-memory) */ +}; + +static const char *lookup_tzname(const char *key) +{ + ll_tzname_item_t *p; + + for (p=ll_tzname ; p ; p=p->next) { + if (!strcmp(p->tzname, key)) { + return p->tzname; + } + } + + /* Hmm... a new name. */ + if (strnlen(key, TZNAME_MAX+1) < TZNAME_MAX+1) { /* Verify legal length */ + if ((p = malloc(sizeof(ll_tzname_item_t))) != NULL) { + /* Insert as 3rd item in the list. */ + p->next = ll_tzname[1].next; + ll_tzname[1].next = p; + strcpy(p->tzname, key); + return p->tzname; + } + } + + /* Either invalid or couldn't alloc. */ + return ll_tzname[1].tzname; +} + +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + +static const unsigned char day_cor[] = { /* non-leap */ + 31, 31, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38 +/* 0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7 */ +/* 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 */ +}; + +/* Note: timezone locking is done by localtime_r. */ + +static int tm_isdst(register const struct tm *__restrict ptm, + register rule_struct *r) +{ + long sec; + int i, isdst, isleap, day, day0, monlen, mday; + int oday = oday; /* ok to be uninitialized, shutting up compiler warning */ + + isdst = 0; + if (r[1].tzname[0] != 0) { + /* First, get the current seconds offset from the start of the year. + * Fields of ptm are assumed to be in their normal ranges. */ + sec = ptm->tm_sec + + 60 * (ptm->tm_min + + 60 * (long)(ptm->tm_hour + + 24 * ptm->tm_yday)); + /* Do some prep work. */ + i = (ptm->tm_year % 400) + 1900; /* Make sure we don't overflow. */ + isleap = __isleap(i); + --i; + day0 = (1 + + i /* Normal years increment 1 wday. */ + + (i/4) + - (i/100) + + (i/400) ) % 7; + i = 0; + do { + day = r->day; /* Common for 'J' and # case. */ + if (r->rule_type == 'J') { + if (!isleap || (day < (31+29))) { + --day; + } + } else if (r->rule_type == 'M') { + /* Find 0-based day number for 1st of the month. */ + day = 31*r->month - day_cor[r->month -1]; + if (isleap && (day >= 59)) { + ++day; + } + monlen = 31 + day_cor[r->month -1] - day_cor[r->month]; + if (isleap && (r->month > 1)) { + ++monlen; + } + /* Wweekday (0 is Sunday) of 1st of the month + * is (day0 + day) % 7. */ + if ((mday = r->day - ((day0 + day) % 7)) >= 0) { + mday -= 7; /* Back up into prev month since r->week>0. */ + } + if ((mday += 7 * r->week) >= monlen) { + mday -= 7; + } + /* So, 0-based day number is... */ + day += mday; + } + + if (i != 0) { + /* Adjust sec since dst->std change time is in dst. */ + sec += (r[-1].gmt_offset - r->gmt_offset); + if (oday > day) { + ++isdst; /* Year starts in dst. */ + } + } + oday = day; + + /* Now convert day to seconds and add offset and compare. */ + if (sec >= (day * 86400L) + r->dst_offset) { + ++isdst; + } + ++r; + } while (++i < 2); + } + + return (isdst & 1); +} + +struct tm attribute_hidden *__time_localtime_tzi(register const time_t *__restrict timer, + register struct tm *__restrict result, + rule_struct *tzi) +{ + time_t x[1]; + long offset; + int days, dst; + + dst = 0; + do { + days = -7; + offset = 604800L - tzi[dst].gmt_offset; + if (*timer > (LONG_MAX - 604800L)) { + days = -days; + offset = -offset; + } + *x = *timer + offset; + + _time_t2tm(x, days, result); + result->tm_isdst = dst; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +# ifdef __USE_BSD + result->tm_gmtoff = - tzi[dst].gmt_offset; + result->tm_zone = lookup_tzname(tzi[dst].tzname); +# else + result->__tm_gmtoff = - tzi[dst].gmt_offset; + result->__tm_zone = lookup_tzname(tzi[dst].tzname); +# endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + } while ((++dst < 2) + && ((result->tm_isdst = tm_isdst(result, tzi)) != 0)); + + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_mktime + +time_t mktime(struct tm *timeptr) +{ + return _time_mktime(timeptr, 1); +} + +/* Another name for `mktime'. */ +/* time_t timelocal(struct tm *tp) */ +strong_alias(mktime,timelocal) + +#endif +/**********************************************************************/ +#ifdef L_timegm +/* Like `mktime' but timeptr represents Universal Time, not local time. */ + +time_t timegm(struct tm *timeptr) +{ + rule_struct gmt_tzinfo[2]; + + memset(gmt_tzinfo, 0, sizeof(gmt_tzinfo)); + strcpy(gmt_tzinfo[0].tzname, "GMT"); /* Match glibc behavior here. */ + + return _time_mktime_tzi(timeptr, 1, gmt_tzinfo); +} + +#endif +/**********************************************************************/ +#if defined(L_strftime) || defined(L_strftime_l) + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +libc_hidden_proto(strftime) + +libc_hidden_proto(strftime_l) + +size_t strftime(char *__restrict s, size_t maxsize, + const char *__restrict format, + const struct tm *__restrict timeptr) +{ + return strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strftime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#define NO_E_MOD 0x80 +#define NO_O_MOD 0x40 + +#define ILLEGAL_SPEC 0x3f + +#define INT_SPEC 0x00 /* must be 0x00!! */ +#define STRING_SPEC 0x10 /* must be 0x10!! */ +#define CALC_SPEC 0x20 +#define STACKED_SPEC 0x30 + +#define MASK_SPEC 0x30 + +/* Compatibility: + * + * No alternate digit (%O?) handling. Always uses 0-9. + * Alternate locale format (%E?) handling is broken for nontrivial ERAs. + * glibc's %P is currently faked by %p. This means it doesn't do lower case. + * glibc's %k, %l, and %s are handled. + * glibc apparently allows (and ignores) extraneous 'E' and 'O' modifiers, + * while they are flagged as illegal conversions here. + */ + +/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */ +static const unsigned char spec[] = { + /* A */ 0x03 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* B */ 0x04 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* C */ 0x0a | INT_SPEC | NO_O_MOD, + /* D */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* F */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* G */ 0x03 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + /* H */ 0x0b | INT_SPEC | NO_E_MOD, + /* I */ 0x0c | INT_SPEC | NO_E_MOD, + /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* M */ 0x0d | INT_SPEC | NO_E_MOD, + /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* P */ 0x05 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc ; use %p */ + /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* R */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* S */ 0x0e | INT_SPEC | NO_E_MOD, + /* T */ 0x05 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* U */ 0x04 | CALC_SPEC | NO_E_MOD, + /* V */ 0x05 | CALC_SPEC | NO_E_MOD, + /* W */ 0x06 | CALC_SPEC | NO_E_MOD, + /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, + /* Y */ 0x0f | INT_SPEC | NO_O_MOD, + /* Z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + '?', /* 26 */ + '?', /* 27 */ + '?', /* 28 */ + '?', /* 29 */ + 0, /* 30 */ + 0, /* 31 */ + /* a */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, + /* d */ 0x00 | INT_SPEC | NO_E_MOD, + /* e */ 0x01 | INT_SPEC | NO_E_MOD, + /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* g */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* same as b */ + /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* j */ 0x08 | INT_SPEC | NO_E_MOD | NO_O_MOD, + /* k */ 0x03 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* l */ 0x04 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* m */ 0x05 | INT_SPEC | NO_E_MOD, + /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* p */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* s */ 0x07 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* t */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* u */ 0x07 | INT_SPEC | NO_E_MOD, + /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* w */ 0x02 | INT_SPEC | NO_E_MOD, + /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, + /* y */ 0x09 | INT_SPEC, + /* z */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + + + /* WARNING!!! These are dependent on the layout of struct tm!!! */ +#define FIELD_MAX (26+6+26) + 60 /* 61? */, 59, 23, 31, 11, 0 /* 9999 */, 6, 0 /* 365 */, + +#define TP_OFFSETS (FIELD_MAX+8) + 3, /* d */ + 3, /* e */ + 6, /* w */ + 2, /* k */ + 2, /* l */ + 4, /* m */ + 0, /* CURRENTLY UNUSED */ + /* NOTE: u,j,y order must be preserved as 6,7,5 seq is used in the code! */ +#define CALC_OFFSETS (TP_OFFSETS + 7) + 6, /* u */ + 7, /* j */ + 5, /* y */ + 5, /* C */ + 2, /* H */ + 2, /* I */ + 1, /* M */ + 0, /* S */ + 5, /* Y */ + 6, /* a */ + 4, /* b, h */ + 2, /* p */ + 6, /* A */ + 4, /* B */ + 2, /* P */ + +#define TP_CODES (TP_OFFSETS + 16 + 6) + 2 | 16, /* d */ + 2, /* e */ + 0 | 16, /* w */ + 2, /* k */ + 2 | 32 | 0, /* l */ + 2 | 16 | 1, /* m */ + 0, /* CURRENTLY UNUSED */ + 0 | 16 | 8 , /* u */ + 4 | 16 | 1, /* j */ + 2 | 128 | 32 | 16 , /* y */ + 2 | 128 | 64 | 32 | 16 , /* C */ + 2 | 16, /* H */ + 2 | 32 | 16 | 0, /* I */ + 2 | 16, /* M */ + 2 | 16, /* S */ + 6 | 16, /* Y */ + 2, /* a */ + 2, /* b, h */ + 2 | 64, /* p */ + 2, /* A */ + 2, /* B */ + 2 | 64, /* P */ + +#define STRINGS_NL_ITEM_START (TP_CODES + 16 + 6) + _NL_ITEM_INDEX(ABDAY_1), /* a */ + _NL_ITEM_INDEX(ABMON_1), /* b, h */ + _NL_ITEM_INDEX(AM_STR), /* p */ + _NL_ITEM_INDEX(DAY_1), /* A */ + _NL_ITEM_INDEX(MON_1), /* B */ + _NL_ITEM_INDEX(AM_STR), /* P -- wrong! need lower case */ + +#define STACKED_STRINGS_START (STRINGS_NL_ITEM_START+6) + 6, 7, 8, 16, 24, 29, /* 6 - offsets from offset-count to strings */ + '\n', 0, /* 2 */ + '\t', 0, /* 2 */ + '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ + '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ + '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ + '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */ + +#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 43) + _NL_ITEM_INDEX(D_T_FMT), /* c */ + _NL_ITEM_INDEX(D_FMT), /* x */ + _NL_ITEM_INDEX(T_FMT), /* X */ + _NL_ITEM_INDEX(T_FMT_AMPM), /* r */ +#ifdef ENABLE_ERA_CODE + _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ + _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ + _NL_ITEM_INDEX(ERA_T_FMT), /* EX */ +#endif +}; + +static int load_field(int k, const struct tm *__restrict timeptr) +{ + int r; + int r_max; + + r = ((int *) timeptr)[k]; + + r_max = spec[FIELD_MAX + k]; + + if (k == 7) { + r_max = 365; + } else if (k == 5) { + r += 1900; + r_max = 9999; + } + + if ((((unsigned int) r) > r_max) || ((k == 3) && !r)) { + r = -1; + } + + return r; +} + +#define MAX_PUSH 4 + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Check multibyte format string validity. +#endif + +libc_hidden_proto(__XL_NPP(strftime)) +size_t __XL_NPP(strftime)(char *__restrict s, size_t maxsize, + const char *__restrict format, + const struct tm *__restrict timeptr __LOCALE_PARAM ) +{ + long tzo; + register const char *p; + register const char *o; +#ifndef __UCLIBC_HAS_TM_EXTENSIONS__ + const rule_struct *rsp; +#endif + const char *stack[MAX_PUSH]; + size_t count; + size_t o_count; + int field_val, i, j, lvl; + int x[3]; /* wday, yday, year */ + int isofm, days; + char buf[__UIM_BUFLEN_LONG]; + unsigned char mod; + unsigned char code; + + /* We'll, let's get this out of the way. */ + _time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts); + + lvl = 0; + p = format; + count = maxsize; + +LOOP: + if (!count) { + return 0; + } + if (!*p) { + if (lvl == 0) { + *s = 0; /* nul-terminate */ + return maxsize - count; + } + p = stack[--lvl]; + goto LOOP; + } + + o_count = 1; + if ((*(o = p) == '%') && (*++p != '%')) { + o_count = 2; + mod = ILLEGAL_SPEC; + if ((*p == 'O') || (*p == 'E')) { /* modifier */ + mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD); + ++o_count; + ++p; + } + if ((((unsigned char)(((*p) | 0x20) - 'a')) >= 26) + || (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC) + ) { + if (!*p) { + --p; + --o_count; + } + goto OUTPUT; + } + code &= ILLEGAL_SPEC; /* modifiers are preserved in mod var. */ + + if ((code & MASK_SPEC) == STACKED_SPEC) { + if (lvl == MAX_PUSH) { + goto OUTPUT; /* Stack full so treat as illegal spec. */ + } + stack[lvl++] = ++p; + if ((code &= 0xf) < 8) { + p = ((const char *) spec) + STACKED_STRINGS_START + code; + p += *((unsigned char *)p); + goto LOOP; + } + p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START + + (code & 7); +#ifdef ENABLE_ERA_CODE + if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ + && (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(((unsigned char *)p)[4])) + __LOCALE_ARG + ))) + ) { + p = o; + goto LOOP; + } +#endif + p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(*((unsigned char *)p))) + __LOCALE_ARG + ); + goto LOOP; + } + + o = ((const char *) spec) + 26; /* set to "????" */ + if ((code & MASK_SPEC) == CALC_SPEC) { + + if (*p == 's') { + time_t t; + + /* Use a cast to silence the warning since *timeptr won't + * be changed. */ + if ((t = _time_mktime((struct tm *) timeptr, 0)) + == ((time_t) -1) + ) { + o_count = 1; + goto OUTPUT; + } +#ifdef TIME_T_IS_UNSIGNED + o = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) t, + 10, __UIM_DECIMAL); +#else + o = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) t, + -10, __UIM_DECIMAL); +#endif + o_count = sizeof(buf); + goto OUTPUT; + } else if (((*p) | 0x20) == 'z') { /* 'z' or 'Z' */ + + if (timeptr->tm_isdst < 0) { + /* SUSv3 specifies this behavior for 'z', but we'll also + * treat it as "no timezone info" for 'Z' too. */ + o_count = 0; + goto OUTPUT; + } + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +# ifdef __USE_BSD +# define RSP_TZNAME timeptr->tm_zone +# define RSP_GMT_OFFSET (-timeptr->tm_gmtoff) +# else +# define RSP_TZNAME timeptr->__tm_zone +# define RSP_GMT_OFFSET (-timeptr->__tm_gmtoff) +# endif + +#else + +#define RSP_TZNAME rsp->tzname +#define RSP_GMT_OFFSET rsp->gmt_offset + + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + rsp = _time_tzinfo; + if (timeptr->tm_isdst > 0) { + ++rsp; + } +#endif + + if (*p == 'Z') { + o = RSP_TZNAME; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + /* Sigh... blasted glibc extensions. Of course we can't + * count on the pointer being valid. Best we can do is + * handle NULL, which looks to be all that glibc does. + * At least that catches the memset() with 0 case. + * NOTE: We handle this case differently than glibc! + * It uses system timezone name (based on tm_isdst) in this + * case... although it always seems to use the embedded + * tm_gmtoff value. What we'll do instead is treat the + * timezone name as unknown/invalid and return "???". */ + if (!o) { + o = "???"; + } +#endif + assert(o != NULL); +#if 0 + if (!o) { /* PARANOIA */ + o = spec+30; /* empty string */ + } +#endif + o_count = SIZE_MAX; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + goto OUTPUT; +#endif + } else { /* z */ + *s = '+'; + if ((tzo = -RSP_GMT_OFFSET) < 0) { + tzo = -tzo; + *s = '-'; + } + ++s; + --count; + + i = tzo / 60; + field_val = ((i / 60) * 100) + (i % 60); + + i = 16 + 6; /* 0-fill, width = 4 */ + } +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +#else + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + if (*p == 'Z') { + goto OUTPUT; + } +#endif + } else { + /* TODO: don't need year for U, W */ + for (i=0 ; i < 3 ; i++) { + if ((x[i] = load_field(spec[CALC_OFFSETS+i],timeptr)) < 0) { + goto OUTPUT; + } + } + + i = 16 + 2; /* 0-fill, width = 2 */ + + if ((*p == 'U') || (*p == 'W')) { + field_val = ((x[1] - x[0]) + 7); + if (*p == 'W') { + ++field_val; + } + field_val /= 7; + if ((*p == 'W') && !x[0]) { + --field_val; + } + } else { /* ((*p == 'g') || (*p == 'G') || (*p == 'V')) */ + ISO_LOOP: + isofm = (((x[1] - x[0]) + 11) % 7) - 3; /* [-3,3] */ + + if (x[1] < isofm) { /* belongs to previous year */ + --x[2]; + x[1] += 365 + __isleap(x[2]); + goto ISO_LOOP; + } + + field_val = ((x[1] - isofm) / 7) + 1; /* week # */ + days = 365 + __isleap(x[2]); + isofm = ((isofm + 7*53 + 3 - days)) %7 + days - 3; /* next year */ + if (x[1] >= isofm) { /* next year */ + x[1] -= days; + ++x[2]; + goto ISO_LOOP; + } + + if (*p != 'V') { /* need year */ + field_val = x[2]; /* TODO: what if x[2] now 10000 ?? */ + if (*p == 'g') { + field_val %= 100; + } else { + i = 16 + 6; /* 0-fill, width = 4 */ + } + } + } + } + } else { + i = TP_OFFSETS + (code & 0x1f); + if ((field_val = load_field(spec[i],timeptr)) < 0) { + goto OUTPUT; + } + + i = spec[i+(TP_CODES - TP_OFFSETS)]; + + j = (i & 128) ? 100: 12; + if (i & 64) { + field_val /= j;; + } + if (i & 32) { + field_val %= j; + if (((i&128) + field_val) == 0) { /* mod 12? == 0 */ + field_val = j; /* set to 12 */ + } + } + field_val += (i & 1); + if ((i & 8) && !field_val) { + field_val += 7; + } + } + + if ((code & MASK_SPEC) == STRING_SPEC) { + o_count = SIZE_MAX; + field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)]; + o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, field_val) __LOCALE_ARG ); + } else { + o_count = ((i >> 1) & 3) + 1; + o = buf + o_count; + do { + *(char *)(--o) = '0' + (field_val % 10); + field_val /= 10; + } while (o > buf); + if (*buf == '0') { + *buf = ' ' + (i & 16); + } + } + } + +OUTPUT: + ++p; + while (o_count && count && *o) { + *s++ = *o++; + --o_count; + --count; + } + goto LOOP; +} +libc_hidden_def(__XL_NPP(strftime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#if defined(L_strptime) || defined(L_strptime_l) + +#define ISDIGIT(C) __isdigit_char((C)) + +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +libc_hidden_proto(strptime) + +libc_hidden_proto(strptime_l) + +char *strptime(const char *__restrict buf, const char *__restrict format, + struct tm *__restrict tm) +{ + return strptime_l(buf, format, tm, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strptime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* TODO: + * 1) %l and %k are space-padded, so "%l" by itself fails while " %l" succeeds. + * Both work for glibc. So, should we always strip spaces? + * 2) %Z + */ + +/* Notes: + * There are several differences between this strptime and glibc's strptime. + * 1) glibc strips leading space before numeric conversions. + * 2) glibc will read fields without whitespace in between. SUSv3 states + * that you must have whitespace between conversion operators. Besides, + * how do you know how long a number should be if there are leading 0s? + * 3) glibc attempts to compute some the struct tm fields based on the + * data retrieved; tm_wday in particular. I don't as I consider it + * another glibc attempt at mind-reading... + */ + +#define NO_E_MOD 0x80 +#define NO_O_MOD 0x40 + +#define ILLEGAL_SPEC 0x3f + +#define INT_SPEC 0x00 /* must be 0x00!! */ +#define STRING_SPEC 0x10 /* must be 0x10!! */ +#define CALC_SPEC 0x20 +#define STACKED_SPEC 0x30 + +#define MASK_SPEC 0x30 + +/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */ +static const unsigned char spec[] = { + /* A */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* B */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* C */ 0x08 | INT_SPEC | NO_O_MOD, + /* D */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* F */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* G */ 0x0f | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* H */ 0x06 | INT_SPEC | NO_E_MOD, + /* I */ 0x07 | INT_SPEC | NO_E_MOD, + /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* M */ 0x04 | INT_SPEC | NO_E_MOD, + /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* P */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* R */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* S */ 0x05 | INT_SPEC | NO_E_MOD, + /* T */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* U */ 0x0c | INT_SPEC | NO_E_MOD, + /* V */ 0x0d | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* W */ 0x0c | INT_SPEC | NO_E_MOD, + /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, + /* Y */ 0x0a | INT_SPEC | NO_O_MOD, + /* Z */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + + /* WARNING! This assumes orderings: + * AM,PM + * ABDAY_1-ABDAY-7,DAY_1-DAY_7 + * ABMON_1-ABMON_12,MON_1-MON12 + * Also, there are exactly 6 bytes between 'Z' and 'a'. + */ +#define STRINGS_NL_ITEM_START (26) + _NL_ITEM_INDEX(AM_STR), /* p (P) */ + _NL_ITEM_INDEX(ABMON_1), /* B, b */ + _NL_ITEM_INDEX(ABDAY_1), /* A, a */ + 2, + 24, + 14, + + /* a */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, + /* d */ 0x00 | INT_SPEC | NO_E_MOD, + /* e */ 0x00 | INT_SPEC | NO_E_MOD, + /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* g */ 0x0e | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* j */ 0x01 | INT_SPEC | NO_E_MOD | NO_O_MOD, + /* k */ 0x06 | INT_SPEC | NO_E_MOD, /* glibc */ + /* l */ 0x07 | INT_SPEC | NO_E_MOD, /* glibc */ + /* m */ 0x02 | INT_SPEC | NO_E_MOD, + /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* p */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* s */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* t */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* u */ 0x0b | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* w */ 0x03 | INT_SPEC | NO_E_MOD, + /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, + /* y */ 0x09 | INT_SPEC, + /* z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + +#define INT_FIELD_START (26+6+26) + /* (field #) << 3 + lower bound (0|1) + correction 0:none, 2:-1, 4:-1900 + * followed by upper bound prior to correction with 1=>366 and 2=>9999. */ + /* d, e */ (3 << 3) + 1 + 0, 31, + /* j */ (7 << 3) + 1 + 2, /* 366 */ 1, + /* m */ (4 << 3) + 1 + 2, 12, + /* w */ (6 << 3) + 0 + 0, 6, + /* M */ (1 << 3) + 0 + 0, 59, + /* S */ 0 + 0 + 0, 60, + /* H (k) */ (2 << 3) + 0 + 0, 23, + /* I (l) */ (9 << 3) + 1 + 0, 12, /* goes with 8 -- am/pm */ + /* C */ (10<< 3) + 0 + 0, 99, + /* y */ (11<< 3) + 0 + 0, 99, + /* Y */ (5 << 3) + 0 + 4, /* 9999 */ 2, + /* u */ (6 << 3) + 1 + 0, 7, + /* The following are processed and range-checked, but ignored otherwise. */ + /* U, W */ (12<< 3) + 0 + 0, 53, + /* V */ (12<< 3) + 1 + 0, 53, + /* g */ (12<< 3) + 0 + 0, 99, + /* G */ (12<< 3) + 0 /*+ 4*/, /* 9999 */ 2, /* Note: -1 or 10000? */ + +#define STACKED_STRINGS_START (INT_FIELD_START+32) + 5, 6, 14, 22, 27, /* 5 - offsets from offset-count to strings */ + ' ', 0, /* 2 - %n or %t */ + '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ + '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ + '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ + '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */ + +#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 40) + _NL_ITEM_INDEX(D_T_FMT), /* c */ + _NL_ITEM_INDEX(D_FMT), /* x */ + _NL_ITEM_INDEX(T_FMT), /* X */ + _NL_ITEM_INDEX(T_FMT_AMPM), /* r */ +#ifdef ENABLE_ERA_CODE + _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ + _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ + _NL_ITEM_INDEX(ERA_T_FMT), /* EX */ +#endif +}; + +#define MAX_PUSH 4 + +libc_hidden_proto(__XL_NPP(strptime)) +char *__XL_NPP(strptime)(const char *__restrict buf, const char *__restrict format, + struct tm *__restrict tm __LOCALE_PARAM) +{ + register const char *p; + char *o; + const char *stack[MAX_PUSH]; + int i, j, lvl; + int fields[13]; + unsigned char mod; + unsigned char code; + + i = 0; + do { + fields[i] = INT_MIN; + } while (++i < 13); + + lvl = 0; + p = format; + +LOOP: + if (!*p) { + if (lvl == 0) { /* Done. */ + if (fields[6] == 7) { /* Cleanup for %u here since just once. */ + fields[6] = 0; /* Don't use mod in case unset. */ + } + + i = 0; + do { /* Store the values into tm. */ + if (fields[i] != INT_MIN) { + ((int *) tm)[i] = fields[i]; + } + } while (++i < 8); + + return (char *) buf; /* Success. */ + } + p = stack[--lvl]; + goto LOOP; + } + + if ((*p == '%') && (*++p != '%')) { + mod = ILLEGAL_SPEC; + if ((*p == 'O') || (*p == 'E')) { /* Modifier? */ + mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD); + ++p; + } + + if (!*p + || (((unsigned char)(((*p) | 0x20) - 'a')) >= 26) + || (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC) + ) { + return NULL; /* Illegal spec. */ + } + + if ((code & MASK_SPEC) == STACKED_SPEC) { + if (lvl == MAX_PUSH) { + return NULL; /* Stack full so treat as illegal spec. */ + } + stack[lvl++] = ++p; + if ((code &= 0xf) < 8) { + p = ((const char *) spec) + STACKED_STRINGS_START + code; + p += *((unsigned char *)p); + goto LOOP; + } + + p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START + + (code & 7); +#ifdef ENABLE_ERA_CODE + if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ + && (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(((unsigned char *)p)[4])) + __LOCALE_ARG + ))) + ) { + p = o; + goto LOOP; + } +#endif + p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(*((unsigned char *)p))) + __LOCALE_ARG ); + goto LOOP; + } + + ++p; + + if ((code & MASK_SPEC) == STRING_SPEC) { + code &= 0xf; + j = spec[STRINGS_NL_ITEM_START + 3 + code]; + i = _NL_ITEM(LC_TIME, spec[STRINGS_NL_ITEM_START + code]); + /* Go backwards to check full names before abreviations. */ + do { + --j; + o = __XL_NPP(nl_langinfo)(i+j __LOCALE_ARG); + if (!__XL_NPP(strncasecmp)(buf,o,strlen(o) __LOCALE_ARG) && *o) { + do { /* Found a match. */ + ++buf; + } while (*++o); + if (!code) { /* am/pm */ + fields[8] = j * 12; + if (fields[9] >= 0) { /* We have a previous %I or %l. */ + fields[2] = fields[9] + fields[8]; + } + } else { /* day (4) or month (6) */ + fields[2 + (code << 1)] + = j % (spec[STRINGS_NL_ITEM_START + 3 + code] >> 1); + } + goto LOOP; + } + } while (j); + return NULL; /* Failed to match. */ + } + + if ((code & MASK_SPEC) == CALC_SPEC) { + if ((code &= 0xf) < 1) { /* s or z*/ + time_t t; + + o = (char *) buf; + i = errno; + __set_errno(0); + if (!ISSPACE(*buf)) { /* Signal an error if whitespace. */ +#ifdef TIME_T_IS_UNSIGNED + t = __XL_NPP(strtoul)(buf, &o, 10 __LOCALE_ARG); +#else + t = __XL_NPP(strtol)(buf, &o, 10 __LOCALE_ARG); +#endif + } + if ((o == buf) || errno) { /* Not a number or overflow. */ + return NULL; + } + __set_errno(i); /* Restore errno. */ + buf = o; + + if (!code) { /* s */ + localtime_r(&t, tm); /* TODO: check for failure? */ + i = 0; + do { /* Now copy values from tm to fields. */ + fields[i] = ((int *) tm)[i]; + } while (++i < 8); + } + } + /* TODO: glibc treats %Z as a nop. For now, do the same. */ + goto LOOP; + } + + assert((code & MASK_SPEC) == INT_SPEC); + { + register const unsigned char *x; + code &= 0xf; + x = spec + INT_FIELD_START + (code << 1); + if ((j = x[1]) < 3) { /* upper bound (inclusive) */ + j = ((j==1) ? 366 : 9999); + } + i = -1; + while (ISDIGIT(*buf)) { + if (i < 0) { + i = 0; + } + if ((i = 10*i + (*buf - '0')) > j) { /* Overflow. */ + return NULL; + } + ++buf; + } + if (i < (*x & 1)) { /* This catches no-digit case too. */ + return NULL; + } + if (*x & 2) { + --i; + } + if (*x & 4) { + i -= 1900; + } + + if (*x == (9 << 3) + 1 + 0) { /* %I or %l */ + if (i == 12) { + i = 0; + } + if (fields[8] >= 0) { /* We have a previous %p or %P. */ + fields[2] = i + fields[8]; + } + } + + fields[(*x) >> 3] = i; + + if (((unsigned char)(*x - (10<< 3) + 0 + 0)) <= 8) { /* %C or %y */ + if ((j = fields[10]) < 0) { /* No %C, so i must be %y data. */ + if (i <= 68) { /* Map [0-68] to 2000+i */ + i += 100; + } + } else { /* Have %C data, but what about %y? */ + if ((i = fields[11]) < 0) { /* No %y data. */ + i = 0; /* Treat %y val as 0 following glibc's example. */ + } + i += 100*(j - 19); + } + fields[5] = i; + } + } + goto LOOP; + } else if (ISSPACE(*p)) { + ++p; + while (ISSPACE(*buf)) { + ++buf; + } + goto LOOP; + } else if (*buf++ == *p++) { + goto LOOP; + } + return NULL; +} +libc_hidden_def(__XL_NPP(strptime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L_time + +#ifndef __BCC__ +#error The uClibc version of time is in sysdeps/linux/common. +#endif + +time_t time(register time_t *tloc) +{ + struct timeval tv; + register struct timeval *p = &tv; + + gettimeofday(p, NULL); /* This should never fail... */ + + if (tloc) { + *tloc = p->tv_sec; + } + + return p->tv_sec; +} + +#endif +/**********************************************************************/ +#ifdef L_tzset + +static const char vals[] = { + 'T', 'Z', 0, /* 3 */ + 'U', 'T', 'C', 0, /* 4 */ + 25, 60, 60, 1, /* 4 */ + '.', 1, /* M */ + 5, '.', 1, + 6, 0, 0, /* Note: overloaded for non-M non-J case... */ + 0, 1, 0, /* J */ + ',', 'M', '4', '.', '1', '.', '0', + ',', 'M', '1', '0', '.', '5', '.', '0', 0, + ',', 'M', '3', '.', '2', '.', '0', + ',', 'M', '1', '1', '.', '1', '.', '0', 0 +}; + +#define TZ vals +#define UTC (vals + 3) +#define RANGE (vals + 7) +#define RULE (vals + 11 - 1) +#define DEFAULT_RULES (vals + 22) +#define DEFAULT_2007_RULES (vals + 38) + +/* Initialize to UTC. */ +int daylight = 0; +long timezone = 0; +char *tzname[2] = { (char *) UTC, (char *) (UTC-1) }; + +__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +rule_struct _time_tzinfo[2]; + +static const char *getoffset(register const char *e, long *pn) +{ + register const char *s = RANGE-1; + long n; + int f; + + n = 0; + f = -1; + do { + ++s; + if (__isdigit_char(*e)) { + f = *e++ - '0'; + } + if (__isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + } + if (((unsigned int)f) >= *s) { + return NULL; + } + n = (*s) * n + f; + f = 0; + if (*e == ':') { + ++e; + --f; + } + } while (*s > 1); + + *pn = n; + return e; +} + +static const char *getnumber(register const char *e, int *pn) +{ +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *n = (const char *) 3; + int f; + + f = 0; + while (n && __isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + --n; + } + + *pn = f; + return (n == (const char *) 3) ? NULL : e; +#else /* __BCC__ */ + int n, f; + + n = 3; + f = 0; + while (n && __isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + --n; + } + + *pn = f; + return (n == 3) ? NULL : e; +#endif /* __BCC__ */ +} + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we preserve errno from open/read/close errors re TZ file? +#endif + +#ifdef __UCLIBC_HAS_TZ_FILE__ + +#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +static smallint TZ_file_read; /* Let BSS initialization set this to 0. */ +#endif /* __UCLIBC_HAS_TZ_FILE_READ_MANY__ */ + +static char *read_TZ_file(char *buf) +{ + int fd; + ssize_t r; + size_t todo; + char *p = NULL; + + if ((fd = open(__UCLIBC_TZ_FILE_PATH__, O_RDONLY)) >= 0) { + todo = TZ_BUFLEN; + p = buf; + do { + if ((r = read(fd, p, todo)) < 0) { + goto ERROR; + } + if (r == 0) { + break; + } + p += r; + todo -= r; + } while (todo); + + if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline. */ + p[-1] = 0; + p = buf; +#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__ + TZ_file_read = 1; +#endif /* __UCLIBC_HAS_TZ_FILE_READ_MANY__ */ + } else { +ERROR: + p = NULL; + } + close(fd); + } + return p; +} + +#endif /* __UCLIBC_HAS_TZ_FILE__ */ + +#ifndef __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(isascii) +#endif + +void tzset(void) +{ + _time_tzset((time(NULL)) < new_rule_starts); +} + +void _time_tzset(int use_old_rules) +{ + register const char *e; + register char *s; + long off = 0; + short *p; + rule_struct new_rules[2]; + int n, count, f; + char c; +#ifdef __UCLIBC_HAS_TZ_FILE__ + char buf[TZ_BUFLEN]; +#endif /* __UCLIBC_HAS_TZ_FILE__ */ +#ifdef __UCLIBC_HAS_TZ_CACHING__ + static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */ +#endif /* __UCLIBC_HAS_TZ_CACHING__ */ + + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + e = getenv(TZ); /* TZ env var always takes precedence. */ + +#if defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__) + /* Put this inside the lock to prevent the possiblity of two different + * timezones being used in a threaded app. */ + + if (e != NULL) { + TZ_file_read = 0; /* Reset if the TZ env var is set. */ + } else if (TZ_file_read) { + goto FAST_DONE; + } +#endif /* defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__) */ + + /* Warning!!! Since uClibc doesn't do lib locking, the following is + * potentially unsafe in a multi-threaded program since it is remotely + * possible that another thread could call setenv() for TZ and overwrite + * the string being parsed. So, don't do that... */ + + if ((!e /* TZ env var not set... */ +#ifdef __UCLIBC_HAS_TZ_FILE__ + && !(e = read_TZ_file(buf)) /* and no file or invalid file */ +#endif /* __UCLIBC_HAS_TZ_FILE__ */ + ) || !*e) { /* or set to empty string. */ +ILLEGAL: /* TODO: Clean up the following... */ +#ifdef __UCLIBC_HAS_TZ_CACHING__ + *oldval = 0; /* Set oldval to an empty string. */ +#endif /* __UCLIBC_HAS_TZ_CACHING__ */ + memset(_time_tzinfo, 0, 2*sizeof(rule_struct)); + strcpy(_time_tzinfo[0].tzname, UTC); + goto DONE; + } + + if (*e == ':') { /* Ignore leading ':'. */ + ++e; + } + +#ifdef __UCLIBC_HAS_TZ_CACHING__ + if (strcmp(e, oldval) == 0) { /* Same string as last time... */ + goto FAST_DONE; /* So nothing to do. */ + } + /* Make a copy of the TZ env string. It won't be nul-terminated if + * it is too long, but it that case it will be illegal and will be reset + * to the empty string anyway. */ + strncpy(oldval, e, TZ_BUFLEN); +#endif /* __UCLIBC_HAS_TZ_CACHING__ */ + + count = 0; + new_rules[1].tzname[0] = 0; +LOOP: + /* Get std or dst name. */ + c = 0; + if (*e == '<') { + ++e; + c = '>'; + } + + s = new_rules[count].tzname; + n = 0; + while (*e + && isascii(*e) /* SUSv3 requires char in portable char set. */ + && (isalpha(*e) + || (c && (isalnum(*e) || (*e == '+') || (*e == '-')))) + ) { + *s++ = *e++; + if (++n > TZNAME_MAX) { + goto ILLEGAL; + } + } + *s = 0; + + if ((n < 3) /* Check for minimum length. */ + || (c && (*e++ != c)) /* Match any quoting '<'. */ + ) { + goto ILLEGAL; + } + + /* Get offset */ + s = (char *) e; + if ((*e != '-') && (*e != '+')) { + if (count && !__isdigit_char(*e)) { + off -= 3600; /* Default to 1 hour ahead of std. */ + goto SKIP_OFFSET; + } + --e; + } + + ++e; + if (!(e = getoffset(e, &off))) { + goto ILLEGAL; + } + + if (*s == '-') { + off = -off; /* Save off in case needed for dst default. */ + } +SKIP_OFFSET: + new_rules[count].gmt_offset = off; + + if (!count) { + new_rules[1].gmt_offset = off; /* Shouldn't be needed... */ + if (*e) { + ++count; + goto LOOP; + } + } else { /* OK, we have dst, so get some rules. */ + count = 0; + if (!*e) { /* No rules so default to US rules. */ + e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES; +#ifdef DEBUG_TZSET + if (e == DEFAULT_RULES) + printf("tzset: Using old rules.\n"); + else if (e == DEFAULT_2007_RULES) + printf("tzset: Using new rules\n"); + else + printf("tzset: Using undefined rules\n"); +#endif /* DEBUG_TZSET */ + } + + do { + if (*e++ != ',') { + goto ILLEGAL; + } + + n = 365; + s = (char *) RULE; + if ((c = *e++) == 'M') { + n = 12; + } else if (c == 'J') { + s += 8; + } else { + --e; + c = 0; + s += 6; + } + + *(p = &new_rules[count].rule_type) = c; + if (c != 'M') { + p -= 2; + } + + do { + ++s; + if (!(e = getnumber(e, &f)) + || (((unsigned int)(f - s[1])) > n) + || (*s && (*e++ != *s)) + ) { + goto ILLEGAL; + } + *--p = f; + } while ((n = *(s += 2)) > 0); + + off = 2 * 60 * 60; /* Default to 2:00:00 */ + if (*e == '/') { + ++e; + if (!(e = getoffset(e, &off))) { + goto ILLEGAL; + } + } + new_rules[count].dst_offset = off; + } while (++count < 2); + + if (*e) { + goto ILLEGAL; + } + } + + memcpy(_time_tzinfo, new_rules, sizeof(new_rules)); +DONE: + tzname[0] = _time_tzinfo[0].tzname; + tzname[1] = _time_tzinfo[1].tzname; + daylight = !!_time_tzinfo[1].tzname[0]; + timezone = _time_tzinfo[0].gmt_offset; + +#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__) +FAST_DONE: +#endif + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); +} +libc_hidden_def(tzset) +#endif +/**********************************************************************/ +/* #ifdef L_utime */ + +/* utime is a syscall in both linux and elks. */ +/* int utime(const char *path, const struct utimbuf *times) */ + +/* #endif */ +/**********************************************************************/ +/* Non-SUSv3 */ +/**********************************************************************/ +#ifdef L_utimes + +#ifndef __BCC__ +#error The uClibc version of utimes is in sysdeps/linux/common. +#endif + +#include + +int utimes(const char *filename, register const struct timeval *tvp) +{ + register struct utimbuf *p = NULL; + struct utimbuf utb; + + if (tvp) { + p = &utb; + p->actime = tvp[0].tv_sec; + p->modtime = tvp[1].tv_sec; + } + return utime(filename, p); +} + +#endif +/**********************************************************************/ +#ifdef L__time_t2tm + +static const uint16_t _vals[] = { + 60, 60, 24, 7 /* special */, 36524, 1461, 365, 0 +}; + +static const unsigned char days[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ + 29, +}; + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +static const char utc_string[] = "UTC"; +#endif + +/* Notes: + * If time_t is 32 bits, then no overflow is possible. + * It time_t is > 32 bits, this needs to be adjusted to deal with overflow. + */ + +/* Note: offset is the correction in _days_ to *timer! */ + +struct tm attribute_hidden *_time_t2tm(const time_t *__restrict timer, + int offset, struct tm *__restrict result) +{ + register int *p; + time_t t1, t, v; + int wday = wday; /* ok to be uninitialized, shutting up warning */ + + { + register const uint16_t *vp; + t = *timer; + p = (int *) result; + p[7] = 0; + vp = _vals; + do { + if ((v = *vp) == 7) { + /* Overflow checking, assuming time_t is long int... */ +#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L) +#if (INT_MAX == 2147483647L) && (LONG_MAX == 9223372036854775807L) + /* Valid range for t is [-784223472856L, 784223421720L]. + * Outside of this range, the tm_year field will overflow. */ + if (((unsigned long)(t + offset- -784223472856L)) + > (784223421720L - -784223472856L) + ) { + return NULL; + } +#else +#error overflow conditions unknown +#endif +#endif + + /* We have days since the epoch, so caluclate the weekday. */ +#if defined(__BCC__) && TIME_T_IS_UNSIGNED + wday = (t + 4) % (*vp); /* t is unsigned */ +#else + wday = ((int)((t % (*vp)) + 11)) % ((int)(*vp)); /* help bcc */ +#endif + /* Set divisor to days in 400 years. Be kind to bcc... */ + v = ((time_t)(vp[1])) << 2; + ++v; + /* Change to days since 1/1/1601 so that for 32 bit time_t + * values, we'll have t >= 0. This should be changed for + * archs with larger time_t types. + * Also, correct for offset since a multiple of 7. */ + + /* TODO: Does this still work on archs with time_t > 32 bits? */ + t += (135140L - 366) + offset; /* 146097 - (365*30 + 7) -366 */ + } +#if defined(__BCC__) && TIME_T_IS_UNSIGNED + t -= ((t1 = t / v) * v); +#else + if ((t -= ((t1 = t / v) * v)) < 0) { + t += v; + --t1; + } +#endif + + if ((*vp == 7) && (t == v-1)) { + --t; /* Correct for 400th year leap case */ + ++p[4]; /* Stash the extra day... */ + } + +#if defined(__BCC__) && 0 + *p = t1; + if (v <= 60) { + *p = t; + t = t1; + } + ++p; +#else + if (v <= 60) { + *p++ = t; + t = t1; + } else { + *p++ = t1; + } +#endif + } while (*++vp); + } + + if (p[-1] == 4) { + --p[-1]; + t = 365; + } + + + *p += ((int) t); /* result[7] .. tm_yday */ + + p -= 2; /* at result[5] */ + +#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L) + /* Protect against overflow. TODO: Unecessary if int arith wraps? */ + *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + (p[1] - 299); /* tm_year */ +#else + *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + p[1] - 299; /* tm_year */ +#endif + + p[1] = wday; /* result[6] .. tm_wday */ + + { + register const unsigned char *d = days; + + wday = 1900 + *p; + if (__isleap(wday)) { + d += 11; + } + + wday = p[2] + 1; /* result[7] .. tm_yday */ + *--p = 0; /* at result[4] .. tm_mon */ + while (wday > *d) { + wday -= *d; + if (*d == 29) { + d -= 11; /* Backup to non-leap Feb. */ + } + ++d; + ++*p; /* Increment tm_mon. */ + } + p[-1] = wday; /* result[3] .. tm_mday */ + } + /* TODO -- should this be 0? */ + p[4] = 0; /* result[8] .. tm_isdst */ +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +# ifdef __USE_BSD + result->tm_gmtoff = 0; + result->tm_zone = utc_string; +# else + result->__tm_gmtoff = 0; + result->__tm_zone = utc_string; +# endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + + return result; +} + +#endif +/**********************************************************************/ +#ifdef L___time_tm + +struct tm __time_tm; /* Global shared by gmtime() and localtime(). */ + +#endif +/**********************************************************************/ +#ifdef L__time_mktime + +time_t attribute_hidden _time_mktime(struct tm *timeptr, int store_on_success) +{ + time_t t; + + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo); + + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return t; +} + +#endif +/**********************************************************************/ +#ifdef L__time_mktime_tzi + +static const unsigned char __vals[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ + 29, +}; + +time_t attribute_hidden _time_mktime_tzi(struct tm *timeptr, int store_on_success, + rule_struct *tzi) +{ +#ifdef __BCC__ + long days, secs; +#else + long long secs; +#endif + time_t t; + struct tm x; + /* 0:sec 1:min 2:hour 3:mday 4:mon 5:year 6:wday 7:yday 8:isdst */ + register int *p = (int *) &x; + register const unsigned char *s; + int d, default_dst; + + memcpy(p, timeptr, sizeof(struct tm)); + + if (!tzi[1].tzname[0]) { /* No dst in this timezone, */ + p[8] = 0; /* so set tm_isdst to 0. */ + } + + default_dst = 0; + if (p[8]) { /* Either dst or unknown? */ + default_dst = 1; /* Assume advancing (even if unknown). */ + p[8] = ((p[8] > 0) ? 1 : -1); /* Normalize so abs() <= 1. */ + } + + d = 400; + p[5] = (p[5] - ((p[6] = p[5]/d) * d)) + (p[7] = p[4]/12); + if ((p[4] -= 12 * p[7]) < 0) { + p[4] += 12; + --p[5]; + } + + s = __vals; + d = (p[5] += 1900); /* Correct year. Now between 1900 and 2300. */ + if (__isleap(d)) { + s += 11; + } + + p[7] = 0; + d = p[4]; + while (d) { + p[7] += *s; + if (*s == 29) { + s -= 11; /* Backup to non-leap Feb. */ + } + ++s; + --d; + } + + _time_tzset (x.tm_year < 2007); /* tm_year was expanded above */ + +#ifdef __BCC__ + d = p[5] - 1; + days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]); + secs = p[0] + 60*( p[1] + 60*((long)(p[2])) ) + + tzi[default_dst].gmt_offset; +DST_CORRECT: + if (secs < 0) { + secs += 120009600L; + days -= 1389; + } + if ( ((unsigned long)(days + secs/86400L)) > 49710L) { + t = ((time_t)(-1)); + goto DONE; + } + secs += (days * 86400L); +#else + d = p[5] - 1; + d = -719163L + d*365 + (d/4) - (d/100) + (d/400); + secs = p[0] + + tzi[default_dst].gmt_offset + + 60*( p[1] + + 60*(p[2] + + 24*(((146073L * ((long long)(p[6])) + d) + + p[3]) + p[7]))); + +DST_CORRECT: + if (((unsigned long long)(secs - LONG_MIN)) + > (((unsigned long long)LONG_MAX) - LONG_MIN) + ) { + t = ((time_t)(-1)); + goto DONE; + } +#endif + + d = ((struct tm *)p)->tm_isdst; + t = secs; + + __time_localtime_tzi(&t, (struct tm *)p, tzi); + + if (t == ((time_t)(-1))) { /* Remember, time_t can be unsigned. */ + goto DONE; + } + + if ((d < 0) && (((struct tm *)p)->tm_isdst != default_dst)) { +#ifdef __BCC__ + secs -= (days * 86400L); +#endif + secs += (tzi[1-default_dst].gmt_offset + - tzi[default_dst].gmt_offset); + goto DST_CORRECT; + } + + + if (store_on_success) { + memcpy(timeptr, p, sizeof(struct tm)); + } + + +DONE: + return t; +} + +#endif +/**********************************************************************/ +#if defined(L_wcsftime) || defined(L_wcsftime_l) + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +libc_hidden_proto(wcsftime) + +libc_hidden_proto(wcsftime_l) + +size_t wcsftime(wchar_t *__restrict s, size_t maxsize, + const wchar_t *__restrict format, + const struct tm *__restrict timeptr) +{ + return wcsftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); +} +libc_hidden_def(wcsftime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +libc_hidden_proto(__XL_NPP(wcsftime)) +size_t __XL_NPP(wcsftime)(wchar_t *__restrict s, size_t maxsize, + const wchar_t *__restrict format, + const struct tm *__restrict timeptr __LOCALE_PARAM ) +{ +#warning wcsftime always fails + return 0; /* always fail */ +} +libc_hidden_def(__XL_NPP(wcsftime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L_dysize +/* Return the number of days in YEAR. */ + +int dysize(int year) +{ + return __isleap(year) ? 366 : 365; +} + +#endif +/**********************************************************************/ diff --git a/libc/misc/time/timegm.c b/libc/misc/time/timegm.c new file mode 100644 index 0000000..ae2fc7d --- /dev/null +++ b/libc/misc/time/timegm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_timegm +#include "time.c" diff --git a/libc/misc/time/tzset.c b/libc/misc/time/tzset.c new file mode 100644 index 0000000..e5607a5 --- /dev/null +++ b/libc/misc/time/tzset.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tzset +#include "time.c" diff --git a/libc/misc/time/wcsftime.c b/libc/misc/time/wcsftime.c new file mode 100644 index 0000000..e4b25c0 --- /dev/null +++ b/libc/misc/time/wcsftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsftime +#include "time.c" diff --git a/libc/misc/time/wcsftime_l.c b/libc/misc/time/wcsftime_l.c new file mode 100644 index 0000000..68c2954 --- /dev/null +++ b/libc/misc/time/wcsftime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsftime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/libc/misc/ttyent/Makefile b/libc/misc/ttyent/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/ttyent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/ttyent/Makefile.in b/libc/misc/ttyent/Makefile.in new file mode 100644 index 0000000..d20f7ad --- /dev/null +++ b/libc/misc/ttyent/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := getttyent.c + +MISC_TTYENT_DIR := $(top_srcdir)libc/misc/ttyent +MISC_TTYENT_OUT := $(top_builddir)libc/misc/ttyent + +MISC_TTYENT_SRC := $(patsubst %.c,$(MISC_TTYENT_DIR)/%.c,$(CSRC)) +MISC_TTYENT_OBJ := $(patsubst %.c,$(MISC_TTYENT_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_TTYENT_OBJ) + +objclean-y += misc_ttyent_clean + +misc_ttyent_clean: + $(do_rm) $(addprefix $(MISC_TTYENT_OUT)/*., o os) diff --git a/libc/misc/ttyent/getttyent.c b/libc/misc/ttyent/getttyent.c new file mode 100644 index 0000000..b55cdb2 --- /dev/null +++ b/libc/misc/ttyent/getttyent.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +libc_hidden_proto(__fsetlocking) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets_unlocked) +libc_hidden_proto(getc_unlocked) +libc_hidden_proto(__fgetc_unlocked) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(abort) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +static char zapchar; +static FILE *tf; +static struct ttyent tty; + + +/* Skip over the current field, removing quotes, and return + * a pointer to the next field. + */ +#define QUOTED 1 +static char * skip(register char *p) +{ + register char *t; + register int c, q; + + for (q = 0, t = p; (c = *p) != '\0'; p++) { + if (c == '"') { + q ^= QUOTED; /* obscure, but nice */ + continue; + } + if (q == QUOTED && *p == '\\' && *(p+1) == '"') + p++; + *t++ = *p; + if (q == QUOTED) + continue; + if (c == '#') { + zapchar = c; + *p = 0; + break; + } + if (c == '\t' || c == ' ' || c == '\n') { + zapchar = c; + *p++ = 0; + while ((c = *p) == '\t' || c == ' ' || c == '\n') + p++; + break; + } + } + *--t = '\0'; + return (p); +} + +static char * value(register char *p) +{ + + return ((p = strchr(p, '=')) ? ++p : NULL); +} + +libc_hidden_proto(setttyent) +int setttyent(void) +{ + + if (tf) { + rewind(tf); + return (1); + } else if ((tf = fopen(_PATH_TTYS, "r"))) { + /* We do the locking ourselves. */ +#ifdef __UCLIBC_HAS_THREADS__ + __fsetlocking (tf, FSETLOCKING_BYCALLER); +#endif + return (1); + } + return (0); +} +libc_hidden_def(setttyent) + +libc_hidden_proto(getttyent) +struct ttyent * getttyent(void) +{ + register int c; + register char *p; + static char *line = NULL; + struct ttyent *retval = NULL; + + if (!tf && !setttyent()) + return (NULL); + + if (!line) { + line = malloc(BUFSIZ); + if (!line) + abort(); + } + + __STDIO_ALWAYS_THREADLOCK(tf); + + for (;;) { + if (!fgets_unlocked(p = line, BUFSIZ, tf)) { + goto DONE; + } + /* skip lines that are too big */ + if (!strchr(p, '\n')) { + while ((c = getc_unlocked(tf)) != '\n' && c != EOF) + ; + continue; + } + while (isspace(*p)) + ++p; + if (*p && *p != '#') + break; + } + + zapchar = 0; + tty.ty_name = p; + p = skip(p); + if (!*(tty.ty_getty = p)) + tty.ty_getty = tty.ty_type = NULL; + else { + p = skip(p); + if (!*(tty.ty_type = p)) + tty.ty_type = NULL; + else + p = skip(p); + } + tty.ty_status = 0; + tty.ty_window = NULL; + +#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1]) +#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '=' + for (; *p; p = skip(p)) { + if (scmp(_TTYS_OFF)) + tty.ty_status &= ~TTY_ON; + else if (scmp(_TTYS_ON)) + tty.ty_status |= TTY_ON; + else if (scmp(_TTYS_SECURE)) + tty.ty_status |= TTY_SECURE; + else if (vcmp(_TTYS_WINDOW)) + tty.ty_window = value(p); + else + break; + } + + if (zapchar == '#' || *p == '#') + while ((c = *++p) == ' ' || c == '\t') + ; + tty.ty_comment = p; + if (*p == 0) + tty.ty_comment = 0; + if ((p = strchr(p, '\n'))) + *p = '\0'; + retval = &tty; + + DONE: + __STDIO_ALWAYS_THREADUNLOCK(tf); + return retval; +} +libc_hidden_def(getttyent) + +libc_hidden_proto(endttyent) +int endttyent(void) +{ + int rval; + + if (tf) { + rval = !(fclose(tf) == EOF); + tf = NULL; + return (rval); + } + return (1); +} +libc_hidden_def(endttyent) + +struct ttyent * getttynam(const char *_tty) +{ + register struct ttyent *t; + + setttyent(); + while ((t = getttyent())) + if (!strcmp(_tty, t->ty_name)) + break; + endttyent(); + return (t); +} diff --git a/libc/misc/utmp/Makefile b/libc/misc/utmp/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/utmp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/utmp/Makefile.in b/libc/misc/utmp/Makefile.in new file mode 100644 index 0000000..fcc8306 --- /dev/null +++ b/libc/misc/utmp/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := utent.c wtent.c + +MISC_UTMP_DIR := $(top_srcdir)libc/misc/utmp +MISC_UTMP_OUT := $(top_builddir)libc/misc/utmp + +MISC_UTMP_SRC := $(patsubst %.c,$(MISC_UTMP_DIR)/%.c,$(CSRC)) +MISC_UTMP_OBJ := $(patsubst %.c,$(MISC_UTMP_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_UTMP_OBJ) + +objclean-y += misc_utmp_clean + +misc_utmp_clean: + $(do_rm) $(addprefix $(MISC_UTMP_OUT)/*., o os) diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c new file mode 100644 index 0000000..6c1793e --- /dev/null +++ b/libc/misc/utmp/utent.c @@ -0,0 +1,210 @@ +/* utent.c */ +/* Let it be known that this is very possibly the worst standard ever. HP-UX + does one thing, someone else does another, linux another... If anyone + actually has the standard, please send it to me. + + Note that because of the way this stupid stupid standard works, you + have to call endutent() to close the file even if you've not called + setutent -- getutid and family use the same file descriptor. + + Modified by Erik Andersen for uClibc... +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(open) +libc_hidden_proto(fcntl) +libc_hidden_proto(close) +libc_hidden_proto(lseek) + +#include +__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER); + + + +/* Some global crap */ +static int static_fd = -1; +static struct utmp static_utmp; +static const char default_file_name[] = _PATH_UTMP; +static const char *static_ut_name = (const char *) default_file_name; + +/* This function must be called with the LOCK held */ +static void __setutent(void) +{ + int ret; + + if (static_fd == -1) { + if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { + if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { + goto bummer; + } + } + /* Make sure the file will be closed on exec() */ + ret = fcntl(static_fd, F_GETFD, 0); + if (ret >= 0) { + ret = fcntl(static_fd, F_SETFD, ret | FD_CLOEXEC); + } + if (ret < 0) { +bummer: + static_fd = -1; + close(static_fd); + return; + } + } + lseek(static_fd, 0, SEEK_SET); + return; +} + +libc_hidden_proto(setutent) +void setutent(void) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + __setutent(); + __UCLIBC_MUTEX_UNLOCK(utmplock); +} +libc_hidden_def(setutent) + +/* This function must be called with the LOCK held */ +static struct utmp *__getutent(int utmp_fd) +{ + struct utmp *ret = NULL; + + if (utmp_fd == -1) { + __setutent(); + } + if (utmp_fd == -1) { + return NULL; + } + + if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) == sizeof(struct utmp)) + { + ret = &static_utmp; + } + + return ret; +} + +void endutent(void) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd != -1) + close(static_fd); + static_fd = -1; + __UCLIBC_MUTEX_UNLOCK(utmplock); +} + +struct utmp *getutent(void) +{ + struct utmp *ret = NULL; + + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __getutent(static_fd); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; +} + +/* This function must be called with the LOCK held */ +static struct utmp *__getutid(const struct utmp *utmp_entry) +{ + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { + if ( (utmp_entry->ut_type == RUN_LVL || + utmp_entry->ut_type == BOOT_TIME || + utmp_entry->ut_type == NEW_TIME || + utmp_entry->ut_type == OLD_TIME) && + lutmp->ut_type == utmp_entry->ut_type) + { + return lutmp; + } + if ( (utmp_entry->ut_type == INIT_PROCESS || + utmp_entry->ut_type == DEAD_PROCESS || + utmp_entry->ut_type == LOGIN_PROCESS || + utmp_entry->ut_type == USER_PROCESS) && + !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id))) + { + return lutmp; + } + } + + return NULL; +} + +libc_hidden_proto(getutid) +struct utmp *getutid(const struct utmp *utmp_entry) +{ + struct utmp *ret = NULL; + + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __getutid(utmp_entry); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; +} +libc_hidden_def(getutid) + +struct utmp *getutline(const struct utmp *utmp_entry) +{ + struct utmp *lutmp = NULL; + + __UCLIBC_MUTEX_LOCK(utmplock); + while ((lutmp = __getutent(static_fd)) != NULL) { + if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && + !strcmp(lutmp->ut_line, utmp_entry->ut_line)) { + break; + } + } + __UCLIBC_MUTEX_UNLOCK(utmplock); + return lutmp; +} + +struct utmp *pututline (const struct utmp *utmp_entry) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + + if (__getutid(utmp_entry) != NULL) + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + else + lseek(static_fd, (off_t) 0, SEEK_END); + if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) + utmp_entry = NULL; + + __UCLIBC_MUTEX_UNLOCK(utmplock); + return (struct utmp *)utmp_entry; +} + +int utmpname (const char *new_ut_name) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + if (new_ut_name != NULL) { + if (static_ut_name != default_file_name) + free((char *)static_ut_name); + static_ut_name = strdup(new_ut_name); + if (static_ut_name == NULL) { + /* We should probably whine about out-of-memory + * errors here... Instead just reset to the default */ + static_ut_name = default_file_name; + } + } + + if (static_fd != -1) + close(static_fd); + static_fd = -1; + __UCLIBC_MUTEX_UNLOCK(utmplock); + return 0; +} diff --git a/libc/misc/utmp/wtent.c b/libc/misc/utmp/wtent.c new file mode 100644 index 0000000..9430bbb --- /dev/null +++ b/libc/misc/utmp/wtent.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* wtmp support rubbish (i.e. complete crap) */ + +#include +#include +#include +#include +#include +#include +#include + +#if 0 +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(updwtmp) +#endif +libc_hidden_proto(open) +libc_hidden_proto(write) +libc_hidden_proto(close) +libc_hidden_proto(lockf) +libc_hidden_proto(gettimeofday) + +#if 0 +/* This is enabled in uClibc/libutil/logwtmp.c */ +void logwtmp (const char *line, const char *name, const char *host) +{ + struct utmp lutmp; + memset (&(lutmp), 0, sizeof (struct utmp)); + + lutmp.ut_type = (name && *name)? USER_PROCESS : DEAD_PROCESS; + lutmp.ut_pid = __getpid(); + strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); + strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); + strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); + gettimeofday(&(lutmp.ut_tv), NULL); + + updwtmp(_PATH_WTMP, &(lutmp)); +} +#endif + +void updwtmp(const char *wtmp_file, const struct utmp *lutmp) +{ + int fd; + + fd = open(wtmp_file, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0)==0) { + write(fd, (const char *) lutmp, sizeof(struct utmp)); + lockf(fd, F_ULOCK, 0); + close(fd); + } + } +} diff --git a/libc/misc/wchar/Makefile b/libc/misc/wchar/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/wchar/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/wchar/Makefile.in b/libc/misc/wchar/Makefile.in new file mode 100644 index 0000000..e72e31e --- /dev/null +++ b/libc/misc/wchar/Makefile.in @@ -0,0 +1,39 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# The stdio and time related wide functions are now built in the normal +# directories. +# +# stdio: +# fwide fgetwc getwchar fgetws fputwc putwchar fputws ungetwc +# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias) +# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias) +# time: +# wcsftime +# + +# multi source wchar.c +CSRC := btowc.c wctob.c mbsinit.c mbrlen.c mbrtowc.c wcrtomb.c mbsrtowcs.c \ + wcsrtombs.c _wchar_utf8sntowcs.c _wchar_wcsntoutf8s.c \ + mbsnrtowcs.c wcsnrtombs.c wcwidth.c wcswidth.c + +ifeq ($(UCLIBC_HAS_LOCALE),y) +CSRC += iconv.c +endif + +MISC_WCHAR_DIR := $(top_srcdir)libc/misc/wchar +MISC_WCHAR_OUT := $(top_builddir)libc/misc/wchar + +MISC_WCHAR_SRC := $(patsubst %.c,$(MISC_WCHAR_DIR)/%.c,$(CSRC)) +MISC_WCHAR_OBJ := $(patsubst %.c,$(MISC_WCHAR_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_WCHAR) += $(MISC_WCHAR_OBJ) + +objclean-y += misc_wchar_clean + +misc_wchar_clean: + $(do_rm) $(addprefix $(MISC_WCHAR_OUT)/*., o os) diff --git a/libc/misc/wchar/_wchar_utf8sntowcs.c b/libc/misc/wchar/_wchar_utf8sntowcs.c new file mode 100644 index 0000000..a01990e --- /dev/null +++ b/libc/misc/wchar/_wchar_utf8sntowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__wchar_utf8sntowcs +#include "wchar.c" diff --git a/libc/misc/wchar/_wchar_wcsntoutf8s.c b/libc/misc/wchar/_wchar_wcsntoutf8s.c new file mode 100644 index 0000000..a63aa91 --- /dev/null +++ b/libc/misc/wchar/_wchar_wcsntoutf8s.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__wchar_wcsntoutf8s +#include "wchar.c" diff --git a/libc/misc/wchar/btowc.c b/libc/misc/wchar/btowc.c new file mode 100644 index 0000000..d5e60ce --- /dev/null +++ b/libc/misc/wchar/btowc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_btowc +#include "wchar.c" diff --git a/libc/misc/wchar/iconv.c b/libc/misc/wchar/iconv.c new file mode 100644 index 0000000..e6e8ea8 --- /dev/null +++ b/libc/misc/wchar/iconv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iconv +#include "wchar.c" diff --git a/libc/misc/wchar/mbrlen.c b/libc/misc/wchar/mbrlen.c new file mode 100644 index 0000000..01bd31e --- /dev/null +++ b/libc/misc/wchar/mbrlen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbrlen +#include "wchar.c" diff --git a/libc/misc/wchar/mbrtowc.c b/libc/misc/wchar/mbrtowc.c new file mode 100644 index 0000000..76ce28a --- /dev/null +++ b/libc/misc/wchar/mbrtowc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbrtowc +#include "wchar.c" diff --git a/libc/misc/wchar/mbsinit.c b/libc/misc/wchar/mbsinit.c new file mode 100644 index 0000000..23aaac5 --- /dev/null +++ b/libc/misc/wchar/mbsinit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsinit +#include "wchar.c" diff --git a/libc/misc/wchar/mbsnrtowcs.c b/libc/misc/wchar/mbsnrtowcs.c new file mode 100644 index 0000000..9b407c1 --- /dev/null +++ b/libc/misc/wchar/mbsnrtowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsnrtowcs +#include "wchar.c" diff --git a/libc/misc/wchar/mbsrtowcs.c b/libc/misc/wchar/mbsrtowcs.c new file mode 100644 index 0000000..dd47a91 --- /dev/null +++ b/libc/misc/wchar/mbsrtowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsrtowcs +#include "wchar.c" diff --git a/libc/misc/wchar/wchar.c b/libc/misc/wchar/wchar.c new file mode 100644 index 0000000..6214243 --- /dev/null +++ b/libc/misc/wchar/wchar.c @@ -0,0 +1,1737 @@ + +/* Copyright (C) 2002, 2003, 2004 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* May 23, 2002 Initial Notes: + * + * I'm still tweaking this stuff, but it passes the tests I've thrown + * at it, and Erik needs it for the gcc port. The glibc extension + * __wcsnrtombs() hasn't been tested, as I didn't find a test for it + * in the glibc source. I also need to fix the behavior of + * _wchar_utf8sntowcs() if the max number of wchars to convert is 0. + * + * UTF-8 -> wchar -> UTF-8 conversion tests on Markus Kuhn's UTF-8-demo.txt + * file on my platform (x86) show about 5-10% faster conversion speed than + * glibc with mbsrtowcs()/wcsrtombs() and almost twice as fast as glibc with + * individual mbrtowc()/wcrtomb() calls. + * + * If 'DECODER' is defined, then _wchar_utf8sntowcs() will be compiled + * as a fail-safe UTF-8 decoder appropriate for a terminal, etc. which + * needs to deal gracefully with whatever is sent to it. In that mode, + * it passes Markus Kuhn's UTF-8-test.txt stress test. I plan to add + * an arg to force that behavior, so the interface will be changing. + * + * I need to fix the error checking for 16-bit wide chars. This isn't + * an issue for uClibc, but may be for ELKS. I'm currently not sure + * if I'll use 16-bit, 32-bit, or configureable wchars in ELKS. + * + * July 1, 2002 + * + * Fixed _wchar_utf8sntowcs() for the max number of wchars == 0 case. + * Fixed nul-char bug in btowc(), and another in __mbsnrtowcs() for 8-bit + * locales. + * Enabled building of a C/POSIX-locale-only version, so full locale support + * no longer needs to be enabled. + * + * Nov 4, 2002 + * + * Fixed a bug in _wchar_wcsntoutf8s(). Don't store wcs position if dst is NULL. + * Also, introduce an awful hack into _wchar_wcsntoutf8s() and wcsrtombs() in + * order to support %ls in printf. See comments below for details. + * Change behaviour of wc<->mb functions when in the C locale. Now they do + * a 1-1 map for the range 0x80-UCHAR_MAX. This is for backwards compatibility + * and consistency with the stds requirements that a printf format string by + * a valid multibyte string beginning and ending in it's initial shift state. + * + * Nov 5, 2002 + * + * Forgot to change btowc and wctob when I changed the wc<->mb functions yesterday. + * + * Nov 7, 2002 + * + * Add wcwidth and wcswidth, based on Markus Kuhn's wcwidth of 2002-05-08. + * Added some size/speed optimizations and integrated it into my locale + * framework. Minimally tested at the moment, but the stub C-locale + * version (which most people would probably be using) should be fine. + * + * Nov 21, 2002 + * + * Revert the wc<->mb changes from earlier this month involving the C-locale. + * Add a couple of ugly hacks to support *wprintf. + * Add a mini iconv() and iconv implementation (requires locale support). + * + * Aug 1, 2003 + * Bug fix for mbrtowc. + * + * Aug 18, 2003 + * Bug fix: _wchar_utf8sntowcs and _wchar_wcsntoutf8s now set errno if EILSEQ. + * + * Feb 11, 2004 + * Bug fix: Fix size check for remaining output space in iconv(). + * + * Manuel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_LOCALE__ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix Cc2wc* and Cwc2c* defines! +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding) + +#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT +#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN +#define Cwc2c_DOMAIN_MAX __LOCALE_DATA_Cwc2c_DOMAIN_MAX +#define Cwc2c_TI_SHIFT __LOCALE_DATA_Cwc2c_TI_SHIFT +#define Cwc2c_TT_SHIFT __LOCALE_DATA_Cwc2c_TT_SHIFT +#define Cwc2c_TI_LEN __LOCALE_DATA_Cwc2c_TI_LEN + +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif + +#else /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_btowc +/* emit only once */ +#warning fix preprocessor logic testing locale settings +#endif +#endif + +#define ENCODING (__ctype_encoding_7_bit) +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#error __CTYPE_HAS_8_BIT_LOCALES is defined! +#endif +#ifdef __CTYPE_HAS_UTF_8_LOCALES +#error __CTYPE_HAS_UTF_8_LOCALES is defined! +#endif +#undef L__wchar_utf8sntowcs +#undef L__wchar_wcsntoutf8s + +#endif /* __UCLIBC_HAS_LOCALE__ */ +/**********************************************************************/ + +#if WCHAR_MAX > 0xffffUL +#define UTF_8_MAX_LEN 6 +#else +#define UTF_8_MAX_LEN 3 +#endif + +#define KUHN 1 + +/* Implementation-specific work functions. */ + +extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) attribute_hidden; + +extern size_t _wchar_wcsntoutf8s(char *__restrict s, size_t n, + const wchar_t **__restrict src, size_t wn) attribute_hidden; + +/**********************************************************************/ +#ifdef L_btowc + +libc_hidden_proto(mbrtowc) + +libc_hidden_proto(btowc) +wint_t btowc(int c) +{ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + + wchar_t wc; + unsigned char buf[1]; + mbstate_t mbstate; + + if (c != EOF) { + *buf = (unsigned char) c; + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (mbrtowc(&wc, buf, 1, &mbstate) <= 1) { + return wc; + } + } + return WEOF; + +#else /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert((ENCODING == __ctype_encoding_7_bit) + || (ENCODING == __ctype_encoding_utf8)); +#endif /* __UCLIBC_HAS_LOCALE__ */ + + /* If we don't have 8-bit locale support, then this is trivial since + * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */ + return (((unsigned int)c) < 0x80) ? c : WEOF; + +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +} +libc_hidden_def(btowc) + +#endif +/**********************************************************************/ +#ifdef L_wctob + +/* Note: We completely ignore ps in all currently supported conversions. */ + +libc_hidden_proto(wcrtomb) + +int wctob(wint_t c) +{ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + + unsigned char buf[MB_LEN_MAX]; + + return (wcrtomb(buf, c, NULL) == 1) ? *buf : EOF; + +#else /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert((ENCODING == __ctype_encoding_7_bit) + || (ENCODING == __ctype_encoding_utf8)); +#endif /* __UCLIBC_HAS_LOCALE__ */ + + /* If we don't have 8-bit locale support, then this is trivial since + * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */ + + /* TODO: need unsigned version of wint_t... */ +/* return (((unsigned int)c) < 0x80) ? c : WEOF; */ + return ((c >= 0) && (c < 0x80)) ? c : EOF; + +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +} + +#endif +/**********************************************************************/ +#ifdef L_mbsinit + +libc_hidden_proto(mbsinit) +int mbsinit(const mbstate_t *ps) +{ + return !ps || !ps->__mask; +} +libc_hidden_def(mbsinit) + +#endif +/**********************************************************************/ +#ifdef L_mbrlen + +libc_hidden_proto(mbrtowc) + +libc_hidden_proto(mbrlen) +size_t mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + + return mbrtowc(NULL, s, n, (ps != NULL) ? ps : &mbstate); +} +libc_hidden_def(mbrlen) + +#endif +/**********************************************************************/ +#ifdef L_mbrtowc + +libc_hidden_proto(mbsnrtowcs) + +libc_hidden_proto(mbrtowc) +size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s, + size_t n, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + wchar_t wcbuf[1]; + const char *p; + size_t r; + char empty_string[1]; /* Avoid static to be fPIC friendly. */ + + if (!ps) { + ps = &mbstate; + } + + if (!s) { + pwc = (wchar_t *) s; /* NULL */ + empty_string[0] = 0; /* Init the empty string when necessary. */ + s = empty_string; + n = 1; + } else if (*s == '\0') { + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + } else if (!n) { + /* TODO: change error code? */ +#if 0 + return (ps->__mask && (ps->__wc == 0xffffU)) + ? ((size_t) -1) : ((size_t) -2); +#else + return 0; +#endif + } + + p = s; + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + /* Need to do this here since mbsrtowcs doesn't allow incompletes. */ + if (ENCODING == __ctype_encoding_utf8) { + if (!pwc) { + pwc = wcbuf; + } + r = _wchar_utf8sntowcs(pwc, 1, &p, n, ps, 1); + return (r == 1) ? (p-s) : r; /* Need to return 0 if nul char. */ + } +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: This adds a trailing nul! +#endif /* __UCLIBC_MJN3_ONLY__ */ + + r = mbsnrtowcs(wcbuf, &p, SIZE_MAX, 1, ps); + + if (((ssize_t) r) >= 0) { + if (pwc) { + *pwc = *wcbuf; + } + } + return (size_t) r; +} +libc_hidden_def(mbrtowc) + +#endif +/**********************************************************************/ +#ifdef L_wcrtomb + +libc_hidden_proto(wcsnrtombs) + +/* Note: We completely ignore ps in all currently supported conversions. */ +/* TODO: Check for valid state anyway? */ + +libc_hidden_proto(wcrtomb) +size_t wcrtomb(register char *__restrict s, wchar_t wc, + mbstate_t *__restrict ps) +{ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Should wcsnrtombs nul-terminate unconditionally? Check glibc. +#endif /* __UCLIBC_MJN3_ONLY__ */ + wchar_t wcbuf[1]; + const wchar_t *pwc; + size_t r; + char buf[MB_LEN_MAX]; + + if (!s) { + s = buf; + wc = 0; + } + + pwc = wcbuf; + wcbuf[0] = wc; + + r = wcsnrtombs(s, &pwc, 1, MB_LEN_MAX, ps); + return (r != 0) ? r : 1; +} +libc_hidden_def(wcrtomb) + +#endif +/**********************************************************************/ +#ifdef L_mbsrtowcs + +libc_hidden_proto(mbsnrtowcs) + +libc_hidden_proto(mbsrtowcs) +size_t mbsrtowcs(wchar_t *__restrict dst, const char **__restrict src, + size_t len, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + + return mbsnrtowcs(dst, src, SIZE_MAX, len, + ((ps != NULL) ? ps : &mbstate)); +} +libc_hidden_def(mbsrtowcs) + +#endif +/**********************************************************************/ +#ifdef L_wcsrtombs + +/* Note: We completely ignore ps in all currently supported conversions. + + * TODO: Check for valid state anyway? */ + +libc_hidden_proto(wcsnrtombs) + +libc_hidden_proto(wcsrtombs) +size_t wcsrtombs(char *__restrict dst, const wchar_t **__restrict src, + size_t len, mbstate_t *__restrict ps) +{ + return wcsnrtombs(dst, src, SIZE_MAX, len, ps); +} +libc_hidden_def(wcsrtombs) + +#endif +/**********************************************************************/ +#ifdef L__wchar_utf8sntowcs + +/* Define DECODER to generate a UTF-8 decoder which passes Markus Kuhn's + * UTF-8-test.txt strss test. + */ +/* #define DECODER */ + +#ifdef DECODER +#ifndef KUHN +#define KUHN +#endif +#endif + +size_t attribute_hidden _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) +{ + register const char *s; + __uwchar_t mask; + __uwchar_t wc; + wchar_t wcbuf[1]; + size_t count; + int incr; + + s = *src; + + assert(s != NULL); + assert(ps != NULL); + + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %s in + * wprintf, we need to be able to compute the number of wchars needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (wchar_t *) ps + * as pwc in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See mbsnrtowcs() as well. */ + if (!pwc || (pwc == ((wchar_t *)ps))) { + if (!pwc) { + wn = SIZE_MAX; + } + pwc = wcbuf; + incr = 0; + } + + /* This is really here only to support the glibc extension function + * __mbsnrtowcs which apparently returns 0 if wn == 0 without any + * check on the validity of the mbstate. */ + if (!(count = wn)) { + return 0; + } + + if ((mask = (__uwchar_t) ps->__mask) != 0) { /* A continuation... */ +#ifdef DECODER + wc = (__uwchar_t) ps->__wc; + if (n) { + goto CONTINUE; + } + goto DONE; +#else + if ((wc = (__uwchar_t) ps->__wc) != 0xffffU) { + /* TODO: change error code here and below? */ + if (n) { + goto CONTINUE; + } + goto DONE; + } + __set_errno(EILSEQ); + return (size_t) -1; /* We're in an error state. */ +#endif + } + + do { + if (!n) { + goto DONE; + } + --n; + if ((wc = ((unsigned char) *s++)) >= 0x80) { /* Not ASCII... */ + mask = 0x40; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix range for 16 bit wchar_t case. +#endif + if (( ((unsigned char)(s[-1] - 0xc0)) < (0xfe - 0xc0) ) && + (((unsigned char)s[-1] != 0xc0 ) && ((unsigned char)s[-1] != 0xc1 ))) { + goto START; + } + BAD: +#ifdef DECODER + wc = 0xfffdU; + goto COMPLETE; +#else + ps->__mask = mask; + ps->__wc = 0xffffU; + __set_errno(EILSEQ); + return (size_t) -1; /* Illegal start byte! */ +#endif + + CONTINUE: + while (n) { + --n; + if ((*s & 0xc0) != 0x80) { + goto BAD; + } + mask <<= 5; + wc <<= 6; + wc += (*s & 0x3f); /* keep seperate for bcc (smaller code) */ + ++s; + START: + wc &= ~(mask << 1); + + if ((wc & mask) == 0) { /* Character completed. */ + if ((mask >>= 5) == 0x40) { + mask += mask; + } + /* Check for invalid sequences (longer than necessary) + * and invalid chars. */ + if ( (wc < mask) /* Sequence not minimal length. */ +#ifdef KUHN +#if UTF_8_MAX_LEN == 3 +#error broken since mask can overflow!! + /* For plane 0, these are the only defined values.*/ + || (wc > 0xfffdU) +#else + /* Note that we don't need to worry about exceeding */ + /* 31 bits as that is the most that UTF-8 provides. */ + || ( ((__uwchar_t)(wc - 0xfffeU)) < 2) +#endif + || ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) ) +#endif /* KUHN */ + ) { + goto BAD; + } + goto COMPLETE; + } + } + /* Character potentially valid but incomplete. */ + if (!allow_continuation) { + if (count != wn) { + return 0; + } + /* NOTE: The following can fail if you allow and then disallow + * continuation!!! */ +#if UTF_8_MAX_LEN == 3 +#error broken since mask can overflow!! +#endif + /* Need to back up... */ + do { + --s; + } while ((mask >>= 5) >= 0x40); + goto DONE; + } + ps->__mask = (wchar_t) mask; + ps->__wc = (wchar_t) wc; + *src = s; + return (size_t) -2; + } + COMPLETE: + *pwc = wc; + pwc += incr; + } +#ifdef DECODER + while (--count); +#else + while (wc && --count); + + if (!wc) { + s = NULL; + } +#endif + + DONE: + /* ps->__wc is irrelavent here. */ + ps->__mask = 0; + if (pwc != wcbuf) { + *src = s; + } + + return wn - count; +} + +#endif +/**********************************************************************/ +#ifdef L__wchar_wcsntoutf8s + +size_t attribute_hidden _wchar_wcsntoutf8s(char *__restrict s, size_t n, + const wchar_t **__restrict src, size_t wn) +{ + register char *p; + size_t len, t; + __uwchar_t wc; + const __uwchar_t *swc; + int store; + char buf[MB_LEN_MAX]; + char m; + + store = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %ls in + * printf, we need to be able to compute the number of bytes needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (char *) src + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See wcsnrtombs() as well. */ + if (!s || (s == ((char *) src))) { + if (!s) { + n = SIZE_MAX; + } + s = buf; + store = 0; + } + + t = n; + swc = (const __uwchar_t *) *src; + + assert(swc != NULL); + + while (wn && t) { + wc = *swc; + + *s = wc; + len = 1; + + if (wc >= 0x80) { +#ifdef KUHN + if ( +#if UTF_8_MAX_LEN == 3 + /* For plane 0, these are the only defined values.*/ + /* Note that we don't need to worry about exceeding */ + /* 31 bits as that is the most that UTF-8 provides. */ + (wc > 0xfffdU) +#else + /* UTF_8_MAX_LEN == 6 */ + (wc > 0x7fffffffUL) + || ( ((__uwchar_t)(wc - 0xfffeU)) < 2) +#endif + || ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) ) + ) { + __set_errno(EILSEQ); + return (size_t) -1; + } +#else /* KUHN */ +#if UTF_8_MAX_LEN != 3 + if (wc > 0x7fffffffUL) { /* Value too large. */ + __set_errno(EILSEQ); + return (size_t) -1; + } +#endif +#endif /* KUHN */ + + wc >>= 1; + p = s; + do { + ++p; + } while (wc >>= 5); + wc = *swc; + if ((len = p - s) > t) { /* Not enough space. */ + break; + } + + m = 0x80; + while( p>s ) { + m = (m >> 1) | 0x80; + *--p = (wc & 0x3f) | 0x80; + wc >>= 6; + } + *s |= (m << 1); + } else if (wc == 0) { /* End of string. */ + swc = NULL; + break; + } + + ++swc; + --wn; + t -= len; + if (store) { + s += len; + } + } + + if (store) { + *src = (const wchar_t *) swc; + } + + return n - t; +} + + +#endif +/**********************************************************************/ +#ifdef L_mbsnrtowcs + +/* WARNING: We treat len as SIZE_MAX when dst is NULL! */ + +libc_hidden_proto(mbsnrtowcs) +size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src, + size_t NMC, size_t len, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + wchar_t wcbuf[1]; + const char *s; + size_t count; + int incr; + + if (!ps) { + ps = &mbstate; + } + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (ENCODING == __ctype_encoding_utf8) { + size_t r; + return ((r = _wchar_utf8sntowcs(dst, len, src, NMC, ps, 1)) + != (size_t) -2) ? r : 0; + } +#endif + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %s in + * wprintf, we need to be able to compute the number of wchars needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of ((wchar_t *)ps) + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See _wchar_utf8sntowcs() as well. */ + if (!dst || (dst == ((wchar_t *)ps))) { + if (!dst) { + len = SIZE_MAX; + } + dst = wcbuf; + incr = 0; + } + + /* Since all the following encodings are single-byte encodings... */ + if (len > NMC) { + len = NMC; + } + + count = len; + s = *src; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (ENCODING == __ctype_encoding_8_bit) { + wchar_t wc; + while (count) { + if ((wc = ((unsigned char)(*s))) >= 0x80) { /* Non-ASCII... */ + wc -= 0x80; + wc = __UCLIBC_CURLOCALE_DATA.tbl8c2wc[ + (__UCLIBC_CURLOCALE_DATA.idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (!wc) { + goto BAD; + } + } + if (!(*dst = wc)) { + s = NULL; + break; + } + dst += incr; + ++s; + --count; + } + if (dst != wcbuf) { + *src = s; + } + return len - count; + } +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + assert(ENCODING == __ctype_encoding_7_bit); +#endif + + while (count) { + if ((*dst = (unsigned char) *s) == 0) { + s = NULL; + break; + } + if (*dst >= 0x80) { +#ifdef __CTYPE_HAS_8_BIT_LOCALES + BAD: +#endif + __set_errno(EILSEQ); + return (size_t) -1; + } + ++s; + dst += incr; + --count; + } + if (dst != wcbuf) { + *src = s; + } + return len - count; +} +libc_hidden_def(mbsnrtowcs) + +#endif +/**********************************************************************/ +#ifdef L_wcsnrtombs + +/* WARNING: We treat len as SIZE_MAX when dst is NULL! */ + +/* Note: We completely ignore ps in all currently supported conversions. + * TODO: Check for valid state anyway? */ + +libc_hidden_proto(wcsnrtombs) +size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src, + size_t NWC, size_t len, mbstate_t *__restrict ps) +{ + const __uwchar_t *s; + size_t count; + int incr; + char buf[MB_LEN_MAX]; + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (ENCODING == __ctype_encoding_utf8) { + return _wchar_wcsntoutf8s(dst, len, src, NWC); + } +#endif /* __CTYPE_HAS_UTF_8_LOCALES */ + + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %ls in + * printf, we need to be able to compute the number of bytes needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (char *) src + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See _wchar_wcsntoutf8s() as well. */ + if (!dst || (dst == ((char *) src))) { + if (!dst) { + len = SIZE_MAX; + } + dst = buf; + incr = 0; + } + + /* Since all the following encodings are single-byte encodings... */ + if (len > NWC) { + len = NWC; + } + + count = len; + s = (const __uwchar_t *) *src; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (ENCODING == __ctype_encoding_8_bit) { + __uwchar_t wc; + __uwchar_t u; + while (count) { + if ((wc = *s) <= 0x7f) { + if (!(*dst = (unsigned char) wc)) { + s = NULL; + break; + } + } else { + u = 0; + if (wc <= Cwc2c_DOMAIN_MAX) { + u = __UCLIBC_CURLOCALE_DATA.idx8wc2c[wc >> (Cwc2c_TI_SHIFT + + Cwc2c_TT_SHIFT)]; + u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[(u << Cwc2c_TI_SHIFT) + + ((wc >> Cwc2c_TT_SHIFT) + & ((1 << Cwc2c_TI_SHIFT)-1))]; + u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[Cwc2c_TI_LEN + + (u << Cwc2c_TT_SHIFT) + + (wc & ((1 << Cwc2c_TT_SHIFT)-1))]; + } + +#ifdef __WCHAR_REPLACEMENT_CHAR + *dst = (unsigned char) ( u ? u : __WCHAR_REPLACEMENT_CHAR ); +#else /* __WCHAR_REPLACEMENT_CHAR */ + if (!u) { + goto BAD; + } + *dst = (unsigned char) u; +#endif /* __WCHAR_REPLACEMENT_CHAR */ + } + ++s; + dst += incr; + --count; + } + if (dst != buf) { + *src = (const wchar_t *) s; + } + return len - count; + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert(ENCODING == __ctype_encoding_7_bit); +#endif + + while (count) { + if (*s >= 0x80) { +#if defined(__CTYPE_HAS_8_BIT_LOCALES) && !defined(__WCHAR_REPLACEMENT_CHAR) + BAD: +#endif + __set_errno(EILSEQ); + return (size_t) -1; + } + if ((*dst = (unsigned char) *s) == 0) { + s = NULL; + break; + } + ++s; + dst += incr; + --count; + } + if (dst != buf) { + *src = (const wchar_t *) s; + } + return len - count; +} +libc_hidden_def(wcsnrtombs) + +#endif +/**********************************************************************/ +#ifdef L_wcswidth + +libc_hidden_proto(wcswidth) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: If we start doing translit, wcwidth and wcswidth will need updating. +#warning TODO: Update wcwidth to match latest by Kuhn. +#endif + +#if defined(__UCLIBC_HAS_LOCALE__) && \ +( defined(__CTYPE_HAS_8_BIT_LOCALES) || defined(__CTYPE_HAS_UTF_8_LOCALES) ) + +static const unsigned char new_idx[] = { + 0, 5, 5, 6, 10, 15, 28, 39, + 48, 48, 71, 94, 113, 128, 139, 154, + 175, 186, 188, 188, 188, 188, 188, 188, + 203, 208, 208, 208, 208, 208, 208, 208, + 208, 219, 219, 219, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 224, + 224, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 233, 233, 233, + 233, 233, 233, 233, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 237, 237, 238, 241, 241, 242, 249, + 255, +}; + +static const unsigned char new_tbl[] = { + 0x00, 0x01, 0x20, 0x7f, 0xa0, 0x00, 0x00, 0x50, + 0x60, 0x70, 0x00, 0x83, 0x87, 0x88, 0x8a, 0x00, + 0x91, 0xa2, 0xa3, 0xba, 0xbb, 0xbe, 0xbf, 0xc0, + 0xc1, 0xc3, 0xc4, 0xc5, 0x00, 0x4b, 0x56, 0x70, + 0x71, 0xd6, 0xe5, 0xe7, 0xe9, 0xea, 0xee, 0x00, + 0x0f, 0x10, 0x11, 0x12, 0x30, 0x4b, 0xa6, 0xb1, + 0x00, 0x01, 0x03, 0x3c, 0x3d, 0x41, 0x49, 0x4d, + 0x4e, 0x51, 0x55, 0x62, 0x64, 0x81, 0x82, 0xbc, + 0xbd, 0xc1, 0xc5, 0xcd, 0xce, 0xe2, 0xe4, 0x00, + 0x02, 0x03, 0x3c, 0x3d, 0x41, 0x43, 0x47, 0x49, + 0x4b, 0x4e, 0x70, 0x72, 0x81, 0x83, 0xbc, 0xbd, + 0xc1, 0xc6, 0xc7, 0xc9, 0xcd, 0xce, 0x00, 0x01, + 0x02, 0x3c, 0x3d, 0x3f, 0x40, 0x41, 0x44, 0x4d, + 0x4e, 0x56, 0x57, 0x82, 0x83, 0xc0, 0xc1, 0xcd, + 0xce, 0x00, 0x3e, 0x41, 0x46, 0x49, 0x4a, 0x4e, + 0x55, 0x57, 0xbf, 0xc0, 0xc6, 0xc7, 0xcc, 0xce, + 0x00, 0x41, 0x44, 0x4d, 0x4e, 0xca, 0xcb, 0xd2, + 0xd5, 0xd6, 0xd7, 0x00, 0x31, 0x32, 0x34, 0x3b, + 0x47, 0x4f, 0xb1, 0xb2, 0xb4, 0xba, 0xbb, 0xbd, + 0xc8, 0xce, 0x00, 0x18, 0x1a, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x71, 0x7f, 0x80, 0x85, 0x86, + 0x88, 0x90, 0x98, 0x99, 0xbd, 0xc6, 0xc7, 0x00, + 0x2d, 0x31, 0x32, 0x33, 0x36, 0x38, 0x39, 0x3a, + 0x58, 0x5a, 0x00, 0x60, 0x00, 0x12, 0x15, 0x32, + 0x35, 0x52, 0x54, 0x72, 0x74, 0xb7, 0xbe, 0xc6, + 0xc7, 0xc9, 0xd4, 0x00, 0x0b, 0x0f, 0xa9, 0xaa, + 0x00, 0x0b, 0x10, 0x2a, 0x2f, 0x60, 0x64, 0x6a, + 0x70, 0xd0, 0xeb, 0x00, 0x29, 0x2b, 0x00, 0x80, + 0x00, 0x2a, 0x30, 0x3f, 0x40, 0x99, 0x9b, 0x00, + 0xd0, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x1e, + 0x1f, 0x00, 0x00, 0x10, 0x20, 0x24, 0x30, 0x70, + 0xff, 0x00, 0x61, 0xe0, 0xe7, 0xf9, 0xfc, +}; + +static const signed char new_wtbl[] = { + 0, -1, 1, -1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 2, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 2, 1, 1, 2, + 2, 0, 2, 1, 2, 0, 2, 2, + 1, 1, 2, 1, 1, 2, 1, 0, + 1, 1, 0, 1, 0, 1, 2, 1, + 0, 2, 1, 2, 1, 0, 1, +}; + +libc_hidden_proto(wcsnrtombs) + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int h, l, m, count; + wchar_t wc; + unsigned char b; + + if (ENCODING == __ctype_encoding_7_bit) { + size_t i; + + for (i = 0 ; (i < n) && pwcs[i] ; i++) { + if (pwcs[i] != (pwcs[i] & 0x7f)) { + return -1; + } + } + } +#ifdef __CTYPE_HAS_8_BIT_LOCALES + else if (ENCODING == __ctype_encoding_8_bit) { + mbstate_t mbstate; + + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (wcsnrtombs(NULL, &pwcs, n, SIZE_MAX, &mbstate) == ((size_t) - 1)) { + return -1; + } + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#if defined(__CTYPE_HAS_UTF_8_LOCALES) && defined(KUHN) + /* For stricter handling of allowed unicode values... see comments above. */ + else if (ENCODING == __ctype_encoding_utf8) { + size_t i; + + for (i = 0 ; (i < n) && pwcs[i] ; i++) { + if ( (((__uwchar_t)((pwcs[i]) - 0xfffeU)) < 2) + || (((__uwchar_t)((pwcs[i]) - 0xd800U)) < (0xe000U - 0xd800U)) + ) { + return -1; + } + } + } +#endif /* __CTYPE_HAS_UTF_8_LOCALES */ + + for (count = 0 ; n && (wc = *pwcs++) ; n--) { + if (wc <= 0xff) { + /* If we're here, wc != 0. */ + if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) { + return -1; + } + ++count; + continue; + } + if (((unsigned int) wc) <= 0xffff) { + b = wc & 0xff; + h = (wc >> 8); + l = new_idx[h]; + h = new_idx[h+1]; + while ((m = (l+h) >> 1) != l) { + if (b >= new_tbl[m]) { + l = m; + } else { /* wc < tbl[m] */ + h = m; + } + } + count += new_wtbl[l]; /* none should be -1. */ + continue; + } + + /* Redo this to minimize average number of compares?*/ + if (wc >= 0x1d167) { + if (wc <= 0x1d1ad) { + if ((wc <= 0x1d169 + || (wc >= 0x1d173 + && (wc <= 0x1d182 + || (wc >= 0x1d185 + && (wc <= 0x1d18b + || (wc >= 0x1d1aa)))))) + ) { + continue; + } + } else if (((wc >= 0xe0020) && (wc <= 0xe007f)) || (wc == 0xe0001)) { + continue; + } else if ((wc >= 0x20000) && (wc <= 0x2ffff)) { + ++count; /* need 2.. add one here */ + } +#if (WCHAR_MAX > 0x7fffffffL) + else if (wc > 0x7fffffffL) { + return -1; + } +#endif /* (WCHAR_MAX > 0x7fffffffL) */ + } + + ++count; + } + + return count; +} + +#else /* __UCLIBC_HAS_LOCALE__ */ + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int count; + wchar_t wc; + + for (count = 0 ; n && (wc = *pwcs++) ; n--) { + if (wc <= 0xff) { + /* If we're here, wc != 0. */ + if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) { + return -1; + } + ++count; + continue; + } else { + return -1; + } + } + + return count; +} + +#endif /* __UCLIBC_HAS_LOCALE__ */ + +libc_hidden_def(wcswidth) + +#endif +/**********************************************************************/ +#ifdef L_wcwidth + +libc_hidden_proto(wcswidth) + +int wcwidth(wchar_t wc) +{ + return wcswidth(&wc, 1); +} + +#endif +/**********************************************************************/ + + +typedef struct { + mbstate_t tostate; + mbstate_t fromstate; + int tocodeset; + int fromcodeset; + int frombom; + int tobom; + int fromcodeset0; + int frombom0; + int tobom0; + int skip_invalid_input; /* To support iconv -c option. */ +} _UC_iconv_t; + + + +#ifdef L_iconv + +#include +#include +#include +#include + +#if (__BYTE_ORDER != __BIG_ENDIAN) && (__BYTE_ORDER != __LITTLE_ENDIAN) +#error unsupported endianness for iconv +#endif + +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#error currently iconv requires 8 bit locales +#endif +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#error currently iconv requires UTF-8 locales +#endif + + +enum { + IC_WCHAR_T = 0xe0, + IC_MULTIBYTE = 0xe0, +#if __BYTE_ORDER == __BIG_ENDIAN + IC_UCS_4 = 0xec, + IC_UTF_32 = 0xe4, + IC_UCS_2 = 0xe2, + IC_UTF_16 = 0xea, +#else + IC_UCS_4 = 0xed, + IC_UTF_32 = 0xe5, + IC_UCS_2 = 0xe3, + IC_UTF_16 = 0xeb, +#endif + IC_UTF_8 = 2, + IC_ASCII = 1 +}; + +/* For the multibyte + * bit 0 means swap endian + * bit 1 means 2 byte + * bit 2 means 4 byte + * + */ + +extern const unsigned char __iconv_codesets[]; +libc_hidden_proto(__iconv_codesets) +const unsigned char __iconv_codesets[] = + "\x0a\xe0""WCHAR_T\x00" /* superset of UCS-4 but platform-endian */ +#if __BYTE_ORDER == __BIG_ENDIAN + "\x08\xec""UCS-4\x00" /* always BE */ + "\x0a\xec""UCS-4BE\x00" + "\x0a\xed""UCS-4LE\x00" + "\x09\fe4""UTF-32\x00" /* platform endian with BOM */ + "\x0b\xe4""UTF-32BE\x00" + "\x0b\xe5""UTF-32LE\x00" + "\x08\xe2""UCS-2\x00" /* always BE */ + "\x0a\xe2""UCS-2BE\x00" + "\x0a\xe3""UCS-2LE\x00" + "\x09\xea""UTF-16\x00" /* platform endian with BOM */ + "\x0b\xea""UTF-16BE\x00" + "\x0b\xeb""UTF-16LE\x00" +#elif __BYTE_ORDER == __LITTLE_ENDIAN + "\x08\xed""UCS-4\x00" /* always BE */ + "\x0a\xed""UCS-4BE\x00" + "\x0a\xec""UCS-4LE\x00" + "\x09\xf4""UTF-32\x00" /* platform endian with BOM */ + "\x0b\xe5""UTF-32BE\x00" + "\x0b\xe4""UTF-32LE\x00" + "\x08\xe3""UCS-2\x00" /* always BE */ + "\x0a\xe3""UCS-2BE\x00" + "\x0a\xe2""UCS-2LE\x00" + "\x09\xfa""UTF-16\x00" /* platform endian with BOM */ + "\x0b\xeb""UTF-16BE\x00" + "\x0b\xea""UTF-16LE\x00" +#endif + "\x08\x02""UTF-8\x00" + "\x0b\x01""US-ASCII\x00" + "\x07\x01""ASCII"; /* Must be last! (special case to save a nul) */ +libc_hidden_data_def(__iconv_codesets) + +/* Experimentally off - libc_hidden_proto(strcasecmp) */ + +static int find_codeset(const char *name) +{ + const unsigned char *s; + int codeset; + + for (s = __iconv_codesets ; *s ; s += *s) { + if (!strcasecmp(s+2, name)) { + return s[1]; + } + } + + /* The following is ripped from find_locale in locale.c. */ + + /* TODO: maybe CODESET_LIST + *s ??? */ + /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */ + codeset = 2; + s = __LOCALE_DATA_CODESET_LIST; + do { + ++codeset; /* Increment codeset first. */ + if (!strcasecmp(__LOCALE_DATA_CODESET_LIST+*s, name)) { + return codeset; + } + } while (*++s); + + return 0; /* No matching codeset! */ +} + +iconv_t weak_function iconv_open(const char *tocode, const char *fromcode) +{ + register _UC_iconv_t *px; + int tocodeset, fromcodeset; + + if (((tocodeset = find_codeset(tocode)) != 0) + && ((fromcodeset = find_codeset(fromcode)) != 0)) { + if ((px = malloc(sizeof(_UC_iconv_t))) != NULL) { + px->tocodeset = tocodeset; + px->tobom0 = px->tobom = (tocodeset & 0x10) >> 4; + px->fromcodeset0 = px->fromcodeset = fromcodeset; + px->frombom0 = px->frombom = (fromcodeset & 0x10) >> 4; + px->skip_invalid_input = px->tostate.__mask + = px->fromstate.__mask = 0; + return (iconv_t) px; + } + } else { + __set_errno(EINVAL); + } + return (iconv_t)(-1); +} + +int weak_function iconv_close(iconv_t cd) +{ + free(cd); + + return 0; +} + +size_t weak_function iconv(iconv_t cd, char **__restrict inbuf, + size_t *__restrict inbytesleft, + char **__restrict outbuf, + size_t *__restrict outbytesleft) +{ + _UC_iconv_t *px = (_UC_iconv_t *) cd; + size_t nrcount, r; + wchar_t wc, wc2; + int inci, inco; + + assert(px != (_UC_iconv_t *)(-1)); + assert(sizeof(wchar_t) == 4); + + if (!inbuf || !*inbuf) { /* Need to reinitialze conversion state. */ + /* Note: For shift-state encodings we possibly need to output the + * shift sequence to return to initial state! */ + if ((px->fromcodeset & 0xf0) == 0xe0) { + } + px->tostate.__mask = px->fromstate.__mask = 0; + px->fromcodeset = px->fromcodeset0; + px->tobom = px->tobom0; + px->frombom = px->frombom0; + return 0; + } + + nrcount = 0; + while (*inbytesleft) { + if (!*outbytesleft) { + TOO_BIG: + __set_errno(E2BIG); + return (size_t) -1; + } + + inci = inco = 1; + if (px->fromcodeset >= IC_MULTIBYTE) { + inci = (px->fromcodeset == IC_WCHAR_T) ? 4: (px->fromcodeset & 6); + if (*inbytesleft < inci) goto INVALID; + wc = (((unsigned int)((unsigned char)((*inbuf)[0]))) << 8) + + ((unsigned char)((*inbuf)[1])); + if (inci == 4) { + wc = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8) + + ((unsigned char)((*inbuf)[3])) + (wc << 16); + if (!(px->fromcodeset & 1)) wc = bswap_32(wc); + } else { + if (!(px->fromcodeset & 1)) wc = bswap_16(wc); + if (((px->fromcodeset & IC_UTF_16) == IC_UTF_16) + && (((__uwchar_t)(wc - 0xd800U)) < (0xdc00U - 0xd800U)) + ) { /* surrogate */ + wc =- 0xd800U; + if (*inbytesleft < 4) goto INVALID; + wc2 = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8) + + ((unsigned char)((*inbuf)[3])); + if (!(px->fromcodeset & 1)) wc = bswap_16(wc2); + if (((__uwchar_t)(wc2 -= 0xdc00U)) < (0xe0000U - 0xdc00U)) { + goto ILLEGAL; + } + inci = 4; /* Change inci here in case skipping illegals. */ + wc = 0x10000UL + (wc << 10) + wc2; + } + } + + if (px->frombom) { + px->frombom = 0; + if ((wc == 0xfeffU) + || (wc == ((inci == 4) + ? (((wchar_t) 0xfffe0000UL)) + : ((wchar_t)(0xfffeUL)))) + ) { + if (wc != 0xfeffU) { + px->fromcodeset ^= 1; /* toggle endianness */ + wc = 0xfeffU; + } + if (!px->frombom) { + goto BOM_SKIP_OUTPUT; + } + goto GOT_BOM; + } + } + + if (px->fromcodeset != IC_WCHAR_T) { + if (((__uwchar_t) wc) > (((px->fromcodeset & IC_UCS_4) == IC_UCS_4) + ? 0x7fffffffUL : 0x10ffffUL) +#ifdef KUHN + || (((__uwchar_t)(wc - 0xfffeU)) < 2) + || (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U)) +#endif + ) { + goto ILLEGAL; + } + } + } else if (px->fromcodeset == IC_UTF_8) { + const char *p = *inbuf; + r = _wchar_utf8sntowcs(&wc, 1, &p, *inbytesleft, &px->fromstate, 0); + if (((ssize_t) r) <= 0) { /* either EILSEQ or incomplete or nul */ + if (((ssize_t) r) < 0) { /* either EILSEQ or incomplete or nul */ + assert((r == (size_t)(-1)) || (r == (size_t)(-2))); + if (r == (size_t)(-2)) { + INVALID: + __set_errno(EINVAL); + } else { + px->fromstate.__mask = 0; + inci = 1; + ILLEGAL: + if (px->skip_invalid_input) { + px->skip_invalid_input = 2; /* flag for iconv utility */ + goto BOM_SKIP_OUTPUT; + } + __set_errno(EILSEQ); + } + return (size_t)(-1); + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: optimize this. +#endif + if (p != NULL) { /* incomplete char case */ + goto INVALID; + } + p = *inbuf + 1; /* nul */ + } + inci = p - *inbuf; + } else if ((wc = ((unsigned char)(**inbuf))) >= 0x80) { /* Non-ASCII... */ + if (px->fromcodeset == IC_ASCII) { /* US-ASCII codeset */ + goto ILLEGAL; + } else { /* some other 8-bit ascii-extension codeset */ + const __codeset_8_bit_t *c8b + = __locale_mmap->codeset_8_bit + px->fromcodeset - 3; + wc -= 0x80; + wc = __UCLIBC_CURLOCALE_DATA.tbl8c2wc[ + (c8b->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (!wc) { + goto ILLEGAL; + } + } + } + + + if (px->tobom) { + inci = 0; + wc = 0xfeffU; + GOT_BOM: + px->tobom = 0; + } + + if (px->tocodeset >= IC_MULTIBYTE) { + inco = (px->tocodeset == IC_WCHAR_T) ? 4: (px->tocodeset & 6); + if (*outbytesleft < inco) goto TOO_BIG; + if (px->tocodeset != IC_WCHAR_T) { + if (((__uwchar_t) wc) > (((px->tocodeset & IC_UCS_4) == IC_UCS_4) + ? 0x7fffffffUL : 0x10ffffUL) +#ifdef KUHN + || (((__uwchar_t)(wc - 0xfffeU)) < 2) + || (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U)) +#endif + ) { + REPLACE_32: + wc = 0xfffd; + ++nrcount; + } + } + if (inco == 4) { + if (px->tocodeset & 1) wc = bswap_32(wc); + } else { + if (((__uwchar_t)wc ) > 0xffffU) { + if ((px->tocodeset & IC_UTF_16) != IC_UTF_16) { + goto REPLACE_32; + } + if (*outbytesleft < (inco = 4)) goto TOO_BIG; + wc2 = 0xdc00U + (wc & 0x3ff); + wc = 0xd800U + ((wc >> 10) & 0x3ff); + if (px->tocodeset & 1) { + wc = bswap_16(wc); + wc2 = bswap_16(wc2); + } + wc += (wc2 << 16); + } else if (px->tocodeset & 1) wc = bswap_16(wc); + } + (*outbuf)[0] = (char)((unsigned char)(wc)); + (*outbuf)[1] = (char)((unsigned char)(wc >> 8)); + if (inco == 4) { + (*outbuf)[2] = (char)((unsigned char)(wc >> 16)); + (*outbuf)[3] = (char)((unsigned char)(wc >> 24)); + } + } else if (px->tocodeset == IC_UTF_8) { + const wchar_t *pw = &wc; + do { + r = _wchar_wcsntoutf8s(*outbuf, *outbytesleft, &pw, 1); + if (r != (size_t)(-1)) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: What happens for a nul? +#endif + if (r == 0) { + if (wc != 0) { + goto TOO_BIG; + } + ++r; + } + break; + } + wc = 0xfffdU; + ++nrcount; + } while (1); + inco = r; + } else if (((__uwchar_t)(wc)) < 0x80) { + CHAR_GOOD: + **outbuf = wc; + } else { + if ((px->tocodeset != 0x01) && (wc <= Cwc2c_DOMAIN_MAX)) { + const __codeset_8_bit_t *c8b + = __locale_mmap->codeset_8_bit + px->tocodeset - 3; + __uwchar_t u; + u = c8b->idx8wc2c[wc >> (Cwc2c_TI_SHIFT + Cwc2c_TT_SHIFT)]; + u = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[(u << Cwc2c_TI_SHIFT) + + ((wc >> Cwc2c_TT_SHIFT) + & ((1 << Cwc2c_TI_SHIFT)-1))]; + wc = __UCLIBC_CURLOCALE_DATA.tbl8wc2c[Cwc2c_TI_LEN + + (u << Cwc2c_TT_SHIFT) + + (wc & ((1 << Cwc2c_TT_SHIFT)-1))]; + if (wc) { + goto CHAR_GOOD; + } + } + **outbuf = '?'; + ++nrcount; + } + + *outbuf += inco; + *outbytesleft -= inco; + BOM_SKIP_OUTPUT: + *inbuf += inci; + *inbytesleft -= inci; + } + return nrcount; +} + +#endif +/**********************************************************************/ +#ifdef L_iconv_main + +#include +#include +#include +#include + +extern const unsigned char __iconv_codesets[]; + +#define IBUF BUFSIZ +#define OBUF BUFSIZ + +char *progname; +int hide_errors; + +static void error_msg(const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 1, 2))); + +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + if (!hide_errors) { + fprintf(stderr, "%s: ", progname); + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + } + + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + FILE *ifile; + FILE *ofile = stdout; + const char *p; + const char *s; + static const char opt_chars[] = "tfocsl"; + /* 012345 */ + const char *opts[sizeof(opt_chars)]; /* last is infile name */ + iconv_t ic; + char ibuf[IBUF]; + char obuf[OBUF]; + char *pi; + char *po; + size_t ni, no, r, pos; + + hide_errors = 0; + + for (s = opt_chars ; *s ; s++) { + opts[ s - opt_chars ] = NULL; + } + + progname = *argv; + while (--argc) { + p = *++argv; + if ((*p != '-') || (*++p == 0)) { + break; + } + do { + if ((s = strchr(opt_chars,*p)) == NULL) { + USAGE: + s = basename(progname); + fprintf(stderr, + "%s [-cs] -f fromcode -t tocode [-o outputfile] [inputfile ...]\n" + " or\n%s -l\n", s, s); + return EXIT_FAILURE; + } + if ((s - opt_chars) < 3) { + if ((--argc == 0) || opts[s - opt_chars]) { + goto USAGE; + } + opts[s - opt_chars] = *++argv; + } else { + opts[s - opt_chars] = p; + } + } while (*++p); + } + + if (opts[5]) { /* -l */ + fprintf(stderr, "Recognized codesets:\n"); + for (s = __iconv_codesets ; *s ; s += *s) { + fprintf(stderr," %s\n", s+2); + } + s = __LOCALE_DATA_CODESET_LIST; + do { + fprintf(stderr," %s\n", __LOCALE_DATA_CODESET_LIST+ (unsigned char)(*s)); + } while (*++s); + + return EXIT_SUCCESS; + } + + if (opts[4]) { + hide_errors = 1; + } + + if (!opts[0] || !opts[1]) { + goto USAGE; + } + if ((ic = iconv_open(opts[0],opts[1])) == ((iconv_t)(-1))) { + error_msg( "unsupported codeset in %s -> %s conversion\n", opts[0], opts[1]); + } + if (opts[3]) { /* -c */ + ((_UC_iconv_t *) ic)->skip_invalid_input = 1; + } + + if ((s = opts[2]) != NULL) { + if (!(ofile = fopen(s, "w"))) { + error_msg( "couldn't open %s for writing\n", s); + } + } + + pos = ni = 0; + do { + if (!argc || ((**argv == '-') && !((*argv)[1]))) { + ifile = stdin; /* we don't check for duplicates */ + } else if (!(ifile = fopen(*argv, "r"))) { + error_msg( "couldn't open %s for reading\n", *argv); + } + + while ((r = fread(ibuf + ni, 1, IBUF - ni, ifile)) > 0) { + pos += r; + ni += r; + no = OBUF; + pi = ibuf; + po = obuf; + if ((r = iconv(ic, &pi, &ni, &po, &no)) == ((size_t)(-1))) { + if ((errno != EINVAL) && (errno != E2BIG)) { + error_msg( "iconv failed at pos %lu : %m\n", (unsigned long) (pos - ni)); + } + } + if ((r = OBUF - no) > 0) { + if (fwrite(obuf, 1, OBUF - no, ofile) < r) { + error_msg( "write error\n"); + } + } + if (ni) { /* still bytes in buffer! */ + memmove(ibuf, pi, ni); + } + } + + if (ferror(ifile)) { + error_msg( "read error\n"); + } + + ++argv; + + if (ifile != stdin) { + fclose(ifile); + } + + } while (--argc > 0); + + iconv_close(ic); + + if (ni) { + error_msg( "incomplete sequence\n"); + } + + return (((_UC_iconv_t *) ic)->skip_invalid_input < 2) + ? EXIT_SUCCESS : EXIT_FAILURE; +} + +#endif +/**********************************************************************/ diff --git a/libc/misc/wchar/wcrtomb.c b/libc/misc/wchar/wcrtomb.c new file mode 100644 index 0000000..91eb306 --- /dev/null +++ b/libc/misc/wchar/wcrtomb.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcrtomb +#include "wchar.c" diff --git a/libc/misc/wchar/wcsnrtombs.c b/libc/misc/wchar/wcsnrtombs.c new file mode 100644 index 0000000..af9d6c3 --- /dev/null +++ b/libc/misc/wchar/wcsnrtombs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsnrtombs +#include "wchar.c" diff --git a/libc/misc/wchar/wcsrtombs.c b/libc/misc/wchar/wcsrtombs.c new file mode 100644 index 0000000..e5b6c0b --- /dev/null +++ b/libc/misc/wchar/wcsrtombs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsrtombs +#include "wchar.c" diff --git a/libc/misc/wchar/wcswidth.c b/libc/misc/wchar/wcswidth.c new file mode 100644 index 0000000..3d955a2 --- /dev/null +++ b/libc/misc/wchar/wcswidth.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcswidth +#include "wchar.c" diff --git a/libc/misc/wchar/wctob.c b/libc/misc/wchar/wctob.c new file mode 100644 index 0000000..88d31f5 --- /dev/null +++ b/libc/misc/wchar/wctob.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctob +#include "wchar.c" diff --git a/libc/misc/wchar/wcwidth.c b/libc/misc/wchar/wcwidth.c new file mode 100644 index 0000000..6c4a344 --- /dev/null +++ b/libc/misc/wchar/wcwidth.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcwidth +#include "wchar.c" diff --git a/libc/misc/wctype/Makefile b/libc/misc/wctype/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/wctype/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/wctype/Makefile.in b/libc/misc/wctype/Makefile.in new file mode 100644 index 0000000..e62c731 --- /dev/null +++ b/libc/misc/wctype/Makefile.in @@ -0,0 +1,34 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# multi source _wctype.c +COM_SRC := \ + iswalnum.c iswalpha.c iswcntrl.c iswdigit.c iswgraph.c \ + iswlower.c iswprint.c iswpunct.c iswspace.c iswupper.c \ + iswxdigit.c iswblank.c wctrans.c towctrans.c \ + wctype.c iswctype.c towlower.c towupper.c + +CSRC := +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += $(COM_SRC) +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += $(patsubst %.c,%_l.c,$(COM_SRC)) +endif + +MISC_WCTYPE_DIR := $(top_srcdir)libc/misc/wctype +MISC_WCTYPE_OUT := $(top_builddir)libc/misc/wctype + +MISC_WCTYPE_SRC := $(patsubst %.c,$(MISC_WCTYPE_DIR)/%.c,$(CSRC)) +MISC_WCTYPE_OBJ := $(patsubst %.c,$(MISC_WCTYPE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_WCTYPE_OBJ) + +objclean-y += misc_wctype_clean + +misc_wctype_clean: + $(do_rm) $(addprefix $(MISC_WCTYPE_OUT)/*., o os) diff --git a/libc/misc/wctype/_wctype.c b/libc/misc/wctype/_wctype.c new file mode 100644 index 0000000..25419b5 --- /dev/null +++ b/libc/misc/wctype/_wctype.c @@ -0,0 +1,947 @@ +/* Copyright (C) 2002, 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#define __NO_CTYPE + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +libc_hidden_proto(tolower) +libc_hidden_proto(toupper) +libc_hidden_proto(towlower) +libc_hidden_proto(towupper) +libc_hidden_proto(towctrans) +libc_hidden_proto(iswctype) + +#if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE) +#error xlocale functionality is not supported in stub locale mode. +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +libc_hidden_proto(towlower_l) +libc_hidden_proto(towupper_l) +libc_hidden_proto(towctrans_l) +libc_hidden_proto(iswctype_l) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__C_ctype_tolower) +libc_hidden_proto(__C_ctype_toupper) +#endif + +/* We know wide char support is enabled. We wouldn't be here otherwise. */ + +/* Define this if you want to unify the towupper and towlower code in the + * towctrans function. */ +/* #define SMALL_UPLOW */ + +/**********************************************************************/ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix the __CTYPE_* codes! +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#if 1 +/* Taking advantage of the C99 mutual-exclusion guarantees for the various + * (w)ctype classes, including the descriptions of printing and control + * (w)chars, we can place each in one of the following mutually-exlusive + * subsets. Since there are less than 16, we can store the data for + * each (w)chars in a nibble. In contrast, glibc uses an unsigned int + * per (w)char, with one bit flag for each is* type. While this allows + * a simple '&' operation to determine the type vs. a range test and a + * little special handling for the "blank" and "xdigit" types in my + * approach, it also uses 8 times the space for the tables on the typical + * 32-bit archs we supported.*/ +enum { + __CTYPE_unclassified = 0, + __CTYPE_alpha_nonupper_nonlower, + __CTYPE_alpha_lower, + __CTYPE_alpha_upper_lower, + __CTYPE_alpha_upper, + __CTYPE_digit, + __CTYPE_punct, + __CTYPE_graph, + __CTYPE_print_space_nonblank, + __CTYPE_print_space_blank, + __CTYPE_space_nonblank_noncntrl, + __CTYPE_space_blank_noncntrl, + __CTYPE_cntrl_space_nonblank, + __CTYPE_cntrl_space_blank, + __CTYPE_cntrl_nonspace +}; +#endif + + +/* The following is used to implement wctype(), but it is defined + * here because the ordering must agree with that of the enumeration + * below (ignoring unclassified). */ +#define __CTYPE_TYPESTRING \ + "\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \ + "\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0" + + +/* The values for wctype_t. */ +enum { + _CTYPE_unclassified = 0, + _CTYPE_isalnum, + _CTYPE_isalpha, + _CTYPE_isblank, + _CTYPE_iscntrl, + _CTYPE_isdigit, + _CTYPE_isgraph, + _CTYPE_islower, + _CTYPE_isprint, + _CTYPE_ispunct, + _CTYPE_isspace, + _CTYPE_isupper, + _CTYPE_isxdigit /* _MUST_ be last of the standard classes! */ +}; + +/* The following is used to implement wctrans(). */ + +#define __CTYPE_TRANSTRING "\10tolower\0\10toupper\0\10totitle\0\0" + +enum { + _CTYPE_tolower = 1, + _CTYPE_toupper, + _CTYPE_totitle +}; + +/*--------------------------------------------------------------------*/ + +#define _CTYPE_iswxdigit (_CTYPE_isxdigit) + +/*--------------------------------------------------------------------*/ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix WC* defines! +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding) + +#define WCctype ((__UCLIBC_CURLOCALE_DATA).tblwctype) +#define WCuplow ((__UCLIBC_CURLOCALE_DATA).tblwuplow) +#define WCcmob ((__UCLIBC_CURLOCALE_DATA).tblwcomb) +#define WCuplow_diff ((__UCLIBC_CURLOCALE_DATA).tblwuplow_diff) + + +#define WC_TABLE_DOMAIN_MAX __LOCALE_DATA_WC_TABLE_DOMAIN_MAX + +#define WCctype_II_LEN __LOCALE_DATA_WCctype_II_LEN +#define WCctype_TI_LEN __LOCALE_DATA_WCctype_TI_LEN +#define WCctype_UT_LEN __LOCALE_DATA_WCctype_UT_LEN +#define WCctype_II_SHIFT __LOCALE_DATA_WCctype_II_SHIFT +#define WCctype_TI_SHIFT __LOCALE_DATA_WCctype_TI_SHIFT + +#define WCuplow_II_LEN __LOCALE_DATA_WCuplow_II_LEN +#define WCuplow_TI_LEN __LOCALE_DATA_WCuplow_TI_LEN +#define WCuplow_UT_LEN __LOCALE_DATA_WCuplow_UT_LEN +#define WCuplow_II_SHIFT __LOCALE_DATA_WCuplow_II_SHIFT +#define WCuplow_TI_SHIFT __LOCALE_DATA_WCuplow_TI_SHIFT + + +#define WCctype_TI_MASK ((1 << (WCctype_TI_SHIFT)) - 1) +#define WCctype_II_MASK ((1 << (WCctype_II_SHIFT)) - 1) + +/**********************************************************************/ + +#undef __PASTE2 +#undef __PASTE3 +#define __PASTE2(X,Y) X ## Y +#define __PASTE3(X,Y,Z) X ## Y ## Z + +#ifdef __UCLIBC_DO_XLOCALE + +#define ISW_FUNC_BODY(NAME) \ +libc_hidden_proto(__PASTE3(isw,NAME,_l)); \ +int __PASTE3(isw,NAME,_l) (wint_t wc, __locale_t l) \ +{ \ + return iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \ +} \ +libc_hidden_def(__PASTE3(isw,NAME,_l)) + +#else /* __UCLIBC_DO_XLOCALE */ + +#define ISW_FUNC_BODY(NAME) \ +libc_hidden_proto(__PASTE2(isw,NAME)); \ +int __PASTE2(isw,NAME) (wint_t wc) \ +{ \ + return iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \ +} \ +libc_hidden_def(__PASTE2(isw,NAME)) + +#endif /* __UCLIBC_DO_XLOCALE */ +/**********************************************************************/ +#if defined(L_iswalnum) || defined(L_iswalnum_l) + +ISW_FUNC_BODY(alnum); + +#endif +/**********************************************************************/ +#if defined(L_iswalpha) || defined(L_iswalpha_l) + +ISW_FUNC_BODY(alpha); + +#endif +/**********************************************************************/ +#if defined(L_iswblank) || defined(L_iswblank_l) + +ISW_FUNC_BODY(blank); + +#endif +/**********************************************************************/ +#if defined(L_iswcntrl) || defined(L_iswcntrl_l) + +ISW_FUNC_BODY(cntrl); + +#endif +/**********************************************************************/ +#if defined(L_iswdigit) || defined(L_iswdigit_l) + +ISW_FUNC_BODY(digit); + +#endif +/**********************************************************************/ +#if defined(L_iswgraph) || defined(L_iswgraph_l) + +ISW_FUNC_BODY(graph); + +#endif +/**********************************************************************/ +#if defined(L_iswlower) || defined(L_iswlower_l) + +ISW_FUNC_BODY(lower); + +#endif +/**********************************************************************/ +#if defined(L_iswprint) || defined(L_iswprint_l) + +ISW_FUNC_BODY(print); + +#endif +/**********************************************************************/ +#if defined(L_iswpunct) || defined(L_iswpunct_l) + +ISW_FUNC_BODY(punct); + +#endif +/**********************************************************************/ +#if defined(L_iswspace) || defined(L_iswspace_l) + +ISW_FUNC_BODY(space); + +#endif +/**********************************************************************/ +#if defined(L_iswupper) || defined(L_iswupper_l) + +ISW_FUNC_BODY(upper); + +#endif +/**********************************************************************/ +#if defined(L_iswxdigit) || defined(L_iswxdigit_l) + +ISW_FUNC_BODY(xdigit); + +#endif +/**********************************************************************/ +#if defined(L_towlower) || defined(L_towlower_l) + +#ifdef L_towlower +#define TOWLOWER(w) towlower(w) +#else /* L_towlower */ +#define TOWLOWER(w) towlower_l(w, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towlower */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWCTRANS(w,d) towctrans(w,d) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#define __C_towlower(wc) \ + ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc)) + +#ifdef __LOCALE_C_ONLY + +wint_t towlower(wint_t wc) +{ +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + return __C_towlower(wc); +#else + return (wc == ((unsigned int)(wc))) + ? __C_tolower(((unsigned int)(wc))) + : 0; +#endif +} + +#else /* __LOCALE_C_ONLY */ + +#ifdef SMALL_UPLOW + +#if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towlower(wint_t wc) +{ + return towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWLOWER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_tolower); +} + +#endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#else /* SMALL_UPLOW */ + +#if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towlower(wint_t wc) +{ + return towlower_l(wc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWLOWER(wint_t wc) +{ + unsigned int sc, n, i; + __uwchar_t u = wc; + + if (ENCODING == __ctype_encoding_7_bit) { + /* We're in the C/POSIX locale, so ignore the tables. */ + return __C_towlower(wc); + } + + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n]) + << WCuplow_TI_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + + i + sc]) << 1; + wc += WCuplow_diff[i + 1]; + } + return wc; +} + +#endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#endif /* SMALL_UPLOW */ + +#ifdef L_towlower_l +libc_hidden_def(towlower_l) +#endif /* L_towlower_l */ + +#endif /* __LOCALE_C_ONLY */ + +#ifndef L_towlower_l +libc_hidden_def(towlower) +#endif + +#endif +/**********************************************************************/ +#if defined(L_towupper) || defined(L_towupper_l) + +#ifdef L_towupper +#define TOWUPPER(w) towupper(w) +#else /* L_towupper */ +#define TOWUPPER(w) towupper_l(w, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towupper */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWCTRANS(w,d) towctrans(w,d) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#define __C_towupper(wc) \ + ((((__uwchar_t)(wc)) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc)) + +#ifdef __LOCALE_C_ONLY + +wint_t towupper(wint_t wc) +{ +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + return __C_towupper(wc); +#else + return (wc == ((unsigned int)(wc))) + ? __C_toupper(((unsigned int)(wc))) + : 0; +#endif + +} + +#else /* __LOCALE_C_ONLY */ + +#ifdef SMALL_UPLOW + +#if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towupper(wint_t wc) +{ + return towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWUPPER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_toupper); +} + +#endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#else /* SMALL_UPLOW */ + +#if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towupper(wint_t wc) +{ + return towupper_l(wc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWUPPER(wint_t wc) +{ + unsigned int sc, n, i; + __uwchar_t u = wc; + + if (ENCODING == __ctype_encoding_7_bit) { + /* We're in the C/POSIX locale, so ignore the tables. */ + return __C_towupper(wc); + } + + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n]) + << WCuplow_TI_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + + i + sc]) << 1; + wc += WCuplow_diff[i]; + } + return wc; +} + +#endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#endif /* SMALL_UPLOW */ + +#ifdef L_towupper_l +libc_hidden_def(towupper_l) +#endif /* L_towupper_l */ + +#endif /* __LOCALE_C_ONLY */ + +#ifndef L_towupper_l +libc_hidden_def(towupper) +#endif + +#endif +/**********************************************************************/ +#ifdef L_wctype + +static const unsigned char typestring[] = __CTYPE_TYPESTRING; +/* extern const unsigned char typestring[]; */ + +libc_hidden_proto(wctype) +wctype_t wctype(const char *property) +{ + const unsigned char *p; + int i; + + p = typestring; + i = 1; + do { + if (!strcmp(property, ++p)) { + return i; + } + ++i; + p += p[-1]; + } while (*p); + + /* TODO - Add locale-specific classifications. */ + return 0; +} +libc_hidden_def(wctype) + +#endif +/**********************************************************************/ +#ifdef L_wctype_l + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Currently wctype_l simply calls wctype. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +libc_hidden_proto(wctype) + +libc_hidden_proto(wctype_l) +wctype_t wctype_l (const char *property, __locale_t locale) +{ + return wctype(property); +} +libc_hidden_def(wctype_l) + +#endif +/**********************************************************************/ +#if defined(L_iswctype) || defined(L_iswctype_l) + +#define __C_iswdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((__uwchar_t)((c) - '0')) < 10)) +#define __C_iswxdigit(c) \ + (__C_iswdigit(c) \ + || ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \ + : (((__uwchar_t)((((c)) | 0x20) - 'a')) < 6))) + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswctype +#warning CONSIDER: Change to bit shift? would need to sync with wctype.h +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ +#if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l) + +static const unsigned short int desc2flag[] = { + [_CTYPE_unclassified] = 0, + [_CTYPE_isalnum] = (unsigned short int) _ISwalnum, + [_CTYPE_isalpha] = (unsigned short int) _ISwalpha, + [_CTYPE_isblank] = (unsigned short int) _ISwblank, + [_CTYPE_iscntrl] = (unsigned short int) _ISwcntrl, + [_CTYPE_isdigit] = (unsigned short int) _ISwdigit, + [_CTYPE_isgraph] = (unsigned short int) _ISwgraph, + [_CTYPE_islower] = (unsigned short int) _ISwlower, + [_CTYPE_isprint] = (unsigned short int) _ISwprint, + [_CTYPE_ispunct] = (unsigned short int) _ISwpunct, + [_CTYPE_isspace] = (unsigned short int) _ISwspace, + [_CTYPE_isupper] = (unsigned short int) _ISwupper, + [_CTYPE_isxdigit] = (unsigned short int) _ISwxdigit, +}; + +#endif /* defined(L_iswctype_L) || defined(__LOCALE_C_ONLY) */ +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#ifdef __LOCALE_C_ONLY + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int iswctype(wint_t wc, wctype_t desc) +{ + /* Note... wctype_t is unsigned. */ + + if ((((__uwchar_t) wc) <= 0x7f) + && (desc < (sizeof(desc2flag)/sizeof(desc2flag[0]))) + ) { + return __isctype(wc, desc2flag[desc]); + } + return 0; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int iswctype(wint_t wc, wctype_t desc) +{ + /* This is lame, but it is here just to get it working for now. */ + + if (wc == ((unsigned int)(wc))) { + switch(desc) { + case _CTYPE_isupper: + return __C_isupper((unsigned int)(wc)); + case _CTYPE_islower: + return __C_islower((unsigned int)(wc)); + case _CTYPE_isalpha: + return __C_isalpha((unsigned int)(wc)); + case _CTYPE_isdigit: + return __C_isdigit((unsigned int)(wc)); + case _CTYPE_isxdigit: + return __C_isxdigit((unsigned int)(wc)); + case _CTYPE_isspace: + return __C_isspace((unsigned int)(wc)); + case _CTYPE_isprint: + return __C_isprint((unsigned int)(wc)); + case _CTYPE_isgraph: + return __C_isgraph((unsigned int)(wc)); + case _CTYPE_isblank: + return __C_isblank((unsigned int)(wc)); + case _CTYPE_iscntrl: + return __C_iscntrl((unsigned int)(wc)); + case _CTYPE_ispunct: + return __C_ispunct((unsigned int)(wc)); + case _CTYPE_isalnum: + return __C_isalnum((unsigned int)(wc)); + default: + break; + } + } + return 0; +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswctype +#warning CONSIDER: Handle combining class? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef L_iswctype +#define ISWCTYPE(w,d) iswctype(w,d) +#else /* L_iswctype */ +#define ISWCTYPE(w,d) iswctype_l(w,d, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_iswctype */ + +#if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) + +int iswctype(wint_t wc, wctype_t desc) +{ + return iswctype_l(wc, desc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ + +int ISWCTYPE(wint_t wc, wctype_t desc) +{ + unsigned int sc, n, i0, i1; + unsigned char d = __CTYPE_unclassified; + + if ((ENCODING != __ctype_encoding_7_bit) || (((__uwchar_t) wc) <= 0x7f)){ + if (desc < _CTYPE_iswxdigit) { + if (((__uwchar_t) wc) <= WC_TABLE_DOMAIN_MAX) { + /* From here on, we know wc > 0. */ + sc = wc & WCctype_TI_MASK; + wc >>= WCctype_TI_SHIFT; + n = wc & WCctype_II_MASK; + wc >>= WCctype_II_SHIFT; + + i0 = WCctype[wc]; + i0 <<= WCctype_II_SHIFT; + i1 = WCctype[WCctype_II_LEN + i0 + n]; + i1 <<= (WCctype_TI_SHIFT-1); + d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)]; + + d = (sc & 1) ? (d >> 4) : (d & 0xf); + } else if ( ((((__uwchar_t)(wc - 0xe0020UL)) <= 0x5f) + || (wc == 0xe0001UL)) + || ( (((__uwchar_t)(wc - 0xf0000UL)) < 0x20000UL) + && ((wc & 0xffffU) <= 0xfffdU)) + ) { + d = __CTYPE_punct; + } + +#if 0 + return ( ((unsigned char)(d - ctype_range[2*desc])) + <= ctype_range[2*desc + 1] ) + && ((desc != _CTYPE_iswblank) || (d & 1)); +#else + return (__UCLIBC_CURLOCALE_DATA).code2flag[d] & desc2flag[desc]; +#endif + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: xdigit really needs to be handled better. Remember only for ascii! +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* TODO - Add locale-specific classifications. */ + return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0; + } + return 0; +} + +#endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef L_iswctype_l +libc_hidden_def(iswctype_l) +#endif /* L_iswctype_l */ + +#endif /* __LOCALE_C_ONLY */ + +#ifdef L_iswctype +libc_hidden_def(iswctype) +#endif /* L_iswctype */ + +#endif +/**********************************************************************/ +#if defined(L_towctrans) || defined(L_towctrans_l) + +#ifdef __LOCALE_C_ONLY + +/* Minimal support for C/POSIX locale. */ + +#ifndef _tolower +#warning _tolower is undefined! +#define _tolower(c) tolower(c) +#endif +#ifndef _toupper +#warning _toupper is undefined! +#define _toupper(c) toupper(c) +#endif + +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + if (((unsigned int)(desc - _CTYPE_tolower)) + <= (_CTYPE_toupper - _CTYPE_tolower) + ) { + /* Transliteration is either tolower or toupper. */ + if (((__uwchar_t) wc) <= 0x7f) { + return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc); + } + } else { + __set_errno(EINVAL); /* Invalid transliteration. */ + } + return wc; +} + +#else /* __LOCALE_C_ONLY */ + +#ifdef L_towctrans +#define TOWCTRANS(w,d) towctrans(w,d) +#else /* L_towctrans */ +#define TOWCTRANS(w,d) towctrans_l(w,d, __locale_t locale) +#undef __UCLIBC_CURLOCALE_DATA +#undef __UCLIBC_CURLOCALE +#define __UCLIBC_CURLOCALE_DATA (*locale) +#define __UCLIBC_CURLOCALE (locale) +#endif /* L_towctrans */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define TOWLOWER(w,l) towlower_l(w,l) +#define TOWUPPER(w,l) towupper_l(w,l) +#else /* __UCLIBC_HAS_XLOCALE__ */ +#define TOWLOWER(w,l) towlower(w) +#define TOWUPPER(w,l) towupper(w) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef SMALL_UPLOW + +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) +{ + unsigned int sc, n, i; + __uwchar_t u = wc; + + /* TODO - clean up */ + if (ENCODING == __ctype_encoding_7_bit) { + if ((((__uwchar_t) wc) > 0x7f) + || (((unsigned int)(desc - _CTYPE_tolower)) + > (_CTYPE_toupper - _CTYPE_tolower)) + ){ + /* We're in the C/POSIX locale, so ignore non-ASCII values + * as well an any mappings other than toupper or tolower. */ + return wc; + } + } + + if (((unsigned int)(desc - _CTYPE_tolower)) + <= (_CTYPE_totitle - _CTYPE_tolower) + ) { + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n]) + << WCuplow_TI_SHIFT; + i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + + i + sc]) << 1; + if (desc == _CTYPE_tolower) { + ++i; + } + wc += WCuplow_diff[i]; + if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify totitle special cases! +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* WARNING! These special cases work for glibc 2.2.4. Changes + * may be needed if the glibc locale tables are updated. */ + if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4)) + || (wc == 0x1f1) + ) { + ++wc; + } + } + } + } else { + /* TODO - Deal with other transliterations. */ + __set_errno(EINVAL); + } + + return wc; +} + +#else /* SMALL_UPLOW */ + +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) +{ + if (ENCODING == __ctype_encoding_7_bit) { + if ((((__uwchar_t) wc) > 0x7f) + || (((unsigned int)(desc - _CTYPE_tolower)) + > (_CTYPE_toupper - _CTYPE_tolower)) + ){ + /* We're in the C/POSIX locale, so ignore non-ASCII values + * as well an any mappings other than toupper or tolower. */ + return wc; + } + } + + if (desc == _CTYPE_tolower) { + return TOWLOWER(wc, __UCLIBC_CURLOCALE); + } else if (((unsigned int)(desc - _CTYPE_toupper)) + <= (_CTYPE_totitle - _CTYPE_toupper) + ) { + wc = TOWUPPER(wc, __UCLIBC_CURLOCALE); + if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify totitle special cases! +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* WARNING! These special cases work for glibc 2.2.4. Changes + * may be needed if the glibc locale tables are updated. */ + if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4)) + || (wc == 0x1f1) + ) { + ++wc; + } + } + } else { + /* TODO - Deal with other transliterations. */ + __set_errno(EINVAL); + } + return wc; +} + +#endif /* SMALL_UPLOW */ + +#endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef L_towctrans_l +libc_hidden_def(towctrans_l) +#endif /* L_towctrans_l */ + +#endif /* __LOCALE_C_ONLY */ + +#ifndef L_towctrans_l +libc_hidden_def(towctrans) +#endif + +#endif +/**********************************************************************/ +#ifdef L_wctrans + +static const char transstring[] = __CTYPE_TRANSTRING; + +libc_hidden_proto(wctrans) +wctrans_t wctrans(const char *property) +{ + const unsigned char *p; + int i; + + p = transstring; + i = 1; + do { + if (!strcmp(property, ++p)) { + return i; + } + ++i; + p += p[-1]; + } while (*p); + + /* TODO - Add locale-specific translations. */ + return 0; +} +libc_hidden_def(wctrans) + +#endif +/**********************************************************************/ +#ifdef L_wctrans_l + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Currently wctrans_l simply calls wctrans. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +libc_hidden_proto(wctrans) + +wctrans_t wctrans_l(const char *property, __locale_t locale) +{ + return wctrans(property); +} + +#endif +/**********************************************************************/ diff --git a/libc/misc/wctype/iswalnum.c b/libc/misc/wctype/iswalnum.c new file mode 100644 index 0000000..a85a03d --- /dev/null +++ b/libc/misc/wctype/iswalnum.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalnum +#include "_wctype.c" diff --git a/libc/misc/wctype/iswalnum_l.c b/libc/misc/wctype/iswalnum_l.c new file mode 100644 index 0000000..6e3cd77 --- /dev/null +++ b/libc/misc/wctype/iswalnum_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalnum_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswalpha.c b/libc/misc/wctype/iswalpha.c new file mode 100644 index 0000000..6b829eb --- /dev/null +++ b/libc/misc/wctype/iswalpha.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalpha +#include "_wctype.c" diff --git a/libc/misc/wctype/iswalpha_l.c b/libc/misc/wctype/iswalpha_l.c new file mode 100644 index 0000000..79b11cf --- /dev/null +++ b/libc/misc/wctype/iswalpha_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalpha_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswblank.c b/libc/misc/wctype/iswblank.c new file mode 100644 index 0000000..67862d5 --- /dev/null +++ b/libc/misc/wctype/iswblank.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswblank +#include "_wctype.c" diff --git a/libc/misc/wctype/iswblank_l.c b/libc/misc/wctype/iswblank_l.c new file mode 100644 index 0000000..4c5709c --- /dev/null +++ b/libc/misc/wctype/iswblank_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswblank_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswcntrl.c b/libc/misc/wctype/iswcntrl.c new file mode 100644 index 0000000..50d72b4 --- /dev/null +++ b/libc/misc/wctype/iswcntrl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswcntrl +#include "_wctype.c" diff --git a/libc/misc/wctype/iswcntrl_l.c b/libc/misc/wctype/iswcntrl_l.c new file mode 100644 index 0000000..2fe64d7 --- /dev/null +++ b/libc/misc/wctype/iswcntrl_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswcntrl_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswctype.c b/libc/misc/wctype/iswctype.c new file mode 100644 index 0000000..777d410 --- /dev/null +++ b/libc/misc/wctype/iswctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswctype +#include "_wctype.c" diff --git a/libc/misc/wctype/iswctype_l.c b/libc/misc/wctype/iswctype_l.c new file mode 100644 index 0000000..71bce18 --- /dev/null +++ b/libc/misc/wctype/iswctype_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswctype_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswdigit.c b/libc/misc/wctype/iswdigit.c new file mode 100644 index 0000000..b2aa5d0 --- /dev/null +++ b/libc/misc/wctype/iswdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswdigit +#include "_wctype.c" diff --git a/libc/misc/wctype/iswdigit_l.c b/libc/misc/wctype/iswdigit_l.c new file mode 100644 index 0000000..4832c9c --- /dev/null +++ b/libc/misc/wctype/iswdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswdigit_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswgraph.c b/libc/misc/wctype/iswgraph.c new file mode 100644 index 0000000..8113054 --- /dev/null +++ b/libc/misc/wctype/iswgraph.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswgraph +#include "_wctype.c" diff --git a/libc/misc/wctype/iswgraph_l.c b/libc/misc/wctype/iswgraph_l.c new file mode 100644 index 0000000..db68315 --- /dev/null +++ b/libc/misc/wctype/iswgraph_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswgraph_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswlower.c b/libc/misc/wctype/iswlower.c new file mode 100644 index 0000000..016d8cc --- /dev/null +++ b/libc/misc/wctype/iswlower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswlower +#include "_wctype.c" diff --git a/libc/misc/wctype/iswlower_l.c b/libc/misc/wctype/iswlower_l.c new file mode 100644 index 0000000..5b9f821 --- /dev/null +++ b/libc/misc/wctype/iswlower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswlower_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswprint.c b/libc/misc/wctype/iswprint.c new file mode 100644 index 0000000..8e47e88 --- /dev/null +++ b/libc/misc/wctype/iswprint.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswprint +#include "_wctype.c" diff --git a/libc/misc/wctype/iswprint_l.c b/libc/misc/wctype/iswprint_l.c new file mode 100644 index 0000000..148414c --- /dev/null +++ b/libc/misc/wctype/iswprint_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswprint_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswpunct.c b/libc/misc/wctype/iswpunct.c new file mode 100644 index 0000000..1175e1a --- /dev/null +++ b/libc/misc/wctype/iswpunct.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswpunct +#include "_wctype.c" diff --git a/libc/misc/wctype/iswpunct_l.c b/libc/misc/wctype/iswpunct_l.c new file mode 100644 index 0000000..a6d3616 --- /dev/null +++ b/libc/misc/wctype/iswpunct_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswpunct_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswspace.c b/libc/misc/wctype/iswspace.c new file mode 100644 index 0000000..603f5cf --- /dev/null +++ b/libc/misc/wctype/iswspace.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswspace +#include "_wctype.c" diff --git a/libc/misc/wctype/iswspace_l.c b/libc/misc/wctype/iswspace_l.c new file mode 100644 index 0000000..e389f89 --- /dev/null +++ b/libc/misc/wctype/iswspace_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswspace_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswupper.c b/libc/misc/wctype/iswupper.c new file mode 100644 index 0000000..4cfdebb --- /dev/null +++ b/libc/misc/wctype/iswupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswupper +#include "_wctype.c" diff --git a/libc/misc/wctype/iswupper_l.c b/libc/misc/wctype/iswupper_l.c new file mode 100644 index 0000000..359aef9 --- /dev/null +++ b/libc/misc/wctype/iswupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswupper_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/iswxdigit.c b/libc/misc/wctype/iswxdigit.c new file mode 100644 index 0000000..568f253 --- /dev/null +++ b/libc/misc/wctype/iswxdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswxdigit +#include "_wctype.c" diff --git a/libc/misc/wctype/iswxdigit_l.c b/libc/misc/wctype/iswxdigit_l.c new file mode 100644 index 0000000..1d543ab --- /dev/null +++ b/libc/misc/wctype/iswxdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswxdigit_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/towctrans.c b/libc/misc/wctype/towctrans.c new file mode 100644 index 0000000..9ad0468 --- /dev/null +++ b/libc/misc/wctype/towctrans.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towctrans +#include "_wctype.c" diff --git a/libc/misc/wctype/towctrans_l.c b/libc/misc/wctype/towctrans_l.c new file mode 100644 index 0000000..e179b50 --- /dev/null +++ b/libc/misc/wctype/towctrans_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towctrans_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/towlower.c b/libc/misc/wctype/towlower.c new file mode 100644 index 0000000..dffbff3 --- /dev/null +++ b/libc/misc/wctype/towlower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towlower +#include "_wctype.c" diff --git a/libc/misc/wctype/towlower_l.c b/libc/misc/wctype/towlower_l.c new file mode 100644 index 0000000..f1aa7e6 --- /dev/null +++ b/libc/misc/wctype/towlower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towlower_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/towupper.c b/libc/misc/wctype/towupper.c new file mode 100644 index 0000000..1dab8fe --- /dev/null +++ b/libc/misc/wctype/towupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towupper +#include "_wctype.c" diff --git a/libc/misc/wctype/towupper_l.c b/libc/misc/wctype/towupper_l.c new file mode 100644 index 0000000..cf05d5c --- /dev/null +++ b/libc/misc/wctype/towupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towupper_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/wctrans.c b/libc/misc/wctype/wctrans.c new file mode 100644 index 0000000..f99d9cd --- /dev/null +++ b/libc/misc/wctype/wctrans.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctrans +#include "_wctype.c" diff --git a/libc/misc/wctype/wctrans_l.c b/libc/misc/wctype/wctrans_l.c new file mode 100644 index 0000000..79854c2 --- /dev/null +++ b/libc/misc/wctype/wctrans_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctrans_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wctype/wctype.c b/libc/misc/wctype/wctype.c new file mode 100644 index 0000000..0dc1e6d --- /dev/null +++ b/libc/misc/wctype/wctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctype +#include "_wctype.c" diff --git a/libc/misc/wctype/wctype_l.c b/libc/misc/wctype/wctype_l.c new file mode 100644 index 0000000..65f82e2 --- /dev/null +++ b/libc/misc/wctype/wctype_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctype_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/libc/misc/wordexp/Makefile b/libc/misc/wordexp/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/misc/wordexp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/misc/wordexp/Makefile.in b/libc/misc/wordexp/Makefile.in new file mode 100644 index 0000000..262f039 --- /dev/null +++ b/libc/misc/wordexp/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := wordexp.c + +MISC_WORDEXP_DIR := $(top_srcdir)libc/misc/wordexp +MISC_WORDEXP_OUT := $(top_builddir)libc/misc/wordexp + +MISC_WORDEXP_SRC := $(patsubst %.c,$(MISC_WORDEXP_DIR)/%.c,$(CSRC)) +MISC_WORDEXP_OBJ := $(patsubst %.c,$(MISC_WORDEXP_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_WORDEXP) += $(MISC_WORDEXP_OBJ) + +objclean-y += misc_wordexp_clean + +misc_wordexp_clean: + $(do_rm) $(addprefix $(MISC_WORDEXP_OUT)/*., o os) diff --git a/libc/misc/wordexp/wordexp.c b/libc/misc/wordexp/wordexp.c new file mode 100644 index 0000000..d8b2db1 --- /dev/null +++ b/libc/misc/wordexp/wordexp.c @@ -0,0 +1,2275 @@ +/* vi: set sw=4 ts=4: */ +/* POSIX.2 wordexp implementation. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tim Waugh . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(mempcpy) */ +/* Experimentally off - libc_hidden_proto(stpcpy) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strndup) */ +/* Experimentally off - libc_hidden_proto(strspn) */ +/* Experimentally off - libc_hidden_proto(strcspn) */ +libc_hidden_proto(setenv) +libc_hidden_proto(unsetenv) +libc_hidden_proto(waitpid) +libc_hidden_proto(kill) +libc_hidden_proto(getuid) +libc_hidden_proto(getpwnam_r) +libc_hidden_proto(getpwuid_r) +libc_hidden_proto(execve) +libc_hidden_proto(dup2) +libc_hidden_proto(atoi) +libc_hidden_proto(fnmatch) +libc_hidden_proto(pipe) +libc_hidden_proto(fork) +libc_hidden_proto(open) +libc_hidden_proto(close) +libc_hidden_proto(read) +libc_hidden_proto(getenv) +libc_hidden_proto(getpid) +libc_hidden_proto(sprintf) +libc_hidden_proto(fprintf) +libc_hidden_proto(abort) +libc_hidden_proto(glob) +libc_hidden_proto(globfree) +libc_hidden_proto(wordfree) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +#define __WORDEXP_FULL +//#undef __WORDEXP_FULL + +/* + * This is a recursive-descent-style word expansion routine. + */ + +/* These variables are defined and initialized in the startup code. */ +//extern int __libc_argc; +//extern char **__libc_argv; + +/* FIXME!!!! */ +int attribute_hidden __libc_argc; +char attribute_hidden **__libc_argv; + +/* Some forward declarations */ +static int parse_dollars(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white, + int quoted); +static int parse_backtick(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white); +static int parse_dquote(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white); + + + +/* The w_*() functions manipulate word lists. */ +#define W_CHUNK (100) + +/* Result of w_newword will be ignored if it's the last word. */ +static __inline__ char *w_newword(size_t * actlen, size_t * maxlen) +{ + *actlen = *maxlen = 0; + return NULL; +} + +/* Add a character to the buffer, allocating room for it if needed. */ +static __inline__ char *w_addchar(char *buffer, size_t * actlen, + size_t * maxlen, char ch) + /* (lengths exclude trailing zero) */ +{ + + if (*actlen == *maxlen) { + char *old_buffer = buffer; + assert(buffer == NULL || *maxlen != 0); + *maxlen += W_CHUNK; + buffer = realloc(buffer, 1 + *maxlen); + if (buffer == NULL) + free(old_buffer); + } + + if (buffer != NULL) { + buffer[*actlen] = ch; + buffer[++(*actlen)] = '\0'; + } + + return buffer; +} + +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +static char *w_addmem(char *buffer, size_t * actlen, size_t * maxlen, + const char *str, size_t len) +{ + /* Add a string to the buffer, allocating room for it if needed. + */ + if (*actlen + len > *maxlen) { + char *old_buffer = buffer; + assert(buffer == NULL || *maxlen != 0); + *maxlen += MAX(2 * len, W_CHUNK); + buffer = realloc(old_buffer, 1 + *maxlen); + if (buffer == NULL) + free(old_buffer); + } + + if (buffer != NULL) { + *((char *) mempcpy(&buffer[*actlen], str, len)) = '\0'; + *actlen += len; + } + return buffer; +} + +/* Add a string to the buffer, allocating room for it if needed. */ +static char *w_addstr(char *buffer, size_t * actlen, size_t * maxlen, + const char *str) + /* (lengths exclude trailing zero) */ +{ + size_t len; + assert(str != NULL); /* w_addstr only called from this file */ + len = strlen(str); + + return w_addmem(buffer, actlen, maxlen, str, len); +} + +/* Add a word to the wordlist */ +static int w_addword(wordexp_t * pwordexp, char *word) +{ + size_t num_p; + char **new_wordv; + + /* Internally, NULL acts like "". Convert NULLs to "" before + * the caller sees them. + */ + if (word == NULL) { + word = strdup(""); + if (word == NULL) + goto no_space; + } + + num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs; + new_wordv = realloc(pwordexp->we_wordv, sizeof(char *) * num_p); + if (new_wordv != NULL) { + pwordexp->we_wordv = new_wordv; + pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc++] = word; + pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc] = NULL; + return 0; + } + + no_space: + return WRDE_NOSPACE; +} + +/* The parse_*() functions should leave *offset being the offset in 'words' + * to the last character processed. + */ +static int +parse_backslash(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised _at_ a backslash, not in quotes */ + + switch (words[1 + *offset]) { + case 0: + /* Backslash is last character of input words */ + return WRDE_SYNTAX; + + case '\n': + ++(*offset); + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[1 + *offset]); + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + } + + return 0; +} + +static int +parse_qtd_backslash(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised _at_ a backslash, inside quotes */ + + switch (words[1 + *offset]) { + case 0: + /* Backslash is last character of input words */ + return WRDE_SYNTAX; + + case '\n': + ++(*offset); + break; + + case '$': + case '`': + case '"': + case '\\': + *word = + w_addchar(*word, word_length, max_length, words[1 + *offset]); + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word != NULL) + *word = + w_addchar(*word, word_length, max_length, + words[1 + *offset]); + + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + } + + return 0; +} + +static int +parse_tilde(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, size_t wordc) +{ + /* We are poised _at_ a tilde */ + size_t i; + + if (*word_length != 0) { + if (!((*word)[*word_length - 1] == '=' && wordc == 0)) { + if (!((*word)[*word_length - 1] == ':' + && strchr(*word, '=') && wordc == 0)) { + *word = w_addchar(*word, word_length, max_length, '~'); + return *word ? 0 : WRDE_NOSPACE; + } + } + } + + for (i = 1 + *offset; words[i]; i++) { + if (words[i] == ':' || words[i] == '/' || words[i] == ' ' || + words[i] == '\t' || words[i] == 0) + break; + + if (words[i] == '\\') { + *word = w_addchar(*word, word_length, max_length, '~'); + return *word ? 0 : WRDE_NOSPACE; + } + } + + if (i == 1 + *offset) { + /* Tilde appears on its own */ + uid_t uid; + struct passwd pwd, *tpwd; + int buflen = 1000; + char *home; + char *buffer; + int result; + + /* POSIX.2 says ~ expands to $HOME and if HOME is unset the + results are unspecified. We do a lookup on the uid if + HOME is unset. */ + + home = getenv("HOME"); + if (home != NULL) { + *word = w_addstr(*word, word_length, max_length, home); + if (*word == NULL) + return WRDE_NOSPACE; + } else { + uid = getuid(); + buffer = alloca(buflen); + + while ((result = getpwuid_r(uid, &pwd, buffer, buflen, &tpwd)) + != 0 && errno == ERANGE) + { + buflen += 1000; + buffer = alloca(buflen); + } + + if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL) { + *word = w_addstr(*word, word_length, max_length, pwd.pw_dir); + if (*word == NULL) + return WRDE_NOSPACE; + } else { + *word = w_addchar(*word, word_length, max_length, '~'); + if (*word == NULL) + return WRDE_NOSPACE; + } + } + } else { + /* Look up user name in database to get home directory */ + char *user = strndup(&words[1 + *offset], i - (1 + *offset)); + struct passwd pwd, *tpwd; + int buflen = 1000; + char *buffer = alloca(buflen); + int result; + + while ((result = getpwnam_r(user, &pwd, buffer, buflen, &tpwd)) != 0 + && errno == ERANGE) { + buflen += 1000; + buffer = alloca(buflen); + } + + if (result == 0 && tpwd != NULL && pwd.pw_dir) + *word = w_addstr(*word, word_length, max_length, pwd.pw_dir); + else { + /* (invalid login name) */ + *word = w_addchar(*word, word_length, max_length, '~'); + if (*word != NULL) + *word = w_addstr(*word, word_length, max_length, user); + } + + *offset = i - 1; + } + return *word ? 0 : WRDE_NOSPACE; +} + + +static int +do_parse_glob(const char *glob_word, char **word, size_t * word_length, + size_t * max_length, wordexp_t * pwordexp, const char *ifs, + const char *ifs_white) +{ + int error; + int match; + glob_t globbuf; + + error = glob(glob_word, GLOB_NOCHECK, NULL, &globbuf); + + if (error != 0) { + /* We can only run into memory problems. */ + assert(error == GLOB_NOSPACE); + return WRDE_NOSPACE; + } + + if (ifs && !*ifs) { + /* No field splitting allowed. */ + assert(globbuf.gl_pathv[0] != NULL); + *word = w_addstr(*word, word_length, max_length, globbuf.gl_pathv[0]); + for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match) { + *word = w_addchar(*word, word_length, max_length, ' '); + if (*word != NULL) + *word = w_addstr(*word, word_length, max_length, + globbuf.gl_pathv[match]); + } + + globfree(&globbuf); + return *word ? 0 : WRDE_NOSPACE; + } + + assert(ifs == NULL || *ifs != '\0'); + if (*word != NULL) { + free(*word); + *word = w_newword(word_length, max_length); + } + + for (match = 0; match < globbuf.gl_pathc; ++match) { + char *matching_word = strdup(globbuf.gl_pathv[match]); + + if (matching_word == NULL || w_addword(pwordexp, matching_word)) { + globfree(&globbuf); + return WRDE_NOSPACE; + } + } + + globfree(&globbuf); + return 0; +} + +static int +parse_glob(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after a '*', a '[' or a '?'. */ + int error = WRDE_NOSPACE; + int quoted = 0; /* 1 if singly-quoted, 2 if doubly */ + int i; + wordexp_t glob_list; /* List of words to glob */ + + glob_list.we_wordc = 0; + glob_list.we_wordv = NULL; + glob_list.we_offs = 0; + for (; words[*offset] != '\0'; ++*offset) { + if ((ifs && strchr(ifs, words[*offset])) || + (!ifs && strchr(" \t\n", words[*offset]))) + /* Reached IFS */ + break; + + /* Sort out quoting */ + if (words[*offset] == '\'') { + if (quoted == 0) { + quoted = 1; + continue; + } else if (quoted == 1) { + quoted = 0; + continue; + } + } else if (words[*offset] == '"') { + if (quoted == 0) { + quoted = 2; + continue; + } else if (quoted == 2) { + quoted = 0; + continue; + } + } + + /* Sort out other special characters */ + if (quoted != 1 && words[*offset] == '$') { + error = parse_dollars(word, word_length, max_length, words, + offset, flags, &glob_list, ifs, + ifs_white, quoted == 2); + if (error) + goto tidy_up; + + continue; + } else if (words[*offset] == '\\') { + if (quoted) + error = parse_qtd_backslash(word, word_length, max_length, + words, offset); + else + error = parse_backslash(word, word_length, max_length, + words, offset); + + if (error) + goto tidy_up; + + continue; + } + + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + goto tidy_up; + } + + /* Don't forget to re-parse the character we stopped at. */ + --*offset; + + /* Glob the words */ + error = w_addword(&glob_list, *word); + *word = w_newword(word_length, max_length); + for (i = 0; error == 0 && i < glob_list.we_wordc; i++) + error = do_parse_glob(glob_list.we_wordv[i], word, word_length, + max_length, pwordexp, ifs, ifs_white); + + /* Now tidy up */ + tidy_up: + wordfree(&glob_list); + return error; +} + +static int +parse_squote(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised just after a single quote */ + for (; words[*offset]; ++(*offset)) { + if (words[*offset] != '\'') { + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + return WRDE_NOSPACE; + } else + return 0; + } + + /* Unterminated string */ + return WRDE_SYNTAX; +} + +#ifdef __WORDEXP_FULL +static int eval_expr(char *expr, long int *result); + +static char *_itoa(unsigned long long int value, char *buflim) +{ + sprintf(buflim, "%llu", value); + return buflim; +} + +/* Functions to evaluate an arithmetic expression */ +static int eval_expr_val(char **expr, long int *result) +{ + int sgn = +1; + char *digit; + + /* Skip white space */ + for (digit = *expr; digit && *digit && isspace(*digit); ++digit); + + switch (*digit) { + case '(': + + /* Scan for closing paren */ + for (++digit; **expr && **expr != ')'; ++(*expr)); + + /* Is there one? */ + if (!**expr) + return WRDE_SYNTAX; + + *(*expr)++ = 0; + + if (eval_expr(digit, result)) + return WRDE_SYNTAX; + + return 0; + + case '+': /* Positive value */ + ++digit; + break; + + case '-': /* Negative value */ + ++digit; + sgn = -1; + break; + + default: + if (!isdigit(*digit)) + return WRDE_SYNTAX; + } + + *result = 0; + for (; *digit && isdigit(*digit); ++digit) + *result = (*result * 10) + (*digit - '0'); + + *expr = digit; + *result *= sgn; + return 0; +} + +static int eval_expr_multdiv(char **expr, long int *result) +{ + long int arg; + + /* Read a Value */ + if (eval_expr_val(expr, result) != 0) + return WRDE_SYNTAX; + + while (**expr) { + /* Skip white space */ + for (; *expr && **expr && isspace(**expr); ++(*expr)); + + if (**expr == '*') { + ++(*expr); + if (eval_expr_val(expr, &arg) != 0) + return WRDE_SYNTAX; + + *result *= arg; + } else if (**expr == '/') { + ++(*expr); + if (eval_expr_val(expr, &arg) != 0) + return WRDE_SYNTAX; + + *result /= arg; + } else + break; + } + + return 0; +} + +static int eval_expr(char *expr, long int *result) +{ + long int arg; + + /* Read a Multdiv */ + if (eval_expr_multdiv(&expr, result) != 0) + return WRDE_SYNTAX; + + while (*expr) { + /* Skip white space */ + for (; expr && *expr && isspace(*expr); ++expr); + + if (*expr == '+') { + ++expr; + if (eval_expr_multdiv(&expr, &arg) != 0) + return WRDE_SYNTAX; + + *result += arg; + } else if (*expr == '-') { + ++expr; + if (eval_expr_multdiv(&expr, &arg) != 0) + return WRDE_SYNTAX; + + *result -= arg; + } else + break; + } + + return 0; +} + +static int +parse_arith(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, int bracket) +{ + /* We are poised just after "$((" or "$[" */ + int error; + int paren_depth = 1; + size_t expr_length; + size_t expr_maxlen; + char *expr; + + expr = w_newword(&expr_length, &expr_maxlen); + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '$': + error = parse_dollars(&expr, &expr_length, &expr_maxlen, + words, offset, flags, NULL, NULL, NULL, + 1); + /* The ``1'' here is to tell parse_dollars not to + * split the fields. + */ + if (error) { + free(expr); + return error; + } + break; + + case '`': + (*offset)++; + error = parse_backtick(&expr, &expr_length, &expr_maxlen, + words, offset, flags, NULL, NULL, NULL); + /* The first NULL here is to tell parse_backtick not to + * split the fields. + */ + if (error) { + free(expr); + return error; + } + break; + + case '\\': + error = parse_qtd_backslash(&expr, &expr_length, &expr_maxlen, + words, offset); + if (error) { + free(expr); + return error; + } + /* I think that a backslash within an + * arithmetic expansion is bound to + * cause an error sooner or later anyway though. + */ + break; + + case ')': + if (--paren_depth == 0) { + char result[21]; /* 21 = ceil(log10(2^64)) + 1 */ + long int numresult = 0; + long long int convertme; + + if (bracket || words[1 + *offset] != ')') { + free(expr); + return WRDE_SYNTAX; + } + + ++(*offset); + + /* Go - evaluate. */ + if (*expr && eval_expr(expr, &numresult) != 0) { + free(expr); + return WRDE_SYNTAX; + } + + if (numresult < 0) { + convertme = -numresult; + *word = w_addchar(*word, word_length, max_length, '-'); + if (!*word) { + free(expr); + return WRDE_NOSPACE; + } + } else + convertme = numresult; + + result[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(convertme, &result[20])); + free(expr); + return *word ? 0 : WRDE_NOSPACE; + } + expr = + w_addchar(expr, &expr_length, &expr_maxlen, + words[*offset]); + if (expr == NULL) + return WRDE_NOSPACE; + + break; + + case ']': + if (bracket && paren_depth == 1) { + char result[21]; /* 21 = ceil(log10(2^64)) + 1 */ + long int numresult = 0; + + /* Go - evaluate. */ + if (*expr && eval_expr(expr, &numresult) != 0) { + free(expr); + return WRDE_SYNTAX; + } + + result[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(numresult, &result[20])); + free(expr); + return *word ? 0 : WRDE_NOSPACE; + } + + free(expr); + return WRDE_SYNTAX; + + case '\n': + case ';': + case '{': + case '}': + free(expr); + return WRDE_BADCHAR; + + case '(': + ++paren_depth; + default: + expr = + w_addchar(expr, &expr_length, &expr_maxlen, + words[*offset]); + if (expr == NULL) + return WRDE_NOSPACE; + } + } + + /* Premature end */ + free(expr); + return WRDE_SYNTAX; +} + +/* Function called by child process in exec_comm() */ +static void attribute_noreturn +exec_comm_child(char *comm, int *fildes, int showerr, int noexec) +{ + const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL }; + + /* Execute the command, or just check syntax? */ + if (noexec) + args[1] = "-nc"; + + /* Redirect output. */ + dup2(fildes[1], 1); + close(fildes[1]); + + /* Redirect stderr to /dev/null if we have to. */ + if (showerr == 0) { + int fd; + + close(2); + fd = open(_PATH_DEVNULL, O_WRONLY); + if (fd >= 0 && fd != 2) { + dup2(fd, 2); + close(fd); + } + } + + /* Make sure the subshell doesn't field-split on our behalf. */ + unsetenv("IFS"); + + close(fildes[0]); + execve(_PATH_BSHELL, (char *const *) args, __environ); + + /* Bad. What now? */ + abort(); +} + +/* Function to execute a command and retrieve the results */ +/* pwordexp contains NULL if field-splitting is forbidden */ +static int +exec_comm(char *comm, char **word, size_t * word_length, + size_t * max_length, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white) +{ + int fildes[2]; + int bufsize = 128; + int buflen; + int i; + int status = 0; + size_t maxnewlines = 0; + char *buffer; + pid_t pid; + + /* Don't fork() unless necessary */ + if (!comm || !*comm) + return 0; + + if (pipe(fildes)) + /* Bad */ + return WRDE_NOSPACE; + + if ((pid = fork()) < 0) { + /* Bad */ + close(fildes[0]); + close(fildes[1]); + return WRDE_NOSPACE; + } + + if (pid == 0) + exec_comm_child(comm, fildes, (flags & WRDE_SHOWERR), 0); + + /* Parent */ + + close(fildes[1]); + buffer = alloca(bufsize); + + if (!pwordexp) + /* Quoted - no field splitting */ + { + while (1) { + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) { + if (waitpid(pid, &status, WNOHANG) == 0) + continue; + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) + break; + } + + maxnewlines += buflen; + + *word = w_addmem(*word, word_length, max_length, buffer, buflen); + if (*word == NULL) + goto no_space; + } + } else + /* Not quoted - split fields */ + { + int copying = 0; + + /* 'copying' is: + * 0 when searching for first character in a field not IFS white space + * 1 when copying the text of a field + * 2 when searching for possible non-whitespace IFS + * 3 when searching for non-newline after copying field + */ + + while (1) { + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) { + if (waitpid(pid, &status, WNOHANG) == 0) + continue; + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) + break; + } + + for (i = 0; i < buflen; ++i) { + if (strchr(ifs, buffer[i]) != NULL) { + /* Current character is IFS */ + if (strchr(ifs_white, buffer[i]) == NULL) { + /* Current character is IFS but not whitespace */ + if (copying == 2) { + /* current character + * | + * V + * eg: textmoretext + * + * So, strip whitespace IFS (like at the start) + */ + copying = 0; + continue; + } + + copying = 0; + /* fall through and delimit field.. */ + } else { + if (buffer[i] == '\n') { + /* Current character is (IFS) newline */ + + /* If copying a field, this is the end of it, + but maybe all that's left is trailing newlines. + So start searching for a non-newline. */ + if (copying == 1) + copying = 3; + + continue; + } else { + /* Current character is IFS white space, but + not a newline */ + + /* If not either copying a field or searching + for non-newline after a field, ignore it */ + if (copying != 1 && copying != 3) + continue; + + /* End of field (search for non-ws IFS afterwards) */ + copying = 2; + } + } + + /* First IFS white space (non-newline), or IFS non-whitespace. + * Delimit the field. Nulls are converted by w_addword. */ + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) + goto no_space; + + *word = w_newword(word_length, max_length); + + maxnewlines = 0; + /* fall back round the loop.. */ + } else { + /* Not IFS character */ + + if (copying == 3) { + /* Nothing but (IFS) newlines since the last field, + so delimit it here before starting new word */ + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) + goto no_space; + + *word = w_newword(word_length, max_length); + } + + copying = 1; + + if (buffer[i] == '\n') /* happens if newline not in IFS */ + maxnewlines++; + else + maxnewlines = 0; + + *word = w_addchar(*word, word_length, max_length, + buffer[i]); + if (*word == NULL) + goto no_space; + } + } + } + } + + /* Chop off trailing newlines (required by POSIX.2) */ + /* Ensure we don't go back further than the beginning of the + substitution (i.e. remove maxnewlines bytes at most) */ + while (maxnewlines-- != 0 && + *word_length > 0 && (*word)[*word_length - 1] == '\n') { + (*word)[--*word_length] = '\0'; + + /* If the last word was entirely newlines, turn it into a new word + * which can be ignored if there's nothing following it. */ + if (*word_length == 0) { + free(*word); + *word = w_newword(word_length, max_length); + break; + } + } + + close(fildes[0]); + + /* Check for syntax error (re-execute but with "-n" flag) */ + if (buflen < 1 && status != 0) { + if ((pid = fork()) < 0) { + /* Bad */ + return WRDE_NOSPACE; + } + + if (pid == 0) { + fildes[0] = fildes[1] = -1; + exec_comm_child(comm, fildes, 0, 1); + } + + if (waitpid(pid, &status, 0) == pid && status != 0) + return WRDE_SYNTAX; + } + + return 0; + + no_space: + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + close(fildes[0]); + return WRDE_NOSPACE; +} + +static int +parse_comm(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after "$(" */ + int paren_depth = 1; + int error = 0; + int quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */ + size_t comm_length; + size_t comm_maxlen; + char *comm = w_newword(&comm_length, &comm_maxlen); + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '\'': + if (quoted == 0) + quoted = 1; + else if (quoted == 1) + quoted = 0; + + break; + + case '"': + if (quoted == 0) + quoted = 2; + else if (quoted == 2) + quoted = 0; + + break; + + case ')': + if (!quoted && --paren_depth == 0) { + /* Go -- give script to the shell */ + if (comm) { + error = exec_comm(comm, word, word_length, max_length, + flags, pwordexp, ifs, ifs_white); + free(comm); + } + + return error; + } + + /* This is just part of the script */ + break; + + case '(': + if (!quoted) + ++paren_depth; + } + + comm = w_addchar(comm, &comm_length, &comm_maxlen, words[*offset]); + if (comm == NULL) + return WRDE_NOSPACE; + } + + /* Premature end */ + free(comm); + + return WRDE_SYNTAX; +} + +static int +parse_backtick(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, + const char *ifs_white) +{ + /* We are poised just after "`" */ + int error; + int squoting = 0; + size_t comm_length; + size_t comm_maxlen; + char *comm = w_newword(&comm_length, &comm_maxlen); + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '`': + /* Go -- give the script to the shell */ + error = exec_comm(comm, word, word_length, max_length, flags, + pwordexp, ifs, ifs_white); + free(comm); + return error; + + case '\\': + if (squoting) { + error = parse_qtd_backslash(&comm, &comm_length, &comm_maxlen, + words, offset); + + if (error) { + free(comm); + return error; + } + + break; + } + + ++(*offset); + error = parse_backslash(&comm, &comm_length, &comm_maxlen, words, + offset); + + if (error) { + free(comm); + return error; + } + + break; + + case '\'': + squoting = 1 - squoting; + default: + comm = w_addchar(comm, &comm_length, &comm_maxlen, + words[*offset]); + if (comm == NULL) + return WRDE_NOSPACE; + } + } + + /* Premature end */ + free(comm); + return WRDE_SYNTAX; +} + +static int +parse_param(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white, + int quoted) +{ + /* We are poised just after "$" */ + enum action { + ACT_NONE, + ACT_RP_SHORT_LEFT = '#', + ACT_RP_LONG_LEFT = 'L', + ACT_RP_SHORT_RIGHT = '%', + ACT_RP_LONG_RIGHT = 'R', + ACT_NULL_ERROR = '?', + ACT_NULL_SUBST = '-', + ACT_NONNULL_SUBST = '+', + ACT_NULL_ASSIGN = '=' + }; + size_t env_length; + size_t env_maxlen; + size_t pat_length; + size_t pat_maxlen; + size_t start = *offset; + char *env; + char *pattern; + char *value = NULL; + enum action action = ACT_NONE; + int depth = 0; + int colon_seen = 0; + int seen_hash = 0; + int free_value = 0; + int pattern_is_quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */ + int error; + int special = 0; + char buffer[21]; + int brace = words[*offset] == '{'; + + env = w_newword(&env_length, &env_maxlen); + pattern = w_newword(&pat_length, &pat_maxlen); + + if (brace) + ++ * offset; + + /* First collect the parameter name. */ + + if (words[*offset] == '#') { + seen_hash = 1; + if (!brace) + goto envsubst; + ++*offset; + } + + if (isalpha(words[*offset]) || words[*offset] == '_') { + /* Normal parameter name. */ + do { + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + } + while (isalnum(words[++*offset]) || words[*offset] == '_'); + } else if (isdigit(words[*offset])) { + /* Numeric parameter name. */ + special = 1; + do { + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + if (!brace) + goto envsubst; + } + while (isdigit(words[++*offset])); + } else if (strchr("*@$", words[*offset]) != NULL) { + /* Special parameter. */ + special = 1; + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + ++*offset; + } else { + if (brace) + goto syntax; + } + + if (brace) { + /* Check for special action to be applied to the value. */ + switch (words[*offset]) { + case '}': + /* Evaluate. */ + goto envsubst; + + case '#': + action = ACT_RP_SHORT_LEFT; + if (words[1 + *offset] == '#') { + ++*offset; + action = ACT_RP_LONG_LEFT; + } + break; + + case '%': + action = ACT_RP_SHORT_RIGHT; + if (words[1 + *offset] == '%') { + ++*offset; + action = ACT_RP_LONG_RIGHT; + } + break; + + case ':': + if (strchr("-=?+", words[1 + *offset]) == NULL) + goto syntax; + + colon_seen = 1; + action = words[++*offset]; + break; + + case '-': + case '=': + case '?': + case '+': + action = words[*offset]; + break; + + default: + goto syntax; + } + + /* Now collect the pattern, but don't expand it yet. */ + ++*offset; + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '{': + if (!pattern_is_quoted) + ++depth; + break; + + case '}': + if (!pattern_is_quoted) { + if (depth == 0) + goto envsubst; + --depth; + } + break; + + case '\\': + if (pattern_is_quoted) + /* Quoted; treat as normal character. */ + break; + + /* Otherwise, it's an escape: next character is literal. */ + if (words[++*offset] == '\0') + goto syntax; + + pattern = w_addchar(pattern, &pat_length, &pat_maxlen, '\\'); + if (pattern == NULL) + goto no_space; + + break; + + case '\'': + if (pattern_is_quoted == 0) + pattern_is_quoted = 1; + else if (pattern_is_quoted == 1) + pattern_is_quoted = 0; + + break; + + case '"': + if (pattern_is_quoted == 0) + pattern_is_quoted = 2; + else if (pattern_is_quoted == 2) + pattern_is_quoted = 0; + + break; + } + + pattern = w_addchar(pattern, &pat_length, &pat_maxlen, + words[*offset]); + if (pattern == NULL) + goto no_space; + } + } + + /* End of input string -- remember to reparse the character that we + * stopped at. */ + --(*offset); + + envsubst: + if (words[start] == '{' && words[*offset] != '}') + goto syntax; + + if (env == NULL) { + if (seen_hash) { + /* $# expands to the number of positional parameters */ + buffer[20] = '\0'; + value = _itoa(__libc_argc - 1, &buffer[20]); + seen_hash = 0; + } else { + /* Just $ on its own */ + *offset = start - 1; + *word = w_addchar(*word, word_length, max_length, '$'); + return *word ? 0 : WRDE_NOSPACE; + } + } + /* Is it a numeric parameter? */ + else if (isdigit(env[0])) { + int n = atoi(env); + + if (n >= __libc_argc) + /* Substitute NULL. */ + value = NULL; + else + /* Replace with appropriate positional parameter. */ + value = __libc_argv[n]; + } + /* Is it a special parameter? */ + else if (special) { + /* Is it `$$'? */ + if (*env == '$') { + buffer[20] = '\0'; + value = _itoa(getpid(), &buffer[20]); + } + /* Is it `${#*}' or `${#@}'? */ + else if ((*env == '*' || *env == '@') && seen_hash) { + buffer[20] = '\0'; + value = _itoa(__libc_argc > 0 ? __libc_argc - 1 : 0, + &buffer[20]); + *word = w_addstr(*word, word_length, max_length, value); + free(env); + free(pattern); + return *word ? 0 : WRDE_NOSPACE; + } + /* Is it `$*' or `$@' (unquoted) ? */ + else if (*env == '*' || (*env == '@' && !quoted)) { + size_t plist_len = 0; + int p; + char *end; + + /* Build up value parameter by parameter (copy them) */ + for (p = 1; __libc_argv[p]; ++p) + plist_len += strlen(__libc_argv[p]) + 1; /* for space */ + value = malloc(plist_len); + if (value == NULL) + goto no_space; + end = value; + *end = 0; + for (p = 1; __libc_argv[p]; ++p) { + if (p > 1) + *end++ = ' '; + end = stpcpy(end, __libc_argv[p]); + } + + free_value = 1; + } else { + /* Must be a quoted `$@' */ + assert(*env == '@' && quoted); + + /* Each parameter is a separate word ("$@") */ + if (__libc_argc == 2) + value = __libc_argv[1]; + else if (__libc_argc > 2) { + int p; + + /* Append first parameter to current word. */ + value = w_addstr(*word, word_length, max_length, + __libc_argv[1]); + if (value == NULL || w_addword(pwordexp, value)) + goto no_space; + + for (p = 2; __libc_argv[p + 1]; p++) { + char *newword = strdup(__libc_argv[p]); + + if (newword == NULL || w_addword(pwordexp, newword)) + goto no_space; + } + + /* Start a new word with the last parameter. */ + *word = w_newword(word_length, max_length); + value = __libc_argv[p]; + } else { + free(env); + free(pattern); + return 0; + } + } + } else + value = getenv(env); + + if (value == NULL && (flags & WRDE_UNDEF)) { + /* Variable not defined. */ + error = WRDE_BADVAL; + goto do_error; + } + + if (action != ACT_NONE) { + int expand_pattern = 0; + + /* First, find out if we need to expand pattern (i.e. if we will + * use it). */ + switch (action) { + case ACT_RP_SHORT_LEFT: + case ACT_RP_LONG_LEFT: + case ACT_RP_SHORT_RIGHT: + case ACT_RP_LONG_RIGHT: + /* Always expand for these. */ + expand_pattern = 1; + break; + + case ACT_NULL_ERROR: + case ACT_NULL_SUBST: + case ACT_NULL_ASSIGN: + if (!value || (!*value && colon_seen)) + /* If param is unset, or set but null and a colon has been seen, + the expansion of the pattern will be needed. */ + expand_pattern = 1; + + break; + + case ACT_NONNULL_SUBST: + /* Expansion of word will be needed if parameter is set and not null, + or set null but no colon has been seen. */ + if (value && (*value || !colon_seen)) + expand_pattern = 1; + + break; + + default: + assert(!"Unrecognised action!"); + } + + if (expand_pattern) { + /* We need to perform tilde expansion, parameter expansion, + command substitution, and arithmetic expansion. We also + have to be a bit careful with wildcard characters, as + pattern might be given to fnmatch soon. To do this, we + convert quotes to escapes. */ + + char *expanded; + size_t exp_len; + size_t exp_maxl; + char *p; + int quoted = 0; /* 1: single quotes; 2: double */ + + expanded = w_newword(&exp_len, &exp_maxl); + for (p = pattern; p && *p; p++) { + size_t offset; + + switch (*p) { + case '"': + if (quoted == 2) + quoted = 0; + else if (quoted == 0) + quoted = 2; + else + break; + + continue; + + case '\'': + if (quoted == 1) + quoted = 0; + else if (quoted == 0) + quoted = 1; + else + break; + + continue; + + case '*': + case '?': + if (quoted) { + /* Convert quoted wildchar to escaped wildchar. */ + expanded = w_addchar(expanded, &exp_len, + &exp_maxl, '\\'); + + if (expanded == NULL) + goto no_space; + } + break; + + case '$': + offset = 0; + error = parse_dollars(&expanded, &exp_len, &exp_maxl, p, + &offset, flags, NULL, NULL, NULL, 1); + if (error) { + if (free_value) + free(value); + + free(expanded); + + goto do_error; + } + + p += offset; + continue; + + case '~': + if (quoted || exp_len) + break; + + offset = 0; + error = parse_tilde(&expanded, &exp_len, &exp_maxl, p, + &offset, 0); + if (error) { + if (free_value) + free(value); + + free(expanded); + + goto do_error; + } + + p += offset; + continue; + + case '\\': + expanded = w_addchar(expanded, &exp_len, &exp_maxl, '\\'); + ++p; + assert(*p); /* checked when extracted initially */ + if (expanded == NULL) + goto no_space; + } + + expanded = w_addchar(expanded, &exp_len, &exp_maxl, *p); + + if (expanded == NULL) + goto no_space; + } + + free(pattern); + + pattern = expanded; + } + + switch (action) { + case ACT_RP_SHORT_LEFT: + case ACT_RP_LONG_LEFT: + case ACT_RP_SHORT_RIGHT: + case ACT_RP_LONG_RIGHT: + { + char *p; + char c; + char *end; + + if (value == NULL || pattern == NULL || *pattern == '\0') + break; + + end = value + strlen(value); + + switch (action) { + case ACT_RP_SHORT_LEFT: + for (p = value; p <= end; ++p) { + c = *p; + *p = '\0'; + if (fnmatch(pattern, value, 0) != FNM_NOMATCH) { + *p = c; + if (free_value) { + char *newval = strdup(p); + + if (newval == NULL) { + free(value); + goto no_space; + } + free(value); + value = newval; + } else + value = p; + break; + } + *p = c; + } + + break; + + case ACT_RP_LONG_LEFT: + for (p = end; p >= value; --p) { + c = *p; + *p = '\0'; + if (fnmatch(pattern, value, 0) != FNM_NOMATCH) { + *p = c; + if (free_value) { + char *newval = strdup(p); + + if (newval == NULL) { + free(value); + goto no_space; + } + free(value); + value = newval; + } else + value = p; + break; + } + *p = c; + } + + break; + + case ACT_RP_SHORT_RIGHT: + for (p = end; p >= value; --p) { + if (fnmatch(pattern, p, 0) != FNM_NOMATCH) { + char *newval; + + newval = malloc(p - value + 1); + + if (newval == NULL) { + if (free_value) + free(value); + goto no_space; + } + + *(char *) mempcpy(newval, value, p - value) = '\0'; + if (free_value) + free(value); + value = newval; + free_value = 1; + break; + } + } + + break; + + case ACT_RP_LONG_RIGHT: + for (p = value; p <= end; ++p) { + if (fnmatch(pattern, p, 0) != FNM_NOMATCH) { + char *newval; + + newval = malloc(p - value + 1); + + if (newval == NULL) { + if (free_value) + free(value); + goto no_space; + } + + *(char *) mempcpy(newval, value, p - value) = '\0'; + if (free_value) + free(value); + value = newval; + free_value = 1; + break; + } + } + + break; + + default: + break; + } + + break; + } + + case ACT_NULL_ERROR: + if (value && *value) + /* Substitute parameter */ + break; + + error = 0; + if (!colon_seen && value) + /* Substitute NULL */ + ; + else if (*pattern) + fprintf(stderr, "%s: %s\n", env, pattern); + else { + fprintf(stderr, "%s: parameter null or not set\n", env); + error = WRDE_BADVAL; + } + + if (free_value) + free(value); + goto do_error; + + case ACT_NULL_SUBST: + if (value && *value) + /* Substitute parameter */ + break; + + if (free_value) + free(value); + + if (!colon_seen && value) + /* Substitute NULL */ + goto success; + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + break; + + case ACT_NONNULL_SUBST: + if (value && (*value || !colon_seen)) { + if (free_value) + free(value); + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + break; + } + + /* Substitute NULL */ + if (free_value) + free(value); + goto success; + + case ACT_NULL_ASSIGN: + if (value && *value) + /* Substitute parameter */ + break; + + if (!colon_seen && value) { + /* Substitute NULL */ + if (free_value) + free(value); + goto success; + } + + if (free_value) + free(value); + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + setenv(env, value, 1); + break; + + default: + assert(!"Unrecognised action!"); + } + } + + free(env); + env = NULL; + free(pattern); + pattern = NULL; + + if (seen_hash) { + char param_length[21]; + + param_length[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(value ? strlen(value) : 0, + ¶m_length[20])); + if (free_value) { + assert(value != NULL); + free(value); + } + + return *word ? 0 : WRDE_NOSPACE; + } + + if (value == NULL) + return 0; + + if (quoted || !pwordexp) { + /* Quoted - no field split */ + *word = w_addstr(*word, word_length, max_length, value); + if (free_value) + free(value); + + return *word ? 0 : WRDE_NOSPACE; + } else { + /* Need to field-split */ + char *value_copy = strdup(value); /* Don't modify value */ + char *field_begin = value_copy; + int seen_nonws_ifs = 0; + + if (free_value) + free(value); + + if (value_copy == NULL) + goto no_space; + + do { + char *field_end = field_begin; + char *next_field; + + /* If this isn't the first field, start a new word */ + if (field_begin != value_copy) { + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) { + free(value_copy); + goto no_space; + } + + *word = w_newword(word_length, max_length); + } + + /* Skip IFS whitespace before the field */ + field_begin += strspn(field_begin, ifs_white); + + if (!seen_nonws_ifs && *field_begin == 0) + /* Nothing but whitespace */ + break; + + /* Search for the end of the field */ + field_end = field_begin + strcspn(field_begin, ifs); + + /* Set up pointer to the character after end of field and + skip whitespace IFS after it. */ + next_field = field_end + strspn(field_end, ifs_white); + + /* Skip at most one non-whitespace IFS character after the field */ + seen_nonws_ifs = 0; + if (*next_field && strchr(ifs, *next_field)) { + seen_nonws_ifs = 1; + next_field++; + } + + /* Null-terminate it */ + *field_end = 0; + + /* Tag a copy onto the current word */ + *word = w_addstr(*word, word_length, max_length, field_begin); + + if (*word == NULL && *field_begin != '\0') { + free(value_copy); + goto no_space; + } + + field_begin = next_field; + } + while (seen_nonws_ifs || *field_begin); + + free(value_copy); + } + + return 0; + + success: + error = 0; + goto do_error; + + no_space: + error = WRDE_NOSPACE; + goto do_error; + + syntax: + error = WRDE_SYNTAX; + + do_error: + free(env); + + free(pattern); + + return error; +} +#else +static __inline__ int +parse_backtick(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, + const char *ifs_white) +{ + return 0; +} +#endif + +static int +parse_dollars(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white, + int quoted) +{ + /* We are poised _at_ "$" */ + switch (words[1 + *offset]) { + case '"': + case '\'': + case 0: + *word = w_addchar(*word, word_length, max_length, '$'); + return *word ? 0 : WRDE_NOSPACE; + +#ifdef __WORDEXP_FULL + case '(': + if (words[2 + *offset] == '(') { + /* Differentiate between $((1+3)) and $((echo);(ls)) */ + int i = 3 + *offset; + int depth = 0; + + while (words[i] && !(depth == 0 && words[i] == ')')) { + if (words[i] == '(') + ++depth; + else if (words[i] == ')') + --depth; + + ++i; + } + + if (words[i] == ')' && words[i + 1] == ')') { + (*offset) += 3; + /* Call parse_arith -- 0 is for "no brackets" */ + return parse_arith(word, word_length, max_length, words, + offset, flags, 0); + } + } + + if (flags & WRDE_NOCMD) + return WRDE_CMDSUB; + + (*offset) += 2; + return parse_comm(word, word_length, max_length, words, offset, + flags, quoted ? NULL : pwordexp, ifs, ifs_white); + + case '[': + (*offset) += 2; + /* Call parse_arith -- 1 is for "brackets" */ + return parse_arith(word, word_length, max_length, words, offset, + flags, 1); + + case '{': + default: + ++(*offset); /* parse_param needs to know if "{" is there */ + return parse_param(word, word_length, max_length, words, offset, + flags, pwordexp, ifs, ifs_white, quoted); +#else + default: + ++(*offset); /* parse_param needs to know if "{" is there */ + return 0; +#endif + } +} + +static int +parse_dquote(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after a double-quote */ + int error; + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '"': + return 0; + + case '$': + error = parse_dollars(word, word_length, max_length, words, offset, + flags, pwordexp, ifs, ifs_white, 1); + /* The ``1'' here is to tell parse_dollars not to + * split the fields. It may need to, however ("$@"). + */ + if (error) + return error; + + break; + + case '`': + if (flags & WRDE_NOCMD) + return WRDE_CMDSUB; + + ++(*offset); + error = parse_backtick(word, word_length, max_length, words, + offset, flags, NULL, NULL, NULL); + /* The first NULL here is to tell parse_backtick not to + * split the fields. + */ + if (error) + return error; + + break; + + case '\\': + error = parse_qtd_backslash(word, word_length, max_length, words, + offset); + + if (error) + return error; + + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + return WRDE_NOSPACE; + } + } + + /* Unterminated string */ + return WRDE_SYNTAX; +} + +/* + * wordfree() is to be called after pwordexp is finished with. + */ + +void wordfree(wordexp_t * pwordexp) +{ + + /* wordexp can set pwordexp to NULL */ + if (pwordexp && pwordexp->we_wordv) { + char **wordv = pwordexp->we_wordv; + + for (wordv += pwordexp->we_offs; *wordv; ++wordv) + free(*wordv); + + free(pwordexp->we_wordv); + pwordexp->we_wordv = NULL; + } +} +libc_hidden_def(wordfree) + +/* + * wordexp() + */ + +int wordexp(const char *words, wordexp_t * we, int flags) +{ + size_t words_offset; + size_t word_length; + size_t max_length; + char *word = w_newword(&word_length, &max_length); + int error; + char *ifs; + char ifs_white[4]; + wordexp_t old_word = *we; + + if (flags & WRDE_REUSE) { + /* Minimal implementation of WRDE_REUSE for now */ + wordfree(we); + old_word.we_wordv = NULL; + } + + if ((flags & WRDE_APPEND) == 0) { + we->we_wordc = 0; + + if (flags & WRDE_DOOFFS) { + we->we_wordv = calloc(1 + we->we_offs, sizeof(char *)); + if (we->we_wordv == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + } else { + we->we_wordv = calloc(1, sizeof(char *)); + if (we->we_wordv == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + + we->we_offs = 0; + } + } + + /* Find out what the field separators are. + * There are two types: whitespace and non-whitespace. + */ + ifs = getenv("IFS"); + + if (!ifs) + /* IFS unset - use . */ + ifs = strcpy(ifs_white, " \t\n"); + else { + char *ifsch = ifs; + char *whch = ifs_white; + + /* Start off with no whitespace IFS characters */ + ifs_white[0] = '\0'; + + while (*ifsch != '\0') { + if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n')) { + /* Whitespace IFS. See first whether it is already in our + collection. */ + char *runp = ifs_white; + + while (runp < whch && *runp != '\0' && *runp != *ifsch) + ++runp; + + if (runp == whch) + *whch++ = *ifsch; + } + + ++ifsch; + } + *whch = '\0'; + } + + for (words_offset = 0; words[words_offset]; ++words_offset) + switch (words[words_offset]) { + case '\\': + error = parse_backslash(&word, &word_length, &max_length, words, + &words_offset); + + if (error) + goto do_error; + + break; + + case '$': + error = parse_dollars(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white, + 0); + + if (error) + goto do_error; + + break; + + case '`': + if (flags & WRDE_NOCMD) { + error = WRDE_CMDSUB; + goto do_error; + } + + ++words_offset; + error = parse_backtick(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, + ifs_white); + + if (error) + goto do_error; + + break; + + case '"': + ++words_offset; + error = parse_dquote(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white); + + if (error) + goto do_error; + + if (!word_length) { + error = w_addword(we, NULL); + + if (error) + return error; + } + + break; + + case '\'': + ++words_offset; + error = parse_squote(&word, &word_length, &max_length, words, + &words_offset); + + if (error) + goto do_error; + + if (!word_length) { + error = w_addword(we, NULL); + + if (error) + return error; + } + + break; + + case '~': + error = parse_tilde(&word, &word_length, &max_length, words, + &words_offset, we->we_wordc); + + if (error) + goto do_error; + + break; + + case '*': + case '[': + case '?': + error = parse_glob(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white); + + if (error) + goto do_error; + + break; + + default: + /* Is it a word separator? */ + if (strchr(" \t", words[words_offset]) == NULL) { + char ch = words[words_offset]; + + /* Not a word separator -- but is it a valid word char? */ + if (strchr("\n|&;<>(){}", ch)) { + /* Fail */ + error = WRDE_BADCHAR; + goto do_error; + } + + /* "Ordinary" character -- add it to word */ + word = w_addchar(word, &word_length, &max_length, ch); + if (word == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + + break; + } + + /* If a word has been delimited, add it to the list. */ + if (word != NULL) { + error = w_addword(we, word); + if (error) + goto do_error; + } + + word = w_newword(&word_length, &max_length); + } + + /* End of string */ + + /* There was a word separator at the end */ + if (word == NULL) /* i.e. w_newword */ + return 0; + + /* There was no field separator at the end */ + return w_addword(we, word); + + do_error: + /* Error: + * free memory used (unless error is WRDE_NOSPACE), and + * set we members back to what they were. + */ + + free(word); + + if (error == WRDE_NOSPACE) + return WRDE_NOSPACE; + + if ((flags & WRDE_APPEND) == 0) + wordfree(we); + + *we = old_word; + return error; +} diff --git a/libc/pwd_grp/.indent.pro b/libc/pwd_grp/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/pwd_grp/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/pwd_grp/Makefile b/libc/pwd_grp/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/pwd_grp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/pwd_grp/Makefile.in b/libc/pwd_grp/Makefile.in new file mode 100644 index 0000000..6805ffe --- /dev/null +++ b/libc/pwd_grp/Makefile.in @@ -0,0 +1,31 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +PWDGRP_DIR := $(top_srcdir)libc/pwd_grp +PWDGRP_OUT := $(top_builddir)libc/pwd_grp + +CSRC := $(notdir $(wildcard $(PWDGRP_DIR)/*.c)) +CSRC := $(filter-out pwd_grp.c pwd_grp_internal.c,$(CSRC)) + +ifneq ($(UCLIBC_HAS_SHADOW),y) +SHADOW_CSRC := \ + fgetspent_r.c fgetspent.c getspent_r.c getspent.c \ + getspnam_r.c getspnam.c lckpwdf.c putspent.c \ + sgetspent_r.c sgetspent.c __parsespent.c +# getspuid_r.c getspuid.c +CSRC := $(filter-out $(SHADOW_CSRC),$(CSRC)) +endif + +PWDGRP_SRC := $(patsubst %.c,$(PWDGRP_DIR)/%.c,$(CSRC)) +PWDGRP_OBJ := $(patsubst %.c,$(PWDGRP_OUT)/%.o,$(CSRC)) + +libc-y += $(PWDGRP_OBJ) + +objclean-y += pwdgrp_clean + +pwdgrp_clean: + $(do_rm) $(addprefix $(PWDGRP_OUT)/*., o os) diff --git a/libc/pwd_grp/__getgrouplist_internal.c b/libc/pwd_grp/__getgrouplist_internal.c new file mode 100644 index 0000000..c2edc99 --- /dev/null +++ b/libc/pwd_grp/__getgrouplist_internal.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___getgrouplist_internal +#include "pwd_grp.c" diff --git a/libc/pwd_grp/__parsegrent.c b/libc/pwd_grp/__parsegrent.c new file mode 100644 index 0000000..e3ac4ad --- /dev/null +++ b/libc/pwd_grp/__parsegrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsegrent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/__parsepwent.c b/libc/pwd_grp/__parsepwent.c new file mode 100644 index 0000000..2804a0a --- /dev/null +++ b/libc/pwd_grp/__parsepwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsepwent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/__parsespent.c b/libc/pwd_grp/__parsespent.c new file mode 100644 index 0000000..08321d0 --- /dev/null +++ b/libc/pwd_grp/__parsespent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsespent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/__pgsreader.c b/libc/pwd_grp/__pgsreader.c new file mode 100644 index 0000000..ac39ce9 --- /dev/null +++ b/libc/pwd_grp/__pgsreader.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___pgsreader +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetgrent.c b/libc/pwd_grp/fgetgrent.c new file mode 100644 index 0000000..695aee1 --- /dev/null +++ b/libc/pwd_grp/fgetgrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetgrent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetgrent_r.c b/libc/pwd_grp/fgetgrent_r.c new file mode 100644 index 0000000..ea97af7 --- /dev/null +++ b/libc/pwd_grp/fgetgrent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetgrent_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetpwent.c b/libc/pwd_grp/fgetpwent.c new file mode 100644 index 0000000..ddcc7ff --- /dev/null +++ b/libc/pwd_grp/fgetpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetpwent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetpwent_r.c b/libc/pwd_grp/fgetpwent_r.c new file mode 100644 index 0000000..8b93503 --- /dev/null +++ b/libc/pwd_grp/fgetpwent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetpwent_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetspent.c b/libc/pwd_grp/fgetspent.c new file mode 100644 index 0000000..b7c1ef2 --- /dev/null +++ b/libc/pwd_grp/fgetspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetspent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/fgetspent_r.c b/libc/pwd_grp/fgetspent_r.c new file mode 100644 index 0000000..7196d80 --- /dev/null +++ b/libc/pwd_grp/fgetspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetspent_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrent.c b/libc/pwd_grp/getgrent.c new file mode 100644 index 0000000..808e4e8 --- /dev/null +++ b/libc/pwd_grp/getgrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrent_r.c b/libc/pwd_grp/getgrent_r.c new file mode 100644 index 0000000..5f0b7c2 --- /dev/null +++ b/libc/pwd_grp/getgrent_r.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_getgrent_r +# include "pwd_grp.c" +#endif diff --git a/libc/pwd_grp/getgrgid.c b/libc/pwd_grp/getgrgid.c new file mode 100644 index 0000000..96ce903 --- /dev/null +++ b/libc/pwd_grp/getgrgid.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrgid +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrgid_r.c b/libc/pwd_grp/getgrgid_r.c new file mode 100644 index 0000000..a962f4c --- /dev/null +++ b/libc/pwd_grp/getgrgid_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrgid_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrnam.c b/libc/pwd_grp/getgrnam.c new file mode 100644 index 0000000..3b47d9a --- /dev/null +++ b/libc/pwd_grp/getgrnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrnam +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrnam_r.c b/libc/pwd_grp/getgrnam_r.c new file mode 100644 index 0000000..592a66c --- /dev/null +++ b/libc/pwd_grp/getgrnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrnam_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getgrouplist.c b/libc/pwd_grp/getgrouplist.c new file mode 100644 index 0000000..a4eba7d --- /dev/null +++ b/libc/pwd_grp/getgrouplist.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrouplist +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpw.c b/libc/pwd_grp/getpw.c new file mode 100644 index 0000000..943da3f --- /dev/null +++ b/libc/pwd_grp/getpw.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_getpw +# include "pwd_grp.c" +#endif diff --git a/libc/pwd_grp/getpwent.c b/libc/pwd_grp/getpwent.c new file mode 100644 index 0000000..a617bc8 --- /dev/null +++ b/libc/pwd_grp/getpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpwent_r.c b/libc/pwd_grp/getpwent_r.c new file mode 100644 index 0000000..9f00b05 --- /dev/null +++ b/libc/pwd_grp/getpwent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwent_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpwnam.c b/libc/pwd_grp/getpwnam.c new file mode 100644 index 0000000..d00640b --- /dev/null +++ b/libc/pwd_grp/getpwnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwnam +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpwnam_r.c b/libc/pwd_grp/getpwnam_r.c new file mode 100644 index 0000000..a4440e7 --- /dev/null +++ b/libc/pwd_grp/getpwnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwnam_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpwuid.c b/libc/pwd_grp/getpwuid.c new file mode 100644 index 0000000..16ac50f --- /dev/null +++ b/libc/pwd_grp/getpwuid.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwuid +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getpwuid_r.c b/libc/pwd_grp/getpwuid_r.c new file mode 100644 index 0000000..21d39ed --- /dev/null +++ b/libc/pwd_grp/getpwuid_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwuid_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getspent.c b/libc/pwd_grp/getspent.c new file mode 100644 index 0000000..5699b67 --- /dev/null +++ b/libc/pwd_grp/getspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getspent_r.c b/libc/pwd_grp/getspent_r.c new file mode 100644 index 0000000..da147a5 --- /dev/null +++ b/libc/pwd_grp/getspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspent_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getspnam.c b/libc/pwd_grp/getspnam.c new file mode 100644 index 0000000..19e40c7 --- /dev/null +++ b/libc/pwd_grp/getspnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspnam +#include "pwd_grp.c" diff --git a/libc/pwd_grp/getspnam_r.c b/libc/pwd_grp/getspnam_r.c new file mode 100644 index 0000000..053b697 --- /dev/null +++ b/libc/pwd_grp/getspnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspnam_r +#include "pwd_grp.c" diff --git a/libc/pwd_grp/initgroups.c b/libc/pwd_grp/initgroups.c new file mode 100644 index 0000000..d02be5e --- /dev/null +++ b/libc/pwd_grp/initgroups.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_initgroups +#include "pwd_grp.c" diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c new file mode 100644 index 0000000..0b0fb47 --- /dev/null +++ b/libc/pwd_grp/lckpwdf.c @@ -0,0 +1,195 @@ +/* vi: set sw=4 ts=4: */ +/* Handle locking of password file. + Copyright (C) 1996,98,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(open) +libc_hidden_proto(fcntl) +libc_hidden_proto(close) +libc_hidden_proto(sigfillset) +libc_hidden_proto(sigaction) +libc_hidden_proto(sigprocmask) +libc_hidden_proto(sigaddset) +libc_hidden_proto(sigemptyset) +libc_hidden_proto(alarm) + +/* How long to wait for getting the lock before returning with an + error. */ +#define TIMEOUT 15 /* sec */ + + +/* File descriptor for lock file. */ +static int lock_fd = -1; + +/* Prevent problems in multithreaded program by using mutex. */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +/* Prototypes for local functions. */ +static void noop_handler (int __sig); + + +int +lckpwdf (void) +{ + int flags; + sigset_t saved_set; /* Saved set of caught signals. */ + struct sigaction saved_act; /* Saved signal action. */ + sigset_t new_set; /* New set of caught signals. */ + struct sigaction new_act; /* New signal action. */ + struct flock fl; /* Information struct for locking. */ + int result; + int rv = -1; + + if (lock_fd != -1) + /* Still locked by own process. */ + return -1; + + /* Prevent problems caused by multiple threads. */ + __UCLIBC_MUTEX_LOCK(mylock); + + lock_fd = open (_PATH_PASSWD, O_WRONLY); + if (lock_fd == -1) { + /* Cannot create lock file. */ + goto DONE; + } + + /* Make sure file gets correctly closed when process finished. */ + flags = fcntl (lock_fd, F_GETFD, 0); + if (flags == -1) { + /* Cannot get file flags. */ + close(lock_fd); + lock_fd = -1; + goto DONE; + } + flags |= FD_CLOEXEC; /* Close on exit. */ + if (fcntl (lock_fd, F_SETFD, flags) < 0) { + /* Cannot set new flags. */ + close(lock_fd); + lock_fd = -1; + goto DONE; + } + + /* Now we have to get exclusive write access. Since multiple + process could try this we won't stop when it first fails. + Instead we set a timeout for the system call. Once the timer + expires it is likely that there are some problems which cannot be + resolved by waiting. + + It is important that we don't change the signal state. We must + restore the old signal behaviour. */ + memset (&new_act, '\0', sizeof (struct sigaction)); + new_act.sa_handler = noop_handler; + sigfillset (&new_act.sa_mask); + new_act.sa_flags = 0ul; + + /* Install new action handler for alarm and save old. */ + if (sigaction (SIGALRM, &new_act, &saved_act) < 0) { + /* Cannot install signal handler. */ + close(lock_fd); + lock_fd = -1; + goto DONE; + } + + /* Now make sure the alarm signal is not blocked. */ + sigemptyset (&new_set); + sigaddset (&new_set, SIGALRM); + if (sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0) { + sigaction (SIGALRM, &saved_act, NULL); + close(lock_fd); + lock_fd = -1; + goto DONE; + } + + /* Start timer. If we cannot get the lock in the specified time we + get a signal. */ + alarm (TIMEOUT); + + /* Try to get the lock. */ + memset (&fl, '\0', sizeof (struct flock)); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + result = fcntl (lock_fd, F_SETLKW, &fl); + + /* Clear alarm. */ + alarm (0); + + /* Restore old set of handled signals. We don't need to know + about the current one.*/ + sigprocmask (SIG_SETMASK, &saved_set, NULL); + + /* Restore old action handler for alarm. We don't need to know + about the current one. */ + sigaction (SIGALRM, &saved_act, NULL); + + if (result < 0) { + close(lock_fd); + lock_fd = -1; + goto DONE; + } + rv = 0; + +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; +} + + +int +ulckpwdf (void) +{ + int result; + + if (lock_fd == -1) + /* There is no lock set. */ + result = -1; + else + { + /* Prevent problems caused by multiple threads. */ + __UCLIBC_MUTEX_LOCK(mylock); + + result = close (lock_fd); + + /* Mark descriptor as unused. */ + lock_fd = -1; + + /* Clear mutex. */ + __UCLIBC_MUTEX_UNLOCK(mylock); + } + + return result; +} + + +static void +noop_handler (int sig) +{ + /* We simply return which makes the `fcntl' call return with an error. */ +} diff --git a/libc/pwd_grp/putgrent.c b/libc/pwd_grp/putgrent.c new file mode 100644 index 0000000..20a6faf --- /dev/null +++ b/libc/pwd_grp/putgrent.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_putgrent +# include "pwd_grp.c" +#endif diff --git a/libc/pwd_grp/putpwent.c b/libc/pwd_grp/putpwent.c new file mode 100644 index 0000000..045462e --- /dev/null +++ b/libc/pwd_grp/putpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_putpwent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/putspent.c b/libc/pwd_grp/putspent.c new file mode 100644 index 0000000..d6b5b28 --- /dev/null +++ b/libc/pwd_grp/putspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_putspent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/pwd_grp.c b/libc/pwd_grp/pwd_grp.c new file mode 100644 index 0000000..5af1f0c --- /dev/null +++ b/libc/pwd_grp/pwd_grp.c @@ -0,0 +1,1228 @@ +/* + * Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Nov 6, 2003 Initial version. + * + * NOTE: This implementation is quite strict about requiring all + * field seperators. It also does not allow leading whitespace + * except when processing the numeric fields. glibc is more + * lenient. See the various glibc difference comments below. + * + * TODO: + * Move to dynamic allocation of (currently statically allocated) + * buffers; especially for the group-related functions since + * large group member lists will cause error returns. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_SHADOW__ +#include +#endif +#include + +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(strtoul) +libc_hidden_proto(rewind) +libc_hidden_proto(fgets_unlocked) +libc_hidden_proto(__fputc_unlocked) +libc_hidden_proto(sprintf) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(fprintf) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +/**********************************************************************/ +/* Prototypes for internal functions. */ + +extern int __parsepwent(void *pw, char *line) attribute_hidden; +extern int __parsegrent(void *gr, char *line) attribute_hidden; +extern int __parsespent(void *sp, char *line) attribute_hidden; + +extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data, + char *__restrict line_buff, size_t buflen, FILE *f) attribute_hidden; + +extern gid_t* __getgrouplist_internal(const char *user, gid_t gid, int *ngroups) attribute_hidden; + +/**********************************************************************/ +/* For the various fget??ent_r funcs, return + * + * 0: success + * ENOENT: end-of-file encountered + * ERANGE: buflen too small + * other error values possible. See __pgsreader. + * + * Also, *result == resultbuf on success and NULL on failure. + * + * NOTE: glibc difference - For the ENOENT case, glibc also sets errno. + * We do not, as it really isn't an error if we reach the end-of-file. + * Doing so is analogous to having fgetc() set errno on EOF. + */ +/**********************************************************************/ +#ifdef L_fgetpwent_r + +#ifdef __USE_SVID +libc_hidden_proto(fgetpwent_r) +int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct passwd **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsepwent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetpwent_r) +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetgrent_r + +#ifdef __USE_SVID +libc_hidden_proto(fgetgrent_r) +int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct group **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsegrent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetgrent_r) +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetspent_r + +libc_hidden_proto(fgetspent_r) +int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct spwd **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsespent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetspent_r) + +#endif +/**********************************************************************/ +/* For the various fget??ent funcs, return NULL on failure and a + * pointer to the appropriate struct (statically allocated) on success. + */ +/**********************************************************************/ +#ifdef L_fgetpwent + +#ifdef __USE_SVID +libc_hidden_proto(fgetpwent_r) + +struct passwd *fgetpwent(FILE *stream) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetgrent + +#ifdef __USE_SVID +libc_hidden_proto(fgetgrent_r) + +struct group *fgetgrent(FILE *stream) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetspent + +libc_hidden_proto(fgetspent_r) + +struct spwd *fgetspent(FILE *stream) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_sgetspent_r + +libc_hidden_proto(sgetspent_r) +int sgetspent_r(const char *string, struct spwd *result_buf, + char *buffer, size_t buflen, struct spwd **result) +{ + int rv = ERANGE; + + *result = NULL; + + if (buflen < __UCLIBC_PWD_BUFFER_SIZE__) { + DO_ERANGE: + __set_errno(rv); + goto DONE; + } + + if (string != buffer) { + if (strlen(string) >= buflen) { + goto DO_ERANGE; + } + strcpy(buffer, string); + } + + if (!(rv = __parsespent(result_buf, buffer))) { + *result = result_buf; + } + + DONE: + return rv; +} +libc_hidden_def(sgetspent_r) + +#endif +/**********************************************************************/ + +#ifdef GETXXKEY_R_FUNC +#error GETXXKEY_R_FUNC is already defined! +#endif + +#ifdef L_getpwnam_r +#define GETXXKEY_R_FUNC getpwnam_r +#define GETXXKEY_R_PARSER __parsepwent +#define GETXXKEY_R_ENTTYPE struct passwd +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->pw_name, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getgrnam_r +#define GETXXKEY_R_FUNC getgrnam_r +#define GETXXKEY_R_PARSER __parsegrent +#define GETXXKEY_R_ENTTYPE struct group +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->gr_name, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_GROUP +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getspnam_r +#define GETXXKEY_R_FUNC getspnam_r +#define GETXXKEY_R_PARSER __parsespent +#define GETXXKEY_R_ENTTYPE struct spwd +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->sp_namp, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_SHADOW +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getpwuid_r +#define GETXXKEY_R_FUNC getpwuid_r +#define GETXXKEY_R_PARSER __parsepwent +#define GETXXKEY_R_ENTTYPE struct passwd +#define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key) +#define DO_GETXXKEY_R_KEYTYPE uid_t +#define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getgrgid_r +#define GETXXKEY_R_FUNC getgrgid_r +#define GETXXKEY_R_PARSER __parsegrent +#define GETXXKEY_R_ENTTYPE struct group +#define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key) +#define DO_GETXXKEY_R_KEYTYPE gid_t +#define DO_GETXXKEY_R_PATHNAME _PATH_GROUP +#include "pwd_grp_internal.c" +#endif + +/**********************************************************************/ +#ifdef L_getpwuid + +libc_hidden_proto(getpwuid_r) + +struct passwd *getpwuid(uid_t uid) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrgid + +libc_hidden_proto(getgrgid_r) + +struct group *getgrgid(gid_t gid) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspuid_r + +/* This function is non-standard and is currently not built. It seems + * to have been created as a reentrant version of the non-standard + * functions getspuid. Why getspuid was added, I do not know. */ + +libc_hidden_proto(getpwuid_r) +libc_hidden_proto(getspnam_r) + +int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct spwd **__restrict result) +{ + int rv; + struct passwd *pp; + struct passwd password; + char pwd_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + + *result = NULL; + if (!(rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp))) { + rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result); + } + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_getspuid + +/* This function is non-standard and is currently not built. + * Why it was added, I do not know. */ + +libc_hidden_proto(getspuid_r) + +struct spwd *getspuid(uid_t uid) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getpwnam + +libc_hidden_proto(getpwnam_r) + +struct passwd *getpwnam(const char *name) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrnam + +libc_hidden_proto(getgrnam_r) + +struct group *getgrnam(const char *name) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspnam + +libc_hidden_proto(getspnam_r) + +struct spwd *getspnam(const char *name) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getpw + +libc_hidden_proto(getpwuid_r) + +int getpw(uid_t uid, char *buf) +{ + struct passwd resultbuf; + struct passwd *result; + char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + + if (!buf) { + __set_errno(EINVAL); + } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) { + if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n", + resultbuf.pw_name, resultbuf.pw_passwd, + (unsigned long)(resultbuf.pw_uid), + (unsigned long)(resultbuf.pw_gid), + resultbuf.pw_gecos, resultbuf.pw_dir, + resultbuf.pw_shell) >= 0 + ) { + return 0; + } + } + + return -1; +} + +#endif +/**********************************************************************/ + +#ifdef L_getpwent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *pwf /*= NULL*/; + +void setpwent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + rewind(pwf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endpwent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + fclose(pwf); + pwf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + + +libc_hidden_proto(getpwent_r) +int getpwent_r(struct passwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct passwd **__restrict result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!pwf) { + if (!(pwf = fopen(_PATH_PASSWD, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(pwf); + } + + if (!(rv = __pgsreader(__parsepwent, resultbuf, + buffer, buflen, pwf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getpwent_r) + +#endif +/**********************************************************************/ +#ifdef L_getgrent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *grf /*= NULL*/; + +void setgrent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + rewind(grf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endgrent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + fclose(grf); + grf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +libc_hidden_proto(getgrent_r) +int getgrent_r(struct group *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct group **__restrict result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!grf) { + if (!(grf = fopen(_PATH_GROUP, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(grf); + } + + if (!(rv = __pgsreader(__parsegrent, resultbuf, + buffer, buflen, grf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getgrent_r) + +#endif +/**********************************************************************/ +#ifdef L_getspent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *spf /*= NULL*/; + +void setspent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + rewind(spf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endspent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + fclose(spf); + spf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +libc_hidden_proto(getspent_r) +int getspent_r(struct spwd *resultbuf, char *buffer, + size_t buflen, struct spwd **result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!spf) { + if (!(spf = fopen(_PATH_SHADOW, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(spf); + } + + if (!(rv = __pgsreader(__parsespent, resultbuf, + buffer, buflen, spf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getspent_r) + +#endif +/**********************************************************************/ +#ifdef L_getpwent + +libc_hidden_proto(getpwent_r) + +struct passwd *getpwent(void) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd pwd; + struct passwd *result; + + getpwent_r(&pwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrent + +libc_hidden_proto(getgrent_r) + +struct group *getgrent(void) +{ + static char line_buff[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group gr; + struct group *result; + + getgrent_r(&gr, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspent + +libc_hidden_proto(getspent_r) + +struct spwd *getspent(void) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd spwd; + struct spwd *result; + + getspent_r(&spwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_sgetspent + +libc_hidden_proto(sgetspent_r) + +struct spwd *sgetspent(const char *string) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd spwd; + struct spwd *result; + + sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L___getgrouplist_internal + +gid_t attribute_hidden *__getgrouplist_internal(const char *user, gid_t gid, int *ngroups) +{ + FILE *grfile; + gid_t *group_list; + int num_groups; + struct group group; + char buff[__UCLIBC_PWD_BUFFER_SIZE__]; + + *ngroups = num_groups = 1; + + /* We alloc space for 8 gids at a time. */ + group_list = malloc(8 * sizeof(group_list[0])); + if (!group_list) + return NULL; + + group_list[0] = gid; + grfile = fopen(_PATH_GROUP, "r"); + /* If /etc/group doesn't exist, we still return 1-element vector */ + if (!grfile) + return group_list; + + __STDIO_SET_USER_LOCKING(grfile); + + while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) { + char **m; + + assert(group.gr_mem); /* Must have at least a NULL terminator. */ + if (group.gr_gid == gid) + continue; + for (m = group.gr_mem; *m; m++) { + if (strcmp(*m, user) != 0) + continue; + if (!(num_groups & 7)) { + gid_t *tmp = realloc(group_list, (num_groups+8) * sizeof(group_list[0])); + if (!tmp) + goto DO_CLOSE; + group_list = tmp; + } + group_list[num_groups++] = group.gr_gid; + break; + } + } + + DO_CLOSE: + fclose(grfile); + *ngroups = num_groups; + return group_list; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrouplist + +#if defined __USE_BSD || defined __USE_GNU +int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) +{ + int sz = *ngroups; + gid_t *group_list = __getgrouplist_internal(user, gid, ngroups); + + if (!group_list) { + /* malloc failure - what shall we do? + * fail with ENOMEM? I bet users never check for that */ + /* *ngroups = 1; - already done by __getgrouplist_internal */ + if (sz) { + groups[0] = gid; + return 1; + } + return -1; + } + /* *ngroups is non-zero here */ + + if (sz > *ngroups) + sz = *ngroups; + if (sz) + memcpy(groups, group_list, sz * sizeof(group_list[0])); + free(group_list); + if (sz < *ngroups) + return -1; + return sz; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_initgroups + +#ifdef __USE_BSD +libc_hidden_proto(setgroups) + +int initgroups(const char *user, gid_t gid) +{ + int rv; + int num_groups = ((unsigned)~0) >> 1; /* INT_MAX */ + gid_t *group_list = __getgrouplist_internal(user, gid, &num_groups); + if (!group_list) + return -1; + rv = setgroups(num_groups, group_list); + free(group_list); + return rv; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_putpwent + +#ifdef __USE_SVID +int putpwent(const struct passwd *__restrict p, FILE *__restrict f) +{ + int rv = -1; + + if (!p || !f) { + __set_errno(EINVAL); + } else { + /* No extra thread locking is needed above what fprintf does. */ + if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n", + p->pw_name, p->pw_passwd, + (unsigned long)(p->pw_uid), + (unsigned long)(p->pw_gid), + p->pw_gecos, p->pw_dir, p->pw_shell) >= 0 + ) { + rv = 0; + } + } + + return rv; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_putgrent + +int putgrent(const struct group *__restrict p, FILE *__restrict f) +{ + static const char format[] = ",%s"; + char **m; + const char *fmt; + int rv = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + if (!p || !f) { /* Sigh... glibc checks. */ + __set_errno(EINVAL); + } else { + __STDIO_AUTO_THREADLOCK(f); + + if (fprintf(f, "%s:%s:%lu:", + p->gr_name, p->gr_passwd, + (unsigned long)(p->gr_gid)) >= 0 + ) { + + fmt = format + 1; + + assert(p->gr_mem); + m = p->gr_mem; + + do { + if (!*m) { + if (__fputc_unlocked('\n', f) >= 0) { + rv = 0; + } + break; + } + if (fprintf(f, fmt, *m) < 0) { + break; + } + ++m; + fmt = format; + } while (1); + + } + + __STDIO_AUTO_THREADUNLOCK(f); + } + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_putspent + +static const unsigned char _sp_off[] = { + offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ + offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ + offsetof(struct spwd, sp_max), /* 4 - not a char ptr */ + offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */ + offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */ + offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */ +}; + +int putspent(const struct spwd *p, FILE *stream) +{ + static const char ld_format[] = "%ld:"; + const char *f; + long int x; + size_t i; + int rv = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + /* Unlike putpwent and putgrent, glibc does not check the args. */ + + __STDIO_AUTO_THREADLOCK(stream); + + if (fprintf(stream, "%s:%s:", p->sp_namp, + (p->sp_pwdp ? p->sp_pwdp : "")) < 0 + ) { + goto DO_UNLOCK; + } + + for (i=0 ; i < sizeof(_sp_off) ; i++) { + f = ld_format; + if ((x = *(const long int *)(((const char *) p) + _sp_off[i])) == -1) { + f += 3; + } + if (fprintf(stream, f, x) < 0) { + goto DO_UNLOCK; + } + } + + if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) { + goto DO_UNLOCK; + } + + if (__fputc_unlocked('\n', stream) > 0) { + rv = 0; + } + + DO_UNLOCK: + __STDIO_AUTO_THREADUNLOCK(stream); + + return rv; +} + +#endif +/**********************************************************************/ +/* Internal uClibc functions. */ +/**********************************************************************/ +#ifdef L___parsepwent + +static const unsigned char pw_off[] = { + offsetof(struct passwd, pw_name), /* 0 */ + offsetof(struct passwd, pw_passwd), /* 1 */ + offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */ + offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */ + offsetof(struct passwd, pw_gecos), /* 4 */ + offsetof(struct passwd, pw_dir), /* 5 */ + offsetof(struct passwd, pw_shell) /* 6 */ +}; + +int attribute_hidden __parsepwent(void *data, char *line) +{ + char *endptr; + char *p; + int i; + + i = 0; + do { + p = ((char *) ((struct passwd *) data)) + pw_off[i]; + + if ((i & 6) ^ 2) { /* i!=2 and i!=3 */ + *((char **) p) = line; + if (i==6) { + return 0; + } + /* NOTE: glibc difference - glibc allows omission of + * ':' seperators after the gid field if all remaining + * entries are empty. We require all separators. */ + if (!(line = strchr(line, ':'))) { + break; + } + } else { + unsigned long t = strtoul(line, &endptr, 10); + /* Make sure we had at least one digit, and that the + * failing char is the next field seperator ':'. See + * glibc difference note above. */ + /* TODO: Also check for leading whitespace? */ + if ((endptr == line) || (*endptr != ':')) { + break; + } + line = endptr; + if (i & 1) { /* i == 3 -- gid */ + *((gid_t *) p) = t; + } else { /* i == 2 -- uid */ + *((uid_t *) p) = t; + } + } + + *line++ = 0; + ++i; + } while (1); + + return -1; +} + +#endif +/**********************************************************************/ +#ifdef L___parsegrent + +static const unsigned char gr_off[] = { + offsetof(struct group, gr_name), /* 0 */ + offsetof(struct group, gr_passwd), /* 1 */ + offsetof(struct group, gr_gid) /* 2 - not a char ptr */ +}; + +int attribute_hidden __parsegrent(void *data, char *line) +{ + char *endptr; + char *p; + int i; + char **members; + char *end_of_buf; + + end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */ + i = 0; + do { + p = ((char *) ((struct group *) data)) + gr_off[i]; + + if (i < 2) { + *((char **) p) = line; + if (!(line = strchr(line, ':'))) { + break; + } + *line++ = 0; + ++i; + } else { + *((gid_t *) p) = strtoul(line, &endptr, 10); + + /* NOTE: glibc difference - glibc allows omission of the + * trailing colon when there is no member list. We treat + * this as an error. */ + + /* Make sure we had at least one digit, and that the + * failing char is the next field seperator ':'. See + * glibc difference note above. */ + if ((endptr == line) || (*endptr != ':')) { + break; + } + + i = 1; /* Count terminating NULL ptr. */ + p = endptr; + + if (p[1]) { /* We have a member list to process. */ + /* Overwrite the last ':' with a ',' before counting. + * This allows us to test for initial ',' and adds + * one ',' so that the ',' count equals the member + * count. */ + *p = ','; + do { + /* NOTE: glibc difference - glibc allows and trims leading + * (but not trailing) space. We treat this as an error. */ + /* NOTE: glibc difference - glibc allows consecutive and + * trailing commas, and ignores "empty string" users. We + * treat this as an error. */ + if (*p == ',') { + ++i; + *p = 0; /* nul-terminate each member string. */ + if (!*++p || (*p == ',') || isspace(*p)) { + goto ERR; + } + } + } while (*++p); + } + + /* Now align (p+1), rounding up. */ + /* Assumes sizeof(char **) is a power of 2. */ + members = (char **)( (((intptr_t) p) + sizeof(char **)) + & ~((intptr_t)(sizeof(char **) - 1)) ); + + if (((char *)(members + i)) > end_of_buf) { /* No space. */ + break; + } + + ((struct group *) data)->gr_mem = members; + + if (--i) { + p = endptr; /* Pointing to char prior to first member. */ + do { + *members++ = ++p; + if (!--i) break; + while (*++p) {} + } while (1); + } + *members = NULL; + + return 0; + } + } while (1); + + ERR: + return -1; +} + +#endif +/**********************************************************************/ +#ifdef L___parsespent + +static const unsigned char sp_off[] = { + offsetof(struct spwd, sp_namp), /* 0 */ + offsetof(struct spwd, sp_pwdp), /* 1 */ + offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ + offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ + offsetof(struct spwd, sp_max), /* 4 - not a char ptr */ + offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */ + offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */ + offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */ + offsetof(struct spwd, sp_flag) /* 8 - not a char ptr */ +}; + +int attribute_hidden __parsespent(void *data, char * line) +{ + char *endptr; + char *p; + int i; + + i = 0; + do { + p = ((char *) ((struct spwd *) data)) + sp_off[i]; + if (i < 2) { + *((char **) p) = line; + if (!(line = strchr(line, ':'))) { + break; + } + } else { +#if 0 + if (i==5) { /* Support for old format. */ + while (isspace(*line)) ++line; /* glibc eats space here. */ + if (!*line) { + ((struct spwd *) data)->sp_warn = -1; + ((struct spwd *) data)->sp_inact = -1; + ((struct spwd *) data)->sp_expire = -1; + ((struct spwd *) data)->sp_flag = ~0UL; + return 0; + } + } +#endif + + *((long *) p) = (long) strtoul(line, &endptr, 10); + + if (endptr == line) { + *((long *) p) = ((i != 8) ? -1L : ((long)(~0UL))); + } + + line = endptr; + + if (i == 8) { + if (!*endptr) { + return 0; + } + break; + } + + if (*endptr != ':') { + break; + } + + } + + *line++ = 0; + ++i; + } while (1); + + return EINVAL; +} + +#endif +/**********************************************************************/ +#ifdef L___pgsreader + +/* Reads until if EOF, or until if finds a line which fits in the buffer + * and for which the parser function succeeds. + * + * Returns 0 on success and ENOENT for end-of-file (glibc concession). + */ + +int attribute_hidden __pgsreader(int (*__parserfunc)(void *d, char *line), void *data, + char *__restrict line_buff, size_t buflen, FILE *f) +{ + size_t line_len; + int skip; + int rv = ERANGE; + __STDIO_AUTO_THREADLOCK_VAR; + + if (buflen < __UCLIBC_PWD_BUFFER_SIZE__) { + __set_errno(rv); + } else { + __STDIO_AUTO_THREADLOCK(f); + + skip = 0; + do { + if (!fgets_unlocked(line_buff, buflen, f)) { + if (feof_unlocked(f)) { + rv = ENOENT; + } + break; + } + + line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */ + if (line_buff[line_len] == '\n') { + line_buff[line_len] = 0; + } else if (line_len + 2 == buflen) { /* line too long */ + ++skip; + continue; + } + + if (skip) { + --skip; + continue; + } + + /* NOTE: glibc difference - glibc strips leading whitespace from + * records. We do not allow leading whitespace. */ + + /* Skip empty lines, comment lines, and lines with leading + * whitespace. */ + if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) { + if (__parserfunc == __parsegrent) { /* Do evil group hack. */ + /* The group entry parsing function needs to know where + * the end of the buffer is so that it can construct the + * group member ptr table. */ + ((struct group *) data)->gr_name = line_buff + buflen; + } + + if (!__parserfunc(data, line_buff)) { + rv = 0; + break; + } + } + } while (1); + + __STDIO_AUTO_THREADUNLOCK(f); + } + + return rv; +} + +#endif +/**********************************************************************/ diff --git a/libc/pwd_grp/pwd_grp_internal.c b/libc/pwd_grp/pwd_grp_internal.c new file mode 100644 index 0000000..c897478 --- /dev/null +++ b/libc/pwd_grp/pwd_grp_internal.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Nov 6, 2003 Initial version. + * + * NOTE: This implementation is quite strict about requiring all + * field seperators. It also does not allow leading whitespace + * except when processing the numeric fields. glibc is more + * lenient. See the various glibc difference comments below. + * + * TODO: + * Move to dynamic allocation of (currently statically allocated) + * buffers; especially for the group-related functions since + * large group member lists will cause error returns. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_SHADOW__ +#include +#endif +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +/**********************************************************************/ +/* Sizes for statically allocated buffers. */ + +/* If you change these values, also change _SC_GETPW_R_SIZE_MAX and + * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */ +#define PWD_BUFFER_SIZE 256 +#define GRP_BUFFER_SIZE 256 + +/**********************************************************************/ +/* Prototypes for internal functions. */ + +#ifndef GETXXKEY_R_FUNC +#error GETXXKEY_R_FUNC is not defined! +#endif +/**********************************************************************/ +#ifdef GETXXKEY_R_FUNC + +libc_hidden_proto(GETXXKEY_R_FUNC) +int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key, + GETXXKEY_R_ENTTYPE *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + GETXXKEY_R_ENTTYPE **__restrict result) +{ + FILE *stream; + int rv; + + *result = NULL; + + if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) { + rv = errno; + } else { + __STDIO_SET_USER_LOCKING(stream); + do { + if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf, + buffer, buflen, stream)) + ) { + if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */ + *result = resultbuf; + break; + } + } else { + if (rv == ENOENT) { /* end-of-file encountered. */ + rv = 0; + } + break; + } + } while (1); + fclose(stream); + } + + return rv; +} +libc_hidden_def(GETXXKEY_R_FUNC) + +#endif +/**********************************************************************/ +#undef GETXXKEY_R_FUNC_HIDDEN +#undef GETXXKEY_R_FUNC +#undef GETXXKEY_R_PARSER +#undef GETXXKEY_R_ENTTYPE +#undef GETXXKEY_R_TEST +#undef DO_GETXXKEY_R_KEYTYPE +#undef DO_GETXXKEY_R_PATHNAME diff --git a/libc/pwd_grp/sgetspent.c b/libc/pwd_grp/sgetspent.c new file mode 100644 index 0000000..877a247 --- /dev/null +++ b/libc/pwd_grp/sgetspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sgetspent +#include "pwd_grp.c" diff --git a/libc/pwd_grp/sgetspent_r.c b/libc/pwd_grp/sgetspent_r.c new file mode 100644 index 0000000..131e0bd --- /dev/null +++ b/libc/pwd_grp/sgetspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sgetspent_r +#include "pwd_grp.c" diff --git a/libc/signal/Makefile b/libc/signal/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/signal/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/signal/Makefile.in b/libc/signal/Makefile.in new file mode 100644 index 0000000..e930d7e --- /dev/null +++ b/libc/signal/Makefile.in @@ -0,0 +1,34 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := allocrtsig.c killpg.c raise.c sigaction.c sigaddset.c sigandset.c \ + sigblock.c sigdelset.c sigempty.c sigfillset.c siggetmask.c \ + sigintr.c sigisempty.c sigismem.c sigjmp.c signal.c \ + sigorset.c sigpause.c sigsetmask.c sigsetops.c sigwait.c +ifeq ($(UCLIBC_HAS_OBSOLETE_BSD_SIGNAL),y) +CSRC += sighold.c sigignore.c sigrelse.c sigset.c +endif +ifeq ($(UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL),y) +CSRC += sysv_signal.c +endif + +ifneq ($(strip $(ARCH_OBJS)),) +CSRC := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)),$(CSRC)) +endif + +SIGNAL_DIR := $(top_srcdir)libc/signal +SIGNAL_OUT := $(top_builddir)libc/signal + +SIGNAL_SRC := $(patsubst %.c,$(SIGNAL_DIR)/%.c,$(CSRC)) +SIGNAL_OBJ := $(patsubst %.c,$(SIGNAL_OUT)/%.o,$(CSRC)) + +libc-y += $(SIGNAL_OBJ) + +objclean-y += signal_clean + +signal_clean: + $(do_rm) $(addprefix $(SIGNAL_OUT)/*., o os) diff --git a/libc/signal/allocrtsig.c b/libc/signal/allocrtsig.c new file mode 100644 index 0000000..3c7d621 --- /dev/null +++ b/libc/signal/allocrtsig.c @@ -0,0 +1,66 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Only enable rt signals when it is supported at compile time */ +#ifndef __NR_rt_sigaction +/* In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +static int current_rtmin = -1; +static int current_rtmax = -1; +#else +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +static int current_rtmin = __SIGRTMIN + 2; +# else +static int current_rtmin = __SIGRTMIN; +# endif +static int current_rtmax = __SIGRTMAX; +#endif + +/* Return number of available real-time signal with highest priority. */ +int __libc_current_sigrtmin (void) +{ + return current_rtmin; +} + +/* Return number of available real-time signal with lowest priority. */ +int __libc_current_sigrtmax (void) +{ + return current_rtmax; +} + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int __libc_allocate_rtsig (int high); +int __libc_allocate_rtsig (int high) +{ + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} diff --git a/libc/signal/killpg.c b/libc/signal/killpg.c new file mode 100644 index 0000000..46b6e4b --- /dev/null +++ b/libc/signal/killpg.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libc_hidden_proto(kill) + +/* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ +int +killpg (__pid_t pgrp, int sig) +{ + if (pgrp < 0) + { + __set_errno (EINVAL); + return -1; + } + + return kill (- pgrp, sig); +} diff --git a/libc/signal/raise.c b/libc/signal/raise.c new file mode 100644 index 0000000..28e5116 --- /dev/null +++ b/libc/signal/raise.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +libc_hidden_proto(getpid) +libc_hidden_proto(kill) + +int __raise (int signo) attribute_hidden; +int __raise(int signo) +{ + return kill(getpid(), signo); +} +libc_hidden_proto(raise) +weak_alias(__raise,raise) +libc_hidden_def(raise) diff --git a/libc/signal/sigaction.c b/libc/signal/sigaction.c new file mode 100644 index 0000000..88fb6b7 --- /dev/null +++ b/libc/signal/sigaction.c @@ -0,0 +1,115 @@ +/* Copyright (C) 1997-2000,2002,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* The difference here is that the sigaction structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include + +#ifndef LIBC_SIGACTION +extern __typeof(sigaction) __libc_sigaction; +#endif + +#if defined __NR_rt_sigaction + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + kact.sa_restorer = act->sa_restorer; +# endif + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = __syscall_rt_sigaction(sig, + act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + + return result; +} + +#else + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + kact.sa_restorer = act->sa_restorer; +# endif + } + + result = __syscall_sigaction(sig, + act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL); + + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + + return result; +} + +#endif + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/libc/signal/sigaddset.c b/libc/signal/sigaddset.c new file mode 100644 index 0000000..9840a56 --- /dev/null +++ b/libc/signal/sigaddset.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Add SIGNO to SET. */ +libc_hidden_proto(sigaddset) +int +sigaddset (sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigaddset (set, signo); +} +libc_hidden_def(sigaddset) diff --git a/libc/signal/sigandset.c b/libc/signal/sigandset.c new file mode 100644 index 0000000..dcc37da --- /dev/null +++ b/libc/signal/sigandset.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Combine sets LEFT and RIGHT by logical AND and place result in DEST. */ +int sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + if (dest == NULL || left == NULL || right == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigandset (dest, left, right); +} diff --git a/libc/signal/sigblock.c b/libc/signal/sigblock.c new file mode 100644 index 0000000..1f1a9fe --- /dev/null +++ b/libc/signal/sigblock.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1994-1998, 2001-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +libc_hidden_proto(sigprocmask) + +#include "sigset-cvt-mask.h" + +/* Block signals in MASK, returning the old mask. */ +libc_hidden_proto(sigblock) +int sigblock (int mask) +{ + sigset_t set, oset; + + if (sigset_set_old_mask (&set, mask) < 0) + return -1; + + if (sigprocmask (SIG_BLOCK, &set, &oset) < 0) + return -1; + + return sigset_get_old_mask (&oset); +} +libc_hidden_def(sigblock) diff --git a/libc/signal/sigdelset.c b/libc/signal/sigdelset.c new file mode 100644 index 0000000..de988a7 --- /dev/null +++ b/libc/signal/sigdelset.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1996, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Add SIGNO to SET. */ +libc_hidden_proto(sigdelset) +int sigdelset (sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigdelset (set, signo); +} +libc_hidden_def(sigdelset) diff --git a/libc/signal/sigempty.c b/libc/signal/sigempty.c new file mode 100644 index 0000000..7d8687b --- /dev/null +++ b/libc/signal/sigempty.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* Clear all signals from SET. */ +libc_hidden_proto(sigemptyset) +int sigemptyset (sigset_t *set) +{ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } + + memset (set, 0, sizeof (sigset_t)); + + return 0; +} +libc_hidden_def(sigemptyset) diff --git a/libc/signal/sigfillset.c b/libc/signal/sigfillset.c new file mode 100644 index 0000000..96ab459 --- /dev/null +++ b/libc/signal/sigfillset.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991,96,97,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* Set all signals in SET. */ +libc_hidden_proto(sigfillset) +int +sigfillset (sigset_t *set) +{ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } + + memset (set, 0xff, sizeof (sigset_t)); + + /* If the implementation uses a cancellation signal don't set the bit. */ +#ifdef SIGCANCEL + __sigdelset (set, SIGCANCEL); +#endif + /* Likewise for the signal to implement setxid. */ +#ifdef SIGSETXID + __sigdelset (set, SIGSETXID); +#endif + + return 0; +} +libc_hidden_def(sigfillset) diff --git a/libc/signal/siggetmask.c b/libc/signal/siggetmask.c new file mode 100644 index 0000000..d3af43a --- /dev/null +++ b/libc/signal/siggetmask.c @@ -0,0 +1,32 @@ +/* siggetmask -- useless alias for `sigblock (0)' for old Linux compatibility. + Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include + +libc_hidden_proto(sigblock) + +int +siggetmask (void) +{ + return sigblock (0); +} + +link_warning (siggetmask, + "warning: `siggetmask' is obsolete; `sigprocmask' is best") diff --git a/libc/signal/sighold.c b/libc/signal/sighold.c new file mode 100644 index 0000000..da723ac --- /dev/null +++ b/libc/signal/sighold.c @@ -0,0 +1,42 @@ +/* Add SIG to the calling process' signal mask. + Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_NULL +#include +#include + +libc_hidden_proto(sigprocmask) +libc_hidden_proto(sigaddset) + +int sighold (int sig) +{ + sigset_t set; + + /* Retrieve current signal set. */ + if (sigprocmask (SIG_SETMASK, NULL, &set) < 0) + return -1; + + /* Add the specified signal. */ + if (sigaddset (&set, sig) < 0) + return -1; + + /* Set the new mask. */ + return sigprocmask (SIG_SETMASK, &set, NULL); +} diff --git a/libc/signal/sigignore.c b/libc/signal/sigignore.c new file mode 100644 index 0000000..17d93ce --- /dev/null +++ b/libc/signal/sigignore.c @@ -0,0 +1,39 @@ +/* Set the disposition of SIG to SIG_IGN. + Copyright (C) 1998, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define __need_NULL +#include +#include +#include /* For the real memset prototype. */ + +libc_hidden_proto(sigaction) + +int sigignore (int sig) +{ + struct sigaction act; + + act.sa_handler = SIG_IGN; + if (__sigemptyset (&act.sa_mask) < 0) + return -1; + act.sa_flags = 0; + + return sigaction (sig, &act, NULL); +} diff --git a/libc/signal/sigintr.c b/libc/signal/sigintr.c new file mode 100644 index 0000000..4313637 --- /dev/null +++ b/libc/signal/sigintr.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1992, 1994, 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(sigaction) + +/* If INTERRUPT is nonzero, make signal SIG interrupt system calls + (causing them to fail with EINTR); if INTERRUPT is zero, make system + calls be restarted after signal SIG. */ +#ifdef SA_RESTART +extern sigset_t _sigintr attribute_hidden; /* Defined in signal.c. */ +#endif + +int siginterrupt (int sig, int interrupt) +{ +#ifdef SA_RESTART + struct sigaction action; + + if (sigaction (sig, (struct sigaction *) NULL, &action) < 0) + return -1; + + if (interrupt) + { + __sigaddset (&_sigintr, sig); + action.sa_flags &= ~SA_RESTART; + } + else + { + __sigdelset (&_sigintr, sig); + action.sa_flags |= SA_RESTART; + } + + if (sigaction (sig, &action, (struct sigaction *) NULL) < 0) + return -1; + + return 0; +#else + __set_errno (ENOSYS); + return -1; +#endif +} diff --git a/libc/signal/sigisempty.c b/libc/signal/sigisempty.c new file mode 100644 index 0000000..a25bb47 --- /dev/null +++ b/libc/signal/sigisempty.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Test whether SET is empty. */ +int sigisemptyset (const sigset_t *set) +{ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigisemptyset (set); +} diff --git a/libc/signal/sigismem.c b/libc/signal/sigismem.c new file mode 100644 index 0000000..b546f62 --- /dev/null +++ b/libc/signal/sigismem.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991,96,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Return 1 if SIGNO is in SET, 0 if not. */ +int sigismember (const sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigismember (set, signo); +} diff --git a/libc/signal/sigjmp.c b/libc/signal/sigjmp.c new file mode 100644 index 0000000..d143e93 --- /dev/null +++ b/libc/signal/sigjmp.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(sigprocmask) + +/* This function is called by the `sigsetjmp' macro + before doing a `__setjmp' on ENV[0].__jmpbuf. + Always return zero. */ + +int __sigjmp_save (sigjmp_buf env, int savemask) attribute_hidden; +int __sigjmp_save (sigjmp_buf env, int savemask) +{ + env[0].__mask_was_saved = (savemask && + sigprocmask (SIG_BLOCK, (sigset_t *) NULL, &env[0].__saved_mask) == 0); + + return 0; +} diff --git a/libc/signal/signal.c b/libc/signal/signal.c new file mode 100644 index 0000000..991a14f --- /dev/null +++ b/libc/signal/signal.c @@ -0,0 +1,57 @@ +/* BSD-like signal function. + Copyright (C) 1991,1992,1996,1997,2000,2002,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For the real memset prototype. */ + +libc_hidden_proto(sigaction) + +sigset_t _sigintr attribute_hidden; /* Set by siginterrupt. */ + +/* Set the handler for the signal SIG to HANDLER, + returning the old handler, or SIG_ERR on error. */ +extern __typeof(bsd_signal) __bsd_signal; +attribute_hidden __sighandler_t +__bsd_signal (int sig, __sighandler_t handler) +{ + struct sigaction act, oact; + + /* Check signal extents to protect __sigismember. */ + if (handler == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + + act.sa_handler = handler; + if (__sigemptyset (&act.sa_mask) < 0 + || __sigaddset (&act.sa_mask, sig) < 0) + return SIG_ERR; + act.sa_flags = __sigismember (&_sigintr, sig) ? 0 : SA_RESTART; + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} +strong_alias(__bsd_signal,bsd_signal) +libc_hidden_proto(signal) +strong_alias(__bsd_signal,signal) +libc_hidden_def(signal) diff --git a/libc/signal/sigorset.c b/libc/signal/sigorset.c new file mode 100644 index 0000000..3588cc4 --- /dev/null +++ b/libc/signal/sigorset.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Combine sets LEFT and RIGHT by logical OR and place result in DEST. */ +int sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + if (dest == NULL || left == NULL || right == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigorset (dest, left, right); +} diff --git a/libc/signal/sigpause.c b/libc/signal/sigpause.c new file mode 100644 index 0000000..8c99af0 --- /dev/null +++ b/libc/signal/sigpause.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1991,92,94-98,2000,2002,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +/* psm: need the BSD version of sigpause here */ +#include +#define __FAVOR_BSD +#include +#include /* For NULL. */ + +libc_hidden_proto(sigprocmask) +libc_hidden_proto(sigdelset) +libc_hidden_proto(sigsuspend) + +#include "sigset-cvt-mask.h" + +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +libc_hidden_proto(__sigpause) +int __sigpause (int sig_or_mask, int is_sig) +{ + sigset_t set; + + if (is_sig != 0) + { + /* The modern X/Open implementation is requested. */ + if (sigprocmask (0, NULL, &set) < 0 + /* Yes, we call `sigdelset' and not `__sigdelset'. */ + || sigdelset (&set, sig_or_mask) < 0) + return -1; + } + else if (sigset_set_old_mask (&set, sig_or_mask) < 0) + return -1; + + return sigsuspend (&set); +} +libc_hidden_def(__sigpause) + +#undef sigpause + +/* We have to provide a default version of this function since the + standards demand it. The version which is a bit more reasonable is + the BSD version. So make this the default. */ +libc_hidden_proto(sigpause) +int sigpause (int mask) +{ + return __sigpause (mask, 0); +} +libc_hidden_def(sigpause) diff --git a/libc/signal/sigrelse.c b/libc/signal/sigrelse.c new file mode 100644 index 0000000..8532a88 --- /dev/null +++ b/libc/signal/sigrelse.c @@ -0,0 +1,42 @@ +/* Remove SIG from the calling process' signal mask. + Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_NULL +#include +#include + +libc_hidden_proto(sigprocmask) +libc_hidden_proto(sigdelset) + +int sigrelse (int sig) +{ + sigset_t set; + + /* Retrieve current signal set. */ + if (sigprocmask (SIG_SETMASK, NULL, &set) < 0) + return -1; + + /* Remove the specified signal. */ + if (sigdelset (&set, sig) < 0) + return -1; + + /* Set the new mask. */ + return sigprocmask (SIG_SETMASK, &set, NULL); +} diff --git a/libc/signal/sigset-cvt-mask.h b/libc/signal/sigset-cvt-mask.h new file mode 100644 index 0000000..7b2f4cd --- /dev/null +++ b/libc/signal/sigset-cvt-mask.h @@ -0,0 +1,44 @@ +/* Convert between lowlevel sigmask and libc representation of sigset_t. + Linux version. + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joe Keane . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static __inline__ int __attribute__ ((unused)) +sigset_set_old_mask (sigset_t *set, int mask) +{ + unsigned long int *ptr; + int cnt; + + ptr = &set->__val[0]; + + *ptr++ = (unsigned int) mask; + + cnt = _SIGSET_NWORDS - 2; + do + *ptr++ = 0ul; + while (--cnt >= 0); + + return 0; +} + +static __inline__ int __attribute__ ((unused)) +sigset_get_old_mask (const sigset_t *set) +{ + return (unsigned int) set->__val[0]; +} diff --git a/libc/signal/sigset.c b/libc/signal/sigset.c new file mode 100644 index 0000000..db1fb7d --- /dev/null +++ b/libc/signal/sigset.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1998, 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define __need_NULL +#include +#include +#include /* For the real memset prototype. */ + +libc_hidden_proto(sigaction) +libc_hidden_proto(sigprocmask) + +/* Set the disposition for SIG. */ +__sighandler_t sigset (int sig, __sighandler_t disp) +{ + struct sigaction act, oact; + sigset_t set; + +#ifdef SIG_HOLD + /* Handle SIG_HOLD first. */ + if (disp == SIG_HOLD) + { + /* Create an empty signal set. */ + if (__sigemptyset (&set) < 0) + return SIG_ERR; + + /* Add the specified signal. */ + if (__sigaddset (&set, sig) < 0) + return SIG_ERR; + + /* Add the signal set to the current signal mask. */ + if (sigprocmask (SIG_BLOCK, &set, NULL) < 0) + return SIG_ERR; + + return SIG_HOLD; + } +#endif /* SIG_HOLD */ + + /* Check signal extents to protect __sigismember. */ + if (disp == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + + act.sa_handler = disp; + if (__sigemptyset (&act.sa_mask) < 0) + return SIG_ERR; + act.sa_flags = 0; + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + /* Create an empty signal set. */ + if (__sigemptyset (&set) < 0) + return SIG_ERR; + + /* Add the specified signal. */ + if (__sigaddset (&set, sig) < 0) + return SIG_ERR; + + /* Remove the signal set from the current signal mask. */ + if (sigprocmask (SIG_UNBLOCK, &set, NULL) < 0) + return SIG_ERR; + + return oact.sa_handler; +} diff --git a/libc/signal/sigsetmask.c b/libc/signal/sigsetmask.c new file mode 100644 index 0000000..2c07467 --- /dev/null +++ b/libc/signal/sigsetmask.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991,1994-1997,2001-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +libc_hidden_proto(sigprocmask) + +#include "sigset-cvt-mask.h" + +/* Set the mask of blocked signals to MASK, returning the old mask. */ +libc_hidden_proto(sigsetmask) +int +sigsetmask (int mask) +{ + sigset_t set, oset; + + if (sigset_set_old_mask (&set, mask) < 0) + return -1; + + if (sigprocmask (SIG_SETMASK, &set, &oset) < 0) + return -1; + + + return sigset_get_old_mask (&oset); +} +libc_hidden_def(sigsetmask) diff --git a/libc/signal/sigsetops.c b/libc/signal/sigsetops.c new file mode 100644 index 0000000..6f1ae5c --- /dev/null +++ b/libc/signal/sigsetops.c @@ -0,0 +1,11 @@ +/* Define the real-function versions of all inline functions + defined in signal.h (or bits/sigset.h). */ + +#include + +#define _EXTERN_INLINE +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif + +#include diff --git a/libc/signal/sigsetops.h b/libc/signal/sigsetops.h new file mode 100644 index 0000000..52081c2 --- /dev/null +++ b/libc/signal/sigsetops.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Definitions relevant to functions that operate on `sigset_t's. */ + +#include +#include +#include + +#define BITS (_NSIG - 1) +#define ELT(signo) (((signo) - 1) / BITS) +#define MASK(signo) (1 << (((signo) - 1) % BITS)) + +#undef sigemptyset +#undef sigfillset +#undef sigaddset +#undef sigdelset +#undef sigismember diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c new file mode 100644 index 0000000..99832f8 --- /dev/null +++ b/libc/signal/sigwait.c @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* sigwait + * + * Copyright (C) 2003 by Erik Andersen + * + * This program 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. */ + +#include +#include +#include + +#if defined __UCLIBC_HAS_REALTIME__ +libc_hidden_proto(sigwaitinfo) + +int __sigwait (const sigset_t *set, int *sig) attribute_hidden; +int __sigwait (const sigset_t *set, int *sig) +{ + int ret = 1; + if ((ret = sigwaitinfo(set, NULL)) != -1) { + *sig = ret; + return 0; + } + return 1; +} +#else /* __UCLIBC_HAS_REALTIME__ */ +/* variant without REALTIME extensions */ +libc_hidden_proto(sigfillset) +libc_hidden_proto(sigaction) +libc_hidden_proto(sigsuspend) + +static int was_sig; /* obviously not thread-safe */ +static void ignore_signal(int sig) +{ + was_sig = sig; +} +int __sigwait (const sigset_t *set, int *sig) attribute_hidden; +int __sigwait (const sigset_t *set, int *sig) +{ + sigset_t tmp_mask; + struct sigaction saved[NSIG]; + struct sigaction action; + int save_errno; + int this; + + /* Prepare set. */ + sigfillset (&tmp_mask); + + /* Unblock all signals in the SET and register our nice handler. */ + action.sa_handler = ignore_signal; + action.sa_flags = 0; + sigfillset (&action.sa_mask); /* Block all signals for handler. */ + + /* Make sure we recognize error conditions by setting WAS_SIG to a + value which does not describe a legal signal number. */ + was_sig = -1; + + for (this = 1; this < NSIG; ++this) + if (__sigismember (set, this)) + { + /* Unblock this signal. */ + __sigdelset (&tmp_mask, this); + + /* Register temporary action handler. */ + if (sigaction (this, &action, &saved[this]) != 0) + goto restore_handler; + } + + /* Now we can wait for signals. */ + sigsuspend (&tmp_mask); + + restore_handler: + save_errno = errno; + + while (--this >= 1) + if (__sigismember (set, this)) + /* We ignore errors here since we must restore all handlers. */ + sigaction (this, &saved[this], NULL); + + __set_errno (save_errno); + + /* Store the result and return. */ + *sig = was_sig; + return was_sig == -1 ? -1 : 0; +} +#endif /* __UCLIBC_HAS_REALTIME__ */ +libc_hidden_proto(sigwait) +weak_alias(__sigwait,sigwait) +libc_hidden_def(sigwait) diff --git a/libc/signal/sysv_signal.c b/libc/signal/sysv_signal.c new file mode 100644 index 0000000..6eebf20 --- /dev/null +++ b/libc/signal/sysv_signal.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For the real memset prototype. */ + +libc_hidden_proto(sigaction) + +/* Tolerate non-threads versions of Posix */ +#ifndef SA_ONESHOT +#define SA_ONESHOT 0 +#endif +#ifndef SA_NOMASK +#define SA_NOMASK 0 +#endif +#ifndef SA_INTERRUPT +#define SA_INTERRUPT 0 +#endif + +/* Set the handler for the signal SIG to HANDLER, + returning the old handler, or SIG_ERR on error. */ +__sighandler_t __sysv_signal (int sig, __sighandler_t handler) +{ + struct sigaction act, oact; + + /* Check signal extents to protect __sigismember. */ + if (handler == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + + act.sa_handler = handler; + if (__sigemptyset (&act.sa_mask) < 0) + return SIG_ERR; + act.sa_flags = SA_ONESHOT | SA_NOMASK | SA_INTERRUPT; + act.sa_flags &= ~SA_RESTART; + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} +strong_alias(__sysv_signal,sysv_signal) diff --git a/libc/stdio/.indent.pro b/libc/stdio/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/stdio/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/stdio/Makefile b/libc/stdio/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/stdio/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/stdio/Makefile.in b/libc/stdio/Makefile.in new file mode 100644 index 0000000..b9aecac --- /dev/null +++ b/libc/stdio/Makefile.in @@ -0,0 +1,107 @@ +# Makefile for uClibc +# +# Copyright (C) 2004 Manuel Novoa III +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. +# + +# SUSv3 functions +CSRC := \ + fclose.c fcloseall.c fdopen.c fgetpos.c fopen.c freopen.c \ + fseeko.c fsetpos.c ftello.c getdelim.c getline.c gets.c getw.c \ + perror.c puts.c putw.c remove.c rewind.c setbuf.c setbuffer.c \ + setlinebuf.c setvbuf.c ungetc.c \ + printf.c vprintf.c vsprintf.c fprintf.c snprintf.c dprintf.c \ + asprintf.c sprintf.c vasprintf.c vdprintf.c vsnprintf.c \ + tmpfile.c tmpnam.c tmpnam_r.c popen.c tempnam.c ctermid.c + +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += fgetpos64.c fopen64.c freopen64.c fseeko64.c fsetpos64.c ftello64.c +endif + +# getc -> alias for fgetc +# putc -> alias for fputc +# rename is a syscall + +# Implementation support functions +CSRC += \ + _READ.c _WRITE.c _adjust_pos.c _fopen.c _fwrite.c \ + _rfill.c _stdio.c _trans2r.c _trans2w.c _wcommit.c \ + _cs_funcs.c _load_inttype.c _store_inttype.c _uintmaxtostr.c +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += _fpmaxtostr.c +endif + +# stdio_ext.h functions +CSRC += \ + __fbufsize.c __flbf.c __fpending.c __fpurge.c __freadable.c \ + __freading.c __fsetlocking.c __fwritable.c __fwriting.c _flushlbf.c + +# Other glibc extensions +ifeq ($(UCLIBC_HAS_GLIBC_CUSTOM_STREAMS),y) +CSRC += fopencookie.c fmemopen.c open_memstream.c +endif + +# pthread functions +CSRC += flockfile.c ftrylockfile.c funlockfile.c + +# Functions with unlocked versions +CUSRC := \ + clearerr.c feof.c ferror.c fflush.c fgetc.c fgets.c fileno.c \ + fputc.c fputs.c fread.c fwrite.c getchar.c putchar.c +# getc_unlocked -> alias for fgetc_unlocked +# putc_unlocked -> alias for fputc_unlocked + +# vfprintf and support functions +ifneq ($(USE_OLD_VFPRINTF),y) +VF_CSRC := \ + vfprintf.c \ + _vfprintf_internal.c \ + _ppfs_init.c _ppfs_prepargs.c _ppfs_setargs.c _ppfs_parsespec.c \ + register_printf_function.c parse_printf_format.c +CSRC += $(VF_CSRC) +else +CSRC += old_vfprintf.c +endif + +# vfscanf and support functions plus other *scanf funcs +CSRC += \ + vfscanf.c __scan_cookie.c __psfs_parse_spec.c __psfs_do_numeric.c \ + scanf.c sscanf.c fscanf.c vscanf.c vsscanf.c + +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += _wfwrite.c fwprintf.c swprintf.c vswprintf.c vwprintf.c wprintf.c \ + fwide.c ungetwc.c +CUSRC += fgetwc.c getwchar.c fgetws.c fputwc.c putwchar.c fputws.c +# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias) +# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias) +CSRC += vfwprintf.c _vfwprintf_internal.c +CSRC += wscanf.c swscanf.c fwscanf.c vwscanf.c vswscanf.c vfwscanf.c +endif + +CUSRC_UNLOCKED := $(patsubst %.c,%_unlocked.c,$(CUSRC)) + +CSRC += $(CUSRC) $(CUSRC_UNLOCKED) + +STDIO_DIR := $(top_srcdir)libc/stdio +STDIO_OUT := $(top_builddir)libc/stdio + +STDIO_SRC := $(patsubst %.c,$(STDIO_DIR)/%.c,$(CSRC)) +STDIO_OBJ := $(patsubst %.c,$(STDIO_OUT)/%.o,$(CSRC)) + +libc-y += $(STDIO_OBJ) + +ifneq ($(USE_OLD_VFPRINTF),y) +libc-nomulti-y += $(patsubst %.c,$(STDIO_OUT)/%.o,$(VF_CSRC)) +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +libc-nomulti-y += $(STDIO_OUT)/vfwprintf.o $(STDIO_OUT)/vfwscanf.o +endif + +objclean-y += stdio_clean + +stdio_clean: + $(do_rm) $(addprefix $(STDIO_OUT)/*., o os oS) diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c new file mode 100644 index 0000000..bafa8df --- /dev/null +++ b/libc/stdio/_READ.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(read) +libc_hidden_proto(abort) + +/* Given a reading stream without its end-of-file indicator set and + * with no buffered input or ungots, read at most 'bufsize' bytes + * into 'buf' (which may be the stream's __bufstart). + * If a read error occurs, set the stream's error indicator. + * If EOF is encountered, set the stream's end-of-file indicator. + * + * Returns the number of bytes read, even in EOF and error cases. + * + * Notes: + * Calling with bufsize == 0 is NOT permitted (unlike __stdio_WRITE). + * NOT THREADSAFE! Assumes stream already locked if necessary. + */ + +size_t attribute_hidden __stdio_READ(register FILE *stream, + unsigned char *buf, size_t bufsize) +{ + ssize_t rv = 0; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_READING(stream)); + assert(!__STDIO_STREAM_BUFFER_RAVAIL(stream)); /* Buffer must be empty. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); + assert(bufsize); + + if (!__FEOF_UNLOCKED(stream)) { + if (bufsize > SSIZE_MAX) { + bufsize = SSIZE_MAX; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning EINTR? +#endif +/* RETRY: */ + if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { + if (rv == 0) { + __STDIO_STREAM_SET_EOF(stream); + } else { +/* if (errno == EINTR) goto RETRY; */ + __STDIO_STREAM_SET_ERROR(stream); + rv = 0; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make custom stream read return check optional. +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + } else { + assert(rv <= bufsize); + if (rv > bufsize) { /* Read more than bufsize! */ + abort(); + } +#endif + } + } + + return rv; +} diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c new file mode 100644 index 0000000..83714bd --- /dev/null +++ b/libc/stdio/_WRITE.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(write) + +/* Given a writing stream with no buffered output, write the + * data in 'buf' (which may be the stream's bufstart) of size + * 'bufsize' to the stream. If a write error occurs, set the + * stream's error indicator and (if buffering) buffer as much + * data as possible (FBF) or only up to '\n' (LBF) to implement + * "as if fputc()" clause in the standard. + * + * Returns the number of bytes written and/or buffered. + * + * Notes: + * Calling with bufsize == 0 is permitted, and buf is ignored in + * that case. + * We implement fflush() by setting bufpos to bufstart and passing + * bufstart as the buf arg. If there is a write error, the + * unwritten buffered data will simply be moved to the beginning + * of the buffer. Since the data obviously fits in the buffer + * and since there will be no '\n' chars in the buffer in the LBF + * case, no data will be lost. + * NOT THREADSAFE! Assumes stream already locked if necessary. + */ + +size_t attribute_hidden __stdio_WRITE(register FILE *stream, + register const unsigned char *buf, size_t bufsize) +{ + size_t todo; + ssize_t rv, stodo; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_WRITING(stream)); + assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */ + + todo = bufsize; + + do { + if (todo == 0) { /* Done? */ + __STDIO_STREAM_VALIDATE(stream); + return bufsize; + } + stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; + if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make custom stream write return check optional. +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + assert(rv <= stodo); + if (rv > stodo) { /* Wrote more than stodo! */ +/* abort(); */ + } +#endif + todo -= rv; + buf += rv; + } else +#ifdef __UCLIBC_MJN3_ONLY__ +#warning EINTR? +#endif +/* if (errno != EINTR) */ + { + __STDIO_STREAM_SET_ERROR(stream); + +#ifdef __STDIO_BUFFERS + if ((stodo = __STDIO_STREAM_BUFFER_SIZE(stream)) != 0) { + unsigned char *s; + + if (stodo > todo) { + stodo = todo; + } + + s = stream->__bufstart; + + do { + if (((*s = *buf) == '\n') + && __STDIO_STREAM_IS_LBF(stream) + ) { + break; + } + ++s; + ++buf; + } while (--stodo); + + stream->__bufpos = s; + + todo -= (s - stream->__bufstart); + } +#endif /* __STDIO_BUFFERS */ + + __STDIO_STREAM_VALIDATE(stream); + return bufsize - todo; + } + } while (1); +} diff --git a/libc/stdio/__fbufsize.c b/libc/stdio/__fbufsize.c new file mode 100644 index 0000000..09ade15 --- /dev/null +++ b/libc/stdio/__fbufsize.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns the size of the buffer in bytes.. + */ + +size_t __fbufsize(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_BUFFER_SIZE(stream); +} diff --git a/libc/stdio/__flbf.c b/libc/stdio/__flbf.c new file mode 100644 index 0000000..13d8cea --- /dev/null +++ b/libc/stdio/__flbf.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns nonzero if the stream is line buffered, and 0 otherwise. + */ + +int __flbf(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_LBF(stream); +} diff --git a/libc/stdio/__fpending.c b/libc/stdio/__fpending.c new file mode 100644 index 0000000..a7fe054 --- /dev/null +++ b/libc/stdio/__fpending.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns the number of bytes in the buffer for a writing stream. + * + * NOTE: GLIBC DIFFERENCE!!! + * + * glibc will return the number of wide chars pending for wide oriented + * streams. We always return the number of bytes in the buffer, as we + * convert wide chars to their multibyte encodings and buffer _those_. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +#warning Note: Unlike the glibc version, this __fpending returns bytes in buffer for wide streams too! + +link_warning(__fpending, "This version of __fpending returns bytes remaining in buffer for both narrow and wide streams. glibc's version returns wide chars in buffer for the wide stream case.") + +#endif + +size_t __fpending(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return (__STDIO_STREAM_IS_WRITING(stream)) + ? __STDIO_STREAM_BUFFER_WUSED(stream) + : 0; +} diff --git a/libc/stdio/__fpurge.c b/libc/stdio/__fpurge.c new file mode 100644 index 0000000..c17ecf4 --- /dev/null +++ b/libc/stdio/__fpurge.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Discard all buffered data whether reading or writing. + */ + +void __fpurge(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + stream->__ungot[1] = 0; + +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif + + stream->__modeflags &= ~(__MASK_READING|__FLAG_WRITING); + + __STDIO_STREAM_VALIDATE(stream); +} diff --git a/libc/stdio/__freadable.c b/libc/stdio/__freadable.c new file mode 100644 index 0000000..006a66f --- /dev/null +++ b/libc/stdio/__freadable.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if readable, and 0 if write-only. + */ + +int __freadable(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return !__STDIO_STREAM_IS_WRITEONLY(stream); +} diff --git a/libc/stdio/__freading.c b/libc/stdio/__freading.c new file mode 100644 index 0000000..aab91b2 --- /dev/null +++ b/libc/stdio/__freading.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if read-only or was last read from, and 0 otherwise. + */ + +int __freading(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_READING_OR_READONLY(stream); +} diff --git a/libc/stdio/__fsetlocking.c b/libc/stdio/__fsetlocking.c new file mode 100644 index 0000000..2e87100 --- /dev/null +++ b/libc/stdio/__fsetlocking.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(__fsetlocking) + +/* Not threadsafe. */ + +/* Notes: + * When setting the locking mode, glibc returns the previous setting. + * glibc treats invalid locking_mode args as FSETLOCKING_INTERNAL. + */ + +int __fsetlocking(FILE *stream, int locking_mode) +{ +#ifdef __UCLIBC_HAS_THREADS__ + int current = 1 + (stream->__user_locking & 1); + + /* Check constant assumptions. We can't test at build time + * since these are enums. */ + assert((FSETLOCKING_QUERY == 0) && (FSETLOCKING_INTERNAL == 1) + && (FSETLOCKING_BYCALLER == 2)); + + __STDIO_STREAM_VALIDATE(stream); + assert(((unsigned int) locking_mode) <= 2); + + if (locking_mode != FSETLOCKING_QUERY) { + stream->__user_locking = ((locking_mode == FSETLOCKING_BYCALLER) + ? 1 + : _stdio_user_locking); /* 0 or 2 */ + __STDIO_STREAM_VALIDATE(stream); + } + + return current; +#else + __STDIO_STREAM_VALIDATE(stream); + assert(((unsigned int) locking_mode) <= 2); + + return FSETLOCKING_INTERNAL; +#endif +} +libc_hidden_def(__fsetlocking) diff --git a/libc/stdio/__fwritable.c b/libc/stdio/__fwritable.c new file mode 100644 index 0000000..59c70a6 --- /dev/null +++ b/libc/stdio/__fwritable.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if writable, and 0 if read-only. + */ + +int __fwritable(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return !__STDIO_STREAM_IS_READONLY(stream); +} diff --git a/libc/stdio/__fwriting.c b/libc/stdio/__fwriting.c new file mode 100644 index 0000000..926eaa9 --- /dev/null +++ b/libc/stdio/__fwriting.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if write-only or was last written to, and 0 otherwise. + */ + +int __fwriting(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(stream); +} diff --git a/libc/stdio/__psfs_do_numeric.c b/libc/stdio/__psfs_do_numeric.c new file mode 100644 index 0000000..e371477 --- /dev/null +++ b/libc/stdio/__psfs_do_numeric.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_do_numeric +#include "_scanf.c" diff --git a/libc/stdio/__psfs_parse_spec.c b/libc/stdio/__psfs_parse_spec.c new file mode 100644 index 0000000..cac9cda --- /dev/null +++ b/libc/stdio/__psfs_parse_spec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_parse_spec +#include "_scanf.c" diff --git a/libc/stdio/__scan_cookie.c b/libc/stdio/__scan_cookie.c new file mode 100644 index 0000000..d5d53c4 --- /dev/null +++ b/libc/stdio/__scan_cookie.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___scan_cookie +#include "_scanf.c" diff --git a/libc/stdio/_adjust_pos.c b/libc/stdio/_adjust_pos.c new file mode 100644 index 0000000..bc6e905 --- /dev/null +++ b/libc/stdio/_adjust_pos.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Both ftell() and fseek() (for SEEK_CUR) need to correct the stream's + * position to take into account buffered data and ungotten chars. + * + * If successful, store corrected position in *pos and return >= 0. + * Otherwise return < 0. + * + * If position is unrepresentable, set errno to EOVERFLOW. + */ + +int attribute_hidden __stdio_adjust_position(register FILE * __restrict stream, + register __offmax_t *pos) +{ + __offmax_t oldpos; + int corr; + + if ((corr = stream->__modeflags & __MASK_READING) != 0) { + --corr; /* Correct for ungots. Assume narrow, and fix below. */ + } + +#ifdef __UCLIBC_HAS_WCHAR__ + if (corr && __STDIO_STREAM_IS_WIDE(stream)) { + /* A wide stream and we have at least one ungotten wchar. + * If it is a user ungot, we need to fail since position + * is unspecified as per C99. */ + if ((corr > 1) || stream->__ungot[1]) { /* User ungetwc, */ + return -1; /* so position is undefined. */ + } + corr -= (1 + stream->__ungot_width[1]); + if (stream->__state.__mask > 0) { /* Incomplete (bad?) mb char. */ + corr -= stream->__ungot_width[0]; + } + } +#endif + +#ifdef __STDIO_BUFFERS + corr += (((__STDIO_STREAM_IS_WRITING(stream)) + ? stream->__bufstart : stream->__bufread) + - stream->__bufpos); +#endif + + oldpos = *pos; + + /* Range checking cases: + * (pos - corr > pos) && (corr > 0) : underflow? return -corr < 0 + * (pos - corr > pos) && (corr < 0) : ok .. return -corr > 0 + * (pos - corr <= pos) && (corr >= 0) : ok .. return corr > 0 + * (pos - corr <= pos) && (corr < 0) : overflow .. return corr < 0 + */ + + if ((*pos -= corr) > oldpos) { + corr = -corr; + } + + if (corr < 0) { + __set_errno(EOVERFLOW); + } + + return corr; +} diff --git a/libc/stdio/_cs_funcs.c b/libc/stdio/_cs_funcs.c new file mode 100644 index 0000000..38a8351 --- /dev/null +++ b/libc/stdio/_cs_funcs.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2004-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(close) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lseek64) +#else +libc_hidden_proto(lseek) +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +/**********************************************************************/ + +ssize_t attribute_hidden _cs_read(void *cookie, char *buf, size_t bufsize) +{ + return read(*((int *) cookie), buf, bufsize); +} + +/**********************************************************************/ + +ssize_t attribute_hidden _cs_write(void *cookie, const char *buf, size_t bufsize) +{ + return write(*((int *) cookie), (char *) buf, bufsize); +} + +/**********************************************************************/ + +int attribute_hidden _cs_seek(void *cookie, register __offmax_t *pos, int whence) +{ + __offmax_t res; + +#ifdef __UCLIBC_HAS_LFS__ + res = lseek64(*((int *) cookie), *pos, whence); +#else + res = lseek(*((int *) cookie), *pos, whence); +#endif + + return (res >= 0) ? ((*pos = res), 0) : ((int) res); +} + +/**********************************************************************/ + +int attribute_hidden _cs_close(void *cookie) +{ + return close(*((int *) cookie)); +} + +/**********************************************************************/ +#else +/**********************************************************************/ + +int attribute_hidden __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) +{ + __offmax_t res; + +#ifdef __UCLIBC_HAS_LFS__ + res = lseek64(stream->__filedes, *pos, whence); +#else + res = lseek(stream->__filedes, *pos, whence); +#endif + + return (res >= 0) ? ((*pos = res), 0) : ((int) res); +} + +/**********************************************************************/ +#endif +/**********************************************************************/ diff --git a/libc/stdio/_flushlbf.c b/libc/stdio/_flushlbf.c new file mode 100644 index 0000000..8a551a7 --- /dev/null +++ b/libc/stdio/_flushlbf.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(fflush_unlocked) + +/* Solaris function -- + * Flush all line buffered (writing) streams. + */ + +void _flushlbf(void) +{ + __STDIO_FLUSH_LBF_STREAMS; +} diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c new file mode 100644 index 0000000..5243e33 --- /dev/null +++ b/libc/stdio/_fopen.c @@ -0,0 +1,223 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(isatty) +libc_hidden_proto(open) +libc_hidden_proto(fcntl) + +/* + * Cases: + * fopen64 : filename != NULL, stream == NULL, filedes == -2 + * fopen : filename != NULL, stream == NULL, filedes == -1 + * freopen : filename != NULL, stream != NULL, filedes == -1 + * fdopen : filename == NULL, stream == NULL, filedes valid + * + * fsfopen : filename != NULL, stream != NULL, filedes == -1 + */ + +#if (O_ACCMODE != 3) || (O_RDONLY != 0) || (O_WRONLY != 1) || (O_RDWR != 2) +#error Assumption violated - mode constants +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/* Internal function -- reentrant (locks open file list) */ + +FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, + register const char * __restrict mode, + register FILE * __restrict stream, int filedes) +{ + __mode_t open_mode; + int i; + + /* Parse the specified mode. */ + open_mode = O_RDONLY; + if (*mode != 'r') { /* Not read... */ + open_mode = (O_WRONLY | O_CREAT | O_TRUNC); + if (*mode != 'w') { /* Not write (create or truncate)... */ + open_mode = (O_WRONLY | O_CREAT | O_APPEND); + if (*mode != 'a') { /* Not write (create or append)... */ + DO_EINVAL: + __set_errno(EINVAL); /* So illegal mode. */ + if (stream) { + FREE_STREAM: + assert(!(stream->__modeflags & __FLAG_FREEBUF)); + __STDIO_STREAM_FREE_FILE(stream); + } + return NULL; + } + } + } + + if ((mode[1] == 'b')) { /* Binary mode (NO-OP currently). */ + ++mode; + } + + if (mode[1] == '+') { /* Read and Write. */ + ++mode; + open_mode |= (O_RDONLY | O_WRONLY); + open_mode += (O_RDWR - (O_RDONLY | O_WRONLY)); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Implement glibc ccs option to bind a codeset? +#warning CONSIDER: Implement glibc mmap option for readonly files? +#warning CONSIDER: Implement a text mode using custom read/write funcs? +#endif +#if defined(__UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__) || defined(__UCLIBC_HAS_FOPEN_LARGEFILE_MODE__) + + while (*++mode) { +# ifdef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ + if (*mode == 'x') { /* Open exclusive (a glibc extension). */ + open_mode |= O_EXCL; + continue; + } +# endif +# ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ + if (*mode == 'F') { /* Open as large file (uClibc extension). */ + open_mode |= O_LARGEFILE; + continue; + } +# endif + } + +#endif + + if (!stream) { /* Need to allocate a FILE (not freopen). */ + if ((stream = malloc(sizeof(FILE))) == NULL) { + return stream; + } + stream->__modeflags = __FLAG_FREEFILE; +#ifdef __STDIO_BUFFERS + stream->__bufstart = NULL; /* We allocate a buffer below. */ +#endif +#ifdef __UCLIBC_HAS_THREADS__ + /* We only initialize the mutex in the non-freopen case. */ + /* stream->__user_locking = _stdio_user_locking; */ + __stdio_init_mutex(&stream->__lock); +#endif + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify fdopen append behavior of glibc. +#endif + + if (filedes >= 0) { /* Handle fdopen trickery. */ + stream->__filedes = filedes; + /* NOTE: it is insufficient to just check R/W/RW agreement. + * We must also check largefile compatibility if applicable. + * Also, if append mode is desired for fdopen but O_APPEND isn't + * currently set, then set it as recommended by SUSv3. However, + * if append mode is not specified for fdopen but O_APPEND is set, + * leave it set (glibc compat). */ + i = (open_mode & (O_ACCMODE|O_LARGEFILE)) + 1; + + /* NOTE: fopencookie needs changing if the basic check changes! */ + if (((i & (((int) fname_or_mode) + 1)) != i) /* Basic agreement? */ + || (((open_mode & ~((__mode_t) fname_or_mode)) & O_APPEND) + && fcntl(filedes, F_SETFL, O_APPEND)) /* Need O_APPEND. */ + ) { + goto DO_EINVAL; + } + /* For later... to reflect largefile setting in stream flags. */ + __STDIO_WHEN_LFS( open_mode |= (((__mode_t) fname_or_mode) + & O_LARGEFILE) ); + } else { + __STDIO_WHEN_LFS( if (filedes < -1) open_mode |= O_LARGEFILE ); + if ((stream->__filedes = open(((const char *) fname_or_mode), + open_mode, 0666)) < 0) { + goto FREE_STREAM; + } + } + + stream->__modeflags &= __FLAG_FREEFILE; +/* stream->__modeflags &= ~(__FLAG_READONLY|__FLAG_WRITEONLY); */ + + stream->__modeflags |= /* Note: Makes assumptions about flag vals! */ +#if (O_APPEND != __FLAG_APPEND) || ((O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0)) +# if (O_APPEND != __FLAG_APPEND) + ((open_mode & O_APPEND) ? __FLAG_APPEND : 0) | +# else + (open_mode & O_APPEND) | +# endif +# if (O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0) + ((open_mode & O_LARGEFILE) ? __FLAG_LARGEFILE : 0) | +# else + (open_mode & O_LARGEFILE) | +# endif +#else + (open_mode & (O_APPEND|O_LARGEFILE)) | /* i386 linux and elks */ +#endif + ((((open_mode & O_ACCMODE) + 1) ^ 0x03) * __FLAG_WRITEONLY); + +#ifdef __STDIO_BUFFERS + i = errno; /* Preserve errno against isatty call. */ + stream->__modeflags |= (isatty(stream->__filedes) * __FLAG_LBF); + __set_errno(i); + + if (!stream->__bufstart) { + if ((stream->__bufstart = malloc(BUFSIZ)) != NULL) { + stream->__bufend = stream->__bufstart + BUFSIZ; + stream->__modeflags |= __FLAG_FREEBUF; + } else { +# if __STDIO_BUILTIN_BUF_SIZE > 0 + stream->__bufstart = stream->__builtinbuf; + stream->__bufend = stream->__builtinbuf + sizeof(stream->__builtinbuf); +# else /* __STDIO_BUILTIN_BUF_SIZE > 0 */ + stream->__bufend = stream->__bufstart; +# endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */ + } + } + + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); +#endif + + __STDIO_STREAM_RESET_GCS(stream); + +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + /* Even in the freopen case, we reset the user locking flag. */ + stream->__user_locking = _stdio_user_locking; + /* __stdio_init_mutex(&stream->__lock); */ +#endif + +#ifdef __STDIO_HAS_OPENLIST +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + if (!(stream->__modeflags & __FLAG_FREEFILE)) + { + /* An freopen call so the file was never removed from the list. */ + } + else +#endif + { + /* We have to lock the del mutex in case another thread wants to fclose() + * the last file. */ + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + stream->__nextopen = _stdio_openlist; /* New files are inserted at */ + _stdio_openlist = stream; /* the head of the list. */ + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; + } +#endif + + __STDIO_STREAM_VALIDATE(stream); + + return stream; +} diff --git a/libc/stdio/_fpmaxtostr.c b/libc/stdio/_fpmaxtostr.c new file mode 100644 index 0000000..b8d93a0 --- /dev/null +++ b/libc/stdio/_fpmaxtostr.c @@ -0,0 +1,766 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + + +/* Copyright (C) 2000, 2001, 2003 Manuel Novoa III + * + * Function: + * + * ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + * __fp_outfunc_t fp_outfunc); + * + * This is derived from the old _dtostr, whic I wrote for uClibc to provide + * floating point support for the printf functions. It handles +/- infinity, + * nan, and signed 0 assuming you have ieee arithmetic. It also now handles + * digit grouping (for the uClibc supported locales) and hexadecimal float + * notation. Finally, via the fp_outfunc parameter, it now supports wide + * output. + * + * Notes: + * + * At most DECIMAL_DIG significant digits are kept. Any trailing digits + * are treated as 0 as they are really just the results of rounding noise + * anyway. If you want to do better, use an arbitary precision arithmetic + * package. ;-) + * + * It should also be fairly portable, as no assumptions are made about the + * bit-layout of doubles. Of course, that does make it less efficient than + * it could be. + * + */ + +/*****************************************************************************/ +/* Don't change anything that follows unless you know what you're doing. */ +/*****************************************************************************/ +/* Fairly portable nan check. Bitwise for i386 generated larger code. + * If you have a better version, comment this out. + */ +#define isnan(x) ((x) != (x)) + +/* Without seminumerical functions to examine the sign bit, this is + * about the best we can do to test for '-0'. + */ +#define zeroisnegative(x) ((1./(x)) < 0) + +/*****************************************************************************/ +/* Don't change anything that follows peroid!!! ;-) */ +/*****************************************************************************/ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#if FLT_RADIX != 2 +#error FLT_RADIX != 2 is not currently supported +#endif +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +#define NUM_HEX_DIGITS ((FPMAX_MANT_DIG + 3)/ 4) + +/* WARNING: Adjust _fp_out_wide() below if this changes! */ +/* With 32 bit ints, we can get 9 decimal digits per block. */ +#define DIGITS_PER_BLOCK 9 +#define HEX_DIGITS_PER_BLOCK 8 + +/* Maximum number of subcases to output double is... + * 0 - sign + * 1 - padding and initial digit + * 2 - digits left of the radix + * 3 - 0s left of the radix or radix + * 4 - radix or digits right of the radix + * 5 - 0s right of the radix + * 6 - exponent + * 7 - trailing space padding + * although not all cases may occur. + */ +#define MAX_CALLS 8 + +/*****************************************************************************/ + +#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) +#define NUM_HEX_DIGIT_BLOCKS \ + ((NUM_HEX_DIGITS+HEX_DIGITS_PER_BLOCK-1)/HEX_DIGITS_PER_BLOCK) + +/* WARNING: Adjust _fp_out_wide() below if this changes! */ + +/* extra space for '-', '.', 'e+###', and nul */ +#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) + +/*****************************************************************************/ + +static const char fmt[] = "inf\0INF\0nan\0NAN\0.\0,"; + +#define INF_OFFSET 0 /* must be 1st */ +#define NAN_OFFSET 8 /* must be 2nd.. see hex sign handling */ +#define DECPT_OFFSET 16 +#define THOUSEP_OFFSET 18 + +#define EMPTY_STRING_OFFSET 3 + +/*****************************************************************************/ +#if FPMAX_MAX_10_EXP < -FPMAX_MIN_10_EXP +#error scaling code can not handle FPMAX_MAX_10_EXP < -FPMAX_MIN_10_EXP +#endif + +static const __fpmax_t exp10_table[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, /* floats */ +#if FPMAX_MAX_10_EXP < 32 +#error unsupported FPMAX_MAX_10_EXP (< 32). ANSI/ISO C requires >= 37. +#endif +#if FPMAX_MAX_10_EXP >= 64 + 1e64L, +#endif +#if FPMAX_MAX_10_EXP >= 128 + 1e128L, +#endif +#if FPMAX_MAX_10_EXP >= 256 + 1e256L, +#endif +#if FPMAX_MAX_10_EXP >= 512 + 1e512L, +#endif +#if FPMAX_MAX_10_EXP >= 1024 + 1e1024L, +#endif +#if FPMAX_MAX_10_EXP >= 2048 + 1e2048L, +#endif +#if FPMAX_MAX_10_EXP >= 4096 + 1e4096L +#endif +#if FPMAX_MAX_10_EXP >= 8192 +#error unsupported FPMAX_MAX_10_EXP. please increase table +#endif +}; + +#define EXP10_TABLE_SIZE (sizeof(exp10_table)/sizeof(exp10_table[0])) +#define EXP10_TABLE_MAX (1U<<(EXP10_TABLE_SIZE-1)) + +/*****************************************************************************/ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + +#if FLT_RADIX != 2 +#error FLT_RADIX != 2 is not currently supported +#endif + +#if FPMAX_MAX_EXP < -FPMAX_MIN_EXP +#error scaling code can not handle FPMAX_MAX_EXP < -FPMAX_MIN_EXP +#endif + +static const __fpmax_t exp16_table[] = { + 0x1.0p4L, 0x1.0p8L, 0x1.0p16L, 0x1.0p32L, 0x1.0p64L, +#if FPMAX_MAX_EXP >= 128 + 0x1.0p128L, +#endif +#if FPMAX_MAX_EXP >= 256 + 0x1.0p256L, +#endif +#if FPMAX_MAX_EXP >= 512 + 0x1.0p512L, +#endif +#if FPMAX_MAX_EXP >= 1024 + 0x1.0p1024L, +#endif +#if FPMAX_MAX_EXP >= 2048 + 0x1.0p2048L, +#endif +#if FPMAX_MAX_EXP >= 4096 + 0x1.0p4096L, +#endif +#if FPMAX_MAX_EXP >= 8192 + 0x1.0p8192L, +#endif +#if FPMAX_MAX_EXP >= 16384 + 0x1.0p16384L +#endif +#if FPMAX_MAX_EXP >= 32768 +#error unsupported FPMAX_MAX_EXP. please increase table +#endif +}; + +#define EXP16_TABLE_SIZE (sizeof(exp16_table)/sizeof(exp16_table[0])) +#define EXP16_TABLE_MAX (1U<<(EXP16_TABLE_SIZE-1)) + +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +/*****************************************************************************/ + +#define FPO_ZERO_PAD (0x80 | '0') +#define FPO_STR_WIDTH (0x80 | ' '); +#define FPO_STR_PREC 'p' + +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) +{ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + __fpmax_t lower_bnd; + __fpmax_t upper_bnd = 1e9; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + uint_fast32_t base = 10; + const __fpmax_t *power_table; + int dpb = DIGITS_PER_BLOCK; + int ndb = NUM_DIGIT_BLOCKS; + int nd = DECIMAL_DIG; + int sufficient_precision = 0; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + int num_groups = 0; + int initial_group; /* This does not need to be initialized. */ + int tslen; /* This does not need to be initialized. */ + int nblk2; /* This does not need to be initialized. */ + const char *ts; /* This does not need to be initialized. */ +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + int round, o_exp; + int exp; + int width, preci; + int cnt; + char *s; + char *e; + intptr_t pc_fwi[3*MAX_CALLS]; + intptr_t *ppc; + intptr_t *ppc_last; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: The size of exp_buf[] should really be determined by the float constants. +#endif /* __UCLIBC_MJN3_ONLY__ */ + char exp_buf[16]; + char buf[BUF_SIZE]; + char sign_str[6]; /* Last 2 are for 1st digit + nul. */ + char o_mode; + char mode; + + + width = info->width; + preci = info->prec; + mode = info->spec; + + *exp_buf = 'e'; + if ((mode|0x20) == 'a') { +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + *exp_buf = 'p'; + if (preci < 0) { + preci = NUM_HEX_DIGITS; + sufficient_precision = 1; + } +#else + mode += ('g' - 'a'); +#endif + } + + if (preci < 0) { + preci = 6; + } + + *sign_str = '\0'; + if (PRINT_INFO_FLAG_VAL(info,showsign)) { + *sign_str = '+'; + } else if (PRINT_INFO_FLAG_VAL(info,space)) { + *sign_str = ' '; + } + + *(sign_str+1) = 0; + pc_fwi[5] = INF_OFFSET; + if (isnan(x)) { /* First, check for nan. */ + pc_fwi[5] = NAN_OFFSET; + goto INF_NAN; + } + + if (x == 0) { /* Handle 0 now to avoid false positive. */ +#ifdef __UCLIBC_HAVE_SIGNED_ZERO__ + if (zeroisnegative(x)) { /* Handle 'signed' zero. */ + *sign_str = '-'; + } +#endif /* __UCLIBC_HAVE_SIGNED_ZERO__ */ + exp = -1; + goto GENERATE_DIGITS; + } + + if (x < 0) { /* Convert negatives to positives. */ + *sign_str = '-'; + x = -x; + } + + if (__FPMAX_ZERO_OR_INF_CHECK(x)) { /* Inf since zero handled above. */ + INF_NAN: + info->pad = ' '; + ppc = pc_fwi + 6; + pc_fwi[3] = FPO_STR_PREC; + pc_fwi[4] = 3; + if (mode < 'a') { + pc_fwi[5] += 4; + } + pc_fwi[5] = (intptr_t)(fmt + pc_fwi[5]); + goto EXIT_SPECIAL; + } + + { + int i, j; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Clean up defines when hexadecimal float notation is unsupported. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + + if ((mode|0x20) == 'a') { + lower_bnd = 0x1.0p31L; + upper_bnd = 0x1.0p32L; + power_table = exp16_table; + exp = HEX_DIGITS_PER_BLOCK - 1; + i = EXP16_TABLE_SIZE; + j = EXP16_TABLE_MAX; + dpb = HEX_DIGITS_PER_BLOCK; + ndb = NUM_HEX_DIGIT_BLOCKS; + nd = NUM_HEX_DIGITS; + base = 16; + } else { + lower_bnd = 1e8; + /* upper_bnd = 1e9; */ + power_table = exp10_table; + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; + /* dpb = DIGITS_PER_BLOCK; */ + /* ndb = NUM_DIGIT_BLOCKS; */ + /* base = 10; */ + } + + + +#else /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +#define lower_bnd 1e8 +#define upper_bnd 1e9 +#define power_table exp10_table +#define dpb DIGITS_PER_BLOCK +#define base 10 +#define ndb NUM_DIGIT_BLOCKS +#define nd DECIMAL_DIG + + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; + +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + { + int exp_neg = 0; + if (x < lower_bnd) { /* Do we need to scale up or down? */ + exp_neg = 1; + } + + do { + --i; + if (exp_neg) { + if (x * power_table[i] < upper_bnd) { + x *= power_table[i]; + exp -= j; + } + } else { + if (x / power_table[i] >= lower_bnd) { + x /= power_table[i]; + exp += j; + } + } + j >>= 1; + } while (i); + } + } + if (x >= upper_bnd) { /* Handle bad rounding case. */ + x /= power_table[0]; + ++exp; + } + assert(x < upper_bnd); + + GENERATE_DIGITS: + { + int i, j; + s = buf + 2; /* Leave space for '\0' and '0'. */ + i = 0; + do { + uint_fast32_t digit_block = (uint_fast32_t) x; + assert(digit_block < upper_bnd); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Can rounding be a problem? +#endif /* __UCLIBC_MJN3_ONLY__ */ + x = (x - digit_block) * upper_bnd; + s += dpb; + j = 0; + do { + s[- ++j] = '0' + (digit_block % base); + digit_block /= base; + } while (j < dpb); + } while (++i < ndb); + } + + /*************************************************************************/ + + if (mode < 'a') { + *exp_buf -= ('a' - 'A'); /* e->E and p->P */ + mode += ('a' - 'A'); + } + + o_mode = mode; + if ((mode == 'g') && (preci > 0)){ + --preci; + } + round = preci; + + if (mode == 'f') { + round += exp; + if (round < -1) { + memset(buf, '0', DECIMAL_DIG); /* OK, since 'f' -> decimal case. */ + exp = -1; + round = -1; + } + } + + s = buf; + *s++ = 0; /* Terminator for rounding and 0-triming. */ + *s = '0'; /* Space to round. */ + + { + int i; + i = 0; + e = s + nd + 1; + if (round < nd) { + e = s + round + 2; + if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */ + i = 1; + } + } + + do { /* Handle rounding and trim trailing 0s. */ + *--e += i; /* Add the carry. */ + } while ((*e == '0') || (*e > '0' - 1 + base)); + } + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + if ((mode|0x20) == 'a') { + char *q; + + for (q = e ; *q ; --q) { + if (*q > '9') { + *q += (*exp_buf - ('p' - 'a') - '9' - 1); + } + } + + if (e > s) { + exp *= 4; /* Change from base 16 to base 2. */ + } + } +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + o_exp = exp; + if (e <= s) { /* We carried into an extra digit. */ + ++o_exp; + e = s; /* Needed if all 0s. */ + } else { + ++s; + } + *++e = 0; /* Terminating nul char. */ + + if ((mode == 'g') && ((o_exp >= -4) && (o_exp <= round))) { + mode = 'f'; + preci = round - o_exp; + } + + exp = o_exp; + if (mode != 'f') { + o_exp = 0; + } + + if (o_exp < 0) { /* Exponent is < 0, so */ + *--s = '0'; /* fake the first 0 digit. */ + } + + pc_fwi[3] = FPO_ZERO_PAD; + pc_fwi[4] = 1; + pc_fwi[5] = (intptr_t)(sign_str + 4); + sign_str[4] = *s++; + sign_str[5] = 0; + ppc = pc_fwi + 6; + + { + int i = e - s; /* Total digits is 'i'. */ + if (o_exp >= 0) { +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + const char *p; + + if (PRINT_INFO_FLAG_VAL(info,group) + && *(p = __UCLIBC_CURLOCALE_DATA.grouping) + ) { + int nblk1; + + nblk2 = nblk1 = *p; + if (*++p) { + nblk2 = *p; + assert(!*++p); + } + + if (o_exp >= nblk1) { + num_groups = (o_exp - nblk1) / nblk2 + 1; + initial_group = (o_exp - nblk1) % nblk2; + +#ifdef __UCLIBC_HAS_WCHAR__ + if (PRINT_INFO_FLAG_VAL(info,wide)) { + /* _fp_out_wide() will fix this up. */ + ts = fmt + THOUSEP_OFFSET; + tslen = 1; + } else { +#endif /* __UCLIBC_HAS_WCHAR__ */ + ts = __UCLIBC_CURLOCALE_DATA.thousands_sep; + tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; +#ifdef __UCLIBC_HAS_WCHAR__ + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + + width -= num_groups * tslen; + } + } + + +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + ppc[0] = FPO_STR_PREC; + ppc[2] = (intptr_t)(s); + if (o_exp >= i) { /* all digit(s) left of decimal */ + ppc[1] = i; + ppc += 3; + o_exp -= i; + i = 0; + if (o_exp>0) { /* have 0s left of decimal */ + ppc[0] = FPO_ZERO_PAD; + ppc[1] = o_exp; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } else if (o_exp > 0) { /* decimal between digits */ + ppc[1] = o_exp; + ppc += 3; + s += o_exp; + i -= o_exp; + } + o_exp = -1; + } + + if (PRINT_INFO_FLAG_VAL(info,alt) + || (i) + || ((o_mode != 'g') +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + && (o_mode != 'a') +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + && (preci > 0)) + ) { + ppc[0] = FPO_STR_PREC; +#ifdef __LOCALE_C_ONLY + ppc[1] = 1; + ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); +#else /* __LOCALE_C_ONLY */ +#ifdef __UCLIBC_HAS_WCHAR__ + if (PRINT_INFO_FLAG_VAL(info,wide)) { + /* _fp_out_wide() will fix this up. */ + ppc[1] = 1; + ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); + } else { +#endif /* __UCLIBC_HAS_WCHAR__ */ + ppc[1] = __UCLIBC_CURLOCALE_DATA.decimal_point_len; + ppc[2] = (intptr_t)(__UCLIBC_CURLOCALE_DATA.decimal_point); +#ifdef __UCLIBC_HAS_WCHAR__ + } +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __LOCALE_C_ONLY */ + ppc += 3; + } + + if (++o_exp < 0) { /* Have 0s right of decimal. */ + ppc[0] = FPO_ZERO_PAD; + ppc[1] = -o_exp; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + if (i) { /* Have digit(s) right of decimal. */ + ppc[0] = FPO_STR_PREC; + ppc[1] = i; + ppc[2] = (intptr_t)(s); + ppc += 3; + } + + if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt)) +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + && !sufficient_precision +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + ) { + i -= o_exp; + if (i < preci) { /* Have 0s right of digits. */ + i = preci - i; + ppc[0] = FPO_ZERO_PAD; + ppc[1] = i; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } + } + + /* Build exponent string. */ + if (mode != 'f') { + char *p = exp_buf + sizeof(exp_buf); + int j; + char exp_char = *exp_buf; + char exp_sign = '+'; +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + int min_exp_dig_plus_2 = ((o_mode != 'a') ? (2+2) : (2+1)); +#else /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#define min_exp_dig_plus_2 (2+2) +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + if (exp < 0) { + exp_sign = '-'; + exp = -exp; + } + + *--p = 0; /* nul-terminate */ + j = 2; /* Count exp_char and exp_sign. */ + do { + *--p = '0' + (exp % 10); + exp /= 10; + } while ((++j < min_exp_dig_plus_2) || exp); /* char+sign+mindigits */ + *--p = exp_sign; + *--p = exp_char; + + ppc[0] = FPO_STR_PREC; + ppc[1] = j; + ppc[2] = (intptr_t)(p); + ppc += 3; + } + + EXIT_SPECIAL: + { + int i; + ppc_last = ppc; + ppc = pc_fwi + 4; /* Need width fields starting with second. */ + do { + width -= *ppc; + ppc += 3; + } while (ppc < ppc_last); + + ppc = pc_fwi; + ppc[0] = FPO_STR_WIDTH; + ppc[1] = i = ((*sign_str) != 0); + ppc[2] = (intptr_t) sign_str; + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */ + /* Hex and not inf or nan, so prefix with 0x. */ + char *h = sign_str + i; + *h = '0'; + *++h = 'x' - 'p' + *exp_buf; + *++h = 0; + ppc[1] = (i += 2); + } +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + if ((width -= i) > 0) { + if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */ + ppc_last[0] = FPO_STR_WIDTH; + ppc_last[1] = width; + ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc_last += 3; + } else if (info->pad == '0') { /* 0 padding */ + ppc[4] += width; /* Pad second field. */ + } else { + ppc[1] += width; /* Pad first (sign) field. */ + } + } + + cnt = 0; + } + + do { +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + if ((ppc == pc_fwi + 6) && num_groups) { + const char *gp = (const char *) ppc[2]; + int len = ppc[1]; + int blk = initial_group; + + cnt += num_groups * tslen; /* Adjust count now for sep chars. */ + +/* __printf("\n"); */ + do { + if (!blk) { /* Initial group could be 0 digits long! */ + blk = nblk2; + } else if (len >= blk) { /* Enough digits for a group. */ +/* __printf("norm: len=%d blk=%d \"%.*s\"\n", len, blk, blk, gp); */ + if (fp_outfunc(fp, *ppc, blk, (intptr_t) gp) != blk) { + return -1; + } + assert(gp); + if (*gp) { + gp += blk; + } + len -= blk; + } else { /* Transition to 0s. */ +/* __printf("trans: len=%d blk=%d \"%.*s\"\n", len, blk, len, gp); */ + if (len) { +/* __printf("len\n"); */ + if (fp_outfunc(fp, *ppc, len, (intptr_t) gp) != len) { + return -1; + } + gp += len; + } + + if (ppc[3] == FPO_ZERO_PAD) { /* Need to group 0s */ +/* __printf("zeropad\n"); */ + cnt += ppc[1]; + ppc += 3; + gp = (const char *) ppc[2]; + blk -= len; /* blk > len, so blk still > 0. */ + len = ppc[1]; + continue; /* Don't decrement num_groups here. */ + } else { + assert(num_groups == 0); + break; + } + } + + if (num_groups <= 0) { + break; + } + --num_groups; + + if (fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts) != tslen) { + return -1; + } + blk = nblk2; + +/* __printf("num_groups=%d blk=%d\n", num_groups, blk); */ + + } while (1); + } else + +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + { /* NOTE: Remember 'else' above! */ + if (fp_outfunc(fp, *ppc, ppc[1], ppc[2]) != ppc[1]) { + return -1; + } + } + + cnt += ppc[1]; + ppc += 3; + } while (ppc < ppc_last); + + return cnt; +} diff --git a/libc/stdio/_fwrite.c b/libc/stdio/_fwrite.c new file mode 100644 index 0000000..ba4b02f --- /dev/null +++ b/libc/stdio/_fwrite.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Experimentally off - libc_hidden_proto(memchr) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memrchr) */ + +#ifdef __STDIO_BUFFERS + +/* Either buffer data or (commit buffer if necessary and) write. */ + +size_t attribute_hidden __stdio_fwrite(const unsigned char * __restrict buffer, + size_t bytes, + register FILE * __restrict stream) +{ + size_t pending; + const unsigned char *p; + + __STDIO_STREAM_VALIDATE(stream); + assert(__STDIO_STREAM_IS_WRITING(stream)); + assert(buffer); + assert(bytes); + + if (!__STDIO_STREAM_IS_NBF(stream)) { /* FBF or LBF. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Try to consolidate some of the code? +#endif + if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) { + pending = __STDIO_STREAM_BUFFER_WAVAIL(stream); + if (pending > bytes) { + pending = bytes; + } + memcpy(stream->__bufpos, buffer, pending); + stream->__bufpos += pending; + __STDIO_STREAM_VALIDATE(stream); + return bytes; + } + +/* RETRY: */ + if (bytes <= __STDIO_STREAM_BUFFER_WAVAIL(stream)) { + memcpy(stream->__bufpos, buffer, bytes); + stream->__bufpos += bytes; + if (__STDIO_STREAM_IS_LBF(stream) + && memrchr(buffer, '\n', bytes) /* Search backwards. */ + ) { + if ((pending = __STDIO_COMMIT_WRITE_BUFFER(stream)) > 0) { + if (pending > bytes) { + pending = bytes; + } + buffer += (bytes - pending); + if ((p = memchr(buffer, '\n', pending)) != NULL) { + pending = (buffer + pending) - p; + bytes -= pending; + stream->__bufpos -= pending; + } + } + } + __STDIO_STREAM_VALIDATE(stream); + return bytes; + } + /* FBF or LBF and not enough space in buffer. */ + if (__STDIO_STREAM_BUFFER_WUSED(stream)) { /* Buffered data. */ + if (__STDIO_COMMIT_WRITE_BUFFER(stream)) { /* Commit failed! */ + return 0; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Do we want to try again if data now fits in buffer? +#endif +/* goto RETRY; */ + } + } + + return __stdio_WRITE(stream, buffer, bytes); +} + +#endif diff --git a/libc/stdio/_load_inttype.c b/libc/stdio/_load_inttype.c new file mode 100644 index 0000000..057f5f2 --- /dev/null +++ b/libc/stdio/_load_inttype.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) attribute_hidden; +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) +{ + if (uflag >= 0) { /* unsigned */ +#if LONG_MAX != INT_MAX + if (desttype & (PA_FLAG_LONG|PA_FLAG_LONG_LONG)) { +#ifdef LLONG_MAX + if (desttype == PA_FLAG_LONG_LONG) { + return *((unsigned long long int *) src); + } +#endif + return *((unsigned long int *) src); + } +#else /* LONG_MAX != INT_MAX */ +#ifdef LLONG_MAX + if (desttype & PA_FLAG_LONG_LONG) { + return *((unsigned long long int *) src); + } +#endif +#endif /* LONG_MAX != INT_MAX */ + { + unsigned int x; + x = *((unsigned int *) src); + if (desttype == __PA_FLAG_CHAR) x = (unsigned char) x; +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) x = (unsigned short int) x; +#endif + return x; + } + } else { /* signed */ +#if LONG_MAX != INT_MAX + if (desttype & (PA_FLAG_LONG|PA_FLAG_LONG_LONG)) { +#ifdef LLONG_MAX + if (desttype == PA_FLAG_LONG_LONG) { + return *((long long int *) src); + } +#endif + return *((long int *) src); + } +#else /* LONG_MAX != INT_MAX */ +#ifdef LLONG_MAX + if (desttype & PA_FLAG_LONG_LONG) { + return *((long long int *) src); + } +#endif +#endif /* LONG_MAX != INT_MAX */ + { + int x; + x = *((int *) src); + if (desttype == __PA_FLAG_CHAR) x = (char) x; +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) x = (short int) x; +#endif + return x; + } + } +} diff --git a/libc/stdio/_ppfs_init.c b/libc/stdio/_ppfs_init.c new file mode 100644 index 0000000..80d8aeb --- /dev/null +++ b/libc/stdio/_ppfs_init.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_init +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_parsespec.c b/libc/stdio/_ppfs_parsespec.c new file mode 100644 index 0000000..a3e2988 --- /dev/null +++ b/libc/stdio/_ppfs_parsespec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_parsespec +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_prepargs.c b/libc/stdio/_ppfs_prepargs.c new file mode 100644 index 0000000..a6efbf4 --- /dev/null +++ b/libc/stdio/_ppfs_prepargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_prepargs +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_setargs.c b/libc/stdio/_ppfs_setargs.c new file mode 100644 index 0000000..41214d9 --- /dev/null +++ b/libc/stdio/_ppfs_setargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_setargs +#include "_vfprintf.c" diff --git a/libc/stdio/_rfill.c b/libc/stdio/_rfill.c new file mode 100644 index 0000000..d61b1a9 --- /dev/null +++ b/libc/stdio/_rfill.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Do we really need a seperate rfill function? +#endif + +#ifdef __STDIO_BUFFERS + +/* Read some data into the buffer. + * Returns number of bytes read into the buffer. + * If 0 is returned, then either EOF or ERROR. + * Side effects are those of _stdio_READ. + */ + +size_t attribute_hidden __stdio_rfill(register FILE *__restrict stream) +{ + size_t rv; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_READING(stream)); + assert(!__STDIO_STREAM_BUFFER_RAVAIL(stream)); /* Buffer must be empty. */ + assert(__STDIO_STREAM_BUFFER_SIZE(stream)); /* Must have a buffer. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +#endif + + rv = __stdio_READ(stream, stream->__bufstart, + stream->__bufend - stream->__bufstart); + stream->__bufpos = stream->__bufstart; + stream->__bufread = stream->__bufstart + rv; + + __STDIO_STREAM_VALIDATE(stream); + return rv; +} + +#endif diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c new file mode 100644 index 0000000..3b004d5 --- /dev/null +++ b/libc/stdio/_scanf.c @@ -0,0 +1,2260 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Aug 1, 2003 + * New *scanf implementation with lots of bug fixes and *wscanf support. + * Also now optionally supports hexadecimal float notation, positional + * args, and glibc locale-specific digit grouping. Should now be + * standards compliant. + * + * Aug 18, 2003 + * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error, + * even when just starting a new mb char. + * Bug fix: wscanf would incorrectly unget in certain situations. + * + * Sep 5, 2003 + * Bug fix: store flag wasn't respected if no positional args. + * Implement vs{n}scanf for the non-buffered stdio no-wchar case. + * + * Sep 13, 2003 + * Bug fix: Fix a problem reported by Atsushi Nemoto + * for environments where long and long long are the same. + * + * Sep 21, 2003 + * Ugh... EOF handling by scanf was completely broken. :-( Regretably, + * I got my mind fixed in one mode and didn't comply with the standards. + * Things should be fixed now, but comparision testing is difficult when + * glibc's scanf is broken and they stubbornly refuse to even acknowledge + * that it is... even when confronted by specific examples from the C99 + * standards and from an official C standard defect report. + */ + +#define _ISOC99_SOURCE /* for LLONG_MAX primarily... */ +#include +#include "_stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#include +#include +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#include +#include + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#include +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#include +#include +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(ungetc) +libc_hidden_proto(vfscanf) +libc_hidden_proto(vsscanf) +libc_hidden_proto(fclose) +libc_hidden_proto(getc_unlocked) +libc_hidden_proto(__fgetc_unlocked) +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(wcslen) +libc_hidden_proto(vfwscanf) +libc_hidden_proto(vswscanf) +libc_hidden_proto(mbsrtowcs) +libc_hidden_proto(mbrtowc) +libc_hidden_proto(wcrtomb) +libc_hidden_proto(ungetwc) +libc_hidden_proto(iswspace) +libc_hidden_proto(fgetwc_unlocked) +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#ifdef L_vfscanf +/* only emit this once */ +#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented! +#endif +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#endif + +#undef __STDIO_HAS_VSSCANF +#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSSCANF 1 + +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) +typedef struct { + FILE f; + unsigned char *bufread; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsscanf; +#endif + +#endif + +extern void _store_inttype(void *dest, int desttype, uintmax_t val); + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +extern unsigned long long +_stdlib_strto_ll(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag); +#if (ULLONG_MAX == UINTMAX_MAX) +#define STRTOUIM(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf) +#endif + +#else /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +extern unsigned long +_stdlib_strto_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag); + +#if (ULONG_MAX == UINTMAX_MAX) +#define STRTOUIM(s,e,b,sf) _stdlib_strto_l(s,e,b,sf) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#ifndef STRTOUIM +#error STRTOUIM conversion function is undefined! +#endif + +/**********************************************************************/ + +/* The standards require EOF < 0. */ +#if EOF >= CHAR_MIN +#define __isdigit_char_or_EOF(C) __isdigit_char((C)) +#else +#define __isdigit_char_or_EOF(C) __isdigit_int((C)) +#endif + +/**********************************************************************/ +#ifdef L_fscanf + +libc_hidden_proto(fscanf) +int fscanf(FILE * __restrict stream, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfscanf(stream, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(fscanf) + +#endif +/**********************************************************************/ +#ifdef L_scanf + +int scanf(const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfscanf(stdin, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_sscanf + +#ifdef __STDIO_HAS_VSSCANF + +libc_hidden_proto(sscanf) +int sscanf(const char * __restrict str, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsscanf(str, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(sscanf) + +#else /* __STDIO_HAS_VSSCANF */ +#warning Skipping sscanf since no vsscanf! +#endif /* __STDIO_HAS_VSSCANF */ + +#endif +/**********************************************************************/ +#ifdef L_vscanf + +libc_hidden_proto(vscanf) +int vscanf(const char * __restrict format, va_list arg) +{ + return vfscanf(stdin, format, arg); +} +libc_hidden_def(vscanf) + +#endif +/**********************************************************************/ +#ifdef L_vsscanf + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Implement vsscanf for non-buf and no custom stream case. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __STDIO_BUFFERS + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + FILE f; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES; + f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.__lock); +#endif + f.__nextopen = NULL; + + /* Set these last since __bufgetc initialization depends on + * __user_locking and only gets set if user locking is on. */ + f.__bufstart = + f.__bufpos = (unsigned char *) ((void *) sp); + f.__bufread = + f.__bufend = f.__bufstart + strlen(sp); + __STDIO_STREAM_ENABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + + return vfscanf(&f, fmt, ap); +} +libc_hidden_def(vsscanf) + +#elif !defined(__UCLIBC_HAS_WCHAR__) + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + __FILE_vsscanf f; + + f.bufpos = (unsigned char *) ((void *) sp); + f.bufread = f.bufpos + strlen(sp); + +/* __STDIO_STREAM_RESET_GCS(&f.f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.f.__cookie = &(f.f.__filedes); + f.f.__gcs.read = NULL; + f.f.__gcs.write = NULL; + f.f.__gcs.seek = NULL; + f.f.__gcs.close = NULL; +#endif + + f.f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB; + f.f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); + +/* #ifdef __UCLIBC_HAS_WCHAR__ */ +/* f.f.__ungot_width[0] = 0; */ +/* #endif */ +#ifdef __STDIO_MBSTATE +#error __STDIO_MBSTATE is defined! +/* __INIT_MBSTATE(&(f.f.__state)); */ +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + f.f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.f.__lock); +#endif + f.f.__nextopen = NULL; + + return vfscanf(&f.f, fmt, ap); +} +libc_hidden_def(vsscanf) + +#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + FILE *f; + int rv = EOF; + + if ((f = fmemopen((char *)sp, strlen(sp), "r")) != NULL) { + rv = vfscanf(f, fmt, ap); + fclose(f); + } + + return rv; +} +libc_hidden_def(vsscanf) + +#else +#warning Skipping vsscanf since no buffering, no custom streams, and wchar enabled! +#ifdef __STDIO_HAS_VSSCANF +#error WHOA! __STDIO_HAS_VSSCANF is defined! +#endif +#endif + +#endif +/**********************************************************************/ +#ifdef L_fwscanf + +int fwscanf(FILE * __restrict stream, const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwscanf(stream, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_wscanf + +int wscanf(const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwscanf(stdin, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_swscanf + +#ifdef __STDIO_BUFFERS + +int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, + ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vswscanf(str, format, arg); + va_end(arg); + + return rv; +} +#else /* __STDIO_BUFFERS */ +#warning Skipping swscanf since no buffering! +#endif /* __STDIO_BUFFERS */ + +#endif +/**********************************************************************/ +#ifdef L_vwscanf + +int vwscanf(const wchar_t * __restrict format, va_list arg) +{ + return vfwscanf(stdin, format, arg); +} + +#endif +/**********************************************************************/ +#ifdef L_vswscanf + +#ifdef __STDIO_BUFFERS + +int vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, + va_list arg) +{ + FILE f; + + f.__bufstart = + f.__bufpos = (char *) str; + f.__bufread = + f.__bufend = (char *)(str + wcslen(str)); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSWSCANF_FILEDES; + f.__modeflags = (__FLAG_WIDE|__FLAG_READONLY|__FLAG_READING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + +#ifdef __UCLIBC_HAS_THREADS__ + f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.__lock); +#endif + f.__nextopen = NULL; + + return vfwscanf(&f, format, arg); +} +libc_hidden_def(vswscanf) +#else /* __STDIO_BUFFERS */ +#warning Skipping vswscanf since no buffering! +#endif /* __STDIO_BUFFERS */ + +#endif +/**********************************************************************/ +/**********************************************************************/ + + + +/* float layout 0123456789012345678901 repeat n for "l[" */ +#define SPEC_CHARS "npxXoudifFeEgGaACSncs[" +/* npxXoudif eEgG CS cs[ */ + +/* NOTE: Ordering is important! In particular, CONV_LEFTBRACKET + * must immediately precede CONV_c. */ + +enum { + CONV_n = 0, + CONV_p, + CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, + CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, + CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket, + CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */ +}; + +#ifdef __UCLIBC_HAS_FLOATS__ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +#else +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10 } +#endif +#else /* __UCLIBC_HAS_FLOATS__ */ +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0 } +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_vfscanf +/* emit once */ +#warning CONSIDER: Add a '0' flag to eat 0 padding when grouping? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#define SPEC_FLAGS "*'I" + +enum { + FLAG_SURPRESS = 0x10, /* MUST BE 1ST!! See DO_FLAGS. */ + FLAG_THOUSANDS = 0x20, + FLAG_I18N = 0x40, /* only works for d, i, u */ + FLAG_MALLOC = 0x80, /* only works for s, S, and [ (and l[)*/ +}; + + +#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ + CONV_C, CONV_LEFTBRACKET, \ + CONV_c, CONV_leftbracket } + +/* Note: We treat L and ll as synonymous... for ints and floats. */ + +#define SPEC_ALLOWED_FLAGS { \ + /* n */ (0x0f|FLAG_SURPRESS), \ + /* p */ ( 0|FLAG_SURPRESS), \ + /* oxXudi */ (0x0f|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ + /* fFeEgGaA */ (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ + /* C */ ( 0|FLAG_SURPRESS), \ + /* S and l[ */ ( 0|FLAG_SURPRESS|FLAG_MALLOC), \ + /* c */ (0x04|FLAG_SURPRESS), \ + /* s and [ */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \ +} + + +/**********************************************************************/ +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +/* TODO -- Fix the table below to take into account stdint.h. */ +/* #ifndef LLONG_MAX */ +/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ +/* #else */ +/* #if LLONG_MAX != INTMAX_MAX */ +/* #error fix QUAL_CHARS intmax_t entry 'j'! */ +/* #endif */ +/* #endif */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int q:long_long */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, 0, /* TODO -- fix!!! */\ + 1, 8 } + + +/**********************************************************************/ + +#ifdef L_vfwscanf +#if WINT_MIN > EOF +#error Unfortunately, we currently need wint_t to be able to store EOF. Sorry. +#endif +#define W_EOF WEOF +#define Wint wint_t +#define Wchar wchar_t +#define Wuchar __uwchar_t +#define ISSPACE(C) iswspace((C)) +#define VFSCANF vfwscanf +#define GETC(SC) (SC)->sc_getc((SC)) +#else +typedef unsigned char __uchar_t; +#define W_EOF EOF +#define Wint int +#define Wchar char +#define Wuchar __uchar_t +#define ISSPACE(C) isspace((C)) +#define VFSCANF vfscanf +#ifdef __UCLIBC_HAS_WCHAR__ +#define GETC(SC) (SC)->sc_getc((SC)) +#else /* __UCLIBC_HAS_WCHAR__ */ +#define GETC(SC) getc_unlocked((SC)->fp) +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif + +struct scan_cookie { + Wint cc; + Wint ungot_char; + FILE *fp; + int nread; + int width; + +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t app_ungot; /* Match FILE struct member type. */ + unsigned char ungot_wchar_width; +#else /* __UCLIBC_HAS_WCHAR__ */ + unsigned char app_ungot; /* Match FILE struct member type. */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + char ungot_flag; + +#ifdef __UCLIBC_HAS_WCHAR__ + char ungot_wflag; /* vfwscanf */ + char mb_fail; /* vfscanf */ + mbstate_t mbstate; /* vfscanf */ + wint_t wc; + wint_t ungot_wchar; /* to support __scan_getc */ + int (*sc_getc)(struct scan_cookie *); +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + const char *grouping; + const unsigned char *thousands_sep; + int tslen; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t thousands_sep_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ + const unsigned char *decpt; + int decpt_len; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t decpt_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ + const unsigned char *fake_decpt; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +}; + +typedef struct { +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) +#if NL_ARGMAX > 10 +#warning NL_ARGMAX > 10, and space is allocated on the stack for positional args. +#endif + void *pos_args[NL_ARGMAX]; + int num_pos_args; /* Must start at -1. */ + int cur_pos_arg; +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + void *cur_ptr; + const unsigned char *fmt; + int cnt, dataargtype, conv_num, max_width; + unsigned char store, flags; +} psfs_t; /* parse scanf format state */ + + +/**********************************************************************/ +/**********************************************************************/ + +extern void __init_scan_cookie(register struct scan_cookie *sc, + register FILE *fp) attribute_hidden; +extern int __scan_getc(register struct scan_cookie *sc) attribute_hidden; +extern void __scan_ungetc(register struct scan_cookie *sc) attribute_hidden; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern int __scan_strtold(long double *ld, struct scan_cookie *sc); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +extern int __psfs_parse_spec(psfs_t *psfs) attribute_hidden; +extern int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) attribute_hidden; + +/**********************************************************************/ +#ifdef L___scan_cookie + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Remove dependence on decpt_str and fake_decpt in stub locale mode. +#endif +#ifndef __UCLIBC_HAS_LOCALE__ +static const char decpt_str[] = "."; +#endif + +void attribute_hidden __init_scan_cookie(register struct scan_cookie *sc, + register FILE *fp) +{ + sc->fp = fp; + sc->nread = 0; + sc->ungot_flag = 0; + sc->app_ungot = ((fp->__modeflags & __FLAG_UNGOT) ? fp->__ungot[1] : 0); +#ifdef __UCLIBC_HAS_WCHAR__ + sc->ungot_wflag = 0; /* vfwscanf */ + sc->mb_fail = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (*(sc->grouping = __UCLIBC_CURLOCALE_DATA.grouping)) { + sc->thousands_sep = __UCLIBC_CURLOCALE_DATA.thousands_sep; + sc->tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; +#ifdef __UCLIBC_HAS_WCHAR__ + sc->thousands_sep_wc = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ + } +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#ifdef __UCLIBC_HAS_LOCALE__ + sc->decpt = __UCLIBC_CURLOCALE_DATA.decimal_point; + sc->decpt_len = __UCLIBC_CURLOCALE_DATA.decimal_point_len; +#else /* __UCLIBC_HAS_LOCALE__ */ + sc->fake_decpt = sc->decpt = (unsigned char *) decpt_str; + sc->decpt_len = 1; +#endif /* __UCLIBC_HAS_LOCALE__ */ +#ifdef __UCLIBC_HAS_WCHAR__ +#ifdef __UCLIBC_HAS_LOCALE__ + sc->decpt_wc = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; +#else + sc->decpt_wc = '.'; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __UCLIBC_HAS_FLOATS__ */ + +} + +int attribute_hidden __scan_getc(register struct scan_cookie *sc) +{ + int c; + +#ifdef __UCLIBC_HAS_WCHAR__ + assert(!sc->mb_fail); +#endif /* __UCLIBC_HAS_WCHAR__ */ + + sc->cc = EOF; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + if (sc->ungot_flag == 0) { +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) + if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { + c = GETC(sc); + } else { + __FILE_vsscanf *fv = (__FILE_vsscanf *)(sc->fp); + if (fv->bufpos < fv->bufread) { + c = *fv->bufpos++; + } else { + c = EOF; + sc->fp->__modeflags |= __FLAG_EOF; + } + } + if (c == EOF) { + sc->ungot_flag |= 2; + return -1; + } +#else + if ((c = GETC(sc)) == EOF) { + sc->ungot_flag |= 2; + return -1; + } +#endif + sc->ungot_char = c; + } else { + assert(sc->ungot_flag == 1); + sc->ungot_flag = 0; + } + + ++sc->nread; + return sc->cc = sc->ungot_char; +} + +void attribute_hidden __scan_ungetc(register struct scan_cookie *sc) +{ + ++sc->width; + if (sc->ungot_flag == 2) { /* last was EOF */ + sc->ungot_flag = 0; + sc->cc = sc->ungot_char; + } else if (sc->ungot_flag == 0) { + sc->ungot_flag = 1; + --sc->nread; + } else { + assert(0); + } +} + +#endif +/**********************************************************************/ +#ifdef L___psfs_parse_spec + +#ifdef SPEC_FLAGS +static const unsigned char spec_flags[] = SPEC_FLAGS; +#endif /* SPEC_FLAGS */ +static const unsigned char spec_chars[] = SPEC_CHARS; +static const unsigned char qual_chars[] = QUAL_CHARS; +static const unsigned char spec_ranges[] = SPEC_RANGES; +static const unsigned short spec_allowed[] = SPEC_ALLOWED_FLAGS; + +int attribute_hidden __psfs_parse_spec(register psfs_t *psfs) +{ + const unsigned char *p; + const unsigned char *fmt0 = psfs->fmt; + int i; +#ifdef SPEC_FLAGS + int j; +#endif +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + unsigned char fail = 0; + + i = 0; /* Do this here to avoid a warning. */ + + if (!__isdigit_char(*psfs->fmt)) { /* Not a positional arg. */ + fail = 1; + goto DO_FLAGS; + } + + /* parse the positional arg (or width) value */ + do { + if (i <= ((INT_MAX - 9)/10)) { + i = (i * 10) + (*psfs->fmt++ - '0'); + } + } while (__isdigit_char(*psfs->fmt)); + + if (*psfs->fmt != '$') { /* This is a max field width. */ + if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ + goto ERROR_EINVAL; + } + psfs->max_width = i; + psfs->num_pos_args = -2; + goto DO_QUALIFIER; + } + ++psfs->fmt; /* Advance past '$'. */ +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + +#if defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) + DO_FLAGS: +#endif /* defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) */ +#ifdef SPEC_FLAGS + p = spec_flags; + j = FLAG_SURPRESS; + do { + if (*p == *psfs->fmt) { + ++psfs->fmt; + psfs->flags |= j; + goto DO_FLAGS; + } + j += j; + } while (*++p); + + if (psfs->flags & FLAG_SURPRESS) { /* Suppress assignment. */ + psfs->store = 0; + goto DO_WIDTH; + } +#else /* SPEC_FLAGS */ + if (*psfs->fmt == '*') { /* Suppress assignment. */ + ++psfs->fmt; + psfs->store = 0; + goto DO_WIDTH; + } +#endif /* SPEC_FLAGS */ + + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + if (fail) { + /* Must be a non-positional arg */ + if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ + goto ERROR_EINVAL; + } + psfs->num_pos_args = -2; + } else { + if ((psfs->num_pos_args == -2) || (((unsigned int)(--i)) >= NL_ARGMAX)) { + /* Already saw a non-pos arg or (0-based) num too large. */ + goto ERROR_EINVAL; + } + psfs->cur_pos_arg = i; + } +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + + DO_WIDTH: + for (i = 0 ; __isdigit_char(*psfs->fmt) ; ) { + if (i <= ((INT_MAX - 9)/10)) { + i = (i * 10) + (*psfs->fmt++ - '0'); + psfs->max_width = i; + } + } + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + DO_QUALIFIER: +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + p = qual_chars; + do { + if (*psfs->fmt == *p) { + ++psfs->fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*psfs->fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++psfs->fmt; + } + psfs->dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we validate that psfs->max_width > 0 in __psfs_parse_spec()? It would avoid whitespace consumption... +#warning CONSIDER: Should INT_MAX be a valid width (%c/%C)? See __psfs_parse_spec(). +#endif /* __UCLIBC_MJN3_ONLY__ */ + + p = spec_chars; + do { + if (*psfs->fmt == *p) { + int p_m_spec_chars = p - spec_chars; + +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#error implement gnu a flag + if ((*p == 'a') + && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's')) + ) { /* Assumes ascii for 's' and 'S' test. */ + psfs->flags |= FLAG_MALLOC; + ++psfs->fmt; + ++p; + continue; /* The related conversions follow 'a'. */ + } +#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ + + for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {} + if (((psfs->dataargtype >> 8) | psfs->flags) + & ~spec_allowed[(int)(p - spec_ranges)] + ) { + goto ERROR_EINVAL; + } + + if ((p_m_spec_chars >= CONV_c) + && (psfs->dataargtype & PA_FLAG_LONG)) { + p_m_spec_chars -= 3; /* lc -> C, ls -> S, l[ -> ?? */ + } + + psfs->conv_num = p_m_spec_chars; + return psfs->fmt - fmt0; + } + if (!*++p) { + ERROR_EINVAL: + __set_errno(EINVAL); + return -1; + } + } while(1); + + assert(0); +} + +#endif +/**********************************************************************/ +#if defined(L_vfscanf) || defined(L_vfwscanf) + +#ifdef __UCLIBC_HAS_WCHAR__ +#ifdef L_vfscanf +static int sc_getc(register struct scan_cookie *sc) +{ + return (getc_unlocked)(sc->fp); /* Disable the macro. */ +} + +static int scan_getwc(register struct scan_cookie *sc) +{ + size_t r; + int width; + wchar_t wc[1]; + char b[1]; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + width = sc->width; /* Preserve width. */ + sc->width = INT_MAX; /* MB_CUR_MAX can invoke a function. */ + + assert(!sc->mb_fail); + + r = (size_t)(-3); + while (__scan_getc(sc) >= 0) { + *b = sc->cc; + + r = mbrtowc(wc, b, 1, &sc->mbstate); + if (((ssize_t) r) >= 0) { /* Successful completion of a wc. */ + sc->wc = *wc; + goto SUCCESS; + } else if (r == ((size_t) -2)) { + /* Potentially valid but incomplete. */ + continue; + } + break; + } + + if (r == ((size_t)(-3))) { /* EOF or ERROR on first read */ + sc->wc = WEOF; + r = (size_t)(-1); + } else { + /* If we reach here, either r == ((size_t)-1) and + * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) + * and stream is in an error state or at EOF with a + * partially complete wchar. */ + __set_errno(EILSEQ); /* In case of incomplete conversion. */ + sc->mb_fail = 1; + } + + SUCCESS: + sc->width = width; /* Restore width. */ + + return (int)((ssize_t) r); +} + +#endif /* L_vfscanf */ + +#ifdef L_vfwscanf + +/* This gets called by __scan_getc. __scan_getc is called by vfwscanf + * when the next wide char is expected to be valid ascii (digits). + */ +static int sc_getc(register struct scan_cookie *sc) +{ + wint_t wc; + + if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { + if (sc->fp->__bufpos < sc->fp->__bufend) { + wc = *((wchar_t *)(sc->fp->__bufpos)); + sc->fp->__bufpos += sizeof(wchar_t); + } else { + sc->fp->__modeflags |= __FLAG_EOF; + return EOF; + } + } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { + return EOF; + } + + sc->ungot_wflag = 1; + sc->ungot_wchar = wc; + sc->ungot_wchar_width = sc->fp->__ungot_width[0]; + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (wc == sc->thousands_sep_wc) { + wc = ','; + } else +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (wc == sc->decpt_wc) { + wc = '.'; + } else +#endif /* __UCLIBC_HAS_FLOATS__ */ + sc->wc = sc->ungot_char = wc; + + return (int) wc; +} + +static int scan_getwc(register struct scan_cookie *sc) +{ + wint_t wc; + + sc->wc = WEOF; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + if (sc->ungot_flag == 0) { + if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { + if (sc->fp->__bufpos < sc->fp->__bufend) { + wc = *((wchar_t *)(sc->fp->__bufpos)); + sc->fp->__bufpos += sizeof(wchar_t); + } else { + sc->ungot_flag |= 2; + return -1; + } + } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { + sc->ungot_flag |= 2; + return -1; + } + sc->ungot_wflag = 1; + sc->ungot_char = wc; + sc->ungot_wchar_width = sc->fp->__ungot_width[0]; + } else { + assert(sc->ungot_flag == 1); + sc->ungot_flag = 0; + } + + ++sc->nread; + sc->wc = sc->ungot_char; + + return 0; +} + + +#endif /* L_vfwscanf */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + +static __inline void kill_scan_cookie(register struct scan_cookie *sc) +{ +#ifdef L_vfscanf + + if (sc->ungot_flag & 1) { +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) + if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { + ungetc(sc->ungot_char, sc->fp); + } +#else + ungetc(sc->ungot_char, sc->fp); +#endif + /* Deal with distiction between user and scanf ungots. */ + if (sc->nread == 0) { /* Only one char was read... app ungot? */ + sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ + } else { + sc->fp->__ungot[1] = 0; + } + } + +#else + + if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1) + && !__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp) + && (sc->fp->__state.__mask == 0) + ) { + ungetwc(sc->ungot_char, sc->fp); + /* Deal with distiction between user and scanf ungots. */ + if (sc->nread == 0) { /* Only one char was read... app ungot? */ + sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ + } else { + sc->fp->__ungot[1] = 0; + } + sc->fp->__ungot_width[1] = sc->ungot_wchar_width; + } + +#endif +} + +#ifdef L_vfwscanf +#ifdef __UCLIBC_HAS_FLOATS__ +static const char fake_decpt_str[] = "."; +#endif +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ +static const char fake_thousands_sep_str[] = ","; +#endif +#endif /* L_vfwscanf */ + + +int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) +{ + const Wuchar *fmt; + unsigned char *b; + + +#ifdef L_vfwscanf + wchar_t wbuf[1]; + wchar_t *wb; +#endif /* L_vfwscanf */ + +#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) || !defined(L_vfscanf) + mbstate_t mbstate; +#endif + + struct scan_cookie sc; + psfs_t psfs; + + int i; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! +#endif +#define MAX_DIGITS 65 /* Allow one leading 0. */ + unsigned char buf[MAX_DIGITS+2]; +#ifdef L_vfscanf + unsigned char scanset[UCHAR_MAX + 1]; + unsigned char invert; /* Careful! Meaning changes. */ +#endif /* L_vfscanf */ + unsigned char fail; + unsigned char zero_conversions = 1; + __STDIO_AUTO_THREADLOCK_VAR; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make checking of the format string in C locale an option. +#endif + /* To support old programs, don't check mb validity if in C locale. */ +#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) + /* ANSI/ISO C99 requires format string to be a valid multibyte string + * beginning and ending in its initial shift state. */ + if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) { + const char *p = format; + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + __set_errno(EINVAL); /* Format string is invalid. */ + return 0; + } + } +#endif /* defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) */ + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + psfs.num_pos_args = -1; /* Must start at -1. */ + /* Initialize positional arg ptrs to NULL. */ + memset(psfs.pos_args, 0, sizeof(psfs.pos_args)); +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + + __STDIO_AUTO_THREADLOCK(fp); + + __STDIO_STREAM_VALIDATE(fp); + + __init_scan_cookie(&sc,fp); +#ifdef __UCLIBC_HAS_WCHAR__ + sc.sc_getc = sc_getc; + sc.ungot_wchar_width = sc.fp->__ungot_width[1]; + +#ifdef L_vfwscanf + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (*sc.grouping) { + sc.thousands_sep = fake_thousands_sep_str; + sc.tslen = 1; + } +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ + sc.fake_decpt = fake_decpt_str; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#else /* L_vfwscanf */ + +#ifdef __UCLIBC_HAS_FLOATS__ + sc.fake_decpt = sc.decpt; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#endif /* L_vfwscanf */ + +#endif /* __UCLIBC_HAS_WCHAR__ */ + psfs.cnt = 0; + + /* Note: If we ever wanted to support non-nice codesets, we + * would really need to do a mb->wc conversion here in the + * vfscanf case. Related changes would have to be made in + * the code that follows... basicly wherever fmt appears. */ + for (fmt = (const Wuchar *) format ; *fmt ; /* ++fmt */) { + + psfs.store = 1; + psfs.flags = 0; +#ifndef NDEBUG + psfs.cur_ptr = NULL; /* Debugging aid. */ +#endif /* NDEBUG */ + + + sc.ungot_flag &= 1; /* Clear (possible fake) EOF. */ + sc.width = psfs.max_width = INT_MAX; + + /* Note: According to the standards, vfscanf does use isspace + * here. So, if we did a mb->wc conversion, we would have to do + * something like + * ((((__uwchar_t)wc) < UCHAR_MAX) && isspace(wc)) + * because wc might not be in the allowed domain. */ + if (ISSPACE(*fmt)) { + do { + ++fmt; + } while (ISSPACE(*fmt)); + --fmt; + psfs.conv_num = CONV_whitespace; + goto DO_WHITESPACE; + } + + if (*fmt == '%') { /* Conversion specification. */ + if (*++fmt == '%') { /* Remember, '%' eats whitespace too. */ + /* Note: The standard says no conversion occurs. + * So do not reset zero_conversions flag. */ + psfs.conv_num = CONV_percent; + goto DO_CONVERSION; + } + + +#ifdef L_vfscanf + psfs.fmt = fmt; +#else /* L_vfscanf */ + { + const __uwchar_t *wf = fmt; + psfs.fmt = b = buf; + + while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) { + *b++ = *wf++; + } +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it. + if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) { + goto DONE; /* Spec was excessively long. */ + } +#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ + *b = 0; + if (b == buf) { /* Bad conversion specifier! */ + goto DONE; + } + } +#endif /* L_vfscanf */ + if ((i = __psfs_parse_spec(&psfs)) < 0) { /* Bad conversion specifier! */ + goto DONE; + } + fmt += i; + + if (psfs.store) { +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + if (psfs.num_pos_args == -2) { + psfs.cur_ptr = va_arg(arg, void *); + } else { + while (psfs.cur_pos_arg > psfs.num_pos_args) { + psfs.pos_args[++psfs.num_pos_args] = va_arg(arg, void *); + } + psfs.cur_ptr = psfs.pos_args[psfs.cur_pos_arg]; + } +#else /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + psfs.cur_ptr = va_arg(arg, void *); +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + } + + DO_CONVERSION: + /* First, consume white-space if not n, c, [, C, or l[. */ + if ((((1L << CONV_n)|(1L << CONV_C)|(1L << CONV_c) + |(1L << CONV_LEFTBRACKET)|(1L << CONV_leftbracket)) + & (1L << psfs.conv_num)) == 0 + ) { + DO_WHITESPACE: + while ((__scan_getc(&sc) >= 0) +#ifdef L_vfscanf + && isspace(sc.cc) +#else /* L_vfscanf */ + && iswspace(sc.wc) +#endif /* L_vfscanf */ + ) {} + __scan_ungetc(&sc); + if (psfs.conv_num == CONV_whitespace) { + goto NEXT_FMT; + } + } + + sc.width = psfs.max_width; /* Now limit the max width. */ + + if (sc.width == 0) { /* 0 width is forbidden. */ + goto DONE; + } + + + if (psfs.conv_num == CONV_percent) { + goto MATCH_CHAR; + } + + if (psfs.conv_num == CONV_n) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should %n count as a conversion as far as EOF return value? +#endif +/* zero_conversions = 0; */ + if (psfs.store) { + _store_inttype(psfs.cur_ptr, psfs.dataargtype, + (uintmax_t) sc.nread); + } + goto NEXT_FMT; + } + + if (psfs.conv_num <= CONV_A) { /* pointer, integer, or float spec */ + int r = __psfs_do_numeric(&psfs, &sc); +#ifndef L_vfscanf + if (sc.ungot_wflag == 1) { /* fix up '?', '.', and ',' hacks */ + sc.cc = sc.ungot_char = sc.ungot_wchar; + } +#endif + if (r != -1) { /* Either success or a matching failure. */ + zero_conversions = 0; + } + if (r < 0) { + goto DONE; + } + goto NEXT_FMT; + } + + /* Do string conversions here since they are not common code. */ + + +#ifdef L_vfscanf + + if +#ifdef __UCLIBC_HAS_WCHAR__ + (psfs.conv_num >= CONV_LEFTBRACKET) +#else /* __UCLIBC_HAS_WCHAR__ */ + (psfs.conv_num >= CONV_c) +#endif /* __UCLIBC_HAS_WCHAR__ */ + { + b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); + fail = 1; + + if (psfs.conv_num == CONV_c) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (__scan_getc(&sc) >= 0) { + zero_conversions = 0; + *b = sc.cc; + b += psfs.store; + } + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + if (psfs.conv_num == CONV_s) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) { + zero_conversions = 0; + *b = sc.cc; + b += psfs.store; + fail = 0; + } + } else { +#ifdef __UCLIBC_HAS_WCHAR__ + assert((psfs.conv_num == CONV_LEFTBRACKET) || \ + (psfs.conv_num == CONV_leftbracket)); +#else /* __UCLIBC_HAS_WCHAR__ */ + assert((psfs.conv_num == CONV_leftbracket)); +#endif /* __UCLIBC_HAS_WCHAR__ */ + + invert = 0; + + if (*++fmt == '^') { + ++fmt; + invert = 1; + } + memset(scanset, invert, sizeof(scanset)); + invert = 1-invert; + + if (*fmt == ']') { + scanset[(int)(']')] = invert; + ++fmt; + } + + while (*fmt != ']') { + if (!*fmt) { /* No closing ']'. */ + goto DONE; + } + if ((*fmt == '-') && (fmt[1] != ']') + && (fmt[-1] < fmt[1]) /* sorted? */ + ) { /* range */ + ++fmt; + i = fmt[-2]; + /* Note: scanset[i] should already have been done + * in the previous iteration. */ + do { + scanset[++i] = invert; + } while (i < *fmt); + /* Safe to fall through, and a bit smaller. */ + } + /* literal char */ + scanset[(int) *fmt] = invert; + ++fmt; + } + +#ifdef __UCLIBC_HAS_WCHAR__ + if (psfs.conv_num == CONV_LEFTBRACKET) { + goto DO_LEFTBRACKET; + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + + + while (__scan_getc(&sc) >= 0) { + zero_conversions = 0; + if (!scanset[sc.cc]) { + break; + } + *b = sc.cc; + b += psfs.store; + fail = 0; + } + } + /* Common tail for processing of %s and %[. */ + + __scan_ungetc(&sc); + if (fail) { /* nothing stored! */ + goto DONE; + } + *b = 0; /* Nul-terminate string. */ + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + +#ifdef __UCLIBC_HAS_WCHAR__ + DO_LEFTBRACKET: /* Need to do common wide init. */ + if (psfs.conv_num >= CONV_C) { + wchar_t wbuf[1]; + wchar_t *wb; + + sc.mbstate.__mask = 0; + + wb = (psfs.store ? ((wchar_t *) psfs.cur_ptr) : wbuf); + fail = 1; + + if (psfs.conv_num == CONV_C) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + assert(sc.width >= 0); + *wb = sc.wc; + wb += psfs.store; + } + + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + + if (psfs.conv_num == CONV_S) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if ((((__uwchar_t)(sc.wc)) <= UCHAR_MAX) && isspace(sc.wc)) { + break; + } + *wb = sc.wc; + wb += psfs.store; + fail = 0; + } + } else { + assert(psfs.conv_num == CONV_LEFTBRACKET); + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (((__uwchar_t) sc.wc) <= UCHAR_MAX) { + if (!scanset[sc.wc]) { + break; + } + } else if (invert) { + break; + } + *wb = sc.wc; + wb += psfs.store; + fail = 0; + } + } + /* Common tail for processing of %ls and %l[. */ + + __scan_ungetc(&sc); + if (fail || sc.mb_fail) { /* Nothing stored or mb error. */ + goto DONE; + } + *wb = 0; /* Nul-terminate string. */ + psfs.cnt += psfs.store; + goto NEXT_FMT; + + } + +#endif /* __UCLIBC_HAS_WCHAR__ */ +#else /* L_vfscanf */ + + if (psfs.conv_num >= CONV_C) { + b = buf; + wb = wbuf; + if (psfs.conv_num >= CONV_c) { + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (psfs.store) { + b = (unsigned char *) psfs.cur_ptr; + } + } else { + if (psfs.store) { + wb = (wchar_t *) psfs.cur_ptr; + } + } + fail = 1; + + + if ((psfs.conv_num == CONV_C) || (psfs.conv_num == CONV_c)) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (psfs.conv_num == CONV_C) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb(b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + } + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + if ((psfs.conv_num == CONV_S) || (psfs.conv_num == CONV_s)) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (iswspace(sc.wc)) { + break; + } + if (psfs.conv_num == CONV_S) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb(b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + fail = 0; + } + } else { + const wchar_t *sss; + const wchar_t *ssp; + unsigned char invert = 0; + + assert((psfs.conv_num == CONV_LEFTBRACKET) + || (psfs.conv_num == CONV_leftbracket)); + + if (*++fmt == '^') { + ++fmt; + invert = 1; + } + sss = (const wchar_t *) fmt; + if (*fmt == ']') { + ++fmt; + } + while (*fmt != ']') { + if (!*fmt) { /* No closing ']'. */ + goto DONE; + } + if ((*fmt == '-') && (fmt[1] != ']') + && (fmt[-1] < fmt[1]) /* sorted? */ + ) { /* range */ + ++fmt; + } + ++fmt; + } + /* Ok... a valid scanset spec. */ + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + ssp = sss; + do { /* We know sss < fmt. */ + if (*ssp == '-') { /* possible range... */ + /* Note: We accept a-c-e (ordered) as + * equivalent to a-e. */ + if (ssp > sss) { + if ((++ssp < (const wchar_t *) fmt) + && (ssp[-2] < *ssp) /* sorted? */ + ) { /* yes */ + if ((sc.wc >= ssp[-2]) + && (sc.wc <= *ssp)) { + break; + } + continue; /* not in range */ + } + --ssp; /* oops... '-' at end, so back up */ + } + /* false alarm... a literal '-' */ + } + if (sc.wc == *ssp) { /* Matched literal char. */ + break; + } + } while (++ssp < (const wchar_t *) fmt); + + if ((ssp == (const wchar_t *) fmt) ^ invert) { + /* no match and not inverting + * or match and inverting */ + break; + } + if (psfs.conv_num == CONV_LEFTBRACKET) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb(b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + fail = 0; + } + } + /* Common tail for processing of %s and %[. */ + + __scan_ungetc(&sc); + if (fail) { /* nothing stored! */ + goto DONE; + } + *wb = 0; /* Nul-terminate string. */ + *b = 0; + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + +#endif /* L_vfscanf */ + + assert(0); + goto DONE; + } /* conversion specification */ + + MATCH_CHAR: + if (__scan_getc(&sc) != *fmt) { +#ifdef L_vfwscanf + DONE_DO_UNGET: +#endif /* L_vfwscanf */ + __scan_ungetc(&sc); + goto DONE; + } + + NEXT_FMT: + ++fmt; + if (__FERROR_UNLOCKED(fp)) { + break; + } + } + + DONE: + if (__FERROR_UNLOCKED(fp) || (*fmt && zero_conversions && __FEOF_UNLOCKED(fp))) { + psfs.cnt = EOF; /* Yes, vfwscanf also returns EOF. */ + } + + kill_scan_cookie(&sc); + + __STDIO_STREAM_VALIDATE(fp); + + __STDIO_AUTO_THREADUNLOCK(fp); + + return psfs.cnt; +} +libc_hidden_def(VFSCANF) +#endif +/**********************************************************************/ +#ifdef L___psfs_do_numeric + +static const unsigned char spec_base[] = SPEC_BASE; +static const unsigned char nil_string[] = "(nil)"; + +int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) +{ + unsigned char *b; + const unsigned char *p; + +#ifdef __UCLIBC_HAS_FLOATS__ + int exp_adjust = 0; +#endif +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! +#warning TODO: Fix buf! +#endif +#define MAX_DIGITS 65 /* Allow one leading 0. */ + unsigned char buf[MAX_DIGITS+2+ 100]; + unsigned char usflag, base; + unsigned char nonzero = 0; + unsigned char seendigit = 0; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should be returned for an invalid conversion specifier? +#endif +#ifndef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + goto DONE; + } +#endif + + base = spec_base[psfs->conv_num - CONV_p]; + usflag = (psfs->conv_num <= CONV_u); /* (1)0 if (un)signed */ + b = buf; + + + if (psfs->conv_num == CONV_p) { /* Pointer */ + p = nil_string; + do { + if ((__scan_getc(sc) < 0) || (*p != sc->cc)) { + __scan_ungetc(sc); + if (p > nil_string) { + /* We matched at least the '(' so even if we + * are at eof, we can not match a pointer. */ + return -2; /* Matching failure */ + } + break; + } + if (!*++p) { /* Matched (nil), so no unget necessary. */ + if (psfs->store) { + ++psfs->cnt; + _store_inttype(psfs->cur_ptr, psfs->dataargtype, + (uintmax_t)0); + } + return 0; + } + } while (1); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we require a 0x prefix and disallow +/- for pointer %p? +#endif /* __UCLIBC_MJN3_ONLY__ */ + } + + __scan_getc(sc); + if (sc->cc < 0) { + return -1; /* Input failure (nothing read yet). */ + } + + if ((sc->cc == '+') || (sc->cc == '-')) { /* Handle leading sign.*/ + *b++ = sc->cc; + __scan_getc(sc); + } + + if ((base & 0xef) == 0) { /* 0xef is ~16, so 16 or 0. */ + if (sc->cc == '0') { /* Possibly set base and handle prefix. */ + __scan_getc(sc); + if ((sc->cc|0x20) == 'x') { /* Assumes ascii.. x or X. */ + if (__scan_getc(sc) < 0) { + /* Either EOF or error (including wc outside char range). + * If EOF or error, this is a matching failure (we read 0x). + * If wc outside char range, this is also a matching failure. + * Hence, we do an unget (although not really necessary here + * and fail. */ + goto DONE_DO_UNGET; /* matching failure */ + } + base = 16; /* Base 16 for sure now. */ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + /* The prefix is required for hexadecimal floats. */ + *b++ = '0'; + *b++ = 'x'; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + } else { /* oops... back up */ + __scan_ungetc(sc); + sc->cc = '0'; /* NASTY HACK! */ + + base = (base >> 1) + 8; /* 0->8, 16->16. no 'if' */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + base = 10; + } +#endif + } + } else if (!base) { + base = 10; + } + } + + /***************** digit grouping **********************/ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + if ((psfs->flags & FLAG_THOUSANDS) && (base == 10) + && *(p = sc->grouping) + ) { + + int nblk1, nblk2, nbmax, lastblock, pass, i; + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we initalize the grouping blocks in __init_scan_cookie()? +#endif /* __UCLIBC_MJN3_ONLY__ */ + nbmax = nblk2 = nblk1 = *p; + if (*++p) { + nblk2 = *p; + if (nbmax < nblk2) { + nbmax = nblk2; + } + assert(!p[1]); + } + + /* Note: for printf, if 0 and \' flags appear then + * grouping is done before 0-padding. Should we + * strip leading 0's first? Or add a 0 flag? */ + + /* For vfwscanf, sc_getc translates, so the value of sc->cc is + * either EOF or a char. */ + + if (!__isdigit_char_or_EOF(sc->cc)) { /* No starting digit! */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + goto NO_STARTING_DIGIT; + } +#endif + goto DONE_DO_UNGET; + } + + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; /* Store the first 0. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should leading 0s be skipped before digit grouping? (printf 0 pad) +#endif /* __UCLIBC_MJN3_ONLY__ */ +#if 0 + do { /* But ignore all subsequent 0s. */ + __scan_getc(sc); + } while (sc->cc == '0'); +#endif + } + pass = 0; + lastblock = 0; + do { + i = 0; + while (__isdigit_char_or_EOF(sc->cc)) { + seendigit = 1; + if (i == nbmax) { /* too many digits for a block */ +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + if (!pass) { /* treat as nongrouped */ + if (nonzero) { + goto DO_NO_GROUP; + } + goto DO_TRIM_LEADING_ZEROS; + } +#endif + if (nbmax > nblk1) { + goto DONE_DO_UNGET; /* matching failure */ + } + goto DONE_GROUPING_DO_UNGET; /* nbmax == nblk1 */ + } + ++i; + + if (nonzero || (sc->cc != '0')) { + if (b < buf + MAX_DIGITS) { + *b++ = sc->cc; + nonzero = 1; +#ifdef __UCLIBC_HAS_FLOATS__ + } else { + ++exp_adjust; +#endif + } + } + + __scan_getc(sc); + } + + if (i) { /* we saw digits digits */ + if ((i == nblk2) || ((i < nblk2) && !pass)) { + /* (possible) outer grp */ + p = sc->thousands_sep; + if (*p == sc->cc) { /* first byte matches... */ + /* so check if grouping mb char */ + /* Since 1st matched, either match or fail now + * unless EOF (yuk) */ + __scan_getc(sc); + MBG_LOOP: + if (!*++p) { /* is a grouping mb char */ + lastblock = i; + ++pass; + continue; + } + if (*p == sc->cc) { + __scan_getc(sc); + goto MBG_LOOP; + } + /* bad grouping mb char! */ + __scan_ungetc(sc); + if ((sc->cc >= 0) || (p > sc->thousands_sep + 1)) { +#ifdef __UCLIBC_HAS_FLOATS__ + /* We failed to match a thousep mb char, and + * we've read too much to recover. But if + * this is a floating point conversion and + * the initial portion of the decpt mb char + * matches, then we may still be able to + * recover. */ + int k = p - sc->thousands_sep - 1; + + if ((psfs->conv_num > CONV_i) /* float conversion */ + && (!pass || (i == nblk1)) /* possible last */ + && !memcmp(sc->thousands_sep, sc->fake_decpt, k) + /* and prefix matched, so could be decpt */ + ) { + __scan_getc(sc); + p = sc->fake_decpt + k; + do { + if (!*++p) { + strcpy(b, sc->decpt); + b += sc->decpt_len; + goto GOT_DECPT; + } + if (*p != sc->cc) { + __scan_ungetc(sc); + break; /* failed */ + } + __scan_getc(sc); + } while (1); + } +#endif /* __UCLIBC_HAS_FLOATS__ */ + goto DONE; + } + /* was EOF and 1st, so recoverable. */ + } + } + if ((i == nblk1) || ((i < nblk1) && !pass)) { + /* got an inner group */ + goto DONE_GROUPING_DO_UNGET; + } + goto DONE_DO_UNGET; /* Matching failure. */ + } /* i != 0 */ + + assert(pass); + + goto DONE_DO_UNGET; + } while (1); + + assert(0); /* Should never get here. */ + } + +#endif /***************** digit grouping **********************/ + + /* Not grouping so first trim all but one leading 0. */ +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + DO_TRIM_LEADING_ZEROS: +#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; /* Store the first 0. */ + do { /* But ignore all subsequent 0s. */ + __scan_getc(sc); + } while (sc->cc == '0'); + } + +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + DO_NO_GROUP: +#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ + /* At this point, we're ready to start reading digits. */ + +#define valid_digit(cc,base) (isxdigit(cc) && ((base == 16) || (cc - '0' < base))) + + while (valid_digit(sc->cc,base)) { /* Now for significant digits.*/ + if (b - buf < MAX_DIGITS) { + nonzero = seendigit = 1; /* Set nonzero too 0s trimmed above. */ + *b++ = sc->cc; +#ifdef __UCLIBC_HAS_FLOATS__ + } else { + ++exp_adjust; +#endif + } + __scan_getc(sc); + } + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + DONE_GROUPING_DO_UNGET: +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + if (psfs->conv_num <= CONV_i) { /* integer conversion */ + __scan_ungetc(sc); + *b = 0; /* null-terminate */ + if (!seendigit) { + goto DONE; /* No digits! */ + } + if (psfs->store) { + if (*buf == '-') { + usflag = 0; + } + ++psfs->cnt; + _store_inttype(psfs->cur_ptr, psfs->dataargtype, + (uintmax_t) STRTOUIM((char *) buf, NULL, base, 1-usflag)); + } + return 0; + } + +#ifdef __UCLIBC_HAS_FLOATS__ + + /* At this point, we have everything left of the decimal point or exponent. */ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + NO_STARTING_DIGIT: +#endif + p = sc->fake_decpt; + do { + if (!*p) { + strcpy((char *) b, (char *) sc->decpt); + b += sc->decpt_len; + break; + } + if (*p != sc->cc) { + if (p > sc->fake_decpt) { + goto DONE_DO_UNGET; /* matching failure (read some of decpt) */ + } + goto DO_DIGIT_CHECK; + } + ++p; + __scan_getc(sc); + } while (1); + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + GOT_DECPT: +#endif + if (!nonzero) { + if (sc->cc == '0') { + assert(exp_adjust == 0); + *b++ = '0'; + ++exp_adjust; + seendigit = 1; + do { + --exp_adjust; + __scan_getc(sc); + } while (sc->cc == '0'); + } + } + + while (valid_digit(sc->cc,base)) { /* Process fractional digits.*/ + if (b - buf < MAX_DIGITS) { + seendigit = 1; + *b++ = sc->cc; + } + __scan_getc(sc); + } + + DO_DIGIT_CHECK: + /* Hmm... no decimal point. */ + if (!seendigit) { + static const unsigned char nan_inf_str[] = "an\0nfinity"; + + if (base == 16) { /* We had a prefix, but no digits! */ + goto DONE_DO_UNGET; /* matching failure */ + } + + /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ +#undef TOLOWER +#define TOLOWER(C) ((C)|0x20) + + switch (TOLOWER(sc->cc)) { + case 'i': + p = nan_inf_str + 3; + break; + case 'n': + p = nan_inf_str; + break; + default: + /* No digits and not inf or nan. */ + goto DONE_DO_UNGET; + } + + *b++ = sc->cc; + + do { + __scan_getc(sc); + if (TOLOWER(sc->cc) == *p) { + *b++ = sc->cc; + ++p; + continue; + } + if (!*p || (p == nan_inf_str + 5)) { /* match nan/infinity or inf */ + goto GOT_FLOAT; + } + /* Unrecoverable. Even if on 1st char, we had no digits. */ + goto DONE_DO_UNGET; + } while (1); + } + + /* If we get here, we had some digits. */ + + if ( +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + ((base == 16) && (((sc->cc)|0x20) == 'p')) || +#endif + (((sc->cc)|0x20) == 'e') + ) { /* Process an exponent. */ + *b++ = sc->cc; + + __scan_getc(sc); + if (sc->cc < 0) { + goto DONE_DO_UNGET; /* matching failure.. no exponent digits */ + } + + if ((sc->cc == '+') || (sc->cc == '-')) { /* Signed exponent? */ + *b++ = sc->cc; + __scan_getc(sc); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_EXP_DIGITS! +#endif +#define MAX_EXP_DIGITS 20 + assert(seendigit); + seendigit = 0; + nonzero = 0; + + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; + do { + __scan_getc(sc); + } while (sc->cc == '0'); + } + + while (__isdigit_char_or_EOF(sc->cc)) { /* Exponent digits (base 10).*/ + if (seendigit < MAX_EXP_DIGITS) { + ++seendigit; + *b++ = sc->cc; + } + __scan_getc(sc); + } + + if (!seendigit) { /* No digits. Unrecoverable. */ + goto DONE_DO_UNGET; + } + } + + + GOT_FLOAT: + *b = 0; + { + __fpmax_t x; + char *e; + x = __strtofpmax((char *) buf, &e, exp_adjust); + assert(!*e); + if (psfs->store) { + if (psfs->dataargtype & PA_FLAG_LONG_LONG) { + *((long double *)psfs->cur_ptr) = (long double) x; + } else if (psfs->dataargtype & PA_FLAG_LONG) { + *((double *)psfs->cur_ptr) = (double) x; + } else { + *((float *)psfs->cur_ptr) = (float) x; + } + ++psfs->cnt; + } + __scan_ungetc(sc); + return 0; + } +#endif /* __UCLIBC_HAS_FLOATS__ */ + + DONE_DO_UNGET: + __scan_ungetc(sc); + DONE: + return -2; /* Matching failure. */ + +} +#endif +/**********************************************************************/ diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c new file mode 100644 index 0000000..d8c0ae2 --- /dev/null +++ b/libc/stdio/_stdio.c @@ -0,0 +1,445 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(isatty) + +/* This is pretty much straight from uClibc, but with one important + * difference. + * + * We now initialize the locking flag to user locking instead of + * auto locking (i.e. FSETLOCKING_BYCALLER vs FSETLOCKING_INTERNAL). + * This greatly benefits non-threading applications linked to a + * shared thread-enabled library. In threading applications, we + * walk the stdio open file list and reset the locking mode + * appropriately when the thread subsystem is initialized. + */ + +/**********************************************************************/ + +#ifdef __UCLIBC_HAS_WCHAR__ +#define __STDIO_FILE_INIT_WUNGOT { 0, 0 }, +#else +#define __STDIO_FILE_INIT_WUNGOT +#endif + +#ifdef __STDIO_GETC_MACRO +# define __STDIO_FILE_INIT_BUFGETC(x) x, +#else +# define __STDIO_FILE_INIT_BUFGETC(x) +#endif + +#ifdef __STDIO_PUTC_MACRO +# define __STDIO_FILE_INIT_BUFPUTC(x) x, +#else +# define __STDIO_FILE_INIT_BUFPUTC(x) +#endif + +#ifdef __STDIO_HAS_OPENLIST +#define __STDIO_FILE_INIT_NEXT(next) (next), +#else +#define __STDIO_FILE_INIT_NEXT(next) +#endif + +#ifdef __STDIO_BUFFERS +#define __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \ + (buf), (buf)+(bufsize), (buf), (buf), +#else +#define __STDIO_FILE_INIT_BUFFERS(buf,bufsize) +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#define __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \ + &((stream).__filedes), { _cs_read, _cs_write, _cs_seek, _cs_close }, +#else +#define __STDIO_FILE_INIT_CUSTOM_STREAM(stream) +#endif + +#ifdef __STDIO_MBSTATE +#define __STDIO_FILE_INIT_MBSTATE \ + { 0, 0 }, +#else +#define __STDIO_FILE_INIT_MBSTATE +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define __STDIO_FILE_INIT_UNUSED \ + NULL, +#else +#define __STDIO_FILE_INIT_UNUSED +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_FILE_INIT_THREADSAFE \ + 2, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, +#else +#define __STDIO_FILE_INIT_THREADSAFE +#endif + +#define __STDIO_INIT_FILE_STRUCT(stream, flags, filedes, next, buf, bufsize) \ + { (flags), \ + { 0, 0 }, /* ungot[2] (no wchar) or ungot_width[2] (wchar)*/ \ + (filedes), \ + __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \ + __STDIO_FILE_INIT_BUFGETC((buf)) \ + __STDIO_FILE_INIT_BUFPUTC((buf)) \ + __STDIO_FILE_INIT_NEXT(next) \ + __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \ + __STDIO_FILE_INIT_WUNGOT \ + __STDIO_FILE_INIT_MBSTATE \ + __STDIO_FILE_INIT_UNUSED \ + __STDIO_FILE_INIT_THREADSAFE \ +} /* TODO: builtin buf */ + +/**********************************************************************/ +/* First we need the standard files. */ + +#ifdef __STDIO_BUFFERS +static unsigned char _fixed_buffers[2 * BUFSIZ]; +#endif + +static FILE _stdio_streams[] = { + __STDIO_INIT_FILE_STRUCT(_stdio_streams[0], \ + __FLAG_LBF|__FLAG_READONLY, \ + 0, \ + _stdio_streams + 1, \ + _fixed_buffers, \ + BUFSIZ ), + __STDIO_INIT_FILE_STRUCT(_stdio_streams[1], \ + __FLAG_LBF|__FLAG_WRITEONLY, \ + 1, \ + _stdio_streams + 2, \ + _fixed_buffers + BUFSIZ, \ + BUFSIZ ), + __STDIO_INIT_FILE_STRUCT(_stdio_streams[2], \ + __FLAG_NBF|__FLAG_WRITEONLY, \ + 2, \ + NULL, \ + NULL, \ + 0 ) +}; + +FILE *stdin = _stdio_streams; +FILE *stdout = _stdio_streams + 1; +FILE *stderr = _stdio_streams + 2; + +#ifdef __STDIO_GETC_MACRO +FILE *__stdin = _stdio_streams; /* For getchar() macro. */ +#endif +#ifdef __STDIO_PUTC_MACRO +FILE *__stdout = _stdio_streams + 1; /* For putchar() macro. */ +/* FILE *__stderr = _stdio_streams + 2; */ +#endif + +/**********************************************************************/ +#ifdef __STDIO_HAS_OPENLIST + +/* In certain configurations, we need to keep a list of open files. + * 1) buffering enabled - We need to initialize the buffering mode + * (full or line buffering) of stdin and stdout. We also + * need to flush all write buffers prior to normal termination. + * 2) custom streams - Even if we aren't buffering in the library + * itself, we need to fclose() all custom streams when terminating + * so that any special cleanup is done. + * 3) threads enabled - We need to be able to reset the locking mode + * of all open streams when the threading system is initialized. + */ + +FILE *_stdio_openlist = _stdio_streams; + +# ifdef __UCLIBC_HAS_THREADS__ +__UCLIBC_MUTEX_INIT(_stdio_openlist_add_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +#ifdef __STDIO_BUFFERS +__UCLIBC_MUTEX_INIT(_stdio_openlist_del_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +volatile int _stdio_openlist_use_count = 0; +int _stdio_openlist_del_count = 0; +#endif +# endif + +#endif +/**********************************************************************/ +#ifdef __UCLIBC_HAS_THREADS__ + +/* 2 if threading not initialized and 0 otherwise; */ +int _stdio_user_locking = 2; + +void attribute_hidden __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) +{ + const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); +} + +#endif +/**********************************************************************/ + +/* We assume here that we are the only remaining thread. */ +void attribute_hidden _stdio_term(void) +{ +#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + register FILE *ptr; + +#ifdef __UCLIBC_HAS_THREADS__ + /* First, make sure the open file list is unlocked. If it was + * locked, then I suppose there is a chance that a pointer in the + * chain might be corrupt due to a partial store. + */ + __stdio_init_mutex(&_stdio_openlist_add_lock); +#warning check +#ifdef __STDIO_BUFFERS + __stdio_init_mutex(&_stdio_openlist_del_lock); +#endif + + /* Next we need to worry about the streams themselves. If a stream + * is currently locked, then it may be in an invalid state. So we + * 'disable' it in case a custom stream is stacked on top of it. + * Then we reinitialize the locks. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { + if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { + /* The stream is already locked, so we don't want to touch it. + * However, if we have custom streams, we can't just close it + * or leave it locked since a custom stream may be stacked + * on top of it. So we do unlock it, while also disabling it. + */ + ptr->__modeflags = (__FLAG_READONLY|__FLAG_WRITEONLY); + __STDIO_STREAM_DISABLE_GETC(ptr); + __STDIO_STREAM_DISABLE_PUTC(ptr); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(ptr); + } + + ptr->__user_locking = 1; /* Set locking mode to "by caller". */ + __stdio_init_mutex(&ptr->__lock); /* Shouldn't be necessary, but... */ + } +#endif + + /* Finally, flush all writing streams and shut down all custom streams. + * NOTE: We assume that any stacking by custom streams is done on top + * of streams previously allocated, and hence further down the + * list. Otherwise we have no way of knowing the order in which + * to shut them down. + * Remember that freopen() counts as a new allocation here, even + * though the stream is reused. That's because it moves the + * stream to the head of the list. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { +#ifdef __STDIO_BUFFERS + /* Write any pending buffered chars. */ + if (__STDIO_STREAM_IS_WRITING(ptr)) { + __STDIO_COMMIT_WRITE_BUFFER(ptr); + } +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + /* Actually close all custom streams to perform any special cleanup. */ + if (ptr->__cookie != &ptr->__filedes) { + __CLOSE(ptr); + } +#endif + } + +#endif +} + +#if defined __STDIO_BUFFERS || !defined __UCLIBC__ +void attribute_hidden _stdio_init(void) +{ +#ifdef __STDIO_BUFFERS + int old_errno = errno; + /* stdin and stdout uses line buffering when connected to a tty. */ + _stdio_streams[0].__modeflags ^= (1-isatty(0)) * __FLAG_LBF; + _stdio_streams[1].__modeflags ^= (1-isatty(1)) * __FLAG_LBF; + __set_errno(old_errno); +#endif +#ifndef __UCLIBC__ + /* _stdio_term is done automatically when exiting if stdio is used. + * See misc/internals/__uClibc_main.c and and stdlib/atexit.c. */ + atexit(_stdio_term); +#endif +} +#endif + +/**********************************************************************/ + +#if !(__MASK_READING & __FLAG_UNGOT) +#error Assumption violated about __MASK_READING and __FLAG_UNGOT +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifndef NDEBUG + +void _stdio_validate_FILE(const FILE *stream) +{ +#ifdef __UCLIBC_HAS_THREADS__ + assert(((unsigned int)(stream->__user_locking)) <= 2); +#endif + +#warning Define a constant for minimum possible valid __filedes? + assert(stream->__filedes >= -3); + + if (stream->__filedes < 0) { +/* assert((stream->__filedes != -1) */ +/* #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ +/* || (stream->__cookie == &stream->__filedes) /\* custom *\/ */ +/* #endif */ +/* ); */ +/* assert((stream->__filedes == -1) || __STDIO_STREAM_IS_FBF(stream)); */ + + assert(!__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream) + || __STDIO_STREAM_IS_NARROW(stream)); + assert(!__STDIO_STREAM_IS_FAKE_VSSCANF(stream) + || __STDIO_STREAM_IS_NARROW(stream)); +#ifdef __STDIO_STREAM_IS_FAKE_VSWPRINTF + assert(!__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream) + || __STDIO_STREAM_IS_WIDE(stream)); +#endif +#ifdef __STDIO_STREAM_IS_FAKE_VSWSCANF + assert(!__STDIO_STREAM_IS_FAKE_VSWSCANF(stream) + || __STDIO_STREAM_IS_WIDE(stream)); +#endif + } + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + if (stream->__cookie != &stream->__filedes) { /* custom */ + assert(stream->__filedes == -1); + } +#endif + + /* Can not be both narrow and wide oriented at the same time. */ + assert(!(__STDIO_STREAM_IS_NARROW(stream) + && __STDIO_STREAM_IS_WIDE(stream))); + + + /* The following impossible case is used to disable a stream. */ + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + == (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + assert(stream->__modeflags == (__FLAG_READONLY|__FLAG_WRITEONLY)); + assert(stream->__filedes == -1); +#ifdef __STDIO_BUFFERS + assert(stream->__bufpos == stream->__bufstart); + assert(stream->__bufread == stream->__bufstart); +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + if (__STDIO_STREAM_IS_READONLY(stream)) { +/* assert(!__STDIO_STREAM_IS_WRITEONLY(stream)); */ + assert(!__STDIO_STREAM_IS_WRITING(stream)); + if (stream->__modeflags & __FLAG_UNGOT) { + assert(((unsigned)(stream->__ungot[1])) <= 1); + assert(!__FEOF_UNLOCKED(stream)); + } + } + + if (__STDIO_STREAM_IS_WRITEONLY(stream)) { +/* assert(!__STDIO_STREAM_IS_READONLY(stream)); */ + assert(!__STDIO_STREAM_IS_READING(stream)); + assert(!(stream->__modeflags & __FLAG_UNGOT)); + } + + if (__STDIO_STREAM_IS_NBF(stream)) { + /* We require that all non buffered streams have no buffer. */ + assert(!__STDIO_STREAM_BUFFER_SIZE(stream)); + } + + assert((stream->__modeflags & __MASK_BUFMODE) <= __FLAG_NBF); + +#ifdef __STDIO_BUFFERS + /* Ensure __bufstart <= __bufpos <= __bufend. */ + assert(stream->__bufpos >= stream->__bufstart); + assert(stream->__bufpos <= stream->__bufend); + /* Ensure __bufstart <= __bufread <= __bufend. */ + assert(stream->__bufread >= stream->__bufstart); + assert(stream->__bufread <= stream->__bufend); +#endif + + /* If EOF, then we must have no buffered readable or ungots. */ + if (__FEOF_UNLOCKED(stream)) { +#ifdef __STDIO_BUFFERS + assert(stream->__bufpos == stream->__bufread); +#endif + assert(!(stream->__modeflags & __FLAG_UNGOT)); + } + + + if (!__STDIO_STREAM_IS_WRITING(stream)) { +#ifdef __STDIO_BUFFERS + /* If not writing, then putc macro must be disabled. */ +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +#endif + } + + if (!__STDIO_STREAM_IS_READING(stream)) { + /* If not reading, then can not have ungots. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); +#ifdef __STDIO_BUFFERS + /* Ensure __bufread == __bufstart. */ + assert(stream->__bufread == stream->__bufstart); + /* If not reading, then getc macro must be disabled. */ +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + if (__STDIO_STREAM_IS_READING(stream)) { + assert(!__STDIO_STREAM_IS_WRITING(stream)); +#ifdef __STDIO_BUFFERS + /* Ensure __bufpos <= __bufread. */ + assert(stream->__bufpos <= stream->__bufread); + + /* Ensure __bufgetc_u is valid. */ +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u >= stream->__bufstart); + assert(stream->__bufgetc_u <= stream->__bufread); +# endif + +#endif + } + + if (__STDIO_STREAM_IS_WRITING(stream)) { + assert(!__STDIO_STREAM_IS_READING(stream)); +#ifdef __STDIO_BUFFERS +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u >= stream->__bufstart); + assert(stream->__bufputc_u <= stream->__bufend); +# endif +#endif + } + + /* If have an ungotten char, then getc (and putc) must be disabled. */ + /* Also, wide streams must have the getc/putc macros disabled. */ + if ((stream->__modeflags & __FLAG_UNGOT) + || __STDIO_STREAM_IS_WIDE(stream) + ) { +#ifdef __STDIO_BUFFERS +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + /* TODO -- filepos? ungot_width? filedes? nextopen? */ +} + +#endif diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h new file mode 100644 index 0000000..27075a8 --- /dev/null +++ b/libc/stdio/_stdio.h @@ -0,0 +1,456 @@ +/* Copyright (C) 2004-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif + +#include + +#define __STDIO_THREADLOCK_OPENLIST_ADD \ + __UCLIBC_MUTEX_LOCK(_stdio_openlist_add_lock) + +#define __STDIO_THREADUNLOCK_OPENLIST_ADD \ + __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_add_lock) + +#ifdef __STDIO_BUFFERS + +#define __STDIO_THREADLOCK_OPENLIST_DEL \ + __UCLIBC_MUTEX_LOCK(_stdio_openlist_del_lock) + +#define __STDIO_THREADUNLOCK_OPENLIST_DEL \ + __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_del_lock) + + +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_OPENLIST_INC_USE \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_use_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +extern void _stdio_openlist_dec_use(void); + +#define __STDIO_OPENLIST_DEC_USE \ + _stdio_openlist_dec_use() + +#define __STDIO_OPENLIST_INC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#define __STDIO_OPENLIST_DEC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + --_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#endif /* __UCLIBC_HAS_THREADS__ */ +#endif /* __STDIO_BUFFERS */ + +#ifndef __STDIO_THREADLOCK_OPENLIST_DEL +#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_THREADUNLOCK_OPENLIST_DEL +#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_USE +#define __STDIO_OPENLIST_INC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_USE +#define __STDIO_OPENLIST_DEC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_DEL_CNT +#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_DEL_CNT +#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0) +#endif + +#define __UNDEFINED_OR_NONPORTABLE ((void)0) + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + +extern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize) attribute_hidden; +extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize) attribute_hidden; +extern int _cs_seek(void *cookie, __offmax_t *pos, int whence) attribute_hidden; +extern int _cs_close(void *cookie) attribute_hidden; + +#define __STDIO_STREAM_RESET_GCS(S) \ + (S)->__cookie = &((S)->__filedes); \ + (S)->__gcs.read = _cs_read; \ + (S)->__gcs.write = _cs_write; \ + (S)->__gcs.seek = _cs_seek; \ + (S)->__gcs.close = _cs_close + + +#define __READ(STREAMPTR,BUF,SIZE) \ + ((((STREAMPTR)->__gcs.read) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.read)((STREAMPTR)->__cookie,(BUF),(SIZE)))) +#define __WRITE(STREAMPTR,BUF,SIZE) \ + ((((STREAMPTR)->__gcs.write) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.write)((STREAMPTR)->__cookie,(BUF),(SIZE)))) +#define __SEEK(STREAMPTR,PPOS,WHENCE) \ + ((((STREAMPTR)->__gcs.seek) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.seek)((STREAMPTR)->__cookie,(PPOS),(WHENCE)))) +#define __CLOSE(STREAMPTR) \ + ((((STREAMPTR)->__gcs.close) == NULL) ? 0 : \ + (((STREAMPTR)->__gcs.close)((STREAMPTR)->__cookie))) + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + +extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attribute_hidden; + +#define __STDIO_STREAM_RESET_GCS(S) ((void)0) + +#define __READ(STREAMPTR,BUF,SIZE) \ + (read((STREAMPTR)->__filedes,(BUF),(SIZE))) +#define __WRITE(STREAMPTR,BUF,SIZE) \ + (write((STREAMPTR)->__filedes,(BUF),(SIZE))) +#define __SEEK(STREAMPTR,PPOS,WHENCE) \ + (__stdio_seek((STREAMPTR),(PPOS),(WHENCE))) +#define __CLOSE(STREAMPTR) \ + (close((STREAMPTR)->__filedes)) + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w_o((S), (O)) +#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r_o((S), (O)) + +#else + +#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w((S)) +#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r((S)) + +#endif +/**********************************************************************/ + +#define __STDIO_STREAM_IS_READING(S) ((S)->__modeflags & __MASK_READING) +#define __STDIO_STREAM_IS_WRITING(S) ((S)->__modeflags & __FLAG_WRITING) + +#define __STDIO_STREAM_SET_READING(S) ((S)->__modeflags |= __FLAG_READING) +#define __STDIO_STREAM_SET_WRITING(S) ((S)->__modeflags |= __FLAG_WRITING) + +#define __STDIO_STREAM_IS_READING_OR_READONLY(S) \ + ((S)->__modeflags & (__MASK_READING|__FLAG_READONLY)) + +#define __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(S) \ + ((S)->__modeflags & (__FLAG_WRITING|__FLAG_WRITEONLY)) + +#define __STDIO_STREAM_IS_READONLY(S) ((S)->__modeflags & __FLAG_READONLY) +#define __STDIO_STREAM_IS_WRITEONLY(S) ((S)->__modeflags & __FLAG_WRITEONLY) + + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __STDIO_STREAM_IS_NARROW_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW)) \ + == (__FLAG_WRITING|__FLAG_NARROW)) + +#define __STDIO_STREAM_IS_WIDE_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE)) \ + == (__FLAG_WRITING|__FLAG_WIDE)) + +#if (__FLAG_NARROW <= __MASK_READING) +#error assumption violated regarding __FLAG_NARROW +#endif + +#define __STDIO_STREAM_IS_NARROW_READING(S) \ + (((S)->__modeflags & (__MASK_READING|__FLAG_NARROW)) > __FLAG_NARROW) + +#define __STDIO_STREAM_IS_WIDE_READING(S) \ + (((S)->__modeflags & (__MASK_READING|__FLAG_WIDE)) > __FLAG_WIDE) + +#define __STDIO_STREAM_IS_NARROW(S) ((S)->__modeflags & __FLAG_NARROW) +#define __STDIO_STREAM_IS_WIDE(S) ((S)->__modeflags & __FLAG_WIDE) + +#define __STDIO_STREAM_SET_NARROW(S) \ + ((void)((S)->__modeflags |= __FLAG_NARROW)) +#define __STDIO_STREAM_SET_WIDE(S) \ + ((void)((S)->__modeflags |= __FLAG_WIDE)) + +#else + +#define __STDIO_STREAM_IS_NARROW_WRITING(S) __STDIO_STREAM_IS_WRITING(S) + +#define __STDIO_STREAM_IS_NARROW_READING(S) __STDIO_STREAM_IS_READING(S) + +#define __STDIO_STREAM_IS_NARROW(S) (1) +#define __STDIO_STREAM_IS_WIDE(S) (0) + +#define __STDIO_STREAM_SET_NARROW(S) ((void)0) +#define __STDIO_STREAM_SET_WIDE(S) ((void)0) + +#endif +/**********************************************************************/ + +#define __STDIO_STREAM_SET_EOF(S) \ + ((void)((S)->__modeflags |= __FLAG_EOF)) +#define __STDIO_STREAM_SET_ERROR(S) \ + ((void)((S)->__modeflags |= __FLAG_ERROR)) + +#define __STDIO_STREAM_CLEAR_EOF(S) \ + ((void)((S)->__modeflags &= ~__FLAG_EOF)) +#define __STDIO_STREAM_CLEAR_ERROR(S) \ + ((void)((S)->__modeflags &= ~__FLAG_ERROR)) + +#define __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(S) \ + ((void)((S)->__modeflags &= ~__MASK_READING)) +#define __STDIO_STREAM_CLEAR_WRITING(S) \ + ((void)((S)->__modeflags &= ~__FLAG_WRITING)) + +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ +# define __STDIO_STREAM_DISABLE_GETC(S) \ + ((void)((S)->__bufgetc_u = (S)->__bufstart)) +# define __STDIO_STREAM_ENABLE_GETC(S) \ + ((void)((S)->__bufgetc_u = (S)->__bufread)) +# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) \ + ((S)->__bufpos < (S)->__bufgetc_u) +#else +# define __STDIO_STREAM_DISABLE_GETC(S) ((void)0) +# define __STDIO_STREAM_ENABLE_GETC(S) ((void)0) +# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) (0) +#endif + +#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ +# define __STDIO_STREAM_DISABLE_PUTC(S) \ + ((void)((S)->__bufputc_u = (S)->__bufstart)) +# define __STDIO_STREAM_ENABLE_PUTC(S) \ + ((void)((S)->__bufputc_u = (S)->__bufend)) +# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) \ + ((S)->__bufpos < (S)->__bufputc_u) +#else +# define __STDIO_STREAM_DISABLE_PUTC(S) ((void)0) +# define __STDIO_STREAM_ENABLE_PUTC(S) ((void)0) +# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) (0) +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#define __STDIO_STREAM_IS_CUSTOM(S) ((S)->__cookie != &((S)->__filedes)) +#else +#define __STDIO_STREAM_IS_CUSTOM(S) (0) +#endif + +/**********************************************************************/ + +#ifdef __STDIO_BUFFERS +#define __STDIO_STREAM_FREE_BUFFER(S) \ + do { if ((S)->__modeflags & __FLAG_FREEBUF) \ + free((S)->__bufstart); } while (0) +#else +#define __STDIO_STREAM_FREE_BUFFER(S) ((void)0) +#endif + +#define __STDIO_STREAM_FREE_FILE(S) \ + do { if ((S)->__modeflags & __FLAG_FREEFILE) \ + free((S)); } while (0) + + +#ifdef __UCLIBC_HAS_LFS__ +#define __STDIO_WHEN_LFS(E) E +#else +#define __STDIO_WHEN_LFS(E) ((void)0) +#endif + +/**********************************************************************/ +/* The following return 0 on success. */ + +#ifdef __STDIO_BUFFERS +/* Assume stream in valid writing state. Do not reset writing flag + * or disble putc macro unless error. */ +/* Should we assume that buffer is not empty to avoid a check? */ +extern size_t __stdio_wcommit(FILE *__restrict stream) attribute_hidden; + +/* Remember to fail if at EOF! */ +extern size_t __stdio_rfill(FILE *__restrict stream) attribute_hidden; + +extern size_t __stdio_fwrite(const unsigned char *__restrict buffer, + size_t bytes, FILE *__restrict stream) attribute_hidden; +#else + +#define __stdio_fwrite(B,N,S) __stdio_WRITE((S),(B),(N)) + +#endif + +extern size_t __stdio_WRITE(FILE *stream, const unsigned char *buf, + size_t bufsize) attribute_hidden; +extern size_t __stdio_READ(FILE *stream, unsigned char *buf, + size_t bufsize) attribute_hidden; + +extern int __stdio_trans2r(FILE *__restrict stream) attribute_hidden; +extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden; + +extern int __stdio_trans2r_o(FILE *__restrict stream, int oflag) attribute_hidden; +extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidden; + +/**********************************************************************/ +#ifdef __STDIO_BUFFERS + +#define __STDIO_STREAM_IS_FBF(S) (!((S)->__modeflags & __MASK_BUFMODE)) +#define __STDIO_STREAM_IS_LBF(S) ((S)->__modeflags & __FLAG_LBF) +#define __STDIO_STREAM_IS_NBF(S) ((S)->__modeflags & __FLAG_NBF) + +#define __STDIO_STREAM_BUFFER_SIZE(S) ((S)->__bufend - (S)->__bufstart) + +/* Valid when writing... */ +#define __STDIO_STREAM_BUFFER_ADD(S,C) (*(S)->__bufpos++ = (C)) +#define __STDIO_STREAM_BUFFER_UNADD(S) (--(S)->__bufpos) +#define __STDIO_STREAM_BUFFER_WAVAIL(S) ((S)->__bufend - (S)->__bufpos) +#define __STDIO_STREAM_BUFFER_WUSED(S) ((S)->__bufpos - (S)->__bufstart) +#define __STDIO_COMMIT_WRITE_BUFFER(S) __stdio_wcommit((S)) +#ifdef __UCLIBC_HAS_WCHAR__ +#define __STDIO_STREAM_IS_NARROW_FBF(S) \ + (!((S)->__modeflags & (__MASK_BUFMODE|__FLAG_WIDE))) +#else +#define __STDIO_STREAM_IS_NARROW_FBF(S) __STDIO_STREAM_IS_FBF((S)) +#endif + +/* Valid when reading... */ +#define __STDIO_STREAM_BUFFER_RAVAIL(S) ((S)->__bufread - (S)->__bufpos) +#define __STDIO_STREAM_BUFFER_GET(S) (*(S)->__bufpos++) +#define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S)) + +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) \ + (S)->__bufread = (S)->__bufpos = (S)->__bufstart + + +#define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES (-2) +#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES (-2) +#define __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES (-3) +#define __STDIO_STREAM_FAKE_VSWSCANF_FILEDES (-3) + +#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSWPRINTF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSWSCANF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSWSCANF_FILEDES) + +#else /* __STDIO_BUFFERS */ + +#define __STDIO_STREAM_IS_FBF(S) (0) +#define __STDIO_STREAM_IS_LBF(S) (0) +#define __STDIO_STREAM_IS_NBF(S) (1) + +#define __STDIO_STREAM_BUFFER_SIZE(S) (0) +#define __STDIO_STREAM_BUFFER_ADD(S,C) ((void)0) +#define __STDIO_STREAM_BUFFER_UNADD(S) ((void)0) +#define __STDIO_STREAM_BUFFER_WAVAIL(S) (0) +#define __STDIO_STREAM_BUFFER_WUSED(S) (0) +#define __STDIO_COMMIT_WRITE_BUFFER(S) (0) +#define __STDIO_STREAM_IS_NARROW_FBF(S) (0) + +#define __STDIO_STREAM_BUFFER_RAVAIL(S) (0) +#define __STDIO_STREAM_BUFFER_GET(S) (EOF) +#define __STDIO_FILL_READ_BUFFER(S) (0) +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) ((void)0) + +#undef __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES +#undef __STDIO_STREAM_FAKE_VSSCANF_FILEDES +#undef __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES + +#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) (0) +#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) (0) +#undef __STDIO_STREAM_IS_FAKE_VSWPRINTF + +# ifdef __USE_OLD_VFPRINTF__ +# define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB) +# endif + +# ifndef __UCLIBC_HAS_WCHAR__ +# define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB) +# endif + +#endif /* __STDIO_BUFFERS */ +/**********************************************************************/ + +extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) attribute_hidden; + +#ifdef __STDIO_HAS_OPENLIST + /* Uses an implementation hack!!! */ +#define __STDIO_FLUSH_LBF_STREAMS \ + fflush_unlocked((FILE *) &_stdio_openlist) +#else +#define __STDIO_FLUSH_LBF_STREAMS ((void)0) +#endif + +#ifdef NDEBUG +#define __STDIO_STREAM_VALIDATE(S) ((void)0) +#else +extern void _stdio_validate_FILE(const FILE *stream); +#define __STDIO_STREAM_VALIDATE(S) _stdio_validate_FILE((S)) +#endif + +#ifdef __STDIO_MBSTATE +#define __COPY_MBSTATE(dest,src) \ + ((void)((dest)->__mask = (src)->__mask, (dest)->__wc = (src)->__wc)) +#define __INIT_MBSTATE(dest) ((void)((dest)->__mask = 0)) +#else +#define __COPY_MBSTATE(dest,src) ((void)0) +#define __INIT_MBSTATE(dest) ((void)0) +#endif + +/**********************************************************************/ + +extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode, + FILE *__restrict stream, int filedes) attribute_hidden; + +#ifdef __UCLIBC_HAS_WCHAR__ +extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, + size_t n, FILE *__restrict stream) attribute_hidden; +#endif + +/**********************************************************************/ + +extern int _vfprintf_internal (FILE * __restrict stream, + const char * __restrict format, + va_list arg) attribute_hidden; + +#ifdef __UCLIBC_HAS_WCHAR__ +extern int _vfwprintf_internal (FILE * __restrict stream, + const wchar_t * __restrict format, + va_list arg) attribute_hidden; +#endif + +/**********************************************************************/ +/* Only use the macro below if you know fp is a valid FILE for a valid fd. + * This is _not_ true for custom streams! */ +#define __FILENO_UNLOCKED(fp) ((fp)->__filedes) + +#define __FEOF_OR_FERROR_UNLOCKED(stream) \ + ((stream)->__modeflags & (__FLAG_EOF|__FLAG_ERROR)) + +#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSNPRINTF 1 +#endif diff --git a/libc/stdio/_store_inttype.c b/libc/stdio/_store_inttype.c new file mode 100644 index 0000000..fdd4dce --- /dev/null +++ b/libc/stdio/_store_inttype.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Right now, we assume intmax_t is either long or long long */ + +#ifdef INTMAX_MAX + +#ifdef LLONG_MAX + +#if INTMAX_MAX > LLONG_MAX +#error INTMAX_MAX > LLONG_MAX! The printf code needs to be updated! +#endif + +#elif INTMAX_MAX > LONG_MAX + +#error No LLONG_MAX and INTMAX_MAX > LONG_MAX! The printf code needs to be updated! + +#endif /* LLONG_MAX */ + +#endif /* INTMAX_MAX */ + +/* We assume int may be short or long, but short and long are different. */ + +void _store_inttype(register void *dest, int desttype, uintmax_t val) attribute_hidden; +void _store_inttype(register void *dest, int desttype, uintmax_t val) +{ + if (desttype == __PA_FLAG_CHAR) { /* assume char not int */ + *((unsigned char *) dest) = val; + return; + } +#if defined(LLONG_MAX) && (INT_MAX != LLONG_MAX) + if (desttype == PA_FLAG_LONG_LONG) { + *((unsigned long long int *) dest) = val; + return; + } +#endif /* LLONG_MAX */ +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) { + *((unsigned short int *) dest) = val; + return; + } +#endif /* SHRT_MAX */ +#if LONG_MAX != INT_MAX + if (desttype == PA_FLAG_LONG) { + *((unsigned long int *) dest) = val; + return; + } +#endif /* LONG_MAX */ + + *((unsigned int *) dest) = val; +} diff --git a/libc/stdio/_trans2r.c b/libc/stdio/_trans2r.c new file mode 100644 index 0000000..1f39300 --- /dev/null +++ b/libc/stdio/_trans2r.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Function to handle transition to reading. + * Initialize or verify the stream's orientation (even if writeonly). + * Check that the stream is readable. + * If currently reading, check that we can transition to writing. + * C99 requires that we not be reading, but attempting to + * auto-transition by commiting the write buffer is a configurable + * option. + * Returns 0 on success and EOF otherwise. + * + * Notes: + * There are two function signatures, depending on wchar support, + * since with no wchar support the orientation is narrow by default. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +int attribute_hidden __stdio_trans2r_o(FILE * __restrict stream, int oflag) +#else +int attribute_hidden __stdio_trans2r(FILE * __restrict stream) +#endif +{ + __STDIO_STREAM_VALIDATE(stream); + assert(!__STDIO_STREAM_IS_READING(stream)); + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!(stream->__modeflags & oflag)) { + if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) { + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; + } + stream->__modeflags |= oflag; + } +#endif + + if (stream->__modeflags & __FLAG_WRITEONLY) { +#if defined(__UCLIBC_HAS_WCHAR__) || !defined(__UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__) + DO_EBADF: +#endif + __set_errno(EBADF); +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + ERROR: +#endif + __STDIO_STREAM_SET_ERROR(stream); + __STDIO_STREAM_VALIDATE(stream); + return EOF; + } + + if (__STDIO_STREAM_IS_WRITING(stream)) { +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + if (__STDIO_COMMIT_WRITE_BUFFER(stream)) { /* commit failed! */ + goto ERROR; + } + assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); + + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); +#else + /* C99: Output shall not be directly followed by input without an + intervening call to the fflush function or to a file positioning + function (fseek, fsetpos, or rewind). */ + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; +#endif + } + + __STDIO_STREAM_SET_READING(stream); + /* getc macro is enabled when data is read into buffer. */ + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} diff --git a/libc/stdio/_trans2w.c b/libc/stdio/_trans2w.c new file mode 100644 index 0000000..ed1a583 --- /dev/null +++ b/libc/stdio/_trans2w.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fseek) + +/* Function to handle transition to writing. + * Initialize or verify the stream's orientation (even if readonly). + * Check that the stream is writable. + * If currently reading, check that we can transition to writing. + * C99 requires that the stream is at EOF, but attempting to + * auto-transition via fseek() is a configurable option. + * Returns 0 on success and EOF otherwise. + * + * Notes: + * There are two function signatures, depending on wchar support, + * since with no wchar support the orientation is narrow by default. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +int attribute_hidden __stdio_trans2w_o(FILE * __restrict stream, int oflag) +#else +int attribute_hidden __stdio_trans2w(FILE * __restrict stream) +#endif +{ + __STDIO_STREAM_VALIDATE(stream); + assert(!__STDIO_STREAM_IS_WRITING(stream)); + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!(stream->__modeflags & oflag)) { + if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) { + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; + } + stream->__modeflags |= oflag; + } +#endif + + if (stream->__modeflags & __FLAG_READONLY) { +#if defined(__UCLIBC_HAS_WCHAR__) || !defined(__UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__) + DO_EBADF: +#endif + __set_errno(EBADF); +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + ERROR: +#endif + __STDIO_STREAM_SET_ERROR(stream); + __STDIO_STREAM_VALIDATE(stream); + return EOF; + } + + if (__STDIO_STREAM_IS_READING(stream)) { + if (!__FEOF_UNLOCKED(stream)) { +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + /* Need to seek to correct position if we have buffered + * read data or ungots. If appending, we might as well + * seek to the end. + * + * NOTE: If the OS does not handle append files correctly, + * this is insufficient since we would need to seek to + * the end even if not reading.*/ + if (((__STDIO_STREAM_BUFFER_RAVAIL(stream)) + || (stream->__modeflags & __FLAG_UNGOT)) + && fseek(stream, 0L, + ((stream->__modeflags & __FLAG_APPEND) + ? SEEK_END : SEEK_CUR)) + ) { + /* fseek() only sets error indicator on read/write error. */ + goto ERROR; + } +#else + /* C99 requires either at EOF or currently not reading. */ + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; +#endif + } + __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + /* Reaching EOF does not reset buffer pointers... */ + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + } + + __STDIO_STREAM_SET_WRITING(stream); + if (__STDIO_STREAM_IS_NARROW_FBF(stream)) { + __STDIO_STREAM_ENABLE_PUTC(stream); + } + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} diff --git a/libc/stdio/_uintmaxtostr.c b/libc/stdio/_uintmaxtostr.c new file mode 100644 index 0000000..0d25a0a --- /dev/null +++ b/libc/stdio/_uintmaxtostr.c @@ -0,0 +1,153 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include "_stdio.h" +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* Avoid using long long / and % operations to cut down dependencies on + * libgcc.a. Definitely helps on i386 at least. */ +#if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX) +#define INTERNAL_DIV_MOD +#endif + +char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, + int base, __UIM_CASE alphacase) +{ + int negative; + unsigned int digit; +#ifdef INTERNAL_DIV_MOD + unsigned int H, L, high, low, rh; +#endif +#ifndef __LOCALE_C_ONLY + int grouping, outdigit; + const char *g; /* This does not need to be initialized. */ +#endif /* __LOCALE_C_ONLY */ + + negative = 0; + if (base < 0) { /* signed value */ + base = -base; + if (uval > INTMAX_MAX) { + uval = -uval; + negative = 1; + } + } + + /* this is an internal routine -- we shouldn't need to check this */ + assert(!((base < 2) || (base > 36))); + +#ifndef __LOCALE_C_ONLY + grouping = -1; + outdigit = 0x80 & alphacase; + alphacase ^= outdigit; + if (alphacase == __UIM_GROUP) { + assert(base == 10); + if (*(g = __UCLIBC_CURLOCALE_DATA.grouping)) { + grouping = *g; + } + } +#endif /* __LOCALE_C_ONLY */ + + *bufend = '\0'; + +#ifndef INTERNAL_DIV_MOD + do { +#ifndef __LOCALE_C_ONLY + if (!grouping) { /* Finished a group. */ + bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; + memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + __UCLIBC_CURLOCALE_DATA.thousands_sep_len); + if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ + /* Note: g[1] == -1 means no further grouping. But since + * we'll never wrap around, we can set grouping to -1 without + * fear of */ + ++g; + } + grouping = *g; + } + --grouping; +#endif /* __LOCALE_C_ONLY */ + digit = uval % base; + uval /= base; + +#ifndef __LOCALE_C_ONLY + if (unlikely(outdigit)) { + bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; + memcpy(bufend, + (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], + __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); + } else +#endif + { + *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase ); + } + } while (uval); + +#else /* ************************************************** */ + + H = (UINT_MAX / base); + L = UINT_MAX % base + 1; + if (L == base) { + ++H; + L = 0; + } + low = (unsigned int) uval; + high = (unsigned int) (uval >> (sizeof(unsigned int) * CHAR_BIT)); + + do { +#ifndef __LOCALE_C_ONLY + if (!grouping) { /* Finished a group. */ + bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; + memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + __UCLIBC_CURLOCALE_DATA.thousands_sep_len); + if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ + /* Note: g[1] == -1 means no further grouping. But since + * we'll never wrap around, we can set grouping to -1 without + * fear of */ + ++g; + } + grouping = *g; + } + --grouping; +#endif /* __LOCALE_C_ONLY */ + + if (unlikely(high)) { + rh = high % base; + high /= base; + digit = (low % base) + (L * rh); + low = (low / base) + (H * rh) + (digit / base); + digit %= base; + } else { + digit = low % base; + low /= base; + } + +#ifndef __LOCALE_C_ONLY + if (unlikely(outdigit)) { + bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; + memcpy(bufend, + (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], + __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); + } else +#endif + { + *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase ); + } + } while (low | high); + +#endif /******************************************************/ + + if (negative) { + *--bufend = '-'; + } + + return bufend; +} diff --git a/libc/stdio/_vfprintf.c b/libc/stdio/_vfprintf.c new file mode 100644 index 0000000..61a730d --- /dev/null +++ b/libc/stdio/_vfprintf.c @@ -0,0 +1,1983 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * My stdio library for linux and (soon) elks. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This code needs a lot of clean up. Some of that is on hold until uClibc + * gets a better configuration system (on Erik's todo list). + * The other cleanup will take place during the implementation/integration of + * the wide char (un)formatted i/o functions which I'm currently working on. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* April 1, 2002 + * Initialize thread locks for fake files in vsnprintf and vdprintf. + * reported by Erik Andersen (andersen@codepoet.com) + * Fix an arg promotion handling bug in _do_one_spec for %c. + * reported by Ilguiz Latypov + * + * May 10, 2002 + * Remove __isdigit and use new ctype.h version. + * Add conditional setting of QUAL_CHARS for size_t and ptrdiff_t. + * + * Aug 16, 2002 + * Fix two problems that showed up with the python 2.2.1 tests; one + * involving %o and one involving %f. + * + * Oct 28, 2002 + * Fix a problem in vasprintf (reported by vodz a while back) when built + * without custom stream support. In that case, it is necessary to do + * a va_copy. + * Make sure each va_copy has a matching va_end, as required by C99. + * + * Nov 4, 2002 + * Add locale-specific grouping support for integer decimal conversion. + * Add locale-specific decimal point support for floating point conversion. + * Note: grouping will have to wait for _dtostr() rewrite. + * Add printf wchar support for %lc (%C) and %ls (%S). + * Require printf format strings to be valid multibyte strings beginning and + * ending in their initial shift state, as per the stds. + * + * Nov 21, 2002 + * Add *wprintf functions. Currently they don't support floating point + * conversions. That will wait until the rewrite of _dtostr. + * + * Aug 1, 2003 + * Optional hexadecimal float notation support for %a/%A. + * Floating point output now works for *wprintf. + * Support for glibc locale-specific digit grouping for floats. + * Misc bug fixes. + * + * Aug 31, 2003 + * Fix precision bug for %g conversion specifier when using %f style. + * + * Sep 5, 2003 + * Implement *s*scanf for the non-buffered stdio case with old_vfprintf. + * + * Sep 23, 2003 + * vfprintf was not always checking for narrow stream orientation. + */ + +/* TODO: + * + * Should we validate that *printf format strings are valid multibyte + * strings in the current locale? ANSI/ISO C99 seems to imply this + * and Plauger's printf implementation in his Standard C Library book + * treats this as an error. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include +#include "_stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#include +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strnlen) */ +libc_hidden_proto(__glibc_strerror_r) +libc_hidden_proto(fputs_unlocked) +libc_hidden_proto(abort) +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(wcslen) +libc_hidden_proto(wcsnlen) +libc_hidden_proto(mbsrtowcs) +libc_hidden_proto(wcsrtombs) +libc_hidden_proto(btowc) +libc_hidden_proto(wcrtomb) +libc_hidden_proto(fputws) +#endif + +/* Some older or broken gcc toolchains define LONG_LONG_MAX but not + * LLONG_MAX. Since LLONG_MAX is part of the standard, that's what + * we use. So complain if we do not have it but should. + */ +#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) +#error Apparently, LONG_LONG_MAX is defined but LLONG_MAX is not. You need to fix your toolchain headers to support the standard macros for (unsigned) long long. +#endif + +/**********************************************************************/ +/* These provide some control over printf's feature set */ + +/* This is undefined below depeding on uClibc's configuration. */ +#define __STDIO_PRINTF_FLOAT 1 + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_PRINTF_M_SPEC__ */ + + +/**********************************************************************/ + +#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_FLOATS__) +#undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __BCC__ +#undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __STDIO_PRINTF_FLOAT +#include +#include +#else /* __STDIO_PRINTF_FLOAT */ +#undef L__fpmaxtostr +#endif /* __STDIO_PRINTF_FLOAT */ + + +#undef __STDIO_HAS_VSNPRINTF +#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSNPRINTF 1 +#endif + +/**********************************************************************/ + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +/* TODO -- move these to a configuration section? */ +#define MAX_FIELD_WIDTH 4095 + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_register_printf_function +/* emit only once */ +#warning WISHLIST: Make MAX_USER_SPEC configurable? +#warning WISHLIST: Make MAX_ARGS_PER_SPEC configurable? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + +#define MAX_USER_SPEC 10 +#define MAX_ARGS_PER_SPEC 5 + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +#undef MAX_USER_SPEC +#define MAX_ARGS_PER_SPEC 1 + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +#if MAX_ARGS_PER_SPEC < 1 +#error MAX_ARGS_PER_SPEC < 1! +#undef MAX_ARGS_PER_SPEC +#define MAX_ARGS_PER_SPEC 1 +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX < 9) +#error NL_ARGMAX < 9! +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX >= (MAX_ARGS_PER_SPEC + 2)) +#define MAX_ARGS NL_ARGMAX +#else +/* N for spec itself, plus 1 each for width and precision */ +#define MAX_ARGS (MAX_ARGS_PER_SPEC + 2) +#endif + +/**********************************************************************/ + +#define __PA_FLAG_INTMASK \ + (__PA_FLAG_CHAR|PA_FLAG_SHORT|__PA_FLAG_INT|PA_FLAG_LONG|PA_FLAG_LONG_LONG) + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +extern printf_function _custom_printf_handler[MAX_USER_SPEC] attribute_hidden; +extern printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC] attribute_hidden; +extern char *_custom_printf_spec attribute_hidden; +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +/**********************************************************************/ + +#define SPEC_FLAGS " +0-#'I" +enum { + FLAG_SPACE = 0x01, + FLAG_PLUS = 0x02, /* must be 2 * FLAG_SPACE */ + FLAG_ZERO = 0x04, + FLAG_MINUS = 0x08, /* must be 2 * FLAG_ZERO */ + FLAG_HASH = 0x10, + FLAG_THOUSANDS = 0x20, + FLAG_I18N = 0x40, /* only works for d, i, u */ + FLAG_WIDESTREAM = 0x80 +}; + +/**********************************************************************/ + +/* float layout 01234567890123456789 TODO: B?*/ +#define SPEC_CHARS "npxXoudifFeEgGaACScs" +enum { + CONV_n = 0, + CONV_p, + CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, + CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, + CONV_C, CONV_S, CONV_c, CONV_s, +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + CONV_m, +#endif + CONV_custom0 /* must be last */ +}; + +/* p x X o u d i */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 10 } + +#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ + CONV_C, CONV_S, CONV_c, CONV_s, CONV_custom0 } + +#define SPEC_OR_MASK { \ + /* n */ (PA_FLAG_PTR|PA_INT), \ + /* p */ PA_POINTER, \ + /* oxXudi */ PA_INT, \ + /* fFeEgGaA */ PA_DOUBLE, \ + /* C */ PA_WCHAR, \ + /* S */ PA_WSTRING, \ + /* c */ PA_CHAR, \ + /* s */ PA_STRING, \ +} + +#define SPEC_AND_MASK { \ + /* n */ (PA_FLAG_PTR|__PA_INTMASK), \ + /* p */ PA_POINTER, \ + /* oxXudi */ (__PA_INTMASK), \ + /* fFeEgGaA */ (PA_FLAG_LONG_DOUBLE|PA_DOUBLE), \ + /* C */ (PA_WCHAR), \ + /* S */ (PA_WSTRING), \ + /* c */ (PA_CHAR), \ + /* s */ (PA_STRING), \ +} + +/**********************************************************************/ +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +/* TODO -- Fix the table below to take into account stdint.h. */ +/* #ifndef LLONG_MAX */ +/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ +/* #else */ +/* #if LLONG_MAX != INTMAX_MAX */ +/* #error fix QUAL_CHARS intmax_t entry 'j'! */ +/* #endif */ +/* #endif */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS intmax_t entry 'j'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ + /* q:long_long Z:(s)size_t */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ + 1, 8 \ +} + +/**********************************************************************/ + +#ifdef __STDIO_VA_ARG_PTR +#ifdef __BCC__ +#define __va_arg_ptr(ap,type) (((type *)(ap += sizeof(type))) - 1) +#endif + +#if 1 +#ifdef __GNUC__ +/* TODO -- need other than for 386 as well! */ + +#ifndef __va_rounded_size +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#endif +#define __va_arg_ptr(AP, TYPE) \ + (AP = (va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + ((void *) ((char *) (AP) - __va_rounded_size (TYPE)))) +#endif +#endif +#endif /* __STDIO_VA_ARG_PTR */ + +#ifdef __va_arg_ptr +#define GET_VA_ARG(AP,F,TYPE,ARGS) (*(AP) = __va_arg_ptr(ARGS,TYPE)) +#define GET_ARG_VALUE(AP,F,TYPE) (*((TYPE *)(*(AP)))) +#else +typedef union { + wchar_t wc; + unsigned int u; + unsigned long ul; +#ifdef ULLONG_MAX + unsigned long long ull; +#endif +#ifdef __STDIO_PRINTF_FLOAT + double d; + long double ld; +#endif /* __STDIO_PRINTF_FLOAT */ + void *p; +} argvalue_t; + +#define GET_VA_ARG(AU,F,TYPE,ARGS) (AU->F = va_arg(ARGS,TYPE)) +#define GET_ARG_VALUE(AU,F,TYPE) ((TYPE)((AU)->F)) +#endif + +typedef struct { + const char *fmtpos; /* TODO: move below struct?? */ + struct printf_info info; +#ifdef NL_ARGMAX + int maxposarg; /* > 0 if args are positional, 0 if not, -1 if unknown */ +#endif /* NL_ARGMAX */ + int num_data_args; /* TODO: use sentinal??? */ + unsigned int conv_num; + unsigned char argnumber[4]; /* width | prec | 1st data | unused */ + int argtype[MAX_ARGS]; + va_list arg; +#ifdef __va_arg_ptr + void *argptr[MAX_ARGS]; +#else +/* if defined(NL_ARGMAX) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) */ + /* While this is wasteful of space in the case where pos args aren't + * enabled, it is also needed to support custom printf handlers. */ + argvalue_t argvalue[MAX_ARGS]; +#endif +} ppfs_t; /* parse printf format state */ + +/**********************************************************************/ + +/* TODO: fix printf to return 0 and set errno if format error. Standard says + only returns -1 if sets error indicator for the stream. */ + +#ifdef __STDIO_PRINTF_FLOAT +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + +extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +#endif + +extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0) attribute_hidden; /* validates */ +extern void _ppfs_prepargs(ppfs_t *ppfs, va_list arg) attribute_hidden; /* sets posargptrs */ +extern void _ppfs_setargs(ppfs_t *ppfs) attribute_hidden; /* sets argptrs for current spec */ +extern int _ppfs_parsespec(ppfs_t *ppfs) attribute_hidden; /* parses specifier */ + +extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; +extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; + +/**********************************************************************/ +#ifdef L_parse_printf_format + +/* NOTE: This function differs from the glibc version in that parsing stops + * upon encountering an invalid conversion specifier. Since this is the way + * my printf functions work, I think it makes sense to do it that way here. + * Unfortunately, since glibc sets the return type as size_t, we have no way + * of returning that the template is illegal, other than returning 0. + */ + +size_t parse_printf_format(register const char *template, + size_t n, register int *argtypes) +{ + ppfs_t ppfs; + size_t i; + size_t count = 0; + + if (_ppfs_init(&ppfs, template) >= 0) { +#ifdef NL_ARGMAX + if (ppfs.maxposarg > 0) { /* Using positional args. */ + count = ppfs.maxposarg; + if (n > count) { + n = count; + } + for (i = 0 ; i < n ; i++) { + *argtypes++ = ppfs.argtype[i]; + } + } else { /* Not using positional args. */ +#endif /* NL_ARGMAX */ + while (*template) { + if ((*template == '%') && (*++template != '%')) { + ppfs.fmtpos = template; + _ppfs_parsespec(&ppfs); /* Can't fail. */ + template = ppfs.fmtpos; /* Update to one past spec end. */ + if (ppfs.info.width == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + if (ppfs.info.prec == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + for (i = 0 ; i < ppfs.num_data_args ; i++) { + if ((ppfs.argtype[i]) != __PA_NOARG) { + ++count; + if (n > 0) { + *argtypes++ = ppfs.argtype[i]; + --n; + } + } + } + } else { + ++template; + } + } +#ifdef NL_ARGMAX + } +#endif /* NL_ARGMAX */ + } + + return count; +} + +#endif +/**********************************************************************/ +#ifdef L__ppfs_init + +int attribute_hidden _ppfs_init(register ppfs_t *ppfs, const char *fmt0) +{ + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif /* NL_ARGMAX */ + ppfs->fmtpos = fmt0; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make checking of the format string in C locale an option. +#endif +#ifdef __UCLIBC_HAS_LOCALE__ + /* To support old programs, don't check mb validity if in C locale. */ + if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) { + /* ANSI/ISO C99 requires format string to be a valid multibyte string + * beginning and ending in its initial shift state. */ + static const char invalid_mbs[] = "Invalid multibyte format string."; + mbstate_t mbstate; + const char *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = invalid_mbs; + return -1; + } + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const char *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = fmt; /* back up to the '%' */ + if ((r = _ppfs_parsespec(ppfs)) < 0) { + return -1; + } + fmt = ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = fmt0; /* rewind */ + } + +#ifdef NL_MAX_ARG + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_MAX_ARG */ + + return 0; +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_prepargs +void attribute_hidden _ppfs_prepargs(register ppfs_t *ppfs, va_list arg) +{ + int i; + + va_copy(ppfs->arg, arg); + +#ifdef NL_ARGMAX + if ((i = ppfs->maxposarg) > 0) { /* init for positional args */ + ppfs->num_data_args = i; + ppfs->info.width = ppfs->info.prec = ppfs->maxposarg = 0; + _ppfs_setargs(ppfs); + ppfs->maxposarg = i; + } +#endif /* NL_ARGMAX */ +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_setargs + +void attribute_hidden _ppfs_setargs(register ppfs_t *ppfs) +{ +#ifdef __va_arg_ptr + register void **p = ppfs->argptr; +#else + register argvalue_t *p = ppfs->argvalue; +#endif + int i; + +#ifdef NL_ARGMAX + if (ppfs->maxposarg == 0) { /* initing for or no pos args */ +#endif /* NL_ARGMAX */ + if (ppfs->info.width == INT_MIN) { + ppfs->info.width = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + i = 0; + while (i < ppfs->num_data_args) { + switch(ppfs->argtype[i++]) { + case (PA_INT|PA_FLAG_LONG_LONG): +#ifdef ULLONG_MAX + GET_VA_ARG(p,ull,unsigned long long,ppfs->arg); + break; +#endif + case (PA_INT|PA_FLAG_LONG): +#if ULONG_MAX != UINT_MAX + GET_VA_ARG(p,ul,unsigned long,ppfs->arg); + break; +#endif + case PA_CHAR: /* TODO - be careful */ + /* ... users could use above and really want below!! */ + case (PA_INT|__PA_FLAG_CHAR):/* TODO -- translate this!!! */ + case (PA_INT|PA_FLAG_SHORT): + case PA_INT: + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + break; + case PA_WCHAR: /* TODO -- assume int? */ + /* we're assuming wchar_t is at least an int */ + GET_VA_ARG(p,wc,wchar_t,ppfs->arg); + break; +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT */ + case PA_DOUBLE: + GET_VA_ARG(p,d,double,ppfs->arg); + break; + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + GET_VA_ARG(p,ld,long double,ppfs->arg); + break; +#else /* __STDIO_PRINTF_FLOAT */ + case PA_DOUBLE: + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + assert(0); + continue; +#endif /* __STDIO_PRINTF_FLOAT */ + default: + /* TODO -- really need to ensure this can't happen */ + assert(ppfs->argtype[i-1] & PA_FLAG_PTR); + case PA_POINTER: + case PA_STRING: + case PA_WSTRING: + GET_VA_ARG(p,p,void *,ppfs->arg); + break; + case __PA_NOARG: + continue; + } + ++p; + } +#ifdef NL_ARGMAX + } else { + if (ppfs->info.width == INT_MIN) { + ppfs->info.width + = (int) GET_ARG_VALUE(p + ppfs->argnumber[0] - 1,u,unsigned int); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec + = (int) GET_ARG_VALUE(p + ppfs->argnumber[1] - 1,u,unsigned int); + } + } +#endif /* NL_ARGMAX */ + + /* Now we know the width and precision. */ + if (ppfs->info.width < 0) { + ppfs->info.width = -ppfs->info.width; + PRINT_INFO_SET_FLAG(&(ppfs->info),left); + PRINT_INFO_CLR_FLAG(&(ppfs->info),space); + ppfs->info.pad = ' '; + } +#if 0 + /* NOTE -- keep neg for now so float knows! */ + if (ppfs->info.prec < 0) { /* spec says treat as omitted. */ + /* so use default prec... 1 for everything but floats and strings. */ + ppfs->info.prec = 1; + } +#endif +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_parsespec + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +/* Notes: argtype differs from glibc for the following: + * mine glibc + * lc PA_WCHAR PA_CHAR the standard says %lc means %C + * ls PA_WSTRING PA_STRING the standard says %ls means %S + * {*}n {*}|PA_FLAG_PTR PA_FLAG_PTR size of n can be qualified + */ + +/* TODO: store positions of positional args */ + +/* TODO -- WARNING -- assumes aligned on integer boundaries!!! */ + +/* TODO -- disable if not using positional args!!! */ +#define _OVERLAPPING_DIFFERENT_ARGS + +/* TODO -- rethink this -- perhaps we should set to largest type??? */ + +#ifdef _OVERLAPPING_DIFFERENT_ARGS + +#define PROMOTED_SIZE_OF(X) ((sizeof(X) + sizeof(int) - 1) / sizeof(X)) + +static const short int type_codes[] = { + __PA_NOARG, /* must be first entry */ + PA_POINTER, + PA_STRING, + PA_WSTRING, + PA_CHAR, + PA_INT|PA_FLAG_SHORT, + PA_INT, + PA_INT|PA_FLAG_LONG, + PA_INT|PA_FLAG_LONG_LONG, + PA_WCHAR, +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT, */ + PA_DOUBLE, + PA_DOUBLE|PA_FLAG_LONG_DOUBLE, +#endif /* __STDIO_PRINTF_FLOAT */ +}; + +static const unsigned char type_sizes[] = { + /* unknown type consumes no arg */ + 0, /* must be first entry */ + PROMOTED_SIZE_OF(void *), + PROMOTED_SIZE_OF(char *), + PROMOTED_SIZE_OF(wchar_t *), + PROMOTED_SIZE_OF(char), + PROMOTED_SIZE_OF(short), + PROMOTED_SIZE_OF(int), + PROMOTED_SIZE_OF(long), +#ifdef ULLONG_MAX + PROMOTED_SIZE_OF(long long), +#else + PROMOTED_SIZE_OF(long), /* TODO -- is this correct? (above too) */ +#endif + PROMOTED_SIZE_OF(wchar_t), +#ifdef __STDIO_PRINTF_FLOAT + /* PROMOTED_SIZE_OF(float), */ + PROMOTED_SIZE_OF(double), + PROMOTED_SIZE_OF(long double), +#endif /* __STDIO_PRINTF_FLOAT */ +}; + +static int _promoted_size(int argtype) +{ + register const short int *p; + + /* note -- since any unrecognized type is treated as a pointer */ + p = type_codes + sizeof(type_codes)/sizeof(type_codes[0]); + do { + if (*--p == argtype) { + break; + } + } while (p > type_codes); + + return type_sizes[(int)(p - type_codes)]; +} + +static int _is_equal_or_bigger_arg(int curtype, int newtype) +{ + /* Quick test */ + if (newtype == __PA_NOARG) { + return 0; + } + if ((curtype == __PA_NOARG) || (curtype == newtype)) { + return 1; + } + /* Ok... slot is already filled and types are different in name. */ + /* So, compare promoted sizes of curtype and newtype args. */ + return _promoted_size(curtype) <= _promoted_size(newtype); +} + +#else + +#define _is_equal_or_bigger_arg(C,N) (((C) == __PA_NOARG) || ((C) == (N))) + +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +/* TODO - do this differently? */ +static char _bss_custom_printf_spec[MAX_USER_SPEC]; /* 0-init'd for us. */ + +attribute_hidden char *_custom_printf_spec = _bss_custom_printf_spec; +attribute_hidden printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC]; +attribute_hidden printf_function _custom_printf_handler[MAX_USER_SPEC]; +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +int attribute_hidden _ppfs_parsespec(ppfs_t *ppfs) +{ + register const char *fmt; + register const char *p; + int preci; + int width; + int flags; + int dataargtype; + int i; + int dpoint; +#ifdef NL_ARGMAX + int maxposarg; +#endif /* NL_ARGMAX */ + int p_m_spec_chars; + int n; + int argtype[MAX_ARGS_PER_SPEC+2]; + int argnumber[3]; /* width, precision, 1st data arg */ + static const char spec_flags[] = SPEC_FLAGS; + static const char spec_chars[] = SPEC_CHARS;/* TODO: b? */ + static const char spec_ranges[] = SPEC_RANGES; + static const short spec_or_mask[] = SPEC_OR_MASK; + static const short spec_and_mask[] = SPEC_AND_MASK; + static const char qual_chars[] = QUAL_CHARS; +#ifdef __UCLIBC_HAS_WCHAR__ + char buf[32]; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* WIDE note: we can test against '%' here since we don't allow */ + /* WIDE note: other mappings of '%' in the wide char set. */ + preci = -1; + argnumber[0] = 0; + argnumber[1] = 0; + argtype[0] = __PA_NOARG; + argtype[1] = __PA_NOARG; +#ifdef NL_ARGMAX + maxposarg = ppfs->maxposarg; +#endif /* NL_ARGMAX */ + +#ifdef __UCLIBC_HAS_WCHAR__ + /* This is somewhat lame, but saves a lot of code. If we're dealing with + * a wide stream, that means the format is a wchar string. So, copy it + * char-by-char into a normal char buffer for processing. Make the buffer + * (buf) big enough so that any reasonable format specifier will fit. + * While there a legal specifiers that won't, the all involve duplicate + * flags or outrageous field widths/precisions. */ + width = dpoint = 0; + if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { + fmt = ppfs->fmtpos; + } else { + fmt = buf + 1; + i = 0; + do { + if ((buf[i] = (char) (((wchar_t *) ppfs->fmtpos)[i-1])) + != (((wchar_t *) ppfs->fmtpos)[i-1]) + ) { + return -1; + } + } while (buf[i++] && (i < sizeof(buf))); + buf[sizeof(buf)-1] = 0; + } +#else /* __UCLIBC_HAS_WCHAR__ */ + width = flags = dpoint = 0; + fmt = ppfs->fmtpos; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + assert(fmt[-1] == '%'); + assert(fmt[0] != '%'); + + /* Process arg pos and/or flags and/or width and/or precision. */ + width_precision: + p = fmt; + if (*fmt == '*') { + argtype[-dpoint] = PA_INT; + ++fmt; + } + i = 0; + while (isdigit(*fmt)) { + if (i < MAX_FIELD_WIDTH) { /* Avoid overflow. */ + i = (i * 10) + (*fmt - '0'); + } + ++fmt; + } + if (p[-1] == '%') { /* Check for a position. */ + + /* TODO: if val not in range, then error */ + +#ifdef NL_ARGMAX + if ((*fmt == '$') && (i > 0)) {/* Positional spec. */ + ++fmt; + if (maxposarg == 0) { + return -1; + } + if ((argnumber[2] = i) > maxposarg) { + maxposarg = i; + } + /* Now fall through to check flags. */ + } else { + if (maxposarg > 0) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Support prec and width for %m when positional args used + /* Actually, positional arg processing will fail in general + * for specifiers that don't require an arg. */ +#endif /* __UCLIBC_MJN3_ONLY__ */ + if (*fmt == 'm') { + goto PREC_WIDTH; + } +#endif /* __UCLIBC_HAS_PRINTF_M_SPEC__ */ + return -1; + } + maxposarg = 0; /* Possible redundant store, but cuts size. */ + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ + } +#else /* NL_ARGMAX */ + if (*fmt == '$') { /* Positional spec. */ + return -1; + } + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ +#endif /* NL_ARGMAX */ + + restart_flags: /* Process flags. */ + i = 1; + p = spec_flags; + + do { + if (*fmt == *p++) { + ++fmt; + flags |= i; + goto restart_flags; + } + i += i; /* Better than i <<= 1 for bcc */ + } while (*p); + i = 0; + + /* If '+' then ignore ' ', and if '-' then ignore '0'. */ + /* Note: Need to ignore '0' when prec is an arg with val < 0, */ + /* but that test needs to wait until the arg is retrieved. */ + flags &= ~((flags & (FLAG_PLUS|FLAG_MINUS)) >> 1); + /* Note: Ignore '0' when prec is specified < 0 too (in printf). */ + + if (fmt[-1] != '%') { /* If we've done anything, loop for width. */ + goto width_precision; + } + } + PREC_WIDTH: + if (*p == '*') { /* Prec or width takes an arg. */ +#ifdef NL_ARGMAX + if (maxposarg) { + if ((*fmt++ != '$') || (i <= 0)) { + /* Using pos args and no $ or invalid arg number. */ + return -1; + } + argnumber[-dpoint] = i; + } else +#endif /* NL_ARGMAX */ + if (++p != fmt) { + /* Not using pos args but digits followed *. */ + return -1; + } + i = INT_MIN; + } + + if (!dpoint) { + width = i; + if (*fmt == '.') { + ++fmt; + dpoint = -1; /* To use as default precison. */ + goto width_precision; + } + } else { + preci = i; + } + + /* Process qualifier. */ + p = qual_chars; + do { + if (*fmt == *p) { + ++fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++fmt; + } + dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + + /* Process conversion specifier. */ + if (!*fmt) { + return -1; + } + + p = spec_chars; + + do { + if (*fmt == *p) { + p_m_spec_chars = p - spec_chars; + + if ((p_m_spec_chars >= CONV_c) + && (dataargtype & PA_FLAG_LONG)) { + p_m_spec_chars -= 2; /* lc -> C and ls -> S */ + } + + ppfs->conv_num = p_m_spec_chars; + p = spec_ranges-1; + while (p_m_spec_chars > *++p) {} + + i = p - spec_ranges; + argtype[2] = (dataargtype | spec_or_mask[i]) & spec_and_mask[i]; + p = spec_chars; + break; + } + } while(*++p); + + ppfs->info.spec = *fmt; + ppfs->info.prec = preci; + ppfs->info.width = width; + ppfs->info.pad = ((flags & FLAG_ZERO) ? '0' : ' '); + ppfs->info._flags = (flags & ~FLAG_ZERO) | (dataargtype & __PA_INTMASK); + ppfs->num_data_args = 1; + + if (!*p) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + if (*fmt == 'm') { + ppfs->conv_num = CONV_m; + ppfs->num_data_args = 0; + goto DONE; + } +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + + /* Handle custom arg -- WARNING -- overwrites p!!! */ + ppfs->conv_num = CONV_custom0; + p = _custom_printf_spec; + do { + if (*p == *fmt) { + if ((ppfs->num_data_args + = ((*_custom_printf_arginfo[(int)(p-_custom_printf_spec)]) + (&(ppfs->info), MAX_ARGS_PER_SPEC, argtype+2))) + > MAX_ARGS_PER_SPEC) { + break; /* Error -- too many args! */ + } + goto DONE; + } + } while (++p < (_custom_printf_spec + MAX_USER_SPEC)); +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + /* Otherwise error. */ + return -1; + } + +#if defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) || defined(__UCLIBC_HAS_PRINTF_M_SPEC__) + DONE: +#endif + +#ifdef NL_ARGMAX + if (maxposarg > 0) { + i = 0; + do { + /* Update maxposarg and check that NL_ARGMAX is not exceeded. */ + n = ((i <= 2) + ? (ppfs->argnumber[i] = argnumber[i]) + : argnumber[2] + (i-2)); + if (n > maxposarg) { + if ((maxposarg = n) > NL_ARGMAX) { + return -1; + } + } + --n; + /* Record argtype with largest size (current, new). */ + if (_is_equal_or_bigger_arg(ppfs->argtype[n], argtype[i])) { + ppfs->argtype[n] = argtype[i]; + } + } while (++i < ppfs->num_data_args + 2); + } else { +#endif /* NL_ARGMAX */ + ppfs->argnumber[2] = 1; + memcpy(ppfs->argtype, argtype + 2, ppfs->num_data_args * sizeof(int)); +#ifdef NL_ARGMAX + } + + ppfs->maxposarg = maxposarg; +#endif /* NL_ARGMAX */ + +#ifdef __UCLIBC_HAS_WCHAR__ + if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { + ppfs->fmtpos = ++fmt; + } else { + ppfs->fmtpos = (const char *) (((const wchar_t *)(ppfs->fmtpos)) + + (fmt - buf) ); + } +#else /* __UCLIBC_HAS_WCHAR__ */ + ppfs->fmtpos = ++fmt; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + return ppfs->num_data_args + 2; +} + +#endif +/**********************************************************************/ +#ifdef L_register_printf_function + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + +int register_printf_function(int spec, printf_function handler, + printf_arginfo_function arginfo) +{ + register char *r; + register char *p; + + if (spec && (arginfo != NULL)) { /* TODO -- check if spec is valid char */ + r = NULL; + p = _custom_printf_spec + MAX_USER_SPEC; + do { + --p; + if (!*p) { + r = p; + } +#ifdef __BCC__ + else /* bcc generates less code with fall-through */ +#endif + if (*p == spec) { + r = p; + p = _custom_printf_spec; + } + } while (p > _custom_printf_spec); + + if (r) { + if (handler) { + *r = spec; + _custom_printf_handler[(int)(r - p)] = handler; + _custom_printf_arginfo[(int)(r - p)] = arginfo; + } else { + *r = 0; + } + return 0; + } + /* TODO -- if asked to unregister a non-existent spec, return what? */ + } + return -1; +} + +#endif + +#endif +/**********************************************************************/ +#if defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) + +/* We only support ascii digits (or their USC equivalent codes) in + * precision and width settings in *printf (wide) format strings. + * In other words, we don't currently support glibc's 'I' flag. + * We do accept it, but it is currently ignored. */ + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); + +#ifdef L__vfprintf_internal + +#define VFPRINTF_internal _vfprintf_internal +#define FMT_TYPE char +#define OUTNSTR _outnstr +#define STRLEN strlen +#define _PPFS_init _ppfs_init +#define OUTPUT(F,S) fputs_unlocked(S,F) +/* #define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) */ +#define _outnstr(stream, string, len) ((len > 0) ? __stdio_fwrite(string, len, stream) : 0) +#define FP_OUT _fp_out_narrow + +#ifdef __STDIO_PRINTF_FLOAT + +static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + size_t r = 0; + + if (type & 0x80) { /* Some type of padding needed. */ + int buflen = strlen((const char *) buf); + if ((len -= buflen) > 0) { + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } + } + len = buflen; + } + return r + OUTNSTR(fp, (const unsigned char *) buf, len); +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +#else /* L__vfprintf_internal */ + +#define VFPRINTF_internal _vfwprintf_internal +#define FMT_TYPE wchar_t +#define OUTNSTR _outnwcs +#define STRLEN wcslen +#define _PPFS_init _ppwfs_init +/* Pulls in fseek: */ +#define OUTPUT(F,S) fputws(S,F) +/* TODO: #define OUTPUT(F,S) _wstdio_fwrite((S),wcslen(S),(F)) */ +#define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream) +#define FP_OUT _fp_out_wide + +static size_t _outnstr(FILE *stream, const char *s, size_t wclen) +{ + /* NOTE!!! len here is the number of wchars we want to generate!!! */ + wchar_t wbuf[64]; + mbstate_t mbstate; + size_t todo, r, n; + + mbstate.__mask = 0; + todo = wclen; + + while (todo) { + r = mbsrtowcs(wbuf, &s, + ((todo <= sizeof(wbuf)/sizeof(wbuf[0])) + ? todo + : sizeof(wbuf)/sizeof(wbuf[0])), + &mbstate); + assert(((ssize_t)r) > 0); + n = _outnwcs(stream, wbuf, r); + todo -= n; + if (n != r) { + break; + } + } + + return wclen - todo; +} + +#ifdef __STDIO_PRINTF_FLOAT + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move defines from _fpmaxtostr. Put them in a common header. +#endif + +/* The following defines are from _fpmaxtostr.*/ +#define DIGITS_PER_BLOCK 9 +#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) +#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) + +static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + wchar_t wbuf[BUF_SIZE]; + const char *s = (const char *) buf; + size_t r = 0; + int i; + + if (type & 0x80) { /* Some type of padding needed */ + int buflen = strlen(s); + if ((len -= buflen) > 0) { + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } + } + len = buflen; + } + + if (len > 0) { + i = 0; + do { +#ifdef __LOCALE_C_ONLY + wbuf[i] = s[i]; +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (s[i] == ',') { + wbuf[i] = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; + } else +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + if (s[i] == '.') { + wbuf[i] = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; + } else { + wbuf[i] = s[i]; + } +#endif /* __LOCALE_C_ONLY */ + + } while (++i < len); + + r += OUTNSTR(fp, wbuf, len); + } + + return r; +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) +{ + static const wchar_t invalid_wcs[] = L"Invalid wide format string."; + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif /* NL_ARGMAX */ + ppfs->fmtpos = (const char *) fmt0; + ppfs->info._flags = FLAG_WIDESTREAM; + + { + mbstate_t mbstate; + const wchar_t *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (wcsrtombs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = (const char *) invalid_wcs; + return -1; + } + } + + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const wchar_t *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = (const char *) fmt; /* back up to the '%' */ + if ((r = _ppfs_parsespec(ppfs)) < 0) { + return -1; + } + fmt = (const wchar_t *) ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = (const char *) fmt0; /* rewind */ + } + +#ifdef NL_ARGMAX + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_ARGMAX */ + + return 0; +} + +#endif /* L__vfprintf_internal */ + + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) +{ + size_t todo = numpad; + + /* TODO -- Use a buffer to cut down on function calls... */ + FMT_TYPE pad[1]; + + *pad = padchar; + while (todo && (OUTNSTR(stream, (const unsigned char *) pad, 1) == 1)) { + --todo; + } + + return numpad - todo; +} + +/* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */ +static int _do_one_spec(FILE * __restrict stream, + register ppfs_t *ppfs, int *count) +{ + static const char spec_base[] = SPEC_BASE; +#ifdef L__vfprintf_internal + static const char prefix[] = "+\0-\0 \0000x\0000X"; + /* 0 2 4 6 9 11*/ +#else /* L__vfprintf_internal */ + static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X"; +#endif /* L__vfprintf_internal */ + enum { + PREFIX_PLUS = 0, + PREFIX_MINUS = 2, + PREFIX_SPACE = 4, + PREFIX_LWR_X = 6, + PREFIX_UPR_X = 9, + PREFIX_NONE = 11 + }; + +#ifdef __va_arg_ptr + const void * const *argptr; +#else + const void * argptr[MAX_ARGS_PER_SPEC]; +#endif + int *argtype; +#ifdef __UCLIBC_HAS_WCHAR__ + const wchar_t *ws = NULL; + mbstate_t mbstate; +#endif /* __UCLIBC_HAS_WCHAR__ */ + size_t slen; +#ifdef L__vfprintf_internal +#define SLEN slen +#else + size_t SLEN; + wchar_t wbuf[2]; +#endif + int base; + int numpad; + int alphacase; + int numfill = 0; /* TODO: fix */ + int prefix_num = PREFIX_NONE; + char padchar = ' '; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Determine appropriate buf size. +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* TODO: buf needs to be big enough for any possible error return strings + * and also for any locale-grouped long long integer strings generated. + * This should be large enough for any of the current archs/locales, but + * eventually this should be handled robustly. */ + char buf[128]; + +#ifdef NDEBUG + _ppfs_parsespec(ppfs); +#else + if (_ppfs_parsespec(ppfs) < 0) { /* TODO: just for debugging */ + abort(); + } +#endif + _ppfs_setargs(ppfs); + + argtype = ppfs->argtype + ppfs->argnumber[2] - 1; + /* Deal with the argptr vs argvalue issue. */ +#ifdef __va_arg_ptr + argptr = (const void * const *) ppfs->argptr; +#ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + argptr += ppfs->argnumber[2] - 1; + } +#endif /* NL_ARGMAX */ +#else + /* Need to build a local copy... */ + { + register argvalue_t *p = ppfs->argvalue; + int i; +#ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + p += ppfs->argnumber[2] - 1; + } +#endif /* NL_ARGMAX */ + for (i = 0 ; i < ppfs->num_data_args ; i++ ) { + argptr[i] = (void *) p++; + } + } +#endif + { + register char *s = NULL; /* TODO: Should s be unsigned char * ? */ + + if (ppfs->conv_num == CONV_n) { + _store_inttype(*(void **)*argptr, + ppfs->info._flags & __PA_INTMASK, + (intmax_t) (*count)); + return 0; + } + if (ppfs->conv_num <= CONV_i) { /* pointer or (un)signed int */ + alphacase = __UIM_LOWER; + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + if ((base = spec_base[(int)(ppfs->conv_num - CONV_p)]) == 10) { + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),group)) { + alphacase = __UIM_GROUP; + } + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),i18n)) { + alphacase |= 0x80; + } + } + + if (ppfs->conv_num <= CONV_u) { /* pointer or unsigned int */ + if (ppfs->conv_num == CONV_X) { + alphacase = __UIM_UPPER; + } + if (ppfs->conv_num == CONV_p) { /* pointer */ + prefix_num = PREFIX_LWR_X; + } else { /* unsigned int */ + } + } else { /* signed int */ + base = -base; + } + if (ppfs->info.prec < 0) { /* Ignore '0' flag if prec specified. */ + padchar = ppfs->info.pad; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: If using outdigits and/or grouping, how should we interpret precision? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + s = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) + _load_inttype(ppfs->conv_num == CONV_p ? PA_FLAG_LONG : *argtype & __PA_INTMASK, + *argptr, base), base, alphacase); + if (ppfs->conv_num > CONV_u) { /* signed int */ + if (*s == '-') { + PRINT_INFO_SET_FLAG(&(ppfs->info),showsign); + ++s; /* handle '-' in the prefix string */ + prefix_num = PREFIX_MINUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),showsign)) { + prefix_num = PREFIX_PLUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),space)) { + prefix_num = PREFIX_SPACE; + } + } + slen = (char *)(buf + sizeof(buf) - 1) - s; +#ifdef L__vfwprintf_internal + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs(NULL, &q, 0, &mbstate); + } +#endif + numfill = ((ppfs->info.prec < 0) ? 1 : ppfs->info.prec); + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),alt)) { + if (ppfs->conv_num <= CONV_x) { /* x or p */ + prefix_num = PREFIX_LWR_X; + } + if (ppfs->conv_num == CONV_X) { + prefix_num = PREFIX_UPR_X; + } + if ((ppfs->conv_num == CONV_o) && (numfill <= SLEN)) { + numfill = ((*s == '0') ? 1 : SLEN + 1); + } + } + if (*s == '0') { + if (prefix_num >= PREFIX_LWR_X) { + prefix_num = PREFIX_NONE; + } + if (ppfs->conv_num == CONV_p) {/* null pointer */ + s = "(nil)"; +#ifdef L__vfwprintf_internal + SLEN = +#endif + slen = 5; + numfill = 0; + } else if (numfill == 0) { /* if precision 0, no output */ +#ifdef L__vfwprintf_internal + SLEN = +#endif + slen = 0; + } + } + numfill = ((numfill > SLEN) ? numfill - SLEN : 0); + } else if (ppfs->conv_num <= CONV_A) { /* floating point */ +#ifdef __STDIO_PRINTF_FLOAT + ssize_t nf; + nf = _fpmaxtostr(stream, + (__fpmax_t) + (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) + ? *(long double *) *argptr + : (long double) (* (double *) *argptr)), + &ppfs->info, FP_OUT ); + if (nf < 0) { + return -1; + } + *count += nf; + + return 0; +#else /* __STDIO_PRINTF_FLOAT */ + return -1; /* TODO -- try to continue? */ +#endif /* __STDIO_PRINTF_FLOAT */ + } else if (ppfs->conv_num <= CONV_S) { /* wide char or string */ +#ifdef L__vfprintf_internal + +#ifdef __UCLIBC_HAS_WCHAR__ + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (ppfs->conv_num == CONV_S) { /* wide string */ + if (!(ws = *((const wchar_t **) *argptr))) { + goto NULL_STRING; + } + /* We use an awful uClibc-specific hack here, passing + * (char*) &ws as the conversion destination. This signals + * uClibc's wcsrtombs that we want a "restricted" length + * such that the mbs fits in a buffer of the specified + * size with no partial conversions. */ + if ((slen = wcsrtombs((char *) &ws, &ws, /* Use awful hack! */ + ((ppfs->info.prec >= 0) + ? ppfs->info.prec + : SIZE_MAX), &mbstate)) + == ((size_t)-1) + ) { + return -1; /* EILSEQ */ + } + } else { /* wide char */ + s = buf; + slen = wcrtomb(s, (*((const wchar_t *) *argptr)), &mbstate); + if (slen == ((size_t)-1)) { + return -1; /* EILSEQ */ + } + s[slen] = 0; /* TODO - Is this necessary? */ + } +#else /* __UCLIBC_HAS_WCHAR__ */ + return -1; +#endif /* __UCLIBC_HAS_WCHAR__ */ + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + if (ppfs->conv_num == CONV_s) { /* string */ + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + slen = strnlen(s, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { +#ifdef __UCLIBC_HAS_WCHAR__ + NULL_STRING: +#endif + s = "(null)"; + slen = 6; + } + } else { /* char */ + s = buf; + *s = (unsigned char)(*((const int *) *argptr)); + s[1] = 0; + slen = 1; + } + +#else /* L__vfprintf_internal */ + + if (ppfs->conv_num == CONV_S) { /* wide string */ + ws = *((wchar_t **) (*argptr)); + if (!ws) { + goto NULL_STRING; + } + SLEN = wcsnlen(ws, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { /* wide char */ + *wbuf = (wchar_t)(*((const wint_t *) *argptr)); + CHAR_CASE: + ws = wbuf; + wbuf[1] = 0; + SLEN = 1; + } + + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + + if (ppfs->conv_num == CONV_s) { /* string */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix %s for _vfwprintf_internal... output upto illegal sequence? +#endif /* __UCLIBC_MJN3_ONLY__ */ + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + /* We use an awful uClibc-specific hack here, passing + * (wchar_t*) &mbstate as the conversion destination. + * This signals uClibc's mbsrtowcs that we want a + * "restricted" length such that the mbs fits in a buffer + * of the specified size with no partial conversions. */ + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs((wchar_t *) &mbstate, &q, + ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX), + &mbstate); + } + if (SLEN == ((size_t)(-1))) { + return -1; /* EILSEQ */ + } + } else { + NULL_STRING: + s = "(null)"; + SLEN = slen = 6; + } + } else { /* char */ + *wbuf = btowc( (unsigned char)(*((const int *) *argptr)) ); + goto CHAR_CASE; + } + +#endif /* L__vfprintf_internal */ + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + } else if (ppfs->conv_num == CONV_m) { + s = __glibc_strerror_r(errno, buf, sizeof(buf)); + goto SET_STRING_LEN; +#endif + } else { +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + assert(ppfs->conv_num == CONV_custom0); + + s = _custom_printf_spec; + do { + if (*s == ppfs->info.spec) { + int rv; + /* TODO -- check return value for sanity? */ + rv = (*_custom_printf_handler + [(int)(s-_custom_printf_spec)]) + (stream, &ppfs->info, argptr); + if (rv < 0) { + return -1; + } + *count += rv; + return 0; + } + } while (++s < (_custom_printf_spec + MAX_USER_SPEC)); +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + assert(0); + return -1; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: If using outdigits and/or grouping, how should we pad? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + { + size_t t; + + t = SLEN + numfill; + if (prefix_num != PREFIX_NONE) { + t += ((prefix_num < PREFIX_LWR_X) ? 1 : 2); + } + numpad = ((ppfs->info.width > t) ? (ppfs->info.width - t) : 0); + *count += t + numpad; + } + if (padchar == '0') { /* TODO: check this */ + numfill += numpad; + numpad = 0; + } + + /* Now handle the output itself. */ + if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) { + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + numpad = 0; + } + OUTPUT(stream, prefix + prefix_num); + + if (_charpad(stream, '0', numfill) != numfill) { + return -1; + } + +#ifdef L__vfprintf_internal + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!ws) { + assert(s); + if (_outnstr(stream, s, slen) != slen) { + return -1; + } + } else { /* wide string */ + size_t t; + mbstate.__mask = 0; /* Initialize the mbstate. */ + while (slen) { + t = (slen <= sizeof(buf)) ? slen : sizeof(buf); + t = wcsrtombs(buf, &ws, t, &mbstate); + assert (t != ((size_t)(-1))); + if (_outnstr(stream, buf, t) != t) { + return -1; + } + slen -= t; + } + } +#else /* __UCLIBC_HAS_WCHAR__ */ + if (_outnstr(stream, (const unsigned char *) s, slen) != slen) { + return -1; + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#else /* L__vfprintf_internal */ + + if (!ws) { + assert(s); + if (_outnstr(stream, s, SLEN) != SLEN) { + return -1; + } + } else { + if (_outnwcs(stream, ws, SLEN) != SLEN) { + return -1; + } + } + +#endif /* L__vfprintf_internal */ + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + } + + return 0; +} + +libc_hidden_proto(fprintf) + +int VFPRINTF_internal (FILE * __restrict stream, + const FMT_TYPE * __restrict format, + va_list arg) +{ + ppfs_t ppfs; + int count, r; + register const FMT_TYPE *s; + + count = 0; + s = format; + + if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */ + OUTNSTR(stream, (const unsigned char *) ppfs.fmtpos, + STRLEN((const FMT_TYPE *)(ppfs.fmtpos))); +#if defined(L__vfprintf_internal) && !defined(NDEBUG) + fprintf(stderr,"\nIMbS: \"%s\"\n\n", format); +#endif + count = -1; + } else { + _ppfs_prepargs(&ppfs, arg); /* This did a va_copy!!! */ + + do { + while (*format && (*format != '%')) { + ++format; + } + + if (format-s) { /* output any literal text in format string */ + if ( (r = OUTNSTR(stream, (const unsigned char *) s, format-s)) != (format-s)) { + count = -1; + break; + } + count += r; + } + + if (!*format) { /* we're done */ + break; + } + + if (format[1] != '%') { /* if we get here, *format == '%' */ + /* TODO: _do_one_spec needs to know what the output funcs are!!! */ + ppfs.fmtpos = (const char *)(++format); + /* TODO: check -- should only fail on stream error */ + if ( (r = _do_one_spec(stream, &ppfs, &count)) < 0) { + count = -1; + break; + } + s = format = (const FMT_TYPE *) ppfs.fmtpos; + } else { /* %% means literal %, so start new string */ + s = ++format; + ++format; + } + } while (1); + + va_end(ppfs.arg); /* Need to clean up after va_copy! */ + } + +/* #if defined(L__vfprintf_internal) && defined(__UCLIBC_HAS_WCHAR__) */ +/* DONE: */ +/* #endif */ + + return count; +} +#endif /* defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) */ + + +/**********************************************************************/ +#if defined(L_vfprintf) || defined(L_vfwprintf) + +/* This is just a wrapper around VFPRINTF_internal. + * Factoring out vfprintf internals allows: + * (1) vdprintf and vsnprintf don't need to setup fake locking, + * (2) __STDIO_STREAM_TRANS_TO_WRITE is not used in vfprintf internals, + * and thus fseek etc is not pulled in by vdprintf and vsnprintf. + * + * In order to not pull in fseek through fputs, OUTPUT() macro + * is using __stdio_fwrite (TODO: do the same for wide functions). + */ +#ifdef L_vfprintf +#define VFPRINTF vfprintf +#define VFPRINTF_internal _vfprintf_internal +#define FMT_TYPE char +#else +#define VFPRINTF vfwprintf +#define VFPRINTF_internal _vfwprintf_internal +#define FMT_TYPE wchar_t +#endif + +libc_hidden_proto(VFPRINTF) +int VFPRINTF (FILE * __restrict stream, + const FMT_TYPE * __restrict format, + va_list arg) +{ + int count; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if +#ifdef L_vfprintf + (!__STDIO_STREAM_IS_NARROW_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) +#else + (!__STDIO_STREAM_IS_WIDE_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)) +#endif + { + count = -1; + } else { + count = VFPRINTF_internal(stream, format, arg); + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return count; +} +libc_hidden_def(VFPRINTF) +#endif /* defined(L_vfprintf) || defined(L_vfwprintf) */ + +/**********************************************************************/ diff --git a/libc/stdio/_vfprintf_internal.c b/libc/stdio/_vfprintf_internal.c new file mode 100644 index 0000000..40bf39e --- /dev/null +++ b/libc/stdio/_vfprintf_internal.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__vfprintf_internal +#include "_vfprintf.c" diff --git a/libc/stdio/_vfwprintf_internal.c b/libc/stdio/_vfwprintf_internal.c new file mode 100644 index 0000000..8584cf4 --- /dev/null +++ b/libc/stdio/_vfwprintf_internal.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__vfwprintf_internal +#include "_vfprintf.c" diff --git a/libc/stdio/_wcommit.c b/libc/stdio/_wcommit.c new file mode 100644 index 0000000..a0b3219 --- /dev/null +++ b/libc/stdio/_wcommit.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __STDIO_BUFFERS + +/* Commit the data in the write buffer. + * Returns 0 on success, >0 (pending) on failure. + * Side effects are those of _stdio_WRITE + */ + +size_t attribute_hidden __stdio_wcommit(register FILE * __restrict stream) +{ + size_t bufsize; + + __STDIO_STREAM_VALIDATE(stream); + + if ((bufsize = __STDIO_STREAM_BUFFER_WUSED(stream)) != 0) { + stream->__bufpos = stream->__bufstart; + __stdio_WRITE(stream, stream->__bufstart, bufsize); + } + + return __STDIO_STREAM_BUFFER_WUSED(stream); +} + +#endif diff --git a/libc/stdio/_wfwrite.c b/libc/stdio/_wfwrite.c new file mode 100644 index 0000000..fb5c6b3 --- /dev/null +++ b/libc/stdio/_wfwrite.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __UCLIBC_HAS_WCHAR__ +#error wide function when no wide support! +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix prototype. +#endif + +libc_hidden_proto(wmemcpy) +libc_hidden_proto(wcsnrtombs) + +size_t attribute_hidden _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, + register FILE *__restrict stream) +{ + size_t r, count; + char buf[64]; + const wchar_t *pw; + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __STDIO_BUFFERS + if (__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream)) { + /* We know buffer is wchar aligned for fake streams. */ + count = (((wchar_t *)(stream->__bufend)) + - ((wchar_t *)(stream->__bufpos))); + if (count > n) { + count = n; + } + if (count) { + wmemcpy((wchar_t *)(stream->__bufpos), ws, count); + stream->__bufpos = (char *)(((wchar_t *)(stream->__bufpos)) + count); + } + __STDIO_STREAM_VALIDATE(stream); + return n; + } +#endif + + count = 0; + + if (__STDIO_STREAM_IS_WIDE_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE) + ) { + + pw = ws; + while (n > count) { + r = wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state); + if (r != ((size_t) -1)) { /* No encoding errors */ + if (!r) { + ++r; /* 0 is returned when nul is reached. */ + pw = ws + count + r; /* pw was set to NULL, so correct. */ + } + if (__stdio_fwrite(buf, r, stream) == r) { + count = pw - ws; + continue; + } + } + break; + } + + /* Note: The count is incorrect if 0 < __stdio_fwrite return < r!!! */ + } + + __STDIO_STREAM_VALIDATE(stream); + return count; +} diff --git a/libc/stdio/asprintf.c b/libc/stdio/asprintf.c new file mode 100644 index 0000000..3f19925 --- /dev/null +++ b/libc/stdio/asprintf.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + +libc_hidden_proto(asprintf) + +libc_hidden_proto(vasprintf) + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping asprintf and __asprintf since no vsnprintf! +#else + +int asprintf(char **__restrict buf, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vasprintf(buf, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(asprintf) + +#endif +#endif diff --git a/libc/stdio/clearerr.c b/libc/stdio/clearerr.c new file mode 100644 index 0000000..a96ecaa --- /dev/null +++ b/libc/stdio/clearerr.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef clearerr +#ifdef __DO_UNLOCKED + +#undef clearerr_unlocked +void clearerr_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __CLEARERR_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(clearerr_unlocked,clearerr) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +void clearerr(register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + __CLEARERR_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); +} + +#endif diff --git a/libc/stdio/clearerr_unlocked.c b/libc/stdio/clearerr_unlocked.c new file mode 100644 index 0000000..1728d03 --- /dev/null +++ b/libc/stdio/clearerr_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "clearerr.c" diff --git a/libc/stdio/ctermid.c b/libc/stdio/ctermid.c new file mode 100644 index 0000000..26369d6 --- /dev/null +++ b/libc/stdio/ctermid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Experimentally off - libc_hidden_proto(strcpy) */ + +char *ctermid(register char *s) +{ + static char sbuf[L_ctermid]; + +#ifdef __BCC__ + /* Currently elks doesn't support /dev/tty. */ + if (!s) { + s = sbuf; + } + *s = 0; + + return s; +#else + /* glibc always returns /dev/tty for linux. */ + return strcpy((s ? s : sbuf), "/dev/tty"); +#endif +} diff --git a/libc/stdio/dprintf.c b/libc/stdio/dprintf.c new file mode 100644 index 0000000..a8b2704 --- /dev/null +++ b/libc/stdio/dprintf.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + +libc_hidden_proto(vdprintf) + +int dprintf(int filedes, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vdprintf(filedes, format, arg); + va_end(arg); + + return rv; +} +#endif diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c new file mode 100644 index 0000000..27d3c7e --- /dev/null +++ b/libc/stdio/fclose.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +libc_hidden_proto(fclose) + +libc_hidden_proto(close) +libc_hidden_proto(fflush_unlocked) + +int fclose(register FILE *stream) +{ + int rv = 0; + __STDIO_AUTO_THREADLOCK_VAR; + +#ifdef __STDIO_HAS_OPENLIST +#if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) + /* First, remove the file from the open file list. */ + { + FILE *ptr; + + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + ptr = _stdio_openlist; + if ((ptr = _stdio_openlist) == stream) { + _stdio_openlist = stream->__nextopen; + } else { + while (ptr) { + if (ptr->__nextopen == stream) { + ptr->__nextopen = stream->__nextopen; + break; + } + ptr = ptr->__nextopen; + } + } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; + } +#endif +#endif + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __STDIO_BUFFERS + /* Write any pending buffered chars. */ + if (__STDIO_STREAM_IS_WRITING(stream)) { + rv = fflush_unlocked(stream); + } +#endif + + if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */ + rv = EOF; + } + + stream->__filedes = -1; + + /* We need a way for freopen to know that a file has been closed. + * Since a file can't be both readonly and writeonly, that makes + * an effective signal. It also has the benefit of disabling + * transitions to either reading or writing. */ +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* Before we mark the file as closed, make sure we increment the openlist use count + * so it isn't freed under us while still cleaning up. */ + __STDIO_OPENLIST_INC_USE; +#endif + stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); + stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); + +#ifndef NDEBUG + __STDIO_STREAM_RESET_GCS(stream); + + /* Reinitialize everything (including putc since fflush could fail). */ + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + +# ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +# endif +# ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +# endif +#endif + + __STDIO_AUTO_THREADUNLOCK(stream); + + __STDIO_STREAM_FREE_BUFFER(stream); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: inefficient - locks and unlocks twice and walks whole list +#endif +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* inefficient - locks/unlocks twice and walks whole list */ + __STDIO_OPENLIST_INC_DEL_CNT; + __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ +#else + __STDIO_STREAM_FREE_FILE(stream); +#endif + + return rv; +} +libc_hidden_def(fclose) diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c new file mode 100644 index 0000000..d3cbb67 --- /dev/null +++ b/libc/stdio/fcloseall.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +libc_hidden_proto(fclose) + +/* NOTE: GLIBC difference!!! -- fcloseall + * According to the info pages, glibc actually fclose()s all open files. + * Apparently, glibc's new version only fflush()s and unbuffers all + * writing streams to cope with unordered destruction of c++ static + * objects. + */ + +int fcloseall (void) +{ +#ifdef __STDIO_HAS_OPENLIST + + int retval = 0; + FILE *f; + + __STDIO_OPENLIST_INC_USE; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_head() operation +#endif + __STDIO_THREADLOCK_OPENLIST_ADD; + f = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while (f) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_next() operation +#endif + FILE *n = f->__nextopen; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(f); + /* Only call fclose on the stream if it is not already closed. */ + if ((f->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + != (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + if (fclose(f)) { + retval = EOF; + } + } + __STDIO_AUTO_THREADUNLOCK(f); + + f = n; + } + + __STDIO_OPENLIST_DEC_USE; + + return retval; + +#else + +#warning Always fails in this configuration because no open file list. + + return EOF; + +#endif +} +#endif diff --git a/libc/stdio/fdopen.c b/libc/stdio/fdopen.c new file mode 100644 index 0000000..635ab80 --- /dev/null +++ b/libc/stdio/fdopen.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fdopen) +libc_hidden_proto(fcntl) + +FILE *fdopen(int filedes, const char *mode) +{ + intptr_t cur_mode; + + return (((cur_mode = fcntl(filedes, F_GETFL))) != -1) + ? _stdio_fopen(cur_mode, mode, NULL, filedes) + : NULL; +} +libc_hidden_def(fdopen) diff --git a/libc/stdio/feof.c b/libc/stdio/feof.c new file mode 100644 index 0000000..e5f03b7 --- /dev/null +++ b/libc/stdio/feof.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef feof +#ifdef __DO_UNLOCKED + +#undef feof_unlocked +int feof_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __FEOF_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(feof_unlocked,feof) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int feof(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + retval = __FEOF_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/libc/stdio/feof_unlocked.c b/libc/stdio/feof_unlocked.c new file mode 100644 index 0000000..4553f30 --- /dev/null +++ b/libc/stdio/feof_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "feof.c" diff --git a/libc/stdio/ferror.c b/libc/stdio/ferror.c new file mode 100644 index 0000000..947b89e --- /dev/null +++ b/libc/stdio/ferror.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef ferror +#ifdef __DO_UNLOCKED + +#undef ferror_unlocked +int ferror_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __FERROR_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(ferror_unlocked,ferror) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int ferror(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + retval = __FERROR_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/libc/stdio/ferror_unlocked.c b/libc/stdio/ferror_unlocked.c new file mode 100644 index 0000000..19722b8 --- /dev/null +++ b/libc/stdio/ferror_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "ferror.c" diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c new file mode 100644 index 0000000..e1527b3 --- /dev/null +++ b/libc/stdio/fflush.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fflush_unlocked) + +#ifdef __DO_UNLOCKED + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Add option to test for undefined behavior of fflush. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +/* Even if the stream is set to user-locking, we still need to lock + * when all (lbf) writing streams are flushed. */ + +#define __MY_STDIO_THREADLOCK(__stream) \ + __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#define __MY_STDIO_THREADUNLOCK(__stream) \ + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) +void _stdio_openlist_dec_use(void) +{ + __STDIO_THREADLOCK_OPENLIST_DEL; + if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) { + FILE *p = NULL; + FILE *n; + FILE *stream; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: As an optimization, we could unlock after we move past the head. +#endif + /* Grab the openlist add lock since we might change the head of the list. */ + __STDIO_THREADLOCK_OPENLIST_ADD; + for (stream = _stdio_openlist; stream; stream = n) { + n = stream->__nextopen; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: fix for nonatomic +#endif + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN)) + == (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { /* The file was closed and should be removed from the list. */ + if (!p) { + _stdio_openlist = n; + } else { + p->__nextopen = n; + } + __STDIO_STREAM_FREE_FILE(stream); + } else { + p = stream; + } + } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + _stdio_openlist_del_count = 0; /* Should be clean now. */ + } + --_stdio_openlist_use_count; + __STDIO_THREADUNLOCK_OPENLIST_DEL; +} +#endif + +int fflush_unlocked(register FILE *stream) +{ +#ifdef __STDIO_BUFFERS + + int retval = 0; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably define a modeflags type +#endif + unsigned short bufmask = __FLAG_LBF; + +#ifndef NDEBUG + if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + + if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */ + stream = NULL; + bufmask = 0; + } + + if (!stream) { /* Flush all (lbf) writing streams. */ + + __STDIO_OPENLIST_INC_USE; + + __STDIO_THREADLOCK_OPENLIST_ADD; + stream = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while(stream) { + /* We only care about currently writing streams and do not want to + * block trying to obtain mutexes on non-writing streams. */ +#warning fix for nonatomic +#warning unnecessary check if no threads + if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ + __MY_STDIO_THREADLOCK(stream); + /* Need to check again once we have the lock. */ + if (!(((stream->__modeflags | bufmask) + ^ (__FLAG_WRITING|__FLAG_LBF) + ) & (__FLAG_WRITING|__MASK_BUFMODE)) + ) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); + } else { + retval = EOF; + } + } + __MY_STDIO_THREADUNLOCK(stream); + } + stream = stream->__nextopen; + } + + __STDIO_OPENLIST_DEC_USE; + + } else if (__STDIO_STREAM_IS_WRITING(stream)) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); + } else { + retval = EOF; + } + } +#if 0 + else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) { + /* ANSI/ISO says behavior in this case is undefined but also says you + * shouldn't flush a stream you were reading from. As usual, glibc + * caters to broken programs and simply ignores this. */ + __UNDEFINED_OR_NONPORTABLE; + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EBADF); + retval = EOF; + } +#endif + +#ifndef NDEBUG + if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + + return retval; + +#else /* __STDIO_BUFFERS --------------------------------------- */ + +#ifndef NDEBUG + if ((stream != NULL) +#ifdef __STDIO_HAS_OPENLIST + && (stream != (FILE *) &_stdio_openlist) +#endif + ) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + +#if 0 + if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) { + /* ANSI/ISO says behavior in this case is undefined but also says you + * shouldn't flush a stream you were reading from. As usual, glibc + * caters to broken programs and simply ignores this. */ + __UNDEFINED_OR_NONPORTABLE; + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EBADF); + return EOF; + } +#endif + + return 0; +#endif /* __STDIO_BUFFERS */ +} +libc_hidden_def(fflush_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fflush) +strong_alias(fflush_unlocked,fflush) +libc_hidden_def(fflush) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fflush) +int fflush(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + if (stream +#ifdef __STDIO_HAS_OPENLIST + && (stream != (FILE *) &_stdio_openlist) +#endif + ) { + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fflush_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + } else { + retval = fflush_unlocked(stream); + } + + return retval; +} +libc_hidden_def(fflush) + +#endif diff --git a/libc/stdio/fflush_unlocked.c b/libc/stdio/fflush_unlocked.c new file mode 100644 index 0000000..a6adb59 --- /dev/null +++ b/libc/stdio/fflush_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fflush.c" diff --git a/libc/stdio/fgetc.c b/libc/stdio/fgetc.c new file mode 100644 index 0000000..7eb2b6e --- /dev/null +++ b/libc/stdio/fgetc.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef fgetc +#undef fgetc_unlocked +#undef getc +#undef getc_unlocked + +libc_hidden_proto(__fgetc_unlocked) + +#ifdef __DO_UNLOCKED + +libc_hidden_proto(fflush_unlocked) + +int __fgetc_unlocked(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* First the fast path. We're good to go if getc macro enabled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) { + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Next quickest... reading and narrow oriented, but macro + * disabled and/or buffer is exhausted. */ + if (__STDIO_STREAM_IS_NARROW_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW) + ) { + if (stream->__modeflags & __FLAG_UNGOT) { /* Use ungots first. */ + unsigned char uc = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + __STDIO_STREAM_VALIDATE(stream); + return uc; + } + + if (__STDIO_STREAM_BUFFER_RAVAIL(stream)) { /* Have buffered? */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Is this a fake stream for *sscanf? */ + if (__STDIO_STREAM_IS_FAKE_VSSCANF(stream)) { + __STDIO_STREAM_SET_EOF(stream); + return EOF; + } + + /* We need to read from the host environment, so we must + * flush all line buffered streams if the stream is not + * fully buffered. */ + if (!__STDIO_STREAM_IS_FBF(stream)) { + __STDIO_FLUSH_LBF_STREAMS; + } + + if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ + __STDIO_STREAM_DISABLE_GETC(stream); + if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ + __STDIO_STREAM_ENABLE_GETC(stream); /* FBF or LBF */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + } else { + unsigned char uc; + if (__stdio_READ(stream, &uc, 1)) { + return uc; + } + } + } + + return EOF; +} +libc_hidden_def(__fgetc_unlocked) + +libc_hidden_proto(fgetc_unlocked) +strong_alias(__fgetc_unlocked,fgetc_unlocked) +libc_hidden_def(fgetc_unlocked) + +//libc_hidden_proto(__getc_unlocked) +//strong_alias(__fgetc_unlocked,__getc_unlocked) +//libc_hidden_def(__getc_unlocked) + +libc_hidden_proto(getc_unlocked) +strong_alias(__fgetc_unlocked,getc_unlocked) +libc_hidden_def(getc_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fgetc) +strong_alias(__fgetc_unlocked,fgetc) +libc_hidden_def(fgetc) + +strong_alias(__fgetc_unlocked,getc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fgetc) +int fgetc(register FILE *stream) +{ + if (stream->__user_locking != 0) { + return __GETC_UNLOCKED_MACRO(stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __GETC_UNLOCKED_MACRO(stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} +libc_hidden_def(fgetc) + +strong_alias(fgetc,getc) + +#endif diff --git a/libc/stdio/fgetc_unlocked.c b/libc/stdio/fgetc_unlocked.c new file mode 100644 index 0000000..a20c7ee --- /dev/null +++ b/libc/stdio/fgetc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetc.c" diff --git a/libc/stdio/fgetpos.c b/libc/stdio/fgetpos.c new file mode 100644 index 0000000..610737d --- /dev/null +++ b/libc/stdio/fgetpos.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +#define FTELL ftell +#endif + +libc_hidden_proto(FTELL) + +int fgetpos(FILE * __restrict stream, register fpos_t * __restrict pos) +{ +#ifdef __STDIO_MBSTATE + + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if ((pos->__pos = FTELL(stream)) >= 0) { + __COPY_MBSTATE(&(pos->__mbstate), &(stream->__state)); + pos->__mblen_pending = stream->__ungot_width[0]; + retval = 0; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else + + return ((pos->__pos = FTELL(stream)) >= 0) ? 0 : -1; + +#endif +} diff --git a/libc/stdio/fgetpos64.c b/libc/stdio/fgetpos64.c new file mode 100644 index 0000000..32b7120 --- /dev/null +++ b/libc/stdio/fgetpos64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define fgetpos fgetpos64 +#define fpos_t fpos64_t +#define FTELL ftello64 +#include "fgetpos.c" diff --git a/libc/stdio/fgets.c b/libc/stdio/fgets.c new file mode 100644 index 0000000..5acaf91 --- /dev/null +++ b/libc/stdio/fgets.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fgets_unlocked) + +#ifdef __DO_UNLOCKED + +libc_hidden_proto(__fgetc_unlocked) + +char *fgets_unlocked(char *__restrict s, int n, + register FILE * __restrict stream) +{ + register char *p; + int c; + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should fgets do if n <= 0? +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* Should we assert here? Or set errno? Or just fail... */ + if (n <= 0) { +/* __set_errno(EINVAL); */ + goto ERROR; + } + + p = s; + + while (--n) { + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) { + if ((*p++ = __STDIO_STREAM_BUFFER_GET(stream)) == '\n') { + break; + } + } else { + if ((c = __fgetc_unlocked(stream)) == EOF) { + if (__FERROR_UNLOCKED(stream)) { + goto ERROR; + } + break; + } + if ((*p++ = c) == '\n') { + break; + } + } + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: If n==1 and not at EOF, should fgets return an empty string? +#endif /* __UCLIBC_MJN3_ONLY__ */ + if (p > s) { + *p = 0; + return s; + } + + ERROR: + return NULL; +} +libc_hidden_def(fgets_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fgets) +strong_alias(fgets_unlocked,fgets) +libc_hidden_def(fgets) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fgets) +char *fgets(char *__restrict s, int n, + register FILE * __restrict stream) +{ + char *retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgets_unlocked(s, n, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fgets) + +#endif diff --git a/libc/stdio/fgets_unlocked.c b/libc/stdio/fgets_unlocked.c new file mode 100644 index 0000000..db01913 --- /dev/null +++ b/libc/stdio/fgets_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fgets.c" +#endif diff --git a/libc/stdio/fgetwc.c b/libc/stdio/fgetwc.c new file mode 100644 index 0000000..062d825 --- /dev/null +++ b/libc/stdio/fgetwc.c @@ -0,0 +1,142 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fgetwc_unlocked) + +libc_hidden_proto(mbrtowc) + +#ifdef __DO_UNLOCKED + +static void munge_stream(register FILE *stream, unsigned char *buf) +{ + stream->__bufend = stream->__bufstart = buf; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); +} + +wint_t fgetwc_unlocked(register FILE *stream) +{ + wint_t wi; + wchar_t wc[1]; + int n; + size_t r; + unsigned char sbuf[1]; + + __STDIO_STREAM_VALIDATE(stream); + + wi = WEOF; /* Prepare for failure. */ + + if (__STDIO_STREAM_IS_WIDE_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE) + ) { + if (stream->__modeflags & __FLAG_UNGOT) { /* Any ungetwc()s? */ + if (((stream->__modeflags & 1) || stream->__ungot[1])) { + stream->__ungot_width[0] = 0; /* Application ungot... */ + } else { /* scanf ungot */ + stream->__ungot_width[0] = stream->__ungot_width[1]; + } + + wi = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + goto DONE; + } + + if (!stream->__bufstart) { /* Ugh... stream isn't buffered! */ + /* Munge the stream temporarily to use a 1-byte buffer. */ + munge_stream(stream, sbuf); + ++stream->__bufend; + } + + if (stream->__state.__mask == 0) { /* If last was a complete char */ + stream->__ungot_width[0] = 0; /* then reset the width. */ + } + + LOOP: + if ((n = __STDIO_STREAM_BUFFER_RAVAIL(stream)) == 0) { + goto FILL_BUFFER; + } + + r = mbrtowc(wc, stream->__bufpos, n, &stream->__state); + if (((ssize_t) r) >= 0) { /* Success... */ + if (r == 0) { /* Nul wide char... means 0 byte for us so */ + ++r; /* increment r and handle below as single. */ + } + stream->__bufpos += r; + stream->__ungot_width[0] += r; + wi = *wc; + goto DONE; + } + + if (r == ((size_t) -2)) { + /* Potentially valid but incomplete and no more buffered. */ + stream->__bufpos += n; /* Update bufpos for stream. */ + stream->__ungot_width[0] += n; + FILL_BUFFER: + if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ + goto LOOP; + } + if (!__FERROR_UNLOCKED(stream)) { /* EOF with no error. */ + if (!stream->__state.__mask) { /* No partial wchar. */ + goto DONE; + } + /* EOF but partially complete wchar. */ + /* TODO: should EILSEQ be set? */ + __set_errno(EILSEQ); + } + } + + /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno + * to EILSEQ, or r == ((size_t)-2) and stream is in an error state + * or at EOF with a partially complete wchar. Make sure stream's + * error indicator is set. */ + stream->__modeflags |= __FLAG_ERROR; + + DONE: + if (stream->__bufstart == sbuf) { /* Need to un-munge the stream. */ + munge_stream(stream, NULL); + } + + } + + __STDIO_STREAM_VALIDATE(stream); + + return wi; +} +libc_hidden_def(fgetwc_unlocked) + +strong_alias(fgetwc_unlocked,getwc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fgetwc) +strong_alias(fgetwc_unlocked,fgetwc) +libc_hidden_def(fgetwc) + +strong_alias(fgetwc_unlocked,getwc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fgetwc) +wint_t fgetwc(register FILE *stream) +{ + wint_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgetwc_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fgetwc) + +strong_alias(fgetwc,getwc) +#endif diff --git a/libc/stdio/fgetwc_unlocked.c b/libc/stdio/fgetwc_unlocked.c new file mode 100644 index 0000000..8eab843 --- /dev/null +++ b/libc/stdio/fgetwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetwc.c" diff --git a/libc/stdio/fgetws.c b/libc/stdio/fgetws.c new file mode 100644 index 0000000..c7dcc7d --- /dev/null +++ b/libc/stdio/fgetws.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fgetws_unlocked) + +libc_hidden_proto(fgetwc_unlocked) + +#ifdef __DO_UNLOCKED + +wchar_t *fgetws_unlocked(wchar_t *__restrict ws, int n, + FILE *__restrict stream) +{ + register wchar_t *p = ws; + wint_t wi; + + __STDIO_STREAM_VALIDATE(stream); + + while ((n > 1) + && ((wi = fgetwc_unlocked(stream)) != WEOF) + && ((*p++ = wi) != '\n') + ) { + --n; + } + if (p == ws) { + /* TODO -- should we set errno? */ +/* if (n <= 0) { */ +/* errno = EINVAL; */ +/* } */ + return NULL; + } + *p = 0; + return ws; +} +libc_hidden_def(fgetws_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fgetws_unlocked,fgetws) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +wchar_t *fgetws(wchar_t *__restrict ws, int n, FILE *__restrict stream) +{ + wchar_t *retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgetws_unlocked(ws, n, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/libc/stdio/fgetws_unlocked.c b/libc/stdio/fgetws_unlocked.c new file mode 100644 index 0000000..6dd58f2 --- /dev/null +++ b/libc/stdio/fgetws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetws.c" diff --git a/libc/stdio/fileno.c b/libc/stdio/fileno.c new file mode 100644 index 0000000..929936b --- /dev/null +++ b/libc/stdio/fileno.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fileno_unlocked) + +#ifdef __DO_UNLOCKED + +int fileno_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + if ((!__STDIO_STREAM_IS_CUSTOM(stream)) && (stream->__filedes >= 0)) { + return stream->__filedes; + } + + __set_errno(EBADF); + return -1; +} +libc_hidden_def(fileno_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fileno) +strong_alias(fileno_unlocked,fileno) +libc_hidden_def(fileno) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fileno) +int fileno(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fileno_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fileno) + +#endif diff --git a/libc/stdio/fileno_unlocked.c b/libc/stdio/fileno_unlocked.c new file mode 100644 index 0000000..e500592 --- /dev/null +++ b/libc/stdio/fileno_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fileno.c" diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c new file mode 100644 index 0000000..3fad711 --- /dev/null +++ b/libc/stdio/flockfile.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +void flockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream); +} + diff --git a/libc/stdio/fmemopen.c b/libc/stdio/fmemopen.c new file mode 100644 index 0000000..ba194d7 --- /dev/null +++ b/libc/stdio/fmemopen.c @@ -0,0 +1,183 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(fopencookie) + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +typedef struct { + size_t pos; + size_t len; + size_t eof; + int dynbuf; + unsigned char *buf; + FILE *fp; +} __fmo_cookie; + +#define COOKIE ((__fmo_cookie *) cookie) + +static ssize_t fmo_read(register void *cookie, char *buf, size_t bufsize) +{ + size_t count = COOKIE->len - COOKIE->pos; + + /* Note: 0 < bufsize < SSIZE_MAX because of _stdio_READ. */ + if (!count) { /* EOF! */ + return 0; + } + + if (bufsize > count) { + bufsize = count; + } + + memcpy(buf, COOKIE->buf + COOKIE->pos, bufsize); + COOKIE->pos += bufsize; + + return bufsize; +} + +static ssize_t fmo_write(register void *cookie, const char *buf, size_t bufsize) +{ + size_t count; + + /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */ + + /* If appending, need to seek to end of file!!!! */ + if (COOKIE->fp->__modeflags & __FLAG_APPEND) { + COOKIE->pos = COOKIE->eof; + } + + count = COOKIE->len - COOKIE->pos; + + if (bufsize > count) { + bufsize = count; + if (count == 0) { /* We're at the end of the buffer... */ + __set_errno(EFBIG); + return -1; + } + } + + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + COOKIE->pos += bufsize; + + if (COOKIE->pos > COOKIE->eof) { + COOKIE->eof = COOKIE->pos; + if (bufsize < count) { /* New eof and still room in buffer? */ + *(COOKIE->buf + COOKIE->pos) = 0; + } + } + + return bufsize; +} + +/* glibc doesn't allow seeking, but it has in-buffer seeks... we don't. */ +static int fmo_seek(register void *cookie, __offmax_t *pos, int whence) +{ + __offmax_t p = *pos; + + /* Note: fseek already checks that whence is legal, so don't check here + * unless debugging. */ + assert(((unsigned int) whence) <= 2); + + if (whence != SEEK_SET) { + p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof; + } + + /* Note: glibc only allows seeking in the buffer. We'll actually restrict + * to the data. */ + /* Check for offset < 0, offset > eof, or offset overflow... */ + if (((uintmax_t) p) > COOKIE->eof) { + return -1; + } + + COOKIE->pos = *pos = p; + return 0; +} + +static int fmo_close(register void *cookie) +{ + if (COOKIE->dynbuf) { + free(COOKIE->buf); + } + free(cookie); + return 0; +} + +#undef COOKIE + +static const cookie_io_functions_t _fmo_io_funcs = { + fmo_read, fmo_write, fmo_seek, fmo_close +}; + +/* TODO: If we have buffers enabled, it might be worthwile to add a pointer + * to the FILE in the cookie and have read, write, and seek operate directly + * on the buffer itself (ie replace the FILE buffer with the cookie buffer + * and update FILE bufstart, etc. whenever we seek). */ + +FILE *fmemopen(void *s, size_t len, const char *modes) +{ + FILE *fp; + register __fmo_cookie *cookie; + size_t i; + + if ((cookie = malloc(sizeof(__fmo_cookie))) != NULL) { + cookie->len = len; + cookie->eof = cookie->pos = 0; /* pos and eof adjusted below. */ + cookie->dynbuf = 0; + if (((cookie->buf = s) == NULL) && (len > 0)) { + if ((cookie->buf = malloc(len)) == NULL) { + goto EXIT_cookie; + } + cookie->dynbuf = 1; + *cookie->buf = 0; /* If we're appending, treat as empty file. */ + } + +#ifndef __BCC__ + fp = fopencookie(cookie, modes, _fmo_io_funcs); +#else + fp = fopencookie(cookie, modes, &_fmo_io_funcs); +#endif + /* Note: We don't need to worry about locking fp in the thread case + * as the only possible access would be a close or flush with + * nothing currently in the FILE's write buffer. */ + + if (fp != NULL) { + cookie->fp = fp; + if (fp->__modeflags & __FLAG_READONLY) { + cookie->eof = len; + } + if ((fp->__modeflags & __FLAG_APPEND) && (len > 0)) { + for (i = 0 ; i < len ; i++) { + if (cookie->buf[i] == 0) { + break; + } + } + cookie->eof = cookie->pos = i; /* Adjust eof and pos. */ + } + + __STDIO_STREAM_VALIDATE(fp); + + return fp; + } + } + + if (!s) { + free(cookie->buf); + } + EXIT_cookie: + free(cookie); + + return NULL; +} +#endif diff --git a/libc/stdio/fopen.c b/libc/stdio/fopen.c new file mode 100644 index 0000000..ec14b59 --- /dev/null +++ b/libc/stdio/fopen.c @@ -0,0 +1,22 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +# define FILEDES_ARG (-1) +#undef fopen +#else +#undef fopen64 +#endif + +libc_hidden_proto(fopen) +FILE *fopen(const char * __restrict filename, const char * __restrict mode) +{ + return _stdio_fopen(((intptr_t) filename), mode, NULL, FILEDES_ARG); +} +libc_hidden_def(fopen) diff --git a/libc/stdio/fopen64.c b/libc/stdio/fopen64.c new file mode 100644 index 0000000..cbdb03d --- /dev/null +++ b/libc/stdio/fopen64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#undef fopen +#define fopen fopen64 +#define FILEDES_ARG (-2) +#include "fopen.c" diff --git a/libc/stdio/fopencookie.c b/libc/stdio/fopencookie.c new file mode 100644 index 0000000..0b7ed84 --- /dev/null +++ b/libc/stdio/fopencookie.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +/* NOTE: GLIBC difference!!! -- fopencookie + * According to the info pages, glibc allows seeking within buffers even if + * no seek function is supplied. We don't. */ + +/* NOTE: GLIBC difference!!! -- fopencookie + * When compiled without large file support, the offset pointer for the + * cookie_seek function is off_t * and not off64_t * as for glibc. */ + +/* NOTE: GLIBC difference!!! -- fopencookie (bcc only) + * Since bcc doesn't support passing of structs, we define fopencookie as a + * macro in terms of _fopencookie which takes a struct * for the io functions + * instead. + */ + +/* Currently no real reentrancy issues other than a possible double close(). */ + +#ifndef __BCC__ +libc_hidden_proto(fopencookie) +FILE *fopencookie(void * __restrict cookie, const char * __restrict mode, + cookie_io_functions_t io_functions) +#else +FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode, + register cookie_io_functions_t *io_functions) +#endif +{ + FILE *stream; + + /* Fake an fdopen guaranteed to pass the _stdio_fopen basic agreement + * check without an fcntl call. */ + stream = _stdio_fopen(((intptr_t)(INT_MAX-1)), mode, NULL, INT_MAX); + if (stream) { + stream->__filedes = -1; +#ifndef __BCC__ + stream->__gcs = io_functions; +#else + stream->__gcs.read = io_functions->read; + stream->__gcs.write = io_functions->write; + stream->__gcs.seek = io_functions->seek; + stream->__gcs.close = io_functions->close; +#endif + stream->__cookie = cookie; + + __STDIO_STREAM_VALIDATE(stream); + } + + return stream; +} +#ifndef __BCC__ +libc_hidden_def(fopencookie) +#endif +#endif diff --git a/libc/stdio/fprintf.c b/libc/stdio/fprintf.c new file mode 100644 index 0000000..4f73441 --- /dev/null +++ b/libc/stdio/fprintf.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(vfprintf) + +libc_hidden_proto(fprintf) +int fprintf(FILE * __restrict stream, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfprintf(stream, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(fprintf) diff --git a/libc/stdio/fputc.c b/libc/stdio/fputc.c new file mode 100644 index 0000000..ac3b23e --- /dev/null +++ b/libc/stdio/fputc.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef fputc +#undef fputc_unlocked +#undef putc +#undef putc_unlocked + +libc_hidden_proto(__fputc_unlocked) + +#ifdef __DO_UNLOCKED + +int __fputc_unlocked(int c, register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* First the fast path. We're good to go if putc macro enabled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_ADD(stream)) { + __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); + return (unsigned char) c; + } + + /* Next quickest... writing and narrow oriented, but macro + * disabled and/or buffer is full. */ + if (__STDIO_STREAM_IS_NARROW_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW) + ) { + if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) { + return (unsigned char) c; + } + + if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ + /* The buffer is full and/or the stream is line buffered. */ + if (!__STDIO_STREAM_BUFFER_WAVAIL(stream) /* Buffer full? */ + && __STDIO_COMMIT_WRITE_BUFFER(stream) /* Commit failed! */ + ) { + goto BAD; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we fail if the commit fails but we now have room? +#endif + + __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); + + if (__STDIO_STREAM_IS_LBF(stream)) { + if ((((unsigned char) c) == '\n') + && __STDIO_COMMIT_WRITE_BUFFER(stream)) { + /* Commit failed! */ + __STDIO_STREAM_BUFFER_UNADD(stream); /* Undo the write! */ + goto BAD; + } + } + } else { + /* NOTE: Do not try to save space by moving uc to the top of + * the file, as that dramaticly increases runtime. */ + unsigned char uc = (unsigned char) c; + if (! __stdio_WRITE(stream, &uc, 1)) { + goto BAD; + } + } + return (unsigned char) c; + } + + BAD: + return EOF; +} +libc_hidden_def(__fputc_unlocked) + +/* exposing these would be fundamentally *wrong*! fix you, instead! */ +/* libc_hidden_proto(fputc_unlocked) */ +strong_alias(__fputc_unlocked,fputc_unlocked) +/* exposing these would be fundamentally *wrong*! fix you, instead! */ +/* libc_hidden_def(fputc_unlocked) */ + +libc_hidden_proto(putc_unlocked) +strong_alias(__fputc_unlocked,putc_unlocked) +libc_hidden_def(putc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fputc) +strong_alias(__fputc_unlocked,fputc) +libc_hidden_def(fputc) + +libc_hidden_proto(putc) +strong_alias(__fputc_unlocked,putc) +libc_hidden_def(putc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fputc) +int fputc(int c, register FILE *stream) +{ + if (stream->__user_locking != 0) { + return __PUTC_UNLOCKED_MACRO(c, stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __PUTC_UNLOCKED_MACRO(c, stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} +libc_hidden_def(fputc) + +libc_hidden_proto(putc) +strong_alias(fputc,putc) +libc_hidden_def(putc) + +#endif diff --git a/libc/stdio/fputc_unlocked.c b/libc/stdio/fputc_unlocked.c new file mode 100644 index 0000000..dc4c77a --- /dev/null +++ b/libc/stdio/fputc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputc.c" diff --git a/libc/stdio/fputs.c b/libc/stdio/fputs.c new file mode 100644 index 0000000..8a5fd40 --- /dev/null +++ b/libc/stdio/fputs.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fputs_unlocked) + +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(fwrite_unlocked) + +/* Note: The standard says fputs returns a nonnegative number on + * success. In this implementation, we return the length of the + * string written on success. + */ + +#ifdef __DO_UNLOCKED + +int fputs_unlocked(register const char * __restrict s, + FILE * __restrict stream) +{ + size_t n = strlen(s); + + return ((fwrite_unlocked(s, 1, n, stream) == n) ? n : EOF); +} +libc_hidden_def(fputs_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fputs) +strong_alias(fputs_unlocked,fputs) +libc_hidden_def(fputs) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fputs) +int fputs(const char * __restrict s, register FILE * __restrict stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputs_unlocked(s, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fputs) + +#endif diff --git a/libc/stdio/fputs_unlocked.c b/libc/stdio/fputs_unlocked.c new file mode 100644 index 0000000..c7ff3f5 --- /dev/null +++ b/libc/stdio/fputs_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fputs.c" +#endif diff --git a/libc/stdio/fputwc.c b/libc/stdio/fputwc.c new file mode 100644 index 0000000..240c1e9 --- /dev/null +++ b/libc/stdio/fputwc.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fputwc_unlocked) + +#ifdef __DO_UNLOCKED + +wint_t fputwc_unlocked(wchar_t wc, FILE *stream) +{ + return _wstdio_fwrite(&wc, 1, stream) ? wc : WEOF; +} +libc_hidden_def(fputwc_unlocked) + +strong_alias(fputwc_unlocked,putwc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fputwc_unlocked,fputwc) +strong_alias(fputwc_unlocked,putwc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +wint_t fputwc(wchar_t wc, register FILE *stream) +{ + wint_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputwc_unlocked(wc, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +strong_alias(fputwc,putwc) + +#endif diff --git a/libc/stdio/fputwc_unlocked.c b/libc/stdio/fputwc_unlocked.c new file mode 100644 index 0000000..757cbd0 --- /dev/null +++ b/libc/stdio/fputwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputwc.c" diff --git a/libc/stdio/fputws.c b/libc/stdio/fputws.c new file mode 100644 index 0000000..ecbc121 --- /dev/null +++ b/libc/stdio/fputws.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fputws_unlocked) + +libc_hidden_proto(wcslen) + +#ifdef __DO_UNLOCKED + +int fputws_unlocked(const wchar_t *__restrict ws, + register FILE *__restrict stream) +{ + size_t n = wcslen(ws); + + return (_wstdio_fwrite(ws, n, stream) == n) ? 0 : -1; +} +libc_hidden_def(fputws_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fputws) +strong_alias(fputws_unlocked,fputws) +libc_hidden_def(fputws) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fputws) +int fputws(const wchar_t *__restrict ws, register FILE *__restrict stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputws_unlocked(ws, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fputws) + +#endif diff --git a/libc/stdio/fputws_unlocked.c b/libc/stdio/fputws_unlocked.c new file mode 100644 index 0000000..b3a0377 --- /dev/null +++ b/libc/stdio/fputws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputws.c" diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c new file mode 100644 index 0000000..4f9c984 --- /dev/null +++ b/libc/stdio/fread.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fread_unlocked) + +#ifdef __DO_UNLOCKED + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(fflush_unlocked) + +size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb, + FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + + /* Note: If nmbem * size > SIZE_MAX then there is an application + * bug since no array can be larger than SIZE_MAX in size. */ + + if ((__STDIO_STREAM_IS_NARROW_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW)) + && size && nmemb + ) { + + if (nmemb <= (SIZE_MAX / size)) { + unsigned char *buffer = (unsigned char *) ptr; + size_t todo, bytes, avail; + + todo = bytes = size * nmemb; + + /* Check for ungots... */ + while (stream->__modeflags & __FLAG_UNGOT) { + *buffer++ = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + if (!--todo) { + goto DONE; + } + } + +#ifdef __STDIO_BUFFERS + /* Next check for available buffered... */ + if ((avail = stream->__bufread - stream->__bufpos) > 0) { + if (avail > todo) { + avail = todo; + } + memcpy(buffer, stream->__bufpos, avail); + buffer += avail; + stream->__bufpos += avail; + if (!(todo -= avail)) { + goto DONE; + } + } + + /* We need to read from the host environment, so we must + * flush all line buffered streams if the stream is not + * fully buffered. */ + if (!__STDIO_STREAM_IS_FBF(stream)) { + __STDIO_FLUSH_LBF_STREAMS; + } +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: should we refill and read from the buffer sometimes? +#endif + while ((avail = __stdio_READ(stream, buffer, todo)) > 0) { + buffer += avail; + if (!(todo -= avail)) { + break; + } + } + + DONE: + __STDIO_STREAM_VALIDATE(stream); + return (bytes - todo) / size; + } + + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EINVAL); + } + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} +libc_hidden_def(fread_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fread) +strong_alias(fread_unlocked,fread) +libc_hidden_def(fread) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fread) +size_t fread(void * __restrict ptr, size_t size, size_t nmemb, + register FILE * __restrict stream) +{ + size_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fread_unlocked(ptr, size, nmemb, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fread) + +#endif diff --git a/libc/stdio/fread_unlocked.c b/libc/stdio/fread_unlocked.c new file mode 100644 index 0000000..441edbb --- /dev/null +++ b/libc/stdio/fread_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fread.c" diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c new file mode 100644 index 0000000..942a679 --- /dev/null +++ b/libc/stdio/freopen.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fclose) + +#ifndef __DO_LARGEFILE +# define FILEDES_ARG (-1) +#endif + +FILE *freopen(const char * __restrict filename, const char * __restrict mode, + register FILE * __restrict stream) +{ + /* + * ANSI/ISO allow (implementation-defined) change of mode for an + * existing file if filename is NULL. It doesn't look like Linux + * supports this, so we don't here. + * + * NOTE: Whether or not the stream is free'd on failure is unclear + * w.r.t. ANSI/ISO. This implementation chooses to NOT free + * the stream and associated buffer if they were dynamically + * allocated. + * NOTE: Previous versions of uClibc did free dynamic storage. + * + * TODO: Apparently linux allows setting append mode. Implement? + */ + unsigned short dynmode; + register FILE *fp; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */ + + /* First, flush and close, but don't deallocate, the stream. */ + /* This also removes the stream for the open file list. */ + dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE)); + + stream->__modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE); + + /* Only call fclose on the stream if it is not already closed. */ + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + != (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + fclose(stream); /* Failures are ignored. */ + /* NOTE: fclose always does __STDIO_OPENLIST_INC_DEL_CNT. But we don't + * want to remove this FILE from the open list, even if the freopen fails. + * Consider the case of a failed freopen() on stdin. You probably still + * want to be able to call freopen() again. Similarly for other "malloc'd" + * streams. */ + __STDIO_OPENLIST_DEC_DEL_CNT; + } + + fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG); + if (!fp) { + /* Don't remove stream from the open file list and (potentially) free it. + * See _stdio_openlist_dec_use() in fflush.c. */ + stream->__modeflags = __FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN; + } + + /* Reset the allocation flags. */ + stream->__modeflags |= dynmode; + + __STDIO_OPENLIST_DEC_USE; + + __STDIO_AUTO_THREADUNLOCK(stream); + + return fp; +} diff --git a/libc/stdio/freopen64.c b/libc/stdio/freopen64.c new file mode 100644 index 0000000..e44c972 --- /dev/null +++ b/libc/stdio/freopen64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define freopen freopen64 +#define FILEDES_ARG (-2) +#include "freopen.c" diff --git a/libc/stdio/fscanf.c b/libc/stdio/fscanf.c new file mode 100644 index 0000000..102cb8d --- /dev/null +++ b/libc/stdio/fscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fscanf +#include "_scanf.c" diff --git a/libc/stdio/fseeko.c b/libc/stdio/fseeko.c new file mode 100644 index 0000000..2510402 --- /dev/null +++ b/libc/stdio/fseeko.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#if SEEK_SET != 0 || SEEK_CUR != 1 || SEEK_END != 2 +# error Assumption violated -- values of SEEK_SET, SEEK_CUR, SEEK_END +#endif + +#ifndef __DO_LARGEFILE +# define FSEEK fseek +# define OFFSET_TYPE long int +#endif + +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(fseeko64) +#endif +libc_hidden_proto(fseek) + +int FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence) +{ +#if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) + + return fseeko64(stream, offset, whence); + +#else + + __offmax_t pos = offset; + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + if (((unsigned int) whence) > 2) { + __set_errno(EINVAL); + } else { + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if ((!__STDIO_STREAM_IS_WRITING(stream) + || !__STDIO_COMMIT_WRITE_BUFFER(stream)) + && ((whence != SEEK_CUR) + || (__stdio_adjust_position(stream, &pos) >= 0)) + && (__SEEK(stream, &pos, whence) >= 0) + ) { + + /* Clear reading/writing modes, EOF, and ungots. */ + stream->__modeflags &= + ~(__MASK_READING|__FLAG_WRITING|__FLAG_EOF); + + /* Make sure all pointers are reset. */ + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + + /* We reinitialize the mbstate object. Doing so is + * implementation defined behavior. */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif + + retval = 0; + } + + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + } + + return retval; + +#endif +} + +#ifdef __DO_LARGEFILE +libc_hidden_def(fseeko64) +#else +libc_hidden_def(fseek) +strong_alias(fseek,fseeko) +#endif diff --git a/libc/stdio/fseeko64.c b/libc/stdio/fseeko64.c new file mode 100644 index 0000000..78cab1b --- /dev/null +++ b/libc/stdio/fseeko64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define FSEEK fseeko64 +#define OFFSET_TYPE __off64_t +#include "fseeko.c" diff --git a/libc/stdio/fsetpos.c b/libc/stdio/fsetpos.c new file mode 100644 index 0000000..d63adc0 --- /dev/null +++ b/libc/stdio/fsetpos.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +#define FSEEK fseek +#endif + +libc_hidden_proto(FSEEK) + +int fsetpos(FILE *stream, register const fpos_t *pos) +{ +#ifdef __STDIO_MBSTATE + + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if ((retval = FSEEK(stream, pos->__pos, SEEK_SET)) == 0) { + __COPY_MBSTATE(&(stream->__state), &(pos->__mbstate)); + stream->__ungot_width[0]= pos->__mblen_pending; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else + + return FSEEK(stream, pos->__pos, SEEK_SET); + +#endif +} diff --git a/libc/stdio/fsetpos64.c b/libc/stdio/fsetpos64.c new file mode 100644 index 0000000..82819a4 --- /dev/null +++ b/libc/stdio/fsetpos64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define fsetpos fsetpos64 +#define fpos_t fpos64_t +#define FSEEK fseeko64 +#include "fsetpos.c" diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c new file mode 100644 index 0000000..bae1d87 --- /dev/null +++ b/libc/stdio/ftello.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(ftello64) +#endif +libc_hidden_proto(ftell) + +#ifndef __DO_LARGEFILE +# define FTELL ftell +# define OFFSET_TYPE long int +#endif + +OFFSET_TYPE FTELL(register FILE *stream) +{ +#if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) + + __offmax_t pos = ftello64(stream); + + if ((sizeof(long) >= sizeof(__offmax_t)) || (((long) pos) == pos)) { + return ((long) pos); + } else { + __set_errno(EOVERFLOW); + return -1; + } + +#else + + __offmax_t pos = 0; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if ((__SEEK(stream, &pos, + ((__STDIO_STREAM_IS_WRITING(stream) + && (stream->__modeflags & __FLAG_APPEND)) + ? SEEK_END : SEEK_CUR)) < 0) + || (__stdio_adjust_position(stream, &pos) < 0)) { + pos = -1; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return pos; + +#endif +} + +#ifdef __DO_LARGEFILE +libc_hidden_def(ftello64) +#else +libc_hidden_def(ftell) +strong_alias(ftell,ftello) +#endif diff --git a/libc/stdio/ftello64.c b/libc/stdio/ftello64.c new file mode 100644 index 0000000..905834f --- /dev/null +++ b/libc/stdio/ftello64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define FTELL ftello64 +#define OFFSET_TYPE __off64_t +#include "ftello.c" diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c new file mode 100644 index 0000000..0d2e156 --- /dev/null +++ b/libc/stdio/ftrylockfile.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should this return when not threading? +#endif + +int ftrylockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); +} diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c new file mode 100644 index 0000000..2ddf097 --- /dev/null +++ b/libc/stdio/funlockfile.c @@ -0,0 +1,15 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +void funlockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); +} diff --git a/libc/stdio/fwide.c b/libc/stdio/fwide.c new file mode 100644 index 0000000..422d789 --- /dev/null +++ b/libc/stdio/fwide.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* TODO: According to SUSv3 should return EBADF if invalid stream. */ + +int fwide(register FILE *stream, int mode) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if (mode && !(stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW))) { + stream->__modeflags |= ((mode > 0) ? __FLAG_WIDE : __FLAG_NARROW); + } + + mode = (stream->__modeflags & __FLAG_WIDE) + - (stream->__modeflags & __FLAG_NARROW); + + assert((stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW)) + != (__FLAG_WIDE|__FLAG_NARROW)); + __STDIO_AUTO_THREADUNLOCK(stream); + + return mode; +} diff --git a/libc/stdio/fwprintf.c b/libc/stdio/fwprintf.c new file mode 100644 index 0000000..f2a1afb --- /dev/null +++ b/libc/stdio/fwprintf.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + +libc_hidden_proto(vfwprintf) + +int fwprintf(FILE * __restrict stream, const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwprintf(stream, format, arg); + va_end(arg); + + return rv; +} diff --git a/libc/stdio/fwrite.c b/libc/stdio/fwrite.c new file mode 100644 index 0000000..7be794a --- /dev/null +++ b/libc/stdio/fwrite.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fwrite_unlocked) + +#ifdef __DO_UNLOCKED + +size_t fwrite_unlocked(const void * __restrict ptr, size_t size, + size_t nmemb, register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* Note: If nmbem * size > SIZE_MAX then there is an application + * bug since no array can be larger than SIZE_MAX in size. */ + + if ((__STDIO_STREAM_IS_NARROW_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) + && size && nmemb + ) { + + if (nmemb <= (SIZE_MAX / size)) { + return __stdio_fwrite((const unsigned char *) ptr, + size*nmemb, stream) / size; + } + + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EINVAL); + } + + return 0; +} +libc_hidden_def(fwrite_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fwrite) +strong_alias(fwrite_unlocked,fwrite) +libc_hidden_def(fwrite) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fwrite) +size_t fwrite(const void * __restrict ptr, size_t size, + size_t nmemb, register FILE * __restrict stream) +{ + size_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fwrite_unlocked(ptr, size, nmemb, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fwrite) + +#endif diff --git a/libc/stdio/fwrite_unlocked.c b/libc/stdio/fwrite_unlocked.c new file mode 100644 index 0000000..0f9e026 --- /dev/null +++ b/libc/stdio/fwrite_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fwrite.c" diff --git a/libc/stdio/fwscanf.c b/libc/stdio/fwscanf.c new file mode 100644 index 0000000..3409d00 --- /dev/null +++ b/libc/stdio/fwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fwscanf +#include "_scanf.c" diff --git a/libc/stdio/getchar.c b/libc/stdio/getchar.c new file mode 100644 index 0000000..e29c426 --- /dev/null +++ b/libc/stdio/getchar.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(__fgetc_unlocked) + +#undef getchar +#ifdef __DO_UNLOCKED + +/* the only use of the hidden getchar_unlocked is in gets.c */ +#undef getchar_unlocked +libc_hidden_proto(getchar_unlocked) +int getchar_unlocked(void) +{ + register FILE *stream = stdin; + + return __GETC_UNLOCKED_MACRO(stream); +} +libc_hidden_def(getchar_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(getchar_unlocked,getchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int getchar(void) +{ + register FILE *stream = stdin; + + if (stream->__user_locking != 0) { + return __GETC_UNLOCKED_MACRO(stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __GETC_UNLOCKED_MACRO(stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} + +#endif diff --git a/libc/stdio/getchar_unlocked.c b/libc/stdio/getchar_unlocked.c new file mode 100644 index 0000000..60ea251 --- /dev/null +++ b/libc/stdio/getchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getchar.c" diff --git a/libc/stdio/getdelim.c b/libc/stdio/getdelim.c new file mode 100644 index 0000000..21c86f4 --- /dev/null +++ b/libc/stdio/getdelim.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +libc_hidden_proto(getdelim) + +libc_hidden_proto(__fgetc_unlocked) + +/* Note: There is a defect in this function. (size_t vs ssize_t). */ + +/* glibc function -- + * Return -1 if error or EOF prior to any chars read. + * Return number of chars read (including possible delimiter but not + * the terminating nul) otherwise. + * + * NOTE: If we need to allocate a buffer, we do so prior to attempting + * a reading. So space may be allocated even if initially at EOF. + */ + +#define GETDELIM_GROWBY 64 + +ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n, + int delimiter, register FILE *__restrict stream) +{ + register char *buf; + ssize_t pos = -1; + int c; + __STDIO_AUTO_THREADLOCK_VAR; + + if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */ + __set_errno(EINVAL); /* though I think we should assert here */ + } else { + __STDIO_AUTO_THREADLOCK(stream); + + if (!(buf = *lineptr)) { /* If passed NULL for buffer, */ + *n = 0; /* ignore value passed and treat size as 0. */ + } + + /* Within the loop, pos is actually the current buffer index + 2, + * because we want to make sure we have enough space to store + * an additional char plus a nul terminator. + */ + pos = 1; + + do { + if (pos >= *n) { + if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) { + pos = -1; + break; + } + *n += GETDELIM_GROWBY; + *lineptr = buf; + } + + if ((c = __GETC_UNLOCKED(stream)) != EOF) { + buf[++pos - 2] = c; + if (c != delimiter) { + continue; + } + } + + /* We're done, so correct pos back to being the current index. */ + if ((pos -= 2) >= 0) { + buf[++pos] = 0; + } + break; + + } while (1); + + __STDIO_AUTO_THREADUNLOCK(stream); + } + + return pos; +} +libc_hidden_def(getdelim) +#endif diff --git a/libc/stdio/getline.c b/libc/stdio/getline.c new file mode 100644 index 0000000..22b67b8 --- /dev/null +++ b/libc/stdio/getline.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +libc_hidden_proto(getline) + +libc_hidden_proto(getdelim) + +ssize_t getline(char **__restrict lineptr, size_t *__restrict n, + FILE *__restrict stream) +{ + return getdelim(lineptr, n, '\n', stream); +} +libc_hidden_def(getline) +#endif diff --git a/libc/stdio/gets.c b/libc/stdio/gets.c new file mode 100644 index 0000000..85bb847 --- /dev/null +++ b/libc/stdio/gets.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +link_warning(gets, "the 'gets' function is dangerous and should not be used.") + +/* UNSAFE FUNCTION -- do not bother optimizing */ + +/* disable macro, force actual function call */ +#undef getchar_unlocked +libc_hidden_proto(getchar_unlocked) + +char *gets(char *s) +{ + register char *p = s; + int c; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stdin); + + /* Note: don't worry about performance here... this shouldn't be used! + * Therefore, force actual function call. */ + while (((c = getchar_unlocked()) != EOF) && ((*p = c) != '\n')) { + ++p; + } + if ((c == EOF) || (s == p)) { + s = NULL; + } else { + *p = 0; + } + + __STDIO_AUTO_THREADUNLOCK(stdin); + + return s; +} diff --git a/libc/stdio/getw.c b/libc/stdio/getw.c new file mode 100644 index 0000000..e3aeda9 --- /dev/null +++ b/libc/stdio/getw.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fread_unlocked) + +/* SUSv2 Legacy function -- need not be reentrant. */ + +int getw(FILE *stream) +{ + int aw; + + return (fread_unlocked((void *) &aw, sizeof(int), 1, stream) != 0) + ? aw : EOF; +} diff --git a/libc/stdio/getwchar.c b/libc/stdio/getwchar.c new file mode 100644 index 0000000..9c480b5 --- /dev/null +++ b/libc/stdio/getwchar.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __DO_UNLOCKED + +libc_hidden_proto(fgetwc_unlocked) + +wint_t getwchar_unlocked(void) +{ + return fgetwc_unlocked(stdin); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(getwchar_unlocked,getwchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(fgetwc) + +wint_t getwchar(void) +{ + return fgetwc(stdin); +} + +#endif diff --git a/libc/stdio/getwchar_unlocked.c b/libc/stdio/getwchar_unlocked.c new file mode 100644 index 0000000..af4a9e8 --- /dev/null +++ b/libc/stdio/getwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getwchar.c" diff --git a/libc/stdio/old_vfprintf.c b/libc/stdio/old_vfprintf.c new file mode 100644 index 0000000..a7ec28d --- /dev/null +++ b/libc/stdio/old_vfprintf.c @@ -0,0 +1,717 @@ +/* + * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) + * + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + */ + +/* Altered to use stdarg, made the core function vfnprintf. + * Hooked into the stdio package using 'inside information' + * Altered sizeof() assumptions, now assumes all integers except chars + * will be either + * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) + * + * -RDB + */ + +/* + * Manuel Novoa III Dec 2000 + * + * The previous vfnprintf routine was almost completely rewritten with the + * goal of fixing some shortcomings and reducing object size. + * + * The summary of changes: + * + * Converted print conversion specification parsing from one big switch + * to a method using string tables. This new method verifies that the + * conversion flags, field width, precision, qualifier, and specifier + * appear in the correct order. Many questionable specifications were + * accepted by the previous code. This new method also resulted in a + * substantial reduction in object size of about 330 bytes (20%) from + * the old version (1627 bytes) on i386, even with the following + * improvements. + * + * Implemented %n specifier as required by the standards. + * Implemented proper handling of precision for int types. + * Implemented # for hex and pointer, fixed error for octal rep of 0. + * Implemented return of -1 on stream error. + * + * Added optional support for the GNU extension %m which prints the string + * corresponding the errno. + * + * Added optional support for long long ints and unsigned long long ints + * using the conversion qualifiers "ll", "L", or "q" (like glibc). + * + * Added optional support for doubles in a very limited form. None of + * the formating options are obeyed. The string returned by __dtostr + * is printed directly. + * + * Converted to use my (un)signed long (long) to string routines, which are + * smaller than the previous functions and don't require static buffers. + * + * Other Modifications: + * Modified sprintf, snprintf, vsprintf, vsnprintf to share on fake-file. + */ + +/* + * Manuel Novoa III Jan 2001 + * + * Removed fake file from *s*printf functions because of possible problems + * if called recursively. Instead, have sprintf, snprintf, and vsprintf + * call vsnprintf which allocates a fake file on the stack. + * Removed WANT_FPUTC option. Always use standard putc macro to avoid + * problems with the fake file used by the *s*printf functions. + * Fixed bug parsing flags -- did not restart scan. + * Added function asprintf. + * Fixed 0-pad prefixing bug. + * Converted sizeof(int) == sizeof(long) tests to compile time vs run time. + * This saves 112 bytes of code on i386. + * Fixed precision bug -- when negative set to default. + * Added function fnprintf to support __dtostr. + * Added floating point support for doubles. Yeah! + * + * + * May 2001 Fixes from Johan Adolfsson (johan.adolfsson@axis.com) + * 1) printf("%c",0) returned 0 instead of 1. + * 2) unrolled loop in asprintf to reduce size and remove compile warning. + * + * + * June 2001 + * 1) fix %p so that "0x" is prepended to outputed hex val + * 2) fix %p so that "(nil)" is output for (void *)0 to match glibc + * + * Sep 5, 2003 + * Convert to new floating point conversion routine. + * Fix qualifier handling on integer and %n conversions. + * Add support for vsnprintf when in non-buffered/no-wchar configuration. + * + */ + +/*****************************************************************************/ +/* OPTIONS */ +/*****************************************************************************/ +/* The optional support for long longs and doubles comes in two forms. + * + * 1) Normal (or partial for doubles) output support. Set to 1 to turn on. + * Adds about 130 bytes for doubles, about 220 bytes for long longs, + * and about 275 for both to the base code size of 1163 on i386. + */ + +/* These are now set in uClibc_config.h based on Config. */ +/* +#define __UCLIBC_HAS_FLOATS__ 1 +*/ + +/* 2) An error message is inserted into the stream, an arg of the + * appropriate size is removed from the arglist, and processing + * continues. This is adds less code and may be useful in some + * cases. Set to 1 to turn on. Adds about 50 bytes for doubles, + * about 140 bytes for long longs, and about 175 bytes for both + * to the base code size of 1163 on i386. + */ + +#define WANT_FLOAT_ERROR 0 + +/* + * Set to support GNU extension of %m to print string corresponding to errno. + * + * Warning: This adds about 50 bytes (i386) to the code but it also pulls in + * strerror and the corresponding string table which together are about 3.8k. + */ + +/* Now controlled by uClibc_stdio.h and set below. */ +/* #define WANT_GNU_ERRNO 0 */ + +/**************************************************************************/ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include "_stdio.h" +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif /* __UCLIBC_HAS_THREADS__ */ + +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strnlen) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(putc_unlocked) +libc_hidden_proto(__fputc_unlocked) +libc_hidden_proto(__glibc_strerror_r) + +/* #undef __UCLIBC_HAS_FLOATS__ */ +/* #undef WANT_FLOAT_ERROR */ +/* #define WANT_FLOAT_ERROR 1 */ + +/* #define __isdigit(c) (((unsigned int)(c - '0')) < 10) */ + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define WANT_GNU_ERRNO 1 +#else +#define WANT_GNU_ERRNO 0 +#endif + +#undef PUTC +#undef OUTNSTR +#undef _outnstr + +#ifdef __STDIO_BUFFERS + +#define PUTC(C,F) putc_unlocked((C),(F)) +#define OUTNSTR _outnstr +#define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) + +#else /* __STDIO_BUFFERS */ + +typedef struct { + FILE f; + unsigned char *bufend; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsnprintf; + +#ifdef __UCLIBC_HAS_FLOATS__ +static void _outnstr(FILE *stream, const unsigned char *s, size_t n) +{ + __FILE_vsnprintf *f = (__FILE_vsnprintf *) stream; + + if (!__STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(&f->f)) { + __stdio_fwrite(s, n, &f->f); + } else if (f->bufend > f->bufpos) { + size_t r = f->bufend - f->bufpos; + if (r > n) { + r = n; + } + memcpy(f->bufpos, s, r); + f->bufpos += r; + } +} +#endif + +static void putc_unlocked_sprintf(int c, __FILE_vsnprintf *f) +{ + if (!__STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(&f->f)) { + putc_unlocked(c, &f->f); + } else if (f->bufpos < f->bufend) { + *f->bufpos++ = c; + } +} + + +#define PUTC(C,F) putc_unlocked_sprintf((C),(__FILE_vsnprintf *)(F)) +#define OUTNSTR _outnstr + +#endif /* __STDIO_BUFFERS */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#include +#include + +typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + +extern size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; + +static void _charpad(FILE * __restrict stream, int padchar, size_t numpad) +{ + /* TODO -- Use a buffer to cut down on function calls... */ + char pad[1]; + + *pad = padchar; + while (numpad) { + OUTNSTR(stream, pad, 1); + --numpad; + } +} + +static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + if (type & 0x80) { /* Some type of padding needed. */ + int buflen = strlen((const char *) buf); + if ((len -= buflen) > 0) { + _charpad(fp, (type & 0x7f), len); + } + len = buflen; + } + if (len) { + OUTNSTR(fp, (const char *) buf, len); + } +} + +#endif + + +enum { + FLAG_PLUS = 0, + FLAG_MINUS_LJUSTIFY, + FLAG_HASH, + FLAG_0_PAD, + FLAG_SPACE, +}; + +/* layout 01234 */ +static const char spec[] = "+-#0 "; + +/**********************************************************************/ + +extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; +extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; + +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS intmax_t entry 'j'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ + /* q:long_long Z:(s)size_t */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ + 1, 8 \ +} + +static const char qual_chars[] = QUAL_CHARS; + +/* static const char qual[] = "hlLq"; */ +/**********************************************************************/ + +#if !defined(__UCLIBC_HAS_FLOATS__) && WANT_FLOAT_ERROR +static const char dbl_err[] = ""; +#endif + +#if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR +/* layout 012345678901234567 */ +static const char u_spec[] = "%nbopxXudicsfgGeEaA"; +#else +/* layout 0123456789012 */ +static const char u_spec[] = "%nbopxXudics"; +#endif + +/* WARNING: u_spec and u_radix need to stay in agreement!!! */ +/* u_radix[i] <-> u_spec[i+2] for unsigned entries only */ +static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a"; + +libc_hidden_proto(vfprintf) +int vfprintf(FILE * __restrict op, register const char * __restrict fmt, + va_list ap) +{ + union { +#ifdef LLONG_MAX + long long ll; +#endif +#if LONG_MAX != INT_MAX + long l; +#endif + int i; + } intarg; + int i, cnt, dataargtype, len; + const void *argptr = argptr; /* ok to be initialized. */ + register char *p; + const char *fmt0; + int preci, width; +#define upcase i + int radix, dpoint /*, upcase*/; + char tmp[65]; /* TODO - determine needed size from headers */ + char flag[sizeof(spec)]; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(op); + + __STDIO_STREAM_VALIDATE(op); + + cnt = 0; + + if (__STDIO_STREAM_IS_NARROW_WRITING(op) + || !__STDIO_STREAM_TRANS_TO_WRITE(op, __FLAG_NARROW) + ) { + + while (*fmt) { + if (*fmt == '%') { + fmt0 = fmt; /* save our position in case of bad format */ + ++fmt; + width = -1; /* min field width */ + preci = -5; /* max string width or mininum digits */ + radix = 10; /* number base */ + dpoint = 0; /* found decimal point */ + + /* init flags */ + for (p =(char *) spec ; *p ; p++) { + flag[p-spec] = '\0'; + } + flag[FLAG_0_PAD] = ' '; + + /* process optional flags */ + for (p = (char *)spec ; *p ; ) { + if (*fmt == *p) { + flag[p-spec] = *fmt++; + p = (char *)spec; /* restart scan */ + } else { + p++; + } + } + + if (!flag[FLAG_PLUS]) { + flag[FLAG_PLUS] = flag[FLAG_SPACE]; + } + + /* process optional width and precision */ + do { + if (*fmt == '.') { + ++fmt; + dpoint = 1; + } + if (*fmt == '*') { /* parameter width value */ + ++fmt; + i = va_arg(ap, int); + } else { + for ( i = 0 ; (*fmt >= '0') && (*fmt <= '9') ; ++fmt ) { + i = (i * 10) + (*fmt - '0'); + } + } + + if (dpoint) { + preci = i; + if (i<0) { + preci = -5; + } + } else { + width = i; + if (i<0) { + width = -i; + flag[FLAG_MINUS_LJUSTIFY] = 1; + } + } + } while ((*fmt == '.') && !dpoint ); + + /* process optional qualifier */ + p = (char *) qual_chars; + do { + if (*fmt == *p) { + ++fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++fmt; + } + dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + +#if WANT_GNU_ERRNO + if (*fmt == 'm') { + flag[FLAG_PLUS] = '\0'; + flag[FLAG_0_PAD] = ' '; + p = __glibc_strerror_r(errno, tmp, sizeof(tmp)); + goto print; + } +#endif + + /* process format specifier */ + for (p = (char *) u_spec ; *p ; p++) { + if (*fmt != *p) continue; + if (p-u_spec < 1) { /* print a % */ + goto charout; + } + if (p-u_spec < 2) { /* store output count in int ptr */ + _store_inttype(va_arg(ap, void *), + dataargtype, + (intmax_t) (cnt)); + goto nextfmt; + } + + if (p-u_spec < 10) { + if (*p == 'p') { +#if INTPTR_MAX == INT_MAX + dataargtype = 0; +#else +#error Fix dataargtype for pointers! +#endif + } + + switch(dataargtype) { + case (PA_INT|PA_FLAG_LONG_LONG): +#ifdef LLONG_MAX + intarg.ll = va_arg(ap, long long); + argptr = &intarg.ll; + break; +#endif + case (PA_INT|PA_FLAG_LONG): +#if LONG_MAX != INT_MAX + intarg.l = va_arg(ap, long); + argptr = &intarg.l; + break; +#endif + default: + intarg.i = va_arg(ap, int); + argptr = &intarg.i; + break; + } + } + + if (p-u_spec < 8) { /* unsigned conversion */ + radix = u_radix[p-u_spec-2]; + upcase = ((*p == 'x') ? __UIM_LOWER : __UIM_UPPER); + if (*p == 'p') { + upcase = __UIM_LOWER; + flag[FLAG_HASH] = 'p'; + } + p = _uintmaxtostr(tmp + sizeof(tmp) - 1, + (uintmax_t) + _load_inttype(dataargtype, argptr, radix), + radix, upcase); + + flag[FLAG_PLUS] = '\0'; /* meaningless for unsigned */ + if (*p != '0') { /* non-zero */ + if (flag[FLAG_HASH]) { + if (radix == 8) { + *--p = '0'; /* add leadding zero */ + } else if (radix != 10) { /* either 2 or 16 */ + flag[FLAG_PLUS] = '0'; + *--p = 'b'; + if (radix == 16) { + *p = 'x'; + if (*fmt == 'X') { + *p = 'X'; + } + } + } + } + } else if (flag[FLAG_HASH] == 'p') { /* null pointer */ + p = "(nil)"; + } + } else if (p-u_spec < 10) { /* signed conversion */ + p = _uintmaxtostr(tmp + sizeof(tmp) - 1, + (uintmax_t) + _load_inttype(dataargtype, argptr, -radix), + -radix, upcase); + + } else if (p-u_spec < 12) { /* character or string */ + flag[FLAG_PLUS] = '\0'; + flag[FLAG_0_PAD] = ' '; + if (*p == 'c') { /* character */ + p = tmp; + *p = va_arg(ap, int); + /* This takes care of the "%c",0 case */ + len = 1; + goto print_len_set; + } else { /* string */ + p = va_arg(ap, char *); + if (!p) { + p = "(null)"; + preci = 6; + } else { + if (preci < 0) { + preci = INT_MAX; + } + } + len = strnlen(p, preci); + goto print_len_set; + } +#if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR + } else if (p-u_spec < 27) { /* floating point */ +#endif /* defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR */ +#if defined(__UCLIBC_HAS_FLOATS__) + struct printf_info info; + if (preci < 0) { + preci = 6; + } + info.width = width; + info.prec = preci; + info.spec = *fmt; + info.pad = flag[FLAG_0_PAD]; + info._flags = 0; + if (flag[FLAG_PLUS] == '+') { + PRINT_INFO_SET_FLAG(&info,showsign); + } else if (flag[FLAG_PLUS] == ' ') { + PRINT_INFO_SET_FLAG(&info,space); + } + if (flag[FLAG_HASH]) { + PRINT_INFO_SET_FLAG(&info,alt); + } + if (flag[FLAG_MINUS_LJUSTIFY]) { + PRINT_INFO_SET_FLAG(&info,left); + } +#if 1 + cnt += _fpmaxtostr(op, + (__fpmax_t) + ((dataargtype == (8 << 8)) + ? va_arg(ap, long double) + : (long double) va_arg(ap, double)), + &info, _fp_out_narrow); +#else + cnt += _fpmaxtostr(op, + (__fpmax_t) + ((lval > 1) + ? va_arg(ap, long double) + : (long double) va_arg(ap, double)), + &info, _fp_out_narrow); +#endif + goto nextfmt; +#elif WANT_FLOAT_ERROR + (void) ((lval > 1) ? va_arg(ap, long double) + : va_arg(ap, double)); /* carry on */ + p = (char *) dbl_err; +#endif /* defined(__UCLIBC_HAS_FLOATS__) */ + } + +#if WANT_GNU_ERRNO + print: +#endif + { /* this used to be printfield */ + /* cheaper than strlen call */ +/* for ( len = 0 ; p[len] ; len++ ) { } */ + len = strnlen(p, SIZE_MAX); + print_len_set: + if ((*p == '-') +#if WANT_GNU_ERRNO + && (*fmt != 'm') +#endif + && (*fmt != 's')) { + flag[FLAG_PLUS] = *p++; + --len; + } + if (flag[FLAG_PLUS]) { + ++len; + ++preci; + if (flag[FLAG_PLUS] == '0') { /* base 16 */ + ++preci; /* account for x or X */ + } + } + + if (preci >= 0) { + if ((*fmt == 's') +#if WANT_GNU_ERRNO + || (*fmt == 'm') +#endif + ) { + if (len > preci) { + len = preci; + } else { + preci = len; + } + } + preci -= len; + if (preci < 0) { + preci = 0; + } + width -= preci; + } + + width -= len; + if (width < 0) { + width = 0; + } + + if (preci < 0) { + preci = 0; + if (!flag[FLAG_MINUS_LJUSTIFY] + /* && flag[FLAG_PLUS] */ + && (flag[FLAG_0_PAD] == '0')) { + preci = width; + width = 0; + } + } + + while (width + len + preci) { + unsigned char ch; + /* right padding || left padding */ + if ((!len && !preci) + || (width && !flag[FLAG_MINUS_LJUSTIFY])) { + ch = ' '; + --width; + } else if (flag[FLAG_PLUS]) { + ch = flag[FLAG_PLUS]; /* sign */ + if (flag[FLAG_PLUS]=='0') { /* base 16 case */ + flag[FLAG_PLUS] = *p++; /* get the x|X */ + } else { + flag[FLAG_PLUS] = '\0'; + } + --len; + } else if (preci) { + ch = '0'; + --preci; + } else { + ch = *p++; /* main field */ + --len; + } + ++cnt; + PUTC(ch, op); + } + } + goto nextfmt; + } + + fmt = fmt0; /* this was an illegal format */ + } + + charout: + ++cnt; + PUTC(*fmt, op); /* normal char out */ + + nextfmt: + ++fmt; + } + + } + + i = (__FERROR_UNLOCKED(op)) ? -1 : cnt; + + __STDIO_STREAM_VALIDATE(op); + + __STDIO_AUTO_THREADUNLOCK(op); + + return i; +} +libc_hidden_def(vfprintf) diff --git a/libc/stdio/open_memstream.c b/libc/stdio/open_memstream.c new file mode 100644 index 0000000..5861017 --- /dev/null +++ b/libc/stdio/open_memstream.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(fopencookie) + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +#define COOKIE ((__oms_cookie *) cookie) + +typedef struct { + char *buf; + size_t len; + size_t pos; + size_t eof; + char **bufloc; + size_t *sizeloc; +} __oms_cookie; + +/* Nothing to do here, as memstreams are write-only. */ +/* static ssize_t oms_read(void *cookie, char *buf, size_t bufsize) */ +/* { */ +/* } */ + +static ssize_t oms_write(register void *cookie, const char *buf, size_t bufsize) +{ + register char *newbuf; + size_t count; + + /* Note: we already know bufsize < SSIZE_MAX... */ + + count = COOKIE->len - COOKIE->pos - 1; + assert(COOKIE->pos < COOKIE->len); /* Always nul-terminate! */ + + if (bufsize > count) { + newbuf = realloc(COOKIE->buf, COOKIE->len + bufsize - count); + if (newbuf) { + *COOKIE->bufloc = COOKIE->buf = newbuf; + COOKIE->len += (bufsize - count); + } else { + bufsize = count; + if (count == 0) { + __set_errno(EFBIG); /* TODO: check glibc errno setting... */ + return -1; + } + } + } + + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + COOKIE->pos += bufsize; + + if (COOKIE->pos > COOKIE->eof) { + *COOKIE->sizeloc = COOKIE->eof = COOKIE->pos; + COOKIE->buf[COOKIE->eof] = 0; /* Need to nul-terminate. */ + } + + return bufsize; +} + +static int oms_seek(register void *cookie, __offmax_t *pos, int whence) +{ + __offmax_t p = *pos; + register char *buf; + size_t leastlen; + + /* Note: fseek already checks that whence is legal, so don't check here + * unless debugging. */ + assert(((unsigned int) whence) <= 2); + + if (whence != SEEK_SET) { + p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof; + } + + /* Note: glibc only allows seeking in the buffer. We'll actually restrict + * to the data. */ + /* Check for offset < 0, offset >= too big (need nul), or overflow... */ + if (((uintmax_t) p) >= SIZE_MAX - 1) { + return -1; + } + + leastlen = ((size_t) p) + 1; /* New pos + 1 for nul if necessary. */ + + if (leastlen >= COOKIE->len) { /* Need to grow buffer... */ + buf = realloc(COOKIE->buf, leastlen); + if (buf) { + *COOKIE->bufloc = COOKIE->buf = buf; + COOKIE->len = leastlen; + memset(buf + COOKIE->eof, 0, leastlen - COOKIE->eof); /* 0-fill */ + } else { + /* TODO: check glibc errno setting... */ + return -1; + } + } + + *pos = COOKIE->pos = --leastlen; + + if (leastlen > COOKIE->eof) { + memset(COOKIE->buf + COOKIE->eof, 0, leastlen - COOKIE->eof); + *COOKIE->sizeloc = COOKIE->eof; + } + + return 0; +} + +static int oms_close(void *cookie) +{ + free(cookie); + return 0; +} + +#undef COOKIE + +static const cookie_io_functions_t _oms_io_funcs = { + NULL, oms_write, oms_seek, oms_close +}; + +/* TODO: If we have buffers enabled, it might be worthwile to add a pointer + * to the FILE in the cookie and operate directly on the buffer itself + * (ie replace the FILE buffer with the cookie buffer and update FILE bufstart, + * etc. whenever we seek). */ + +libc_hidden_proto(open_memstream) +FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc) +{ + register __oms_cookie *cookie; + register FILE *fp; + + if ((cookie = malloc(sizeof(__oms_cookie))) != NULL) { + if ((cookie->buf = malloc(cookie->len = BUFSIZ)) == NULL) { + goto EXIT_cookie; + } + *cookie->buf = 0; /* Set nul terminator for buffer. */ + *(cookie->bufloc = bufloc) = cookie->buf; + *(cookie->sizeloc = sizeloc) = cookie->eof = cookie->pos = 0; + +#ifndef __BCC__ + fp = fopencookie(cookie, "w", _oms_io_funcs); +#else + fp = fopencookie(cookie, "w", &_oms_io_funcs); +#endif + /* Note: We don't need to worry about locking fp in the thread case + * as the only possible access would be a close or flush with + * nothing currently in the FILE's write buffer. */ + + if (fp != NULL) { + __STDIO_STREAM_VALIDATE(fp); + return fp; + } + } + + free(cookie->buf); + EXIT_cookie: + free(cookie); + + return NULL; +} +libc_hidden_def(open_memstream) +#endif diff --git a/libc/stdio/parse_printf_format.c b/libc/stdio/parse_printf_format.c new file mode 100644 index 0000000..38266b3 --- /dev/null +++ b/libc/stdio/parse_printf_format.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_parse_printf_format +#include "_vfprintf.c" diff --git a/libc/stdio/perror.c b/libc/stdio/perror.c new file mode 100644 index 0000000..993fcf4 --- /dev/null +++ b/libc/stdio/perror.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fprintf) +libc_hidden_proto(__glibc_strerror_r) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Increase buffer size for error message (non-%m case)? +#endif + +libc_hidden_proto(perror) +void perror(register const char *s) +{ + /* If the program is calling perror, it's a safe bet that printf and + * friends are used as well. It is also possible that the calling + * program could buffer stderr, or reassign it. */ + + register const char *sep; + + sep = ": "; + if (!(s && *s)) { /* Caller did not supply a prefix message */ + s = (sep += 2); /* or passed an empty string. */ + } + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + fprintf(stderr, "%s%s%m\n", s, sep); /* Use the gnu %m feature. */ +#else + { + char buf[64]; + fprintf(stderr, "%s%s%s\n", s, sep, + __glibc_strerror_r(errno, buf, sizeof(buf))); + } +#endif +} +libc_hidden_def(perror) diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c new file mode 100644 index 0000000..43d07fa --- /dev/null +++ b/libc/stdio/popen.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +/* Jan 1, 2004 + * + * Rewrite popen for SUSv3 compliance. + * Added a list of popen()'d to store pids and use waitpid() in pclose(). + * Loop on waitpid() failure due to EINTR as required. + * Close parent's popen()'d FILEs in the {v}fork()'d child. + * Fix failure exit code for failed execve(). + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "hmm... susv3 says Pipe streams are byte-oriented." +#endif /* __UCLIBC_MJN3_ONLY__ */ + +libc_hidden_proto(close) +libc_hidden_proto(_exit) +libc_hidden_proto(waitpid) +libc_hidden_proto(execl) +libc_hidden_proto(dup2) +libc_hidden_proto(fdopen) +libc_hidden_proto(pipe) +libc_hidden_proto(vfork) +libc_hidden_proto(fclose) + +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#if ! defined __NR_vfork +# define vfork fork +# define VFORK_LOCK ((void) 0) +# define VFORK_UNLOCK ((void) 0) +libc_hidden_proto(fork) +#endif + +#ifndef VFORK_LOCK +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); +# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock) +# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock) +#endif + +struct popen_list_item { + struct popen_list_item *next; + FILE *f; + pid_t pid; +}; + +static struct popen_list_item *popen_list /* = NULL (bss initialized) */; + +FILE *popen(const char *command, const char *modes) +{ + FILE *fp; + struct popen_list_item *pi; + struct popen_list_item *po; + int pipe_fd[2]; + int parent_fd; + int child_fd; + int child_writing; /* Doubles as the desired child fildes. */ + pid_t pid; + + child_writing = 0; /* Assume child is writing. */ + if (modes[0] != 'w') { /* Parent not writing... */ + ++child_writing; /* so child must be writing. */ + if (modes[0] != 'r') { /* Oops! Parent not reading either! */ + __set_errno(EINVAL); + goto RET_NULL; + } + } + + if (!(pi = malloc(sizeof(struct popen_list_item)))) { + goto RET_NULL; + } + + if (pipe(pipe_fd)) { + goto FREE_PI; + } + + child_fd = pipe_fd[child_writing]; + parent_fd = pipe_fd[1-child_writing]; + + if (!(fp = fdopen(parent_fd, modes))) { + close(parent_fd); + close(child_fd); + goto FREE_PI; + } + + VFORK_LOCK; + if ((pid = vfork()) == 0) { /* Child of vfork... */ + close(parent_fd); + if (child_fd != child_writing) { + dup2(child_fd, child_writing); + close(child_fd); + } + + /* SUSv3 requires that any previously popen()'d streams in the + * parent shall be closed in the child. */ + for (po = popen_list ; po ; po = po->next) { + close(po->f->__filedes); + } + + execl("/bin/sh", "sh", "-c", command, (char *)0); + + /* SUSv3 mandates an exit code of 127 for the child if the + * command interpreter can not be invoked. */ + _exit(127); + } + VFORK_UNLOCK; + + /* We need to close the child filedes whether vfork failed or + * it succeeded and we're in the parent. */ + close(child_fd); + + if (pid > 0) { /* Parent of vfork... */ + pi->pid = pid; + pi->f = fp; + VFORK_LOCK; + pi->next = popen_list; + popen_list = pi; + VFORK_UNLOCK; + + return fp; + } + + /* If we get here, vfork failed. */ + fclose(fp); /* Will close parent_fd. */ + + FREE_PI: + free(pi); + + RET_NULL: + return NULL; +} + +#warning is pclose correct wrt the new mutex semantics? + +int pclose(FILE *stream) +{ + struct popen_list_item *p; + int stat; + pid_t pid; + + /* First, find the list entry corresponding to stream and remove it + * from the list. Set p to the list item (NULL if not found). */ + VFORK_LOCK; + if ((p = popen_list) != NULL) { + if (p->f == stream) { + popen_list = p->next; + } else { + struct popen_list_item *t; + do { + t = p; + if (!(p = t->next)) { + __set_errno(EINVAL); /* Not required by SUSv3. */ + break; + } + if (p->f == stream) { + t->next = p->next; + break; + } + } while (1); + } + } + VFORK_UNLOCK; + + if (p) { + pid = p->pid; /* Save the pid we need */ + free(p); /* and free the list item. */ + + fclose(stream); /* The SUSv3 example code ignores the return. */ + + /* SUSv3 specificly requires that pclose not return before the child + * terminates, in order to disallow pclose from returning on EINTR. */ + do { + if (waitpid(pid, &stat, 0) >= 0) { + return stat; + } + if (errno != EINTR) { + break; + } + } while (1); + } + + return -1; +} diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c new file mode 100644 index 0000000..617561f --- /dev/null +++ b/libc/stdio/printf.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(vfprintf) + +libc_hidden_proto(printf) +int printf(const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfprintf(stdout, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(printf) diff --git a/libc/stdio/putchar.c b/libc/stdio/putchar.c new file mode 100644 index 0000000..b54a7a8 --- /dev/null +++ b/libc/stdio/putchar.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(__fputc_unlocked) + +#undef putchar +#ifdef __DO_UNLOCKED + +#undef putchar_unlocked +int putchar_unlocked(int c) +{ + register FILE *stream = stdout; + + return __PUTC_UNLOCKED_MACRO(c, stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(putchar_unlocked,putchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int putchar(int c) +{ + register FILE *stream = stdout; + + if (stream->__user_locking != 0) { + return __PUTC_UNLOCKED_MACRO(c, stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __PUTC_UNLOCKED_MACRO(c, stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} + +#endif diff --git a/libc/stdio/putchar_unlocked.c b/libc/stdio/putchar_unlocked.c new file mode 100644 index 0000000..6d6ec47 --- /dev/null +++ b/libc/stdio/putchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putchar.c" diff --git a/libc/stdio/puts.c b/libc/stdio/puts.c new file mode 100644 index 0000000..08525b2 --- /dev/null +++ b/libc/stdio/puts.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(__fputc_unlocked) +libc_hidden_proto(fputs_unlocked) + +int puts(register const char * __restrict s) +{ + register FILE *stream = stdout; /* This helps bcc optimize. */ + int n; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + /* Note: Don't try to optimize by switching to FBF until the newline. + * If the string itself contained a newline a write error occurred, + * then we could have a newline in the buffer of an LBF stream. */ + + /* Note: Nonportable as fputs need only return nonnegative on success. */ + if ((n = fputs_unlocked(s, stream)) != EOF) { + ++n; + if (__fputc_unlocked('\n', stream) == EOF) { + n = EOF; + } + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return n; +} diff --git a/libc/stdio/putw.c b/libc/stdio/putw.c new file mode 100644 index 0000000..469e44a --- /dev/null +++ b/libc/stdio/putw.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fwrite_unlocked) + +/* SUSv2 Legacy function -- need not be reentrant. */ + +int putw(int w, FILE *stream) +{ +#define PW &w + /* If w is passed in a register, enable the following. */ +#if 0 +#undef PW + int PW[1]; + PW[0] = w; +#endif + +#if EOF == -1 + return fwrite_unlocked((void *) PW, sizeof(int), 1, stream) - 1; +#else + return (fwrite_unlocked((void *) PW, sizeof(int), 1, stream) != 0) + ? 0 : EOF; +#endif +} diff --git a/libc/stdio/putwchar.c b/libc/stdio/putwchar.c new file mode 100644 index 0000000..7a6501c --- /dev/null +++ b/libc/stdio/putwchar.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __DO_UNLOCKED + +libc_hidden_proto(fputwc_unlocked) + +wint_t putwchar_unlocked(wchar_t wc) +{ + return fputwc_unlocked(wc, stdout); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(putwchar_unlocked,putwchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +libc_hidden_proto(__fputc_unlocked) +/* psm: should this be fputwc? */ +libc_hidden_proto(fputc) + +wint_t putwchar(wchar_t wc) +{ + return fputc(wc, stdout); +} + +#endif diff --git a/libc/stdio/putwchar_unlocked.c b/libc/stdio/putwchar_unlocked.c new file mode 100644 index 0000000..5b0c600 --- /dev/null +++ b/libc/stdio/putwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putwchar.c" diff --git a/libc/stdio/register_printf_function.c b/libc/stdio/register_printf_function.c new file mode 100644 index 0000000..c6b3240 --- /dev/null +++ b/libc/stdio/register_printf_function.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_register_printf_function +#include "_vfprintf.c" diff --git a/libc/stdio/remove.c b/libc/stdio/remove.c new file mode 100644 index 0000000..f322411 --- /dev/null +++ b/libc/stdio/remove.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#include +#include + +libc_hidden_proto(rmdir) +libc_hidden_proto(unlink) + +/* SUSv3 states: + * If path does not name a directory, remove(path) shall be equivalent + * to unlink(path). If path names a directory, remove(path) shall be + * equivalent to rmdir(path). + */ + +libc_hidden_proto(remove) +int remove(register const char *filename) +{ + int saved_errno = errno; + int rv; + + if (((rv = rmdir(filename)) < 0) && (errno == ENOTDIR)) { + __set_errno(saved_errno); /* Need to restore errno. */ + rv = unlink(filename); + } + return rv; +} +libc_hidden_def(remove) diff --git a/libc/stdio/rewind.c b/libc/stdio/rewind.c new file mode 100644 index 0000000..e04d7a0 --- /dev/null +++ b/libc/stdio/rewind.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(fseek) + +libc_hidden_proto(rewind) +void rewind(register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_CLEAR_ERROR(stream); /* Clear the error indicator */ + fseek(stream, 0L, SEEK_SET); /* first since fseek could set it. */ + + __STDIO_AUTO_THREADUNLOCK(stream); +} +libc_hidden_def(rewind) diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c new file mode 100644 index 0000000..4943c88 --- /dev/null +++ b/libc/stdio/scanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_scanf +#include "_scanf.c" diff --git a/libc/stdio/setbuf.c b/libc/stdio/setbuf.c new file mode 100644 index 0000000..6de2c91 --- /dev/null +++ b/libc/stdio/setbuf.c @@ -0,0 +1,17 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +libc_hidden_proto(setvbuf) + +void setbuf(FILE * __restrict stream, register char * __restrict buf) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, buf, ((buf != NULL) ? _IOFBF : _IONBF), BUFSIZ); +#endif +} diff --git a/libc/stdio/setbuffer.c b/libc/stdio/setbuffer.c new file mode 100644 index 0000000..ea2421a --- /dev/null +++ b/libc/stdio/setbuffer.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __USE_BSD + +libc_hidden_proto(setvbuf) + +/* A BSD function. The implementation matches the linux man page, + * except that we do not bother calling setvbuf if not configured + * for stream buffering. + */ + +void setbuffer(FILE * __restrict stream, register char * __restrict buf, + size_t size) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), size); +#endif +} +#endif diff --git a/libc/stdio/setlinebuf.c b/libc/stdio/setlinebuf.c new file mode 100644 index 0000000..9b4be53 --- /dev/null +++ b/libc/stdio/setlinebuf.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __USE_BSD + +libc_hidden_proto(setvbuf) + +/* A BSD function. The implementation matches the linux man page, + * except that we do not bother calling setvbuf if not configured + * for stream buffering. + */ + +void setlinebuf(FILE * __restrict stream) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, NULL, _IOLBF, (size_t) 0); +#endif +} +#endif diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c new file mode 100644 index 0000000..6dbb532 --- /dev/null +++ b/libc/stdio/setvbuf.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#if (_IOFBF != 0) || (_IOLBF != 1) || (_IONBF != 2) +#error Assumption violated -- values of _IOFBF, _IOLBF, _IONBF +#endif +#if (__FLAG_FBF != 0) || (__FLAG_NBF != (2*__FLAG_LBF)) +#error Assumption violated for buffering mode flags +#endif + +libc_hidden_proto(setvbuf) +int setvbuf(register FILE * __restrict stream, register char * __restrict buf, + int mode, size_t size) +{ +#ifdef __STDIO_BUFFERS + + int retval = EOF; + int alloc_flag = 0; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); + + if (((unsigned int) mode) > 2) { + __set_errno(EINVAL); + goto ERROR; + } + + /* C99 states that setvbuf may only be used between a successful + * open of the stream and before any other operation other than + * an unsuccessful call to setvbuf. */ + +#ifdef __STDIO_FLEXIBLE_SETVBUF + /* If we aren't currently reading (including ungots) or writing, + * then allow the request to proceed. */ + + if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) { + goto ERROR; + } +#else + /* The following test isn't quite as strict as C99, as it will + * not detect file positioning operations. */ + + if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING + |__FLAG_NARROW|__FLAG_WIDE + |__FLAG_ERROR|__FLAG_EOF) + ) { + goto ERROR; + } +#endif + + stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */ + stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */ + + if ((mode == _IONBF) || !size) { + size = 0; + buf = NULL; + } else if (!buf) { + if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */ + || !(buf = malloc(size)) /* malloc failed, so don't change. */ + ) { + goto DONE; + } + alloc_flag = __FLAG_FREEBUF; + } + + if (stream->__modeflags & __FLAG_FREEBUF) { + stream->__modeflags &= ~(__FLAG_FREEBUF); + free(stream->__bufstart); + } + + stream->__modeflags |= alloc_flag; + stream->__bufstart = (unsigned char *) buf; + stream->__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + + DONE: + retval = 0; + + ERROR: + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else /* __STDIO_BUFFERS */ + + if (mode == _IONBF) { + return 0; + } + + if (((unsigned int) mode) > 2) { + __set_errno(EINVAL); + } + + return EOF; + +#endif +} +libc_hidden_def(setvbuf) diff --git a/libc/stdio/snprintf.c b/libc/stdio/snprintf.c new file mode 100644 index 0000000..ef9c692 --- /dev/null +++ b/libc/stdio/snprintf.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping snprintf since no vsnprintf! +#else + +libc_hidden_proto(vsnprintf) + +libc_hidden_proto(snprintf) +int snprintf(char *__restrict buf, size_t size, + const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsnprintf(buf, size, format, arg); + va_end(arg); + return rv; +} +libc_hidden_def(snprintf) + +#endif diff --git a/libc/stdio/sprintf.c b/libc/stdio/sprintf.c new file mode 100644 index 0000000..3602453 --- /dev/null +++ b/libc/stdio/sprintf.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping sprintf since no vsnprintf! +#else + +libc_hidden_proto(vsnprintf) + +libc_hidden_proto(sprintf) +int sprintf(char *__restrict buf, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsnprintf(buf, SIZE_MAX, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(sprintf) + +#endif diff --git a/libc/stdio/sscanf.c b/libc/stdio/sscanf.c new file mode 100644 index 0000000..f53c065 --- /dev/null +++ b/libc/stdio/sscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_sscanf +#include "_scanf.c" diff --git a/libc/stdio/swprintf.c b/libc/stdio/swprintf.c new file mode 100644 index 0000000..0c209fe --- /dev/null +++ b/libc/stdio/swprintf.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + +libc_hidden_proto(vswprintf) + +#ifndef __STDIO_BUFFERS +#warning Skipping swprintf since no buffering! +#else /* __STDIO_BUFFERS */ + +int swprintf(wchar_t *__restrict buf, size_t size, + const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vswprintf(buf, size, format, arg); + va_end(arg); + + return rv; +} + +#endif /* __STDIO_BUFFERS */ diff --git a/libc/stdio/swscanf.c b/libc/stdio/swscanf.c new file mode 100644 index 0000000..06f8cb7 --- /dev/null +++ b/libc/stdio/swscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_swscanf +#include "_scanf.c" diff --git a/libc/stdio/tempnam.c b/libc/stdio/tempnam.c new file mode 100644 index 0000000..3673f4b --- /dev/null +++ b/libc/stdio/tempnam.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Experimentally off - libc_hidden_proto(strdup) */ + +/* Generate a unique temporary filename using up to five characters of PFX + if it is not NULL. The directory to put this file in is searched for + as follows: First the environment variable "TMPDIR" is checked. + If it contains the name of a writable directory, that directory is used. + If not and if DIR is not NULL, that value is checked. If that fails, + P_tmpdir is tried and finally "/tmp". The storage for the filename + is allocated by `malloc'. */ +char * +tempnam (const char *dir, const char *pfx) +{ + char buf[FILENAME_MAX]; + + if (__path_search (buf, FILENAME_MAX, dir, pfx, 1)) + return NULL; + + if (__gen_tempname (buf, __GT_NOCREATE)) + return NULL; + + return strdup (buf); +} + diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c new file mode 100644 index 0000000..f839445 --- /dev/null +++ b/libc/stdio/tmpfile.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "../misc/internals/tempname.h" + +libc_hidden_proto(fdopen) +libc_hidden_proto(remove) +libc_hidden_proto(close) + +/* This returns a new stream opened on a temporary file (generated + by tmpnam). The file is opened with mode "w+b" (binary read/write). + If we couldn't generate a unique filename or the file couldn't + be opened, NULL is returned. */ +FILE * tmpfile (void) +{ + char buf[FILENAME_MAX]; + int fd; + FILE *f; + + if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0)) + return NULL; + fd = __gen_tempname (buf, __GT_FILE); + if (fd < 0) + return NULL; + + /* Note that this relies on the Unix semantics that + a file is not really removed until it is closed. */ + (void) remove (buf); + + if ((f = fdopen (fd, "w+b")) == NULL) + close (fd); + + return f; +} +#ifdef __UCLIBC_HAS_LFS__ +strong_alias(tmpfile,tmpfile64) +#endif diff --git a/libc/stdio/tmpnam.c b/libc/stdio/tmpnam.c new file mode 100644 index 0000000..8df6ff5 --- /dev/null +++ b/libc/stdio/tmpnam.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +static char tmpnam_buffer[L_tmpnam]; + +/* Generate a unique filename in P_tmpdir. + + This function is *not* thread safe! */ +char * +tmpnam (char *s) +{ + /* By using two buffers we manage to be thread safe in the case + where S != NULL. */ + char tmpbufmem[L_tmpnam]; + char *tmpbuf = s ?: tmpbufmem; + + /* In the following call we use the buffer pointed to by S if + non-NULL although we don't know the size. But we limit the size + to L_tmpnam characters in any case. */ + if (__builtin_expect (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0), + 0)) + return NULL; + + if (__builtin_expect (__gen_tempname (tmpbuf, __GT_NOCREATE), 0)) + return NULL; + + if (s == NULL) + return (char *) memcpy (tmpnam_buffer, tmpbuf, L_tmpnam); + + return s; +} + +link_warning (tmpnam, + "the use of `tmpnam' is dangerous, better use `mkstemp'") diff --git a/libc/stdio/tmpnam_r.c b/libc/stdio/tmpnam_r.c new file mode 100644 index 0000000..eec589e --- /dev/null +++ b/libc/stdio/tmpnam_r.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique filename in P_tmpdir. If S is NULL return NULL. + This makes this function thread safe. */ +char * tmpnam_r (char *s) +{ + if (s == NULL) + return NULL; + + if (__path_search (s, L_tmpnam, NULL, NULL, 0)) + return NULL; + if (__gen_tempname (s, __GT_NOCREATE)) + return NULL; + + return s; +} diff --git a/libc/stdio/ungetc.c b/libc/stdio/ungetc.c new file mode 100644 index 0000000..d900928 --- /dev/null +++ b/libc/stdio/ungetc.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Having ungotten characters implies the stream is reading. + * The scheme used here treats the least significant 2 bits of + * the stream's modeflags member as follows: + * 0 0 Not currently reading. + * 0 1 Reading, but no ungetc() or scanf() push back chars. + * 1 0 Reading with one ungetc() char (ungot[1] is 1) + * or one scanf() pushed back char (ungot[1] is 0). + * 1 1 Reading with both an ungetc() char and a scanf() + * pushed back char. Note that this must be the result + * of a scanf() push back (in ungot[0]) _followed_ by + * an ungetc() call (in ungot[1]). + * + * Notes: + * scanf() can NOT use ungetc() to push back characters. + * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.) + */ + +libc_hidden_proto(ungetc) +int ungetc(int c, register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Make fast ungetc an option? +#endif +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + /* If buffered narrow reading with no ungot slots filled, and if not + * ungetting a different char than the one last read from the buffer, + * we can simply decrement the position and not worry about disabling + * the getc macros. This will cut down on overhead in applications + * that use getc/ungetc extensively (like gcc). */ + /* NOTE: If we can use getc, then we are buffered narrow reading with + * no ungot slots filled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream) + && (c != EOF) + && (stream->__bufpos > stream->__bufstart) + && (stream->__bufpos[-1] == ((unsigned char)c)) + ) { + --stream->__bufpos; + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } else +#endif + /* Note: Even if c == EOF, we need to initialize/verify the + * stream's orientation and ensure the stream is in reading + * mode (if readable and properly oriented). */ + if ((!__STDIO_STREAM_IS_NARROW_READING(stream) + && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW)) + || ((stream->__modeflags & __FLAG_UNGOT) + && ((stream->__modeflags & 1) || stream->__ungot[1])) + ) { + c = EOF; + } else if (c != EOF) { + __STDIO_STREAM_DISABLE_GETC(stream); + + /* Flag this as a user ungot, as scanf does the necessary fixup. */ + stream->__ungot[1] = 1; + stream->__ungot[(++stream->__modeflags) & 1] = c; + + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } + + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return c; +} +libc_hidden_def(ungetc) diff --git a/libc/stdio/ungetwc.c b/libc/stdio/ungetwc.c new file mode 100644 index 0000000..5790222 --- /dev/null +++ b/libc/stdio/ungetwc.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Note: This is the application-callable ungetwc. If wscanf calls this, it + * should also set stream->__ungot[1] to 0 if this is the only ungot, as well + * as reset stream->__ungot_width[1] for use by _stdio_adjpos(). + */ + +libc_hidden_proto(ungetwc) +wint_t ungetwc(wint_t c, register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + + /* Note: Even if c == WEOF, we need to initialize/verify the + * stream's orientation and ensure the stream is in reading + * mode (if readable and properly oriented). */ + if ((!__STDIO_STREAM_IS_WIDE_READING(stream) + && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE)) + || ((stream->__modeflags & __FLAG_UNGOT) + && ((stream->__modeflags & 1) || stream->__ungot[1])) + || (c == WEOF) + ) { + c = WEOF; + } else { + /* In the wide case, getc macros should already be disabled. */ + /* __STDIO_STREAM_DISABLE_GETC(stream); */ + + /* Flag this as a user ungot, as scanf does the necessary fixup. */ + stream->__ungot[1] = 1; + stream->__ungot[(++stream->__modeflags) & 1] = c; + /* Note: ungot_width is handled by fgetwc. */ + + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } + + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return c; +} +libc_hidden_def(ungetwc) diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c new file mode 100644 index 0000000..b7e2e08 --- /dev/null +++ b/libc/stdio/vasprintf.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include +#include + + +#ifdef __UCLIBC_MJN3_ONLY__ +/* Do the memstream stuff inline to avoid fclose and the openlist? */ +#warning CONSIDER: avoid open_memstream call? +#endif + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping vasprintf since no vsnprintf! +#else + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +libc_hidden_proto(open_memstream) +libc_hidden_proto(fclose) +libc_hidden_proto(vfprintf) +#else +libc_hidden_proto(vsnprintf) +#endif + +libc_hidden_proto(vasprintf) +int vasprintf(char **__restrict buf, const char * __restrict format, + va_list arg) +{ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + + FILE *f; + size_t size; + int rv = -1; + + *buf = NULL; + + if ((f = open_memstream(buf, &size)) != NULL) { + rv = vfprintf(f, format, arg); + fclose(f); + if (rv < 0) { + free(*buf); + *buf = NULL; + } + } + + assert(rv >= -1); + + return rv; + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + + /* This implementation actually calls the printf machinery twice, but + * only does one malloc. This can be a problem though when custom printf + * specs or the %m specifier are involved because the results of the + * second call might be different from the first. */ + va_list arg2; + int rv; + + va_copy(arg2, arg); + rv = vsnprintf(NULL, 0, format, arg2); + va_end(arg2); + + *buf = NULL; + + if (rv >= 0) { + if ((*buf = malloc(++rv)) != NULL) { + if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) { + free(*buf); + *buf = NULL; + } + } + } + + assert(rv >= -1); + + return rv; + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ +} +libc_hidden_def(vasprintf) + +#endif +#endif diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c new file mode 100644 index 0000000..6e28b14 --- /dev/null +++ b/libc/stdio/vdprintf.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + +#ifdef __USE_OLD_VFPRINTF__ +libc_hidden_proto(vfprintf) +#endif +libc_hidden_proto(fflush_unlocked) + +libc_hidden_proto(vdprintf) +int vdprintf(int filedes, const char * __restrict format, va_list arg) +{ + FILE f; + int rv; +#ifdef __STDIO_BUFFERS + char buf[64]; /* TODO: provide _optional_ buffering? */ + + f.__bufend = (unsigned char *) buf + sizeof(buf); + f.__bufstart = (unsigned char *) buf; + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); +#endif + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = _cs_write; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = filedes; + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + +/* _vfprintf_internal doesn't do any locking, locking init is here + * only because of fflush_unlocked. TODO? */ +#if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__) + f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.__lock); +#endif + f.__nextopen = NULL; + +#ifdef __USE_OLD_VFPRINTF__ + rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif + +#ifdef __STDIO_BUFFERS + /* If not buffering, then fflush is unnecessary. */ + if ((rv > 0) && fflush_unlocked(&f)) { + rv = -1; + } +#endif + + assert(rv >= -1); + + return rv; +} +libc_hidden_def(vdprintf) +#endif diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c new file mode 100644 index 0000000..78b725f --- /dev/null +++ b/libc/stdio/vfprintf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfprintf +#include "_vfprintf.c" diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c new file mode 100644 index 0000000..b13ff8d --- /dev/null +++ b/libc/stdio/vfscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfscanf +#include "_scanf.c" diff --git a/libc/stdio/vfwprintf.c b/libc/stdio/vfwprintf.c new file mode 100644 index 0000000..323b900 --- /dev/null +++ b/libc/stdio/vfwprintf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwprintf +#include "_vfprintf.c" diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.c new file mode 100644 index 0000000..ac982b4 --- /dev/null +++ b/libc/stdio/vfwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwscanf +#include "_scanf.c" diff --git a/libc/stdio/vprintf.c b/libc/stdio/vprintf.c new file mode 100644 index 0000000..7848a07 --- /dev/null +++ b/libc/stdio/vprintf.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(vfprintf) + +int vprintf(const char * __restrict format, va_list arg) +{ + return vfprintf(stdout, format, arg); +} diff --git a/libc/stdio/vscanf.c b/libc/stdio/vscanf.c new file mode 100644 index 0000000..834fe92 --- /dev/null +++ b/libc/stdio/vscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vscanf +#include "_scanf.c" diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c new file mode 100644 index 0000000..f7d2349 --- /dev/null +++ b/libc/stdio/vsnprintf.c @@ -0,0 +1,221 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +libc_hidden_proto(vsnprintf) + +#ifdef __USE_OLD_VFPRINTF__ +libc_hidden_proto(vfprintf) +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __STDIO_BUFFERS +/* NB: we can still have __USE_OLD_VFPRINTF__ defined in this case! */ + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + FILE f; + int rv; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES; + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + +#if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__) + f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.__lock); +#endif + f.__nextopen = NULL; + + if (size > SIZE_MAX - (size_t) buf) { + size = SIZE_MAX - (size_t) buf; + } + +/* TODO: this comment seems to be wrong */ + /* Set these last since __bufputc initialization depends on + * __user_locking and only gets set if user locking is on. */ + f.__bufstart = (unsigned char *) buf; + f.__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_ENABLE_PUTC(&f); + +#ifdef __USE_OLD_VFPRINTF__ + rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif + if (size) { + if (f.__bufpos == f.__bufend) { + --f.__bufpos; + } + *f.__bufpos = 0; + } + return rv; +} +libc_hidden_def(vsnprintf) + +#elif defined(__USE_OLD_VFPRINTF__) + +typedef struct { + FILE f; + unsigned char *bufend; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsnprintf; + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + __FILE_vsnprintf f; + int rv; + + f.bufpos = buf; + + if (size > SIZE_MAX - (size_t) buf) { + size = SIZE_MAX - (size_t) buf; + } + f.bufend = buf + size; + +/* __STDIO_STREAM_RESET_GCS(&f.f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.f.__cookie = &(f.f.__filedes); + f.f.__gcs.read = NULL; + f.f.__gcs.write = NULL; + f.f.__gcs.seek = NULL; + f.f.__gcs.close = NULL; +#endif + + f.f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB; + f.f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.f.__state)); +#endif /* __STDIO_MBSTATE */ + +#ifdef __UCLIBC_HAS_THREADS__ + f.f.__user_locking = 1; /* Set user locking. */ + __stdio_init_mutex(&f.f.__lock); +#endif + f.f.__nextopen = NULL; + + rv = vfprintf((FILE *) &f, format, arg); + if (size) { + if (f.bufpos == f.bufend) { + --f.bufpos; + } + *f.bufpos = 0; + } + return rv; +} +libc_hidden_def(vsnprintf) + +#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + +typedef struct { + size_t pos; + size_t len; + unsigned char *buf; + FILE *fp; +} __snpf_cookie; + +#define COOKIE ((__snpf_cookie *) cookie) + +static ssize_t snpf_write(register void *cookie, const char *buf, + size_t bufsize) +{ + size_t count; + register char *p; + + /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */ + + if (COOKIE->len > COOKIE->pos) { + count = COOKIE->len - COOKIE->pos - 1; /* Leave space for nul. */ + if (count > bufsize) { + count = bufsize; + } + + p = COOKIE->buf + COOKIE->pos; + while (count) { + *p++ = *buf++; + --count; + } + *p = 0; + } + + COOKIE->pos += bufsize; + + return bufsize; +} + +#undef COOKIE + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + FILE f; + __snpf_cookie cookie; + int rv; + + cookie.buf = buf; + cookie.len = size; + cookie.pos = 0; + cookie.fp = &f; + + f.__cookie = &cookie; + f.__gcs.write = snpf_write; + f.__gcs.read = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; + + f.__filedes = -1; /* For debugging. */ + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + + f.__nextopen = NULL; + + rv = _vfprintf_internal(&f, format, arg); + + return rv; +} +libc_hidden_def(vsnprintf) + +#else +#warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf! +#ifdef __STDIO_HAS_VSNPRINTF +#error WHOA! __STDIO_HAS_VSNPRINTF is defined! +#endif +#endif diff --git a/libc/stdio/vsprintf.c b/libc/stdio/vsprintf.c new file mode 100644 index 0000000..8e27c19 --- /dev/null +++ b/libc/stdio/vsprintf.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping vsprintf since no vsnprintf! +#else + +libc_hidden_proto(vsnprintf) + +int vsprintf(char *__restrict buf, const char * __restrict format, + va_list arg) +{ + return vsnprintf(buf, SIZE_MAX, format, arg); +} + +#endif diff --git a/libc/stdio/vsscanf.c b/libc/stdio/vsscanf.c new file mode 100644 index 0000000..882c271 --- /dev/null +++ b/libc/stdio/vsscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vsscanf +#include "_scanf.c" diff --git a/libc/stdio/vswprintf.c b/libc/stdio/vswprintf.c new file mode 100644 index 0000000..cddf1d5 --- /dev/null +++ b/libc/stdio/vswprintf.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + +libc_hidden_proto(vswprintf) + +/* NB: this file is not used if __USE_OLD_VFPRINTF__ */ + +#ifndef __STDIO_BUFFERS +#warning Skipping vswprintf since no buffering! +#else /* __STDIO_BUFFERS */ + +int vswprintf(wchar_t *__restrict buf, size_t size, + const wchar_t * __restrict format, va_list arg) +{ + FILE f; + int rv; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES; + f.__modeflags = (__FLAG_WIDE|__FLAG_WRITEONLY|__FLAG_WRITING); + + f.__ungot_width[0] = 0; +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + + f.__nextopen = NULL; + + if (size > ((SIZE_MAX - (size_t) buf)/sizeof(wchar_t))) { + size = ((SIZE_MAX - (size_t) buf)/sizeof(wchar_t)); + } + + f.__bufstart = (char *) buf; + f.__bufend = (char *)(buf + size); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + + rv = _vfwprintf_internal(&f, format, arg); + + /* NOTE: Return behaviour differs from snprintf... */ + if (f.__bufpos == f.__bufend) { + rv = -1; + if (size) { + f.__bufpos = (char *)(((wchar_t *) f.__bufpos) - 1); + } + } + if (size) { + *((wchar_t *) f.__bufpos) = 0; + } + return rv; +} +libc_hidden_def(vswprintf) + +#endif /* __STDIO_BUFFERS */ diff --git a/libc/stdio/vswscanf.c b/libc/stdio/vswscanf.c new file mode 100644 index 0000000..fddb602 --- /dev/null +++ b/libc/stdio/vswscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vswscanf +#include "_scanf.c" diff --git a/libc/stdio/vwprintf.c b/libc/stdio/vwprintf.c new file mode 100644 index 0000000..1c32887 --- /dev/null +++ b/libc/stdio/vwprintf.c @@ -0,0 +1,17 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + +libc_hidden_proto(vfwprintf) + +int vwprintf(const wchar_t * __restrict format, va_list arg) +{ + return vfwprintf(stdout, format, arg); +} diff --git a/libc/stdio/vwscanf.c b/libc/stdio/vwscanf.c new file mode 100644 index 0000000..9e21a27 --- /dev/null +++ b/libc/stdio/vwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vwscanf +#include "_scanf.c" diff --git a/libc/stdio/wprintf.c b/libc/stdio/wprintf.c new file mode 100644 index 0000000..9dc274a --- /dev/null +++ b/libc/stdio/wprintf.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + +libc_hidden_proto(vfwprintf) + +int wprintf(const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwprintf(stdout, format, arg); + va_end(arg); + + return rv; +} + diff --git a/libc/stdio/wscanf.c b/libc/stdio/wscanf.c new file mode 100644 index 0000000..d354d52 --- /dev/null +++ b/libc/stdio/wscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_wscanf +#include "_scanf.c" diff --git a/libc/stdlib/.indent.pro b/libc/stdlib/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/stdlib/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/stdlib/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/stdlib/Makefile.in b/libc/stdlib/Makefile.in new file mode 100644 index 0000000..75c613c --- /dev/null +++ b/libc/stdlib/Makefile.in @@ -0,0 +1,99 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)libc/stdlib/malloc/Makefile.in +include $(top_srcdir)libc/stdlib/malloc-simple/Makefile.in +include $(top_srcdir)libc/stdlib/malloc-standard/Makefile.in + +CSRC := \ + abort.c getenv.c mkdtemp.c mktemp.c realpath.c mkstemp.c \ + rand.c random.c random_r.c setenv.c system.c div.c ldiv.c lldiv.c \ + getpt.c drand48-iter.c jrand48.c \ + jrand48_r.c lrand48.c lrand48_r.c mrand48.c mrand48_r.c nrand48.c \ + nrand48_r.c rand_r.c srand48.c srand48_r.c seed48.c seed48_r.c \ + valloc.c a64l.c l64a.c __uc_malloc.c +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +CSRC += posix_memalign.c +endif +ifeq ($(UCLIBC_HAS_PTY),y) +CSRC += grantpt.c unlockpt.c ptsname.c +endif +ifeq ($(UCLIBC_HAS_ARC4RANDOM),y) +CSRC += arc4random.c +endif +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += mkstemp64.c +endif +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += drand48.c drand48_r.c erand48.c erand48_r.c +ifeq ($(UCLIBC_SUSV3_LEGACY),y) +CSRC += gcvt.c +endif +endif + +# multi source stdlib.c +CSRC += abs.c labs.c atoi.c atol.c strtol.c strtoul.c _stdlib_strto_l.c \ + qsort.c bsearch.c \ + llabs.c atoll.c strtoll.c strtoull.c _stdlib_strto_ll.c +# (aliases) strtoq.o strtouq.o +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += atof.c +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += strtol_l.c strtoul_l.c _stdlib_strto_l_l.c \ + strtoll_l.c strtoull_l.c _stdlib_strto_ll_l.c +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += mblen.c mbtowc.c wctomb.c mbstowcs.c wcstombs.c \ + _stdlib_mb_cur_max.c _stdlib_wcsto_l.c _stdlib_wcsto_ll.c \ + wcstol.c wcstoul.c wcstoll.c wcstoull.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC +=_stdlib_wcsto_l_l.c _stdlib_wcsto_ll_l.c \ + wcstol_l.c wcstoul_l.c wcstoll_l.c wcstoull_l.c +endif +endif + +# multi source _strtod.c +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += strtod.c strtof.c strtold.c __strtofpmax.c __fp_range_check.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += strtod_l.c strtof_l.c strtold_l.c __strtofpmax_l.c +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += wcstod.c wcstof.c wcstold.c __wcstofpmax.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += wcstod_l.c wcstof_l.c wcstold_l.c __wcstofpmax_l.c +endif +endif +endif +# (aliases) wcstoq.o wcstouq.o +# wcstod wcstof wcstold + +# multi source _atexit.c +CSRC += __cxa_atexit.c __cxa_finalize.c __exit_handler.c exit.c on_exit.c +ifeq ($(COMPAT_ATEXIT),y) +CSRC += old_atexit.c +endif + +STDLIB_DIR := $(top_srcdir)libc/stdlib +STDLIB_OUT := $(top_builddir)libc/stdlib + +STDLIB_SRC := $(patsubst %.c,$(STDLIB_DIR)/%.c,$(CSRC)) +STDLIB_OBJ := $(patsubst %.c,$(STDLIB_OUT)/%.o,$(CSRC)) + +libc-y += $(STDLIB_OBJ) +libc-static-y += $(STDLIB_OUT)/atexit.o +# this should always be the PIC version, because it could be used in shared libs +libc-nonshared-y += $(STDLIB_OUT)/atexit.os + +libc-nomulti-y += $(STDLIB_OUT)/labs.o $(STDLIB_OUT)/atol.o $(STDLIB_OUT)/_stdlib_strto_l.o $(STDLIB_OUT)/_stdlib_strto_ll.o +libc-nomulti-$(UCLIBC_HAS_XLOCALE) += $(STDLIB_OUT)/_stdlib_strto_l_l.o $(STDLIB_OUT)/_stdlib_strto_ll_l.o + +objclean-y += stdlib_clean + +stdlib_clean: + $(do_rm) $(addprefix $(STDLIB_OUT)/*., o os oS) diff --git a/libc/stdlib/__cxa_atexit.c b/libc/stdlib/__cxa_atexit.c new file mode 100644 index 0000000..fbf06e5 --- /dev/null +++ b/libc/stdlib/__cxa_atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___cxa_atexit +#include "_atexit.c" diff --git a/libc/stdlib/__cxa_finalize.c b/libc/stdlib/__cxa_finalize.c new file mode 100644 index 0000000..4a91626 --- /dev/null +++ b/libc/stdlib/__cxa_finalize.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___cxa_finalize +#include "_atexit.c" diff --git a/libc/stdlib/__exit_handler.c b/libc/stdlib/__exit_handler.c new file mode 100644 index 0000000..ae4ff84 --- /dev/null +++ b/libc/stdlib/__exit_handler.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___exit_handler +#include "_atexit.c" diff --git a/libc/stdlib/__fp_range_check.c b/libc/stdlib/__fp_range_check.c new file mode 100644 index 0000000..9c60972 --- /dev/null +++ b/libc/stdlib/__fp_range_check.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___fp_range_check +#include "_strtod.c" diff --git a/libc/stdlib/__strtofpmax.c b/libc/stdlib/__strtofpmax.c new file mode 100644 index 0000000..6b01aca --- /dev/null +++ b/libc/stdlib/__strtofpmax.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___strtofpmax +#include "_strtod.c" diff --git a/libc/stdlib/__strtofpmax_l.c b/libc/stdlib/__strtofpmax_l.c new file mode 100644 index 0000000..a614132 --- /dev/null +++ b/libc/stdlib/__strtofpmax_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___strtofpmax_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/__uc_malloc.c b/libc/stdlib/__uc_malloc.c new file mode 100644 index 0000000..81eee13 --- /dev/null +++ b/libc/stdlib/__uc_malloc.c @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: */ +/* uClibc internal malloc. + Copyright (C) 2007 Denys Vlasenko + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +version 2 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include + +libc_hidden_proto(_exit) +libc_hidden_proto(__uc_malloc) +libc_hidden_proto(__uc_malloc_failed) + +void (*__uc_malloc_failed)(size_t size) = NULL; +/* Seemingly superfluous assigment of NULL above prevents gas error + * ("__uc_malloc_failed can't be equated to common symbol + * __GI___uc_malloc_failed") in libc_hidden_data_def: */ +libc_hidden_data_def(__uc_malloc_failed) + +void *__uc_malloc(size_t size) +{ + void *p; + + while (1) { + p = malloc(size); + if (!size || p) + return p; + if (!__uc_malloc_failed) + _exit(1); + __uc_malloc_failed(size); + } +} +libc_hidden_def(__uc_malloc) diff --git a/libc/stdlib/__wcstofpmax.c b/libc/stdlib/__wcstofpmax.c new file mode 100644 index 0000000..3c3fdcc --- /dev/null +++ b/libc/stdlib/__wcstofpmax.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___wcstofpmax +#include "_strtod.c" diff --git a/libc/stdlib/__wcstofpmax_l.c b/libc/stdlib/__wcstofpmax_l.c new file mode 100644 index 0000000..909b720 --- /dev/null +++ b/libc/stdlib/__wcstofpmax_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___wcstofpmax_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/_atexit.c b/libc/stdlib/_atexit.c new file mode 100644 index 0000000..e5840f4 --- /dev/null +++ b/libc/stdlib/_atexit.c @@ -0,0 +1,339 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* + * Dec 2000 Manuel Novoa III + * + * Made atexit handling conform to standards... i.e. no args. + * Removed on_exit since it did not match gnu libc definition. + * Combined atexit and __do_exit into one object file. + * + * Feb 2001 Manuel Novoa III + * + * Reworked file after addition of __uClibc_main. + * Changed name of __do_exit to atexit_handler. + * Changed name of __cleanup to __uClibc_cleanup. + * Moved declaration of __uClibc_cleanup to __uClibc_main + * where it is initialized with (possibly weak alias) + * _stdio_term. + * + * Jul 2001 Steve Thayer + * + * Added an on_exit implementation (that now matches gnu libc definition.) + * Pulled atexit_handler out of the atexit object since it is now required by + * on_exit as well. Renamed it to __exit_handler. + * Fixed a problem where exit functions stop getting called if one of + * them calls exit(). + * As a side effect of these changes, abort() no longer calls the exit + * functions (it now matches the gnu libc definition). + * + * August 2002 Erik Andersen + * Added locking so atexit and friends can be thread safe + * + * August 2005 Stephen Warren + * Added __cxa_atexit and __cxa_finalize support + * + */ + +#include +#include +#include +#include +#include + +#include +__UCLIBC_MUTEX_EXTERN(__atexit_lock); + +libc_hidden_proto(exit) +libc_hidden_proto(_exit) + + +typedef void (*aefuncp) (void); /* atexit function pointer */ +typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +typedef void (*cxaefuncp) (void *); /* __cxa_atexit function pointer */ +typedef enum { + ef_free, + ef_in_use, + ef_on_exit, + ef_cxa_atexit +} ef_type; /* exit function types */ + +/* this is in the L_exit object */ +extern void (*__exit_cleanup) (int) attribute_hidden; + +/* these are in the L___do_exit object */ +extern int __exit_slots attribute_hidden; +extern int __exit_count attribute_hidden; +extern void __exit_handler(int) attribute_hidden; +struct exit_function { + /* + * 'type' should be of type of the 'enum ef_type' above but since we + * need this element in an atomic operation we have to use 'long int'. + */ + long int type; /* enum ef_type */ + union { + struct { + oefuncp func; + void *arg; + } on_exit; + struct { + cxaefuncp func; + void *arg; + void* dso_handle; + } cxa_atexit; + } funcs; +}; +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +extern struct exit_function *__exit_function_table attribute_hidden; +#else +extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT] attribute_hidden; +#endif +extern struct exit_function *__new_exitfn (void) attribute_hidden; + +/* this is in the L___cxa_atexit object */ +extern int __cxa_atexit (cxaefuncp, void *arg, void *dso_handle); + + +/* remove old_atexit after 0.9.29 */ +#if defined(L_atexit) || defined(L_old_atexit) +extern void *__dso_handle __attribute__ ((__weak__)); + +/* + * register a function to be called at normal program termination + * (the registered function takes no arguments) + */ +#ifdef L_atexit +int attribute_hidden atexit(aefuncp func) +#else +int old_atexit(aefuncp func); +int old_atexit(aefuncp func) +#endif +{ + /* + * glibc casts aefuncp to cxaefuncp. + * This seems dodgy, but I guess calling a function with more + * parameters than it needs will work everywhere? + */ + return __cxa_atexit((cxaefuncp)func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef L_atexit +weak_alias(old_atexit,atexit) +#endif +#endif + +#ifdef L_on_exit +/* + * register a function to be called at normal program termination + * the registered function takes two arguments: + * status - the exit status that was passed to the exit() function + * arg - generic argument + */ +int on_exit(oefuncp func, void *arg) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_on_exit; + + return 0; +} +#endif + +#ifdef L___cxa_atexit +libc_hidden_proto(__cxa_atexit) +int __cxa_atexit (cxaefuncp func, void *arg, void *dso_handle) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.cxa_atexit.func = func; + efp->funcs.cxa_atexit.arg = arg; + efp->funcs.cxa_atexit.dso_handle = dso_handle; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_cxa_atexit; + + return 0; +} +libc_hidden_def(__cxa_atexit) +#endif + +#ifdef L___cxa_finalize +/* + * If D is non-NULL, call all functions registered with `__cxa_atexit' + * with the same dso handle. Otherwise, if D is NULL, call all of the + * registered handlers. + */ +void __cxa_finalize (void *dso_handle); +void __cxa_finalize (void *dso_handle) +{ + struct exit_function *efp; + int exit_count_snapshot = __exit_count; + + /* In reverse order */ + while (exit_count_snapshot) { + efp = &__exit_function_table[--exit_count_snapshot]; + + /* + * We check dso_handle match before we verify the type of the union entry. + * However, the atomic_exchange will validate that we were really "allowed" + * to read dso_handle... + */ + if ((dso_handle == NULL || dso_handle == efp->funcs.cxa_atexit.dso_handle) + /* We don't want to run this cleanup more than once. */ + && !atomic_compare_and_exchange_bool_acq(&efp->type, ef_free, ef_cxa_atexit) + ) { + /* glibc passes status (0) too, but that's not in the prototype */ + (*efp->funcs.cxa_atexit.func)(efp->funcs.cxa_atexit.arg); + } + } + +#if 0 /* haven't looked into this yet... */ + /* + * Remove the registered fork handlers. We do not have to + * unregister anything if the program is going to terminate anyway. + */ +#ifdef UNREGISTER_ATFORK + if (d != NULL) { + UNREGISTER_ATFORK (d); + } +#endif +#endif +} +#endif + +#ifdef L___exit_handler +int __exit_count = 0; /* Number of registered exit functions */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +struct exit_function *__exit_function_table = NULL; +int __exit_slots = 0; /* Size of __exit_function_table */ +#else +struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif + +/* + * Find and return a new exit_function pointer, for atexit, + * onexit and __cxa_atexit to initialize + */ +struct exit_function attribute_hidden *__new_exitfn(void) +{ + struct exit_function *efp; + + __UCLIBC_MUTEX_LOCK(__atexit_lock); + +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ + if (__exit_slots < __exit_count+1) { + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + __exit_function_table = efp; + __exit_slots += 20; + } +#else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { + __set_errno(ENOMEM); + efp = NULL; + goto DONE; + } +#endif + + __exit_cleanup = __exit_handler; /* enable cleanup */ + efp = &__exit_function_table[__exit_count++]; + efp->type = ef_in_use; + +DONE: + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + return efp; +} + +/* + * Handle the work of executing the registered exit functions + * This is called while we are locked, so no additional locking + * is needed... + */ +void __exit_handler(int status) +{ + struct exit_function *efp; + + /* In reverse order */ + while ( __exit_count ) { + efp = &__exit_function_table[--__exit_count]; + switch (efp->type) { + case ef_on_exit: + if (efp->funcs.on_exit.func) { + (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg); + } + break; + case ef_cxa_atexit: + if (efp->funcs.cxa_atexit.func) { + /* glibc passes status too, but that's not in the prototype */ + (efp->funcs.cxa_atexit.func) (efp->funcs.cxa_atexit.arg); + } + break; + } + } +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* Free up memory used by the __exit_function_table structure */ + free(__exit_function_table); +#endif +} +#endif + +#ifdef L_exit +extern void weak_function _stdio_term(void) attribute_hidden; +attribute_hidden void (*__exit_cleanup) (int) = 0; +__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +extern void __uClibc_fini(void); +libc_hidden_proto(__uClibc_fini) + +/* + * Normal program termination + */ +void exit(int rv) +{ + /* Perform exit-specific cleanup (atexit and on_exit) */ + __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (__exit_cleanup) { + __exit_cleanup(rv); + } + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + + __uClibc_fini(); + + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) + _stdio_term(); + + _exit(rv); +} +libc_hidden_def(exit) +#endif diff --git a/libc/stdlib/_stdlib_mb_cur_max.c b/libc/stdlib/_stdlib_mb_cur_max.c new file mode 100644 index 0000000..b87f609 --- /dev/null +++ b/libc/stdlib/_stdlib_mb_cur_max.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_mb_cur_max +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_strto_l.c b/libc/stdlib/_stdlib_strto_l.c new file mode 100644 index 0000000..4dfa037 --- /dev/null +++ b/libc/stdlib/_stdlib_strto_l.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_l +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_strto_l_l.c b/libc/stdlib/_stdlib_strto_l_l.c new file mode 100644 index 0000000..1692f0c --- /dev/null +++ b/libc/stdlib/_stdlib_strto_l_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_l_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_strto_ll.c b/libc/stdlib/_stdlib_strto_ll.c new file mode 100644 index 0000000..ce79598 --- /dev/null +++ b/libc/stdlib/_stdlib_strto_ll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_ll +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_strto_ll_l.c b/libc/stdlib/_stdlib_strto_ll_l.c new file mode 100644 index 0000000..b5fb111 --- /dev/null +++ b/libc/stdlib/_stdlib_strto_ll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_ll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_wcsto_l.c b/libc/stdlib/_stdlib_wcsto_l.c new file mode 100644 index 0000000..d05a207 --- /dev/null +++ b/libc/stdlib/_stdlib_wcsto_l.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_l +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_wcsto_l_l.c b/libc/stdlib/_stdlib_wcsto_l_l.c new file mode 100644 index 0000000..26ea5a7 --- /dev/null +++ b/libc/stdlib/_stdlib_wcsto_l_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_l_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_wcsto_ll.c b/libc/stdlib/_stdlib_wcsto_ll.c new file mode 100644 index 0000000..e67a577 --- /dev/null +++ b/libc/stdlib/_stdlib_wcsto_ll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_ll +#include "stdlib.c" diff --git a/libc/stdlib/_stdlib_wcsto_ll_l.c b/libc/stdlib/_stdlib_wcsto_ll_l.c new file mode 100644 index 0000000..9d64712 --- /dev/null +++ b/libc/stdlib/_stdlib_wcsto_ll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_ll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/_strtod.c b/libc/stdlib/_strtod.c new file mode 100644 index 0000000..1b2adc9 --- /dev/null +++ b/libc/stdlib/_strtod.c @@ -0,0 +1,620 @@ +/* + * Copyright (C) 2000-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Notes: + * + * The primary objective of this implementation was minimal size and + * portablility, while providing robustness and resonable accuracy. + * + * This implementation depends on IEEE floating point behavior and expects + * to be able to generate +/- infinity as a result. + * + * There are a number of compile-time options below. + */ + +/* July 27, 2003 + * + * General cleanup and some minor size optimizations. + * Change implementation to support __strtofpmax() rather than strtod(). + * Now all the strto{floating pt}() funcs are implemented in terms of + * of the internal __strtofpmax() function. + * Support "nan", "inf", and "infinity" strings (case-insensitive). + * Support hexadecimal floating point notation. + * Support wchar variants. + * Support xlocale variants. + * + * TODO: + * + * Consider accumulating blocks of digits in longs to save floating pt mults. + * This would likely be much better on anything that only supported floats + * where DECIMAL_DIG == 9. Actually, if floats have FLT_MAX_10_EXP == 38, + * we could calculate almost all the exponent multipliers (p_base) in + * long arithmetic as well. + */ + +/**********************************************************************/ +/* OPTIONS */ +/**********************************************************************/ + +/* Defined if we want to recognize "nan", "inf", and "infinity". (C99) */ +#define _STRTOD_NAN_INF_STRINGS 1 + +/* Defined if we want support hexadecimal floating point notation. (C99) */ +/* Note! Now controlled by uClibc configuration. See below. */ +#define _STRTOD_HEXADECIMAL_FLOATS 1 + +/* Defined if we want to scale with a O(log2(exp)) multiplications. + * This is generally a good thing to do unless you are really tight + * on space and do not expect to convert values of large magnitude. */ + +#define _STRTOD_LOG_SCALING 1 + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * Clearing any of the options below this point is not advised (or tested). + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! */ + +/* Defined if we want strtod to set errno appropriately. */ +/* NOTE: Implies all options below. */ +#define _STRTOD_ERRNO 1 + +/* Defined if we want support for the endptr arg. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ENDPTR 1 + +/* Defined if we want to prevent overflow in accumulating the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_EXP 1 + +/* Defined if we want to process mantissa digits more intelligently. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_DIGITS 1 + +/* Defined if we want to skip scaling 0 for the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ZERO_CHECK 1 + +/**********************************************************************/ +/* Don't change anything that follows. */ +/**********************************************************************/ + +#ifdef _STRTOD_ERRNO +#undef _STRTOD_ENDPTR +#undef _STRTOD_RESTRICT_EXP +#undef _STRTOD_RESTRICT_DIGITS +#undef _STRTOD_ZERO_CHECK +#define _STRTOD_ENDPTR 1 +#define _STRTOD_RESTRICT_EXP 1 +#define _STRTOD_RESTRICT_DIGITS 1 +#define _STRTOD_ZERO_CHECK 1 +#endif + +/**********************************************************************/ + +#define _ISOC99_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __UCLIBC_HAS_WCHAR__ + +#include +#include +#include +libc_hidden_proto(iswspace) +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +libc_hidden_proto(iswspace_l) +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Handle _STRTOD_HEXADECIMAL_FLOATS via uClibc config now. */ +#undef _STRTOD_HEXADECIMAL_FLOATS +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#define _STRTOD_HEXADECIMAL_FLOATS 1 +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +/**********************************************************************/ + +#undef _STRTOD_FPMAX + +#if FPMAX_TYPE == 3 + +#define NEED_STRTOLD_WRAPPER +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 2 + +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 1 + +#define NEED_STRTOF_WRAPPER + +#else + +#error unknown FPMAX_TYPE! + +#endif + +extern void __fp_range_check(__fpmax_t y, __fpmax_t x) attribute_hidden; + +/**********************************************************************/ + +#ifdef _STRTOD_RESTRICT_DIGITS +#define EXP_DENORM_ADJUST DECIMAL_DIG +#define MAX_ALLOWED_EXP (DECIMAL_DIG + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP) + +#if MAX_ALLOWED_EXP > INT_MAX +#error size assumption violated for MAX_ALLOWED_EXP +#endif +#else +/* We want some excess if we're not restricting mantissa digits. */ +#define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2) +#endif + + +#if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS) +#undef _STRTOD_NEED_NUM_DIGITS +#define _STRTOD_NEED_NUM_DIGITS 1 +#endif + +/**********************************************************************/ +#if defined(L___strtofpmax) || defined(L___strtofpmax_l) || defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +libc_hidden_proto(__ctype_tolower) +#endif + +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l + +#define Wchar wchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +#else +#define ISSPACE(C) iswspace((C)) +#endif + +#else /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + +#define Wchar char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#endif /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +__fpmax_t attribute_hidden __strtofpmax(const Wchar *str, Wchar **endptr, int exponent_power) +{ + return __strtofpmax_l(str, endptr, exponent_power, __UCLIBC_CURLOCALE); +} + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* Experimentally off - libc_hidden_proto(memcmp) */ + +__fpmax_t attribute_hidden __XL_NPP(__strtofpmax)(const Wchar *str, Wchar **endptr, int exponent_power + __LOCALE_PARAM ) +{ + __fpmax_t number; + __fpmax_t p_base = 10; /* Adjusted to 16 in the hex case. */ + Wchar *pos0; +#ifdef _STRTOD_ENDPTR + Wchar *pos1; +#endif + Wchar *pos = (Wchar *) str; + int exponent_temp; + int negative; /* A flag for the number, a multiplier for the exponent. */ +#ifdef _STRTOD_NEED_NUM_DIGITS + int num_digits; +#endif +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + wchar_t decpt_wc = __LOCALE_PTR->decimal_point_wc; +#else + const char *decpt = __LOCALE_PTR->decimal_point; + int decpt_len = __LOCALE_PTR->decimal_point_len; +#endif +#endif + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + Wchar expchar = 'e'; + Wchar *poshex = NULL; + __uint16_t is_mask = _ISdigit; +#define EXPCHAR expchar +#define IS_X_DIGIT(C) __isctype((C), is_mask) +#else /* _STRTOD_HEXADECIMAL_FLOATS */ +#define EXPCHAR 'e' +#define IS_X_DIGIT(C) isdigit((C)) +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + while (ISSPACE(*pos)) { /* Skip leading whitespace. */ + ++pos; + } + + negative = 0; + switch(*pos) { /* Handle optional sign. */ + case '-': negative = 1; /* Fall through to increment position. */ + case '+': ++pos; + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if ((*pos == '0') && (((pos[1])|0x20) == 'x')) { + poshex = ++pos; /* Save position of 'x' in case no digits */ + ++pos; /* and advance past it. */ + is_mask = _ISxdigit; /* Used by IS_X_DIGIT. */ + expchar = 'p'; /* Adjust exponent char. */ + p_base = 16; /* Adjust base multiplier. */ + } +#endif + + number = 0.; +#ifdef _STRTOD_NEED_NUM_DIGITS + num_digits = -1; +#endif +/* exponent_power = 0; */ + pos0 = NULL; + + LOOP: + while (IS_X_DIGIT(*pos)) { /* Process string of (hex) digits. */ +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits < 0) { /* First time through? */ + ++num_digits; /* We've now seen a digit. */ + } + if (num_digits || (*pos != '0')) { /* Had/have nonzero. */ + ++num_digits; + if (num_digits <= DECIMAL_DIG) { /* Is digit significant? */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + } + } +#else /* _STRTOD_RESTRICT_DIGITS */ +#ifdef _STRTOD_NEED_NUM_DIGITS + ++num_digits; +#endif +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ +#endif /* _STRTOD_RESTRICT_DIGITS */ + ++pos; + } + +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + if (!pos0 && (*pos == decpt_wc)) { /* First decimal point? */ + pos0 = ++pos; + goto LOOP; + } +#else + if (!pos0 && !memcmp(pos, decpt, decpt_len)) { /* First decimal point? */ + pos0 = (pos += decpt_len); + goto LOOP; + } +#endif +#else /* __UCLIBC_HAS_LOCALE__ */ + if ((*pos == '.') && !pos0) { /* First decimal point? */ + pos0 = ++pos; /* Save position of decimal point */ + goto LOOP; /* and process rest of digits. */ + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef _STRTOD_NEED_NUM_DIGITS + if (num_digits<0) { /* Must have at least one digit. */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { /* Back up to '0' in '0x' prefix. */ + pos = poshex; + goto DONE; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + +#ifdef _STRTOD_NAN_INF_STRINGS + if (!pos0) { /* No decimal point, so check for inf/nan. */ + /* Note: nan is the first string so 'number = i/0.;' works. */ + static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0"; + int i = 0; + +#ifdef __UCLIBC_HAS_LOCALE__ + /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ +#undef _tolower +#define _tolower(C) ((C)|0x20) +#endif /* __UCLIBC_HAS_LOCALE__ */ + + do { + /* Unfortunately, we have no memcasecmp(). */ + int j = 0; + while (_tolower(pos[j]) == nan_inf_str[i+1+j]) { + ++j; + if (!nan_inf_str[i+1+j]) { + number = i / 0.; + if (negative) { /* Correct for sign. */ + number = -number; + } + pos += nan_inf_str[i] - 2; + goto DONE; + } + } + i += nan_inf_str[i]; + } while (nan_inf_str[i]); + } + +#endif /* STRTOD_NAN_INF_STRINGS */ +#ifdef _STRTOD_ENDPTR + pos = (Wchar *) str; +#endif + goto DONE; + } +#endif /* _STRTOD_NEED_NUM_DIGITS */ + +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits > DECIMAL_DIG) { /* Adjust exponent for skipped digits. */ + exponent_power += num_digits - DECIMAL_DIG; + } +#endif + + if (pos0) { + exponent_power += pos0 - pos; /* Adjust exponent for decimal point. */ + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { + exponent_power *= 4; /* Above is 2**4, but below is 2. */ + p_base = 2; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + if (negative) { /* Correct for sign. */ + number = -number; + } + + /* process an exponent string */ + if (((*pos)|0x20) == EXPCHAR) { +#ifdef _STRTOD_ENDPTR + pos1 = pos; +#endif + negative = 1; + switch(*++pos) { /* Handle optional sign. */ + case '-': negative = -1; /* Fall through to increment pos. */ + case '+': ++pos; + } + + pos0 = pos; + exponent_temp = 0; + while (isdigit(*pos)) { /* Process string of digits. */ +#ifdef _STRTOD_RESTRICT_EXP + if (exponent_temp < MAX_ALLOWED_EXP) { /* Avoid overflow. */ + exponent_temp = exponent_temp * 10 + (*pos - '0'); + } +#else + exponent_temp = exponent_temp * 10 + (*pos - '0'); +#endif + ++pos; + } + +#ifdef _STRTOD_ENDPTR + if (pos == pos0) { /* No digits? */ + pos = pos1; /* Back up to {e|E}/{p|P}. */ + } /* else */ +#endif + + exponent_power += negative * exponent_temp; + } + +#ifdef _STRTOD_ZERO_CHECK + if (number == 0.) { + goto DONE; + } +#endif + + /* scale the result */ +#ifdef _STRTOD_LOG_SCALING + exponent_temp = exponent_power; + + if (exponent_temp < 0) { + exponent_temp = -exponent_temp; + } + + while (exponent_temp) { + if (exponent_temp & 1) { + if (exponent_power < 0) { + /* Warning... caluclating a factor for the exponent and + * then dividing could easily be faster. But doing so + * might cause problems when dealing with denormals. */ + number /= p_base; + } else { + number *= p_base; + } + } + exponent_temp >>= 1; + p_base *= p_base; + } + +#else /* _STRTOD_LOG_SCALING */ + while (exponent_power) { + if (exponent_power < 0) { + number /= p_base; + exponent_power++; + } else { + number *= p_base; + exponent_power--; + } + } +#endif /* _STRTOD_LOG_SCALING */ + +#ifdef _STRTOD_ERRNO + if (__FPMAX_ZERO_OR_INF_CHECK(number)) { + __set_errno(ERANGE); + } +#endif + + DONE: +#ifdef _STRTOD_ENDPTR + if (endptr) { + *endptr = pos; + } +#endif + + return number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L___fp_range_check +#if defined(NEED_STRTOF_WRAPPER) || defined(NEED_STRTOD_WRAPPER) + +void attribute_hidden __fp_range_check(__fpmax_t y, __fpmax_t x) +{ + if (__FPMAX_ZERO_OR_INF_CHECK(y) /* y is 0 or +/- infinity */ + && (y != 0) /* y is not 0 (could have x>0, y==0 if underflow) */ + && !__FPMAX_ZERO_OR_INF_CHECK(x) /* x is not 0 or +/- infinity */ + ) { + __set_errno(ERANGE); /* Then x is not in y's range. */ + } +} + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtof) || defined(L_strtof_l) || defined(L_wcstof) || defined(L_wcstof_l) +#if defined(NEED_STRTOF_WRAPPER) + +#if defined(L_wcstof) || defined(L_wcstof_l) +#define strtof wcstof +#define strtof_l wcstof_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + + +libc_hidden_proto(__XL_NPP(strtof)) +float __XL_NPP(strtof)(const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 1 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + float y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (float) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtof)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtod) || defined(L_strtod_l) || defined(L_wcstod) || defined(L_wcstod_l) +#if defined(NEED_STRTOD_WRAPPER) + +#if defined(L_wcstod) || defined(L_wcstod_l) +#define strtod wcstod +#define strtod_l wcstod_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtod)) +double __XL_NPP(strtod)(const Wchar *__restrict str, + Wchar **__restrict endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 2 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtod)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtold) || defined(L_strtold_l) || defined(L_wcstold) || defined(L_wcstold_l) +#if defined(NEED_STRTOLD_WRAPPER) + +#if defined(L_wcstold) || defined(L_wcstold_l) +#define strtold wcstold +#define strtold_l wcstold_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtold)) +long double __XL_NPP(strtold) (const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 3 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + long double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (long double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtold)) + +#endif +#endif +/**********************************************************************/ diff --git a/libc/stdlib/a64l.c b/libc/stdlib/a64l.c new file mode 100644 index 0000000..d09dbf4 --- /dev/null +++ b/libc/stdlib/a64l.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define TABLE_BASE 0x2e +#define TABLE_SIZE 0x4d + +#define XX ((char)0x40) + + +static const char a64l_table[TABLE_SIZE] = +{ + /* 0x2e */ 0, 1, + /* 0x30 */ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, XX, XX, XX, XX, XX, XX, + /* 0x40 */ XX, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + /* 0x50 */ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, XX, XX, XX, XX, XX, + /* 0x60 */ XX, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 0x70 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 +}; + + +long int a64l (const char *string) +{ + const char *ptr = string; + unsigned long int result = 0ul; + const char *end = ptr + 6; + int shift = 0; + + do + { + unsigned index; + unsigned value; + + index = *ptr - TABLE_BASE; + if ((unsigned int) index >= TABLE_SIZE) + break; + value = (int) a64l_table[index]; + if (value == (int) XX) + break; + ++ptr; + result |= value << shift; + shift += 6; + } + while (ptr != end); + + return (long int) result; +} diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c new file mode 100644 index 0000000..b71512f --- /dev/null +++ b/libc/stdlib/abort.c @@ -0,0 +1,120 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Hacked up for uClibc by Erik Andersen */ + +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(abort) + +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(sigaction) +libc_hidden_proto(sigprocmask) +libc_hidden_proto(raise) +libc_hidden_proto(_exit) + +/* Our last ditch effort to commit suicide */ +#ifdef __UCLIBC_ABORT_INSTRUCTION__ +# define ABORT_INSTRUCTION __asm__(__UCLIBC_ABORT_INSTRUCTION__) +#else +# define ABORT_INSTRUCTION +# warning "no abort instruction defined for your arch" +#endif + +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +extern void weak_function _stdio_term(void) attribute_hidden; +#endif +static smallint been_there_done_that = 0; + +/* Be prepared in case multiple threads try to abort() */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +/* Cause an abnormal program termination with core-dump */ +void abort(void) +{ + sigset_t sigs; + + /* Make sure we acquire the lock before proceeding */ + __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + + /* Unmask SIGABRT to be sure we can get it */ + if (__sigemptyset(&sigs) == 0 && __sigaddset(&sigs, SIGABRT) == 0) { + sigprocmask(SIG_UNBLOCK, &sigs, (sigset_t *) NULL); + } + + while (1) { + /* Try to suicide with a SIGABRT */ + if (been_there_done_that == 0) { + been_there_done_that++; + +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) { + _stdio_term(); + } +#endif + +abort_it: + __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock); + raise(SIGABRT); + __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + } + + /* Still here? Try to remove any signal handlers */ + if (been_there_done_that == 1) { + struct sigaction act; + + been_there_done_that++; + memset(&act, '\0', sizeof(struct sigaction)); + act.sa_handler = SIG_DFL; + __sigfillset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGABRT, &act, NULL); + + goto abort_it; + } + + /* Still here? Try to suicide with an illegal instruction */ + if (been_there_done_that == 2) { + been_there_done_that++; + ABORT_INSTRUCTION; + } + + /* Still here? Try to at least exit */ + if (been_there_done_that == 3) { + been_there_done_that++; + _exit(127); + } + + /* Still here? We're screwed. Sleepy time. Good night. */ + while (1) + /* Try for ever and ever */ + ABORT_INSTRUCTION; + } +} +libc_hidden_def(abort) diff --git a/libc/stdlib/abs.c b/libc/stdlib/abs.c new file mode 100644 index 0000000..540c020 --- /dev/null +++ b/libc/stdlib/abs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_abs +#include "stdlib.c" diff --git a/libc/stdlib/arc4random.c b/libc/stdlib/arc4random.c new file mode 100644 index 0000000..bf6a4cd --- /dev/null +++ b/libc/stdlib/arc4random.c @@ -0,0 +1,210 @@ +/* $$$: arc4random.c 2005/02/08 robert */ +/* $NetBSD: arc4random.c,v 1.5.2.1 2004/03/26 22:52:50 jmc Exp $ */ +/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */ + +/* + * Arc4 random number generator for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +/* + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __ARC4RANDOM_USE_ERANDOM__ +#include +//libc_hidden_proto(sysctl) +#endif + +libc_hidden_proto(open) +libc_hidden_proto(read) +libc_hidden_proto(close) +libc_hidden_proto(gettimeofday) + +struct arc4_stream { + uint8_t i; + uint8_t j; + uint8_t s[256]; +}; + +static int rs_initialized; +static struct arc4_stream rs; + +static __inline__ void arc4_init(struct arc4_stream *); +static __inline__ void arc4_addrandom(struct arc4_stream *, u_char *, int); +static void arc4_stir(struct arc4_stream *); +static __inline__ uint8_t arc4_getbyte(struct arc4_stream *); +static __inline__ uint32_t arc4_getword(struct arc4_stream *); + +static __inline__ void +arc4_init(as) + struct arc4_stream *as; +{ + int n; + + for (n = 0; n < 256; n++) + as->s[n] = n; + as->i = 0; + as->j = 0; +} + +static __inline__ void +arc4_addrandom(as, dat, datlen) + struct arc4_stream *as; + u_char *dat; + int datlen; +{ + int n; + uint8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } + as->j = as->i; +} + +static void +arc4_stir(as) + struct arc4_stream *as; +{ + int fd; + struct { + struct timeval tv; + uint rnd[(128 - sizeof(struct timeval)) / sizeof(uint)]; + } rdat; + int n; + + gettimeofday(&rdat.tv, NULL); + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + read(fd, rdat.rnd, sizeof(rdat.rnd)); + close(fd); + } +#ifdef __ARC4RANDOM_USE_ERANDOM__ + else { + int mib[3]; + uint i; + size_t len; + + /* Device could not be opened, we might be chrooted, take + * randomness from sysctl. */ + + mib[0] = CTL_KERN; + mib[1] = KERN_RANDOM; + mib[2] = RANDOM_ERANDOM; + + for (i = 0; i < sizeof(rdat.rnd) / sizeof(uint); i++) { + len = sizeof(uint); + if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1) + break; + } + } +#endif + + arc4_addrandom(as, (void *) &rdat, sizeof(rdat)); + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + * N = 256 in our case. + */ + for (n = 0; n < 256 * 4; n++) + arc4_getbyte(as); +} + +static __inline__ uint8_t +arc4_getbyte(as) + struct arc4_stream *as; +{ + uint8_t si, sj; + + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +static __inline__ uint32_t +arc4_getword(as) + struct arc4_stream *as; +{ + uint32_t val; + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return val; +} + +libc_hidden_proto(arc4random_stir) +void +arc4random_stir(void) +{ + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} +libc_hidden_def(arc4random_stir) + +void +arc4random_addrandom(u_char *dat, int datlen) +{ + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +uint32_t +arc4random(void) +{ + if (!rs_initialized) + arc4random_stir(); + return arc4_getword(&rs); +} + +#if 0 +/*-------- Test code --------*/ +#include +#include + +int main(void) { + int random_number; + random_number = arc4random() % 65536; + printf("%d\n", random_number); + return 0; +} +#endif diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c new file mode 100644 index 0000000..158869e --- /dev/null +++ b/libc/stdlib/atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atexit +#include "_atexit.c" diff --git a/libc/stdlib/atof.c b/libc/stdlib/atof.c new file mode 100644 index 0000000..2fdd75c --- /dev/null +++ b/libc/stdlib/atof.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atof +#include "stdlib.c" diff --git a/libc/stdlib/atoi.c b/libc/stdlib/atoi.c new file mode 100644 index 0000000..61562bb --- /dev/null +++ b/libc/stdlib/atoi.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atoi +#include "stdlib.c" diff --git a/libc/stdlib/atol.c b/libc/stdlib/atol.c new file mode 100644 index 0000000..3e57720 --- /dev/null +++ b/libc/stdlib/atol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atol +#include "stdlib.c" diff --git a/libc/stdlib/atoll.c b/libc/stdlib/atoll.c new file mode 100644 index 0000000..f6b04a6 --- /dev/null +++ b/libc/stdlib/atoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atoll +#include "stdlib.c" diff --git a/libc/stdlib/bsd_getpt.c b/libc/stdlib/bsd_getpt.c new file mode 100644 index 0000000..1afd57f --- /dev/null +++ b/libc/stdlib/bsd_getpt.c @@ -0,0 +1,78 @@ +/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if defined __USE_BSD +libc_hidden_proto(open) +/* Experimentally off - libc_hidden_proto(mempcpy) */ + +/* Prefix for master pseudo terminal nodes. */ +#define _PATH_PTY "/dev/pty" + +/* Letters indicating a series of pseudo terminals. */ +#ifndef PTYNAME1 +#define PTYNAME1 "pqrsPQRS" +#endif +const char __libc_ptyname1[] attribute_hidden = PTYNAME1; + +/* Letters indicating the position within a series. */ +#ifndef PTYNAME2 +#define PTYNAME2 "0123456789abcdefghijklmnopqrstuv"; +#endif +const char __libc_ptyname2[] attribute_hidden = PTYNAME2; + +/* Open a master pseudo terminal and return its file descriptor. */ +int +__getpt (void) +{ + char buf[sizeof (_PATH_PTY) + 2]; + const char *p, *q; + char *s; + + s = mempcpy (buf, _PATH_PTY, sizeof (_PATH_PTY) - 1); + /* s[0] and s[1] will be filled in the loop. */ + s[2] = '\0'; + + for (p = __libc_ptyname1; *p != '\0'; ++p) + { + s[0] = *p; + + for (q = __libc_ptyname2; *q != '\0'; ++q) + { + int fd; + + s[1] = *q; + + fd = open (buf, O_RDWR); + if (fd != -1) + return fd; + + if (errno == ENOENT) + return -1; + } + } + + __set_errno (ENOENT); + return -1; +} +#endif /* __USE_BSD */ diff --git a/libc/stdlib/bsearch.c b/libc/stdlib/bsearch.c new file mode 100644 index 0000000..4feceef --- /dev/null +++ b/libc/stdlib/bsearch.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_bsearch +#include "stdlib.c" diff --git a/libc/stdlib/div.c b/libc/stdlib/div.c new file mode 100644 index 0000000..6c59595 --- /dev/null +++ b/libc/stdlib/div.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * div for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +div_t div(int numer, int denom) +{ + div_t result; + result.quot = numer / denom; + result.rem = numer - (result.quot * denom); + return(result); +} + diff --git a/libc/stdlib/drand48-iter.c b/libc/stdlib/drand48-iter.c new file mode 100644 index 0000000..221cbe0 --- /dev/null +++ b/libc/stdlib/drand48-iter.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Global state for non-reentrant functions. */ +struct drand48_data __libc_drand48_data attribute_hidden; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning turn int __drand48_iterate into void +#endif /* __UCLIBC_MJN3_ONLY__ */ +int __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer) attribute_hidden; +int __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer) +{ + uint64_t X; + uint64_t result; + + /* Initialize buffer, if not yet done. */ + if (unlikely(!buffer->__init)) + { + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + } + + /* Do the real work. We choose a data type which contains at least + 48 bits. Because we compute the modulus it does not care how + many bits really are computed. */ + + X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0]; + + result = X * buffer->__a + buffer->__c; + + xsubi[0] = result & 0xffff; + xsubi[1] = (result >> 16) & 0xffff; + xsubi[2] = (result >> 32) & 0xffff; + + return 0; +} diff --git a/libc/stdlib/drand48.c b/libc/stdlib/drand48.c new file mode 100644 index 0000000..f96947c --- /dev/null +++ b/libc/stdlib/drand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(erand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +double drand48 (void) +{ + double result; + + (void) erand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/drand48_r.c b/libc/stdlib/drand48_r.c new file mode 100644 index 0000000..1000a3a --- /dev/null +++ b/libc/stdlib/drand48_r.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(erand48_r) + +int drand48_r (struct drand48_data *buffer, double *result) +{ + return erand48_r (buffer->__x, buffer, result); +} diff --git a/libc/stdlib/erand48.c b/libc/stdlib/erand48.c new file mode 100644 index 0000000..853c2c3 --- /dev/null +++ b/libc/stdlib/erand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(erand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +double erand48 (unsigned short int xsubi[3]) +{ + double result; + + (void) erand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/erand48_r.c b/libc/stdlib/erand48_r.c new file mode 100644 index 0000000..42db6f7 --- /dev/null +++ b/libc/stdlib/erand48_r.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1995, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +libc_hidden_proto(erand48_r) +int erand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, double *result) +{ + union ieee754_double temp; + + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Construct a positive double with the 48 random bits distributed over + its fractional part so the resulting FP number is [0.0,1.0). */ + + temp.ieee.negative = 0; + temp.ieee.exponent = IEEE754_DOUBLE_BIAS; + temp.ieee.mantissa0 = (xsubi[2] << 4) | (xsubi[1] >> 12); + temp.ieee.mantissa1 = ((xsubi[1] & 0xfff) << 20) | (xsubi[0] << 4); + + /* Please note the lower 4 bits of mantissa1 are always 0. */ + *result = temp.d - 1.0; + + return 0; +} +libc_hidden_def(erand48_r) diff --git a/libc/stdlib/exit.c b/libc/stdlib/exit.c new file mode 100644 index 0000000..a2255d2 --- /dev/null +++ b/libc/stdlib/exit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_exit +#include "_atexit.c" diff --git a/libc/stdlib/gcvt.c b/libc/stdlib/gcvt.c new file mode 100644 index 0000000..f1c1f42 --- /dev/null +++ b/libc/stdlib/gcvt.c @@ -0,0 +1,13 @@ +#include +#include + +libc_hidden_proto(sprintf) + +#ifdef __UCLIBC_HAS_FLOATS__ +#define MAX_NDIGIT 17 +char *gcvt (double number, int ndigit, char *buf) +{ + sprintf(buf, "%.*g", (ndigit > MAX_NDIGIT)? MAX_NDIGIT : ndigit, number); + return buf; +} +#endif diff --git a/libc/stdlib/getenv.c b/libc/stdlib/getenv.c new file mode 100644 index 0000000..7b3df7e --- /dev/null +++ b/libc/stdlib/getenv.c @@ -0,0 +1,33 @@ +/* getenv.c for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(getenv) +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ + +/* IEEE Std 1003.1-2001 says getenv need not be thread safe, so + * don't bother locking access to __environ */ +char *getenv(const char *var) +{ + int len; + char **ep; + + if (!(ep=__environ)) + return NULL; + len = strlen(var); + while(*ep) { + if (memcmp(var, *ep, len) == 0 && (*ep)[len] == '=') { + return *ep + len + 1; + } + ep++; + } + return NULL; +} +libc_hidden_def(getenv) diff --git a/libc/stdlib/getpt.c b/libc/stdlib/getpt.c new file mode 100644 index 0000000..5b06743 --- /dev/null +++ b/libc/stdlib/getpt.c @@ -0,0 +1,135 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +extern __typeof(statfs) __libc_statfs; +libc_hidden_proto(__libc_statfs) + +libc_hidden_proto(open) +libc_hidden_proto(close) + +#if !defined __ASSUME_DEVPTS__ + +/* Constant that identifies the `devpts' filesystem. */ +# define DEVPTS_SUPER_MAGIC 0x1cd1 +/* Constant that identifies the `devfs' filesystem. */ +# define DEVFS_SUPER_MAGIC 0x1373 +#endif + +/* Path to the master pseudo terminal cloning device. */ +#define _PATH_DEVPTMX _PATH_DEV "ptmx" +/* Directory containing the UNIX98 pseudo terminals. */ +#define _PATH_DEVPTS _PATH_DEV "pts" + +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ +/* Prototype for function that opens BSD-style master pseudo-terminals. */ +extern int __bsd_getpt (void) attribute_hidden; +#endif + +/* Open a master pseudo terminal and return its file descriptor. */ +int +posix_openpt (int flags) +{ +#define have_no_dev_ptmx (1<<0) +#define devpts_mounted (1<<1) +#if !defined __UNIX98PTY_ONLY__ + static smallint _state; +#endif + int fd; + +#if !defined __UNIX98PTY_ONLY__ + if (!(_state & have_no_dev_ptmx)) +#endif + { + fd = open (_PATH_DEVPTMX, flags); + if (fd != -1) + { +#if defined __ASSUME_DEVPTS__ + return fd; +#else + struct statfs fsbuf; + + /* Check that the /dev/pts filesystem is mounted + or if /dev is a devfs filesystem (this implies /dev/pts). */ + if ( +#if !defined __UNIX98PTY_ONLY__ + (_state & devpts_mounted) || +#endif + (__libc_statfs (_PATH_DEVPTS, &fsbuf) == 0 + && fsbuf.f_type == DEVPTS_SUPER_MAGIC) + || (__libc_statfs (_PATH_DEV, &fsbuf) == 0 + && fsbuf.f_type == DEVFS_SUPER_MAGIC)) + { + /* Everything is ok. */ +#if !defined __UNIX98PTY_ONLY__ + _state |= devpts_mounted; +#endif + return fd; + } + + /* If /dev/pts is not mounted then the UNIX98 pseudo terminals + are not usable. */ + close (fd); +#if !defined __UNIX98PTY_ONLY__ + _state |= have_no_dev_ptmx; +#endif +#endif + } + else + { +#if !defined __UNIX98PTY_ONLY__ + if (errno == ENOENT || errno == ENODEV) + _state |= have_no_dev_ptmx; + else +#endif + return -1; + } + } +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ + /* If we have no ptmx then ignore flags and use the fallback. */ + if (_state & have_no_dev_ptmx) + return __bsd_getpt(); +#endif + return -1; +} +libc_hidden_def(posix_openpt) +#undef have_no_dev_ptmx +#undef devpts_mounted + +#if defined __USE_GNU && defined __UCLIBC_HAS_GETPT__ +int getpt (void) +{ + return posix_openpt(O_RDWR); +} + +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ +# define PTYNAME1 "pqrstuvwxyzabcde"; +# define PTYNAME2 "0123456789abcdef"; + +# define __getpt __bsd_getpt +# include "bsd_getpt.c" +#endif +#endif /* GNU && __UCLIBC_HAS_GETPT__ */ diff --git a/libc/stdlib/grantpt.c b/libc/stdlib/grantpt.c new file mode 100644 index 0000000..8c85850 --- /dev/null +++ b/libc/stdlib/grantpt.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* If __ASSUME_DEVPTS__ is defined, grantpt() reduces to a stub since we + assume that the devfs/devpts filesystem automatically manages the + permissions. */ +#if !defined __ASSUME_DEVPTS__ +#include + +/* Constant that identifies the `devpts' filesystem. */ +#define DEVPTS_SUPER_MAGIC 0x1cd1 +/* Constant that identifies the `devfs' filesystem. */ +#define DEVFS_SUPER_MAGIC 0x1373 + +/* Prototype for function that changes ownership and access permission + for slave pseudo terminals that do not live on a `devpts' + filesystem. */ +int __unix_grantpt (int fd); + +/* Prototype for private function that gets the name of the slave + pseudo terminal in a safe way. */ +static int pts_name (int fd, char **pts, size_t buf_len); +extern __typeof(statfs) __libc_statfs; +libc_hidden_proto(__libc_statfs) +#endif + +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ +int +#if !defined __ASSUME_DEVPTS__ +grantpt (int fd) +#else +grantpt (attribute_unused int fd) +#endif +{ +#if !defined __ASSUME_DEVPTS__ + struct statfs fsbuf; + char _buf[PATH_MAX]; + char *buf = _buf; + + if (pts_name (fd, &buf, sizeof (_buf))) + return -1; + + if (__libc_statfs (buf, &fsbuf) < 0) + return -1; + + /* If the slave pseudo terminal lives on a `devpts' filesystem, the + ownership and access permission are already set. */ + if (fsbuf.f_type != DEVPTS_SUPER_MAGIC && fsbuf.f_type != DEVFS_SUPER_MAGIC) + return __unix_grantpt (fd); +#endif + return 0; +} + +#if !defined __ASSUME_DEVPTS__ +# define grantpt __unix_grantpt +# include "unix_grantpt.c" +#endif diff --git a/libc/stdlib/jrand48.c b/libc/stdlib/jrand48.c new file mode 100644 index 0000000..6f81206 --- /dev/null +++ b/libc/stdlib/jrand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(jrand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int jrand48 (unsigned short int xsubi[3]) +{ + long int result; + + (void) jrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/jrand48_r.c b/libc/stdlib/jrand48_r.c new file mode 100644 index 0000000..fe77c3c --- /dev/null +++ b/libc/stdlib/jrand48_r.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +libc_hidden_proto(jrand48_r) +int jrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + *result = ((xsubi[2] << 16) | xsubi[1]) & 0xffffffffl; + + return 0; +} +libc_hidden_def(jrand48_r) diff --git a/libc/stdlib/l64a.c b/libc/stdlib/l64a.c new file mode 100644 index 0000000..a8b2d55 --- /dev/null +++ b/libc/stdlib/l64a.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Conversion table. */ +static const char conv_table[64] = +{ + '.', '/', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' +}; + +char * l64a (long int n) +{ + unsigned long int m = (unsigned long int) n; + static char result[7]; + int cnt; + + /* The standard says that only 32 bits are used. */ + m &= 0xffffffff; + + if (m == 0ul) + /* The value for N == 0 is defined to be the empty string. */ + return (char *) ""; + + for (cnt = 0; m > 0ul; ++cnt) + { + result[cnt] = conv_table[m & 0x3f]; + m >>= 6; + } + result[cnt] = '\0'; + + return result; +} diff --git a/libc/stdlib/labs.c b/libc/stdlib/labs.c new file mode 100644 index 0000000..95196af --- /dev/null +++ b/libc/stdlib/labs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_labs +#include "stdlib.c" diff --git a/libc/stdlib/ldiv.c b/libc/stdlib/ldiv.c new file mode 100644 index 0000000..88a8771 --- /dev/null +++ b/libc/stdlib/ldiv.c @@ -0,0 +1,61 @@ + +/* Copyright (C) 1992, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return the `ldiv_t' representation of NUMER over DENOM. */ +ldiv_t +ldiv (long int numer, long int denom) +{ + ldiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where + NUMER / DENOM is to be computed in infinite precision. In + other words, we should always truncate the quotient towards + zero, never -infinity. Machine division and remainer may + work either way when one or both of NUMER or DENOM is + negative. If only one is negative and QUOT has been + truncated towards -infinity, REM will have the same sign as + DENOM and the opposite sign of NUMER; if both are negative + and QUOT has been truncated towards -infinity, REM will be + positive (will have the opposite sign of NUMER). These are + considered `wrong'. If both are NUM and DENOM are positive, + RESULT will always be positive. This all boils down to: if + NUMER >= 0, but REM < 0, we got the wrong answer. In that + case, to get the right answer, add 1 to QUOT and subtract + DENOM from REM. */ + + if (numer >= 0 && result.rem < 0) + { + ++result.quot; + result.rem -= denom; + } + + return result; +} + +#if __WORDSIZE == 64 +#undef imaxdiv +strong_alias(ldiv,imaxdiv) +#endif diff --git a/libc/stdlib/llabs.c b/libc/stdlib/llabs.c new file mode 100644 index 0000000..17ec30a --- /dev/null +++ b/libc/stdlib/llabs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_llabs +#include "stdlib.c" diff --git a/libc/stdlib/lldiv.c b/libc/stdlib/lldiv.c new file mode 100644 index 0000000..ff67017 --- /dev/null +++ b/libc/stdlib/lldiv.c @@ -0,0 +1,61 @@ +/* `long long int' divison with remainder. + Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return the `lldiv_t' representation of NUMER over DENOM. */ +lldiv_t +lldiv (long long int numer, long long int denom) +{ + lldiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where + NUMER / DENOM is to be computed in infinite precision. In + other words, we should always truncate the quotient towards + zero, never -infinity. Machine division and remainer may + work either way when one or both of NUMER or DENOM is + negative. If only one is negative and QUOT has been + truncated towards -infinity, REM will have the same sign as + DENOM and the opposite sign of NUMER; if both are negative + and QUOT has been truncated towards -infinity, REM will be + positive (will have the opposite sign of NUMER). These are + considered `wrong'. If both are NUM and DENOM are positive, + RESULT will always be positive. This all boils down to: if + NUMER >= 0, but REM < 0, we got the wrong answer. In that + case, to get the right answer, add 1 to QUOT and subtract + DENOM from REM. */ + + if (numer >= 0 && result.rem < 0) + { + ++result.quot; + result.rem -= denom; + } + + return result; +} + +#if __WORDSIZE != 64 +#undef imaxdiv +strong_alias(lldiv,imaxdiv) +#endif diff --git a/libc/stdlib/lrand48.c b/libc/stdlib/lrand48.c new file mode 100644 index 0000000..863951f --- /dev/null +++ b/libc/stdlib/lrand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(nrand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int lrand48 (void) +{ + long int result; + + nrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/lrand48_r.c b/libc/stdlib/lrand48_r.c new file mode 100644 index 0000000..277fb9a --- /dev/null +++ b/libc/stdlib/lrand48_r.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(nrand48_r) + +libc_hidden_proto(lrand48_r) +int lrand48_r (struct drand48_data *buffer, long int *result) +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return nrand48_r (buffer->__x, buffer, result); +} +libc_hidden_def(lrand48_r) diff --git a/libc/stdlib/malloc-simple/Makefile b/libc/stdlib/malloc-simple/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/stdlib/malloc-simple/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/stdlib/malloc-simple/Makefile.in b/libc/stdlib/malloc-simple/Makefile.in new file mode 100644 index 0000000..4762d57 --- /dev/null +++ b/libc/stdlib/malloc-simple/Makefile.in @@ -0,0 +1,22 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +STDLIB_MALLOC_SIMPLE_DIR := $(top_srcdir)libc/stdlib/malloc-simple +STDLIB_MALLOC_SIMPLE_OUT := $(top_builddir)libc/stdlib/malloc-simple + +CSRC := $(notdir $(wildcard $(STDLIB_MALLOC_SIMPLE_DIR)/*.c)) +CSRC := $(filter-out alloc.c,$(CSRC)) + +STDLIB_MALLOC_SIMPLE_SRC := $(patsubst %.c,$(STDLIB_MALLOC_SIMPLE_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_SIMPLE_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_SIMPLE_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC_SIMPLE) += $(STDLIB_MALLOC_SIMPLE_OBJ) + +objclean-y += stdlib_malloc_simple_clean + +stdlib_malloc_simple_clean: + $(do_rm) $(addprefix $(STDLIB_MALLOC_SIMPLE_OUT)/*., o os) diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c new file mode 100644 index 0000000..45faf62 --- /dev/null +++ b/libc/stdlib/malloc-simple/alloc.c @@ -0,0 +1,190 @@ +/* alloc.c + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Parts of the memalign code were stolen from malloc-930716. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/*libc_hidden_proto(memset)*/ +libc_hidden_proto(mmap) +libc_hidden_proto(munmap) + +#ifdef L_malloc +void *malloc(size_t size) +{ + void *result; + + if (unlikely(size == 0)) { +#if defined(__MALLOC_GLIBC_COMPAT__) + size++; +#else + /* Some programs will call malloc (0). Lets be strict and return NULL */ + __set_errno(ENOMEM); + return NULL; +#endif + } + +#ifdef __ARCH_USE_MMU__ +# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS +#else +# define MMAP_FLAGS MAP_SHARED | MAP_ANONYMOUS +#endif + + result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, + MMAP_FLAGS, 0, 0); + if (result == MAP_FAILED) + return 0; + * (size_t *) result = size; + return(result + sizeof(size_t)); +} +#endif + +#ifdef L_calloc +void * calloc(size_t nmemb, size_t lsize) +{ + void *result; + size_t size=lsize * nmemb; + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + if (nmemb && lsize != (size / nmemb)) { + __set_errno(ENOMEM); + return NULL; + } + result=malloc(size); +#if 0 + /* Standard unix mmap using /dev/zero clears memory so calloc + * doesn't need to actually zero anything.... + */ + if (result != NULL) { + memset(result, 0, size); + } +#endif + return result; +} +#endif + +#ifdef L_realloc +void *realloc(void *ptr, size_t size) +{ + void *newptr = NULL; + + if (!ptr) + return malloc(size); + if (!size) { + free(ptr); + return malloc(0); + } + + newptr = malloc(size); + if (newptr) { + size_t old_size = *((size_t *) (ptr - sizeof(size_t))); + memcpy(newptr, ptr, (old_size < size ? old_size : size)); + free(ptr); + } + return newptr; +} +#endif + +#ifdef L_free +extern int weak_function __libc_free_aligned(void *ptr); +void free(void *ptr) +{ + if (unlikely(ptr == NULL)) + return; + if (unlikely(__libc_free_aligned != NULL)) { + if (__libc_free_aligned(ptr)) + return; + } + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); +} +#endif + +#ifdef L_memalign + +#include +__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + +/* List of blocks allocated with memalign or valloc */ +struct alignlist +{ + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ +}; +struct alignlist *_aligned_blocks; + +/* Return memory to the heap. */ +int __libc_free_aligned(void *ptr) +{ + struct alignlist *l; + + if (ptr == NULL) + return 0; + + __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ + l->aligned = NULL; + ptr = l->exact; + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); + return 1; + } + } + __MALLOC_UNLOCK; + return 0; +} +void * memalign (size_t alignment, size_t size) +{ + void * result; + unsigned long int adj; + + result = malloc (size + alignment - 1); + if (result == NULL) + return NULL; + + adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % alignment; + if (adj != 0) { + struct alignlist *l; + __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); + result = NULL; + goto DONE; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; +DONE: + __MALLOC_UNLOCK; + } + + return result; +} +#endif diff --git a/libc/stdlib/malloc-simple/calloc.c b/libc/stdlib/malloc-simple/calloc.c new file mode 100644 index 0000000..b404896 --- /dev/null +++ b/libc/stdlib/malloc-simple/calloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_calloc +#include "alloc.c" diff --git a/libc/stdlib/malloc-simple/free.c b/libc/stdlib/malloc-simple/free.c new file mode 100644 index 0000000..3fc7a96 --- /dev/null +++ b/libc/stdlib/malloc-simple/free.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_free +#include "alloc.c" diff --git a/libc/stdlib/malloc-simple/malloc.c b/libc/stdlib/malloc-simple/malloc.c new file mode 100644 index 0000000..1ad8ca2 --- /dev/null +++ b/libc/stdlib/malloc-simple/malloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_malloc +#include "alloc.c" diff --git a/libc/stdlib/malloc-simple/memalign.c b/libc/stdlib/malloc-simple/memalign.c new file mode 100644 index 0000000..d7ee352 --- /dev/null +++ b/libc/stdlib/malloc-simple/memalign.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_memalign +#include "alloc.c" diff --git a/libc/stdlib/malloc-simple/realloc.c b/libc/stdlib/malloc-simple/realloc.c new file mode 100644 index 0000000..b116ab1 --- /dev/null +++ b/libc/stdlib/malloc-simple/realloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_realloc +#include "alloc.c" diff --git a/libc/stdlib/malloc-standard/Makefile b/libc/stdlib/malloc-standard/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/stdlib/malloc-standard/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/stdlib/malloc-standard/Makefile.in b/libc/stdlib/malloc-standard/Makefile.in new file mode 100644 index 0000000..32884d1 --- /dev/null +++ b/libc/stdlib/malloc-standard/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# calloc.c can be found at uClibc/libc/stdlib/calloc.c +# valloc.c can be found at uClibc/libc/stdlib/valloc.c +CSRC := malloc.c calloc.c realloc.c free.c memalign.c mallopt.c mallinfo.c + +STDLIB_MALLOC_STANDARD_DIR := $(top_srcdir)libc/stdlib/malloc-standard +STDLIB_MALLOC_STANDARD_OUT := $(top_builddir)libc/stdlib/malloc-standard + +STDLIB_MALLOC_STANDARD_SRC := $(patsubst %.c,$(STDLIB_MALLOC_STANDARD_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_STANDARD_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_STANDARD_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC_STANDARD) += $(STDLIB_MALLOC_STANDARD_OBJ) + +objclean-y += stdlib_malloc_standard_clean + +stdlib_malloc_standard_clean: + $(do_rm) $(addprefix $(STDLIB_MALLOC_STANDARD_OUT)/*., o os) diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c new file mode 100644 index 0000000..80ba3d0 --- /dev/null +++ b/libc/stdlib/malloc-standard/calloc.c @@ -0,0 +1,94 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* ------------------------------ calloc ------------------------------ */ +void* calloc(size_t n_elements, size_t elem_size) +{ + mchunkptr p; + unsigned long clearsize; + unsigned long nclears; + size_t size, *d; + void* mem; + + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + size = n_elements * elem_size; + if (n_elements && elem_size != (size / n_elements)) { + __set_errno(ENOMEM); + return NULL; + } + + __MALLOC_LOCK; + mem = malloc(size); + if (mem != 0) { + p = mem2chunk(mem); + + if (!chunk_is_mmapped(p)) + { + /* + Unroll clear of <= 36 bytes (72 if 8byte sizes) + We know that contents have an odd number of + size_t-sized words; minimally 3. + */ + + d = (size_t*)mem; + clearsize = chunksize(p) - (sizeof(size_t)); + nclears = clearsize / sizeof(size_t); + assert(nclears >= 3); + + if (nclears > 9) + memset(d, 0, clearsize); + + else { + *(d+0) = 0; + *(d+1) = 0; + *(d+2) = 0; + if (nclears > 4) { + *(d+3) = 0; + *(d+4) = 0; + if (nclears > 6) { + *(d+5) = 0; + *(d+6) = 0; + if (nclears > 8) { + *(d+7) = 0; + *(d+8) = 0; + } + } + } + } + } +#if 0 + else + { + /* Standard unix mmap using /dev/zero clears memory so calloc + * doesn't need to actually zero anything.... + */ + d = (size_t*)mem; + /* Note the additional (sizeof(size_t)) */ + clearsize = chunksize(p) - 2*(sizeof(size_t)); + memset(d, 0, clearsize); + } +#endif + } + __MALLOC_UNLOCK; + return mem; +} + diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c new file mode 100644 index 0000000..4d24697 --- /dev/null +++ b/libc/stdlib/malloc-standard/free.c @@ -0,0 +1,411 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + +libc_hidden_proto(munmap) + +/* ------------------------- __malloc_trim ------------------------- + __malloc_trim is an inverse of sorts to __malloc_alloc. It gives memory + back to the system (via negative arguments to sbrk) if there is unused + memory at the `high' end of the malloc pool. It is called automatically by + free() when top space exceeds the trim threshold. It is also called by the + public malloc_trim routine. It returns 1 if it actually released any + memory, else 0. +*/ +static int __malloc_trim(size_t pad, mstate av) +{ + long top_size; /* Amount of top-most memory */ + long extra; /* Amount to release */ + long released; /* Amount actually released */ + char* current_brk; /* address returned by pre-check sbrk call */ + char* new_brk; /* address returned by post-check sbrk call */ + size_t pagesz; + + pagesz = av->pagesize; + top_size = chunksize(av->top); + + /* Release in pagesize units, keeping at least one page */ + extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz; + + if (extra > 0) { + + /* + Only proceed if end of memory is where we last set it. + This avoids problems if there were foreign sbrk calls. + */ + current_brk = (char*)(MORECORE(0)); + if (current_brk == (char*)(av->top) + top_size) { + + /* + Attempt to release memory. We ignore MORECORE return value, + and instead call again to find out where new end of memory is. + This avoids problems if first call releases less than we asked, + of if failure somehow altered brk value. (We could still + encounter problems if it altered brk in some very bad way, + but the only thing we can do is adjust anyway, which will cause + some downstream failure.) + */ + + MORECORE(-extra); + new_brk = (char*)(MORECORE(0)); + + if (new_brk != (char*)MORECORE_FAILURE) { + released = (long)(current_brk - new_brk); + + if (released != 0) { + /* Success. Adjust top. */ + av->sbrked_mem -= released; + set_head(av->top, (top_size - released) | PREV_INUSE); + check_malloc_state(); + return 1; + } + } + } + } + return 0; +} + +/* ------------------------- malloc_trim ------------------------- + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative + arguments to sbrk) if there is unused memory at the `high' end of + the malloc pool. You can call this after freeing large blocks of + memory to potentially reduce the system-level memory requirements + of a program. However, it cannot guarantee to reduce memory. Under + some allocation patterns, some large free blocks of memory will be + locked between two used chunks, so they cannot be given back to + the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, + only the minimum amount of memory to maintain internal data + structures will be left (one page or less). Non-zero arguments + can be supplied to maintain enough trailing space to service + future expected allocations without having to re-obtain memory + from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. + On systems that do not support "negative sbrks", it will always + return 0. +*/ +int malloc_trim(size_t pad) +{ + mstate av = get_malloc_state(); + __malloc_consolidate(av); + return __malloc_trim(pad, av); +} + +/* + Initialize a malloc_state struct. + + This is called only from within __malloc_consolidate, which needs + be called in the same contexts anyway. It is never called directly + outside of __malloc_consolidate because some optimizing compilers try + to inline it at all call points, which turns out not to be an + optimization at all. (Inlining it in __malloc_consolidate is fine though.) +*/ +static void malloc_init_state(mstate av) +{ + int i; + mbinptr bin; + + /* Establish circular links for normal bins */ + for (i = 1; i < NBINS; ++i) { + bin = bin_at(av,i); + bin->fd = bin->bk = bin; + } + + av->top_pad = DEFAULT_TOP_PAD; + av->n_mmaps_max = DEFAULT_MMAP_MAX; + av->mmap_threshold = DEFAULT_MMAP_THRESHOLD; + av->trim_threshold = DEFAULT_TRIM_THRESHOLD; + +#if MORECORE_CONTIGUOUS + set_contiguous(av); +#else + set_noncontiguous(av); +#endif + + + set_max_fast(av, DEFAULT_MXFAST); + + av->top = initial_top(av); + av->pagesize = malloc_getpagesize; +} + + +/* ---------------------------------------------------------------------- + * + * PUBLIC STUFF + * + * ----------------------------------------------------------------------*/ + + +/* ------------------------- __malloc_consolidate ------------------------- + + __malloc_consolidate is a specialized version of free() that tears + down chunks held in fastbins. Free itself cannot be used for this + purpose since, among other things, it might place chunks back onto + fastbins. So, instead, we need to use a minor variant of the same + code. + + Also, because this routine needs to be called the first time through + malloc anyway, it turns out to be the perfect place to trigger + initialization code. +*/ +void attribute_hidden __malloc_consolidate(mstate av) +{ + mfastbinptr* fb; /* current fastbin being consolidated */ + mfastbinptr* maxfb; /* last fastbin (for loop control) */ + mchunkptr p; /* current chunk being consolidated */ + mchunkptr nextp; /* next chunk to consolidate */ + mchunkptr unsorted_bin; /* bin header */ + mchunkptr first_unsorted; /* chunk to link to */ + + /* These have same use as in free() */ + mchunkptr nextchunk; + size_t size; + size_t nextsize; + size_t prevsize; + int nextinuse; + mchunkptr bck; + mchunkptr fwd; + + /* + If max_fast is 0, we know that av hasn't + yet been initialized, in which case do so below + */ + + if (av->max_fast != 0) { + clear_fastchunks(av); + + unsorted_bin = unsorted_chunks(av); + + /* + Remove each chunk from fast bin and consolidate it, placing it + then in unsorted bin. Among other reasons for doing this, + placing in unsorted bin avoids needing to calculate actual bins + until malloc is sure that chunks aren't immediately going to be + reused anyway. + */ + + maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); + fb = &(av->fastbins[0]); + do { + if ( (p = *fb) != 0) { + *fb = 0; + + do { + check_inuse_chunk(p); + nextp = p->fd; + + /* Slightly streamlined version of consolidation code in free() */ + size = p->size & ~PREV_INUSE; + nextchunk = chunk_at_offset(p, size); + nextsize = chunksize(nextchunk); + + if (!prev_inuse(p)) { + prevsize = p->prev_size; + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); + unlink(p, bck, fwd); + } + + if (nextchunk != av->top) { + nextinuse = inuse_bit_at_offset(nextchunk, nextsize); + set_head(nextchunk, nextsize); + + if (!nextinuse) { + size += nextsize; + unlink(nextchunk, bck, fwd); + } + + first_unsorted = unsorted_bin->fd; + unsorted_bin->fd = p; + first_unsorted->bk = p; + + set_head(p, size | PREV_INUSE); + p->bk = unsorted_bin; + p->fd = first_unsorted; + set_foot(p, size); + } + + else { + size += nextsize; + set_head(p, size | PREV_INUSE); + av->top = p; + } + + } while ( (p = nextp) != 0); + + } + } while (fb++ != maxfb); + } + else { + malloc_init_state(av); + check_malloc_state(); + } +} + + +/* ------------------------------ free ------------------------------ */ +void free(void* mem) +{ + mstate av; + + mchunkptr p; /* chunk corresponding to mem */ + size_t size; /* its size */ + mfastbinptr* fb; /* associated fastbin */ + mchunkptr nextchunk; /* next contiguous chunk */ + size_t nextsize; /* its size */ + int nextinuse; /* true if nextchunk is used */ + size_t prevsize; /* size of previous contiguous chunk */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + + /* free(0) has no effect */ + if (mem == NULL) + return; + + __MALLOC_LOCK; + av = get_malloc_state(); + p = mem2chunk(mem); + size = chunksize(p); + + check_inuse_chunk(p); + + /* + If eligible, place chunk on a fastbin so it can be found + and used quickly in malloc. + */ + + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) + +#if TRIM_FASTBINS + /* If TRIM_FASTBINS set, don't place chunks + bordering top into fastbins */ + && (chunk_at_offset(p, size) != av->top) +#endif + ) { + + set_fastchunks(av); + fb = &(av->fastbins[fastbin_index(size)]); + p->fd = *fb; + *fb = p; + } + + /* + Consolidate other non-mmapped chunks as they arrive. + */ + + else if (!chunk_is_mmapped(p)) { + set_anychunks(av); + + nextchunk = chunk_at_offset(p, size); + nextsize = chunksize(nextchunk); + + /* consolidate backward */ + if (!prev_inuse(p)) { + prevsize = p->prev_size; + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); + unlink(p, bck, fwd); + } + + if (nextchunk != av->top) { + /* get and clear inuse bit */ + nextinuse = inuse_bit_at_offset(nextchunk, nextsize); + set_head(nextchunk, nextsize); + + /* consolidate forward */ + if (!nextinuse) { + unlink(nextchunk, bck, fwd); + size += nextsize; + } + + /* + Place the chunk in unsorted chunk list. Chunks are + not placed into regular bins until after they have + been given one chance to be used in malloc. + */ + + bck = unsorted_chunks(av); + fwd = bck->fd; + p->bk = bck; + p->fd = fwd; + bck->fd = p; + fwd->bk = p; + + set_head(p, size | PREV_INUSE); + set_foot(p, size); + + check_free_chunk(p); + } + + /* + If the chunk borders the current high end of memory, + consolidate into top + */ + + else { + size += nextsize; + set_head(p, size | PREV_INUSE); + av->top = p; + check_chunk(p); + } + + /* + If freeing a large space, consolidate possibly-surrounding + chunks. Then, if the total unused topmost memory exceeds trim + threshold, ask malloc_trim to reduce top. + + Unless max_fast is 0, we don't know if there are fastbins + bordering top, so we cannot tell for sure whether threshold + has been reached unless fastbins are consolidated. But we + don't want to consolidate on each free. As a compromise, + consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD + is reached. + */ + + if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { + if (have_fastchunks(av)) + __malloc_consolidate(av); + + if ((unsigned long)(chunksize(av->top)) >= + (unsigned long)(av->trim_threshold)) + __malloc_trim(av->top_pad, av); + } + + } + /* + If the chunk was allocated via mmap, release via munmap() + Note that if HAVE_MMAP is false but chunk_is_mmapped is + true, then user must have overwritten memory. There's nothing + we can do to catch this error unless DEBUG is set, in which case + check_inuse_chunk (above) will have triggered error. + */ + + else { + size_t offset = p->prev_size; + av->n_mmaps--; + av->mmapped_mem -= (size + offset); + munmap((char*)p - offset, size + offset); + } + __MALLOC_UNLOCK; +} + diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c new file mode 100644 index 0000000..1833101 --- /dev/null +++ b/libc/stdlib/malloc-standard/mallinfo.c @@ -0,0 +1,126 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + +libc_hidden_proto(fprintf) + +/* ------------------------------ mallinfo ------------------------------ */ +libc_hidden_proto(mallinfo) +struct mallinfo mallinfo(void) +{ + mstate av; + struct mallinfo mi; + unsigned int i; + mbinptr b; + mchunkptr p; + size_t avail; + size_t fastavail; + int nblocks; + int nfastblocks; + + __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization */ + if (av->top == 0) { + __malloc_consolidate(av); + } + + check_malloc_state(); + + /* Account for top */ + avail = chunksize(av->top); + nblocks = 1; /* top always exists */ + + /* traverse fastbins */ + nfastblocks = 0; + fastavail = 0; + + for (i = 0; i < NFASTBINS; ++i) { + for (p = av->fastbins[i]; p != 0; p = p->fd) { + ++nfastblocks; + fastavail += chunksize(p); + } + } + + avail += fastavail; + + /* traverse regular bins */ + for (i = 1; i < NBINS; ++i) { + b = bin_at(av, i); + for (p = last(b); p != b; p = p->bk) { + ++nblocks; + avail += chunksize(p); + } + } + + mi.smblks = nfastblocks; + mi.ordblks = nblocks; + mi.fordblks = avail; + mi.uordblks = av->sbrked_mem - avail; + mi.arena = av->sbrked_mem; + mi.hblks = av->n_mmaps; + mi.hblkhd = av->mmapped_mem; + mi.fsmblks = fastavail; + mi.keepcost = chunksize(av->top); + mi.usmblks = av->max_total_mem; + __MALLOC_UNLOCK; + return mi; +} +libc_hidden_def(mallinfo) + +void malloc_stats(FILE *file) +{ + struct mallinfo mi; + + if (file==NULL) { + file = stderr; + } + + mi = mallinfo(); + fprintf(file, + "total bytes allocated = %10u\n" + "total bytes in use bytes = %10u\n" + "total non-mmapped bytes allocated = %10d\n" + "number of mmapped regions = %10d\n" + "total allocated mmap space = %10d\n" + "total allocated sbrk space = %10d\n" +#if 0 + "number of free chunks = %10d\n" + "number of fastbin blocks = %10d\n" + "space in freed fastbin blocks = %10d\n" +#endif + "maximum total allocated space = %10d\n" + "total free space = %10d\n" + "memory releasable via malloc_trim = %10d\n", + + (unsigned int)(mi.arena + mi.hblkhd), + (unsigned int)(mi.uordblks + mi.hblkhd), + mi.arena, + mi.hblks, + mi.hblkhd, + mi.uordblks, +#if 0 + mi.ordblks, + mi.smblks, + mi.fsmblks, +#endif + mi.usmblks, + mi.fordblks, + mi.keepcost + ); +} + diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c new file mode 100644 index 0000000..3253ebd --- /dev/null +++ b/libc/stdlib/malloc-standard/malloc.c @@ -0,0 +1,1167 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +/* + There is exactly one instance of this struct in this malloc. + If you are adapting this malloc in a way that does NOT use a static + malloc_state, you MUST explicitly zero-fill it before using. This + malloc relies on the property that malloc_state is initialized to + all zeroes (as is true of C statics). +*/ +struct malloc_state __malloc_state; /* never directly referenced */ + +/* forward declaration */ +static int __malloc_largebin_index(unsigned int sz); + +#ifdef __UCLIBC_MALLOC_DEBUGGING__ + +/* + Debugging support + + Because freed chunks may be overwritten with bookkeeping fields, this + malloc will often die when freed memory is overwritten by user + programs. This can be very effective (albeit in an annoying way) + in helping track down dangling pointers. + + If you compile with __UCLIBC_MALLOC_DEBUGGING__, a number of assertion checks are + enabled that will catch more memory errors. You probably won't be + able to make much sense of the actual assertion errors, but they + should help you locate incorrectly overwritten memory. The + checking is fairly extensive, and will slow down execution + noticeably. Calling malloc_stats or mallinfo with __UCLIBC_MALLOC_DEBUGGING__ set will + attempt to check every non-mmapped allocated and free chunk in the + course of computing the summmaries. (By nature, mmapped regions + cannot be checked very much automatically.) + + Setting __UCLIBC_MALLOC_DEBUGGING__ may also be helpful if you are trying to modify + this code. The assertions in the check routines spell out in more + detail the assumptions and invariants underlying the algorithms. + + Setting __UCLIBC_MALLOC_DEBUGGING__ does NOT provide an automated mechanism for checking + that all accesses to malloced memory stay within their + bounds. However, there are several add-ons and adaptations of this + or other mallocs available that do this. +*/ + +/* Properties of all chunks */ +void __do_check_chunk(mchunkptr p) +{ + mstate av = get_malloc_state(); +#ifdef __DOASSERTS__ + /* min and max possible addresses assuming contiguous allocation */ + char* max_address = (char*)(av->top) + chunksize(av->top); + char* min_address = max_address - av->sbrked_mem; + unsigned long sz = chunksize(p); +#endif + + if (!chunk_is_mmapped(p)) { + + /* Has legal address ... */ + if (p != av->top) { + if (contiguous(av)) { + assert(((char*)p) >= min_address); + assert(((char*)p + sz) <= ((char*)(av->top))); + } + } + else { + /* top size is always at least MINSIZE */ + assert((unsigned long)(sz) >= MINSIZE); + /* top predecessor always marked inuse */ + assert(prev_inuse(p)); + } + + } + else { + /* address is outside main heap */ + if (contiguous(av) && av->top != initial_top(av)) { + assert(((char*)p) < min_address || ((char*)p) > max_address); + } + /* chunk is page-aligned */ + assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); + /* mem is aligned */ + assert(aligned_OK(chunk2mem(p))); + } +} + +/* Properties of free chunks */ +void __do_check_free_chunk(mchunkptr p) +{ + size_t sz = p->size & ~PREV_INUSE; +#ifdef __DOASSERTS__ + mstate av = get_malloc_state(); + mchunkptr next = chunk_at_offset(p, sz); +#endif + + __do_check_chunk(p); + + /* Chunk must claim to be free ... */ + assert(!inuse(p)); + assert (!chunk_is_mmapped(p)); + + /* Unless a special marker, must have OK fields */ + if ((unsigned long)(sz) >= MINSIZE) + { + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert(aligned_OK(chunk2mem(p))); + /* ... matching footer field */ + assert(next->prev_size == sz); + /* ... and is fully consolidated */ + assert(prev_inuse(p)); + assert (next == av->top || inuse(next)); + + /* ... and has minimally sane links */ + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size (sizeof(size_t)) */ + assert(sz == (sizeof(size_t))); +} + +/* Properties of inuse chunks */ +void __do_check_inuse_chunk(mchunkptr p) +{ + mstate av = get_malloc_state(); + mchunkptr next; + __do_check_chunk(p); + + if (chunk_is_mmapped(p)) + return; /* mmapped chunks have no next/prev */ + + /* Check whether it claims to be in use ... */ + assert(inuse(p)); + + next = next_chunk(p); + + /* ... and is surrounded by OK chunks. + Since more things can be checked with free chunks than inuse ones, + if an inuse chunk borders them and debug is on, it's worth doing them. + */ + if (!prev_inuse(p)) { + /* Note that we cannot even look at prev unless it is not inuse */ + mchunkptr prv = prev_chunk(p); + assert(next_chunk(prv) == p); + __do_check_free_chunk(prv); + } + + if (next == av->top) { + assert(prev_inuse(next)); + assert(chunksize(next) >= MINSIZE); + } + else if (!inuse(next)) + __do_check_free_chunk(next); +} + +/* Properties of chunks recycled from fastbins */ +void __do_check_remalloced_chunk(mchunkptr p, size_t s) +{ +#ifdef __DOASSERTS__ + size_t sz = p->size & ~PREV_INUSE; +#endif + + __do_check_inuse_chunk(p); + + /* Legal size ... */ + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert((unsigned long)(sz) >= MINSIZE); + /* ... and alignment */ + assert(aligned_OK(chunk2mem(p))); + /* chunk is less than MINSIZE more than request */ + assert((long)(sz) - (long)(s) >= 0); + assert((long)(sz) - (long)(s + MINSIZE) < 0); +} + +/* Properties of nonrecycled chunks at the point they are malloced */ +void __do_check_malloced_chunk(mchunkptr p, size_t s) +{ + /* same as recycled case ... */ + __do_check_remalloced_chunk(p, s); + + /* + ... plus, must obey implementation invariant that prev_inuse is + always true of any allocated chunk; i.e., that each allocated + chunk borders either a previously allocated and still in-use + chunk, or the base of its memory arena. This is ensured + by making all allocations from the the `lowest' part of any found + chunk. This does not necessarily hold however for chunks + recycled via fastbins. + */ + + assert(prev_inuse(p)); +} + + +/* + Properties of malloc_state. + + This may be useful for debugging malloc, as well as detecting user + programmer errors that somehow write into malloc_state. + + If you are extending or experimenting with this malloc, you can + probably figure out how to hack this routine to print out or + display chunk addresses, sizes, bins, and other instrumentation. +*/ +void __do_check_malloc_state(void) +{ + mstate av = get_malloc_state(); + int i; + mchunkptr p; + mchunkptr q; + mbinptr b; + unsigned int binbit; + int empty; + unsigned int idx; + size_t size; + unsigned long total = 0; + int max_fast_bin; + + /* internal size_t must be no wider than pointer type */ + assert(sizeof(size_t) <= sizeof(char*)); + + /* alignment is a power of 2 */ + assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0); + + /* cannot run remaining checks until fully initialized */ + if (av->top == 0 || av->top == initial_top(av)) + return; + + /* pagesize is a power of 2 */ + assert((av->pagesize & (av->pagesize-1)) == 0); + + /* properties of fastbins */ + + /* max_fast is in allowed range */ + assert(get_max_fast(av) <= request2size(MAX_FAST_SIZE)); + + max_fast_bin = fastbin_index(av->max_fast); + + for (i = 0; i < NFASTBINS; ++i) { + p = av->fastbins[i]; + + /* all bins past max_fast are empty */ + if (i > max_fast_bin) + assert(p == 0); + + while (p != 0) { + /* each chunk claims to be inuse */ + __do_check_inuse_chunk(p); + total += chunksize(p); + /* chunk belongs in this bin */ + assert(fastbin_index(chunksize(p)) == i); + p = p->fd; + } + } + + if (total != 0) + assert(have_fastchunks(av)); + else if (!have_fastchunks(av)) + assert(total == 0); + + /* check normal bins */ + for (i = 1; i < NBINS; ++i) { + b = bin_at(av,i); + + /* binmap is accurate (except for bin 1 == unsorted_chunks) */ + if (i >= 2) { + binbit = get_binmap(av,i); + empty = last(b) == b; + if (!binbit) + assert(empty); + else if (!empty) + assert(binbit); + } + + for (p = last(b); p != b; p = p->bk) { + /* each chunk claims to be free */ + __do_check_free_chunk(p); + size = chunksize(p); + total += size; + if (i >= 2) { + /* chunk belongs in bin */ + idx = bin_index(size); + assert(idx == i); + /* lists are sorted */ + if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { + assert(p->bk == b || + (unsigned long)chunksize(p->bk) >= + (unsigned long)chunksize(p)); + } + } + /* chunk is followed by a legal chain of inuse chunks */ + for (q = next_chunk(p); + (q != av->top && inuse(q) && + (unsigned long)(chunksize(q)) >= MINSIZE); + q = next_chunk(q)) + __do_check_inuse_chunk(q); + } + } + + /* top chunk is OK */ + __do_check_chunk(av->top); + + /* sanity checks for statistics */ + + assert(total <= (unsigned long)(av->max_total_mem)); + assert(av->n_mmaps >= 0); + assert(av->n_mmaps <= av->max_n_mmaps); + + assert((unsigned long)(av->sbrked_mem) <= + (unsigned long)(av->max_sbrked_mem)); + + assert((unsigned long)(av->mmapped_mem) <= + (unsigned long)(av->max_mmapped_mem)); + + assert((unsigned long)(av->max_total_mem) >= + (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); +} +#endif + + +/* ----------- Routines dealing with system allocation -------------- */ + +/* + sysmalloc handles malloc cases requiring more memory from the system. + On entry, it is assumed that av->top does not have enough + space to service request for nb bytes, thus requiring that av->top + be extended or replaced. +*/ +static void* __malloc_alloc(size_t nb, mstate av) +{ + mchunkptr old_top; /* incoming value of av->top */ + size_t old_size; /* its size */ + char* old_end; /* its end address */ + + long size; /* arg to first MORECORE or mmap call */ + char* fst_brk; /* return value from MORECORE */ + + long correction; /* arg to 2nd MORECORE call */ + char* snd_brk; /* 2nd return val */ + + size_t front_misalign; /* unusable bytes at front of new space */ + size_t end_misalign; /* partial page left at end of new space */ + char* aligned_brk; /* aligned offset into brk */ + + mchunkptr p; /* the allocated/returned chunk */ + mchunkptr remainder; /* remainder from allocation */ + unsigned long remainder_size; /* its size */ + + unsigned long sum; /* for updating stats */ + + size_t pagemask = av->pagesize - 1; + + /* + If there is space available in fastbins, consolidate and retry + malloc from scratch rather than getting memory from system. This + can occur only if nb is in smallbin range so we didn't consolidate + upon entry to malloc. It is much easier to handle this case here + than in malloc proper. + */ + + if (have_fastchunks(av)) { + assert(in_smallbin_range(nb)); + __malloc_consolidate(av); + return malloc(nb - MALLOC_ALIGN_MASK); + } + + + /* + If have mmap, and the request size meets the mmap threshold, and + the system supports mmap, and there are few enough currently + allocated mmapped regions, try to directly map this request + rather than expanding top. + */ + + if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) && + (av->n_mmaps < av->n_mmaps_max)) { + + char* mm; /* return value from mmap call*/ + + /* + Round up size to nearest page. For mmapped chunks, the overhead + is one (sizeof(size_t)) unit larger than for normal chunks, because there + is no following chunk whose prev_size field could be used. + */ + size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; + + /* Don't try if size wraps around 0 */ + if ((unsigned long)(size) > (unsigned long)(nb)) { + + mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); + + if (mm != (char*)(MORECORE_FAILURE)) { + + /* + The offset to the start of the mmapped region is stored + in the prev_size field of the chunk. This allows us to adjust + returned start address to meet alignment requirements here + and in memalign(), and still be able to compute proper + address argument for later munmap in free() and realloc(). + */ + + front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + correction = MALLOC_ALIGNMENT - front_misalign; + p = (mchunkptr)(mm + correction); + p->prev_size = correction; + set_head(p, (size - correction) |IS_MMAPPED); + } + else { + p = (mchunkptr)mm; + p->prev_size = 0; + set_head(p, size|IS_MMAPPED); + } + + /* update statistics */ + + if (++av->n_mmaps > av->max_n_mmaps) + av->max_n_mmaps = av->n_mmaps; + + sum = av->mmapped_mem += size; + if (sum > (unsigned long)(av->max_mmapped_mem)) + av->max_mmapped_mem = sum; + sum += av->sbrked_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + check_chunk(p); + + return chunk2mem(p); + } + } + } + + /* Record incoming configuration of top */ + + old_top = av->top; + old_size = chunksize(old_top); + old_end = (char*)(chunk_at_offset(old_top, old_size)); + + fst_brk = snd_brk = (char*)(MORECORE_FAILURE); + + /* If not the first time through, we require old_size to + * be at least MINSIZE and to have prev_inuse set. */ + + assert((old_top == initial_top(av) && old_size == 0) || + ((unsigned long) (old_size) >= MINSIZE && + prev_inuse(old_top))); + + /* Precondition: not enough current space to satisfy nb request */ + assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE)); + + /* Precondition: all fastbins are consolidated */ + assert(!have_fastchunks(av)); + + + /* Request enough space for nb + pad + overhead */ + + size = nb + av->top_pad + MINSIZE; + + /* + If contiguous, we can subtract out existing space that we hope to + combine with new space. We add it back later only if + we don't actually get contiguous space. + */ + + if (contiguous(av)) + size -= old_size; + + /* + Round to a multiple of page size. + If MORECORE is not contiguous, this ensures that we only call it + with whole-page arguments. And if MORECORE is contiguous and + this is not first time through, this preserves page-alignment of + previous calls. Otherwise, we correct to page-align below. + */ + + size = (size + pagemask) & ~pagemask; + + /* + Don't try to call MORECORE if argument is so big as to appear + negative. Note that since mmap takes size_t arg, it may succeed + below even if we cannot call MORECORE. + */ + + if (size > 0) + fst_brk = (char*)(MORECORE(size)); + + /* + If have mmap, try using it as a backup when MORECORE fails or + cannot be used. This is worth doing on systems that have "holes" in + address space, so sbrk cannot extend to give contiguous space, but + space is available elsewhere. Note that we ignore mmap max count + and threshold limits, since the space will not be used as a + segregated mmap region. + */ + + if (fst_brk == (char*)(MORECORE_FAILURE)) { + + /* Cannot merge with old top, so add its size back in */ + if (contiguous(av)) + size = (size + old_size + pagemask) & ~pagemask; + + /* If we are relying on mmap as backup, then use larger units */ + if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) + size = MMAP_AS_MORECORE_SIZE; + + /* Don't try if size wraps around 0 */ + if ((unsigned long)(size) > (unsigned long)(nb)) { + + fst_brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); + + if (fst_brk != (char*)(MORECORE_FAILURE)) { + + /* We do not need, and cannot use, another sbrk call to find end */ + snd_brk = fst_brk + size; + + /* Record that we no longer have a contiguous sbrk region. + After the first time mmap is used as backup, we do not + ever rely on contiguous space since this could incorrectly + bridge regions. + */ + set_noncontiguous(av); + } + } + } + + if (fst_brk != (char*)(MORECORE_FAILURE)) { + av->sbrked_mem += size; + + /* + If MORECORE extends previous space, we can likewise extend top size. + */ + + if (fst_brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { + set_head(old_top, (size + old_size) | PREV_INUSE); + } + + /* + Otherwise, make adjustments: + + * If the first time through or noncontiguous, we need to call sbrk + just to find out where the end of memory lies. + + * We need to ensure that all returned chunks from malloc will meet + MALLOC_ALIGNMENT + + * If there was an intervening foreign sbrk, we need to adjust sbrk + request size to account for fact that we will not be able to + combine new space with existing space in old_top. + + * Almost all systems internally allocate whole pages at a time, in + which case we might as well use the whole last page of request. + So we allocate enough more memory to hit a page boundary now, + which in turn causes future contiguous calls to page-align. + */ + + else { + front_misalign = 0; + end_misalign = 0; + correction = 0; + aligned_brk = fst_brk; + + /* + If MORECORE returns an address lower than we have seen before, + we know it isn't really contiguous. This and some subsequent + checks help cope with non-conforming MORECORE functions and + the presence of "foreign" calls to MORECORE from outside of + malloc or by other threads. We cannot guarantee to detect + these in all cases, but cope with the ones we do detect. + */ + if (contiguous(av) && old_size != 0 && fst_brk < old_end) { + set_noncontiguous(av); + } + + /* handle contiguous cases */ + if (contiguous(av)) { + + /* We can tolerate forward non-contiguities here (usually due + to foreign calls) but treat them as part of our space for + stats reporting. */ + if (old_size != 0) + av->sbrked_mem += fst_brk - old_end; + + /* Guarantee alignment of first new chunk made from this space */ + + front_misalign = (size_t)chunk2mem(fst_brk) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + + /* + Skip over some bytes to arrive at an aligned position. + We don't need to specially mark these wasted front bytes. + They will never be accessed anyway because + prev_inuse of av->top (and any chunk created from its start) + is always true after initialization. + */ + + correction = MALLOC_ALIGNMENT - front_misalign; + aligned_brk += correction; + } + + /* + If this isn't adjacent to existing space, then we will not + be able to merge with old_top space, so must add to 2nd request. + */ + + correction += old_size; + + /* Extend the end address to hit a page boundary */ + end_misalign = (size_t)(fst_brk + size + correction); + correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; + + assert(correction >= 0); + snd_brk = (char*)(MORECORE(correction)); + + if (snd_brk == (char*)(MORECORE_FAILURE)) { + /* + If can't allocate correction, try to at least find out current + brk. It might be enough to proceed without failing. + */ + correction = 0; + snd_brk = (char*)(MORECORE(0)); + } + else if (snd_brk < fst_brk) { + /* + If the second call gives noncontiguous space even though + it says it won't, the only course of action is to ignore + results of second call, and conservatively estimate where + the first call left us. Also set noncontiguous, so this + won't happen again, leaving at most one hole. + + Note that this check is intrinsically incomplete. Because + MORECORE is allowed to give more space than we ask for, + there is no reliable way to detect a noncontiguity + producing a forward gap for the second call. + */ + snd_brk = fst_brk + size; + correction = 0; + set_noncontiguous(av); + } + + } + + /* handle non-contiguous cases */ + else { + /* MORECORE/mmap must correctly align */ + assert(aligned_OK(chunk2mem(fst_brk))); + + /* Find out current end of memory */ + if (snd_brk == (char*)(MORECORE_FAILURE)) { + snd_brk = (char*)(MORECORE(0)); + av->sbrked_mem += snd_brk - fst_brk - size; + } + } + + /* Adjust top based on results of second sbrk */ + if (snd_brk != (char*)(MORECORE_FAILURE)) { + av->top = (mchunkptr)aligned_brk; + set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); + av->sbrked_mem += correction; + + /* + If not the first time through, we either have a + gap due to foreign sbrk or a non-contiguous region. Insert a + double fencepost at old_top to prevent consolidation with space + we don't own. These fenceposts are artificial chunks that are + marked as inuse and are in any case too small to use. We need + two to make sizes and alignments work out. + */ + + if (old_size != 0) { + /* Shrink old_top to insert fenceposts, keeping size a + multiple of MALLOC_ALIGNMENT. We know there is at least + enough space in old_top to do this. + */ + old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; + set_head(old_top, old_size | PREV_INUSE); + + /* + Note that the following assignments completely overwrite + old_top when old_size was previously MINSIZE. This is + intentional. We need the fencepost, even if old_top otherwise gets + lost. + */ + chunk_at_offset(old_top, old_size )->size = + (sizeof(size_t))|PREV_INUSE; + + chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = + (sizeof(size_t))|PREV_INUSE; + + /* If possible, release the rest, suppressing trimming. */ + if (old_size >= MINSIZE) { + size_t tt = av->trim_threshold; + av->trim_threshold = (size_t)(-1); + free(chunk2mem(old_top)); + av->trim_threshold = tt; + } + } + } + } + + /* Update statistics */ + sum = av->sbrked_mem; + if (sum > (unsigned long)(av->max_sbrked_mem)) + av->max_sbrked_mem = sum; + + sum += av->mmapped_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + check_malloc_state(); + + /* finally, do the allocation */ + + p = av->top; + size = chunksize(p); + + /* check that one of the above allocation paths succeeded */ + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(p, nb); + av->top = remainder; + set_head(p, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + check_malloced_chunk(p, nb); + return chunk2mem(p); + } + + } + + /* catch all failure paths */ + errno = ENOMEM; + return 0; +} + + +/* + Compute index for size. We expect this to be inlined when + compiled with optimization, else not, which works out well. +*/ +static int __malloc_largebin_index(unsigned int sz) +{ + unsigned int x = sz >> SMALLBIN_WIDTH; + unsigned int m; /* bit position of highest set bit of m */ + + if (x >= 0x10000) return NBINS-1; + + /* On intel, use BSRL instruction to find highest bit */ +#if defined(__GNUC__) && defined(i386) + + __asm__("bsrl %1,%0\n\t" + : "=r" (m) + : "g" (x)); + +#else + { + /* + Based on branch-free nlz algorithm in chapter 5 of Henry + S. Warren Jr's book "Hacker's Delight". + */ + + unsigned int n = ((x - 0x100) >> 16) & 8; + x <<= n; + m = ((x - 0x1000) >> 16) & 4; + n += m; + x <<= m; + m = ((x - 0x4000) >> 16) & 2; + n += m; + x = (x << m) >> 14; + m = 13 - n + (x & ~(x>>1)); + } +#endif + + /* Use next 2 bits to create finer-granularity bins */ + return NSMALLBINS + (m << 2) + ((sz >> (m + 6)) & 3); +} + + + +/* ---------------------------------------------------------------------- + * + * PUBLIC STUFF + * + * ----------------------------------------------------------------------*/ + + +/* ------------------------------ malloc ------------------------------ */ +void* malloc(size_t bytes) +{ + mstate av; + + size_t nb; /* normalized request size */ + unsigned int idx; /* associated bin index */ + mbinptr bin; /* associated bin */ + mfastbinptr* fb; /* associated fastbin */ + + mchunkptr victim; /* inspected/selected chunk */ + size_t size; /* its size */ + int victim_index; /* its bin index */ + + mchunkptr remainder; /* remainder from a split */ + unsigned long remainder_size; /* its size */ + + unsigned int block; /* bit map traverser */ + unsigned int bit; /* bit map traverser */ + unsigned int map; /* current word of binmap */ + + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + void * sysmem; + void * retval; + +#if !defined(__MALLOC_GLIBC_COMPAT__) + if (!bytes) { + __set_errno(ENOMEM); + return NULL; + } +#endif + + __MALLOC_LOCK; + av = get_malloc_state(); + /* + Convert request size to internal form by adding (sizeof(size_t)) bytes + overhead plus possibly more to obtain necessary alignment and/or + to obtain a size of at least MINSIZE, the smallest allocatable + size. Also, checked_request2size traps (returning 0) request sizes + that are so large that they wrap around zero when padded and + aligned. + */ + + checked_request2size(bytes, nb); + + /* + Bypass search if no frees yet + */ + if (!have_anychunks(av)) { + if (av->max_fast == 0) /* initialization check */ + __malloc_consolidate(av); + goto use_top; + } + + /* + If the size qualifies as a fastbin, first check corresponding bin. + */ + + if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) { + fb = &(av->fastbins[(fastbin_index(nb))]); + if ( (victim = *fb) != 0) { + *fb = victim->fd; + check_remalloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + + /* + If a small request, check regular bin. Since these "smallbins" + hold one size each, no searching within bins is necessary. + (For a large request, we need to wait until unsorted chunks are + processed to find best fit. But for small ones, fits are exact + anyway, so we can check now, which is faster.) + */ + + if (in_smallbin_range(nb)) { + idx = smallbin_index(nb); + bin = bin_at(av,idx); + + if ( (victim = last(bin)) != bin) { + bck = victim->bk; + set_inuse_bit_at_offset(victim, nb); + bin->bk = bck; + bck->fd = bin; + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + + /* If this is a large request, consolidate fastbins before continuing. + While it might look excessive to kill all fastbins before + even seeing if there is space available, this avoids + fragmentation problems normally associated with fastbins. + Also, in practice, programs tend to have runs of either small or + large requests, but less often mixtures, so consolidation is not + invoked all that often in most programs. And the programs that + it is called frequently in otherwise tend to fragment. + */ + + else { + idx = __malloc_largebin_index(nb); + if (have_fastchunks(av)) + __malloc_consolidate(av); + } + + /* + Process recently freed or remaindered chunks, taking one only if + it is exact fit, or, if this a small request, the chunk is remainder from + the most recent non-exact fit. Place other traversed chunks in + bins. Note that this step is the only place in any routine where + chunks are placed in bins. + */ + + while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { + bck = victim->bk; + size = chunksize(victim); + + /* If a small request, try to use last remainder if it is the + only chunk in unsorted bin. This helps promote locality for + runs of consecutive small requests. This is the only + exception to best-fit, and applies only when there is + no exact fit for a small chunk. + */ + + if (in_smallbin_range(nb) && + bck == unsorted_chunks(av) && + victim == av->last_remainder && + (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { + + /* split and reattach remainder */ + remainder_size = size - nb; + remainder = chunk_at_offset(victim, nb); + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + av->last_remainder = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* remove from unsorted list */ + unsorted_chunks(av)->bk = bck; + bck->fd = unsorted_chunks(av); + + /* Take now instead of binning if exact fit */ + + if (size == nb) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* place chunk in bin */ + + if (in_smallbin_range(size)) { + victim_index = smallbin_index(size); + bck = bin_at(av, victim_index); + fwd = bck->fd; + } + else { + victim_index = __malloc_largebin_index(size); + bck = bin_at(av, victim_index); + fwd = bck->fd; + + if (fwd != bck) { + /* if smaller than smallest, place first */ + if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { + fwd = bck; + bck = bck->bk; + } + else if ((unsigned long)(size) >= + (unsigned long)(FIRST_SORTED_BIN_SIZE)) { + + /* maintain large bins in sorted order */ + size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ + while ((unsigned long)(size) < (unsigned long)(fwd->size)) + fwd = fwd->fd; + bck = fwd->bk; + } + } + } + + mark_bin(av, victim_index); + victim->bk = bck; + victim->fd = fwd; + fwd->bk = victim; + bck->fd = victim; + } + + /* + If a large request, scan through the chunks of current bin to + find one that fits. (This will be the smallest that fits unless + FIRST_SORTED_BIN_SIZE has been changed from default.) This is + the only step where an unbounded number of chunks might be + scanned without doing anything useful with them. However the + lists tend to be short. + */ + + if (!in_smallbin_range(nb)) { + bin = bin_at(av, idx); + + for (victim = last(bin); victim != bin; victim = victim->bk) { + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb)) { + remainder_size = size - nb; + unlink(victim, bck, fwd); + + /* Exhaust */ + if (remainder_size < MINSIZE) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + /* Split */ + else { + remainder = chunk_at_offset(victim, nb); + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + } + } + + /* + Search for a chunk by scanning bins, starting with next largest + bin. This search is strictly by best-fit; i.e., the smallest + (with ties going to approximately the least recently used) chunk + that fits is selected. + + The bitmap avoids needing to check that most blocks are nonempty. + */ + + ++idx; + bin = bin_at(av,idx); + block = idx2block(idx); + map = av->binmap[block]; + bit = idx2bit(idx); + + for (;;) { + + /* Skip rest of block if there are no more set bits in this block. */ + if (bit > map || bit == 0) { + do { + if (++block >= BINMAPSIZE) /* out of bins */ + goto use_top; + } while ( (map = av->binmap[block]) == 0); + + bin = bin_at(av, (block << BINMAPSHIFT)); + bit = 1; + } + + /* Advance to bin with set bit. There must be one. */ + while ((bit & map) == 0) { + bin = next_bin(bin); + bit <<= 1; + assert(bit != 0); + } + + /* Inspect the bin. It is likely to be non-empty */ + victim = last(bin); + + /* If a false alarm (empty bin), clear the bit. */ + if (victim == bin) { + av->binmap[block] = map &= ~bit; /* Write through */ + bin = next_bin(bin); + bit <<= 1; + } + + else { + size = chunksize(victim); + + /* We know the first chunk in this bin is big enough to use. */ + assert((unsigned long)(size) >= (unsigned long)(nb)); + + remainder_size = size - nb; + + /* unlink */ + bck = victim->bk; + bin->bk = bck; + bck->fd = bin; + + /* Exhaust */ + if (remainder_size < MINSIZE) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* Split */ + else { + remainder = chunk_at_offset(victim, nb); + + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + /* advertise as last remainder */ + if (in_smallbin_range(nb)) + av->last_remainder = remainder; + + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + } + +use_top: + /* + If large enough, split off the chunk bordering the end of memory + (held in av->top). Note that this is in accord with the best-fit + search rule. In effect, av->top is treated as larger (and thus + less well fitting) than any other available chunk since it can + be extended to be as large as necessary (up to system + limitations). + + We require that av->top always exists (i.e., has size >= + MINSIZE) after initialization, so if it would otherwise be + exhuasted by current request, it is replenished. (The main + reason for ensuring it exists is that we may need MINSIZE space + to put in fenceposts in sysmalloc.) + */ + + victim = av->top; + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(victim, nb); + av->top = remainder; + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* If no space in top, relay to handle system-dependent cases */ + sysmem = __malloc_alloc(nb, av); + retval = sysmem; +DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h new file mode 100644 index 0000000..e0f3658 --- /dev/null +++ b/libc/stdlib/malloc-standard/malloc.h @@ -0,0 +1,966 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(mmap) +libc_hidden_proto(sysconf) +libc_hidden_proto(sbrk) +libc_hidden_proto(abort) + + +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + + + +/* + MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks. + It must be a power of two at least 2 * (sizeof(size_t)), even on machines + for which smaller alignments would suffice. It may be defined as + larger than this though. Note however that code and data structures + are optimized for the case of 8-byte alignment. +*/ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT (2 * (sizeof(size_t))) +#endif + +/* The corresponding bit mask value */ +#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) + +/* + TRIM_FASTBINS controls whether free() of a very small chunk can + immediately lead to trimming. Setting to true (1) can reduce memory + footprint, but will almost always slow down programs that use a lot + of small chunks. + + Define this only if you are willing to give up some speed to more + aggressively reduce system-level memory footprint when releasing + memory in programs that use many small chunks. You can get + essentially the same effect by setting MXFAST to 0, but this can + lead to even greater slowdowns in programs using many small chunks. + TRIM_FASTBINS is an in-between compile-time option, that disables + only those chunks bordering topmost memory from being placed in + fastbins. +*/ +#ifndef TRIM_FASTBINS +#define TRIM_FASTBINS 0 +#endif + + +/* + MORECORE-related declarations. By default, rely on sbrk +*/ + + +/* + MORECORE is the name of the routine to call to obtain more memory + from the system. See below for general guidance on writing + alternative MORECORE functions, as well as a version for WIN32 and a + sample version for pre-OSX macos. +*/ +#ifndef MORECORE +#define MORECORE sbrk +#endif + +/* + MORECORE_FAILURE is the value returned upon failure of MORECORE + as well as mmap. Since it cannot be an otherwise valid memory address, + and must reflect values of standard sys calls, you probably ought not + try to redefine it. +*/ +#ifndef MORECORE_FAILURE +#define MORECORE_FAILURE (-1) +#endif + +/* + If MORECORE_CONTIGUOUS is true, take advantage of fact that + consecutive calls to MORECORE with positive arguments always return + contiguous increasing addresses. This is true of unix sbrk. Even + if not defined, when regions happen to be contiguous, malloc will + permit allocations spanning regions obtained from different + calls. But defining this when applicable enables some stronger + consistency checks and space efficiencies. +*/ +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif + +/* + MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if + sbrk fails, and mmap is used as a backup (which is done only if + HAVE_MMAP). The value must be a multiple of page size. This + backup strategy generally applies only when systems have "holes" in + address space, so sbrk cannot perform contiguous expansion, but + there is still space available on system. On systems for which + this is known to be useful (i.e. most linux kernels), this occurs + only when programs allocate huge amounts of memory. Between this, + and the fact that mmap regions tend to be limited, the size should + be large, to avoid too many mmap calls and thus avoid running out + of kernel resources. +*/ +#ifndef MMAP_AS_MORECORE_SIZE +#define MMAP_AS_MORECORE_SIZE (1024 * 1024) +#endif + +/* + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. Note that this value is + cached during initialization into a field of malloc_state. So even + if malloc_getpagesize is a function, it is only called once. + + The following mechanics for getpagesize were adapted from bsd/gnu + getpagesize.h. If none of the system-probes here apply, a value of + 4096 is used, which should be OK: If they don't apply, then using + the actual value probably doesn't impact performance. +*/ +#ifndef malloc_getpagesize +# include +# define malloc_getpagesize sysconf(_SC_PAGESIZE) +#else /* just guess */ +# define malloc_getpagesize (4096) +#endif + + +/* mallopt tuning options */ + +/* + M_MXFAST is the maximum request size used for "fastbins", special bins + that hold returned chunks without consolidating their spaces. This + enables future requests for chunks of the same size to be handled + very quickly, but can increase fragmentation, and thus increase the + overall memory footprint of a program. + + This malloc manages fastbins very conservatively yet still + efficiently, so fragmentation is rarely a problem for values less + than or equal to the default. The maximum supported value of MXFAST + is 80. You wouldn't want it any higher than this anyway. Fastbins + are designed especially for use with many small structs, objects or + strings -- the default handles structs/objects/arrays with sizes up + to 16 4byte fields, or small strings representing words, tokens, + etc. Using fastbins for larger objects normally worsens + fragmentation without improving speed. + + M_MXFAST is set in REQUEST size units. It is internally used in + chunksize units, which adds padding and alignment. You can reduce + M_MXFAST to 0 to disable all use of fastbins. This causes the malloc + algorithm to be a closer approximation of fifo-best-fit in all cases, + not just for larger requests, but will generally cause it to be + slower. +*/ + + +/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */ +#ifndef M_MXFAST +#define M_MXFAST 1 +#endif + +#ifndef DEFAULT_MXFAST +#define DEFAULT_MXFAST 64 +#endif + + +/* + M_TRIM_THRESHOLD is the maximum amount of unused top-most memory + to keep before releasing via malloc_trim in free(). + + Automatic trimming is mainly useful in long-lived programs. + Because trimming via sbrk can be slow on some systems, and can + sometimes be wasteful (in cases where programs immediately + afterward allocate more large chunks) the value should be high + enough so that your overall system performance would improve by + releasing this much memory. + + The trim threshold and the mmap control parameters (see below) + can be traded off with one another. Trimming and mmapping are + two different ways of releasing unused memory back to the + system. Between these two, it is often possible to keep + system-level demands of a long-lived program down to a bare + minimum. For example, in one test suite of sessions measuring + the XF86 X server on Linux, using a trim threshold of 128K and a + mmap threshold of 192K led to near-minimal long term resource + consumption. + + If you are using this malloc in a long-lived program, it should + pay to experiment with these values. As a rough guide, you + might set to a value close to the average size of a process + (program) running on your system. Releasing this much memory + would allow such a process to run in memory. Generally, it's + worth it to tune for trimming rather tham memory mapping when a + program undergoes phases where several large chunks are + allocated and released in ways that can reuse each other's + storage, perhaps mixed with phases where there are no such + chunks at all. And in well-behaved long-lived programs, + controlling release of large blocks via trimming versus mapping + is usually faster. + + However, in most programs, these parameters serve mainly as + protection against the system-level effects of carrying around + massive amounts of unneeded memory. Since frequent calls to + sbrk, mmap, and munmap otherwise degrade performance, the default + parameters are set to relatively high values that serve only as + safeguards. + + The trim value must be greater than page size to have any useful + effect. To disable trimming completely, you can set to + (unsigned long)(-1) + + Trim settings interact with fastbin (MXFAST) settings: Unless + TRIM_FASTBINS is defined, automatic trimming never takes place upon + freeing a chunk with size less than or equal to MXFAST. Trimming is + instead delayed until subsequent freeing of larger chunks. However, + you can still force an attempted trim by calling malloc_trim. + + Also, trimming is not generally possible in cases where + the main arena is obtained via mmap. + + Note that the trick some people use of mallocing a huge space and + then freeing it at program startup, in an attempt to reserve system + memory, doesn't have the intended effect under automatic trimming, + since that memory will immediately be returned to the system. +*/ +#define M_TRIM_THRESHOLD -1 + +#ifndef DEFAULT_TRIM_THRESHOLD +#define DEFAULT_TRIM_THRESHOLD (256 * 1024) +#endif + +/* + M_TOP_PAD is the amount of extra `padding' space to allocate or + retain whenever sbrk is called. It is used in two ways internally: + + * When sbrk is called to extend the top of the arena to satisfy + a new malloc request, this much padding is added to the sbrk + request. + + * When malloc_trim is called automatically from free(), + it is used as the `pad' argument. + + In both cases, the actual amount of padding is rounded + so that the end of the arena is always a system page boundary. + + The main reason for using padding is to avoid calling sbrk so + often. Having even a small pad greatly reduces the likelihood + that nearly every malloc request during program start-up (or + after trimming) will invoke sbrk, which needlessly wastes + time. + + Automatic rounding-up to page-size units is normally sufficient + to avoid measurable overhead, so the default is 0. However, in + systems where sbrk is relatively slow, it can pay to increase + this value, at the expense of carrying around more memory than + the program needs. +*/ +#define M_TOP_PAD -2 + +#ifndef DEFAULT_TOP_PAD +#define DEFAULT_TOP_PAD (0) +#endif + +/* + M_MMAP_THRESHOLD is the request size threshold for using mmap() + to service a request. Requests of at least this size that cannot + be allocated using already-existing space will be serviced via mmap. + (If enough normal freed space already exists it is used instead.) + + Using mmap segregates relatively large chunks of memory so that + they can be individually obtained and released from the host + system. A request serviced through mmap is never reused by any + other request (at least not directly; the system may just so + happen to remap successive requests to the same locations). + + Segregating space in this way has the benefits that: + + 1. Mmapped space can ALWAYS be individually released back + to the system, which helps keep the system level memory + demands of a long-lived program low. + 2. Mapped memory can never become `locked' between + other chunks, as can happen with normally allocated chunks, which + means that even trimming via malloc_trim would not release them. + 3. On some systems with "holes" in address spaces, mmap can obtain + memory that sbrk cannot. + + However, it has the disadvantages that: + + 1. The space cannot be reclaimed, consolidated, and then + used to service later requests, as happens with normal chunks. + 2. It can lead to more wastage because of mmap page alignment + requirements + 3. It causes malloc performance to be more dependent on host + system memory management support routines which may vary in + implementation quality and may impose arbitrary + limitations. Generally, servicing a request via normal + malloc steps is faster than going through a system's mmap. + + The advantages of mmap nearly always outweigh disadvantages for + "large" chunks, but the value of "large" varies across systems. The + default is an empirically derived value that works well in most + systems. +*/ +#define M_MMAP_THRESHOLD -3 + +#ifndef DEFAULT_MMAP_THRESHOLD +#define DEFAULT_MMAP_THRESHOLD (256 * 1024) +#endif + +/* + M_MMAP_MAX is the maximum number of requests to simultaneously + service using mmap. This parameter exists because +. Some systems have a limited number of internal tables for + use by mmap, and using more than a few of them may degrade + performance. + + The default is set to a value that serves only as a safeguard. + Setting to 0 disables use of mmap for servicing large requests. If + HAVE_MMAP is not set, the default value is 0, and attempts to set it + to non-zero values in mallopt will fail. +*/ +#define M_MMAP_MAX -4 + +#ifndef DEFAULT_MMAP_MAX +#define DEFAULT_MMAP_MAX (65536) +#endif + + +/* ------------------ MMAP support ------------------ */ +#include +#include + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#ifdef __ARCH_USE_MMU__ + +#define MMAP(addr, size, prot) \ + (mmap((addr), (size), (prot), MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) + +#else + +#define MMAP(addr, size, prot) \ + (mmap((addr), (size), (prot), MAP_SHARED|MAP_ANONYMOUS, 0, 0)) + +#endif + + +/* ----------------------- Chunk representations ----------------------- */ + + +/* + This struct declaration is misleading (but accurate and necessary). + It declares a "view" into memory allowing access to necessary + fields at known offsets from a given base. See explanation below. +*/ + +struct malloc_chunk { + + size_t prev_size; /* Size of previous chunk (if free). */ + size_t size; /* Size in bytes, including overhead. */ + + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + + +typedef struct malloc_chunk* mchunkptr; + +/* + malloc_chunk details: + + (The following includes lightly edited explanations by Colin Plumb.) + + Chunks of memory are maintained using a `boundary tag' method as + described in e.g., Knuth or Standish. (See the paper by Paul + Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a + survey of such techniques.) Sizes of free chunks are stored both + in the front of each chunk and at the end. This makes + consolidating fragmented chunks into bigger chunks very fast. The + size fields also hold bits representing whether chunks are free or + in use. + + An allocated chunk looks like this: + + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk, if allocated | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | User data starts here... . + . . + . (malloc_usable_space() bytes) . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Where "chunk" is the front of the chunk for the purpose of most of + the malloc code, but "mem" is the pointer that is returned to the + user. "Nextchunk" is the beginning of the next contiguous chunk. + + Chunks always begin on even word boundries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + Free chunks are stored in circular doubly-linked lists, and look like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The P (PREV_INUSE) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, + preventing access to non-existent (or non-owned) memory. If + prev_inuse is set for any given chunk, then you CANNOT determine + the size of the previous chunk, and might even get a memory + addressing fault when trying to do so. + + Note that the `foot' of the current chunk is actually represented + as the prev_size of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The two exceptions to all this are + + 1. The special chunk `top' doesn't bother using the + trailing size field since there is no next contiguous chunk + that would have to index off it. After initialization, `top' + is forced to always exist. If it would become less than + MINSIZE bytes long, it is replenished. + + 2. Chunks allocated via mmap, which have the second-lowest-order + bit (IS_MMAPPED) set in their size fields. Because they are + allocated one-by-one, each must contain its own trailing size field. + +*/ + +/* + ---------- Size and alignment checks and conversions ---------- +*/ + +/* conversion from malloc headers to user pointers, and back */ + +#define chunk2mem(p) ((void*)((char*)(p) + 2*(sizeof(size_t)))) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*(sizeof(size_t)))) + +/* The smallest possible chunk */ +#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk)) + +/* The smallest size we can malloc is an aligned minimal chunk */ + +#define MINSIZE \ + (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) + +/* Check if m has acceptable alignment */ + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) + + +/* Check if a request is so large that it would wrap around zero when + padded and aligned. To simplify some other code, the bound is made + low enough so that adding MINSIZE will also not wrap around sero. +*/ + +#define REQUEST_OUT_OF_RANGE(req) \ + ((unsigned long)(req) >= \ + (unsigned long)(size_t)(-2 * MINSIZE)) + +/* pad request bytes into a usable size -- internal version */ + +#define request2size(req) \ + (((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK < MINSIZE) ? \ + MINSIZE : \ + ((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + +/* Same, except also perform argument check */ + +#define checked_request2size(req, sz) \ + if (REQUEST_OUT_OF_RANGE(req)) { \ + errno = ENOMEM; \ + return 0; \ + } \ + (sz) = request2size(req); + +/* + --------------- Physical chunk operations --------------- +*/ + + +/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ +#define PREV_INUSE 0x1 + +/* extract inuse bit of previous chunk */ +#define prev_inuse(p) ((p)->size & PREV_INUSE) + + +/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ +#define IS_MMAPPED 0x2 + +/* check for mmap()'ed chunk */ +#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) + +/* Bits to mask off when extracting size + + Note: IS_MMAPPED is intentionally not masked off from size field in + macros for which mmapped chunks should never be seen. This should + cause helpful core dumps to occur if it is tried by accident by + people extending or adapting this malloc. +*/ +#define SIZE_BITS (PREV_INUSE|IS_MMAPPED) + +/* Get size, ignoring use bits */ +#define chunksize(p) ((p)->size & ~(SIZE_BITS)) + + +/* Ptr to next physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) + +/* Ptr to previous physical malloc_chunk */ +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) + +/* Treat space at ptr + offset as a chunk */ +#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) + +/* extract p's inuse bit */ +#define inuse(p)\ +((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) + +/* set/clear chunk as being inuse without otherwise disturbing */ +#define set_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE + +#define clear_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) + + +/* check/set/clear inuse bits in known places */ +#define inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) + +#define set_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE) + +#define clear_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) + + +/* Set size at head, without disturbing its use bit */ +#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) + +/* Set size/use field */ +#define set_head(p, s) ((p)->size = (s)) + +/* Set size at footer (only when chunk is not in use) */ +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) + + +/* -------------------- Internal data structures -------------------- */ + +/* + Bins + + An array of bin headers for free chunks. Each bin is doubly + linked. The bins are approximately proportionally (log) spaced. + There are a lot of these bins (128). This may look excessive, but + works very well in practice. Most bins hold sizes that are + unusual as malloc request sizes, but are more usual for fragments + and consolidated sets of chunks, which is what these bins hold, so + they can be found quickly. All procedures maintain the invariant + that no consolidated chunk physically borders another one, so each + chunk in a list is known to be preceeded and followed by either + inuse chunks or the ends of memory. + + Chunks in bins are kept in size order, with ties going to the + approximately least recently used chunk. Ordering isn't needed + for the small bins, which all contain the same-sized chunks, but + facilitates best-fit allocation for larger chunks. These lists + are just sequential. Keeping them in order almost never requires + enough traversal to warrant using fancier ordered data + structures. + + Chunks of the same size are linked with the most + recently freed at the front, and allocations are taken from the + back. This results in LRU (FIFO) allocation order, which tends + to give each chunk an equal opportunity to be consolidated with + adjacent freed chunks, resulting in larger free chunks and less + fragmentation. + + To simplify use in double-linked lists, each bin header acts + as a malloc_chunk. This avoids special-casing for headers. + But to conserve space and improve locality, we allocate + only the fd/bk pointers of bins, and then use repositioning tricks + to treat these as the fields of a malloc_chunk*. +*/ + +typedef struct malloc_chunk* mbinptr; + +/* addressing -- note that bin_at(0) does not exist */ +#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - ((sizeof(size_t))<<1))) + +/* analog of ++bin */ +#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1))) + +/* Reminders about list directionality within bins */ +#define first(b) ((b)->fd) +#define last(b) ((b)->bk) + +/* Take a chunk off a bin list */ +#define unlink(P, BK, FD) { \ + FD = P->fd; \ + BK = P->bk; \ + if (FD->bk != P || BK->fd != P) \ + abort(); \ + FD->bk = BK; \ + BK->fd = FD; \ +} + +/* + Indexing + + Bins for sizes < 512 bytes contain chunks of all the same size, spaced + 8 bytes apart. Larger bins are approximately logarithmically spaced: + + 64 bins of size 8 + 32 bins of size 64 + 16 bins of size 512 + 8 bins of size 4096 + 4 bins of size 32768 + 2 bins of size 262144 + 1 bin of size what's left + + The bins top out around 1MB because we expect to service large + requests via mmap. +*/ + +#define NBINS 96 +#define NSMALLBINS 32 +#define SMALLBIN_WIDTH 8 +#define MIN_LARGE_SIZE 256 + +#define in_smallbin_range(sz) \ + ((unsigned long)(sz) < (unsigned long)MIN_LARGE_SIZE) + +#define smallbin_index(sz) (((unsigned)(sz)) >> 3) + +#define bin_index(sz) \ + ((in_smallbin_range(sz)) ? smallbin_index(sz) : __malloc_largebin_index(sz)) + +/* + FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the + first bin that is maintained in sorted order. This must + be the smallest size corresponding to a given bin. + + Normally, this should be MIN_LARGE_SIZE. But you can weaken + best fit guarantees to sometimes speed up malloc by increasing value. + Doing this means that malloc may choose a chunk that is + non-best-fitting by up to the width of the bin. + + Some useful cutoff values: + 512 - all bins sorted + 2560 - leaves bins <= 64 bytes wide unsorted + 12288 - leaves bins <= 512 bytes wide unsorted + 65536 - leaves bins <= 4096 bytes wide unsorted + 262144 - leaves bins <= 32768 bytes wide unsorted + -1 - no bins sorted (not recommended!) +*/ + +#define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE +/* #define FIRST_SORTED_BIN_SIZE 65536 */ + +/* + Unsorted chunks + + All remainders from chunk splits, as well as all returned chunks, + are first placed in the "unsorted" bin. They are then placed + in regular bins after malloc gives them ONE chance to be used before + binning. So, basically, the unsorted_chunks list acts as a queue, + with chunks being placed on it in free (and __malloc_consolidate), + and taken off (to be either used or placed in bins) in malloc. +*/ + +/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */ +#define unsorted_chunks(M) (bin_at(M, 1)) + +/* + Top + + The top-most available chunk (i.e., the one bordering the end of + available memory) is treated specially. It is never included in + any bin, is used only if no other chunk is available, and is + released back to the system if it is very large (see + M_TRIM_THRESHOLD). Because top initially + points to its own bin with initial zero size, thus forcing + extension on the first malloc request, we avoid having any special + code in malloc to check whether it even exists yet. But we still + need to do so when getting memory from system, so we make + initial_top treat the bin as a legal but unusable chunk during the + interval between initialization and the first call to + __malloc_alloc. (This is somewhat delicate, since it relies on + the 2 preceding words to be zero during this interval as well.) +*/ + +/* Conveniently, the unsorted bin can be used as dummy top on first call */ +#define initial_top(M) (unsorted_chunks(M)) + +/* + Binmap + + To help compensate for the large number of bins, a one-level index + structure is used for bin-by-bin searching. `binmap' is a + bitvector recording whether bins are definitely empty so they can + be skipped over during during traversals. The bits are NOT always + cleared as soon as bins are empty, but instead only + when they are noticed to be empty during traversal in malloc. +*/ + +/* Conservatively use 32 bits per map word, even if on 64bit system */ +#define BINMAPSHIFT 5 +#define BITSPERMAP (1U << BINMAPSHIFT) +#define BINMAPSIZE (NBINS / BITSPERMAP) + +#define idx2block(i) ((i) >> BINMAPSHIFT) +#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1)))) + +#define mark_bin(m,i) ((m)->binmap[idx2block(i)] |= idx2bit(i)) +#define unmark_bin(m,i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i))) +#define get_binmap(m,i) ((m)->binmap[idx2block(i)] & idx2bit(i)) + +/* + Fastbins + + An array of lists holding recently freed small chunks. Fastbins + are not doubly linked. It is faster to single-link them, and + since chunks are never removed from the middles of these lists, + double linking is not necessary. Also, unlike regular bins, they + are not even processed in FIFO order (they use faster LIFO) since + ordering doesn't much matter in the transient contexts in which + fastbins are normally used. + + Chunks in fastbins keep their inuse bit set, so they cannot + be consolidated with other free chunks. __malloc_consolidate + releases all chunks in fastbins and consolidates them with + other free chunks. +*/ + +typedef struct malloc_chunk* mfastbinptr; + +/* offset 2 to use otherwise unindexable first 2 bins */ +#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2) + +/* The maximum fastbin request size we support */ +#define MAX_FAST_SIZE 80 + +#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1) + +/* + FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free() + that triggers automatic consolidation of possibly-surrounding + fastbin chunks. This is a heuristic, so the exact value should not + matter too much. It is defined at half the default trim threshold as a + compromise heuristic to only attempt consolidation if it is likely + to lead to trimming. However, it is not dynamically tunable, since + consolidation reduces fragmentation surrounding loarge chunks even + if trimming is not used. +*/ + +#define FASTBIN_CONSOLIDATION_THRESHOLD \ + ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1) + +/* + Since the lowest 2 bits in max_fast don't matter in size comparisons, + they are used as flags. +*/ + +/* + ANYCHUNKS_BIT held in max_fast indicates that there may be any + freed chunks at all. It is set true when entering a chunk into any + bin. +*/ + +#define ANYCHUNKS_BIT (1U) + +#define have_anychunks(M) (((M)->max_fast & ANYCHUNKS_BIT)) +#define set_anychunks(M) ((M)->max_fast |= ANYCHUNKS_BIT) +#define clear_anychunks(M) ((M)->max_fast &= ~ANYCHUNKS_BIT) + +/* + FASTCHUNKS_BIT held in max_fast indicates that there are probably + some fastbin chunks. It is set true on entering a chunk into any + fastbin, and cleared only in __malloc_consolidate. +*/ + +#define FASTCHUNKS_BIT (2U) + +#define have_fastchunks(M) (((M)->max_fast & FASTCHUNKS_BIT)) +#define set_fastchunks(M) ((M)->max_fast |= (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) +#define clear_fastchunks(M) ((M)->max_fast &= ~(FASTCHUNKS_BIT)) + +/* Set value of max_fast. Use impossibly small value if 0. */ +#define set_max_fast(M, s) \ + (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \ + ((M)->max_fast & (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) + +#define get_max_fast(M) \ + ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT)) + + +/* + morecore_properties is a status word holding dynamically discovered + or controlled properties of the morecore function +*/ + +#define MORECORE_CONTIGUOUS_BIT (1U) + +#define contiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT)) +#define noncontiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT) == 0) +#define set_contiguous(M) \ + ((M)->morecore_properties |= MORECORE_CONTIGUOUS_BIT) +#define set_noncontiguous(M) \ + ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT) + + +/* + ----------- Internal state representation and initialization ----------- +*/ + +struct malloc_state { + + /* The maximum chunk size to be eligible for fastbin */ + size_t max_fast; /* low 2 bits used as flags */ + + /* Fastbins */ + mfastbinptr fastbins[NFASTBINS]; + + /* Base of the topmost chunk -- not otherwise kept in a bin */ + mchunkptr top; + + /* The remainder from the most recent split of a small request */ + mchunkptr last_remainder; + + /* Normal bins packed as described above */ + mchunkptr bins[NBINS * 2]; + + /* Bitmap of bins. Trailing zero map handles cases of largest binned size */ + unsigned int binmap[BINMAPSIZE+1]; + + /* Tunable parameters */ + unsigned long trim_threshold; + size_t top_pad; + size_t mmap_threshold; + + /* Memory map support */ + int n_mmaps; + int n_mmaps_max; + int max_n_mmaps; + + /* Cache malloc_getpagesize */ + unsigned int pagesize; + + /* Track properties of MORECORE */ + unsigned int morecore_properties; + + /* Statistics */ + size_t mmapped_mem; + size_t sbrked_mem; + size_t max_sbrked_mem; + size_t max_mmapped_mem; + size_t max_total_mem; +}; + +typedef struct malloc_state *mstate; + +/* + There is exactly one instance of this struct in this malloc. + If you are adapting this malloc in a way that does NOT use a static + malloc_state, you MUST explicitly zero-fill it before using. This + malloc relies on the property that malloc_state is initialized to + all zeroes (as is true of C statics). +*/ +extern struct malloc_state __malloc_state; /* never directly referenced */ + +/* + All uses of av_ are via get_malloc_state(). + At most one "call" to get_malloc_state is made per invocation of + the public versions of malloc and free, but other routines + that in turn invoke malloc and/or free may call more then once. + Also, it is called in check* routines if __UCLIBC_MALLOC_DEBUGGING__ is set. +*/ + +#define get_malloc_state() (&(__malloc_state)) + +/* External internal utilities operating on mstates */ +void __malloc_consolidate(mstate) attribute_hidden; + + +/* Debugging support */ +#ifndef __UCLIBC_MALLOC_DEBUGGING__ + +#define check_chunk(P) +#define check_free_chunk(P) +#define check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) +#define check_malloc_state() +#define assert(x) ((void)0) + + +#else + +#define check_chunk(P) __do_check_chunk(P) +#define check_free_chunk(P) __do_check_free_chunk(P) +#define check_inuse_chunk(P) __do_check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) __do_check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) __do_check_malloced_chunk(P,N) +#define check_malloc_state() __do_check_malloc_state() + +extern void __do_check_chunk(mchunkptr p); +extern void __do_check_free_chunk(mchunkptr p); +extern void __do_check_inuse_chunk(mchunkptr p); +extern void __do_check_remalloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloc_state(void); + +#include + +#endif diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c new file mode 100644 index 0000000..053242d --- /dev/null +++ b/libc/stdlib/malloc-standard/mallopt.c @@ -0,0 +1,64 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------------ mallopt ------------------------------ */ +int mallopt(int param_number, int value) +{ + int ret; + mstate av; + + ret = 0; + + __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization/consolidation */ + __malloc_consolidate(av); + + switch(param_number) { + case M_MXFAST: + if (value >= 0 && value <= MAX_FAST_SIZE) { + set_max_fast(av, value); + ret = 1; + } + break; + + case M_TRIM_THRESHOLD: + av->trim_threshold = value; + ret = 1; + break; + + case M_TOP_PAD: + av->top_pad = value; + ret = 1; + break; + + case M_MMAP_THRESHOLD: + av->mmap_threshold = value; + ret = 1; + break; + + case M_MMAP_MAX: + av->n_mmaps_max = value; + ret = 1; + break; + } + __MALLOC_UNLOCK; + return ret; +} + diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c new file mode 100644 index 0000000..7e0674b --- /dev/null +++ b/libc/stdlib/malloc-standard/memalign.c @@ -0,0 +1,130 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include +#include "malloc.h" + + +/* ------------------------------ memalign ------------------------------ */ +void* memalign(size_t alignment, size_t bytes) +{ + size_t nb; /* padded request size */ + char* m; /* memory returned by malloc call */ + mchunkptr p; /* corresponding chunk */ + char* _brk; /* alignment point within p */ + mchunkptr newp; /* chunk to return */ + size_t newsize; /* its size */ + size_t leadsize; /* leading space before alignment point */ + mchunkptr remainder; /* spare room at end to split off */ + unsigned long remainder_size; /* its size */ + size_t size; + void *retval; + + /* If need less alignment than we give anyway, just relay to malloc */ + + if (alignment <= MALLOC_ALIGNMENT) return malloc(bytes); + + /* Otherwise, ensure that it is at least a minimum chunk size */ + + if (alignment < MINSIZE) alignment = MINSIZE; + + /* Make sure alignment is power of 2 (in case MINSIZE is not). */ + if ((alignment & (alignment - 1)) != 0) { + size_t a = MALLOC_ALIGNMENT * 2; + while ((unsigned long)a < (unsigned long)alignment) a <<= 1; + alignment = a; + } + + __MALLOC_LOCK; + checked_request2size(bytes, nb); + + /* Strategy: find a spot within that chunk that meets the alignment + * request, and then possibly free the leading and trailing space. */ + + + /* Call malloc with worst case padding to hit alignment. */ + + m = (char*)(malloc(nb + alignment + MINSIZE)); + + if (m == 0) { + retval = 0; /* propagate failure */ + goto DONE; + } + + p = mem2chunk(m); + + if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */ + + /* + Find an aligned spot inside chunk. Since we need to give back + leading space in a chunk of at least MINSIZE, if the first + calculation places us at a spot with less than MINSIZE leader, + we can move to the next aligned spot -- we've allocated enough + total room so that this is always possible. + */ + + _brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & + -((signed long) alignment))); + if ((unsigned long)(_brk - (char*)(p)) < MINSIZE) + _brk += alignment; + + newp = (mchunkptr)_brk; + leadsize = _brk - (char*)(p); + newsize = chunksize(p) - leadsize; + + /* For mmapped chunks, just adjust offset */ + if (chunk_is_mmapped(p)) { + newp->prev_size = p->prev_size + leadsize; + set_head(newp, newsize|IS_MMAPPED); + retval = chunk2mem(newp); + goto DONE; + } + + /* Otherwise, give back leader, use the rest */ + set_head(newp, newsize | PREV_INUSE); + set_inuse_bit_at_offset(newp, newsize); + set_head_size(p, leadsize); + free(chunk2mem(p)); + p = newp; + + assert (newsize >= nb && + (((unsigned long)(chunk2mem(p))) % alignment) == 0); + } + + /* Also give back spare room at the end */ + if (!chunk_is_mmapped(p)) { + size = chunksize(p); + if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(p, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_head_size(p, nb); + free(chunk2mem(remainder)); + } + } + + check_inuse_chunk(p); + retval = chunk2mem(p); + + DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c new file mode 100644 index 0000000..41cae43 --- /dev/null +++ b/libc/stdlib/malloc-standard/realloc.c @@ -0,0 +1,242 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + +libc_hidden_proto(mremap) +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* ------------------------------ realloc ------------------------------ */ +void* realloc(void* oldmem, size_t bytes) +{ + mstate av; + + size_t nb; /* padded request size */ + + mchunkptr oldp; /* chunk corresponding to oldmem */ + size_t oldsize; /* its size */ + + mchunkptr newp; /* chunk to return */ + size_t newsize; /* its size */ + void* newmem; /* corresponding user mem */ + + mchunkptr next; /* next contiguous chunk after oldp */ + + mchunkptr remainder; /* extra space at end of newp */ + unsigned long remainder_size; /* its size */ + + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + + unsigned long copysize; /* bytes to copy */ + unsigned int ncopies; /* size_t words to copy */ + size_t* s; /* copy source */ + size_t* d; /* copy destination */ + + void *retval; + + /* Check for special cases. */ + if (! oldmem) + return malloc(bytes); + if (! bytes) { + free (oldmem); + return NULL; + } + + __MALLOC_LOCK; + av = get_malloc_state(); + checked_request2size(bytes, nb); + + oldp = mem2chunk(oldmem); + oldsize = chunksize(oldp); + + check_inuse_chunk(oldp); + + if (!chunk_is_mmapped(oldp)) { + + if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { + /* already big enough; split below */ + newp = oldp; + newsize = oldsize; + } + + else { + next = chunk_at_offset(oldp, oldsize); + + /* Try to expand forward into top */ + if (next == av->top && + (unsigned long)(newsize = oldsize + chunksize(next)) >= + (unsigned long)(nb + MINSIZE)) { + set_head_size(oldp, nb); + av->top = chunk_at_offset(oldp, nb); + set_head(av->top, (newsize - nb) | PREV_INUSE); + retval = chunk2mem(oldp); + goto DONE; + } + + /* Try to expand forward into next chunk; split off remainder below */ + else if (next != av->top && + !inuse(next) && + (unsigned long)(newsize = oldsize + chunksize(next)) >= + (unsigned long)(nb)) { + newp = oldp; + unlink(next, bck, fwd); + } + + /* allocate, copy, free */ + else { + newmem = malloc(nb - MALLOC_ALIGN_MASK); + if (newmem == 0) { + retval = 0; /* propagate failure */ + goto DONE; + } + + newp = mem2chunk(newmem); + newsize = chunksize(newp); + + /* + Avoid copy if newp is next chunk after oldp. + */ + if (newp == next) { + newsize += oldsize; + newp = oldp; + } + else { + /* + Unroll copy of <= 36 bytes (72 if 8byte sizes) + We know that contents have an odd number of + size_t-sized words; minimally 3. + */ + + copysize = oldsize - (sizeof(size_t)); + s = (size_t*)(oldmem); + d = (size_t*)(newmem); + ncopies = copysize / sizeof(size_t); + assert(ncopies >= 3); + + if (ncopies > 9) + memcpy(d, s, copysize); + + else { + *(d+0) = *(s+0); + *(d+1) = *(s+1); + *(d+2) = *(s+2); + if (ncopies > 4) { + *(d+3) = *(s+3); + *(d+4) = *(s+4); + if (ncopies > 6) { + *(d+5) = *(s+5); + *(d+6) = *(s+6); + if (ncopies > 8) { + *(d+7) = *(s+7); + *(d+8) = *(s+8); + } + } + } + } + + free(oldmem); + check_inuse_chunk(newp); + retval = chunk2mem(newp); + goto DONE; + } + } + } + + /* If possible, free extra space in old or extended chunk */ + + assert((unsigned long)(newsize) >= (unsigned long)(nb)); + + remainder_size = newsize - nb; + + if (remainder_size < MINSIZE) { /* not enough extra to split off */ + set_head_size(newp, newsize); + set_inuse_bit_at_offset(newp, newsize); + } + else { /* split remainder */ + remainder = chunk_at_offset(newp, nb); + set_head_size(newp, nb); + set_head(remainder, remainder_size | PREV_INUSE); + /* Mark remainder as inuse so free() won't complain */ + set_inuse_bit_at_offset(remainder, remainder_size); + free(chunk2mem(remainder)); + } + + check_inuse_chunk(newp); + retval = chunk2mem(newp); + goto DONE; + } + + /* + Handle mmap cases + */ + + else { + size_t offset = oldp->prev_size; + size_t pagemask = av->pagesize - 1; + char *cp; + unsigned long sum; + + /* Note the extra (sizeof(size_t)) overhead */ + newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; + + /* don't need to remap if still within same page */ + if (oldsize == newsize - offset) { + retval = oldmem; + goto DONE; + } + + cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); + + if (cp != (char*)MORECORE_FAILURE) { + + newp = (mchunkptr)(cp + offset); + set_head(newp, (newsize - offset)|IS_MMAPPED); + + assert(aligned_OK(chunk2mem(newp))); + assert((newp->prev_size == offset)); + + /* update statistics */ + sum = av->mmapped_mem += newsize - oldsize; + if (sum > (unsigned long)(av->max_mmapped_mem)) + av->max_mmapped_mem = sum; + sum += av->sbrked_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + retval = chunk2mem(newp); + goto DONE; + } + + /* Note the extra (sizeof(size_t)) overhead. */ + if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) + newmem = oldmem; /* do nothing */ + else { + /* Must alloc, copy, free. */ + newmem = malloc(nb - MALLOC_ALIGN_MASK); + if (newmem != 0) { + memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); + free(oldmem); + } + } + retval = newmem; + } + + DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/libc/stdlib/malloc/Makefile b/libc/stdlib/malloc/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/stdlib/malloc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/stdlib/malloc/Makefile.in b/libc/stdlib/malloc/Makefile.in new file mode 100644 index 0000000..11b250d --- /dev/null +++ b/libc/stdlib/malloc/Makefile.in @@ -0,0 +1,37 @@ +# Makefile for uClibc +# +# Copyright (C) 2002-2003 NEC Electronics Corporation +# Copyright (C) 2002-2003 Miles Bader +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := malloc.c calloc.c free.c realloc.c memalign.c \ + heap_alloc.c heap_alloc_at.c heap_free.c + +# Turn on malloc debugging if requested +ifeq ($(UCLIBC_MALLOC_DEBUGGING),y) +CSRC += malloc_debug.c heap_debug.c +CFLAGS += -DMALLOC_DEBUGGING -DHEAP_DEBUGGING +ifeq ($(UCLIBC_UCLINUX_BROKEN_MUNMAP),y) +CFLAGS += -DMALLOC_MMB_DEBUGGING +endif +endif + +STDLIB_MALLOC_DIR := $(top_srcdir)libc/stdlib/malloc +STDLIB_MALLOC_OUT := $(top_builddir)libc/stdlib/malloc + +STDLIB_MALLOC_SRC := $(patsubst %.c,$(STDLIB_MALLOC_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC) += $(STDLIB_MALLOC_OBJ) + +objclean-y += stdlib_malloc_clean + +stdlib_malloc_clean: + $(do_rm) $(addprefix $(STDLIB_MALLOC_OUT)/*., o os) + +malloc.o free.o realloc.o memalign.o: malloc.h +# Depend on uClinux_config.h to cache changes in __UCLIBC_MALLOC_DEBUGGING__ +$(STDLIB_MALLOC_OBJ): $(STDLIB_MALLOC_DIR)/heap.h $(top_builddir)include/bits/uClibc_config.h diff --git a/libc/stdlib/malloc/calloc.c b/libc/stdlib/malloc/calloc.c new file mode 100644 index 0000000..79e6ec6 --- /dev/null +++ b/libc/stdlib/malloc/calloc.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* calloc for uClibc + * + * Copyright (C) 2002 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +void * calloc(size_t nmemb, size_t lsize) +{ + void *result; + size_t size=lsize * nmemb; + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + if (nmemb && lsize != (size / nmemb)) { + __set_errno(ENOMEM); + return NULL; + } + if ((result=malloc(size)) != NULL) { + memset(result, 0, size); + } + return result; +} + diff --git a/libc/stdlib/malloc/free.c b/libc/stdlib/malloc/free.c new file mode 100644 index 0000000..9155291 --- /dev/null +++ b/libc/stdlib/malloc/free.c @@ -0,0 +1,274 @@ +/* + * libc/stdlib/malloc/free.c -- free function + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + +libc_hidden_proto(munmap) +libc_hidden_proto(sbrk) + +#include "malloc.h" +#include "heap.h" + +#ifdef HEAP_USE_LOCKING +#define free_to_heap(mem, heap, lck) __free_to_heap(mem, heap, lck) +#else +#define free_to_heap(mem, heap, lck) __free_to_heap(mem, heap) +#endif + +static void +__free_to_heap (void *mem, struct heap_free_area **heap +#ifdef HEAP_USE_LOCKING + , malloc_mutex_t *heap_lock +#endif + ) +{ + size_t size; + struct heap_free_area *fa; + + /* Check for special cases. */ + if (unlikely (! mem)) + return; + + /* Normal free. */ + + MALLOC_DEBUG (1, "free: 0x%lx (base = 0x%lx, total_size = %d)", + (long)mem, (long)MALLOC_BASE (mem), MALLOC_SIZE (mem)); + + size = MALLOC_SIZE (mem); + mem = MALLOC_BASE (mem); + + __heap_lock (heap_lock); + + /* Put MEM back in the heap, and get the free-area it was placed in. */ + fa = __heap_free (heap, mem, size); + + /* See if the free-area FA has grown big enough that it should be + unmapped. */ + if (HEAP_FREE_AREA_SIZE (fa) < MALLOC_UNMAP_THRESHOLD) + /* Nope, nothing left to do, just release the lock. */ + __heap_unlock (heap_lock); + else + /* Yup, try to unmap FA. */ + { + unsigned long start = (unsigned long)HEAP_FREE_AREA_START (fa); + unsigned long end = (unsigned long)HEAP_FREE_AREA_END (fa); +#ifndef MALLOC_USE_SBRK +# ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + struct malloc_mmb *mmb, *prev_mmb; + unsigned long mmb_start, mmb_end; +# else /* !__UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + unsigned long unmap_start, unmap_end; +# endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ +#endif /* !MALLOC_USE_SBRK */ + +#ifdef MALLOC_USE_SBRK + /* Get the sbrk lock so that the two possible calls to sbrk below + are guaranteed to be contiguous. */ + __malloc_lock_sbrk (); + /* When using sbrk, we only shrink the heap from the end. It would + be possible to allow _both_ -- shrinking via sbrk when possible, + and otherwise shrinking via munmap, but this results in holes in + memory that prevent the brk from every growing back down; since + we only ever grow the heap via sbrk, this tends to produce a + continuously growing brk (though the actual memory is unmapped), + which could eventually run out of address space. Note that + `sbrk(0)' shouldn't normally do a system call, so this test is + reasonably cheap. */ + if ((void *)end != sbrk (0)) + { + MALLOC_DEBUG (-1, "not unmapping: 0x%lx - 0x%lx (%ld bytes)", + start, end, end - start); + __malloc_unlock_sbrk (); + __heap_unlock (heap_lock); + return; + } +#endif + + MALLOC_DEBUG (0, "unmapping: 0x%lx - 0x%lx (%ld bytes)", + start, end, end - start); + + /* Remove FA from the heap. */ + __heap_delete (heap, fa); + + if (__heap_is_empty (heap)) + /* We want to avoid the heap from losing all memory, so reserve + a bit. This test is only a heuristic -- the existance of + another free area, even if it's smaller than + MALLOC_MIN_SIZE, will cause us not to reserve anything. */ + { + /* Put the reserved memory back in the heap; we assume that + MALLOC_UNMAP_THRESHOLD is greater than MALLOC_MIN_SIZE, so + we use the latter unconditionally here. */ + __heap_free (heap, (void *)start, MALLOC_MIN_SIZE); + start += MALLOC_MIN_SIZE; + } + +#ifdef MALLOC_USE_SBRK + + /* Release the heap lock; we're still holding the sbrk lock. */ + __heap_unlock (heap_lock); + /* Lower the brk. */ + sbrk (start - end); + /* Release the sbrk lock too; now we hold no locks. */ + __malloc_unlock_sbrk (); + +#else /* !MALLOC_USE_SBRK */ + +# ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + /* Using the uClinux broken munmap, we have to only munmap blocks + exactly as we got them from mmap, so scan through our list of + mmapped blocks, and return them in order. */ + + MALLOC_MMB_DEBUG (1, "walking mmb list for region 0x%x[%d]...", + start, end - start); + + prev_mmb = 0; + mmb = __malloc_mmapped_blocks; + while (mmb + && ((mmb_end = (mmb_start = (unsigned long)mmb->mem) + mmb->size) + <= end)) + { + MALLOC_MMB_DEBUG (1, "considering mmb at 0x%x: 0x%x[%d]", + (unsigned)mmb, mmb_start, mmb_end - mmb_start); + + if (mmb_start >= start + /* If the space between START and MMB_START is non-zero, but + too small to return to the heap, we can't unmap MMB. */ + && (start == mmb_start + || mmb_start - start > HEAP_MIN_FREE_AREA_SIZE)) + { + struct malloc_mmb *next_mmb = mmb->next; + + if (mmb_end != end && mmb_end + HEAP_MIN_FREE_AREA_SIZE > end) + /* There's too little space left at the end to deallocate + this block, so give up. */ + break; + + MALLOC_MMB_DEBUG (1, "unmapping mmb at 0x%x: 0x%x[%d]", + (unsigned)mmb, mmb_start, mmb_end - mmb_start); + + if (mmb_start != start) + /* We're going to unmap a part of the heap that begins after + start, so put the intervening region back into the heap. */ + { + MALLOC_MMB_DEBUG (0, "putting intervening region back into heap: 0x%x[%d]", + start, mmb_start - start); + __heap_free (heap, (void *)start, mmb_start - start); + } + + MALLOC_MMB_DEBUG_INDENT (-1); + + /* Unlink MMB from the list. */ + if (prev_mmb) + prev_mmb->next = next_mmb; + else + __malloc_mmapped_blocks = next_mmb; + + /* Start searching again from the end of this block. */ + start = mmb_end; + + /* We have to unlock the heap before we recurse to free the mmb + descriptor, because we might be unmapping from the mmb + heap. */ + __heap_unlock (heap_lock); + + /* Release the descriptor block we used. */ + free_to_heap (mmb, &__malloc_mmb_heap, &__malloc_mmb_heap_lock); + + /* Do the actual munmap. */ + munmap ((void *)mmb_start, mmb_end - mmb_start); + + __heap_lock (heap_lock); + +# ifdef __UCLIBC_HAS_THREADS__ + /* In a multi-threaded program, it's possible that PREV_MMB has + been invalidated by another thread when we released the + heap lock to do the munmap system call, so just start over + from the beginning of the list. It sucks, but oh well; + it's probably not worth the bother to do better. */ + prev_mmb = 0; + mmb = __malloc_mmapped_blocks; +# else + mmb = next_mmb; +# endif + } + else + { + prev_mmb = mmb; + mmb = mmb->next; + } + + MALLOC_MMB_DEBUG_INDENT (-1); + } + + if (start != end) + /* Hmm, well there's something we couldn't unmap, so put it back + into the heap. */ + { + MALLOC_MMB_DEBUG (0, "putting tail region back into heap: 0x%x[%d]", + start, end - start); + __heap_free (heap, (void *)start, end - start); + } + + /* Finally release the lock for good. */ + __heap_unlock (heap_lock); + + MALLOC_MMB_DEBUG_INDENT (-1); + +# else /* !__UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + /* MEM/LEN may not be page-aligned, so we have to page-align them, + and return any left-over bits on the end to the heap. */ + unmap_start = MALLOC_ROUND_UP_TO_PAGE_SIZE (start); + unmap_end = MALLOC_ROUND_DOWN_TO_PAGE_SIZE (end); + + /* We have to be careful that any left-over bits are large enough to + return. Note that we _don't check_ to make sure there's room to + grow/shrink the start/end by another page, we just assume that + the unmap threshold is high enough so that this is always safe + (i.e., it should probably be at least 3 pages). */ + if (unmap_start > start) + { + if (unmap_start - start < HEAP_MIN_FREE_AREA_SIZE) + unmap_start += MALLOC_PAGE_SIZE; + __heap_free (heap, (void *)start, unmap_start - start); + } + if (end > unmap_end) + { + if (end - unmap_end < HEAP_MIN_FREE_AREA_SIZE) + unmap_end -= MALLOC_PAGE_SIZE; + __heap_free (heap, (void *)unmap_end, end - unmap_end); + } + + /* Release the heap lock before we do the system call. */ + __heap_unlock (heap_lock); + + if (unmap_end > unmap_start) + /* Finally, actually unmap the memory. */ + munmap ((void *)unmap_start, unmap_end - unmap_start); + +# endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + +#endif /* MALLOC_USE_SBRK */ + } + + MALLOC_DEBUG_INDENT (-1); +} + +void +free (void *mem) +{ + free_to_heap (mem, &__malloc_heap, &__malloc_heap_lock); +} diff --git a/libc/stdlib/malloc/heap.h b/libc/stdlib/malloc/heap.h new file mode 100644 index 0000000..c0c5df8 --- /dev/null +++ b/libc/stdlib/malloc/heap.h @@ -0,0 +1,230 @@ +/* + * libc/stdlib/malloc/heap.h -- heap allocator used for malloc + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + + +/* On multi-threaded systems, the heap includes a lock. */ +#ifdef __UCLIBC_HAS_THREADS__ +# include +# include +# define HEAP_USE_LOCKING +# define __heap_lock(heap_lock) __pthread_mutex_lock (heap_lock) +# define __heap_unlock(heap_lock) __pthread_mutex_unlock (heap_lock) +#else +# define __heap_lock(heap_lock) +# define __heap_unlock(heap_lock) +#endif + + +/* The heap allocates in multiples of, and aligned to, HEAP_GRANULARITY. + HEAP_GRANULARITY must be a power of 2. Malloc depends on this being the + same as MALLOC_ALIGNMENT. */ +#define HEAP_GRANULARITY_TYPE double __attribute_aligned__ (sizeof (size_t)) +#define HEAP_GRANULARITY (__alignof__ (HEAP_GRANULARITY_TYPE)) + + +/* The HEAP_INIT macro can be used as a static initializer for a heap + variable. The HEAP_INIT_WITH_FA variant is used to initialize a heap + with an initial static free-area; its argument FA should be declared + using HEAP_DECLARE_STATIC_FREE_AREA. */ +# define HEAP_INIT 0 +# define HEAP_INIT_WITH_FA(fa) &fa._fa + +/* A free-list area `header'. These are actually stored at the _ends_ of + free areas (to make allocating from the beginning of the area simpler), + so one might call it a `footer'. */ +struct heap_free_area +{ + size_t size; + struct heap_free_area *next, *prev; +}; + +/* Return the address of the end of the frea area FA. */ +#define HEAP_FREE_AREA_END(fa) ((void *)(fa + 1)) +/* Return the address of the beginning of the frea area FA. FA is + evaulated multiple times. */ +#define HEAP_FREE_AREA_START(fa) ((void *)((char *)(fa + 1) - (fa)->size)) +/* Return the size of the frea area FA. */ +#define HEAP_FREE_AREA_SIZE(fa) ((fa)->size) + +/* This rather clumsy macro allows one to declare a static free-area for + passing to HEAP_INIT_WITH_FA initializer macro. This is only use for + which NAME is allowed. */ +#define HEAP_DECLARE_STATIC_FREE_AREA(name, size) \ + static struct \ + { \ + HEAP_GRANULARITY_TYPE aligned_space; \ + char space[HEAP_ADJUST_SIZE(size) \ + - sizeof (struct heap_free_area) \ + - HEAP_GRANULARITY]; \ + struct heap_free_area _fa; \ + } name = { (HEAP_GRANULARITY_TYPE)0, "", { HEAP_ADJUST_SIZE(size), 0, 0 } } + + +/* Rounds SZ up to be a multiple of HEAP_GRANULARITY. */ +#define HEAP_ADJUST_SIZE(sz) \ + (((sz) + HEAP_GRANULARITY - 1) & ~(HEAP_GRANULARITY - 1)) + + +/* The minimum allocatable size. */ +#define HEAP_MIN_SIZE HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)) + +/* The minimum size of a free area; if allocating memory from a free-area + would make the free-area smaller than this, the allocation is simply + given the whole free-area instead. It must include at least enough room + to hold a struct heap_free_area, plus some extra to avoid excessive heap + fragmentation (thus increasing speed). This is only a heuristic -- it's + possible for smaller free-areas than this to exist (say, by realloc + returning the tail-end of a previous allocation), but __heap_alloc will + try to get rid of them when possible. */ +#define HEAP_MIN_FREE_AREA_SIZE \ + HEAP_ADJUST_SIZE (sizeof (struct heap_free_area) + 32) + + +/* branch-prediction macros; they may already be defined by libc. */ +#ifndef likely +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define likely(cond) __builtin_expect(!!(int)(cond), 1) +#define unlikely(cond) __builtin_expect((int)(cond), 0) +#else +#define likely(cond) (cond) +#define unlikely(cond) (cond) +#endif +#endif /* !likely */ + + +/* Define HEAP_DEBUGGING to cause the heap routines to emit debugging info + to stderr when the variable __heap_debug is set to true. */ +#ifdef HEAP_DEBUGGING +extern int __heap_debug; +#define HEAP_DEBUG(heap, str) (__heap_debug ? __heap_dump (heap, str) : 0) +#else +#define HEAP_DEBUG(heap, str) (void)0 +#endif + +/* Output a text representation of HEAP to stderr, labelling it with STR. */ +extern void __heap_dump (struct heap_free_area *heap, const char *str); + +/* Do some consistency checks on HEAP. If they fail, output an error + message to stderr, and exit. STR is printed with the failure message. */ +extern void __heap_check (struct heap_free_area *heap, const char *str); + + +/* Delete the free-area FA from HEAP. */ +static __inline__ void +__heap_delete (struct heap_free_area **heap, struct heap_free_area *fa) +{ + if (fa->next) + fa->next->prev = fa->prev; + if (fa->prev) + fa->prev->next = fa->next; + else + *heap = fa->next; +} + + +/* Link the free-area FA between the existing free-area's PREV and NEXT in + HEAP. PREV and NEXT may be 0; if PREV is 0, FA is installed as the + first free-area. */ +static __inline__ void +__heap_link_free_area (struct heap_free_area **heap, struct heap_free_area *fa, + struct heap_free_area *prev, + struct heap_free_area *next) +{ + fa->next = next; + fa->prev = prev; + + if (prev) + prev->next = fa; + else + *heap = fa; + if (next) + next->prev = fa; +} + +/* Update the mutual links between the free-areas PREV and FA in HEAP. + PREV may be 0, in which case FA is installed as the first free-area (but + FA may not be 0). */ +static __inline__ void +__heap_link_free_area_after (struct heap_free_area **heap, + struct heap_free_area *fa, + struct heap_free_area *prev) +{ + if (prev) + prev->next = fa; + else + *heap = fa; + fa->prev = prev; +} + +/* Add a new free-area MEM, of length SIZE, in between the existing + free-area's PREV and NEXT in HEAP, and return a pointer to its header. + PREV and NEXT may be 0; if PREV is 0, MEM is installed as the first + free-area. */ +static __inline__ struct heap_free_area * +__heap_add_free_area (struct heap_free_area **heap, void *mem, size_t size, + struct heap_free_area *prev, + struct heap_free_area *next) +{ + struct heap_free_area *fa = (struct heap_free_area *) + ((char *)mem + size - sizeof (struct heap_free_area)); + + fa->size = size; + + __heap_link_free_area (heap, fa, prev, next); + + return fa; +} + + +/* Allocate SIZE bytes from the front of the free-area FA in HEAP, and + return the amount actually allocated (which may be more than SIZE). */ +static __inline__ size_t +__heap_free_area_alloc (struct heap_free_area **heap, + struct heap_free_area *fa, size_t size) +{ + size_t fa_size = fa->size; + + if (fa_size < size + HEAP_MIN_FREE_AREA_SIZE) + /* There's not enough room left over in FA after allocating the block, so + just use the whole thing, removing it from the list of free areas. */ + { + __heap_delete (heap, fa); + /* Remember that we've alloced the whole area. */ + size = fa_size; + } + else + /* Reduce size of FA to account for this allocation. */ + fa->size = fa_size - size; + + return size; +} + + +/* Allocate and return a block at least *SIZE bytes long from HEAP. + *SIZE is adjusted to reflect the actual amount allocated (which may be + greater than requested). */ +extern void *__heap_alloc (struct heap_free_area **heap, size_t *size); + +/* Allocate SIZE bytes at address MEM in HEAP. Return the actual size + allocated, or 0 if we failed. */ +extern size_t __heap_alloc_at (struct heap_free_area **heap, void *mem, size_t size); + +/* Return the memory area MEM of size SIZE to HEAP. + Returns the heap free area into which the memory was placed. */ +extern struct heap_free_area *__heap_free (struct heap_free_area **heap, + void *mem, size_t size); + +/* Return true if HEAP contains absolutely no memory. */ +#define __heap_is_empty(heap) (! (heap)) diff --git a/libc/stdlib/malloc/heap_alloc.c b/libc/stdlib/malloc/heap_alloc.c new file mode 100644 index 0000000..77b7d85 --- /dev/null +++ b/libc/stdlib/malloc/heap_alloc.c @@ -0,0 +1,51 @@ +/* + * libc/stdlib/malloc/heap_alloc.c -- allocate memory from a heap + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Allocate and return a block at least *SIZE bytes long from HEAP. + *SIZE is adjusted to reflect the actual amount allocated (which may be + greater than requested). */ +void * +__heap_alloc (struct heap_free_area **heap, size_t *size) +{ + struct heap_free_area *fa; + size_t _size = *size; + void *mem = 0; + + _size = HEAP_ADJUST_SIZE (_size); + + if (_size < sizeof (struct heap_free_area)) + /* Because we sometimes must use a freed block to hold a free-area node, + we must make sure that every allocated block can hold one. */ + _size = HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)); + + HEAP_DEBUG (*heap, "before __heap_alloc"); + + /* Look for a free area that can contain _SIZE bytes. */ + for (fa = *heap; fa; fa = fa->next) + if (fa->size >= _size) + { + /* Found one! */ + mem = HEAP_FREE_AREA_START (fa); + *size = __heap_free_area_alloc (heap, fa, _size); + break; + } + + HEAP_DEBUG (*heap, "after __heap_alloc"); + + return mem; +} diff --git a/libc/stdlib/malloc/heap_alloc_at.c b/libc/stdlib/malloc/heap_alloc_at.c new file mode 100644 index 0000000..45d6859 --- /dev/null +++ b/libc/stdlib/malloc/heap_alloc_at.c @@ -0,0 +1,47 @@ +/* + * libc/stdlib/malloc/heap_alloc_at.c -- allocate at a specific address + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Allocate SIZE bytes at address MEM in HEAP. Return the actual size + allocated, or 0 if we failed. */ +size_t +__heap_alloc_at (struct heap_free_area **heap, void *mem, size_t size) +{ + struct heap_free_area *fa; + size_t alloced = 0; + + size = HEAP_ADJUST_SIZE (size); + + HEAP_DEBUG (*heap, "before __heap_alloc_at"); + + /* Look for a free area that can contain SIZE bytes. */ + for (fa = *heap; fa; fa = fa->next) + { + void *fa_mem = HEAP_FREE_AREA_START (fa); + if (fa_mem <= mem) + { + if (fa_mem == mem && fa->size >= size) + /* FA has the right addr, and is big enough! */ + alloced = __heap_free_area_alloc (heap, fa, size); + break; + } + } + + HEAP_DEBUG (*heap, "after __heap_alloc_at"); + + return alloced; +} diff --git a/libc/stdlib/malloc/heap_debug.c b/libc/stdlib/malloc/heap_debug.c new file mode 100644 index 0000000..59a1780 --- /dev/null +++ b/libc/stdlib/malloc/heap_debug.c @@ -0,0 +1,147 @@ +/* + * libc/stdlib/malloc/heap_debug.c -- optional heap debugging routines + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(vfprintf) +libc_hidden_proto(fprintf) +libc_hidden_proto(_exit) + +#include "malloc.h" +#include "heap.h" + + +#ifdef HEAP_DEBUGGING +int __heap_debug = 0; +#endif + + +static void +__heap_dump_freelist (struct heap_free_area *heap) +{ + struct heap_free_area *fa; + for (fa = heap; fa; fa = fa->next) + __malloc_debug_printf (0, + "0x%lx: 0x%lx - 0x%lx (%d)\tP=0x%lx, N=0x%lx", + (long)fa, + (long)HEAP_FREE_AREA_START (fa), + (long)HEAP_FREE_AREA_END (fa), + fa->size, + (long)fa->prev, + (long)fa->next); +} + +/* Output a text representation of HEAP to stderr, labelling it with STR. */ +void +__heap_dump (struct heap_free_area *heap, const char *str) +{ + static smallint recursed; + + if (! recursed) + { + __heap_check (heap, str); + + recursed = 1; + + __malloc_debug_printf (1, "%s: heap @0x%lx:", str, (long)heap); + __heap_dump_freelist (heap); + __malloc_debug_indent (-1); + + recursed = 0; + } +} + + +/* Output an error message to stderr, and exit. STR is printed with the + failure message. */ +static void attribute_noreturn +__heap_check_failure (struct heap_free_area *heap, struct heap_free_area *fa, + const char *str, char *fmt, ...) +{ + va_list val; + + if (str) + fprintf (stderr, "\nHEAP CHECK FAILURE %s: ", str); + else + fprintf (stderr, "\nHEAP CHECK FAILURE: "); + + va_start (val, fmt); + vfprintf (stderr, fmt, val); + va_end (val); + + fprintf (stderr, "\n"); + + __malloc_debug_set_indent (0); + __malloc_debug_printf (1, "heap dump:"); + __heap_dump_freelist (heap); + + _exit (22); +} + +/* Do some consistency checks on HEAP. If they fail, output an error + message to stderr, and exit. STR is printed with the failure message. */ +void +__heap_check (struct heap_free_area *heap, const char *str) +{ + typedef unsigned long ul_t; + struct heap_free_area *fa, *prev; + struct heap_free_area *first_fa = heap; + + if (first_fa && first_fa->prev) + __heap_check_failure (heap, first_fa, str, +"first free-area has non-zero prev pointer:\n\ + first free-area = 0x%lx\n\ + (0x%lx)->prev = 0x%lx\n", + (ul_t)first_fa, + (ul_t)first_fa, (ul_t)first_fa->prev); + + for (prev = 0, fa = first_fa; fa; prev = fa, fa = fa->next) + { + if (((ul_t)HEAP_FREE_AREA_END (fa) & (HEAP_GRANULARITY - 1)) + || (fa->size & (HEAP_GRANULARITY - 1))) + __heap_check_failure (heap, fa, str, "alignment error:\n\ + (0x%lx)->start = 0x%lx\n\ + (0x%lx)->size = 0x%lx\n", + (ul_t)fa, + (ul_t)HEAP_FREE_AREA_START (fa), + (ul_t)fa, fa->size); + + if (fa->prev != prev) + __heap_check_failure (heap, fa, str, "prev pointer corrupted:\n\ + (0x%lx)->next = 0x%lx\n\ + (0x%lx)->prev = 0x%lx\n", + (ul_t)prev, (ul_t)prev->next, + (ul_t)fa, (ul_t)fa->prev); + + if (prev) + { + ul_t start = (ul_t)HEAP_FREE_AREA_START (fa); + ul_t prev_end = (ul_t)HEAP_FREE_AREA_END (prev); + + if (prev_end >= start) + __heap_check_failure (heap, fa, str, + "start %s with prev free-area end:\n\ + (0x%lx)->prev = 0x%lx\n\ + (0x%lx)->start = 0x%lx\n\ + (0x%lx)->end = 0x%lx\n", + (prev_end == start ? "unmerged" : "overlaps"), + (ul_t)fa, (ul_t)prev, + (ul_t)fa, start, + (ul_t)prev, prev_end); + } + } +} diff --git a/libc/stdlib/malloc/heap_free.c b/libc/stdlib/malloc/heap_free.c new file mode 100644 index 0000000..15343c0 --- /dev/null +++ b/libc/stdlib/malloc/heap_free.c @@ -0,0 +1,89 @@ +/* + * libc/stdlib/malloc/heap_free.c -- return memory to a heap + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Return the block of memory at MEM, of size SIZE, to HEAP. */ +struct heap_free_area * +__heap_free (struct heap_free_area **heap, void *mem, size_t size) +{ + struct heap_free_area *fa, *prev_fa; + void *end = (char *)mem + size; + + HEAP_DEBUG (*heap, "before __heap_free"); + + /* Find the right position in the free-list entry to place the new block. + This is the most speed critical loop in this malloc implementation: + since we use a simple linked-list for the free-list, and we keep it in + address-sorted order, it can become very expensive to insert something + in the free-list when it becomes fragmented and long. [A better + implemention would use a balanced tree or something for the free-list, + though that bloats the code-size and complexity quite a bit.] */ + for (prev_fa = 0, fa = *heap; fa; prev_fa = fa, fa = fa->next) + if (unlikely (HEAP_FREE_AREA_END (fa) >= mem)) + break; + + if (fa && HEAP_FREE_AREA_START (fa) <= end) + /* The free-area FA is adjacent to the new block, merge them. */ + { + size_t fa_size = fa->size + size; + + if (HEAP_FREE_AREA_START (fa) == end) + /* FA is just after the new block, grow down to encompass it. */ + { + /* See if FA can now be merged with its predecessor. */ + if (prev_fa && mem == HEAP_FREE_AREA_END (prev_fa)) + /* Yup; merge PREV_FA's info into FA. */ + { + fa_size += prev_fa->size; + __heap_link_free_area_after (heap, fa, prev_fa->prev); + } + } + else + /* FA is just before the new block, expand to encompass it. */ + { + struct heap_free_area *next_fa = fa->next; + + /* See if FA can now be merged with its successor. */ + if (next_fa && end == HEAP_FREE_AREA_START (next_fa)) + /* Yup; merge FA's info into NEXT_FA. */ + { + fa_size += next_fa->size; + __heap_link_free_area_after (heap, next_fa, prev_fa); + fa = next_fa; + } + else + /* FA can't be merged; move the descriptor for it to the tail-end + of the memory block. */ + { + /* The new descriptor is at the end of the extended block, + SIZE bytes later than the old descriptor. */ + fa = (struct heap_free_area *)((char *)fa + size); + /* Update links with the neighbors in the list. */ + __heap_link_free_area (heap, fa, prev_fa, next_fa); + } + } + + fa->size = fa_size; + } + else + /* Make the new block into a separate free-list entry. */ + fa = __heap_add_free_area (heap, mem, size, prev_fa, fa); + + HEAP_DEBUG (*heap, "after __heap_free"); + + return fa; +} diff --git a/libc/stdlib/malloc/malloc.c b/libc/stdlib/malloc/malloc.c new file mode 100644 index 0000000..620a9fb --- /dev/null +++ b/libc/stdlib/malloc/malloc.c @@ -0,0 +1,234 @@ +/* + * libc/stdlib/malloc/malloc.c -- malloc function + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) +libc_hidden_proto(sbrk) + +#include "malloc.h" +#include "heap.h" + + +/* The malloc heap. We provide a bit of initial static space so that + programs can do a little mallocing without mmaping in more space. */ +HEAP_DECLARE_STATIC_FREE_AREA (initial_fa, 256); +struct heap_free_area *__malloc_heap = HEAP_INIT_WITH_FA (initial_fa); +#ifdef HEAP_USE_LOCKING +malloc_mutex_t __malloc_heap_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +#if defined(MALLOC_USE_LOCKING) && defined(MALLOC_USE_SBRK) +/* A lock protecting our use of sbrk. */ +malloc_mutex_t __malloc_sbrk_lock; +#endif /* MALLOC_USE_LOCKING && MALLOC_USE_SBRK */ + + +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +/* A list of all malloc_mmb structures describing blocks that + malloc has mmapped, ordered by the block address. */ +struct malloc_mmb *__malloc_mmapped_blocks = 0; + +/* A heap used for allocating malloc_mmb structures. We could allocate + them from the main heap, but that tends to cause heap fragmentation in + annoying ways. */ +HEAP_DECLARE_STATIC_FREE_AREA (initial_mmb_fa, 48); /* enough for 3 mmbs */ +struct heap_free_area *__malloc_mmb_heap = HEAP_INIT_WITH_FA (initial_mmb_fa); +#ifdef HEAP_USE_LOCKING +malloc_mutex_t __malloc_mmb_heap_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + +#ifdef HEAP_USE_LOCKING +#define malloc_from_heap(size, heap, lck) __malloc_from_heap(size, heap, lck) +#else +#define malloc_from_heap(size, heap, lck) __malloc_from_heap(size, heap) +#endif +static void * +__malloc_from_heap (size_t size, struct heap_free_area **heap +#ifdef HEAP_USE_LOCKING + , malloc_mutex_t *heap_lock +#endif + ) +{ + void *mem; + + MALLOC_DEBUG (1, "malloc: %d bytes", size); + + /* Include extra space to record the size of the allocated block. */ + size += MALLOC_HEADER_SIZE; + + __heap_lock (heap_lock); + + /* First try to get memory that's already in our heap. */ + mem = __heap_alloc (heap, &size); + + __heap_unlock (heap_lock); + + if (unlikely (! mem)) + /* We couldn't allocate from the heap, so grab some more + from the system, add it to the heap, and try again. */ + { + /* If we're trying to allocate a block bigger than the default + MALLOC_HEAP_EXTEND_SIZE, make sure we get enough to hold it. */ + void *block; + size_t block_size + = (size < MALLOC_HEAP_EXTEND_SIZE + ? MALLOC_HEAP_EXTEND_SIZE + : MALLOC_ROUND_UP_TO_PAGE_SIZE (size)); + + /* Allocate the new heap block. */ +#ifdef MALLOC_USE_SBRK + + __malloc_lock_sbrk (); + + /* Use sbrk we can, as it's faster than mmap, and guarantees + contiguous allocation. */ + block = sbrk (block_size); + if (likely (block != (void *)-1)) + { + /* Because sbrk can return results of arbitrary + alignment, align the result to a MALLOC_ALIGNMENT boundary. */ + long aligned_block = MALLOC_ROUND_UP ((long)block, MALLOC_ALIGNMENT); + if (block != (void *)aligned_block) + /* Have to adjust. We should only have to actually do this + the first time (after which we will have aligned the brk + correctly). */ + { + /* Move the brk to reflect the alignment; our next allocation + should start on exactly the right alignment. */ + sbrk (aligned_block - (long)block); + block = (void *)aligned_block; + } + } + + __malloc_unlock_sbrk (); + +#else /* !MALLOC_USE_SBRK */ + + /* Otherwise, use mmap. */ +#ifdef __ARCH_USE_MMU__ + block = mmap ((void *)0, block_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#else + block = mmap ((void *)0, block_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, 0, 0); +#endif + +#endif /* MALLOC_USE_SBRK */ + + if (likely (block != (void *)-1)) + { +#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__) + struct malloc_mmb *mmb, *prev_mmb, *new_mmb; +#endif + + MALLOC_DEBUG (1, "adding system memory to heap: 0x%lx - 0x%lx (%d bytes)", + (long)block, (long)block + block_size, block_size); + + /* Get back the heap lock. */ + __heap_lock (heap_lock); + + /* Put BLOCK into the heap. */ + __heap_free (heap, block, block_size); + + MALLOC_DEBUG_INDENT (-1); + + /* Try again to allocate. */ + mem = __heap_alloc (heap, &size); + + __heap_unlock (heap_lock); + +#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__) + /* Insert a record of BLOCK in sorted order into the + __malloc_mmapped_blocks list. */ + + for (prev_mmb = 0, mmb = __malloc_mmapped_blocks; + mmb; + prev_mmb = mmb, mmb = mmb->next) + if (block < mmb->mem) + break; + + new_mmb = malloc_from_heap (sizeof *new_mmb, &__malloc_mmb_heap, &__malloc_mmb_heap_lock); + new_mmb->next = mmb; + new_mmb->mem = block; + new_mmb->size = block_size; + + if (prev_mmb) + prev_mmb->next = new_mmb; + else + __malloc_mmapped_blocks = new_mmb; + + MALLOC_MMB_DEBUG (0, "new mmb at 0x%x: 0x%x[%d]", + (unsigned)new_mmb, + (unsigned)new_mmb->mem, block_size); +#endif /* !MALLOC_USE_SBRK && __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + } + } + + if (likely (mem)) + /* Record the size of the block and get the user address. */ + { + mem = MALLOC_SETUP (mem, size); + + MALLOC_DEBUG (-1, "malloc: returning 0x%lx (base:0x%lx, total_size:%ld)", + (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); + } + else + MALLOC_DEBUG (-1, "malloc: returning 0"); + + return mem; +} + +void * +malloc (size_t size) +{ + void *mem; +#ifdef MALLOC_DEBUGGING + static smallint debugging_initialized; + if (! debugging_initialized) + { + debugging_initialized = 1; + __malloc_debug_init (); + } + if (__malloc_check) + __heap_check (__malloc_heap, "malloc"); +#endif + +#ifdef __MALLOC_GLIBC_COMPAT__ + if (unlikely (size == 0)) + size++; +#else + /* Some programs will call malloc (0). Lets be strict and return NULL */ + if (unlikely (size == 0)) + goto oom; +#endif + + /* Check if they are doing something dumb like malloc(-1) */ + if (unlikely(((unsigned long)size > (unsigned long)(MALLOC_HEADER_SIZE*-2)))) + goto oom; + + mem = malloc_from_heap (size, &__malloc_heap, &__malloc_heap_lock); + if (unlikely (!mem)) + { + oom: + __set_errno (ENOMEM); + return 0; + } + + return mem; +} diff --git a/libc/stdlib/malloc/malloc.h b/libc/stdlib/malloc/malloc.h new file mode 100644 index 0000000..2afc3a8 --- /dev/null +++ b/libc/stdlib/malloc/malloc.h @@ -0,0 +1,230 @@ +/* + * libc/stdlib/malloc/malloc.h -- small malloc implementation + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +/* The alignment we guarantee for malloc return values. We prefer this + to be at least sizeof (size_t) bytes because (a) we have to allocate + that many bytes for the header anyway and (b) guaranteeing word + alignment can be a significant win on targets like m68k and Coldfire, + where __alignof__(double) == 2. */ +#define MALLOC_ALIGNMENT \ + __alignof__ (double __attribute_aligned__ (sizeof (size_t))) + +/* The system pagesize... */ +extern size_t __pagesize; +#define MALLOC_PAGE_SIZE __pagesize + +/* The minimum size of block we request from the the system to extend the + heap for small allocations (we may request a bigger block if necessary to + satisfy a particularly big request). */ +#define MALLOC_HEAP_EXTEND_SIZE MALLOC_PAGE_SIZE + +/* When a heap free-area grows above this size, try to unmap it, releasing + the memory back to the system. */ +#define MALLOC_UNMAP_THRESHOLD (8*MALLOC_PAGE_SIZE) +/* When unmapping a free-area, retain this many bytes if it's the only one, + to avoid completely emptying the heap. This is only a heuristic -- the + existance of another free area, even if it's smaller than + MALLOC_MIN_SIZE, will cause us not to reserve anything. */ +#define MALLOC_MIN_SIZE (2*MALLOC_PAGE_SIZE) + +/* When realloc shrinks an allocation, it only does so if more than this + many bytes will be freed; it must at at least HEAP_MIN_SIZE. Larger + values increase speed (by reducing heap fragmentation) at the expense of + space. */ +#define MALLOC_REALLOC_MIN_FREE_SIZE (HEAP_MIN_SIZE + 16) + + +/* For systems with an MMU, use sbrk to map/unmap memory for the malloc + heap, instead of mmap/munmap. This is a tradeoff -- sbrk is faster than + mmap/munmap, and guarantees contiguous allocation, but is also less + flexible, and causes the heap to only be shrinkable from the end. */ +#ifdef __ARCH_USE_MMU__ +# define MALLOC_USE_SBRK +#endif + + +/* The current implementation of munmap in uClinux doesn't work correctly: + it requires that ever call to munmap exactly match a corresponding call + to mmap (that is, it doesn't allow you to unmap only part of a + previously allocated block, or to unmap two contiguous blocks with a + single call to munmap). This behavior is broken, and uClinux should be + fixed; however, until it is, we add code to work around the problem in + malloc. */ +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + +/* A structure recording a block of memory mmapped by malloc. */ +struct malloc_mmb +{ + void *mem; /* the mmapped block */ + size_t size; /* its size */ + struct malloc_mmb *next; +}; + +/* A list of all malloc_mmb structures describing blocks that malloc has + mmapped, ordered by the block address. */ +extern struct malloc_mmb *__malloc_mmapped_blocks; + +/* A heap used for allocating malloc_mmb structures. We could allocate + them from the main heap, but that tends to cause heap fragmentation in + annoying ways. */ +extern struct heap_free_area *__malloc_mmb_heap; + +/* Define MALLOC_MMB_DEBUGGING to cause malloc to emit debugging info about + about mmap block allocation/freeing by the `uclinux broken munmap' code + to stderr, when the variable __malloc_mmb_debug is set to true. */ +#ifdef MALLOC_MMB_DEBUGGING +# include + +extern int __malloc_mmb_debug; +# define MALLOC_MMB_DEBUG(indent, fmt, args...) \ + (__malloc_mmb_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0) +# define MALLOC_MMB_DEBUG_INDENT(indent) \ + (__malloc_mmb_debug ? __malloc_debug_indent (indent) : 0) +# ifndef MALLOC_DEBUGGING +# define MALLOC_DEBUGGING +# endif +#else /* !MALLOC_MMB_DEBUGGING */ +# define MALLOC_MMB_DEBUG(fmt, args...) (void)0 +# define MALLOC_MMB_DEBUG_INDENT(indent) (void)0 +#endif /* MALLOC_MMB_DEBUGGING */ + +#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + +/* The size of a malloc allocation is stored in a size_t word + MALLOC_HEADER_SIZE bytes prior to the start address of the allocation: + + +--------+---------+-------------------+ + | SIZE |(unused) | allocation ... | + +--------+---------+-------------------+ + ^ BASE ^ ADDR + ^ ADDR - MALLOC_HEADER_SIZE +*/ + +/* The amount of extra space used by the malloc header. */ +#define MALLOC_HEADER_SIZE \ + (MALLOC_ALIGNMENT < sizeof (size_t) \ + ? sizeof (size_t) \ + : MALLOC_ALIGNMENT) + +/* Set up the malloc header, and return the user address of a malloc block. */ +#define MALLOC_SETUP(base, size) \ + (MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE)) +/* Set the size of a malloc allocation, given the base address. */ +#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size)) + +/* Return base-address of a malloc allocation, given the user address. */ +#define MALLOC_BASE(addr) ((void *)((char *)addr - MALLOC_HEADER_SIZE)) +/* Return the size of a malloc allocation, given the user address. */ +#define MALLOC_SIZE(addr) (*(size_t *)MALLOC_BASE(addr)) + + +/* Locking for multithreaded apps. */ +#ifdef __UCLIBC_HAS_THREADS__ + +# include +# include + +# define MALLOC_USE_LOCKING + +typedef pthread_mutex_t malloc_mutex_t; +# define MALLOC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER + +# ifdef MALLOC_USE_SBRK +/* This lock is used to serialize uses of the `sbrk' function (in both + malloc and free, sbrk may be used several times in succession, and + things will break if these multiple calls are interleaved with another + thread's use of sbrk!). */ +extern malloc_mutex_t __malloc_sbrk_lock; +# define __malloc_lock_sbrk() __pthread_mutex_lock (&__malloc_sbrk_lock) +# define __malloc_unlock_sbrk() __pthread_mutex_unlock (&__malloc_sbrk_lock) +# endif /* MALLOC_USE_SBRK */ + +#else /* !__UCLIBC_HAS_THREADS__ */ + +/* Without threads, mutex operations are a nop. */ +# define __malloc_lock_sbrk() (void)0 +# define __malloc_unlock_sbrk() (void)0 + +#endif /* __UCLIBC_HAS_THREADS__ */ + + +/* branch-prediction macros; they may already be defined by libc. */ +#ifndef likely +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define likely(cond) __builtin_expect(!!(int)(cond), 1) +#define unlikely(cond) __builtin_expect((int)(cond), 0) +#else +#define likely(cond) (cond) +#define unlikely(cond) (cond) +#endif +#endif /* !likely */ + + +/* Define MALLOC_DEBUGGING to cause malloc to emit debugging info to stderr + when the variable __malloc_debug is set to true. */ +#ifdef MALLOC_DEBUGGING + +extern void __malloc_debug_init (void); + +/* The number of spaces in a malloc debug indent level. */ +#define MALLOC_DEBUG_INDENT_SIZE 3 + +extern int __malloc_debug, __malloc_check; + +# define MALLOC_DEBUG(indent, fmt, args...) \ + (__malloc_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0) +# define MALLOC_DEBUG_INDENT(indent) \ + (__malloc_debug ? __malloc_debug_indent (indent) : 0) + +extern int __malloc_debug_cur_indent; + +/* Print FMT and args indented at the current debug print level, followed + by a newline, and change the level by INDENT. */ +extern void __malloc_debug_printf (int indent, const char *fmt, ...); + +/* Change the current debug print level by INDENT, and return the value. */ +#define __malloc_debug_indent(indent) (__malloc_debug_cur_indent += indent) + +/* Set the current debug print level to LEVEL. */ +#define __malloc_debug_set_indent(level) (__malloc_debug_cur_indent = level) + +#else /* !MALLOC_DEBUGGING */ +# define MALLOC_DEBUG(fmt, args...) (void)0 +# define MALLOC_DEBUG_INDENT(indent) (void)0 +#endif /* MALLOC_DEBUGGING */ + + +/* Return SZ rounded down to POWER_OF_2_SIZE (which must be power of 2). */ +#define MALLOC_ROUND_DOWN(sz, power_of_2_size) \ + ((sz) & ~(power_of_2_size - 1)) +/* Return SZ rounded to POWER_OF_2_SIZE (which must be power of 2). */ +#define MALLOC_ROUND_UP(sz, power_of_2_size) \ + MALLOC_ROUND_DOWN ((sz) + (power_of_2_size - 1), (power_of_2_size)) + +/* Return SZ rounded down to a multiple MALLOC_PAGE_SIZE. */ +#define MALLOC_ROUND_DOWN_TO_PAGE_SIZE(sz) \ + MALLOC_ROUND_DOWN (sz, MALLOC_PAGE_SIZE) +/* Return SZ rounded up to a multiple MALLOC_PAGE_SIZE. */ +#define MALLOC_ROUND_UP_TO_PAGE_SIZE(sz) \ + MALLOC_ROUND_UP (sz, MALLOC_PAGE_SIZE) + + +/* The malloc heap. */ +extern struct heap_free_area *__malloc_heap; +#ifdef __UCLIBC_HAS_THREADS__ +extern malloc_mutex_t __malloc_heap_lock; +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +extern malloc_mutex_t __malloc_mmb_heap_lock; +#endif +#endif diff --git a/libc/stdlib/malloc/malloc_debug.c b/libc/stdlib/malloc/malloc_debug.c new file mode 100644 index 0000000..39c3919 --- /dev/null +++ b/libc/stdlib/malloc/malloc_debug.c @@ -0,0 +1,91 @@ +/* + * libc/stdlib/malloc/malloc_debug.c -- malloc debugging support + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +libc_hidden_proto(atoi) +libc_hidden_proto(vfprintf) +libc_hidden_proto(putc) +libc_hidden_proto(getenv) + +#include "malloc.h" +#include "heap.h" + +int __malloc_debug = 0, __malloc_check = 0; + +#ifdef MALLOC_MMB_DEBUGGING +int __malloc_mmb_debug = 0; +#endif + +/* Debugging output is indented this may levels. */ +int __malloc_debug_cur_indent = 0; + + +/* Print FMT and args indented at the current debug print level, followed + by a newline, and change the level by INDENT. */ +void +__malloc_debug_printf (int indent, const char *fmt, ...) +{ + unsigned spaces = __malloc_debug_cur_indent * MALLOC_DEBUG_INDENT_SIZE; + va_list val; + + while (spaces > 0) + { + putc (' ', stderr); + spaces--; + } + + va_start (val, fmt); + vfprintf (stderr, fmt, val); + va_end (val); + + putc ('\n', stderr); + + __malloc_debug_indent (indent); +} + +void +__malloc_debug_init (void) +{ + char *ev = getenv ("MALLOC_DEBUG"); + if (ev) + { + int val = atoi (ev); + + if (val & 1) + __malloc_check = 1; + + if (val & 2) + __malloc_debug = 1; + +#ifdef MALLOC_MMB_DEBUGGING + if (val & 4) + __malloc_mmb_debug = 1; +#endif + +#ifdef HEAP_DEBUGGING + if (val & 8) + __heap_debug = 1; +#endif + + if (val) + __malloc_debug_printf + (0, "malloc_debug: initialized to %d (check = %d, dump = %d, dump_mmb = %d, dump_heap = %d)", + val, + !!(val & 1), !!(val & 2), + !!(val & 4), !!(val & 8)); + } +} diff --git a/libc/stdlib/malloc/memalign.c b/libc/stdlib/malloc/memalign.c new file mode 100644 index 0000000..6826d62 --- /dev/null +++ b/libc/stdlib/malloc/memalign.c @@ -0,0 +1,95 @@ +/* + * libc/stdlib/malloc/memalign.c -- memalign (`aligned malloc') function + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#include "malloc.h" +#include "heap.h" + + +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +/* + ______________________ TOTAL _________________________ + / \ + +---------------+-------------------------+--------------+ + | | | | + +---------------+-------------------------+--------------+ + \____ INIT ____/ \______ RETURNED _______/ \____ END ___/ +*/ + +void *memalign (size_t alignment, size_t size); +void * +memalign (size_t alignment, size_t size) +{ + void *mem, *base; + unsigned long tot_addr, tot_end_addr, addr, end_addr; + struct heap_free_area **heap = &__malloc_heap; + + /* Make SIZE something we like. */ + size = HEAP_ADJUST_SIZE (size); + + /* Use malloc to do the initial allocation, since it deals with getting + system memory. We over-allocate enough to be sure that we'll get + enough memory to hold a properly aligned block of size SIZE, + _somewhere_ in the result. */ + mem = malloc (size + 2 * alignment); + if (! mem) + /* Allocation failed, we can't do anything. */ + return 0; + if (alignment < MALLOC_ALIGNMENT) + return mem; + + /* Remember the base-address, of the allocation, although we normally + use the user-address for calculations, since that's where the + alignment matters. */ + base = MALLOC_BASE (mem); + + /* The bounds of the initial allocation. */ + tot_addr = (unsigned long)mem; + tot_end_addr = (unsigned long)base + MALLOC_SIZE (mem); + + /* Find a likely place inside MEM with the right alignment. */ + addr = MALLOC_ROUND_UP (tot_addr, alignment); + + /* Unless TOT_ADDR was already aligned correctly, we need to return the + initial part of MEM to the heap. */ + if (addr != tot_addr) + { + size_t init_size = addr - tot_addr; + + /* Ensure that memory returned to the heap is large enough. */ + if (init_size < HEAP_MIN_SIZE) + { + addr = MALLOC_ROUND_UP (tot_addr + HEAP_MIN_SIZE, alignment); + init_size = addr - tot_addr; + } + + __heap_free (heap, base, init_size); + + /* Remember that we've freed the initial part of MEM. */ + base += init_size; + } + + /* Return the end part of MEM to the heap, unless it's too small. */ + end_addr = addr + size; + if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr) + __heap_free (heap, (void *)end_addr, tot_end_addr - end_addr); + else + /* We didn't free the end, so include it in the size. */ + end_addr = tot_end_addr; + + return MALLOC_SETUP (base, end_addr - (unsigned long)base); +} diff --git a/libc/stdlib/malloc/realloc.c b/libc/stdlib/malloc/realloc.c new file mode 100644 index 0000000..a827199 --- /dev/null +++ b/libc/stdlib/malloc/realloc.c @@ -0,0 +1,98 @@ +/* + * libc/stdlib/malloc/realloc.c -- realloc function + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +#include "malloc.h" +#include "heap.h" + + +void * +realloc (void *mem, size_t new_size) +{ + size_t size; + char *base_mem; + + /* Check for special cases. */ + if (! new_size) + { + free (mem); + return malloc (new_size); + } + if (! mem) + return malloc (new_size); + + /* Normal realloc. */ + + base_mem = MALLOC_BASE (mem); + size = MALLOC_SIZE (mem); + + /* Include extra space to record the size of the allocated block. + Also make sure that we're dealing in a multiple of the heap + allocation unit (SIZE is already guaranteed to be so).*/ + new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE); + + if (new_size < sizeof (struct heap_free_area)) + /* Because we sometimes must use a freed block to hold a free-area node, + we must make sure that every allocated block can hold one. */ + new_size = HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)); + + MALLOC_DEBUG (1, "realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)", + (long)mem, new_size, (long)base_mem, size); + + if (new_size > size) + /* Grow the block. */ + { + size_t extra = new_size - size; + + __heap_lock (&__malloc_heap_lock); + extra = __heap_alloc_at (&__malloc_heap, base_mem + size, extra); + __heap_unlock (&__malloc_heap_lock); + + if (extra) + /* Record the changed size. */ + MALLOC_SET_SIZE (base_mem, size + extra); + else + /* Our attempts to extend MEM in place failed, just + allocate-and-copy. */ + { + void *new_mem = malloc (new_size - MALLOC_HEADER_SIZE); + if (new_mem) + { + memcpy (new_mem, mem, size - MALLOC_HEADER_SIZE); + free (mem); + } + mem = new_mem; + } + } + else if (new_size + MALLOC_REALLOC_MIN_FREE_SIZE <= size) + /* Shrink the block. */ + { + __heap_lock (&__malloc_heap_lock); + __heap_free (&__malloc_heap, base_mem + new_size, size - new_size); + __heap_unlock (&__malloc_heap_lock); + MALLOC_SET_SIZE (base_mem, new_size); + } + + if (mem) + MALLOC_DEBUG (-1, "realloc: returning 0x%lx (base:0x%lx, total_size:%d)", + (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); + else + MALLOC_DEBUG (-1, "realloc: returning 0"); + + return mem; +} diff --git a/libc/stdlib/mblen.c b/libc/stdlib/mblen.c new file mode 100644 index 0000000..c7a0ccb --- /dev/null +++ b/libc/stdlib/mblen.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mblen +#include "stdlib.c" diff --git a/libc/stdlib/mbstowcs.c b/libc/stdlib/mbstowcs.c new file mode 100644 index 0000000..f618003 --- /dev/null +++ b/libc/stdlib/mbstowcs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbstowcs +#include "stdlib.c" diff --git a/libc/stdlib/mbtowc.c b/libc/stdlib/mbtowc.c new file mode 100644 index 0000000..5d888d1 --- /dev/null +++ b/libc/stdlib/mbtowc.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbtowc +#include "stdlib.c" diff --git a/libc/stdlib/mkdtemp.c b/libc/stdlib/mkdtemp.c new file mode 100644 index 0000000..fa9ae3b --- /dev/null +++ b/libc/stdlib/mkdtemp.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +#ifdef __USE_BSD +/* Generate a unique temporary directory name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * mkdtemp (char *template) +{ + if (__gen_tempname (template, __GT_DIR)) + return NULL; + else + return template; +} +#endif diff --git a/libc/stdlib/mkstemp.c b/libc/stdlib/mkstemp.c new file mode 100644 index 0000000..c569cea --- /dev/null +++ b/libc/stdlib/mkstemp.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int mkstemp (char *template) +{ + return __gen_tempname (template, __GT_FILE); +} diff --git a/libc/stdlib/mkstemp64.c b/libc/stdlib/mkstemp64.c new file mode 100644 index 0000000..02a03f0 --- /dev/null +++ b/libc/stdlib/mkstemp64.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int mkstemp64 (char *template) +{ + return __gen_tempname (template, __GT_BIGFILE); +} diff --git a/libc/stdlib/mktemp.c b/libc/stdlib/mktemp.c new file mode 100644 index 0000000..f3af1c1 --- /dev/null +++ b/libc/stdlib/mktemp.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + * The last six characters of TEMPLATE must be "XXXXXX"; + * they are replaced with a string that makes the filename unique. */ +char *mktemp(char *template) +{ + if (__gen_tempname (template, __GT_NOCREATE) < 0) + /* We return the null string if we can't find a unique file name. */ + template[0] = '\0'; + + return template; +} + +link_warning(mktemp, "the use of `mktemp' is dangerous, better use `mkstemp'") diff --git a/libc/stdlib/mrand48.c b/libc/stdlib/mrand48.c new file mode 100644 index 0000000..6905545 --- /dev/null +++ b/libc/stdlib/mrand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(jrand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int mrand48 (void) +{ + long int result; + + jrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/mrand48_r.c b/libc/stdlib/mrand48_r.c new file mode 100644 index 0000000..ca2bd7b --- /dev/null +++ b/libc/stdlib/mrand48_r.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(jrand48_r) + +int mrand48_r (struct drand48_data *buffer, long int *result) +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return jrand48_r (buffer->__x, buffer, result); +} diff --git a/libc/stdlib/nrand48.c b/libc/stdlib/nrand48.c new file mode 100644 index 0000000..0199a30 --- /dev/null +++ b/libc/stdlib/nrand48.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(nrand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int nrand48 (unsigned short int xsubi[3]) +{ + long int result; + + nrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/libc/stdlib/nrand48_r.c b/libc/stdlib/nrand48_r.c new file mode 100644 index 0000000..63b0ac8 --- /dev/null +++ b/libc/stdlib/nrand48_r.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +libc_hidden_proto(nrand48_r) +int nrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + if (sizeof (unsigned short int) == 2) + *result = xsubi[2] << 15 | xsubi[1] >> 1; + else + *result = xsubi[2] >> 1; + + return 0; +} +libc_hidden_def(nrand48_r) diff --git a/libc/stdlib/old_atexit.c b/libc/stdlib/old_atexit.c new file mode 100644 index 0000000..b15fd0a --- /dev/null +++ b/libc/stdlib/old_atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_old_atexit +#include "_atexit.c" diff --git a/libc/stdlib/on_exit.c b/libc/stdlib/on_exit.c new file mode 100644 index 0000000..cb943ac --- /dev/null +++ b/libc/stdlib/on_exit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_on_exit +#include "_atexit.c" diff --git a/libc/stdlib/posix_memalign.c b/libc/stdlib/posix_memalign.c new file mode 100644 index 0000000..115fb89 --- /dev/null +++ b/libc/stdlib/posix_memalign.c @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* posix_memalign for uClibc + * + * Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2005 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +int posix_memalign(void **memptr, size_t alignment, size_t size) +{ + /* Make sure alignment is correct. */ + if (alignment % sizeof(void *) != 0) + /* Skip these checks because the memalign() func does them for us + || !powerof2(alignment / sizeof(void *)) != 0 + || alignment == 0 + */ + return EINVAL; + + *memptr = memalign(alignment, size); + + return (*memptr != NULL ? 0 : ENOMEM); +} diff --git a/libc/stdlib/ptsname.c b/libc/stdlib/ptsname.c new file mode 100644 index 0000000..bd9c3ca --- /dev/null +++ b/libc/stdlib/ptsname.c @@ -0,0 +1,200 @@ +/* Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(isatty) +libc_hidden_proto(ioctl) +libc_hidden_proto(fstat) +libc_hidden_proto(stat) + +#if !defined __UNIX98PTY_ONLY__ + +/* Check if DEV corresponds to a master pseudo terminal device. */ +#define MASTER_P(Dev) \ + (major ((Dev)) == 2 \ + || (major ((Dev)) == 4 && minor ((Dev)) >= 128 && minor ((Dev)) < 192) \ + || (major ((Dev)) >= 128 && major ((Dev)) < 136)) + +/* Check if DEV corresponds to a slave pseudo terminal device. */ +#define SLAVE_P(Dev) \ + (major ((Dev)) == 3 \ + || (major ((Dev)) == 4 && minor ((Dev)) >= 192 && minor ((Dev)) < 256) \ + || (major ((Dev)) >= 136 && major ((Dev)) < 144)) + +/* Note that major number 4 corresponds to the old BSD style pseudo + terminal devices. As of Linux 2.1.115 these are no longer + supported. They have been replaced by major numbers 2 (masters) + and 3 (slaves). */ + +/* The are declared in getpt.c. */ +extern const char __libc_ptyname1[] attribute_hidden; +extern const char __libc_ptyname2[] attribute_hidden; + +#endif + +/* Directory where we can find the slave pty nodes. */ +#define _PATH_DEVPTS "/dev/pts/" + +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +libc_hidden_proto(ptsname_r) +int ptsname_r (int fd, char *buf, size_t buflen) +{ + int save_errno = errno; +#if !defined __UNIX98PTY_ONLY__ + struct stat st; +#endif + int ptyno; + + if (buf == NULL) + { + errno = EINVAL; + return EINVAL; + } + +#if !defined __UNIX98PTY_ONLY__ + if (!isatty (fd)) + { + errno = ENOTTY; + return ENOTTY; + } +#elif !defined TIOCGPTN +# error "__UNIX98PTY_ONLY__ enabled but TIOCGPTN ioctl not supported by your kernel." +#endif +#ifdef TIOCGPTN + if (ioctl (fd, TIOCGPTN, &ptyno) == 0) + { + /* Buffer we use to print the number in. */ + char numbuf[__BUFLEN_INT10TOSTR]; + static const char devpts[] = _PATH_DEVPTS; + char *p; + + p = _int10tostr(&numbuf[sizeof numbuf - 1], ptyno); + + if (buflen < sizeof(devpts) + (size_t)(&numbuf[sizeof(numbuf) - 1] - p)) + { + errno = ERANGE; + return ERANGE; + } + + strcpy (buf, devpts); + strcat (buf, p); + /* Note: Don't bother with stat on the slave name and checking the + driver's major device number - the ioctl above succeeded so + we know the fd was a Unix'98 master and the /dev/pts/ prefix + is set by definition. If the name isn't really a slave PTY, + the system is misconfigured anyway - something else will fail + later. + */ + errno = save_errno; + return 0; + } +#endif +#if defined __UNIX98PTY_ONLY__ + else + { + /* If the ioctl fails it wasn't a Unix 98 master PTY */ + errno = ENOTTY; + return ENOTTY; + } +#else +# if defined TIOCGPTN + else if (errno == EINVAL) +# endif + { + char *p; + + if (buflen < strlen (_PATH_TTY) + 3) + { + errno = ERANGE; + return ERANGE; + } + + if (fstat (fd, &st) < 0) + return errno; + + /* Check if FD really is a master pseudo terminal. */ + if (! MASTER_P (st.st_rdev)) + { + errno = ENOTTY; + return ENOTTY; + } + + ptyno = minor (st.st_rdev); + /* This is for the old BSD pseudo terminals. As of Linux + 2.1.115 these are no longer supported. */ + if (major (st.st_rdev) == 4) + ptyno -= 128; + + if (ptyno / 16 >= strlen (__libc_ptyname1)) + { + errno = ENOTTY; + return ENOTTY; + } + + strcpy (buf, _PATH_TTY); + p = buf + strlen (buf); + p[0] = __libc_ptyname1[ptyno / 16]; + p[1] = __libc_ptyname2[ptyno % 16]; + p[2] = '\0'; + } + + if (stat(buf, &st) < 0) + return errno; + + /* Check if the name we're about to return really corresponds to a + slave pseudo terminal. */ + if (! S_ISCHR (st.st_mode) || ! SLAVE_P (st.st_rdev)) + { + /* This really is a configuration problem. */ + errno = ENOTTY; + return ENOTTY; + } +#endif + + errno = save_errno; + return 0; +} +libc_hidden_def(ptsname_r) + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +char * +ptsname (int fd) +{ + static char buffer[sizeof (_PATH_DEVPTS) + 20]; + + return ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer; +} diff --git a/libc/stdlib/pty-private.h b/libc/stdlib/pty-private.h new file mode 100644 index 0000000..621dbfd --- /dev/null +++ b/libc/stdlib/pty-private.h @@ -0,0 +1,42 @@ +/* Internal defenitions and declarations for pseudo terminal functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PTY_PRIVATE_H +#define _PTY_PRIVATE_H 1 + +/* The group slave pseudo terminals belong to. */ +#define TTY_GROUP "tty" + +/* The file descriptor connected to the master pseudo terminal. */ +#define PTY_FILENO 3 + +/* Path to the helper program that implements `grantpt' in user space. */ +#define _PATH_PT_CHOWN "/sbin/pt_chown" + +/* Exit codes for the helper program. */ +enum /* failure modes */ +{ + FAIL_EBADF = 1, + FAIL_EINVAL, + FAIL_EACCES, + FAIL_EXEC +}; + +#endif /* pty-private.h */ diff --git a/libc/stdlib/qsort.c b/libc/stdlib/qsort.c new file mode 100644 index 0000000..31fc2ea --- /dev/null +++ b/libc/stdlib/qsort.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_qsort +#include "stdlib.c" diff --git a/libc/stdlib/rand.c b/libc/stdlib/rand.c new file mode 100644 index 0000000..03323f5 --- /dev/null +++ b/libc/stdlib/rand.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * rand for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +libc_hidden_proto(random) + +int rand (void) +{ + return((int)random()); +} + diff --git a/libc/stdlib/rand_r.c b/libc/stdlib/rand_r.c new file mode 100644 index 0000000..6100440 --- /dev/null +++ b/libc/stdlib/rand_r.c @@ -0,0 +1,48 @@ +/* Reentrant random function frm POSIX.1c. + Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* This algorithm is mentioned in the ISO C standard, here extended + for 32 bits. */ +int rand_r (unsigned int *seed) +{ + unsigned int next = *seed; + int result; + + next *= 1103515245; + next += 12345; + result = (unsigned int) (next / 65536) % 2048; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + *seed = next; + + return result; +} diff --git a/libc/stdlib/random.c b/libc/stdlib/random.c new file mode 100644 index 0000000..3eb8aed --- /dev/null +++ b/libc/stdlib/random.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to use reentrant functions by Ulrich Drepper, 1995. + */ + +#include +#include +#include +#include + +libc_hidden_proto(random_r) +libc_hidden_proto(srandom_r) +libc_hidden_proto(setstate_r) +libc_hidden_proto(initstate_r) + +/* POSIX.1c requires that there is mutual exclusion for the `rand' and + `srand' functions to prevent concurrent calls from modifying common + data. */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least this many + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +static int32_t randtbl[DEG_3 + 1] = +{ + TYPE_3, + + -1726662223, 379960547, 1735697613, 1040273694, 1313901226, + 1627687941, -179304937, -2073333483, 1780058412, -1989503057, + -615974602, 344556628, 939512070, -1249116260, 1507946756, + -812545463, 154635395, 1388815473, -1926676823, 525320961, + -1009028674, 968117788, -123449607, 1284210865, 435012392, + -2017506339, -911064859, -370259173, 1132637927, 1398500161, + -205601318, +}; + + +static struct random_data unsafe_state = +{ + /* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + + fptr : &randtbl[SEP_3 + 1], + rptr : &randtbl[1], + + /* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + + state : &randtbl[1], + + rand_type : TYPE_3, + rand_deg : DEG_3, + rand_sep : SEP_3, + + end_ptr : &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] +}; + + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +void srandom (unsigned int x) +{ + __UCLIBC_MUTEX_LOCK(mylock); + srandom_r (x, &unsafe_state); + __UCLIBC_MUTEX_UNLOCK(mylock); +} +strong_alias(srandom,srand) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +char * initstate (unsigned int seed, char *arg_state, size_t n) +{ + int32_t *ostate; + + __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + initstate_r (seed, arg_state, n, &unsafe_state); + __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; +} + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +char * setstate (char *arg_state) +{ + int32_t *ostate; + + __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + if (setstate_r (arg_state, &unsafe_state) < 0) + ostate = NULL; + __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; +} + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +libc_hidden_proto(random) +long int random (void) +{ + int32_t retval; + + __UCLIBC_MUTEX_LOCK(mylock); + random_r (&unsafe_state, &retval); + __UCLIBC_MUTEX_UNLOCK(mylock); + return retval; +} +libc_hidden_def(random) diff --git a/libc/stdlib/random_r.c b/libc/stdlib/random_r.c new file mode 100644 index 0000000..ca80a78 --- /dev/null +++ b/libc/stdlib/random_r.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to be reentrant by Ulrich Drepper, 1995 + */ + +#include +#include +#include +#include +#include + + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least this many + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + +struct random_poly_info +{ + int seps[MAX_TYPES]; + int degrees[MAX_TYPES]; +}; + +static const struct random_poly_info random_poly_info = +{ + { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, + { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } +}; + + + + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +libc_hidden_proto(random_r) +int random_r(struct random_data *buf, int32_t *result) +{ + int32_t *state; + + if (buf == NULL || result == NULL) + goto fail; + + state = buf->state; + + if (buf->rand_type == TYPE_0) + { + int32_t val = state[0]; + val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; + state[0] = val; + *result = val; + } + else + { + int32_t *fptr = buf->fptr; + int32_t *rptr = buf->rptr; + int32_t *end_ptr = buf->end_ptr; + int32_t val; + + val = *fptr += *rptr; + /* Chucking least random bit. */ + *result = (val >> 1) & 0x7fffffff; + ++fptr; + if (fptr >= end_ptr) + { + fptr = state; + ++rptr; + } + else + { + ++rptr; + if (rptr >= end_ptr) + rptr = state; + } + buf->fptr = fptr; + buf->rptr = rptr; + } + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(random_r) + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +libc_hidden_proto(srandom_r) +int srandom_r (unsigned int seed, struct random_data *buf) +{ + int type; + int32_t *state; + long int i; + long int word; + int32_t *dst; + int kc; + + if (buf == NULL) + goto fail; + type = buf->rand_type; + if ((unsigned int) type >= MAX_TYPES) + goto fail; + + state = buf->state; + /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ + if (seed == 0) + seed = 1; + state[0] = seed; + if (type == TYPE_0) + goto done; + + dst = state; + word = seed; + kc = buf->rand_deg; + for (i = 1; i < kc; ++i) + { + /* This does: + state[i] = (16807 * state[i - 1]) % 2147483647; + but avoids overflowing 31 bits. */ + long int hi = word / 127773; + long int lo = word % 127773; + word = 16807 * lo - 2836 * hi; + if (word < 0) + word += 2147483647; + *++dst = word; + } + + buf->fptr = &state[buf->rand_sep]; + buf->rptr = &state[0]; + kc *= 10; + while (--kc >= 0) + { + int32_t discard; + (void) random_r (buf, &discard); + } + +done: + return 0; + +fail: + return -1; +} +libc_hidden_def(srandom_r) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +libc_hidden_proto(initstate_r) +int initstate_r (unsigned int seed, char *arg_state, size_t n, struct random_data *buf) +{ + int type; + int degree; + int separation; + int32_t *state; + + if (buf == NULL) + goto fail; + + if (n >= BREAK_3) + type = n < BREAK_4 ? TYPE_3 : TYPE_4; + else if (n < BREAK_1) + { + if (n < BREAK_0) + { + __set_errno (EINVAL); + goto fail; + } + type = TYPE_0; + } + else + type = n < BREAK_2 ? TYPE_1 : TYPE_2; + + degree = random_poly_info.degrees[type]; + separation = random_poly_info.seps[type]; + + buf->rand_type = type; + buf->rand_sep = separation; + buf->rand_deg = degree; + state = &((int32_t *) arg_state)[1]; /* First location. */ + /* Must set END_PTR before srandom. */ + buf->end_ptr = &state[degree]; + + buf->state = state; + + srandom_r (seed, buf); + + state[-1] = TYPE_0; + if (type != TYPE_0) + state[-1] = (buf->rptr - state) * MAX_TYPES + type; + + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(initstate_r) + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +libc_hidden_proto(setstate_r) +int setstate_r (char *arg_state, struct random_data *buf) +{ + int32_t *new_state = 1 + (int32_t *) arg_state; + int type; + int old_type; + int32_t *old_state; + int degree; + int separation; + + if (arg_state == NULL || buf == NULL) + goto fail; + + old_type = buf->rand_type; + old_state = buf->state; + if (old_type == TYPE_0) + old_state[-1] = TYPE_0; + else + old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; + + type = new_state[-1] % MAX_TYPES; + if (type < TYPE_0 || type > TYPE_4) + goto fail; + + buf->rand_deg = degree = random_poly_info.degrees[type]; + buf->rand_sep = separation = random_poly_info.seps[type]; + buf->rand_type = type; + + if (type != TYPE_0) + { + int rear = new_state[-1] / MAX_TYPES; + buf->rptr = &new_state[rear]; + buf->fptr = &new_state[(rear + separation) % degree]; + } + buf->state = new_state; + /* Set end_ptr too. */ + buf->end_ptr = &new_state[degree]; + + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(setstate_r) diff --git a/libc/stdlib/realpath.c b/libc/stdlib/realpath.c new file mode 100644 index 0000000..e9eabdf --- /dev/null +++ b/libc/stdlib/realpath.c @@ -0,0 +1,172 @@ +/* + * realpath.c -- canonicalize pathname by removing symlinks + * Copyright (C) 1993 Rick Sladkey + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include /* for MAXPATHLEN */ +#include +#include + +#include /* for S_IFLNK */ + +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(readlink) +libc_hidden_proto(getcwd) + +#ifndef PATH_MAX +#ifdef _POSIX_VERSION +#define PATH_MAX _POSIX_PATH_MAX +#else +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +#define MAX_READLINKS 32 + +#ifdef __STDC__ +char *realpath(const char *path, char got_path[]) +#else +char *realpath(path, got_path) +const char *path; +char got_path[]; +#endif +{ + char copy_path[PATH_MAX]; + /* use user supplied buffer directly - reduces stack usage */ + /* char got_path[PATH_MAX]; */ + char *max_path; + char *new_path; + size_t path_len; + int readlinks = 0; +#ifdef S_IFLNK + int link_len; +#endif + + if (path == NULL) { + __set_errno(EINVAL); + return NULL; + } + if (*path == '\0') { + __set_errno(ENOENT); + return NULL; + } + /* Make a copy of the source path since we may need to modify it. */ + path_len = strlen(path); + if (path_len >= PATH_MAX - 2) { + __set_errno(ENAMETOOLONG); + return NULL; + } + /* Copy so that path is at the end of copy_path[] */ + strcpy(copy_path + (PATH_MAX-1) - path_len, path); + path = copy_path + (PATH_MAX-1) - path_len; + max_path = got_path + PATH_MAX - 2; /* points to last non-NUL char */ + new_path = got_path; + if (*path != '/') { + /* If it's a relative pathname use getcwd for starters. */ + if (!getcwd(new_path, PATH_MAX - 1)) + return NULL; + new_path += strlen(new_path); + if (new_path[-1] != '/') + *new_path++ = '/'; + } else { + *new_path++ = '/'; + path++; + } + /* Expand each slash-separated pathname component. */ + while (*path != '\0') { + /* Ignore stray "/". */ + if (*path == '/') { + path++; + continue; + } + if (*path == '.') { + /* Ignore ".". */ + if (path[1] == '\0' || path[1] == '/') { + path++; + continue; + } + if (path[1] == '.') { + if (path[2] == '\0' || path[2] == '/') { + path += 2; + /* Ignore ".." at root. */ + if (new_path == got_path + 1) + continue; + /* Handle ".." by backing up. */ + while ((--new_path)[-1] != '/'); + continue; + } + } + } + /* Safely copy the next pathname component. */ + while (*path != '\0' && *path != '/') { + if (new_path > max_path) { + __set_errno(ENAMETOOLONG); + return NULL; + } + *new_path++ = *path++; + } +#ifdef S_IFLNK + /* Protect against infinite loops. */ + if (readlinks++ > MAX_READLINKS) { + __set_errno(ELOOP); + return NULL; + } + path_len = strlen(path); + /* See if last (so far) pathname component is a symlink. */ + *new_path = '\0'; + { + int sv_errno = errno; + link_len = readlink(got_path, copy_path, PATH_MAX - 1); + if (link_len < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) { + return NULL; + } + } else { + /* Safe sex check. */ + if (path_len + link_len >= PATH_MAX - 2) { + __set_errno(ENAMETOOLONG); + return NULL; + } + /* Note: readlink doesn't add the null byte. */ + /* copy_path[link_len] = '\0'; - we don't need it too */ + if (*copy_path == '/') + /* Start over for an absolute symlink. */ + new_path = got_path; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/'); + /* Prepend symlink contents to path. */ + memmove(copy_path + (PATH_MAX-1) - link_len - path_len, copy_path, link_len); + path = copy_path + (PATH_MAX-1) - link_len - path_len; + } + __set_errno(sv_errno); + } +#endif /* S_IFLNK */ + *new_path++ = '/'; + } + /* Delete trailing slash but don't whomp a lone slash. */ + if (new_path != got_path + 1 && new_path[-1] == '/') + new_path--; + /* Make sure it's null terminated. */ + *new_path = '\0'; + return got_path; +} diff --git a/libc/stdlib/seed48.c b/libc/stdlib/seed48.c new file mode 100644 index 0000000..f068b98 --- /dev/null +++ b/libc/stdlib/seed48.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(seed48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +unsigned short int * +seed48 (unsigned short int seed16v[3]) +{ + (void) seed48_r (seed16v, &__libc_drand48_data); + return __libc_drand48_data.__old_x; +} diff --git a/libc/stdlib/seed48_r.c b/libc/stdlib/seed48_r.c new file mode 100644 index 0000000..3769e0f --- /dev/null +++ b/libc/stdlib/seed48_r.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +libc_hidden_proto(seed48_r) +int seed48_r (unsigned short int seed16v[3], struct drand48_data *buffer) +{ + /* Save old value at a private place to be used as return value. */ + memcpy (buffer->__old_x, buffer->__x, sizeof (buffer->__x)); + + /* Install new state. */ + buffer->__x[2] = seed16v[2]; + buffer->__x[1] = seed16v[1]; + buffer->__x[0] = seed16v[0]; + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +libc_hidden_def(seed48_r) diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c new file mode 100644 index 0000000..833bd8f --- /dev/null +++ b/libc/stdlib/setenv.c @@ -0,0 +1,206 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + modified for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +/* Experimentally off - libc_hidden_proto(strndup) */ +libc_hidden_proto(unsetenv) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +/* If this variable is not a null pointer we allocated the current + environment. */ +static char **last_environ; + + +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. */ +int __add_to_environ (const char *name, const char *value, + const char *combined, int replace) attribute_hidden; +int __add_to_environ (const char *name, const char *value, + const char *combined, int replace) +{ + register char **ep; + register size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; + int rv = -1; + + __UCLIBC_MUTEX_LOCK(mylock); + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) { + for (; *ep != NULL; ++ep) { + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } + } + + if (ep == NULL || *ep == NULL) { + char **new_environ; + + /* We allocated this space; we can extend it. */ + new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *)); + if (new_environ == NULL) { + goto DONE; + } + + /* If the whole entry is given add it. */ + if (combined != NULL) { + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + } else { + /* See whether the value is already known. */ + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (new_environ[size] == NULL) { + __set_errno (ENOMEM); + goto DONE; + } + + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); + } + + if (__environ != last_environ) { + memcpy ((char *) new_environ, (char *) __environ, + size * sizeof (char *)); + } + + new_environ[size + 1] = NULL; + last_environ = __environ = new_environ; + } else if (replace) { + char *np; + + /* Use the user string if given. */ + if (combined != NULL) { + np = (char *) combined; + } else { + np = malloc (namelen + 1 + vallen); + if (np == NULL) { + goto DONE; + } + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); + } + *ep = np; + } + + rv = 0; + + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; +} + +libc_hidden_proto(setenv) +int setenv (const char *name, const char *value, int replace) +{ + return __add_to_environ (name, value, NULL, replace); +} +libc_hidden_def(setenv) + +libc_hidden_proto(unsetenv) +int unsetenv (const char *name) +{ + size_t len; + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { + __set_errno (EINVAL); + return -1; + } + + len = strlen (name); + __UCLIBC_MUTEX_LOCK(mylock); + ep = __environ; + while (*ep != NULL) { + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + do { + dp[0] = dp[1]; + } while (*dp++); + /* Continue the loop in case NAME appears again. */ + } else { + ++ep; + } + } + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; +} +libc_hidden_def(unsetenv) + +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int clearenv (void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (__environ == last_environ && __environ != NULL) { + /* We allocated this environment so we can free it. */ + free (__environ); + last_environ = NULL; + } + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; +} + +/* Put STRING, which is of the form "NAME=VALUE", in the environment. */ +int putenv (char *string) +{ + int result; + const char *const name_end = strchr (string, '='); + + if (name_end != NULL) { + char *name = strndup(string, name_end - string); + result = __add_to_environ (name, NULL, string, 1); + free(name); + return(result); + } + unsetenv (string); + return 0; +} + diff --git a/libc/stdlib/srand48.c b/libc/stdlib/srand48.c new file mode 100644 index 0000000..42e90c9 --- /dev/null +++ b/libc/stdlib/srand48.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(srand48_r) + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +void srand48 (long seedval) +{ + srand48_r (seedval, &__libc_drand48_data); +} diff --git a/libc/stdlib/srand48_r.c b/libc/stdlib/srand48_r.c new file mode 100644 index 0000000..45bb75f --- /dev/null +++ b/libc/stdlib/srand48_r.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libc_hidden_proto(srand48_r) +int srand48_r (long int seedval, struct drand48_data *buffer) +{ + /* The standards say we only have 32 bits. */ + if (sizeof (long int) > 4) + seedval &= 0xffffffffl; + + buffer->__x[2] = seedval >> 16; + buffer->__x[1] = seedval & 0xffffl; + buffer->__x[0] = 0x330e; + + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +libc_hidden_def(srand48_r) diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c new file mode 100644 index 0000000..3c74be7 --- /dev/null +++ b/libc/stdlib/stdlib.c @@ -0,0 +1,1177 @@ +/* Copyright (C) 2002 Manuel Novoa III + * From my (incomplete) stdlib library for linux and (soon) elks. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +/* Oct 29, 2002 + * Fix a couple of 'restrict' bugs in mbstowcs and wcstombs. + * + * Nov 21, 2002 + * Add wscto{inttype} functions. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include +#include +/* Work around gcc's refusal to create aliases. + * TODO: Add in a define to disable the aliases? */ + +#if UINT_MAX == ULONG_MAX +#ifdef L_labs +#define abs __ignore_abs +#endif +#ifdef L_atol +#define atoi __ignore_atoi +#endif +#endif +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_labs +#define llabs __ignore_llabs +#endif +#ifdef L_atol +#define atoll __ignore_atoll +#endif +#ifdef L_strtol +#define strtoll __ignore_strtoll +#endif +#ifdef L_strtoul +#define strtoull __ignore_strtoull +#endif +#ifdef L_wcstol +#define wcstoll __ignore_wcstoll +#endif +#ifdef L_wcstoul +#define wcstoull __ignore_wcstoull +#endif +#ifdef L_strtol_l +#define strtoll_l __ignore_strtoll_l +#endif +#ifdef L_strtoul_l +#define strtoull_l __ignore_strtoull_l +#endif +#ifdef L_wcstol_l +#define wcstoll_l __ignore_wcstoll_l +#endif +#ifdef L_wcstoul_l +#define wcstoull_l __ignore_wcstoull_l +#endif +#endif +#if defined(ULLONG_MAX) && (ULLONG_MAX == UINTMAX_MAX) +#if defined L_labs || defined L_llabs +#define imaxabs __ignore_imaxabs +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* TODO: clean up the following... */ + +#if WCHAR_MAX > 0xffffUL +#define UTF_8_MAX_LEN 6 +#else +#define UTF_8_MAX_LEN 3 +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + +#define ENCODING ((__UCLIBC_CURLOCALE_DATA).encoding) +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#ifdef L_mblen +/* emit only once */ +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif +#endif + +#else /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_mblen +/* emit only once */ +#warning devel checks +#endif +#endif +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#error __CTYPE_HAS_8_BIT_LOCALES is defined! +#endif +#ifdef __CTYPE_HAS_UTF_8_LOCALES +#error __CTYPE_HAS_UTF_8_LOCALES is defined! +#endif +#endif + +#endif /* __UCLIBC_HAS_LOCALE__ */ + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_XLOCALE__ + +extern unsigned long +_stdlib_strto_l_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_strto_ll_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern unsigned long +_stdlib_wcsto_l_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_wcsto_ll_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + + +extern unsigned long +_stdlib_strto_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_strto_ll(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern unsigned long +_stdlib_wcsto_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_wcsto_ll(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +/**********************************************************************/ +#ifdef L_atof + +libc_hidden_proto(strtod) + +double atof(const char *nptr) +{ + return strtod(nptr, (char **) NULL); +} + +#endif +/**********************************************************************/ +#ifdef L_abs + +#if INT_MAX < LONG_MAX + +int abs(int j) +{ + return (j >= 0) ? j : -j; +} + +#endif /* INT_MAX < LONG_MAX */ + +#endif +/**********************************************************************/ +#ifdef L_labs + +long int labs(long int j) +{ + return (j >= 0) ? j : -j; +} + +#if UINT_MAX == ULONG_MAX +#undef abs +extern __typeof(labs) abs; +strong_alias(labs,abs) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#undef llabs +extern __typeof(labs) llabs; +strong_alias(labs,llabs) +#endif + +#if ULONG_MAX == UINTMAX_MAX +#undef imaxabs +extern __typeof(labs) imaxabs; +strong_alias(labs,imaxabs) +#endif + +#endif +/**********************************************************************/ +#ifdef L_llabs + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +long long int llabs(long long int j) +{ + return (j >= 0) ? j : -j; +} + +#if (ULLONG_MAX == UINTMAX_MAX) +#undef imaxabs +extern __typeof(llabs) imaxabs; +strong_alias(llabs,imaxabs) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#ifdef L_atoi + +#if INT_MAX < LONG_MAX + +libc_hidden_proto(strtol) + +libc_hidden_proto(atoi) +int atoi(const char *nptr) +{ + return (int) strtol(nptr, (char **) NULL, 10); +} +libc_hidden_def(atoi) + +#endif /* INT_MAX < LONG_MAX */ + +#endif +/**********************************************************************/ +#ifdef L_atol + +libc_hidden_proto(strtol) + +libc_hidden_proto(atol) +long atol(const char *nptr) +{ + return strtol(nptr, (char **) NULL, 10); +} +libc_hidden_def(atol) + +#if UINT_MAX == ULONG_MAX +#undef atoi +extern __typeof(atol) atoi; +libc_hidden_proto(atoi) +strong_alias(atol,atoi) +libc_hidden_def(atoi) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#undef atoll +extern __typeof(atol) atoll; +strong_alias(atol,atoll) +#endif + +#endif +/**********************************************************************/ +#ifdef L_atoll + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(strtoll) + +long long atoll(const char *nptr) +{ + return strtoll(nptr, (char **) NULL, 10); +} + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_strtol) || defined(L_strtol_l) + +libc_hidden_proto(__XL_NPP(strtol)) +long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr, + int base __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtol)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtol_l) +strong_alias(strtol,strtoimax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_strtol_l +#undef strtoll_l +#else +#undef strtoll +#endif +extern __typeof(__XL_NPP(strtol)) __XL_NPP(strtoll); +libc_hidden_proto(__XL_NPP(strtoll)) +strong_alias(__XL_NPP(strtol),__XL_NPP(strtoll)) +libc_hidden_def(__XL_NPP(strtoll)) +#endif + +#endif +/**********************************************************************/ +#if defined(L_strtoll) || defined(L_strtoll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(strtoll)) +long long __XL_NPP(strtoll)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoll)) + +#if !defined(L_strtoll_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(strtoll,strtoimax) +#endif +strong_alias(strtoll,strtoq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_strtoul) || defined(L_strtoul_l) + +libc_hidden_proto(__XL_NPP(strtoul)) +unsigned long __XL_NPP(strtoul)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoul)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtoul_l) +strong_alias(strtoul,strtoumax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_strtoul_l +#undef strtoull_l +#else +#undef strtoull +#endif +extern __typeof(__XL_NPP(strtoul)) __XL_NPP(strtoull); +libc_hidden_proto(__XL_NPP(strtoull)) +strong_alias(__XL_NPP(strtoul),__XL_NPP(strtoull)) +libc_hidden_def(__XL_NPP(strtoull)) +#endif + + +#endif +/**********************************************************************/ +#if defined(L_strtoull) || defined(L_strtoull_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(strtoull)) +unsigned long long __XL_NPP(strtoull)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoull)) + +#if !defined(L_strtoull_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(strtoull,strtoumax) +#endif +strong_alias(strtoull,strtouq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +/* Support routines follow */ +/**********************************************************************/ +/* Set if we want errno set appropriately. */ +/* NOTE: Implies _STRTO_ENDPTR below */ +#define _STRTO_ERRNO 1 + +/* Set if we want support for the endptr arg. */ +/* Implied by _STRTO_ERRNO. */ +#define _STRTO_ENDPTR 1 + +#if _STRTO_ERRNO +#undef _STRTO_ENDPTR +#define _STRTO_ENDPTR 1 +#define SET_ERRNO(X) __set_errno(X) +#else +#define SET_ERRNO(X) ((void)(X)) /* keep side effects */ +#endif + +/**********************************************************************/ +#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) +#ifndef L__stdlib_strto_l +#define L__stdlib_strto_l +#endif +#endif + +#if defined(L__stdlib_strto_l) || defined(L__stdlib_strto_l_l) + +#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) + +#define _stdlib_strto_l _stdlib_wcsto_l +#define _stdlib_strto_l_l _stdlib_wcsto_l_l +#define Wchar wchar_t +#define Wuchar __uwchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +libc_hidden_proto(iswspace_l) +#else +#define ISSPACE(C) iswspace((C)) +libc_hidden_proto(iswspace) +#endif + +#else /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */ + +#define Wchar char +#define Wuchar unsigned char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +libc_hidden_proto(isspace_l) +#else +#define ISSPACE(C) isspace((C)) +libc_hidden_proto(isspace) +#endif + +#endif /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag) +{ + return _stdlib_strto_l_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE); +} + + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* This is the main work fuction which handles both strtol (sflag = 1) and + * strtoul (sflag = 0). */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag __LOCALE_PARAM) +{ + unsigned long number, cutoff; +#if _STRTO_ENDPTR + const Wchar *fail_char; +#define SET_FAIL(X) fail_char = (X) +#else +#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */ +#endif + unsigned char negative, digit, cutoff_digit; + + assert(((unsigned int)sflag) <= 1); + + SET_FAIL(str); + + while (ISSPACE(*str)) { /* Skip leading whitespace. */ + ++str; + } + + /* Handle optional sign. */ + negative = 0; + switch (*str) { + case '-': negative = 1; /* Fall through to increment str. */ + case '+': ++str; + } + + if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */ + base += 10; /* Default is 10 (26). */ + if (*str == '0') { + SET_FAIL(++str); + base -= 2; /* Now base is 8 or 16 (24). */ + if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */ + ++str; + base += base; /* Base is 16 (16 or 48). */ + } + } + + if (base > 16) { /* Adjust in case base wasn't dynamic. */ + base = 16; + } + } + + number = 0; + + if (((unsigned)(base - 2)) < 35) { /* Legal base. */ + cutoff_digit = ULONG_MAX % base; + cutoff = ULONG_MAX / base; + do { + digit = ((Wuchar)(*str - '0') <= 9) + ? /* 0..9 */ (*str - '0') + : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */ + ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10)) + : /* else */ 40 /* bad value */); + + if (digit >= base) { + break; + } + + SET_FAIL(++str); + + if ((number > cutoff) + || ((number == cutoff) && (digit > cutoff_digit))) { + number = ULONG_MAX; + negative &= sflag; + SET_ERRNO(ERANGE); + } else { + number = number * base + digit; + } + } while (1); + } + +#if _STRTO_ENDPTR + if (endptr) { + *endptr = (Wchar *) fail_char; + } +#endif + + { + unsigned long tmp = (negative + ? ((unsigned long)(-(1+LONG_MIN)))+1 + : LONG_MAX); + if (sflag && (number > tmp)) { + number = tmp; + SET_ERRNO(ERANGE); + } + } + + return negative ? (unsigned long)(-((long)number)) : number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + + +#endif +/**********************************************************************/ +#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) +#ifndef L__stdlib_strto_ll +#define L__stdlib_strto_ll +#endif +#endif + +#if defined(L__stdlib_strto_ll) || defined(L__stdlib_strto_ll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) +#define _stdlib_strto_ll _stdlib_wcsto_ll +#define _stdlib_strto_ll_l _stdlib_wcsto_ll_l +#define Wchar wchar_t +#define Wuchar __uwchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +libc_hidden_proto(iswspace_l) +#else +#define ISSPACE(C) iswspace((C)) +libc_hidden_proto(iswspace) +#endif + +#else /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */ + +#define Wchar char +#define Wuchar unsigned char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +libc_hidden_proto(isspace_l) +#else +#define ISSPACE(C) isspace((C)) +libc_hidden_proto(isspace) +#endif + +#endif /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +unsigned long long attribute_hidden _stdlib_strto_ll(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag) +{ + return _stdlib_strto_ll_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE); +} + + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#if !defined __UCLIBC_HAS_XLOCALE__ && defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif +/* This is the main work fuction which handles both strtoll (sflag = 1) and + * strtoull (sflag = 0). */ + +unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag __LOCALE_PARAM) +{ + unsigned long long number; +#if _STRTO_ENDPTR + const Wchar *fail_char; +#define SET_FAIL(X) fail_char = (X) +#else +#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */ +#endif + unsigned int n1; + unsigned char negative, digit; + + assert(((unsigned int)sflag) <= 1); + + SET_FAIL(str); + + while (ISSPACE(*str)) { /* Skip leading whitespace. */ + ++str; + } + + /* Handle optional sign. */ + negative = 0; + switch (*str) { + case '-': negative = 1; /* Fall through to increment str. */ + case '+': ++str; + } + + if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */ + base += 10; /* Default is 10 (26). */ + if (*str == '0') { + SET_FAIL(++str); + base -= 2; /* Now base is 8 or 16 (24). */ + if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */ + ++str; + base += base; /* Base is 16 (16 or 48). */ + } + } + + if (base > 16) { /* Adjust in case base wasn't dynamic. */ + base = 16; + } + } + + number = 0; + + if (((unsigned)(base - 2)) < 35) { /* Legal base. */ + do { + digit = ((Wuchar)(*str - '0') <= 9) + ? /* 0..9 */ (*str - '0') + : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */ + ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10)) + : /* else */ 40 /* bad value */); + + if (digit >= base) { + break; + } + + SET_FAIL(++str); + +#if 1 + /* Optional, but speeds things up in the usual case. */ + if (number <= (ULLONG_MAX >> 6)) { + number = number * base + digit; + } else +#endif + { + n1 = ((unsigned char) number) * base + digit; + number = (number >> CHAR_BIT) * base; + + if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) { + number = (number << CHAR_BIT) + n1; + } else { /* Overflow. */ + number = ULLONG_MAX; + negative &= sflag; + SET_ERRNO(ERANGE); + } + } + + } while (1); + } + +#if _STRTO_ENDPTR + if (endptr) { + *endptr = (Wchar *) fail_char; + } +#endif + + { + unsigned long long tmp = ((negative) + ? ((unsigned long long)(-(1+LLONG_MIN)))+1 + : LLONG_MAX); + if (sflag && (number > tmp)) { + number = tmp; + SET_ERRNO(ERANGE); + } + } + + return negative ? (unsigned long long)(-((long long)number)) : number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +/* Made _Exit() an alias for _exit(), as per C99. */ +/* #ifdef L__Exit */ +/* libc_hidden_proto(_exit) */ +/* void _Exit(int status) */ +/* { */ +/* _exit(status); */ +/* } */ + +/* #endif */ +/**********************************************************************/ +#ifdef L_bsearch + +void *bsearch(const void *key, const void *base, size_t /* nmemb */ high, + size_t size, int (*compar)(const void *, const void *)) +{ + register char *p; + size_t low; + size_t mid; + int r; + + if (size > 0) { /* TODO: change this to an assert?? */ + low = 0; + while (low < high) { + mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */ + p = ((char *)base) + mid * size; /* Could overflow here... */ + r = (*compar)(key, p); /* but that's an application problem! */ + if (r > 0) { + low = mid + 1; + } else if (r < 0) { + high = mid; + } else { + return p; + } + } + } + return NULL; +} + +#endif +/**********************************************************************/ +#ifdef L_qsort + +/* This code is derived from a public domain shell sort routine by + * Ray Gardner and found in Bob Stout's snippets collection. The + * original code is included below in an #if 0/#endif block. + * + * I modified it to avoid the possibility of overflow in the wgap + * calculation, as well as to reduce the generated code size with + * bcc and gcc. */ + +libc_hidden_proto(qsort) +void qsort(void *base, + size_t nel, + size_t width, + int (*comp)(const void *, const void *)) +{ + size_t wgap, i, j, k; + char tmp; + + if ((nel > 1) && (width > 0)) { + assert(nel <= ((size_t)(-1)) / width); /* check for overflow */ + wgap = 0; + do { + wgap = 3 * wgap + 1; + } while (wgap < (nel-1)/3); + /* From the above, we know that either wgap == 1 < nel or */ + /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */ + wgap *= width; /* So this can not overflow if wnel doesn't. */ + nel *= width; /* Convert nel to 'wnel' */ + do { + i = wgap; + do { + j = i; + do { + register char *a; + register char *b; + + j -= wgap; + a = j + ((char *)base); + b = a + wgap; + if ((*comp)(a, b) <= 0) { + break; + } + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--k); + } while (j >= wgap); + i += width; + } while (i < nel); + wgap = (wgap - width)/3; + } while (wgap); + } +} +libc_hidden_def(qsort) + +/* ---------- original snippets version below ---------- */ + +#if 0 +/* +** ssort() -- Fast, small, qsort()-compatible Shell sort +** +** by Ray Gardner, public domain 5/90 +*/ + +#include + +void ssort(void *base, + size_t nel, + size_t width, + int (*comp)(const void *, const void *)) +{ + size_t wnel, gap, wgap, i, j, k; + char *a, *b, tmp; + + wnel = width * nel; + for (gap = 0; ++gap < nel;) + gap *= 3; + while ((gap /= 3) != 0) { + wgap = width * gap; + for (i = wgap; i < wnel; i += width) { + for (j = i - wgap; ;j -= wgap) { + a = j + (char *)base; + b = a + wgap; + if ((*comp)(a, b) <= 0) + break; + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--k); + if (j < wgap) + break; + } + } + } +} +#endif + +#endif +/**********************************************************************/ +#ifdef L__stdlib_mb_cur_max + +libc_hidden_proto(_stdlib_mb_cur_max) +size_t _stdlib_mb_cur_max(void) +{ +#ifdef __CTYPE_HAS_UTF_8_LOCALES + return __UCLIBC_CURLOCALE_DATA.mb_cur_max; +#else +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#ifdef __UCLIBC_MJN3_ONLY__ +#warning need to change this when/if transliteration is implemented +#endif +#endif + return 1; +#endif +} +libc_hidden_def(_stdlib_mb_cur_max) + +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ +/* + * The following function return 1 if the encoding is stateful, 0 if stateless. + * To note, until now all the supported encoding are stateless. + */ + +static __always_inline int is_stateful(unsigned char encoding) +{ + switch (encoding) + { + case __ctype_encoding_7_bit: + case __ctype_encoding_utf8: + case __ctype_encoding_8_bit: + return 0; + default: + assert(0); + return -1; + } +} +#else +#define is_stateful(encoding) 0 +#endif + +/**********************************************************************/ +#ifdef L_mblen + +libc_hidden_proto(mbrlen) + +int mblen(register const char *s, size_t n) +{ + static mbstate_t state; + size_t r; + + if (!s) { + state.__mask = 0; + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See mblen() documentation. + */ + return is_stateful(ENCODING); + } + + if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + + if ((r = mbrlen(s, n, &state)) == (size_t) -2) { + /* TODO: Should we set an error state? */ + state.__wc = 0xffffU; /* Make sure we're in an error state. */ + return -1; /* TODO: Change error code above? */ + } + return r; +} + +#endif +/**********************************************************************/ +#ifdef L_mbtowc + +libc_hidden_proto(mbrtowc) + +int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n) +{ + static mbstate_t state; + size_t r; + + if (!s) { + state.__mask = 0; + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See mbtowc() documentation. + */ + + return is_stateful(ENCODING); + } + + if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + + if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) { + /* TODO: Should we set an error state? */ + state.__wc = 0xffffU; /* Make sure we're in an error state. */ + return -1; /* TODO: Change error code above? */ + } + return r; +} + +#endif +/**********************************************************************/ +#ifdef L_wctomb + +/* Note: We completely ignore state in all currently supported conversions. */ + +libc_hidden_proto(wcrtomb) + +int wctomb(register char *__restrict s, wchar_t swc) +{ + return (!s) + ? + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See wctomb() documentation. + */ + + is_stateful(ENCODING) + : ((ssize_t) wcrtomb(s, swc, NULL)); +} + +#endif +/**********************************************************************/ +#ifdef L_mbstowcs + +libc_hidden_proto(mbsrtowcs) + +size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + mbstate_t state; + const char *e = s; /* Needed because of restrict. */ + + state.__mask = 0; /* Always start in initial shift state. */ + return mbsrtowcs(pwcs, &e, n, &state); +} + +#endif +/**********************************************************************/ +#ifdef L_wcstombs + +/* Note: We completely ignore state in all currently supported conversions. */ + +libc_hidden_proto(wcsrtombs) + +size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + const wchar_t *e = pwcs; /* Needed because of restrict. */ + + return wcsrtombs(s, &e, n, NULL); +} + +#endif +/**********************************************************************/ +#if defined(L_wcstol) || defined(L_wcstol_l) + +libc_hidden_proto(__XL_NPP(wcstol)) +long __XL_NPP(wcstol)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstol)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstol_l) +strong_alias(wcstol,wcstoimax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_wcstol_l +#undef wcstoll_l +#else +#undef wcstoll +#endif +extern __typeof(__XL_NPP(wcstol)) __XL_NPP(wcstoll); +libc_hidden_proto(__XL_NPP(wcstoll)) +strong_alias(__XL_NPP(wcstol),__XL_NPP(wcstoll)) +libc_hidden_def(__XL_NPP(wcstoll)) +#endif + +#endif +/**********************************************************************/ +#if defined(L_wcstoll) || defined(L_wcstoll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(wcstoll)) +long long __XL_NPP(wcstoll)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoll)) + +#if !defined(L_wcstoll_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(wcstoll,wcstoimax) +#endif +strong_alias(wcstoll,wcstoq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_wcstoul) || defined(L_wcstoul_l) + +libc_hidden_proto(__XL_NPP(wcstoul)) +unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoul)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstoul_l) +strong_alias(wcstoul,wcstoumax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_wcstoul_l +#undef wcstoull_l +#else +#undef wcstoull +#endif +extern __typeof(__XL_NPP(wcstoul)) __XL_NPP(wcstoull); +libc_hidden_proto(__XL_NPP(wcstoull)) +strong_alias(__XL_NPP(wcstoul),__XL_NPP(wcstoull)) +libc_hidden_def(__XL_NPP(wcstoull)) +#endif + +#endif +/**********************************************************************/ +#if defined(L_wcstoull) || defined(L_wcstoull_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(wcstoull)) +unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoull)) + +#if !defined(L_wcstoull_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(wcstoull,wcstoumax) +#endif +strong_alias(wcstoull,wcstouq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c new file mode 100644 index 0000000..7f59aef --- /dev/null +++ b/libc/stdlib/strtod.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtod +#include "_strtod.c" diff --git a/libc/stdlib/strtod_l.c b/libc/stdlib/strtod_l.c new file mode 100644 index 0000000..4131242 --- /dev/null +++ b/libc/stdlib/strtod_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtod_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/strtof.c b/libc/stdlib/strtof.c new file mode 100644 index 0000000..35e8977 --- /dev/null +++ b/libc/stdlib/strtof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtof +#include "_strtod.c" diff --git a/libc/stdlib/strtof_l.c b/libc/stdlib/strtof_l.c new file mode 100644 index 0000000..7b44d1b --- /dev/null +++ b/libc/stdlib/strtof_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtof_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/strtol.c b/libc/stdlib/strtol.c new file mode 100644 index 0000000..cee4e13 --- /dev/null +++ b/libc/stdlib/strtol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtol +#include "stdlib.c" diff --git a/libc/stdlib/strtol_l.c b/libc/stdlib/strtol_l.c new file mode 100644 index 0000000..d59c1e5 --- /dev/null +++ b/libc/stdlib/strtol_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtol_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/strtold.c b/libc/stdlib/strtold.c new file mode 100644 index 0000000..91a3ba7 --- /dev/null +++ b/libc/stdlib/strtold.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtold +#include "_strtod.c" diff --git a/libc/stdlib/strtold_l.c b/libc/stdlib/strtold_l.c new file mode 100644 index 0000000..7eccd00 --- /dev/null +++ b/libc/stdlib/strtold_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtold_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/strtoll.c b/libc/stdlib/strtoll.c new file mode 100644 index 0000000..a9c7c83 --- /dev/null +++ b/libc/stdlib/strtoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoll +#include "stdlib.c" diff --git a/libc/stdlib/strtoll_l.c b/libc/stdlib/strtoll_l.c new file mode 100644 index 0000000..9fa46bd --- /dev/null +++ b/libc/stdlib/strtoll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/strtoul.c b/libc/stdlib/strtoul.c new file mode 100644 index 0000000..e92d246 --- /dev/null +++ b/libc/stdlib/strtoul.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoul +#include "stdlib.c" diff --git a/libc/stdlib/strtoul_l.c b/libc/stdlib/strtoul_l.c new file mode 100644 index 0000000..2aef138 --- /dev/null +++ b/libc/stdlib/strtoul_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoul_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/strtoull.c b/libc/stdlib/strtoull.c new file mode 100644 index 0000000..60b626f --- /dev/null +++ b/libc/stdlib/strtoull.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoull +#include "stdlib.c" diff --git a/libc/stdlib/strtoull_l.c b/libc/stdlib/strtoull_l.c new file mode 100644 index 0000000..81e045a --- /dev/null +++ b/libc/stdlib/strtoull_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoull_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/system.c b/libc/stdlib/system.c new file mode 100644 index 0000000..4d75a40 --- /dev/null +++ b/libc/stdlib/system.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(_exit) +libc_hidden_proto(wait4) +libc_hidden_proto(execl) +libc_hidden_proto(signal) +libc_hidden_proto(vfork) + +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#ifndef __NR_vfork +# define vfork fork +libc_hidden_proto(fork) +#endif + +extern __typeof(system) __libc_system; +int __libc_system(const char *command) +{ + int wait_val, pid; + __sighandler_t save_quit, save_int, save_chld; + + if (command == 0) + return 1; + + save_quit = signal(SIGQUIT, SIG_IGN); + save_int = signal(SIGINT, SIG_IGN); + save_chld = signal(SIGCHLD, SIG_DFL); + + if ((pid = vfork()) < 0) { + signal(SIGQUIT, save_quit); + signal(SIGINT, save_int); + signal(SIGCHLD, save_chld); + return -1; + } + if (pid == 0) { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + execl("/bin/sh", "sh", "-c", command, (char *) 0); + _exit(127); + } + /* Signals are not absolutly guarenteed with vfork */ + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + +#if 0 + __printf("Waiting for child %d\n", pid); +#endif + + if (wait4(pid, &wait_val, 0, 0) == -1) + wait_val = -1; + + signal(SIGQUIT, save_quit); + signal(SIGINT, save_int); + signal(SIGCHLD, save_chld); + return wait_val; +} +weak_alias(__libc_system,system) diff --git a/libc/stdlib/unix_grantpt.c b/libc/stdlib/unix_grantpt.c new file mode 100644 index 0000000..d1eef9e --- /dev/null +++ b/libc/stdlib/unix_grantpt.c @@ -0,0 +1,215 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pty-private.h" + +/* Experimentally off - libc_hidden_proto(memchr) */ +libc_hidden_proto(getgid) +libc_hidden_proto(getuid) +libc_hidden_proto(setrlimit) +libc_hidden_proto(waitpid) +libc_hidden_proto(dup2) +libc_hidden_proto(chmod) +libc_hidden_proto(chown) +libc_hidden_proto(vfork) +libc_hidden_proto(fork) +libc_hidden_proto(stat) +libc_hidden_proto(ptsname_r) +libc_hidden_proto(execle) +libc_hidden_proto(_exit) + +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#if ! defined __NR_vfork +#define vfork fork +#endif + +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_r (fd, buf, buf_len); + + if (rv != 0 || memchr (buf, '\0', buf_len)) + /* We either got an error, or we succeeded and the + returned name fit in the buffer. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + errno = ENOMEM; + break; + } + buf = new_buf; + } + + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} + +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ +int +grantpt (int fd) +{ + int retval = -1; +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; + struct stat st; + uid_t uid; + gid_t gid; + pid_t pid; + + if (pts_name (fd, &buf, sizeof (_buf))) + return -1; + + if (stat(buf, &st) < 0) + goto cleanup; + + /* Make sure that we own the device. */ + uid = getuid (); + if (st.st_uid != uid) + { + if (chown (buf, uid, st.st_gid) < 0) + goto helper; + } + + gid = getgid (); + + /* Make sure the group of the device is that special group. */ + if (st.st_gid != gid) + { + if (chown (buf, uid, gid) < 0) + goto helper; + } + + /* Make sure the permission mode is set to readable and writable by + the owner, and writable by the group. */ + if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) + { + if (chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) + goto helper; + } + + retval = 0; + goto cleanup; + + /* We have to use the helper program. */ + helper: + + pid = vfork (); + if (pid == -1) + goto cleanup; + else if (pid == 0) + { + /* Disable core dumps. */ + struct rlimit rl = { 0, 0 }; + setrlimit (RLIMIT_CORE, &rl); + + /* We pase the master pseudo terminal as file descriptor PTY_FILENO. */ + if (fd != PTY_FILENO) + if (dup2 (fd, PTY_FILENO) < 0) + _exit (FAIL_EBADF); + + execle (_PATH_PT_CHOWN, _PATH_PT_CHOWN, NULL, NULL); + _exit (FAIL_EXEC); + } + else + { + int w; + + if (waitpid (pid, &w, 0) == -1) + goto cleanup; + if (!WIFEXITED (w)) + errno = ENOEXEC; + else + switch (WEXITSTATUS(w)) + { + case 0: + retval = 0; + break; + case FAIL_EBADF: + errno = EBADF; + break; + case FAIL_EINVAL: + errno = EINVAL; + break; + case FAIL_EACCES: + errno = EACCES; + break; + case FAIL_EXEC: + errno = ENOEXEC; + break; + + default: + assert(! "getpt: internal error: invalid exit code from pt_chown"); + } + } + + cleanup: + if (buf != _buf) + free (buf); + + return retval; +} diff --git a/libc/stdlib/unlockpt.c b/libc/stdlib/unlockpt.c new file mode 100644 index 0000000..8c42655 --- /dev/null +++ b/libc/stdlib/unlockpt.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(ioctl) + +/* Unlock the slave pseudo terminal associated with the master pseudo + terminal specified by FD. */ +int +unlockpt (int fd) +{ +#ifdef TIOCSPTLCK + int save_errno = errno; + int unlock = 0; + + if (ioctl (fd, TIOCSPTLCK, &unlock)) + { + if (errno == EINVAL) + { + errno = save_errno; + return 0; + } + else + return -1; + } +#endif + /* If we have no TIOCSPTLCK ioctl, all slave pseudo terminals are + unlocked by default. */ + return 0; +} diff --git a/libc/stdlib/valloc.c b/libc/stdlib/valloc.c new file mode 100644 index 0000000..13dbe0f --- /dev/null +++ b/libc/stdlib/valloc.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* Allocate memory on a page boundary. + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include +#include +#include + +libc_hidden_proto(getpagesize) + +static size_t pagesize; + +__ptr_t valloc (size_t size) +{ + if (pagesize == 0) + pagesize = getpagesize (); + + return memalign(pagesize, size); +} diff --git a/libc/stdlib/wcstod.c b/libc/stdlib/wcstod.c new file mode 100644 index 0000000..08f8021 --- /dev/null +++ b/libc/stdlib/wcstod.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstod +#include "_strtod.c" diff --git a/libc/stdlib/wcstod_l.c b/libc/stdlib/wcstod_l.c new file mode 100644 index 0000000..be0e58e --- /dev/null +++ b/libc/stdlib/wcstod_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstod_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/wcstof.c b/libc/stdlib/wcstof.c new file mode 100644 index 0000000..27ad22f --- /dev/null +++ b/libc/stdlib/wcstof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstof +#include "_strtod.c" diff --git a/libc/stdlib/wcstof_l.c b/libc/stdlib/wcstof_l.c new file mode 100644 index 0000000..953ebe0 --- /dev/null +++ b/libc/stdlib/wcstof_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstof_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/wcstol.c b/libc/stdlib/wcstol.c new file mode 100644 index 0000000..74462e1 --- /dev/null +++ b/libc/stdlib/wcstol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstol +#include "stdlib.c" diff --git a/libc/stdlib/wcstol_l.c b/libc/stdlib/wcstol_l.c new file mode 100644 index 0000000..4282987 --- /dev/null +++ b/libc/stdlib/wcstol_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstol_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/wcstold.c b/libc/stdlib/wcstold.c new file mode 100644 index 0000000..cd879c1 --- /dev/null +++ b/libc/stdlib/wcstold.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstold +#include "_strtod.c" diff --git a/libc/stdlib/wcstold_l.c b/libc/stdlib/wcstold_l.c new file mode 100644 index 0000000..2ea23b0 --- /dev/null +++ b/libc/stdlib/wcstold_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstold_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/libc/stdlib/wcstoll.c b/libc/stdlib/wcstoll.c new file mode 100644 index 0000000..4cc9b05 --- /dev/null +++ b/libc/stdlib/wcstoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoll +#include "stdlib.c" diff --git a/libc/stdlib/wcstoll_l.c b/libc/stdlib/wcstoll_l.c new file mode 100644 index 0000000..66c23c2 --- /dev/null +++ b/libc/stdlib/wcstoll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/wcstombs.c b/libc/stdlib/wcstombs.c new file mode 100644 index 0000000..c3d08d8 --- /dev/null +++ b/libc/stdlib/wcstombs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstombs +#include "stdlib.c" diff --git a/libc/stdlib/wcstoul.c b/libc/stdlib/wcstoul.c new file mode 100644 index 0000000..5542744 --- /dev/null +++ b/libc/stdlib/wcstoul.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoul +#include "stdlib.c" diff --git a/libc/stdlib/wcstoul_l.c b/libc/stdlib/wcstoul_l.c new file mode 100644 index 0000000..529e8e4 --- /dev/null +++ b/libc/stdlib/wcstoul_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoul_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/wcstoull.c b/libc/stdlib/wcstoull.c new file mode 100644 index 0000000..ea884ef --- /dev/null +++ b/libc/stdlib/wcstoull.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoull +#include "stdlib.c" diff --git a/libc/stdlib/wcstoull_l.c b/libc/stdlib/wcstoull_l.c new file mode 100644 index 0000000..976d103 --- /dev/null +++ b/libc/stdlib/wcstoull_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoull_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/libc/stdlib/wctomb.c b/libc/stdlib/wctomb.c new file mode 100644 index 0000000..3f612be --- /dev/null +++ b/libc/stdlib/wctomb.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctomb +#include "stdlib.c" diff --git a/libc/string/.indent.pro b/libc/string/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/string/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/string/Makefile b/libc/string/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/string/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/Makefile.in b/libc/string/Makefile.in new file mode 100644 index 0000000..5ea86f0 --- /dev/null +++ b/libc/string/Makefile.in @@ -0,0 +1,139 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# +# Arch specific fun +# +# Collect the subarch specific implementation (asm files) +ifneq ($(strip $(TARGET_SUBARCH)),) +STRING_SUBARCH_DIR := $(top_srcdir)libc/string/$(TARGET_ARCH)/$(TARGET_SUBARCH) +STRING_SUBARCH_OUT := $(top_builddir)libc/string/$(TARGET_ARCH)/$(TARGET_SUBARCH) + +STRING_SUBARCH_SSRC := $(wildcard $(STRING_SUBARCH_OUT)/*.S) +STRING_SUBARCH_SOBJ := $(patsubst $(STRING_SUBARCH_DIR)/%.S,$(STRING_SUBARCH_OUT)/%.o,$(STRING_SUBARCH_SSRC)) + +STRING_SUBARCH_OBJS := $(STRING_SUBARCH_SOBJ) +endif + +# Collect the arch specific implementation (asm, c files) +STRING_ARCH_DIR := $(top_srcdir)libc/string/$(TARGET_ARCH) +STRING_ARCH_OUT := $(top_builddir)libc/string/$(TARGET_ARCH) + +STRING_ARCH_SRC := $(wildcard $(STRING_ARCH_DIR)/*.c) +STRING_ARCH_OBJ := $(patsubst $(STRING_ARCH_DIR)/%.c,$(STRING_ARCH_OUT)/%.o,$(STRING_ARCH_SRC)) + +STRING_ARCH_SSRC := $(wildcard $(STRING_ARCH_DIR)/*.S) + +# Exclude the subarch implementation from the arch ones +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_ARCH_SSRC := $(filter-out $(patsubst %.o,$(STRING_ARCH_DIR)/%.S,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_ARCH_SSRC)) +endif + +STRING_ARCH_SOBJ := $(patsubst $(STRING_ARCH_DIR)/%.S,$(STRING_ARCH_OUT)/%.o,$(STRING_ARCH_SSRC)) + +STRING_ARCH_OBJS := $(STRING_ARCH_OBJ) $(STRING_ARCH_SOBJ) + +libc-$(UCLIBC_HAS_STRING_ARCH_OPT) += $(STRING_ARCH_OBJS) $(STRING_SUBARCH_OBJS) + +libc-nomulti-$(UCLIBC_HAS_STRING_ARCH_OPT) += $(STRING_ARCH_SOBJ) $(STRING_SUBARCH_OBJS) + +# +# Generic stuff +# +STRING_GENERIC_DIR := $(top_srcdir)libc/string/generic +STRING_GENERIC_OUT := $(top_builddir)libc/string/generic + +STRING_GENERIC_SRC := $(wildcard $(STRING_GENERIC_DIR)/*.c) +STRING_GENERIC_SRC := $(filter-out $(STRING_GENERIC_DIR)/_memcpy_fwd.c, $(STRING_GENERIC_SRC)) + +ifeq ($(UCLIBC_HAS_STRING_ARCH_OPT),y) +ifneq ($(strip $(STRING_ARCH_OBJS)),) +STRING_GENERIC_SRC := $(filter-out $(patsubst %.o,$(STRING_GENERIC_DIR)/%.c,$(notdir $(STRING_ARCH_OBJS))),$(STRING_GENERIC_SRC)) +endif +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_GENERIC_SRC := $(filter-out $(patsubst %.o,$(STRING_GENERIC_DIR)/%.c,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_GENERIC_SRC)) +endif +endif + +STRING_GENERIC_OBJS := $(patsubst $(STRING_GENERIC_DIR)/%.c,$(STRING_GENERIC_OUT)/%.o,$(STRING_GENERIC_SRC)) + +libc-$(UCLIBC_HAS_STRING_GENERIC_OPT) += $(STRING_GENERIC_OBJS) + +# +# Top level string +# +STRING_DIR := $(top_srcdir)libc/string +STRING_OUT := $(top_builddir)libc/string + +STRING_ALL_WXSRC := $(wildcard $(STRING_DIR)/w*_l.c) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_WXSRC := $(STRING_ALL_WXSRC) +else +# wcscoll_l +STRING_WXSRC := $(filter-out $(STRING_DIR)/wcsxfrm_l.c,$(STRING_ALL_WXSRC)) +endif + +STRING_ALL_XLSRC := $(filter-out $(STRING_ALL_WXSRC),$(wildcard $(STRING_DIR)/*_l.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_XLSRC := $(STRING_ALL_XLSRC) +else +# strcoll_l +STRING_XLSRC := $(filter-out $(STRING_DIR)/strxfrm_l.c,$(STRING_ALL_XLSRC)) +endif + +STRING_ALL_WSRC := $(filter-out $(STRING_ALL_WXSRC),$(wildcard $(STRING_DIR)/w*.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_WSRC := $(STRING_ALL_WSRC) +else +# wcscoll +STRING_WSRC := $(filter-out $(STRING_DIR)/wcsxfrm.c,$(STRING_ALL_WSRC)) +endif + +STRING_ALL_CSRC := $(filter-out $(STRING_ALL_WXSRC) $(STRING_ALL_XLSRC) $(STRING_ALL_WSRC) $(STRING_DIR)/_collate.c,$(wildcard $(STRING_DIR)/*.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_CSRC := $(STRING_ALL_CSRC) +else +# strcoll +STRING_CSRC := $(filter-out $(STRING_DIR)/strxfrm.c,$(STRING_ALL_CSRC)) +endif + +ifeq ($(UCLIBC_HAS_WCHAR),y) +STRING_CSRC += $(STRING_WSRC) +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +STRING_CSRC += $(STRING_XLSRC) +ifeq ($(UCLIBC_HAS_WCHAR),y) +STRING_CSRC += $(STRING_WXSRC) +endif +endif + +ifeq ($(UCLIBC_HAS_STRING_ARCH_OPT),y) +ifneq ($(strip $(STRING_ARCH_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_ARCH_OBJS))),$(STRING_CSRC)) +endif +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_CSRC)) +endif +endif + +ifeq ($(UCLIBC_HAS_STRING_GENERIC_OPT),y) +ifneq ($(strip $(STRING_GENERIC_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_GENERIC_OBJS))),$(STRING_CSRC)) +endif +endif + +STRING_COBJ := $(patsubst $(STRING_DIR)/%.c,$(STRING_OUT)/%.o,$(STRING_CSRC)) + +libc-y += $(STRING_COBJ) + +libc-nomulti-$(UCLIBC_HAS_XLOCALE) += $(STRING_OUT)/wcsxfrm_l.o +libc-nomulti-y += $(STRING_OUT)/__xpg_strerror_r.o + +objclean-y += string_clean + +string_clean: + $(do_rm) $(addprefix $(STRING_OUT)/,$(addprefix *., o os oS) $(addprefix */*., o os oS)) diff --git a/libc/string/__glibc_strerror_r.c b/libc/string/__glibc_strerror_r.c new file mode 100644 index 0000000..0f9cd16 --- /dev/null +++ b/libc/string/__glibc_strerror_r.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(__glibc_strerror_r) +libc_hidden_proto(__xpg_strerror_r) + +char *__glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + __xpg_strerror_r(errnum, strerrbuf, buflen); + + return strerrbuf; +} +libc_hidden_def(__glibc_strerror_r) diff --git a/libc/string/__xpg_basename.c b/libc/string/__xpg_basename.c new file mode 100644 index 0000000..2449d1d --- /dev/null +++ b/libc/string/__xpg_basename.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +char *__xpg_basename(register char *path) +{ + static const char null_or_empty[] = "."; + char *first; + register char *last; + + first = (char *) null_or_empty; + + if (path && *path) { + first = path; + last = path - 1; + + do { + if ((*path != '/') && (path > ++last)) { + last = first = path; + } + } while (*++path); + + if (*first == '/') { + last = first; + } + last[1] = 0; + } + + return first; +} diff --git a/libc/string/__xpg_strerror_r.c b/libc/string/__xpg_strerror_r.c new file mode 100644 index 0000000..ff41192 --- /dev/null +++ b/libc/string/__xpg_strerror_r.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Make sure we get proper strerror_r() prototype */ +#define strerror_r _hidestrerror_r + +#include +#include +#include +#include "_syserrmsg.h" + +#undef strerror_r + +libc_hidden_proto(__xpg_strerror_r) +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +extern const char _string_syserrmsgs[] attribute_hidden; + +#if defined(__alpha__) || defined(__mips__) || defined(__sparc__) + +static const unsigned char estridx[] = { + 0, /* success is always 0 */ + EPERM, + ENOENT, + ESRCH, + EINTR, + EIO, + ENXIO, + E2BIG, + ENOEXEC, + EBADF, + ECHILD, + EAGAIN, + ENOMEM, + EACCES, + EFAULT, + ENOTBLK, + EBUSY, + EEXIST, + EXDEV, + ENODEV, + ENOTDIR, + EISDIR, + EINVAL, + ENFILE, + EMFILE, + ENOTTY, + ETXTBSY, + EFBIG, + ENOSPC, + ESPIPE, + EROFS, + EMLINK, + EPIPE, + EDOM, + ERANGE, + EDEADLK, + ENAMETOOLONG, + ENOLCK, + ENOSYS, + ENOTEMPTY, + ELOOP, + 0, + ENOMSG, + EIDRM, + ECHRNG, + EL2NSYNC, + EL3HLT, + EL3RST, + ELNRNG, + EUNATCH, + ENOCSI, + EL2HLT, + EBADE, + EBADR, + EXFULL, + ENOANO, + EBADRQC, + EBADSLT, + 0, + EBFONT, + ENOSTR, + ENODATA, + ETIME, + ENOSR, + ENONET, + ENOPKG, + EREMOTE, + ENOLINK, + EADV, + ESRMNT, + ECOMM, + EPROTO, + EMULTIHOP, + EDOTDOT, + EBADMSG, + EOVERFLOW, + ENOTUNIQ, + EBADFD, + EREMCHG, + ELIBACC, + ELIBBAD, + ELIBSCN, + ELIBMAX, + ELIBEXEC, + EILSEQ, + ERESTART, + ESTRPIPE, + EUSERS, + ENOTSOCK, + EDESTADDRREQ, + EMSGSIZE, + EPROTOTYPE, + ENOPROTOOPT, + EPROTONOSUPPORT, + ESOCKTNOSUPPORT, + EOPNOTSUPP, + EPFNOSUPPORT, + EAFNOSUPPORT, + EADDRINUSE, + EADDRNOTAVAIL, + ENETDOWN, + ENETUNREACH, + ENETRESET, + ECONNABORTED, + ECONNRESET, + ENOBUFS, + EISCONN, + ENOTCONN, + ESHUTDOWN, + ETOOMANYREFS, + ETIMEDOUT, + ECONNREFUSED, + EHOSTDOWN, + EHOSTUNREACH, + EALREADY, + EINPROGRESS, + ESTALE, + EUCLEAN, + ENOTNAM, + ENAVAIL, + EISNAM, + EREMOTEIO, +#if EDQUOT > 200 /* mips has an outrageous value for this... */ + 0, +#else + EDQUOT, +#endif + ENOMEDIUM, + EMEDIUMTYPE, +#if EDEADLOCK != EDEADLK + EDEADLOCK, +#endif +}; + +#endif + +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + register char *s; + int i, retval; + char buf[_STRERROR_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' ' + }; + + retval = EINVAL; + + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +#if defined(__alpha__) || defined(__mips__) || defined(__sparc__) + /* Need to translate errno to string index. */ + for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) { + if (estridx[i] == errnum) { + goto GOT_ESTRIDX; + } + } + i = INT_MAX; /* Failed, but may need to check mips special case. */ +#if EDQUOT > 200 /* Deal with large EDQUOT value on mips */ + if (errnum == EDQUOT) + i = 122; +#endif + GOT_ESTRIDX: +#else + /* No errno to string index translation needed. */ + i = errnum; +#endif + + if (((unsigned int) i) < _SYS_NERR) { + /* Trade time for space. This function should rarely be called + * so rather than keeping an array of pointers for the different + * messages, just run through the buffer until we find the + * correct string. */ + for (s = (char *) _string_syserrmsgs ; i ; ++s) { + if (!*s) { + --i; + } + } + if (*s) { /* Make sure we have an actual message. */ + retval = 0; + goto GOT_MESG; + } + } + +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + + s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + GOT_MESG: + if (!strerrbuf) { /* SUSv3 */ + buflen = 0; + } + i = strlen(s) + 1; + if (i > buflen) { + i = buflen; + retval = ERANGE; + } + + if (i) { + memcpy(strerrbuf, s, i); + strerrbuf[i-1] = 0; /* In case buf was too small. */ + } + + if (retval) { + __set_errno(retval); + } + + return retval; +} + +#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + register char *s; + int i, retval; + char buf[_STRERROR_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' ' + }; + + s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + if (!strerrbuf) { /* SUSv3 */ + buflen = 0; + } + + retval = EINVAL; + + i = buf + sizeof(buf) - s; + + if (i > buflen) { + i = buflen; + retval = ERANGE; + } + + if (i) { + memcpy(strerrbuf, s, i); + strerrbuf[i-1] = 0; /* In case buf was too small. */ + } + + __set_errno(retval); + + return retval; +} + +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ +libc_hidden_def(__xpg_strerror_r) +weak_alias(__xpg_strerror_r, strerror_r) diff --git a/libc/string/_collate.c b/libc/string/_collate.c new file mode 100644 index 0000000..64b5d96 --- /dev/null +++ b/libc/string/_collate.c @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Dec 20, 2002 + * Initial test implementation of strcoll, strxfrm, wcscoll, and wcsxfrm. + * The code needs to be cleaned up a good bit, but I'd like to see people + * test it out. + * + */ + +#include "_string.h" +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strlcpy) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +#ifdef WANT_WIDE +libc_hidden_proto(wcsxfrm) +libc_hidden_proto(wcscmp) +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) + +#ifdef L_strxfrm +#ifndef WANT_WIDE +#error WANT_WIDE should be defined for L_strxfrm +#endif +#ifdef L_wcsxfrm +#error L_wcsxfrm already defined for L_strxfrm +#endif +#endif /* L_strxfrm */ + +#if defined(L_strxfrm) || defined(L_strxfrm_l) + +#define wcscoll strcoll +#define wcscoll_l strcoll_l +#define wcsxfrm strxfrm +#define wcsxfrm_l strxfrm_l + +#undef WANT_WIDE +#undef Wvoid +#undef Wchar +#undef Wuchar +#undef Wint + +#define Wchar char + +#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +libc_hidden_proto(wcscoll_l) + +libc_hidden_proto(wcscoll) +int wcscoll (const Wchar *s0, const Wchar *s1) +{ + return wcscoll_l(s0, s1, __UCLIBC_CURLOCALE ); +} +libc_hidden_def(wcscoll) + +libc_hidden_proto(wcsxfrm_l) + +libc_hidden_proto(wcsxfrm) +size_t wcsxfrm(Wchar *__restrict ws1, const Wchar *__restrict ws2, size_t n) +{ + return wcsxfrm_l(ws1, ws2, n, __UCLIBC_CURLOCALE ); +} +libc_hidden_def(wcsxfrm) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + + +#if 0 +#define CUR_COLLATE (&__UCLIBC_CURLOCALE_DATA.collate) +#else +#define CUR_COLLATE (& __LOCALE_PTR->collate) +#endif + +#define MAX_PENDING 8 + +typedef struct { + const Wchar *s; + const Wchar *eob; /* end of backward */ + + __uwchar_t weight; + __uwchar_t ui_weight; /* undefined or invalid */ + int colitem; + int weightidx; + int rule; + size_t position; + /* should be wchar_t. if wchar < 0 do EILSEQ? */ + __uwchar_t *cip; + __uwchar_t ci_pending[MAX_PENDING]; /* nul-terminated */ + + char *back_buf; + char *bbe; /* end of back_buf (actual last... not 1 past end) */ + char *bp; /* ptr into backbuf, NULL if not in backward mode */ + char ibb[128]; + size_t bb_size; + + int ru_pushed; +} col_state_t; + + +#define WEIGHT_MASK 0x3fffU +#define RULE_MASK 0xc000U + +#define RULE_FORWARD (1 << 14) +#define RULE_POSITION (1 << 15) + +#define UI_IDX (WEIGHT_MASK-6) +#define POSIT_IDX (WEIGHT_MASK-5) +#define RANGE_IDX (WEIGHT_MASK-4) +#define UNDEF_IDX (WEIGHT_MASK-3) +#define INVAL_IDX (WEIGHT_MASK-2) +#define DITTO_IDX (WEIGHT_MASK-1) + + +#undef TRACE +#if 0 +#define TRACE(X) printf X +#else +#define TRACE(X) ((void)0) +#endif + +static int lookup(wchar_t wc __LOCALE_PARAM ) +{ + unsigned int sc, n, i0, i1; + + if (((__uwchar_t) wc) > 0xffffU) { + return 0; + } + + sc = wc & CUR_COLLATE->ti_mask; + wc >>= CUR_COLLATE->ti_shift; + n = wc & CUR_COLLATE->ii_mask; + wc >>= CUR_COLLATE->ii_shift; + + i0 = CUR_COLLATE->wcs2colidt_tbl[wc]; + i0 <<= CUR_COLLATE->ii_shift; + i1 = CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + i0 + n]; + i1 <<= CUR_COLLATE->ti_shift; + return CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + CUR_COLLATE->ti_len + i1 + sc]; + +} + +static void init_col_state(col_state_t *cs, const Wchar *wcs) +{ + memset(cs, 0, sizeof(col_state_t)); + cs->s = wcs; + cs->bp = cs->back_buf = cs->ibb; + cs->bb_size = 128; + cs->bbe = cs->back_buf + (cs->bb_size -1); +} + +static void next_weight(col_state_t *cs, int pass __LOCALE_PARAM ) +{ + int r, w, ru, ri, popping_backup_stack; + ssize_t n; + const uint16_t *p; +#ifdef WANT_WIDE +#define WC (*cs->s) +#define N (1) +#else /* WANT_WIDE */ + wchar_t WC; + size_t n0, nx; +#define N n0 + +#endif /* WANT_WIDE */ + + do { + + if (cs->ru_pushed) { + ru = cs->ru_pushed; + TRACE(("ru_pushed = %d\n", ru)); + cs->ru_pushed = 0; + goto POSITION_SKIP; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning should we walk pendings backwards? +#endif + if (cs->cip) { /* possible pending weight */ + if ((r = *(cs->cip++)) == 0) { + cs->cip = NULL; + continue; + } + cs->weightidx = r & WEIGHT_MASK; + assert(cs->weightidx); +/* assert(cs->weightidx != WEIGHT_MASK); */ + } else { /* get the next collation item from the string */ + TRACE(("clearing popping flag\n")); + popping_backup_stack = 0; + + IGNORE_LOOP: + /* keep first pos as 0 for a sentinal */ + if (*cs->bp) { /* pending backward chars */ + POP_BACKUP: + popping_backup_stack = 1; + TRACE(("setting popping flag\n")); + n = 0; + if (*cs->bp > 0) { /* singles pending */ + cs->s -= 1; + if ((*cs->bp -= 1) == 0) { + cs->bp -= 1; + } + } else { /* last was a multi */ + cs->s += *cs->bp; + cs->bp -= 1; + } + } else if (!*cs->s) { /* not in backward mode and end of string */ + cs->weight = 0; + return; + } else { + cs->position += 1; + } + + BACK_LOOP: +#ifdef WANT_WIDE + n = 1; + cs->colitem = r = lookup(*cs->s __LOCALE_ARG ); +#else /* WANT_WIDE */ + n = n0 = __locale_mbrtowc_l(&WC, cs->s, __LOCALE_PTR); + if (n < 0) { + __set_errno(EILSEQ); + cs->weight = 0; + return; + } + cs->colitem = r = lookup(WC __LOCALE_ARG ); +#endif /* WANT_WIDE */ + + TRACE((" r=%d WC=%#lx\n", r, (unsigned long)(WC))); + + if (r > CUR_COLLATE->max_col_index) { /* starting char for one or more sequences */ + p = CUR_COLLATE->multistart_tbl; + p += p[r-CUR_COLLATE->max_col_index -1]; + do { + n = N; + r = *p++; + do { + if (!*p) { /* found it */ + cs->colitem = r; + TRACE((" found multi %d\n", n)); + goto FOUND; + } +#ifdef WANT_WIDE + /* the lookup check here is safe since we're assured that *p is a valid colidx */ + if (!cs->s[n] || (lookup(cs->s[n] __LOCALE_ARG ) != *p)) { + do {} while (*p++); + break; + } + ++p; + ++n; +#else /* WANT_WIDE */ + if (cs->s[n]) { + nx = __locale_mbrtowc_l(&WC, cs->s + n, __LOCALE_PTR); + if (nx < 0) { + __set_errno(EILSEQ); + cs->weight = 0; + return; + } + } + if (!cs->s[n] || (lookup(WC __LOCALE_ARG ) != *p)) { + do {} while (*p++); + break; + } + ++p; + n += nx; /* Only gets here if cs->s[n] != 0, so nx is set. */ +#endif /* WANT_WIDE */ + } while (1); + } while (1); + } else if (r == 0) { /* illegal, undefined, or part of a range */ + if ((CUR_COLLATE->range_count) +#ifdef __UCLIBC_MJN3_ONLY__ +#warning .. need to introduce range as a collating item? +#endif + && (((__uwchar_t)(WC - CUR_COLLATE->range_low)) <= CUR_COLLATE->range_count) + ) { /* part of a range */ + /* Note: cs->colitem = 0 already. */ + TRACE((" found range\n")); + ru = CUR_COLLATE->ruletable[CUR_COLLATE->range_rule_offset*CUR_COLLATE->MAX_WEIGHTS + pass]; + assert((ru & WEIGHT_MASK) != DITTO_IDX); + if ((ru & WEIGHT_MASK) == WEIGHT_MASK) { + ru = (ru & RULE_MASK) | RANGE_IDX; + cs->weight = CUR_COLLATE->range_base_weight + (WC - CUR_COLLATE->range_low); + } + goto RANGE_SKIP_TO; + } else if (((__uwchar_t)(WC)) <= 0x7fffffffUL) { /* legal but undefined */ + UNDEFINED: + /* Note: cs->colitem = 0 already. */ + ri = CUR_COLLATE->undefined_idx; + assert(ri != 0); /* implicit undefined isn't supported */ + + TRACE((" found explicit UNDEFINED\n")); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning right now single weight locales do not support .. +#endif + if (CUR_COLLATE->num_weights == 1) { + TRACE((" single weight UNDEFINED\n")); + cs->weightidx = RANGE_IDX; + cs->weight = ri; + cs->s += n; + goto PROCESS_WEIGHT; + } + + ri = CUR_COLLATE->index2ruleidx[ri - 1]; + ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass]; + assert((ru & WEIGHT_MASK) != WEIGHT_MASK); /* TODO: handle ".." */ + if ((ru & WEIGHT_MASK) == DITTO_IDX) { + cs->colitem = CUR_COLLATE->undefined_idx; + } + goto RANGE_SKIP_TO; + } else { /* illegal */ + TRACE((" found illegal\n")); + __set_errno(EINVAL); + /* We put all illegals in the same equiv class with maximal weight, + * and ignore them after the first pass. */ + if (pass > 0) { + cs->s += n; + goto IGNORE_LOOP; + } + ru = (RULE_FORWARD | RANGE_IDX); + cs->weight = 0xffffU; + goto RANGE_SKIP_TO; + } + } else if (CUR_COLLATE->num_weights == 1) { + TRACE((" single weight\n")); + cs->weightidx = RANGE_IDX; + cs->weight = cs->colitem; + cs->s += n; + goto PROCESS_WEIGHT; + } else { + TRACE((" normal\n")); + } + + /* if we get here, it is a normal char either singlely weighted, undefined, or in a range */ + FOUND: + ri = CUR_COLLATE->index2ruleidx[cs->colitem - 1]; + TRACE((" ri=%d ", ri)); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning make sure this is correct +#endif + if (!ri) { + TRACE(("NOT IN THIS LOCALE\n")); + goto UNDEFINED; + } + ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass]; + + RANGE_SKIP_TO: + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning ignoreables probably should not interrupt backwards processing, but this is wrong +#endif +/* if (!(ru & WEIGHT_MASK)) { */ +/* TRACE(("IGNORE\n")); */ +/* cs->s += n; */ +/* continue; */ +/* } */ + + + TRACE((" rule = %#x weight = %#x popping = %d s = %p eob = %p\n", + ru & RULE_MASK, ru & WEIGHT_MASK, popping_backup_stack, + cs->s, cs->eob)); + /* now we need to check if we're going backwards... */ + + if (!popping_backup_stack) { + if (!(ru & RULE_MASK)) { /* backward */ + TRACE(("backwards\n")); + assert(cs->bp <= cs->bbe); + if (cs->bp == cs->bbe) { + if (cs->back_buf == cs->ibb) { /* was using internal buffer */ + cs->bp = malloc(cs->bb_size + 128); + if (!cs->bp) { + __set_errno(ENOMEM); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning what to do here? +#endif + cs->weight = 0; + return; + } + memcpy(cs->bp, cs->back_buf, cs->bb_size); + + } else { + cs->bp = realloc(cs->back_buf, cs->bb_size + 128); + if (!cs->bp) { + __set_errno(ENOMEM); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning what to do here? +#endif + cs->weight = 0; + return; + } + } + cs->bb_size += 128; + cs->bbe = cs->bp + (cs->bbe - cs->back_buf); + cs->back_buf = cs->bp; + cs->bp = cs->bbe; + + } + if (n==1) { /* single char */ + if (*cs->bp && (((unsigned char)(*cs->bp)) < CHAR_MAX)) { + *cs->bp += 1; /* increment last single's count */ + } else { /* last was a multi, or just starting */ + if (!cs->bp) { + cs->bp = cs->back_buf; + } else { + assert(cs->bp < cs->bbe); + ++cs->bp; + } + *cs->bp = 1; + } + } else { /* multichar */ + assert(n>1); + assert(cs->bp < cs->bbe); + *++cs->bp = -n; + } + cs->s += n; + if (*cs->s) { + goto BACK_LOOP; + } + /* end-of-string so start popping */ + cs->eob = cs->s; + TRACE(("popping\n")); + goto POP_BACKUP; + } else if (*cs->bp) { /* was going backward but this element isn't */ + /* discard current and use previous backward element */ + assert(!cs->cip); + cs->eob = cs->s; + TRACE(("popping\n")); + goto POP_BACKUP; + } else { /* was and still going forward */ + TRACE(("forwards\n")); + if ((ru & (RULE_POSITION|WEIGHT_MASK)) > RULE_POSITION) { + assert(ru & WEIGHT_MASK); + cs->ru_pushed = ru; + cs->weight = cs->position; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning devel code +#endif + cs->position = 0; /* reset to reduce size for strcoll? */ + cs->s += n; + cs->weightidx = RANGE_IDX; + goto PROCESS_WEIGHT; + } + } + } else { /* popping backwards stack */ + TRACE(("popping (continued)\n")); + if (!*cs->bp) { + cs->s = cs->eob; + } + cs->s -= n; + } + + cs->s += n; + POSITION_SKIP: + cs->weightidx = ru & WEIGHT_MASK; + cs->rule = ru & RULE_MASK; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning for pending we only want the weight... _not_ the rule +#endif + if (!cs->weightidx) { /* ignore */ + continue; + } + + PROCESS_WEIGHT: + assert(cs->weightidx); + + + if (((unsigned int)(cs->weightidx - UI_IDX)) <= (INVAL_IDX-UI_IDX)) { + if (cs->weightidx == UI_IDX) { + cs->weight = cs->ui_weight; + } + return; + } + + assert(cs->weightidx != WEIGHT_MASK); + if (cs->weightidx == DITTO_IDX) { /* want the weight of the current collating item */ + TRACE(("doing ditto\n")); + w = CUR_COLLATE->index2weight[cs->colitem -1]; + } else if (cs->weightidx <= CUR_COLLATE->max_col_index) { /* normal */ + TRACE(("doing normal\n")); + w = CUR_COLLATE->index2weight[cs->weightidx -1]; + } else { /* a string */ + TRACE(("doing string\n")); + assert(!(cs->weightidx & RULE_MASK)); + /* note: iso14561 allows null string here */ + p = CUR_COLLATE->weightstr + (cs->weightidx - (CUR_COLLATE->max_col_index + 2)); + if (*p & WEIGHT_MASK) { + r = 0; + do { + assert(r < MAX_PENDING); + cs->ci_pending[r++] = *p++; + } while (*p & WEIGHT_MASK); + cs->cip = cs->ci_pending; + } + continue; + } + + cs->weight = w; + return; + } while (1); +} + +libc_hidden_proto(__XL_NPP(wcscoll)) +int __XL_NPP(wcscoll) (const Wchar *s0, const Wchar *s1 __LOCALE_PARAM ) +{ + col_state_t ws[2]; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ +#ifdef WANT_WIDE + return wcscmp(s0, s1); +#else /* WANT_WIDE */ + return strcmp(s0, s1); +#endif /* WANT_WIDE */ + } + + pass = 0; + do { /* loop through the weights levels */ + init_col_state(ws, s0); + init_col_state(ws+1, s1); + do { /* loop through the strings */ + /* for each string, get the next weight */ + next_weight(ws, pass __LOCALE_ARG ); + next_weight(ws+1, pass __LOCALE_ARG ); + TRACE(("w0=%lu w1=%lu\n", + (unsigned long) ws[0].weight, + (unsigned long) ws[1].weight)); + + if (ws[0].weight != ws[1].weight) { + return ws[0].weight - ws[1].weight; + } + } while (ws[0].weight); + } while (++pass < CUR_COLLATE->num_weights); + + return 0; +} +libc_hidden_def(__XL_NPP(wcscoll)) + +#ifdef WANT_WIDE + +extern size_t __wcslcpy(wchar_t *__restrict dst, + const wchar_t *__restrict src, size_t n); + +libc_hidden_proto(__XL_NPP(wcsxfrm)) +size_t __XL_NPP(wcsxfrm)(wchar_t *__restrict ws1, const wchar_t *__restrict ws2, + size_t n __LOCALE_PARAM ) +{ + col_state_t cs; + size_t count; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ + return __wcslcpy(ws1, ws2, n); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning handle empty string as a special case +#endif + + count = pass = 0; + do { /* loop through the weights levels */ + init_col_state(&cs, ws2); + do { /* loop through the string */ + next_weight(&cs, pass __LOCALE_ARG ); + TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight)); + if (count < n) { + ws1[count] = cs.weight +1; + } + ++count; + TRACE(("--------------------------------------------\n")); + } while (cs.weight); + if (count <= n) { /* overwrite the trailing 0 end-of-pass marker */ + ws1[count-1] = 1; + } + TRACE(("-------------------- pass %d --------------------\n", pass)); + } while (++pass < CUR_COLLATE->num_weights); + if (count <= n) { /* oops... change it back */ + ws1[count-1] = 0; + } + return count-1; +} +libc_hidden_def(__XL_NPP(wcsxfrm)) + +#else /* WANT_WIDE */ + +static const unsigned long bound[] = { + 1UL << 7, + 1UL << 11, + 1UL << 16, + 1UL << 21, + 1UL << 26, +}; + +static unsigned char first[] = { + 0x0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* Use an extension of UTF-8 to store a 32 bit val in max 6 bytes. */ + +static size_t store(unsigned char *s, size_t count, size_t n, __uwchar_t weight) +{ + int i, r; + + i = 0; + do { + if (weight < bound[i]) { + break; + } + } while (++i < sizeof(bound)/sizeof(bound[0])); + + r = i+1; + if (i + count < n) { + s += count; + s[0] = first[i]; + while (i) { + s[i] = 0x80 | (weight & 0x3f); + weight >>= 6; + --i; + } + s[0] |= weight; + } + + return r; +} + +libc_hidden_proto(__XL_NPP(strxfrm)) +size_t __XL_NPP(strxfrm)(char *__restrict ws1, const char *__restrict ws2, size_t n + __LOCALE_PARAM ) +{ + col_state_t cs; + size_t count, inc; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ + return strlcpy(ws1, ws2, n); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning handle empty string as a special case +#endif + + inc = count = pass = 0; + do { /* loop through the weights levels */ + init_col_state(&cs, ws2); + do { /* loop through the string */ + next_weight(&cs, pass __LOCALE_ARG ); + TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight)); + inc = store((unsigned char *)ws1, count, n, cs.weight + 1); + count += inc; + TRACE(("--------------------------------------------\n")); + } while (cs.weight); + /* overwrite the trailing 0 end-of-pass marker */ + assert(inc == 1); + if (count <= n) { + ws1[count-1] = 1; + } + TRACE(("-------------------- pass %d --------------------\n", pass)); + } while (++pass < CUR_COLLATE->num_weights); + if (count <= n) { /* oops... change it back */ + ws1[count-1] = 0; + } + return count-1; +} +libc_hidden_def(__XL_NPP(strxfrm)) + +#endif /* WANT_WIDE */ + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) */ + +#endif /* __UCLIBC_HAS_LOCALE__ */ +/**********************************************************************/ diff --git a/libc/string/_string.h b/libc/string/_string.h new file mode 100644 index 0000000..67f17b1 --- /dev/null +++ b/libc/string/_string.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __STRING_H +#define __STRING_H + +#include +#include +#include +#include + +#ifdef WANT_WIDE +# include +# include +# include +# define Wvoid wchar_t +# define Wchar wchar_t +# define Wuchar __uwchar_t +# define Wint wchar_t +#else +# define Wvoid void +# define Wchar char +typedef unsigned char __string_uchar_t; +# define Wuchar __string_uchar_t +# define Wint int +#endif + +#endif /* __STRING_H */ diff --git a/libc/string/_string_syserrmsgs.c b/libc/string/_string_syserrmsgs.c new file mode 100644 index 0000000..893af5c --- /dev/null +++ b/libc/string/_string_syserrmsgs.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +attribute_hidden +const char _string_syserrmsgs[] = { + /* 0: 0, 8 */ "Success\0" + /* 1: 8, 24 */ "Operation not permitted\0" + /* 2: 32, 26 */ "No such file or directory\0" + /* 3: 58, 16 */ "No such process\0" + /* 4: 74, 24 */ "Interrupted system call\0" + /* 5: 98, 19 */ "Input/output error\0" + /* 6: 117, 26 */ "No such device or address\0" + /* 7: 143, 23 */ "Argument list too long\0" + /* 8: 166, 18 */ "Exec format error\0" + /* 9: 184, 20 */ "Bad file descriptor\0" + /* 10: 204, 19 */ "No child processes\0" + /* 11: 223, 33 */ "Resource temporarily unavailable\0" + /* 12: 256, 23 */ "Cannot allocate memory\0" + /* 13: 279, 18 */ "Permission denied\0" + /* 14: 297, 12 */ "Bad address\0" + /* 15: 309, 22 */ "Block device required\0" + /* 16: 331, 24 */ "Device or resource busy\0" + /* 17: 355, 12 */ "File exists\0" + /* 18: 367, 26 */ "Invalid cross-device link\0" + /* 19: 393, 15 */ "No such device\0" + /* 20: 408, 16 */ "Not a directory\0" + /* 21: 424, 15 */ "Is a directory\0" + /* 22: 439, 17 */ "Invalid argument\0" + /* 23: 456, 30 */ "Too many open files in system\0" + /* 24: 486, 20 */ "Too many open files\0" + /* 25: 506, 31 */ "Inappropriate ioctl for device\0" + /* 26: 537, 15 */ "Text file busy\0" + /* 27: 552, 15 */ "File too large\0" + /* 28: 567, 24 */ "No space left on device\0" + /* 29: 591, 13 */ "Illegal seek\0" + /* 30: 604, 22 */ "Read-only file system\0" + /* 31: 626, 15 */ "Too many links\0" + /* 32: 641, 12 */ "Broken pipe\0" + /* 33: 653, 33 */ "Numerical argument out of domain\0" + /* 34: 686, 30 */ "Numerical result out of range\0" + /* 35: 716, 26 */ "Resource deadlock avoided\0" + /* 36: 742, 19 */ "File name too long\0" + /* 37: 761, 19 */ "No locks available\0" + /* 38: 780, 25 */ "Function not implemented\0" + /* 39: 805, 20 */ "Directory not empty\0" + /* 40: 825, 34 */ "Too many levels of symbolic links\0" + /* 41: 859, 1 */ "\0" + /* 42: 860, 27 */ "No message of desired type\0" + /* 43: 887, 19 */ "Identifier removed\0" + /* 44: 906, 28 */ "Channel number out of range\0" + /* 45: 934, 25 */ "Level 2 not synchronized\0" + /* 46: 959, 15 */ "Level 3 halted\0" + /* 47: 974, 14 */ "Level 3 reset\0" + /* 48: 988, 25 */ "Link number out of range\0" + /* 49: 1013, 29 */ "Protocol driver not attached\0" + /* 50: 1042, 27 */ "No CSI structure available\0" + /* 51: 1069, 15 */ "Level 2 halted\0" + /* 52: 1084, 17 */ "Invalid exchange\0" + /* 53: 1101, 27 */ "Invalid request descriptor\0" + /* 54: 1128, 14 */ "Exchange full\0" + /* 55: 1142, 9 */ "No anode\0" + /* 56: 1151, 21 */ "Invalid request code\0" + /* 57: 1172, 13 */ "Invalid slot\0" + /* 58: 1185, 1 */ "\0" + /* 59: 1186, 21 */ "Bad font file format\0" + /* 60: 1207, 20 */ "Device not a stream\0" + /* 61: 1227, 18 */ "No data available\0" + /* 62: 1245, 14 */ "Timer expired\0" + /* 63: 1259, 25 */ "Out of streams resources\0" + /* 64: 1284, 30 */ "Machine is not on the network\0" + /* 65: 1314, 22 */ "Package not installed\0" + /* 66: 1336, 17 */ "Object is remote\0" + /* 67: 1353, 22 */ "Link has been severed\0" + /* 68: 1375, 16 */ "Advertise error\0" + /* 69: 1391, 14 */ "Srmount error\0" + /* 70: 1405, 28 */ "Communication error on send\0" + /* 71: 1433, 15 */ "Protocol error\0" + /* 72: 1448, 19 */ "Multihop attempted\0" + /* 73: 1467, 19 */ "RFS specific error\0" + /* 74: 1486, 12 */ "Bad message\0" + /* 75: 1498, 38 */ "Value too large for defined data type\0" + /* 76: 1536, 27 */ "Name not unique on network\0" + /* 77: 1563, 29 */ "File descriptor in bad state\0" + /* 78: 1592, 23 */ "Remote address changed\0" + /* 79: 1615, 39 */ "Can not access a needed shared library\0" + /* 80: 1654, 37 */ "Accessing a corrupted shared library\0" + /* 81: 1691, 32 */ ".lib section in a.out corrupted\0" + /* 82: 1723, 48 */ "Attempting to link in too many shared libraries\0" + /* 83: 1771, 38 */ "Cannot exec a shared library directly\0" + /* 84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0" + /* 85: 1859, 44 */ "Interrupted system call should be restarted\0" + /* 86: 1903, 19 */ "Streams pipe error\0" + /* 87: 1922, 15 */ "Too many users\0" + /* 88: 1937, 31 */ "Socket operation on non-socket\0" + /* 89: 1968, 29 */ "Destination address required\0" + /* 90: 1997, 17 */ "Message too long\0" + /* 91: 2014, 31 */ "Protocol wrong type for socket\0" + /* 92: 2045, 23 */ "Protocol not available\0" + /* 93: 2068, 23 */ "Protocol not supported\0" + /* 94: 2091, 26 */ "Socket type not supported\0" + /* 95: 2117, 24 */ "Operation not supported\0" + /* 96: 2141, 30 */ "Protocol family not supported\0" + /* 97: 2171, 41 */ "Address family not supported by protocol\0" + /* 98: 2212, 23 */ "Address already in use\0" + /* 99: 2235, 32 */ "Cannot assign requested address\0" + /* 100: 2267, 16 */ "Network is down\0" + /* 101: 2283, 23 */ "Network is unreachable\0" + /* 102: 2306, 36 */ "Network dropped connection on reset\0" + /* 103: 2342, 33 */ "Software caused connection abort\0" + /* 104: 2375, 25 */ "Connection reset by peer\0" + /* 105: 2400, 26 */ "No buffer space available\0" + /* 106: 2426, 40 */ "Transport endpoint is already connected\0" + /* 107: 2466, 36 */ "Transport endpoint is not connected\0" + /* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0" + /* 109: 2548, 35 */ "Too many references: cannot splice\0" + /* 110: 2583, 21 */ "Connection timed out\0" + /* 111: 2604, 19 */ "Connection refused\0" + /* 112: 2623, 13 */ "Host is down\0" + /* 113: 2636, 17 */ "No route to host\0" + /* 114: 2653, 30 */ "Operation already in progress\0" + /* 115: 2683, 26 */ "Operation now in progress\0" + /* 116: 2709, 22 */ "Stale NFS file handle\0" + /* 117: 2731, 25 */ "Structure needs cleaning\0" + /* 118: 2756, 28 */ "Not a XENIX named type file\0" + /* 119: 2784, 30 */ "No XENIX semaphores available\0" + /* 120: 2814, 21 */ "Is a named type file\0" + /* 121: 2835, 17 */ "Remote I/O error\0" + /* 122: 2852, 20 */ "Disk quota exceeded\0" + /* 123: 2872, 16 */ "No medium found\0" + /* 124: 2888, 18 */ "Wrong medium type" +#if defined(__mips__) || defined(__sparc__) + "\0" + /* 125: 2906, 28 */ "File locking deadlock error" +#endif + /* Note: for mips we are ignoring ECANCELED since glibc doesn't have a + * corresponsding message.*/ +}; + +#endif diff --git a/libc/string/_string_syssigmsgs.c b/libc/string/_string_syssigmsgs.c new file mode 100644 index 0000000..26c0948 --- /dev/null +++ b/libc/string/_string_syssigmsgs.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ + +attribute_hidden +const char _string_syssigmsgs[] = { + /* 0: 0, 1 */ "\0" + /* 1: 1, 7 */ "Hangup\0" + /* 2: 8, 10 */ "Interrupt\0" + /* 3: 18, 5 */ "Quit\0" + /* 4: 23, 20 */ "Illegal instruction\0" + /* 5: 43, 22 */ "Trace/breakpoint trap\0" + /* 6: 65, 8 */ "Aborted\0" + /* 7: 73, 10 */ "Bus error\0" + /* 8: 83, 25 */ "Floating point exception\0" + /* 9: 108, 7 */ "Killed\0" + /* 10: 115, 22 */ "User defined signal 1\0" + /* 11: 137, 19 */ "Segmentation fault\0" + /* 12: 156, 22 */ "User defined signal 2\0" + /* 13: 178, 12 */ "Broken pipe\0" + /* 14: 190, 12 */ "Alarm clock\0" + /* 15: 202, 11 */ "Terminated\0" + /* 16: 213, 12 */ "Stack fault\0" + /* 17: 225, 13 */ "Child exited\0" + /* 18: 238, 10 */ "Continued\0" + /* 19: 248, 17 */ "Stopped (signal)\0" + /* 20: 265, 8 */ "Stopped\0" + /* 21: 273, 20 */ "Stopped (tty input)\0" + /* 22: 293, 21 */ "Stopped (tty output)\0" + /* 23: 314, 21 */ "Urgent I/O condition\0" + /* 24: 335, 24 */ "CPU time limit exceeded\0" + /* 25: 359, 25 */ "File size limit exceeded\0" + /* 26: 384, 22 */ "Virtual timer expired\0" + /* 27: 406, 24 */ "Profiling timer expired\0" + /* 28: 430, 15 */ "Window changed\0" + /* 29: 445, 13 */ "I/O possible\0" + /* 30: 458, 14 */ "Power failure\0" + /* 31: 472, 16 */ "Bad system call" +#if defined SIGEMT + /* 32: 488, 9 */ "\0EMT trap" +#endif +}; + +#endif diff --git a/libc/string/_syserrmsg.h b/libc/string/_syserrmsg.h new file mode 100644 index 0000000..8bd742e --- /dev/null +++ b/libc/string/_syserrmsg.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __SYSERRMSG_H +#define __SYSERRMSG_H 1 + +#include + +/**********************************************************************/ +/* NOTE: If we ever do internationalized syserr messages, this will + * have to be changed! */ + +#if defined(__mips__) || defined(__sparc__) +/* sparce and mips have an extra error entry, as EDEADLK and EDEADLOCK have + * different meanings on those platforms. */ +# define _SYS_NERR 126 +#else +# define _SYS_NERR 125 +#endif + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ +# define _SYS_ERRMSG_MAXLEN 50 +#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ +# define _SYS_ERRMSG_MAXLEN 0 +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + +#if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14 +# define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14) +#else +# define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN +#endif + +#endif diff --git a/libc/string/arm/Makefile b/libc/string/arm/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/arm/_memcpy.S b/libc/string/arm/_memcpy.S new file mode 100644 index 0000000..103580a --- /dev/null +++ b/libc/string/arm/_memcpy.S @@ -0,0 +1,746 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Adapted for uClibc from NetBSD _memcpy.S,v 1.6 2003/10/09 + * by Erik Andersen + */ + +#include +#include +#include + +#if !defined(THUMB1_ONLY) +/* + * This is one fun bit of code ... + * Some easy listening music is suggested while trying to understand this + * code e.g. Iron Maiden + * + * For anyone attempting to understand it : + * + * The core code is implemented here with simple stubs for memcpy() + * memmove() and bcopy(). + * + * All local labels are prefixed with Lmemcpy_ + * Following the prefix a label starting f is used in the forward copy code + * while a label using b is used in the backwards copy code + * The source and destination addresses determine whether a forward or + * backward copy is performed. + * Separate bits of code are used to deal with the following situations + * for both the forward and backwards copy. + * unaligned source address + * unaligned destination address + * Separate copy routines are used to produce an optimised result for each + * of these cases. + * The copy code will use LDM/STM instructions to copy up to 32 bytes at + * a time where possible. + * + * Note: r12 (aka ip) can be trashed during the function along with + * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out. + * Additional registers are preserved prior to use i.e. r4, r5 & lr + * + * Apologies for the state of the comments ;-) + */ + +.text +.global _memcpy +.hidden _memcpy +.type _memcpy,%function +.align 4 + +/* XXX: The Thumb-2 conditionals can be removed if/when we require an + assembler that supports unified syntax. */ +.macro copy regs +#if defined(__thumb2__) + ittt ge + ldmiage r1!, \regs + stmiage r0!, \regs +#else + ldmgeia r1!, \regs + stmgeia r0!, \regs +#endif +.endm + +.macro copydb regs +#if defined(__thumb2__) + ittt ge + ldmdbge r1!, \regs + stmdbge r0!, \regs +#else + ldmgedb r1!, \regs + stmgedb r0!, \regs +#endif +.endm + +_memcpy: + /* Determine copy direction */ + cmp r1, r0 + bcc .Lmemcpy_backwards + + IT(tt, eq) /* Quick abort for src=dst */ +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr +#endif + stmdb sp!, {r0, lr} /* memcpy() returns dest addr */ + subs r2, r2, #4 + blt .Lmemcpy_fl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemcpy_fdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemcpy_fsrcul /* oh unaligned source addr */ + +.Lmemcpy_ft8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemcpy_fl12 /* less than 12 bytes (4 from above) */ + subs r2, r2, #0x14 + blt .Lmemcpy_fl32 /* less than 32 bytes (12 from above) */ + str r4, [sp, #-4]! /* borrow r4 */ + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemcpy_floop32: + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemcpy_floop32 + + cmn r2, #0x10 + /* blat a remaining 16 bytes */ + copy "{r3, r4, r12, lr}" + subge r2, r2, #0x10 + ldr r4, [sp], #4 /* restore r4 */ + +.Lmemcpy_fl32: + adds r2, r2, #0x14 + + /* blat 12 bytes at a time */ +.Lmemcpy_floop12: + copy "{r3, r12, lr}" +#if defined(__thumb2__) + subsge r2, r2, #0x0c +#else + subges r2, r2, #0x0c +#endif + bge .Lmemcpy_floop12 + +.Lmemcpy_fl12: + adds r2, r2, #8 + blt .Lmemcpy_fl4 + + subs r2, r2, #4 + IT(tt, lt) + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + copy "{r3, r12}" + subge r2, r2, #4 + +.Lmemcpy_fl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 +#if defined(__thumb2__) + it eq + popeq {r0, pc} /* done */ +#elif defined(__ARM_ARCH_4T__) + ldmeqia sp!, {r0, r3} /* done */ + bxeq r3 +#else + ldmeqia sp!, {r0, pc} /* done */ +#endif + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 +#if defined(__thumb2__) + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 +#else + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 +#endif +#if defined(__ARM_ARCH_4T__) + ldmia sp!, {r0, r3} + bx r3 +#else + ldmia sp!, {r0, pc} +#endif + + /* erg - unaligned destination */ +.Lmemcpy_fdestul: + rsb r12, r12, #4 + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1], #1 + strb r3, [r0], #1 +#if defined(__thumb2__) + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 +#else + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 +#endif + subs r2, r2, r12 + blt .Lmemcpy_fl4 /* less the 4 bytes */ + + ands r12, r1, #3 + beq .Lmemcpy_ft8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemcpy_fsrcul: + bic r1, r1, #3 + ldr lr, [r1], #4 + cmp r12, #2 + bgt .Lmemcpy_fsrcul3 + beq .Lmemcpy_fsrcul2 + cmp r2, #0x0c + blt .Lmemcpy_fsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul1loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, lr, lsr #24 +#else + mov r3, lr, lsr #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, lr, lsl #24 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul1loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul1l4 + +.Lmemcpy_fsrcul1loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #24 +#else + mov r12, lr, lsr #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #24 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul1loop4 + +.Lmemcpy_fsrcul1l4: + sub r1, r1, #3 + b .Lmemcpy_fl4 + +.Lmemcpy_fsrcul2: + cmp r2, #0x0c + blt .Lmemcpy_fsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul2loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, lr, lsr #16 +#else + mov r3, lr, lsr #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, lr, lsl #16 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul2loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul2l4 + +.Lmemcpy_fsrcul2loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #16 +#else + mov r12, lr, lsr #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #16 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul2loop4 + +.Lmemcpy_fsrcul2l4: + sub r1, r1, #2 + b .Lmemcpy_fl4 + +.Lmemcpy_fsrcul3: + cmp r2, #0x0c + blt .Lmemcpy_fsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul3loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, lr, lsr #8 +#else + mov r3, lr, lsr #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, lr, lsl #8 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul3loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul3l4 + +.Lmemcpy_fsrcul3loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #8 +#else + mov r12, lr, lsr #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #8 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul3loop4 + +.Lmemcpy_fsrcul3l4: + sub r1, r1, #1 + b .Lmemcpy_fl4 + +.Lmemcpy_backwards: + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt .Lmemcpy_bl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemcpy_bdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemcpy_bsrcul /* oh unaligned source addr */ + +.Lmemcpy_bt8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemcpy_bl12 /* less than 12 bytes (4 from above) */ + stmdb sp!, {r4, lr} + subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */ + blt .Lmemcpy_bl32 + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemcpy_bloop32: + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemcpy_bloop32 + +.Lmemcpy_bl32: + cmn r2, #0x10 + /* blat a remaining 16 bytes */ + copydb "{r3, r4, r12, lr}" + subge r2, r2, #0x10 + adds r2, r2, #0x14 + /* blat a remaining 12 bytes */ + copydb "{r3, r12, lr}" + subge r2, r2, #0x0c + ldmia sp!, {r4, lr} + +.Lmemcpy_bl12: + adds r2, r2, #8 + blt .Lmemcpy_bl4 + subs r2, r2, #4 + IT(tt, lt) + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + copydb "{r3, r12}" + subge r2, r2, #4 + +.Lmemcpy_bl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + IT(t, eq) +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr /* done */ +#endif + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! +#ifdef __thumb2__ + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! +#else + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! +#endif +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif + /* erg - unaligned destination */ +.Lmemcpy_bdestul: + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! +#ifdef __thumb2__ + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! +#else + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! +#endif + subs r2, r2, r12 + blt .Lmemcpy_bl4 /* less than 4 bytes to go */ + ands r12, r1, #3 + beq .Lmemcpy_bt8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemcpy_bsrcul: + bic r1, r1, #3 + ldr r3, [r1, #0] + cmp r12, #2 + blt .Lmemcpy_bsrcul1 + beq .Lmemcpy_bsrcul2 + cmp r2, #0x0c + blt .Lmemcpy_bsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul3loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r3, lsl #24 +#else + mov lr, r3, lsl #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul3loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul3l4 + +.Lmemcpy_bsrcul3loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #24 +#else + mov r12, r3, lsl #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #24 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul3loop4 + +.Lmemcpy_bsrcul3l4: + add r1, r1, #3 + b .Lmemcpy_bl4 + +.Lmemcpy_bsrcul2: + cmp r2, #0x0c + blt .Lmemcpy_bsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul2loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r3, lsl #16 +#else + mov lr, r3, lsl #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul2loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul2l4 + +.Lmemcpy_bsrcul2loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #16 +#else + mov r12, r3, lsl #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #16 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul2loop4 + +.Lmemcpy_bsrcul2l4: + add r1, r1, #2 + b .Lmemcpy_bl4 + +.Lmemcpy_bsrcul1: + cmp r2, #0x0c + blt .Lmemcpy_bsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul1loop32: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r3, lsl #8 +#else + mov lr, r3, lsl #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul1loop32 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul1l4 + +.Lmemcpy_bsrcul1loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #8 +#else + mov r12, r3, lsl #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #8 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul1loop4 + +.Lmemcpy_bsrcul1l4: + add r1, r1, #1 + b .Lmemcpy_bl4 + +#else /* THUMB1_ONLY */ + +/* This is a fairly dumb implementation for when we can't use the 32-bit code + above. */ +.text +.global _memcpy +.hidden _memcpy +.type _memcpy,%function +.align 4 +.thumb +_memcpy: + push {r0, r4} + cmp r2, #0 + beq .Lmemcpy_exit + @ See if we have overlapping regions, and need to reverse the + @ direction of the copy + cmp r0, r1 + bls .Lmemcpy_forwards + add r4, r1, r2 + cmp r0, r4 + bcc .Lmemcpy_backwards +.Lmemcpy_forwards: + /* Forwards. */ + mov r3, r0 + eor r3, r1 + mov r4, #3 + tst r3, r4 + bne .Lmemcpy_funaligned + cmp r2, #8 + bcc .Lmemcpy_funaligned +1: @ copy up to the first word boundary. + tst r0, r4 + beq 1f + ldrb r3, [r1] + add r1, r1, #1 + strb r3, [r0] + add r0, r0, #1 + sub r2, r2, #1 + b 1b +1: @ Copy aligned words + ldr r3, [r1] + add r1, r1, #4 + str r3, [r0] + add r0, r0, #4 + sub r2, r2, #4 + cmp r2, #4 + bcs 1b + cmp r2, #0 + beq .Lmemcpy_exit +.Lmemcpy_funaligned: +1: + ldrb r3, [r1] + add r1, r1, #1 + strb r3, [r0] + add r0, r0, #1 + sub r2, r2, #1 + bne 1b +.Lmemcpy_exit: + pop {r0, r4} + bx lr + +.Lmemcpy_backwards: + add r0, r0, r2 + add r1, r1, r2 +1: + sub r0, r0, #1 + sub r1, r1, #1 + ldrb r3, [r1] + strb r3, [r0] + sub r2, r2, #1 + bne 1b + b .Lmemcpy_exit +#endif diff --git a/libc/string/arm/bcopy.S b/libc/string/arm/bcopy.S new file mode 100644 index 0000000..2d6e90d --- /dev/null +++ b/libc/string/arm/bcopy.S @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Adapted for uClibc from NetBSD bcopy.S,v 1.2 1997/10/09 + * by Erik Andersen + */ + +/* bcopy = memcpy/memmove with arguments reversed. */ + +#include +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +.text +.global bcopy +.type bcopy,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +bcopy: + push {r2, lr} + mov ip, r0 + mov r0, r1 + mov r1, ip + bl _memcpy + POP_RET +#else +bcopy: + /* switch the source and destination registers */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + b _memcpy /* (PLT) */ +#endif + +.size bcopy,.-bcopy + +#endif diff --git a/libc/string/arm/bzero.S b/libc/string/arm/bzero.S new file mode 100644 index 0000000..e576a12 --- /dev/null +++ b/libc/string/arm/bzero.S @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Adapted for uClibc from NetBSD bzero.S,v 1.2 1997/10/09 + * by Erik Andersen + */ + +#include +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +.text +.global bzero +.type bzero,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +bzero: + push {r2, lr} + mov r2, r1 + mov r1, #0 + bl HIDDEN_JUMPTARGET(memset) + POP_RET +#else + +bzero: + mov r2, r1 + mov r1, #0 + b HIDDEN_JUMPTARGET(memset) +#endif + +.size bzero,.-bzero + +#endif diff --git a/libc/string/arm/memcmp.S b/libc/string/arm/memcmp.S new file mode 100644 index 0000000..65409f4 --- /dev/null +++ b/libc/string/arm/memcmp.S @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002 ARM Ltd + * 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. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. + * + * Adapted for uClibc from NetBSD memcmp.S, version 1.2 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memcmp +.type memcmp,%function +.align 4 + +#if defined(THUMB1_ONLY) +.thumb_func +memcmp: + cmp r2, #0 + bne 1f + mov r0, #0 + bx lr +1: + push {r4} + add r4, r0, r2 +2: + ldrb r2, [r0] + add r0, r0, #1 + ldrb r3, [r1] + add r1, r1, #1 + cmp r4, r0 + beq 3f + cmp r2, r3 + beq 2b +3: + sub r0, r2, r3 + pop {r4} + bx lr +#else +memcmp: + /* if ((len - 1) < 0) return 0 */ + subs r2, r2, #1 + IT(tt, mi) + movmi r0, #0 +#if defined(__USE_BX__) + bxmi lr +#else + movmi pc, lr +#endif + /* ip == last src address to compare */ + add ip, r0, r2 +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp ip, r0 + IT(t, cs) + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size memcmp,.-memcmp + +libc_hidden_def(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/libc/string/arm/memcpy.S b/libc/string/arm/memcpy.S new file mode 100644 index 0000000..d2013d2 --- /dev/null +++ b/libc/string/arm/memcpy.S @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Adapted for uClibc from NetBSD memcpy.S,v 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memcpy +.type memcpy,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +memcpy: + push {r0, lr} + bl _memcpy + POP_RET +#else +memcpy: + b _memcpy +#endif + +.size memcpy,.-memcpy + +libc_hidden_def(memcpy) diff --git a/libc/string/arm/memmove.S b/libc/string/arm/memmove.S new file mode 100644 index 0000000..c11b98d --- /dev/null +++ b/libc/string/arm/memmove.S @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * Adapted for uClibc from NetBSD memmove.S,v 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memmove +.type memmove,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +memmove: + push {r2, lr} + bl _memcpy + POP_RET +#else +memmove: + b _memcpy +#endif + +.size memmove,.-memmove + +libc_hidden_def(memmove) diff --git a/libc/string/arm/memset.S b/libc/string/arm/memset.S new file mode 100644 index 0000000..66aa603 --- /dev/null +++ b/libc/string/arm/memset.S @@ -0,0 +1,144 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +.text +.global memset +.type memset,%function +.align 4 + +#if defined(THUMB1_ONLY) +.thumb_func +memset: + mov ip, r0 + cmp r2, #8 @ at least 8 bytes to do? + bcc 2f + + lsl r3, r1, #8 + orr r1, r3 + lsl r3, r1, #16 + orr r1, r3 + + mov r3, #3 +1: @ Fill up to the first word boundary + tst r0, r3 + beq 1f + strb r1, [r0] + add r0, r0, #1 + sub r2, r2, #1 + b 1b +1: @ Fill aligned words + str r1, [r0] + add r0, r0, #4 + sub r2, r2, #4 + cmp r2, #4 + bcs 1b + +2: @ Fill the remaining bytes + cmp r2, #0 + beq 2f +1: + strb r1, [r0] + add r0, r0, #1 + sub r2, r2, #1 + bne 1b +2: + mov r0, ip + bx lr +#else +memset: + mov a4, a1 + cmp a3, $8 @ at least 8 bytes to do? + blt 2f + orr a2, a2, a2, lsl $8 + orr a2, a2, a2, lsl $16 +1: + tst a4, $3 @ aligned yet? +#if defined(__thumb2__) + itt ne + strbne a2, [a4], $1 + subne a3, a3, $1 +#else + strneb a2, [a4], $1 + subne a3, a3, $1 +#endif + bne 1b + mov ip, a2 +1: + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? +#if defined(__thumb2__) + itt ge + stmiage a4!, {a2, ip} + subge a3, a3, $8 +#else + stmgeia a4!, {a2, ip} + subge a3, a3, $8 +#endif + bge 1b +2: + movs a3, a3 @ anything left? + IT(t, eq) +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr @ nope +#endif +#if defined (__thumb2__) +1: + strb a2, [a4], #1 + subs a3, a3, #1 + bne 1b + bx lr +#else + rsb a3, a3, $7 + add pc, pc, a3, lsl $2 + mov r0, r0 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif +#endif + +.size memset,.-memset + +libc_hidden_def(memset) diff --git a/libc/string/arm/strcmp.S b/libc/string/arm/strcmp.S new file mode 100644 index 0000000..97363c1 --- /dev/null +++ b/libc/string/arm/strcmp.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002 ARM Ltd + * 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. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. + * + * Adapted for uClibc from NetBSD strcmp.S, version 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global strcmp +.type strcmp,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +strcmp: +1: + ldrb r2, [r0] + add r0, r0, #1 + ldrb r3, [r1] + add r1, r1, #1 + cmp r2, #0 + beq 2f + cmp r2, r3 + beq 1b +2: + sub r0, r2, r3 + bx lr +#else +strcmp: +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp r2, #1 + IT(t, cs) + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size strcmp,.-strcmp + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/arm/strlen.S b/libc/string/arm/strlen.S new file mode 100644 index 0000000..949e918 --- /dev/null +++ b/libc/string/arm/strlen.S @@ -0,0 +1,111 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Code contributed by Matthew Wilcox + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* size_t strlen(const char *S) + * entry: r0 -> string + * exit: r0 = len + */ + +.text +.global strlen +.type strlen,%function +.align 4 + +#if defined(THUMB1_ONLY) +/* A simple implementation for when the ARM implementation can't be used. */ +.thumb_func +strlen: + mov r2, #0 +1: + ldrb r1, [r0, r2] + add r2, r2, #1 + cmp r1, #0 + bne 1b + sub r0, r2, #1 + bx lr +#else +strlen: + bic r1, r0, $3 @ addr of word containing first byte + ldr r2, [r1], $4 @ get the first word + ands r3, r0, $3 @ how many bytes are duff? + rsb r0, r3, $0 @ get - that number into counter. + beq Laligned @ skip into main check routine if no + @ more +#if __BYTE_ORDER == __BIG_ENDIAN + orr r2, r2, $0xff000000 @ set this byte to non-zero + subs r3, r3, $1 @ any more to do? + IT(t, gt) + orrgt r2, r2, $0x00ff0000 @ if so, set this byte + subs r3, r3, $1 @ more? + IT(t, gt) + orrgt r2, r2, $0x0000ff00 @ then set. +#else + orr r2, r2, $0x000000ff @ set this byte to non-zero + subs r3, r3, $1 @ any more to do? + IT(t, gt) + orrgt r2, r2, $0x0000ff00 @ if so, set this byte + subs r3, r3, $1 @ more? + IT(t, gt) + orrgt r2, r2, $0x00ff0000 @ then set. +#endif +Laligned: @ here, we have a word in r2. Does it + tst r2, $0x000000ff @ contain any zeroes? + IT(tttt, ne) + tstne r2, $0x0000ff00 @ + tstne r2, $0x00ff0000 @ + tstne r2, $0xff000000 @ + addne r0, r0, $4 @ if not, the string is 4 bytes longer + IT(t, ne) + ldrne r2, [r1], $4 @ and we continue to the next word + bne Laligned @ +Llastword: @ drop through to here once we find a +#if __BYTE_ORDER == __BIG_ENDIAN + tst r2, $0xff000000 @ word that has a zero byte in it + IT(tttt, ne) + addne r0, r0, $1 @ + tstne r2, $0x00ff0000 @ and add up to 3 bytes on to it + addne r0, r0, $1 @ + tstne r2, $0x0000ff00 @ (if first three all non-zero, 4th + IT(t, ne) + addne r0, r0, $1 @ must be zero) +#else + tst r2, $0x000000ff @ + IT(tttt, ne) + addne r0, r0, $1 @ + tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it + addne r0, r0, $1 @ + tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th + IT(t, ne) + addne r0, r0, $1 @ must be zero) +#endif +#if defined(__USE_BX__) + bx lr +#else + mov pc,lr +#endif +#endif + +.size strlen,.-strlen + +libc_hidden_def(strlen) diff --git a/libc/string/avr32/Makefile b/libc/string/avr32/Makefile new file mode 100644 index 0000000..e19e9d9 --- /dev/null +++ b/libc/string/avr32/Makefile @@ -0,0 +1,26 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +top_srcdir := ../../../ +top_builddir := ../../../ + +all: objs + +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/avr32/bcopy.S b/libc/string/avr32/bcopy.S new file mode 100644 index 0000000..bdd5218 --- /dev/null +++ b/libc/string/avr32/bcopy.S @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + + .text + .global bcopy + .type bcopy, @function + .align 1 +bcopy: + /* Swap the first two arguments */ + eor r11, r12 + eor r12, r11 + eor r11, r12 + rjmp HIDDEN_JUMPTARGET(memmove) + + .size bcopy, . - bcopy + +#endif /* __UCLIBC_SUSV3_LEGACY__ */ diff --git a/libc/string/avr32/bzero.S b/libc/string/avr32/bzero.S new file mode 100644 index 0000000..ca1bd2d --- /dev/null +++ b/libc/string/avr32/bzero.S @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + + .text + .global bzero + .type bzero, @function + .align 1 +bzero: + mov r10, r11 + mov r11, 0 + rjmp HIDDEN_JUMPTARGET(memset) + + .size bzero, . - bzero + +#endif /* __UCLIBC_SUSV3_LEGACY__ */ diff --git a/libc/string/avr32/memcmp.S b/libc/string/avr32/memcmp.S new file mode 100644 index 0000000..ae6cc91 --- /dev/null +++ b/libc/string/avr32/memcmp.S @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s1 r12 +#define s2 r11 +#define len r10 + + .text + .global memcmp + .type memcmp, @function + .align 1 +memcmp: + sub len, 4 + brlt .Lless_than_4 + +1: ld.w r8, s1++ + ld.w r9, s2++ + cp.w r8, r9 + brne .Lfound_word + sub len, 4 + brge 1b + +.Lless_than_4: + sub len, -4 + reteq 0 + +1: ld.ub r8, s1++ + ld.ub r9, s2++ + sub r8, r9 + retne r8 + sub len, 1 + brgt 1b + + retal 0 + +.Lfound_word: + mov len, 4 + +2: bfextu r11, r9, 24, 8 + bfextu r12, r8, 24, 8 + sub r12, r11 + retne r12 + lsl r8, 8 + lsl r9, 8 + sub len, 1 + brne 2b + retal r12 + + .size memcmp, . - memcmp + +libc_hidden_def(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/libc/string/avr32/memcpy.S b/libc/string/avr32/memcpy.S new file mode 100644 index 0000000..bf091ab --- /dev/null +++ b/libc/string/avr32/memcpy.S @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +/* Don't use r12 as dst since we must return it unmodified */ +#define dst r9 +#define src r11 +#define len r10 + + .text + .global memcpy + .type memcpy, @function +memcpy: + pref src[0] + mov dst, r12 + + /* If we have less than 32 bytes, don't do anything fancy */ + cp.w len, 32 + brge .Lmore_than_31 + + sub len, 1 + retlt r12 +1: ld.ub r8, src++ + st.b dst++, r8 + sub len, 1 + brge 1b + retal r12 + +.Lmore_than_31: + pushm r0-r7, lr + + /* Check alignment */ + mov r8, src + andl r8, 31, COH + brne .Lunaligned_src + mov r8, dst + andl r8, 3, COH + brne .Lunaligned_dst + +.Laligned_copy: + sub len, 32 + brlt .Lless_than_32 + +1: /* Copy 32 bytes at a time */ + ldm src, r0-r7 + sub src, -32 + stm dst, r0-r7 + sub dst, -32 + sub len, 32 + brge 1b + +.Lless_than_32: + /* Copy 16 more bytes if possible */ + sub len, -16 + brlt .Lless_than_16 + ldm src, r0-r3 + sub src, -16 + sub len, 16 + stm dst, r0-r3 + sub dst, -16 + +.Lless_than_16: + /* Do the remaining as byte copies */ + neg len + add pc, pc, len << 2 + .rept 15 + ld.ub r0, src++ + st.b dst++, r0 + .endr + + popm r0-r7, pc + +.Lunaligned_src: + /* Make src cacheline-aligned. r8 = (src & 31) */ + rsub r8, r8, 32 + sub len, r8 +1: ld.ub r0, src++ + st.b dst++, r0 + sub r8, 1 + brne 1b + + /* If dst is word-aligned, we're ready to go */ + pref src[0] + mov r8, 3 + tst dst, r8 + breq .Laligned_copy + +.Lunaligned_dst: + /* src is aligned, but dst is not. Expect bad performance */ + sub len, 4 + brlt 2f +1: ld.w r0, src++ + st.w dst++, r0 + sub len, 4 + brge 1b + +2: neg len + add pc, pc, len << 2 + .rept 3 + ld.ub r0, src++ + st.b dst++, r0 + .endr + + popm r0-r7, pc + .size memcpy, . - memcpy + +libc_hidden_def(memcpy) diff --git a/libc/string/avr32/memmove.S b/libc/string/avr32/memmove.S new file mode 100644 index 0000000..535f4a2 --- /dev/null +++ b/libc/string/avr32/memmove.S @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#define dst r12 +#define src r11 +#define len r10 + + .text + .global memmove + .type memmove, @function +memmove: + cp.w src, dst + brge HIDDEN_JUMPTARGET(memcpy) + + add dst, len + add src, len + pref src[-1] + + /* + * The rest is basically the same as in memcpy.S except that + * the direction is reversed. + */ + cp.w len, 32 + brge .Lmore_than_31 + + sub len, 1 + retlt r12 +1: ld.ub r8, --src + st.b --dst, r8 + sub len, 1 + brge 1b + retal r12 + +.Lmore_than_31: + pushm r0-r7, lr + + /* Check alignment */ + mov r8, src + andl r8, 31, COH + brne .Lunaligned_src + mov r8, r12 + andl r8, 3, COH + brne .Lunaligned_dst + +.Laligned_copy: + sub len, 32 + brlt .Lless_than_32 + +1: /* Copy 32 bytes at a time */ + sub src, 32 + ldm src, r0-r7 + sub dst, 32 + sub len, 32 + stm dst, r0-r7 + brge 1b + +.Lless_than_32: + /* Copy 16 more bytes if possible */ + sub len, -16 + brlt .Lless_than_16 + sub src, 16 + ldm src, r0-r3 + sub dst, 16 + sub len, 16 + stm dst, r0-r3 + +.Lless_than_16: + /* Do the remaining as byte copies */ + sub len, -16 + breq 2f +1: ld.ub r0, --src + st.b --dst, r0 + sub len, 1 + brne 1b + +2: popm r0-r7, pc + +.Lunaligned_src: + /* Make src cacheline-aligned. r8 = (src & 31) */ + sub len, r8 +1: ld.ub r0, --src + st.b --dst, r0 + sub r8, 1 + brne 1b + + /* If dst is word-aligned, we're ready to go */ + pref src[-4] + mov r8, 3 + tst dst, r8 + breq .Laligned_copy + +.Lunaligned_dst: + /* src is aligned, but dst is not. Expect bad performance */ + sub len, 4 + brlt 2f +1: ld.w r0, --src + st.w --dst, r0 + sub len, 4 + brge 1b + +2: neg len + add pc, pc, len << 2 + .rept 3 + ld.ub r0, --src + st.b --dst, r0 + .endr + + popm r0-r7, pc + .size memmove, . - memmove + +libc_hidden_def(memmove) diff --git a/libc/string/avr32/memset.S b/libc/string/avr32/memset.S new file mode 100644 index 0000000..472b2be --- /dev/null +++ b/libc/string/avr32/memset.S @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s r12 +#define c r11 +#define n r10 + + .text + .global memset + .type memset, @function + + .align 1 +memset: + cp.w n, 32 + mov r9, s + brge .Llarge_memset + + sub n, 1 + retlt s +1: st.b s++, c + sub n, 1 + brge 1b + + retal r9 + +.Llarge_memset: + mov r8, r11 + mov r11, 3 + bfins r8, r8, 8, 8 + bfins r8, r8, 16, 16 + tst s, r11 + breq 2f + +1: st.b s++, r8 + sub n, 1 + tst s, r11 + brne 1b + +2: mov r11, r9 + mov r9, r8 + sub n, 8 + +3: st.d s++, r8 + sub n, 8 + brge 3b + + /* If we are done, n == -8 and we'll skip all st.b insns below */ + neg n + lsl n, 1 + add pc, n + .rept 7 + st.b s++, r8 + .endr + retal r11 + + .size memset, . - memset + +libc_hidden_def(memset) diff --git a/libc/string/avr32/strcmp.S b/libc/string/avr32/strcmp.S new file mode 100644 index 0000000..f73bd43 --- /dev/null +++ b/libc/string/avr32/strcmp.S @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s1 r12 +#define s2 r11 +#define len r10 + + .text + .global strcmp + .type strcmp, @function + .align 1 +strcmp: + mov r8, 3 + tst s1, r8 + brne .Lunaligned_s1 + tst s2, r8 + brne .Lunaligned_s2 + +1: ld.w r8, s1++ + ld.w r9, s2++ + cp.w r8, r9 + brne 2f + tnbz r8 + brne 1b + retal 0 + +2: bfextu r12, r8, 24, 8 + bfextu r11, r9, 24, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 16, 8 + bfextu r11, r9, 16, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 8, 8 + bfextu r11, r9, 8, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 0, 8 + bfextu r11, r9, 0, 8 + sub r12, r11 + retal r12 + +.Lunaligned_s1: +3: tst s1, r8 + breq 4f + ld.ub r10, s1++ + ld.ub r9, s2++ + sub r10, r9 + retne r10 + cp.w r9, 0 + brne 3b + retal r10 + +4: tst s2, r8 + breq 1b + +.Lunaligned_s2: + /* + * s1 and s2 can't both be aligned, and unaligned word loads + * can trigger spurious exceptions if we cross a page boundary. + * Do it the slow way... + */ +1: ld.ub r8, s1++ + ld.ub r9, s2++ + sub r8, r9 + retne r8 + cp.w r9, 0 + brne 1b + retal 0 + + .size strcmp, . - strcmp + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp, strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/avr32/strlen.S b/libc/string/avr32/strlen.S new file mode 100644 index 0000000..5223e53 --- /dev/null +++ b/libc/string/avr32/strlen.S @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define str r12 + + .text + .global strlen + .type strlen, @function +strlen: + mov r11, r12 + + mov r9, str + andl r9, 3, COH + brne .Lunaligned_str + +1: ld.w r8, str++ + tnbz r8 + brne 1b + + sub r12, r11 + bfextu r9, r8, 24, 8 + cp.w r9, 0 + subeq r12, 4 + reteq r12 + bfextu r9, r8, 16, 8 + cp.w r9, 0 + subeq r12, 3 + reteq r12 + bfextu r9, r8, 8, 8 + cp.w r9, 0 + subeq r12, 2 + reteq r12 + sub r12, 1 + retal r12 + +.Lunaligned_str: + add pc, pc, r9 << 3 + sub r0, r0, 0 /* 4-byte nop */ + ld.ub r8, str++ + sub r8, r8, 0 + breq 1f + ld.ub r8, str++ + sub r8, r8, 0 + breq 1f + ld.ub r8, str++ + sub r8, r8, 0 + brne 1b + +1: sub r12, 1 + sub r12, r11 + retal r12 + + .size strlen, . - strlen + +libc_hidden_def(strlen) diff --git a/libc/string/basename.c b/libc/string/basename.c new file mode 100644 index 0000000..a076c20 --- /dev/null +++ b/libc/string/basename.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(basename) */ + +char *basename(const char *path) +{ + register const char *s; + register const char *p; + + p = s = path; + + while (*s) { + if (*s++ == '/') { + p = s; + } + } + + return (char *) p; +} +libc_hidden_def(basename) +#endif diff --git a/libc/string/bcopy.c b/libc/string/bcopy.c new file mode 100644 index 0000000..3aa7eab --- /dev/null +++ b/libc/string/bcopy.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +/* Experimentally off - libc_hidden_proto(memmove) */ + +void bcopy(const void *s2, void *s1, size_t n) +{ +#if 1 + memmove(s1, s2, n); +#else +#ifdef __BCC__ + register char *s; + register const char *p; + + s = s1; + p = s2; + if (p >= s) { + while (n--) { + *s++ = *p++; + } + } else { + s += n; + p += n; + while (n--) { + *--s = *--p; + } + } +#else + register char *s; + register const char *p; + + s = s1; + p = s2; + if (p >= s) { + while (n) { + *s++ = *p++; + --n; + } + } else { + while (n) { + --n; + s[n] = p[n]; + } + } +#endif +#endif +} +#endif diff --git a/libc/string/bfin/Makefile b/libc/string/bfin/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/bfin/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/bfin/memchr.S b/libc/string/bfin/memchr.S new file mode 100644 index 0000000..26d419f --- /dev/null +++ b/libc/string/bfin/memchr.S @@ -0,0 +1,55 @@ +/* memchr.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memchr(const void *s, int c, size_t n); + * R0 = address (s) + * R1 = sought byte (c) + * R2 = count (n) + * + * Returns pointer to located character. + */ + +.text + +.align 2 + +.weak _memchr +ENTRY(_memchr) + P0 = R0; /* P0 = address */ + P2 = R2; /* P2 = count */ + R1 = R1.B(Z); + CC = R2 == 0; + IF CC JUMP .Lfailed; + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; + +.Lbyte_loop_s: + R3 = B[P0++](Z); + CC = R3 == R1; + IF CC JUMP .Lfound; +.Lbyte_loop_e: + NOP; + +.Lfailed: + R0=0; + RTS; + +.Lfound: + R0 = P0; + R0 += -1; + RTS; + +.size _memchr,.-_memchr + +libc_hidden_def (memchr) diff --git a/libc/string/bfin/memcmp.S b/libc/string/bfin/memcmp.S new file mode 100644 index 0000000..7cc76ad --- /dev/null +++ b/libc/string/bfin/memcmp.S @@ -0,0 +1,104 @@ +/* memcmp.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* int memcmp(const void *s1, const void *s2, size_t n); + * R0 = First Address (s1) + * R1 = Second Address (s2) + * R2 = count (n) + * + * Favours word aligned data. + */ + +.text + +.align 2 + +.weak _memcmp +ENTRY(_memcmp) + I1 = P3; + P0 = R0; /* P0 = s1 address */ + P3 = R1; /* P3 = s2 Address */ + P2 = R2 ; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; /* s2 */ + R1 = R1 | R0; /* OR addresses together */ + R1 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned. */ + + P1 = P2 >> 2; /* count = n/4 */ + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: +#if !defined(__WORKAROUND_AVOID_DAG1) + MNOP || R0 = [P0++] || R1 = [I0++]; +#else + R0 = [P0++]; + R1 = [I0++]; +#endif + CC = R0 == R1; + IF !CC JUMP .Lquad_different; +.Lquad_loop_e: + NOP; + + P3 = I0; /* s2 */ +.Ltoo_small: + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely*/ + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: + R1 = B[P3++](Z); /* *s2 */ + R0 = B[P0++](Z); /* *s1 */ + CC = R0 == R1; + IF !CC JUMP .Ldifferent; +.Lbyte_loop_e: + NOP; + +.Ldifferent: + R0 = R0 - R1; + P3 = I1; + RTS; + +.Lquad_different: + /* We've read two quads which don't match. + * Can't just compare them, because we're + * a little-endian machine, so the MSBs of + * the regs occur at later addresses in the + * string. + * Arrange to re-read those two quads again, + * byte-by-byte. + */ + P0 += -4; /* back up to the start of the */ + P3 = I0; /* quads, and increase the*/ + P2 += 4; /* remainder count*/ + P3 += -4; + JUMP .Lbytes; + +.Lfinished: + R0 = 0; + P3 = I1; + RTS; + +.size _memcmp,.-_memcmp + +libc_hidden_def (memcmp) + +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias (memcmp,bcmp) +#endif diff --git a/libc/string/bfin/memcpy.S b/libc/string/bfin/memcpy.S new file mode 100644 index 0000000..bdd7606 --- /dev/null +++ b/libc/string/bfin/memcpy.S @@ -0,0 +1,77 @@ +/* memcpy.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memcpy(void *dest, const void *src, size_t n); + * R0 = To Address (dest) (leave unchanged to form result) + * R1 = From Address (src) + * R2 = count + * + * Note: Favours word alignment + */ + +.text + +.align 2 + +.weak _memcpy +ENTRY(_memcpy) + [--SP] = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes; /* Jump if addrs not aligned. */ + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; +#if !defined(__WORKAROUND_AVOID_DAG1) + LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; +#else + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: [P0++] = R1; +.Lquad_loop_e: R1 = [I0++]; +#endif + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 for remaining copy */ + IF !CC JUMP .Lbytes; + P3 = [SP++]; + RTS; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* very unlikely */ + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: R1 = B[P3++](Z); +.Lbyte_loop_e: B[P0++] = R1; + +.Lfinished: + P3 = [SP++]; + + RTS; + +.size _memcpy,.-_memcpy + +libc_hidden_def (memcpy) diff --git a/libc/string/bfin/memmove.S b/libc/string/bfin/memmove.S new file mode 100644 index 0000000..73e3638 --- /dev/null +++ b/libc/string/bfin/memmove.S @@ -0,0 +1,100 @@ +/* memmove.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memmove(void *dest, const void *src, size_t n); + * R0 = To Address (dest) (leave unchanged to form result) + * R1 = From Address (src) + * R2 = count (n) + * + * Note: Data may overlap + */ + +.text + +.align 2 + +.weak _memmove +ENTRY(_memmove) + I1 = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2; /* P2 = count */ + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely */ + + CC = R1 < R0 (IU); /* From < To */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 <= R3 (IU); /* (From+len) >= To */ + IF CC JUMP .Loverlap; +.Lno_overlap: + R3 = 11; + CC = R2 <= R3; + IF CC JUMP .Lbytes; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero.*/ + IF !CC JUMP .Lbytes; /* Jump if addrs not aligned.*/ + + I0 = P3; + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; + +#if !defined(__WORKAROUND_AVOID_DAG1) + LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; +#else + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: [P0++] = R1; +.Lquad_loop_e: R1 = [I0++]; +#endif + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 to updated ptr. */ + IF !CC JUMP .Lbytes; + P3 = I1; + RTS; + +.Lbytes: LSETUP (.Lbyte2_s, .Lbyte2_e) LC0=P2; +.Lbyte2_s: R1 = B[P3++](Z); +.Lbyte2_e: B[P0++] = R1; + +.Lfinished: P3 = I1; + RTS; + +.Loverlap: + P2 += -1; + P0 = P0 + P2; + P3 = P3 + P2; + R1 = B[P3--] (Z); + CC = P2 == 0; + IF CC JUMP .Lno_loop; +#if defined(__WORKAROUND_SPECULATIVE_LOADS) + NOP; + NOP; +#endif + LSETUP (.Lol_s, .Lol_e) LC0 = P2; +.Lol_s: B[P0--] = R1; +.Lol_e: R1 = B[P3--] (Z); +.Lno_loop: B[P0] = R1; + P3 = I1; + RTS; + +.size _memmove,.-_memmove + +libc_hidden_def (memmove) diff --git a/libc/string/bfin/memset.S b/libc/string/bfin/memset.S new file mode 100644 index 0000000..64012f7 --- /dev/null +++ b/libc/string/bfin/memset.S @@ -0,0 +1,90 @@ +/* memset.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memset(void *s, int c, size_t n); + * R0 = address (s) (leave unchanged to form result) + * R1 = filler byte (c) + * R2 = count (n) + * + * Note: Favours word aligned data. + */ + +.text + +.align 2 + +.weak _memset +ENTRY(_memset) + P0 = R0 ; /* P0 = address */ + P2 = R2 ; /* P2 = count */ + R3 = R0 + R2; /* end */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + R1 = R1.B (Z); /* R1 = fill char */ + R2 = 3; + R2 = R0 & R2; /* addr bottom two bits */ + CC = R2 == 0; /* AZ set if zero. */ + IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */ + +.Laligned: + P1 = P2 >> 2; /* count = n/4 */ + R2 = R1 << 8; /* create quad filler */ + R2.L = R2.L + R1.L(NS); + R2.H = R2.L + R1.H(NS); + P2 = R3; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: + [P0++] = R2; + + CC = P0 == P2; + IF !CC JUMP .Lbytes_left; + RTS; + +.Lbytes_left: + R2 = R3; /* end point */ + R3 = P0; /* current position */ + R2 = R2 - R3; /* bytes left */ + P2 = R2; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* Unusual */ + +.Lbytes: + LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2; +.Lbyte_loop: + B[P0++] = R1; + +.Lfinished: + RTS; + +.Lforce_align: + CC = BITTST (R0, 0); /* odd byte */ + R0 = 4; + R0 = R0 - R2; + P1 = R0; + R0 = P0; /* Recover return address */ + IF !CC JUMP .Lskip1; + B[P0++] = R1; +.Lskip1: + CC = R2 <= 2; /* 2 bytes */ + P2 -= P1; /* reduce count */ + IF !CC JUMP .Laligned; + B[P0++] = R1; + B[P0++] = R1; + JUMP .Laligned; + +.size _memset,.-_memset + +libc_hidden_def (memset) diff --git a/libc/string/bfin/strcmp.S b/libc/string/bfin/strcmp.S new file mode 100644 index 0000000..ef23aa9 --- /dev/null +++ b/libc/string/bfin/strcmp.S @@ -0,0 +1,122 @@ +/* strcmp.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* Fast strcmp() for Blackfin. + * When both strings are aligned, this processes four characters at + * a time. Uses a hw loop with "very big" count to loop "forever", + * until difference or a terminating zero is found. + * Once the end-case word has been identified, breaks out of the + * loop to check more carefully (same as the unaligned case). + */ + +.text + +.align 2 + +.weak _strcmp +ENTRY(_strcmp) + [--sp] = (R7:4); + p1 = r0; + p2 = r1; + + p0 = -1; /* (need for loop counter init) */ + + /* check if byte aligned */ + r0 = r0 | r1; /* check both pointers at same time */ + r0 <<= 30; /* dump all but last 2 bits */ + cc = az; /* are they zero? */ + if !cc jump .Lunaligned; /* no; use unaligned code. */ + /* fall-thru for aligned case.. */ + + /* note that r0 is zero from the previous... */ + /* p0 set to -1 */ + + LSETUP (.Lbeginloop, .Lendloop) lc0=p0; + /* pick up first words */ + r1 = [p1++]; + r2 = [p2++]; + /* make up mask: 0FF0FF */ + r7 = 0xFF; + r7.h = 0xFF; + /* loop : 9 cycles to check 4 characters */ + cc = r1 == r2; +.Lbeginloop: + if !cc jump .Lnotequal4; /* compare failure, exit loop */ + + /* starting with 44332211 */ + /* see if char 3 or char 1 is 0 */ + r3 = r1 & r7; /* form 00330011 */ + /* add to zero, and (r2 is free, reload) */ + r6 = r3 +|+ r0 || r2 = [p2++] || nop; + cc = az; /* true if either is zero */ + r3 = r1 ^ r3; /* form 44002200 (4321^0301 => 4020) */ + /* (trick, saves having another mask) */ + /* add to zero, and (r1 is free, reload) */ + r6 = r3 +|+ r0 || r1 = [p1++] || nop; + cc |= az; /* true if either is zero */ + if cc jump .Lzero4; /* leave if a zero somewhere */ +.Lendloop: + cc = r1 == r2; + + /* loop exits */ +.Lnotequal4: /* compare failure on 4-char compare */ + /* address pointers are one word ahead; */ + /* faster to use zero4 exit code */ + p1 += 4; + p2 += 4; + +.Lzero4: /* one of the bytes in word 1 is zero */ + /* but we've already fetched the next word; so */ + /* backup two to look at failing word again */ + p1 += -8; + p2 += -8; + + + + /* here when pointers are unaligned: checks one */ + /* character at a time. Also use at the end of */ + /* the word-check algorithm to figure out what happened */ +.Lunaligned: + /* R0 is non-zero from before. */ + /* p0 set to -1 */ + + r0 = 0 (Z); + r1 = B[p1++] (Z); + r2 = B[p2++] (Z); + LSETUP (.Lbeginloop1, .Lendloop1) lc0=p0; + +.Lbeginloop1: + cc = r1; /* first char must be non-zero */ + /* chars must be the same */ + r3 = r2 - r1 (NS) || r1 = B[p1++] (Z) || nop; + cc &= az; + r3 = r0 - r2; /* second char must be non-zero */ + cc &= an; + if !cc jump .Lexitloop1; +.Lendloop1: + r2 = B[p2++] (Z); + +.Lexitloop1: /* here means we found a zero or a difference. */ + /* we have r2(N), p2(N), r1(N+1), p1(N+2) */ + r1=B[p1+ -2] (Z); + r0 = r1 - r2; + (r7:4) = [sp++]; + rts; +.size _strcmp,.-_strcmp + +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +weak_alias (strcmp,strcoll) +libc_hidden_def (strcoll) +#endif diff --git a/libc/string/bzero.c b/libc/string/bzero.c new file mode 100644 index 0000000..7498f79 --- /dev/null +++ b/libc/string/bzero.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +/* Experimentally off - libc_hidden_proto(memset) */ + +void bzero(void *s, size_t n) +{ +#if 1 + (void)memset(s, 0, n); +#else + register unsigned char *p = s; +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *np = (const char *) n; +#else +#define np n +#endif + + while (np) { + *p++ = 0; + --np; + } +#endif +} +#undef np +#endif diff --git a/libc/string/cris/memcopy.h b/libc/string/cris/memcopy.h new file mode 100644 index 0000000..449c756 --- /dev/null +++ b/libc/string/cris/memcopy.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + Modified for use in uClibc (C) 2007 Axis Communications AB. + Minimal modifications: include path name and #undef of WORD_COPY_FWD/BWD + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "../generic/memcopy.h" + +/* We override the word-copying macros, partly because misalignment in one + pointer isn't cause for a special function, partly because we want to + get rid of all the static functions in generic/memcopy.c; these macros + are only used in memmove.c since we have arch-specific mempcpy, memcpy and + memset. */ + +#undef OP_T_THRES +#define OP_T_THRES OPSIZ + +#undef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + unsigned long enddst_bp = dst_bp + nbytes - (nbytes % OPSIZ); \ + nbytes_left = (nbytes % OPSIZ); \ + while (dst_bp < (unsigned long) enddst_bp) \ + { \ + op_t x = *(op_t *) src_bp; \ + src_bp += sizeof x; \ + *(op_t *) dst_bp = x; \ + dst_bp += sizeof x; \ + } \ + } while (0) + +#undef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + unsigned long enddst_bp = dst_bp - nbytes + (nbytes % OPSIZ); \ + nbytes_left = (nbytes % OPSIZ); \ + while (dst_bp > enddst_bp) \ + { \ + op_t x; \ + src_bp -= sizeof x; \ + x = *(op_t *) src_bp; \ + dst_bp -= sizeof x; \ + *(op_t *) dst_bp = x; \ + } \ + } while (0) diff --git a/libc/string/cris/memcpy.c b/libc/string/cris/memcpy.c new file mode 100644 index 0000000..94ece05 --- /dev/null +++ b/libc/string/cris/memcpy.c @@ -0,0 +1,243 @@ +/* A memcpy for CRIS. + Copyright (C) 1994-2008 Axis Communications. + 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. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS 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 AXIS + COMMUNICATIONS OR ITS 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. */ + +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +#include + +#ifdef __arch_v32 +/* For CRISv32, movem is very cheap. */ +#define MEMCPY_BY_BLOCK_THRESHOLD (44) +#else +/* Break even between movem and move16 is really at 38.7 * 2, but + modulo 44, so up to the next multiple of 44, we use ordinary code. */ +#define MEMCPY_BY_BLOCK_THRESHOLD (44 * 2) +#endif + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +/* Experimentally off - libc_hidden_proto(memcpy) */ +void * +memcpy(void *pdst, const void *psrc, size_t pn) +{ + /* Now we want the parameters put in special registers. + Make sure the compiler is able to make something useful of this. + As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). + + If gcc was allright, it really would need no temporaries, and no + stack space to save stuff on. */ + + register void *return_dst __asm__ ("r10") = pdst; + register unsigned char *dst __asm__ ("r13") = pdst; + register unsigned const char *src __asm__ ("r11") = psrc; + register int n __asm__ ("r12") = pn; + + /* When src is aligned but not dst, this makes a few extra needless + cycles. I believe it would take as many to check that the + re-alignment was unnecessary. */ + if (((unsigned long) dst & 3) != 0 + /* Don't align if we wouldn't copy more than a few bytes; so we + don't have to check further for overflows. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + n--; + *dst = *src; + src++; + dst++; + } + + if ((unsigned long) dst & 2) + { + n -= 2; + *(short *) dst = *(short *) src; + src += 2; + dst += 2; + } + } + + /* Decide which copying method to use. */ + if (n >= MEMCPY_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-movem sizes + suboptimal. */ + __asm__ __volatile__ + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%2,$r13-$r11-$r12 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ + \n\ + ;; Save the registers we'll use in the movem process \n\ + ;; on the stack. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ + \n\ + ;; Now we've got this: \n\ + ;; r11 - src \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop. \n\ + subq 44,r12 \n\ +0: \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" movem [r11+],r10 \n\ + subq 44,r12 \n\ + bge 0b \n\ + movem r10,[r13+] \n\ + \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 44,r12 \n\ + \n\ + ;; Restore registers from stack. \n\ + movem [sp+],r10" + + /* Outputs. */ + : "=r" (dst), "=r" (src), "=r" (n) + + /* Inputs. */ + : "0" (dst), "1" (src), "2" (n)); + } + + while (n >= 16) + { + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + + n -= 16; + } + + switch (n) + { + case 0: + break; + + case 1: + *dst = *src; + break; + + case 2: + *(short *) dst = *(short *) src; + break; + + case 3: + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 4: + *(long *) dst = *(long *) src; + break; + + case 5: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 6: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 7: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 8: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; + break; + + case 9: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 10: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 11: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 12: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; + break; + + case 13: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 14: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 15: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + } + + return return_dst; +} +libc_hidden_def(memcpy) diff --git a/libc/string/cris/memmove.c b/libc/string/cris/memmove.c new file mode 100644 index 0000000..fa495eb --- /dev/null +++ b/libc/string/cris/memmove.c @@ -0,0 +1,101 @@ +/* Taken from generic/memmove.c; trivially modified to work with + arch-specific memcopy.h for Cris. + + Copy memory to memory until the specified number of bytes + has been copied. Overlap is handled correctly. + Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" +#include "../generic/pagecopy.h" + +/* Experimentally off - libc_hidden_proto(memmove) */ +void *memmove (void *dest, const void *src, size_t len) +{ + unsigned long int dstp = (long int) dest; + unsigned long int srcp = (long int) src; + + /* This test makes the forward copying code be used whenever possible. + Reduces the working set. */ + if (dstp - srcp >= len) /* *Unsigned* compare! */ + { +#if 1 +#warning REMINDER: Cris arch-opt memmove assumes memcpy does forward copying! + memcpy(dest, src, len); +#else + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address + manipulation, as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); +#endif + } + else + { + /* Copy from the end to the beginning. */ + srcp += len; + dstp += len; + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= dstp % OPSIZ; + BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_BWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, len); + } + + return (dest); +} +libc_hidden_def(memmove) diff --git a/libc/string/cris/memset.c b/libc/string/cris/memset.c new file mode 100644 index 0000000..f4c5bb6 --- /dev/null +++ b/libc/string/cris/memset.c @@ -0,0 +1,263 @@ +/* A memset for CRIS. + Copyright (C) 1999-2008 Axis Communications. + 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. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS 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 AXIS + COMMUNICATIONS OR ITS 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. */ + +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +#include + +/* Note the multiple occurrence of the expression "12*4", including the + asm. It is hard to get it into the asm in a good way. Thus better to + expose the problem everywhere: no macro. */ + +/* Assuming one cycle per dword written or read (ok, not really true; the + world is not ideal), and one cycle per instruction, then 43+3*(n/48-1) + <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full + 48-byte block to set. */ + +#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48) + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +/* Experimentally off - libc_hidden_proto(memset) */ +void *memset(void *pdst, int c, unsigned int plen) +{ + /* Now we want the parameters in special registers. Make sure the + compiler does something usable with this. */ + + register char *return_dst __asm__ ("r10") = pdst; + register int n __asm__ ("r12") = plen; + register int lc __asm__ ("r11") = c; + + /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get + penalized here compared to the generic implementation. */ + + /* This is fragile performancewise at best. Check with newer GCC + releases, if they compile cascaded "x |= x << 8" to sane code. */ + __asm__("movu.b %0,r13 \n\ + lslq 8,r13 \n\ + move.b %0,r13 \n\ + move.d r13,%0 \n\ + lslq 16,r13 \n\ + or.d r13,%0" + : "=r" (lc) /* Inputs. */ + : "0" (lc) /* Outputs. */ + : "r13"); /* Trash. */ + + { + register char *dst __asm__ ("r13") = pdst; + + if (((unsigned long) pdst & 3) != 0 + /* Oops! n = 0 must be a valid call, regardless of alignment. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + *dst = (char) lc; + n--; + dst++; + } + + if ((unsigned long) dst & 2) + { + *(short *) dst = lc; + n -= 2; + dst += 2; + } + } + + /* Decide which setting method to use. */ + if (n >= MEMSET_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-block sizes + suboptimal. */ + __asm__ __volatile__ + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ + \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ + \n\ + move.d r11,r0 \n\ + move.d r11,r1 \n\ + move.d r11,r2 \n\ + move.d r11,r3 \n\ + move.d r11,r4 \n\ + move.d r11,r5 \n\ + move.d r11,r6 \n\ + move.d r11,r7 \n\ + move.d r11,r8 \n\ + move.d r11,r9 \n\ + move.d r11,r10 \n\ + \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 12*4,r12 \n\ +0: \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" subq 12*4,r12 \n\ + bge 0b \n\ + movem r11,[r13+] \n\ + \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 12*4,r12 \n\ + \n\ + ;; Restore registers from stack. \n\ + movem [sp+],r10" + + /* Outputs. */ + : "=r" (dst), "=r" (n) + + /* Inputs. */ + : "0" (dst), "1" (n), "r" (lc)); + } + + /* An ad-hoc unroll, used for 4*12-1..16 bytes. */ + while (n >= 16) + { + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + n -= 16; + } + + switch (n) + { + case 0: + break; + + case 1: + *dst = (char) lc; + break; + + case 2: + *(short *) dst = (short) lc; + break; + + case 3: + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 4: + *(long *) dst = lc; + break; + + case 5: + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 6: + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 7: + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 8: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; + break; + + case 9: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 10: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 11: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 12: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; + break; + + case 13: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 14: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 15: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + } + } + + return return_dst; +} +libc_hidden_def(memset) diff --git a/libc/string/cris/strcpy.c b/libc/string/cris/strcpy.c new file mode 100644 index 0000000..955a990 --- /dev/null +++ b/libc/string/cris/strcpy.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006-2007 Axis Communications AB + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* Experimentally off - libc_hidden_proto(strcpy) */ +char *strcpy(char *dest, const char *src) +{ + char *ret = dest; + unsigned long himagic = 0x80808080L; + unsigned long lomagic = 0x01010101L; + + while ((unsigned long)src & (sizeof src - 1)) + { + if (!(*dest++ = *src++)) + { + return ret; + } + } + + while (1) + { + unsigned long value = *(unsigned long*)src; + unsigned long magic; + + src += sizeof (unsigned long); + + if ((magic = (value - lomagic) & himagic)) + { + if (magic & ~value) + { + break; + } + } + + *(unsigned long*)dest = value; + dest += sizeof (unsigned long); + } + + src -= sizeof (unsigned long); + + while ((*dest++ = *src++)) + { + } + + return ret; +} +libc_hidden_def(strcpy) diff --git a/libc/string/cris/strncpy.c b/libc/string/cris/strncpy.c new file mode 100644 index 0000000..3f2775b --- /dev/null +++ b/libc/string/cris/strncpy.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006-2007 Axis Communications AB + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* Experimentally off - libc_hidden_proto(strncpy) */ +char *strncpy(char *dest, const char *src, size_t count) +{ + char *ret = dest; + unsigned long himagic = 0x80808080L; + unsigned long lomagic = 0x01010101L; + + while (count && (unsigned long)src & (sizeof src - 1)) + { + count--; + if (!(*dest++ = *src++)) + { + goto finalize; + } + } + + while (count >= sizeof (unsigned long)) + { + unsigned long value = *(unsigned long*)src; + unsigned long magic; + + if ((magic = (value - lomagic) & himagic)) + { + if (magic & ~value) + { + break; + } + } + + *(unsigned long*)dest = value; + dest += sizeof (unsigned long); + src += sizeof (unsigned long); + count -= sizeof (unsigned long); + } + + while (count) + { + count--; + if (!(*dest++ = *src++)) + break; + } + +finalize: + if (count) + { + memset(dest, '\0', count); + } + + return ret; +} +libc_hidden_def(strncpy) diff --git a/libc/string/dirname.c b/libc/string/dirname.c new file mode 100644 index 0000000..6265e56 --- /dev/null +++ b/libc/string/dirname.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +char *dirname(char *path) +{ + static const char null_or_empty_or_noslash[] = "."; + register char *s; + register char *last; + char *first; + + last = s = path; + + if (s != NULL) { + + LOOP: + while (*s && (*s != '/')) ++s; + first = s; + while (*s == '/') ++s; + if (*s) { + last = first; + goto LOOP; + } + + if (last == path) { + if (*last != '/') { + goto DOT; + } + if ((*++last == '/') && (last[1] == 0)) { + ++last; + } + } + *last = 0; + return path; + } + DOT: + return (char *) null_or_empty_or_noslash; +} diff --git a/libc/string/ffs.c b/libc/string/ffs.c new file mode 100644 index 0000000..241b745 --- /dev/null +++ b/libc/string/ffs.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* ffsl,ffsll */ + +#include "_string.h" + +/* Experimentally off - libc_hidden_proto(ffs) */ + +int ffs(int i) +{ +#if 1 + /* inlined binary search method */ + char n = 1; +#if UINT_MAX == 0xffffU + /* nothing to do here -- just trying to avoiding possible problems */ +#elif UINT_MAX == 0xffffffffU + if (!(i & 0xffff)) { + n += 16; + i >>= 16; + } +#else +#error ffs needs rewriting! +#endif + + if (!(i & 0xff)) { + n += 8; + i >>= 8; + } + if (!(i & 0x0f)) { + n += 4; + i >>= 4; + } + if (!(i & 0x03)) { + n += 2; + i >>= 2; + } + return (i) ? (n + ((i+1) & 0x01)) : 0; + +#else + /* linear search -- slow, but small */ + int n; + + for (n = 0 ; i ; ++n) { + i >>= 1; + } + + return n; +#endif +} +libc_hidden_def(ffs) diff --git a/libc/string/frv/Makefile b/libc/string/frv/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/frv/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/frv/memcpy.S b/libc/string/frv/memcpy.S new file mode 100644 index 0000000..ae84379 --- /dev/null +++ b/libc/string/frv/memcpy.S @@ -0,0 +1,127 @@ +/* memcpy.S: optimised assembly memcpy + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + + .text + .p2align 4 + +############################################################################### +# +# void *memcpy(void *to, const char *from, size_t count) +# +# - NOTE: must not use any stack. exception detection performs function return +# to caller's fixup routine, aborting the remainder of the copy +# +############################################################################### + .globl memcpy + .type memcpy,@function +memcpy: + or.p gr8,gr9,gr4 + orcc gr10,gr0,gr0,icc3 + or.p gr10,gr4,gr4 + beqlr icc3,#0 + + # optimise based on best common alignment for to, from & count + andicc.p gr4,#0x1f,gr0,icc0 + setlos #8,gr11 + andicc.p gr4,#0x0f,gr0,icc1 + beq icc0,#0,memcpy_32 + andicc.p gr4,#0x07,gr0,icc0 + beq icc1,#0,memcpy_16 + andicc.p gr4,#0x03,gr0,icc1 + beq icc0,#0,memcpy_8 + andicc.p gr4,#0x01,gr0,icc0 + beq icc1,#0,memcpy_4 + setlos.p #1,gr11 + beq icc0,#0,memcpy_2 + + # do byte by byte copy + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: ldubu.p @(gr9,gr11),gr4 + subicc gr10,#1,gr10,icc0 + stbu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do halfword by halfword copy +memcpy_2: + setlos #2,gr11 + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lduhu.p @(gr9,gr11),gr4 + subicc gr10,#2,gr10,icc0 + sthu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do word by word copy +memcpy_4: + setlos #4,gr11 + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: ldu.p @(gr9,gr11),gr4 + subicc gr10,#4,gr10,icc0 + stu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do double-word by double-word copy +memcpy_8: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu.p @(gr9,gr11),gr4 + subicc gr10,#8,gr10,icc0 + stdu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do quad-word by quad-word copy +memcpy_16: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu @(gr9,gr11),gr4 + lddu.p @(gr9,gr11),gr6 + subicc gr10,#16,gr10,icc0 + stdu gr4,@(gr3,gr11) + stdu.p gr6,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do eight-word by eight-word copy +memcpy_32: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu @(gr9,gr11),gr4 + lddu @(gr9,gr11),gr6 + lddu @(gr9,gr11),gr12 + lddu.p @(gr9,gr11),gr14 + subicc gr10,#32,gr10,icc0 + stdu gr4,@(gr3,gr11) + stdu gr6,@(gr3,gr11) + stdu gr12,@(gr3,gr11) + stdu.p gr14,@(gr3,gr11) + bne icc0,#2,0b + bralr + + .size memcpy, .-memcpy + +libc_hidden_def(memcpy) diff --git a/libc/string/frv/memset.S b/libc/string/frv/memset.S new file mode 100644 index 0000000..477597d --- /dev/null +++ b/libc/string/frv/memset.S @@ -0,0 +1,158 @@ +/* memset.S: optimised assembly memset + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + + .text + .p2align 4 + +############################################################################### +# +# void *memset(void *p, char ch, size_t count) +# +# - NOTE: must not use any stack. exception detection performs function return +# to caller's fixup routine, aborting the remainder of the set +# GR4, GR7, GR8, and GR11 must be managed +# +############################################################################### + .globl memset + .type memset,@function +memset: + orcc.p gr10,gr0,gr5,icc3 ; GR5 = count + andi gr9,#0xff,gr9 + or.p gr8,gr0,gr4 ; GR4 = address + beqlr icc3,#0 + + # conditionally write a byte to 2b-align the address + setlos.p #1,gr6 + andicc gr4,#1,gr0,icc0 + ckne icc0,cc7 + cstb.p gr9,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + # conditionally write a word to 4b-align the address + andicc.p gr4,#2,gr0,icc0 + subicc gr5,#2,gr0,icc1 + setlos.p #2,gr6 + ckne icc0,cc7 + slli.p gr9,#8,gr12 ; need to double up the pattern + cknc icc1,cc5 + or.p gr9,gr12,gr12 + andcr cc7,cc5,cc7 + + csth.p gr12,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + # conditionally write a dword to 8b-align the address + andicc.p gr4,#4,gr0,icc0 + subicc gr5,#4,gr0,icc1 + setlos.p #4,gr6 + ckne icc0,cc7 + slli.p gr12,#16,gr13 ; need to quadruple-up the pattern + cknc icc1,cc5 + or.p gr13,gr12,gr12 + andcr cc7,cc5,cc7 + + cst.p gr12,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + or.p gr12,gr12,gr13 ; need to octuple-up the pattern + + # the address is now 8b-aligned - loop around writing 64b chunks + setlos #8,gr7 + subi.p gr4,#8,gr4 ; store with update index does weird stuff + setlos #64,gr6 + + subicc gr5,#64,gr0,icc0 +0: cknc icc0,cc7 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + subicc gr5,#64,gr0,icc0 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + bnc icc0,#2,0b + + # now do 32-byte remnant + subicc.p gr5,#32,gr0,icc0 + setlos #32,gr6 + cknc icc0,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + setlos #16,gr6 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + subicc gr5,#16,gr0,icc0 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + + # now do 16-byte remnant + cknc icc0,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + + # now do 8-byte remnant + subicc gr5,#8,gr0,icc1 + cknc icc1,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + setlos.p #4,gr7 + beqlr icc3,#0 + + # now do 4-byte remnant + subicc gr5,#4,gr0,icc0 + addi.p gr4,#4,gr4 + cknc icc0,cc7 + cstu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + subicc.p gr5,#2,gr0,icc1 + beqlr icc3,#0 + + # now do 2-byte remnant + setlos #2,gr7 + addi.p gr4,#2,gr4 + cknc icc1,cc7 + csthu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + subicc.p gr5,#1,gr0,icc0 + beqlr icc3,#0 + + # now do 1-byte remnant + setlos #0,gr7 + addi.p gr4,#2,gr4 + cknc icc0,cc7 + cstb.p gr12,@(gr4,gr0) ,cc7,#1 + bralr + .size memset, .-memset + +/* Experimentally off - libc_hidden_proto(memset) */ diff --git a/libc/string/generic/Makefile b/libc/string/generic/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/generic/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/generic/_memcpy_fwd.c b/libc/string/generic/_memcpy_fwd.c new file mode 100644 index 0000000..470165a --- /dev/null +++ b/libc/string/generic/_memcpy_fwd.c @@ -0,0 +1,185 @@ +/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to + block beginning at DSTP with LEN `op_t' words (not LEN bytes!). + Both SRCP and DSTP should be aligned for memory operations on `op_t's. */ + +static void _wordcopy_fwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) + { + case 2: + a0 = ((op_t *) srcp)[0]; + srcp -= 6 * OPSIZ; + dstp -= 7 * OPSIZ; + len += 6; + goto do1; + case 3: + a1 = ((op_t *) srcp)[0]; + srcp -= 5 * OPSIZ; + dstp -= 6 * OPSIZ; + len += 5; + goto do2; + case 4: + a0 = ((op_t *) srcp)[0]; + srcp -= 4 * OPSIZ; + dstp -= 5 * OPSIZ; + len += 4; + goto do3; + case 5: + a1 = ((op_t *) srcp)[0]; + srcp -= 3 * OPSIZ; + dstp -= 4 * OPSIZ; + len += 3; + goto do4; + case 6: + a0 = ((op_t *) srcp)[0]; + srcp -= 2 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do5; + case 7: + a1 = ((op_t *) srcp)[0]; + srcp -= 1 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do6; + + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + a0 = ((op_t *) srcp)[0]; + srcp -= 0 * OPSIZ; + dstp -= 1 * OPSIZ; + goto do7; + case 1: + a1 = ((op_t *) srcp)[0]; + srcp -=-1 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do + { + do8: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a1; + do7: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a0; + do6: + a0 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a1; + do5: + a1 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a0; + do4: + a0 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a1; + do3: + a1 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a0; + do2: + a0 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a1; + do1: + a1 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a0; + + srcp += 8 * OPSIZ; + dstp += 8 * OPSIZ; + len -= 8; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[0] = a1; +} + +/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to + block beginning at DSTP with LEN `op_t' words (not LEN bytes!). + DSTP should be aligned for memory operations on `op_t's, but SRCP must + *not* be aligned. */ + +static void _wordcopy_fwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* Calculate how to shift a word read at the memory operation + aligned srcp to make it aligned for copy. */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* Make SRCP aligned by rounding it down to the beginning of the `op_t' + it points in the middle of. */ + srcp &= -OPSIZ; + + switch (len % 4) + { + case 2: + a1 = ((op_t *) srcp)[0]; + a2 = ((op_t *) srcp)[1]; + srcp -= 1 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp)[0]; + a1 = ((op_t *) srcp)[1]; + srcp -= 0 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + a3 = ((op_t *) srcp)[0]; + a0 = ((op_t *) srcp)[1]; + srcp -=-1 * OPSIZ; + dstp -= 1 * OPSIZ; + len += 0; + goto do3; + case 1: + a2 = ((op_t *) srcp)[0]; + a3 = ((op_t *) srcp)[1]; + srcp -=-2 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do + { + do4: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); + do3: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2); + do2: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2); + do1: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2); + + srcp += 4 * OPSIZ; + dstp += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +} diff --git a/libc/string/generic/bp-checks.h b/libc/string/generic/bp-checks.h new file mode 100644 index 0000000..08c70aa --- /dev/null +++ b/libc/string/generic/bp-checks.h @@ -0,0 +1,129 @@ +/* Bounded-pointer checking macros for C. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Greg McGary + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _bp_checks_h_ +#define _bp_checks_h_ 1 + +#if __BOUNDED_POINTERS__ + +# define BOUNDS_VIOLATED (__builtin_trap (), 0) + +/* Verify that pointer's value >= low. Return pointer value. */ +# define CHECK_BOUNDS_LOW(ARG) \ + (((__ptrvalue (ARG) < __ptrlow (ARG)) && BOUNDS_VIOLATED), \ + __ptrvalue (ARG)) + +/* Verify that pointer's value < high. Return pointer value. */ +# define CHECK_BOUNDS_HIGH(ARG) \ + (((__ptrvalue (ARG) > __ptrhigh (ARG)) && BOUNDS_VIOLATED), \ + __ptrvalue (ARG)) + +# define _CHECK_N(ARG, N, COND) \ + (((COND) \ + && (__ptrvalue (ARG) < __ptrlow (ARG) \ + || __ptrvalue (ARG) + (N) > __ptrhigh (ARG)) \ + && BOUNDS_VIOLATED), \ + __ptrvalue (ARG)) + +extern void *__unbounded __ubp_memchr (const void *__unbounded, int, unsigned); + +# define _CHECK_STRING(ARG, COND) \ + (((COND) \ + && (__ptrvalue (ARG) < __ptrlow (ARG) \ + || !__ubp_memchr (__ptrvalue (ARG), '\0', \ + (__ptrhigh (ARG) - __ptrvalue (ARG)))) \ + && BOUNDS_VIOLATED), \ + __ptrvalue (ARG)) + +/* Check bounds of a pointer seated to an array of N objects. */ +# define CHECK_N(ARG, N) _CHECK_N ((ARG), (N), 1) +/* Same as CHECK_N, but tolerate ARG == NULL. */ +# define CHECK_N_NULL_OK(ARG, N) _CHECK_N ((ARG), (N), __ptrvalue (ARG)) + +/* Check bounds of a pointer seated to a single object. */ +# define CHECK_1(ARG) CHECK_N ((ARG), 1) +/* Same as CHECK_1, but tolerate ARG == NULL. */ +# define CHECK_1_NULL_OK(ARG) CHECK_N_NULL_OK ((ARG), 1) + +/* Check for NUL-terminator within string's bounds. */ +# define CHECK_STRING(ARG) _CHECK_STRING ((ARG), 1) +/* Same as CHECK_STRING, but tolerate ARG == NULL. */ +# define CHECK_STRING_NULL_OK(ARG) _CHECK_STRING ((ARG), __ptrvalue (ARG)) + +/* Check bounds of signal syscall args with type sigset_t. */ +# define CHECK_SIGSET(SET) CHECK_N ((SET), _NSIG / (8 * sizeof *(SET))) +/* Same as CHECK_SIGSET, but tolerate SET == NULL. */ +# define CHECK_SIGSET_NULL_OK(SET) CHECK_N_NULL_OK ((SET), _NSIG / (8 * sizeof *(SET))) + +# if defined (_IOC_SIZESHIFT) && defined (_IOC_SIZEBITS) +/* Extract the size of the ioctl data and check its bounds. */ +# define CHECK_IOCTL(ARG, CMD) \ + CHECK_N ((const char *) (ARG), \ + (((CMD) >> _IOC_SIZESHIFT) & ((1 << _IOC_SIZEBITS) - 1))) +# else +/* We don't know the size of the ioctl data, so the best we can do + is check that the first byte is within bounds. */ +# define CHECK_IOCTL(ARG, CMD) CHECK_1 ((const char *) ARG) +# endif + +/* Check bounds of `struct flock *' for the locking fcntl commands. */ +# define CHECK_FCNTL(ARG, CMD) \ + (((CMD) == F_GETLK || (CMD) == F_SETLK || (CMD) == F_SETLKW) \ + ? CHECK_1 ((struct flock *) ARG) : (unsigned long) (ARG)) + +/* Check bounds of an array of mincore residency-status flags that + cover a region of NBYTES. Such a vector occupies one byte per page + of memory. */ +# define CHECK_N_PAGES(ARG, NBYTES) \ + ({ int _page_size_ = __sysconf (_SC_PAGE_SIZE); \ + CHECK_N ((const char *) (ARG), \ + ((NBYTES) + _page_size_ - 1) / _page_size_); }) + +/* Return a bounded pointer with value PTR that satisfies CHECK_N (PTR, N). */ +# define BOUNDED_N(PTR, N) \ + ({ __typeof (PTR) __bounded _p_; \ + __ptrvalue _p_ = __ptrlow _p_ = __ptrvalue (PTR); \ + __ptrhigh _p_ = __ptrvalue _p_ + (N); \ + _p_; }) + +#else /* !__BOUNDED_POINTERS__ */ + +/* Do nothing if not compiling with -fbounded-pointers. */ + +# define BOUNDS_VIOLATED +# define CHECK_BOUNDS_LOW(ARG) (ARG) +# define CHECK_BOUNDS_HIGH(ARG) (ARG) +# define CHECK_1(ARG) (ARG) +# define CHECK_1_NULL_OK(ARG) (ARG) +# define CHECK_N(ARG, N) (ARG) +# define CHECK_N_NULL_OK(ARG, N) (ARG) +# define CHECK_STRING(ARG) (ARG) +# define CHECK_SIGSET(SET) (SET) +# define CHECK_SIGSET_NULL_OK(SET) (SET) +# define CHECK_IOCTL(ARG, CMD) (ARG) +# define CHECK_FCNTL(ARG, CMD) (ARG) +# define CHECK_N_PAGES(ARG, NBYTES) (ARG) +# define BOUNDED_N(PTR, N) (PTR) + +#endif /* !__BOUNDED_POINTERS__ */ + +#define BOUNDED_1(PTR) BOUNDED_N (PTR, 1) + +#endif /* _bp_checks_h_ */ diff --git a/libc/string/generic/memchr.c b/libc/string/generic/memchr.c new file mode 100644 index 0000000..3c7c997 --- /dev/null +++ b/libc/string/generic/memchr.c @@ -0,0 +1,177 @@ +/* Copyright (C) 1991,93,96,97,99,2000,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memchr) */ +libc_hidden_proto(abort) + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Search no more than N bytes of S for C. */ +void *memchr (const void * s, int c_in, size_t n) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + n > 0 && ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + --n, ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (n >= sizeof (longword)) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++ ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (cp[0] == c) + return (void *) cp; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[3] == c) + return (void *) &cp[3]; +#if LONG_MAX > 2147483647 + if (cp[4] == c) + return (void *) &cp[4]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[7] == c) + return (void *) &cp[7]; +#endif + } + + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + while (n-- > 0) + { + if (*char_ptr == c) + return (void *) char_ptr; + else + ++char_ptr; + } + + return 0; +} +libc_hidden_weak(memchr) diff --git a/libc/string/generic/memcmp.c b/libc/string/generic/memcmp.c new file mode 100644 index 0000000..fc63a2e --- /dev/null +++ b/libc/string/generic/memcmp.c @@ -0,0 +1,329 @@ +/* Copyright (C) 1991,1993,1995,1997,1998,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(memcmp) */ + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN +#endif + +#ifdef WORDS_BIGENDIAN +# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) +#else +# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) +#endif + +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE! */ + +/* The strategy of this memcmp is: + + 1. Compare bytes until one of the block pointers is aligned. + + 2. Compare using memcmp_common_alignment or + memcmp_not_common_alignment, regarding the alignment of the other + block after the initial byte operations. The maximum number of + full words (of type op_t) are compared in this way. + + 3. Compare the few remaining bytes. */ + +#ifndef WORDS_BIGENDIAN +/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. + A and B are known to be different. + This is needed only on little-endian machines. */ + +static int memcmp_bytes __P((op_t, op_t)); + +# ifdef __GNUC__ +__inline +# endif +static int +memcmp_bytes (op_t a, op_t b) +{ + long int srcp1 = (long int) &a; + long int srcp2 = (long int) &b; + op_t a0, b0; + + do + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + } + while (a0 == b0); + return a0 - b0; +} +#endif + +static int memcmp_common_alignment __P((long, long, size_t)); + +/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' + objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for + memory operations on `op_t's. */ +static int +memcmp_common_alignment (long int srcp1, long int srcp2, size_t len) +{ + op_t a0, a1; + op_t b0, b1; + + switch (len % 4) + { + default: /* Avoid warning about uninitialized local variables. */ + case 2: + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + srcp1 -= 2 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 -= OPSIZ; + srcp2 -= OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + goto do3; + case 1: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 += OPSIZ; + srcp2 += OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + do2: + a0 = ((op_t *) srcp1)[2]; + b0 = ((op_t *) srcp2)[2]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do1: + a1 = ((op_t *) srcp1)[3]; + b1 = ((op_t *) srcp2)[3]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + return 0; +} + +static int memcmp_not_common_alignment __P((long, long, size_t)); + +/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN + `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory + operations on `op_t', but SRCP1 *should be unaligned*. */ +static int +memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len) +{ + op_t a0, a1, a2, a3; + op_t b0, b1, b2, b3; + op_t x; + int shl, shr; + + /* Calculate how to shift a word read at the memory operation + aligned srcp1 to make it aligned for comparison. */ + + shl = 8 * (srcp1 % OPSIZ); + shr = 8 * OPSIZ - shl; + + /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t' + it points in the middle of. */ + srcp1 &= -OPSIZ; + + switch (len % 4) + { + default: /* Avoid warning about uninitialized local variables. */ + case 2: + a1 = ((op_t *) srcp1)[0]; + a2 = ((op_t *) srcp1)[1]; + b2 = ((op_t *) srcp2)[0]; + srcp1 -= 1 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp1)[0]; + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[0]; + srcp2 -= 1 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a3 = ((op_t *) srcp1)[0]; + a0 = ((op_t *) srcp1)[1]; + b0 = ((op_t *) srcp2)[0]; + srcp1 += 1 * OPSIZ; + goto do3; + case 1: + a2 = ((op_t *) srcp1)[0]; + a3 = ((op_t *) srcp1)[1]; + b3 = ((op_t *) srcp2)[0]; + srcp1 += 2 * OPSIZ; + srcp2 += 1 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + x = MERGE(a3, shl, a0, shr); + if (x != b0) + return CMP_LT_OR_GT (x, b0); + + do2: + a2 = ((op_t *) srcp1)[2]; + b2 = ((op_t *) srcp2)[2]; + x = MERGE(a0, shl, a1, shr); + if (x != b1) + return CMP_LT_OR_GT (x, b1); + + do1: + a3 = ((op_t *) srcp1)[3]; + b3 = ((op_t *) srcp2)[3]; + x = MERGE(a1, shl, a2, shr); + if (x != b2) + return CMP_LT_OR_GT (x, b2); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + return 0; +} + +int +memcmp (const __ptr_t s1, const __ptr_t s2, size_t len) +{ + op_t a0; + op_t b0; + long int srcp1 = (long int) s1; + long int srcp2 = (long int) s2; + op_t res; + + if (len >= OP_T_THRES) + { + /* There are at least some bytes to compare. No need to test + for LEN == 0 in this alignment loop. */ + while (srcp2 % OPSIZ != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + /* SRCP2 is now aligned for memory operations on `op_t'. + SRCP1 alignment determines if we can do a simple, + aligned compare or need to shuffle bits. */ + + if (srcp1 % OPSIZ == 0) + res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ); + else + res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ); + if (res != 0) + return res; + + /* Number of bytes remaining in the interval [0..OPSIZ-1]. */ + srcp1 += len & -OPSIZ; + srcp2 += len & -OPSIZ; + len %= OPSIZ; + } + + /* There are just a few bytes to compare. Use byte memory operations. */ + while (len != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + return 0; +} +libc_hidden_weak(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/libc/string/generic/memcopy.h b/libc/string/generic/memcopy.h new file mode 100644 index 0000000..df1ba9a --- /dev/null +++ b/libc/string/generic/memcopy.h @@ -0,0 +1,150 @@ +/* memcopy.h -- definitions for memory copy functions. Generic C version. + Copyright (C) 1991, 1992, 1993, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The strategy of the memory functions is: + + 1. Copy bytes until the destination pointer is aligned. + + 2. Copy words in unrolled loops. If the source and destination + are not aligned in the same way, use word memory operations, + but shift and merge two read words before writing. + + 3. Copy the few remaining bytes. + + This is fast on processors that have at least 10 registers for + allocation by GCC, and that can access memory at reg+const in one + instruction. + + I made an "exhaustive" test of this memmove when I wrote it, + exhaustive in the sense that I tried all alignment and length + combinations, with and without overlap. */ + +#include +#include + +/* The macros defined in this file are: + + BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + + BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + + WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy) + + WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy) + + MERGE(old_word, sh_1, new_word, sh_2) + [I fail to understand. I feel stupid. --roland] +*/ + +/* Type to use for aligned memory operations. + This should normally be the biggest type supported by a single load + and store. */ +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +/* Type to use for unaligned operations. */ +typedef unsigned char byte; + +/* Optimal type for storing bytes in registers. */ +#define reg_char char + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) +#endif +#if __BYTE_ORDER == __BIG_ENDIAN +#define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) +#endif + +/* Copy exactly NBYTES bytes from SRC_BP to DST_BP, + without any assumptions about alignment of the pointers. */ +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ + do \ + { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) \ + { \ + byte __x = ((byte *) src_bp)[0]; \ + src_bp += 1; \ + __nbytes -= 1; \ + ((byte *) dst_bp)[0] = __x; \ + dst_bp += 1; \ + } \ + } while (0) + +/* Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + beginning at the bytes right before the pointers and continuing towards + smaller addresses. Don't assume anything about alignment of the + pointers. */ +#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) \ + do \ + { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) \ + { \ + byte __x; \ + src_ep -= 1; \ + __x = ((byte *) src_ep)[0]; \ + dst_ep -= 1; \ + __nbytes -= 1; \ + ((byte *) dst_ep)[0] = __x; \ + } \ + } while (0) + +/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with + the assumption that DST_BP is aligned on an OPSIZ multiple. If + not all bytes could be easily copied, store remaining number of bytes + in NBYTES_LEFT, otherwise store 0. */ +/* extern void _wordcopy_fwd_aligned __P ((long int, long int, size_t)); */ +/* extern void _wordcopy_fwd_dest_aligned __P ((long int, long int, size_t)); */ +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + if (src_bp % OPSIZ == 0) \ + _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + else \ + _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + src_bp += (nbytes) & -OPSIZ; \ + dst_bp += (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ + } while (0) + +/* Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + beginning at the words (of type op_t) right before the pointers and + continuing towards smaller addresses. May take advantage of that + DST_END_PTR is aligned on an OPSIZ multiple. If not all bytes could be + easily copied, store remaining number of bytes in NBYTES_REMAINING, + otherwise store 0. */ +/* extern void _wordcopy_bwd_aligned __P ((long int, long int, size_t)); */ +/* extern void _wordcopy_bwd_dest_aligned __P ((long int, long int, size_t)); */ +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ + do \ + { \ + if (src_ep % OPSIZ == 0) \ + _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + else \ + _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + src_ep -= (nbytes) & -OPSIZ; \ + dst_ep -= (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ + } while (0) + + +/* Threshold value for when to enter the unrolled loops. */ +#define OP_T_THRES 16 diff --git a/libc/string/generic/memcpy.c b/libc/string/generic/memcpy.c new file mode 100644 index 0000000..a19e0c3 --- /dev/null +++ b/libc/string/generic/memcpy.c @@ -0,0 +1,62 @@ +/* Copy memory to memory until the specified number of bytes + has been copied. Overlap is NOT handled correctly. + Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" +#include "pagecopy.h" +#include "_memcpy_fwd.c" + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +void *memcpy (void *dstpp, const void *srcpp, size_t len) +{ + unsigned long int dstp = (long int) dstpp; + unsigned long int srcp = (long int) srcpp; + + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address manipulation, + as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known alignment of + DSTP. Number of bytes remaining is put in the third argument, + i.e. in LEN. This number may vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); + + return dstpp; +} +libc_hidden_weak(memcpy) diff --git a/libc/string/generic/memmem.c b/libc/string/generic/memmem.c new file mode 100644 index 0000000..c75bb24 --- /dev/null +++ b/libc/string/generic/memmem.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(memmem) */ +/* Experimentally off - libc_hidden_proto(memcmp) */ + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +void *memmem (const void *haystack, size_t haystack_len, + const void *needle, size_t needle_len) +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} +libc_hidden_def(memmem) +#endif diff --git a/libc/string/generic/memmove.c b/libc/string/generic/memmove.c new file mode 100644 index 0000000..7f945b1 --- /dev/null +++ b/libc/string/generic/memmove.c @@ -0,0 +1,291 @@ +/* Copy memory to memory until the specified number of bytes + has been copied. Overlap is handled correctly. + Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" +#include "pagecopy.h" + +#ifdef __ARCH_HAS_BWD_MEMCPY__ +/* generic-opt memmove assumes memcpy does forward copying! */ +#include "_memcpy_fwd.c" +#endif + +/* Experimentally off - libc_hidden_proto(memmove) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ + +static void _wordcopy_bwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0 = 0; + op_t a1 = 0; + + switch (len % 8) + { + case 2: + srcp -= 2 * OPSIZ; + dstp -= 1 * OPSIZ; + a0 = ((op_t *) srcp)[1]; + len += 6; + goto do1; + case 3: + srcp -= 3 * OPSIZ; + dstp -= 2 * OPSIZ; + a1 = ((op_t *) srcp)[2]; + len += 5; + goto do2; + case 4: + srcp -= 4 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[3]; + len += 4; + goto do3; + case 5: + srcp -= 5 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[4]; + len += 3; + goto do4; + case 6: + srcp -= 6 * OPSIZ; + dstp -= 5 * OPSIZ; + a0 = ((op_t *) srcp)[5]; + len += 2; + goto do5; + case 7: + srcp -= 7 * OPSIZ; + dstp -= 6 * OPSIZ; + a1 = ((op_t *) srcp)[6]; + len += 1; + goto do6; + + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + srcp -= 8 * OPSIZ; + dstp -= 7 * OPSIZ; + a0 = ((op_t *) srcp)[7]; + goto do7; + case 1: + srcp -= 9 * OPSIZ; + dstp -= 8 * OPSIZ; + a1 = ((op_t *) srcp)[8]; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do + { + do8: + a0 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a1; + do7: + a1 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a0; + do6: + a0 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a1; + do5: + a1 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a0; + do4: + a0 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a1; + do3: + a1 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a0; + do2: + a0 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a1; + do1: + a1 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a0; + + srcp -= 8 * OPSIZ; + dstp -= 8 * OPSIZ; + len -= 8; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[7] = a1; +} + +/* _wordcopy_bwd_dest_aligned -- Copy block finishing right + before SRCP to block finishing right before DSTP with LEN `op_t' + words (not LEN bytes!). DSTP should be aligned for memory + operations on `op_t', but SRCP must *not* be aligned. */ + +static void _wordcopy_bwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0 = 0; + op_t a1 = 0; + op_t a2 = 0; + op_t a3 = 0; + int sh_1, sh_2; + + /* Calculate how to shift a word read at the memory operation + aligned srcp to make it aligned for copy. */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* Make srcp aligned by rounding it down to the beginning of the op_t + it points in the middle of. */ + srcp &= -OPSIZ; + srcp += OPSIZ; + + switch (len % 4) + { + case 2: + srcp -= 3 * OPSIZ; + dstp -= 1 * OPSIZ; + a2 = ((op_t *) srcp)[2]; + a1 = ((op_t *) srcp)[1]; + len += 2; + goto do1; + case 3: + srcp -= 4 * OPSIZ; + dstp -= 2 * OPSIZ; + a3 = ((op_t *) srcp)[3]; + a2 = ((op_t *) srcp)[2]; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + srcp -= 5 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[4]; + a3 = ((op_t *) srcp)[3]; + goto do3; + case 1: + srcp -= 6 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[5]; + a0 = ((op_t *) srcp)[4]; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do + { + do4: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); + do3: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2); + do2: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2); + do1: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2); + + srcp -= 4 * OPSIZ; + dstp -= 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +} + +void *memmove (void *dest, const void *src, size_t len) +{ + unsigned long int dstp = (long int) dest; + unsigned long int srcp = (long int) src; + + /* This test makes the forward copying code be used whenever possible. + Reduces the working set. */ + if (dstp - srcp >= len) /* *Unsigned* compare! */ + { +#ifndef __ARCH_HAS_BWD_MEMCPY__ + /* Backward memcpy implementation cannot be used */ + memcpy(dest, src, len); +#else + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address + manipulation, as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); +#endif + } + else + { + /* Copy from the end to the beginning. */ + srcp += len; + dstp += len; + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= dstp % OPSIZ; + BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_BWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, len); + } + + return (dest); +} +libc_hidden_weak(memmove) diff --git a/libc/string/generic/mempcpy.c b/libc/string/generic/mempcpy.c new file mode 100644 index 0000000..8d73564 --- /dev/null +++ b/libc/string/generic/mempcpy.c @@ -0,0 +1,20 @@ +/* Copy memory to memory until the specified number of bytes + has been copied, return pointer to following byte. + Overlap is NOT handled correctly. +*/ + +/* Ditch the glibc version and just wrap memcpy. */ + +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(mempcpy) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ + +void *mempcpy (void *dstpp, const void *srcpp, size_t len) +{ + memcpy(dstpp, srcpp, len); + return (void *)(((char *)dstpp) + len); +} +libc_hidden_weak(mempcpy) +#endif diff --git a/libc/string/generic/memrchr.c b/libc/string/generic/memrchr.c new file mode 100644 index 0000000..9ab805c --- /dev/null +++ b/libc/string/generic/memrchr.c @@ -0,0 +1,178 @@ +/* memrchr -- find the last occurrence of a byte in a memory block + Copyright (C) 1991, 93, 96, 97, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(memrchr) */ +libc_hidden_proto(abort) + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Search no more than N bytes of S for C. */ +void *memrchr (const void * s, int c_in, size_t n) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the last few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s + n; + n > 0 && ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + --n) + if (*--char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (const unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (n >= sizeof (longword)) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *--longword_ptr ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) longword_ptr; + +#if LONG_MAX > 2147483647 + if (cp[7] == c) + return (void *) &cp[7]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[4] == c) + return (void *) &cp[4]; +#endif + if (cp[3] == c) + return (void *) &cp[3]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[0] == c) + return (void *) cp; + } + + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + while (n-- > 0) + { + if (*--char_ptr == c) + return (void *) char_ptr; + } + + return 0; +} +libc_hidden_def(memrchr) +#endif diff --git a/libc/string/generic/memset.c b/libc/string/generic/memset.c new file mode 100644 index 0000000..62cc36f --- /dev/null +++ b/libc/string/generic/memset.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(memset) */ +void *memset (void *dstpp, int c, size_t len) +{ + long int dstp = (long int) dstpp; + + if (len >= 8) + { + size_t xlen; + op_t cccc; + + cccc = (unsigned char) c; + cccc |= cccc << 8; + cccc |= cccc << 16; + if (OPSIZ > 4) + /* Do the shift in two steps to avoid warning if long has 32 bits. */ + cccc |= (cccc << 16) << 16; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + while (dstp % OPSIZ != 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ + xlen = len / (OPSIZ * 8); + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + ((op_t *) dstp)[1] = cccc; + ((op_t *) dstp)[2] = cccc; + ((op_t *) dstp)[3] = cccc; + ((op_t *) dstp)[4] = cccc; + ((op_t *) dstp)[5] = cccc; + ((op_t *) dstp)[6] = cccc; + ((op_t *) dstp)[7] = cccc; + dstp += 8 * OPSIZ; + xlen -= 1; + } + len %= OPSIZ * 8; + + /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ + xlen = len / OPSIZ; + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + dstp += OPSIZ; + xlen -= 1; + } + len %= OPSIZ; + } + + /* Write the last few bytes. */ + while (len > 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + return dstpp; +} +libc_hidden_weak(memset) diff --git a/libc/string/generic/pagecopy.h b/libc/string/generic/pagecopy.h new file mode 100644 index 0000000..b00db49 --- /dev/null +++ b/libc/string/generic/pagecopy.h @@ -0,0 +1,75 @@ +/* Macros for copying by pages; used in memcpy, memmove. Generic macros. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file defines the macro: + + PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nbytes) + + which is invoked like WORD_COPY_FWD et al. The pointers should be at + least word aligned. This will check if virtual copying by pages can and + should be done and do it if so. + + System-specific pagecopy.h files should define these macros and then + #include this file: + + PAGE_COPY_THRESHOLD + -- Minimum size for which virtual copying by pages is worthwhile. + + PAGE_SIZE + -- Size of a page. + + PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes) + -- Macro to perform the virtual copy operation. + The pointers will be aligned to PAGE_SIZE bytes. +*/ + + +#if defined PAGE_COPY_THRESHOLD && PAGE_COPY_THRESHOLD + +#include + +#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) \ + do \ + { \ + if ((nbytes) >= PAGE_COPY_THRESHOLD && \ + PAGE_OFFSET ((dstp) - (srcp)) == 0) \ + { \ + /* The amount to copy is past the threshold for copying \ + pages virtually with kernel VM operations, and the \ + source and destination addresses have the same alignment. */ \ + size_t nbytes_before = PAGE_OFFSET (-(dstp)); \ + if (nbytes_before != 0) \ + { \ + /* First copy the words before the first page boundary. */ \ + WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before); \ + assert (nbytes_left == 0); \ + nbytes -= nbytes_before; \ + } \ + PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes); \ + } \ + } while (0) + +/* The page size is always a power of two, so we can avoid modulo division. */ +#define PAGE_OFFSET(n) ((n) & (PAGE_SIZE - 1)) + +#else + +#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) /* nada */ + +#endif diff --git a/libc/string/generic/rawmemchr.c b/libc/string/generic/rawmemchr.c new file mode 100644 index 0000000..f8b97a6 --- /dev/null +++ b/libc/string/generic/rawmemchr.c @@ -0,0 +1,164 @@ +/* Copyright (C) 1991,93,96,97,99,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(rawmemchr) */ +libc_hidden_proto(abort) + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Find the first occurrence of C in S. */ +void *rawmemchr (const void * s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (1) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++ ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (cp[0] == c) + return (void *) cp; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[3] == c) + return (void *) &cp[3]; +#if LONG_MAX > 2147483647 + if (cp[4] == c) + return (void *) &cp[4]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[7] == c) + return (void *) &cp[7]; +#endif + } + } +} +libc_hidden_def(rawmemchr) +#endif diff --git a/libc/string/generic/strcat.c b/libc/string/generic/strcat.c new file mode 100644 index 0000000..e004940 --- /dev/null +++ b/libc/string/generic/strcat.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Append SRC on the end of DEST. */ +char *strcat (char *dest, const char *src) +{ + char *s1 = dest; + const char *s2 = src; + reg_char c; + + /* Find the end of the string. */ + do + c = *s1++; + while (c != '\0'); + + /* Make S1 point before the next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + + do + { + c = *s2++; + *++s1 = c; + } + while (c != '\0'); + + return dest; +} +libc_hidden_def(strcat) diff --git a/libc/string/generic/strchr.c b/libc/string/generic/strchr.c new file mode 100644 index 0000000..66aed1e --- /dev/null +++ b/libc/string/generic/strchr.c @@ -0,0 +1,187 @@ +/* Copyright (C) 1991,93,94,95,96,97,99,2000,03 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Experimentally off - libc_hidden_proto(strchr) */ +libc_hidden_proto(abort) + +#include "memcopy.h" + +/* Find the first occurrence of C in S. */ +char *strchr (const char *s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + else if (*char_ptr == '\0') + return NULL; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + switch (sizeof (longword)) + { + case 4: magic_bits = 0x7efefeffL; break; + case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; + default: + abort (); + } + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; + if (sizeof (longword) > 4) + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + charmask |= (charmask << 16) << 16; + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C as well as zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0 || + + /* That caught zeroes. Now test for C. */ + ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) + & ~magic_bits) != 0) + { + /* Which of the bytes was C or zero? + If none of them were, it was a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (*cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (sizeof (longword) > 4) + { + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + } + } + } + + return NULL; +} +libc_hidden_weak(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strchr,index) +#endif diff --git a/libc/string/generic/strchrnul.c b/libc/string/generic/strchrnul.c new file mode 100644 index 0000000..72cab28 --- /dev/null +++ b/libc/string/generic/strchrnul.c @@ -0,0 +1,169 @@ +/* Copyright (C) 1991,93,94,95,96,97,99,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(strchrnul) */ +libc_hidden_proto(abort) + +#include "memcopy.h" + +/* Find the first occurrence of C in S or the final NUL byte. */ +char *strchrnul (const char *s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c || *char_ptr == '\0') + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + switch (sizeof (longword)) + { + case 4: magic_bits = 0x7efefeffL; break; + case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; + default: + abort (); + } + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; + if (sizeof (longword) > 4) + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + charmask |= (charmask << 16) << 16; + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C as well as zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0 || + + /* That caught zeroes. Now test for C. */ + ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) + & ~magic_bits) != 0) + { + /* Which of the bytes was C or zero? + If none of them were, it was a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (*cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (sizeof (longword) > 4) + { + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + } + } + } + + /* This should never happen. */ + return NULL; +} +libc_hidden_def(strchrnul) +#endif diff --git a/libc/string/generic/strcmp.c b/libc/string/generic/strcmp.c new file mode 100644 index 0000000..50acd35 --- /dev/null +++ b/libc/string/generic/strcmp.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int strcmp (const char *p1, const char *p2) +{ + register const unsigned char *s1 = (const unsigned char *) p1; + register const unsigned char *s2 = (const unsigned char *) p2; + unsigned reg_char c1, c2; + + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} +libc_hidden_weak(strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +/* Experimentally off - libc_hidden_proto(strcoll) */ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/generic/strcpy.c b/libc/string/generic/strcpy.c new file mode 100644 index 0000000..99e0771 --- /dev/null +++ b/libc/string/generic/strcpy.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "memcopy.h" +#include "bp-checks.h" + +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Copy SRC to DEST. */ +char *strcpy (char *dest, const char *src) +{ + reg_char c; + char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src); + const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1; + size_t n; + + do + { + c = *s++; + s[off] = c; + } + while (c != '\0'); + + n = s - src; + (void) CHECK_BOUNDS_HIGH (src + n); + (void) CHECK_BOUNDS_HIGH (dest + n); + + return dest; +} +libc_hidden_def(strcpy) diff --git a/libc/string/generic/strcspn.c b/libc/string/generic/strcspn.c new file mode 100644 index 0000000..b65b3b9 --- /dev/null +++ b/libc/string/generic/strcspn.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1994, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(strcspn) */ +/* Experimentally off - libc_hidden_proto(strchr) */ + +/* Return the length of the maximum initial segment of S + which contains no characters from REJECT. */ +size_t strcspn (const char *s, const char *reject) +{ + size_t count = 0; + + while (*s != '\0') + if (strchr (reject, *s++) == NULL) + ++count; + else + return count; + + return count; +} +libc_hidden_def(strcspn) diff --git a/libc/string/generic/strlen.c b/libc/string/generic/strlen.c new file mode 100644 index 0000000..764dae1 --- /dev/null +++ b/libc/string/generic/strlen.c @@ -0,0 +1,152 @@ +/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se); + commentary by Jim Blandy (jimb@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(abort) + +/* Return the length of the null-terminated string STR. Scan for + the null terminator quickly by testing four bytes at a time. */ +size_t strlen (const char *str) +{ + const char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, himagic, lomagic; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = str; ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == '\0') + return char_ptr - str; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + magic_bits = 0x7efefeffL; + himagic = 0x80808080L; + lomagic = 0x01010101L; + if (sizeof (longword) > 4) + { + /* 64-bit version of the magic. */ + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; + himagic = ((himagic << 16) << 16) | himagic; + lomagic = ((lomagic << 16) << 16) | lomagic; + } + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. */ + + longword = *longword_ptr++; + + if ( +#if 0 + /* Add MAGIC_BITS to LONGWORD. */ + (((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) +#else + ((longword - lomagic) & himagic) +#endif + != 0) + { + /* Which of the bytes was the zero? If none of them were, it was + a misfire; continue the search. */ + + const char *cp = (const char *) (longword_ptr - 1); + + if (cp[0] == 0) + return cp - str; + if (cp[1] == 0) + return cp - str + 1; + if (cp[2] == 0) + return cp - str + 2; + if (cp[3] == 0) + return cp - str + 3; + if (sizeof (longword) > 4) + { + if (cp[4] == 0) + return cp - str + 4; + if (cp[5] == 0) + return cp - str + 5; + if (cp[6] == 0) + return cp - str + 6; + if (cp[7] == 0) + return cp - str + 7; + } + } + } +} +libc_hidden_weak(strlen) diff --git a/libc/string/generic/strncat.c b/libc/string/generic/strncat.c new file mode 100644 index 0000000..8e3423e --- /dev/null +++ b/libc/string/generic/strncat.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(strncat) */ +char *strncat (char *s1, const char *s2, size_t n) +{ + reg_char c; + char *s = s1; + + /* Find the end of S1. */ + do + c = *s1++; + while (c != '\0'); + + /* Make S1 point before next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + n--; + } + + if (c != '\0') + *++s1 = '\0'; + + return s; +} +libc_hidden_def(strncat) diff --git a/libc/string/generic/strncmp.c b/libc/string/generic/strncmp.c new file mode 100644 index 0000000..c49f36d --- /dev/null +++ b/libc/string/generic/strncmp.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(strncmp) */ +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int strncmp (const char *s1, const char *s2, size_t n) +{ + unsigned reg_char c1 = '\0'; + unsigned reg_char c2 = '\0'; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + + return c1 - c2; +} +libc_hidden_weak(strncmp) diff --git a/libc/string/generic/strncpy.c b/libc/string/generic/strncpy.c new file mode 100644 index 0000000..d2d693f --- /dev/null +++ b/libc/string/generic/strncpy.c @@ -0,0 +1,82 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Experimentally off - libc_hidden_proto(strncpy) */ +char *strncpy (char *s1, const char *s2, size_t n) +{ + reg_char c; + char *s = s1; + + --s1; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (s1 - s) - 1; + if (n == 0) + return s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return s; + + do + { + c = *s2++; + *++s1 = c; + if (--n == 0) + return s; + } + while (c != '\0'); + + zero_fill: + do + *++s1 = '\0'; + while (--n > 0); + + return s; +} +libc_hidden_def(strncpy) diff --git a/libc/string/generic/strnlen.c b/libc/string/generic/strnlen.c new file mode 100644 index 0000000..d9ba761 --- /dev/null +++ b/libc/string/generic/strnlen.c @@ -0,0 +1,164 @@ +/* Find the length of STRING, but scan at most MAXLEN characters. + Copyright (C) 1991, 1993, 1997, 2000, 2001 Free Software Foundation, Inc. + Contributed by Jakub Jelinek . + + Based on strlen written by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se); + commentary by Jim Blandy (jimb@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(strnlen) */ +libc_hidden_proto(abort) + +/* Find the length of S, but scan at most MAXLEN characters. If no + '\0' terminator is found in that many characters, return MAXLEN. */ +size_t strnlen (const char *str, size_t maxlen) +{ + const char *char_ptr, *end_ptr = str + maxlen; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, himagic, lomagic; + + if (maxlen == 0) + return 0; + + if (__builtin_expect (end_ptr < str, 0)) + end_ptr = (const char *) ~0UL; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = str; ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == '\0') + { + if (char_ptr > end_ptr) + char_ptr = end_ptr; + return char_ptr - str; + } + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + magic_bits = 0x7efefeffL; + himagic = 0x80808080L; + lomagic = 0x01010101L; + if (sizeof (longword) > 4) + { + /* 64-bit version of the magic. */ + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; + himagic = ((himagic << 16) << 16) | himagic; + lomagic = ((lomagic << 16) << 16) | lomagic; + } + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (longword_ptr < (unsigned long int *) end_ptr) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. */ + + longword = *longword_ptr++; + + if ((longword - lomagic) & himagic) + { + /* Which of the bytes was the zero? If none of them were, it was + a misfire; continue the search. */ + + const char *cp = (const char *) (longword_ptr - 1); + + char_ptr = cp; + if (cp[0] == 0) + break; + char_ptr = cp + 1; + if (cp[1] == 0) + break; + char_ptr = cp + 2; + if (cp[2] == 0) + break; + char_ptr = cp + 3; + if (cp[3] == 0) + break; + if (sizeof (longword) > 4) + { + char_ptr = cp + 4; + if (cp[4] == 0) + break; + char_ptr = cp + 5; + if (cp[5] == 0) + break; + char_ptr = cp + 6; + if (cp[6] == 0) + break; + char_ptr = cp + 7; + if (cp[7] == 0) + break; + } + } + char_ptr = end_ptr; + } + + if (char_ptr > end_ptr) + char_ptr = end_ptr; + return char_ptr - str; +} +libc_hidden_def(strnlen) +#endif diff --git a/libc/string/generic/strrchr.c b/libc/string/generic/strrchr.c new file mode 100644 index 0000000..c857072 --- /dev/null +++ b/libc/string/generic/strrchr.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(strrchr) */ +/* Experimentally off - libc_hidden_proto(strchr) */ + +/* Find the last occurrence of C in S. */ +char *strrchr (const char *s, int c) +{ + register const char *found, *p; + + c = (unsigned char) c; + + /* Since strchr is fast, we use it rather than the obvious loop. */ + + if (c == '\0') + return strchr (s, '\0'); + + found = NULL; + while ((p = strchr (s, c)) != NULL) + { + found = p; + s = p + 1; + } + + return (char *) found; +} +libc_hidden_weak(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strrchr,rindex) +#endif diff --git a/libc/string/generic/strsep.c b/libc/string/generic/strsep.c new file mode 100644 index 0000000..e02e570 --- /dev/null +++ b/libc/string/generic/strsep.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1992, 93, 96, 97, 98, 99, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_BSD + +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strpbrk) */ + +/* Experimentally off - libc_hidden_proto(strsep) */ +char *strsep (char **stringp, const char *delim) +{ + char *begin, *end; + + begin = *stringp; + if (begin == NULL) + return NULL; + + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; + + if (ch == '\0') + end = NULL; + else + { + if (*begin == ch) + end = begin; + else if (*begin == '\0') + end = NULL; + else + end = strchr (begin + 1, ch); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + + if (end) + { + /* Terminate the token and set *STRINGP past NUL character. */ + *end++ = '\0'; + *stringp = end; + } + else + /* No more delimiters; this is the last token. */ + *stringp = NULL; + + return begin; +} +libc_hidden_def(strsep) +#endif diff --git a/libc/string/generic/strspn.c b/libc/string/generic/strspn.c new file mode 100644 index 0000000..0105677 --- /dev/null +++ b/libc/string/generic/strspn.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(strspn) */ +/* Return the length of the maximum initial segment + of S which contains only characters in ACCEPT. */ +size_t strspn (const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) + { + for (a = accept; *a != '\0'; ++a) + if (*p == *a) + break; + if (*a == '\0') + return count; + else + ++count; + } + + return count; +} +libc_hidden_def(strspn) diff --git a/libc/string/generic/strstr.c b/libc/string/generic/strstr.c new file mode 100644 index 0000000..c12dceb --- /dev/null +++ b/libc/string/generic/strstr.c @@ -0,0 +1,114 @@ +/* Return the offset of one string within another. + Copyright (C) 1994,1996,1997,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * My personal strstr() implementation that beats most other algorithms. + * Until someone tells me otherwise, I assume that this is the + * fastest implementation of strstr() in C. + * I deliberately chose not to comment it. You should have at least + * as much fun trying to understand it, as I had to write it :-). + * + * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ + +#include + +/* Experimentally off - libc_hidden_proto(strstr) */ + +typedef unsigned chartype; + +char *strstr (const char *phaystack, const char *pneedle) +{ + const unsigned char *haystack, *needle; + chartype b; + const unsigned char *rneedle; + + haystack = (const unsigned char *) phaystack; + + if ((b = *(needle = (const unsigned char *) pneedle))) + { + chartype c; + haystack--; /* possible ANSI violation */ + + { + chartype a; + do + if (!(a = *++haystack)) + goto ret0; + while (a != b); + } + + if (!(c = *++needle)) + goto foundneedle; + ++needle; + goto jin; + + for (;;) + { + { + chartype a; + if (0) + jin:{ + if ((a = *++haystack) == c) + goto crest; + } + else + a = *++haystack; + do + { + for (; a != b; a = *++haystack) + { + if (!a) + goto ret0; + if ((a = *++haystack) == b) + break; + if (!a) + goto ret0; + } + } + while ((a = *++haystack) != c); + } + crest: + { + chartype a; + { + const unsigned char *rhaystack; + if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle))) + do + { + if (!a) + goto foundneedle; + if (*++rhaystack != (a = *++needle)) + break; + if (!a) + goto foundneedle; + } + while (*++rhaystack == (a = *++needle)); + needle = rneedle; /* took the register-poor aproach */ + } + if (!a) + break; + } + } + } +foundneedle: + return (char *) haystack; +ret0: + return 0; +} +libc_hidden_def(strstr) diff --git a/libc/string/generic/strtok_r.c b/libc/string/generic/strtok_r.c new file mode 100644 index 0000000..7648212 --- /dev/null +++ b/libc/string/generic/strtok_r.c @@ -0,0 +1,72 @@ +/* Reentrant string tokenizer. Generic version. + Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(strtok_r) */ +/* Experimentally off - libc_hidden_proto(strspn) */ +/* Experimentally off - libc_hidden_proto(strpbrk) */ +#ifdef __USE_GNU +# define __rawmemchr rawmemchr +/* Experimentally off - libc_hidden_proto(rawmemchr) */ +#else +# define __rawmemchr strchr +/* Experimentally off - libc_hidden_proto(strchr) */ +#endif +#if 0 + Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); /* x = "abc", sp = "=-def" */ + x = strtok_r(NULL, "-=", &sp); /* x = "def", sp = NULL */ + x = strtok_r(NULL, "=", &sp); /* x = NULL */ + /* s = "abc\0-def\0" */ +#endif +char *strtok_r (char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) + s = *save_ptr; + + /* Scan leading delimiters. */ + s += strspn (s, delim); + if (*s == '\0') + { + *save_ptr = s; + return NULL; + } + + /* Find the end of the token. */ + token = s; + s = strpbrk (token, delim); + if (s == NULL) + /* This token finishes the string. */ + *save_ptr = __rawmemchr (token, '\0'); + else + { + /* Terminate the token and make *SAVE_PTR point past it. */ + *s = '\0'; + *save_ptr = s + 1; + } + return token; +} +libc_hidden_def(strtok_r) diff --git a/libc/string/i386/Makefile b/libc/string/i386/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/i386/memchr.c b/libc/string/i386/memchr.c new file mode 100644 index 0000000..fe45379 --- /dev/null +++ b/libc/string/i386/memchr.c @@ -0,0 +1,51 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(memchr) */ +void *memchr(const void *cs, int c, size_t count) +{ + int d0; + register void * __res; + if (!count) + return NULL; + __asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "je 1f\n\t" + "movl $1,%0\n" + "1:\tdecl %0" + :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count)); + return __res; +} +libc_hidden_def(memchr) diff --git a/libc/string/i386/memcpy.c b/libc/string/i386/memcpy.c new file mode 100644 index 0000000..285583f --- /dev/null +++ b/libc/string/i386/memcpy.c @@ -0,0 +1,53 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +void *memcpy(void * to, const void * from, size_t n) +{ + int d0, d1, d2; + __asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); + return (to); +} +libc_hidden_def(memcpy) diff --git a/libc/string/i386/memmove.c b/libc/string/i386/memmove.c new file mode 100644 index 0000000..a924efc --- /dev/null +++ b/libc/string/i386/memmove.c @@ -0,0 +1,59 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(memmove) */ +void *memmove(void *dest, const void *src, size_t n) +{ + int d0, d1, d2; + if (dest + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(memset) */ +void *memset(void *s, int c, size_t count) +{ + int d0, d1; + __asm__ __volatile__( + "rep\n\t" + "stosb" + : "=&c" (d0), "=&D" (d1) + :"a" (c),"1" (s),"0" (count) + :"memory"); + return s; +} +libc_hidden_def(memset) diff --git a/libc/string/i386/strcat.c b/libc/string/i386/strcat.c new file mode 100644 index 0000000..2cf0237 --- /dev/null +++ b/libc/string/i386/strcat.c @@ -0,0 +1,51 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strcat) */ +char *strcat(char * dest, const char * src) +{ + int d0, d1, d2, d3; + __asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); + return dest; +} +libc_hidden_def(strcat) diff --git a/libc/string/i386/strchr.c b/libc/string/i386/strchr.c new file mode 100644 index 0000000..46b1dfb --- /dev/null +++ b/libc/string/i386/strchr.c @@ -0,0 +1,56 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strchr) */ +char *strchr(const char *s, int c) +{ + int d0; + register char * __res; + __asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); + return __res; +} +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif diff --git a/libc/string/i386/strcmp.c b/libc/string/i386/strcmp.c new file mode 100644 index 0000000..eff230c --- /dev/null +++ b/libc/string/i386/strcmp.c @@ -0,0 +1,61 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strcmp) */ +int strcmp(const char *cs, const char *ct) +{ + int d0, d1; + register int __res; + __asm__ __volatile__( + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "3:" + :"=a" (__res), "=&S" (d0), "=&D" (d1) + :"1" (cs),"2" (ct)); + return __res; +} +libc_hidden_def(strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +/* Experimentally off - libc_hidden_proto(strcoll) */ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/i386/strcpy.c b/libc/string/i386/strcpy.c new file mode 100644 index 0000000..09065a9 --- /dev/null +++ b/libc/string/i386/strcpy.c @@ -0,0 +1,48 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strcpy) */ +char *strcpy(char * dest, const char * src) +{ + int d0, d1, d2; + __asm__ __volatile__( + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); + return dest; +} +libc_hidden_def(strcpy) diff --git a/libc/string/i386/strlen.c b/libc/string/i386/strlen.c new file mode 100644 index 0000000..61a1783 --- /dev/null +++ b/libc/string/i386/strlen.c @@ -0,0 +1,48 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strlen) */ +size_t strlen(const char *s) +{ + int d0; + register int __res; + __asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "notl %0\n\t" + "decl %0" + :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); + return __res; +} +libc_hidden_def(strlen) diff --git a/libc/string/i386/strncat.c b/libc/string/i386/strncat.c new file mode 100644 index 0000000..3872679 --- /dev/null +++ b/libc/string/i386/strncat.c @@ -0,0 +1,61 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strncat) */ +char *strncat(char * dest, + const char * src, size_t count) +{ + int d0, d1, d2, d3; + __asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %8,%3\n" + "incl %3\n" + "1:\tdecl %3\n\t" + "jz 2f\n" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "jmp 3f\n" + "2:\txorl %2,%2\n\t" + "stosb\n" + "3:" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) + : "memory"); + return dest; +} +libc_hidden_def(strncat) diff --git a/libc/string/i386/strncmp.c b/libc/string/i386/strncmp.c new file mode 100644 index 0000000..a14bb50 --- /dev/null +++ b/libc/string/i386/strncmp.c @@ -0,0 +1,58 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strncmp) */ +int strncmp(const char *cs, const char *ct, size_t count) +{ + register int __res; + int d0, d1, d2; + __asm__ __volatile__( + "incl %3\n" + "1:\tdecl %3\n\t" + "jz 2f\n" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "4:" + :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + :"1" (cs),"2" (ct),"3" (count)); + return __res; +} +libc_hidden_weak(strncmp) diff --git a/libc/string/i386/strncpy.c b/libc/string/i386/strncpy.c new file mode 100644 index 0000000..76aa6ae --- /dev/null +++ b/libc/string/i386/strncpy.c @@ -0,0 +1,56 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strncpy) */ +char *strncpy(char * dest, const char * src, size_t count) +{ + int d0, d1, d2, d3; + __asm__ __volatile__( + "incl %2\n" + "1:\n" + "decl %2\n" + "jz 2f\n" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "decl %2\n" + "rep\n\t" + "stosb\n" + "2:" + : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) + :"0" (src),"1" (dest),"2" (count) : "memory"); + return dest; +} +libc_hidden_def(strncpy) diff --git a/libc/string/i386/strnlen.c b/libc/string/i386/strnlen.c new file mode 100644 index 0000000..02c72f5 --- /dev/null +++ b/libc/string/i386/strnlen.c @@ -0,0 +1,56 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(strnlen) */ +size_t strnlen(const char *s, size_t count) +{ + int d0; + register int __res; + __asm__ __volatile__( + "movl %2,%0\n\t" + "incl %1\n" + "jmp 2f\n" + "1:\tcmpb $0,(%0)\n\t" + "je 3f\n\t" + "incl %0\n" + "2:\tdecl %1\n\t" + "jne 1b\n" + "3:\tsubl %2,%0" + :"=a" (__res), "=&d" (d0) + :"c" (s),"1" (count)); + return __res; +} +libc_hidden_def(strnlen) +#endif diff --git a/libc/string/i386/strrchr.c b/libc/string/i386/strrchr.c new file mode 100644 index 0000000..ef37868 --- /dev/null +++ b/libc/string/i386/strrchr.c @@ -0,0 +1,54 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +/* Experimentally off - libc_hidden_proto(strrchr) */ +char *strrchr(const char *s, int c) +{ + int d0, d1; + register char * __res; + __asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "leal -1(%%esi),%0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); + return __res; +} +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/libc/string/ia64/Makefile b/libc/string/ia64/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/ia64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/ia64/bcopy.S b/libc/string/ia64/bcopy.S new file mode 100644 index 0000000..c5637c3 --- /dev/null +++ b/libc/string/ia64/bcopy.S @@ -0,0 +1,14 @@ +#include "sysdep.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +ENTRY(bcopy) + .regstk 3, 0, 0, 0 + mov r8 = in0 + mov in0 = in1 + ;; + mov in1 = r8 + br.cond.sptk.many HIDDEN_JUMPTARGET(memmove) +END(bcopy) + +#endif diff --git a/libc/string/ia64/bzero.S b/libc/string/ia64/bzero.S new file mode 100644 index 0000000..1f0f8b7 --- /dev/null +++ b/libc/string/ia64/bzero.S @@ -0,0 +1,320 @@ +/* Optimized version of the standard bzero() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: count + + The algorithm is fairly straightforward: set byte by byte until we + we get to a 16B-aligned address, then loop on 128 B chunks using an + early store as prefetching, then loop on 32B chucks, then clear remaining + words, finally clear remaining bytes. + Since a stf.spill f0 can store 16B in one go, we use this instruction + to get peak speed. */ + +#include "sysdep.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +#undef ret + +#define dest in0 +#define cnt in1 + +#define tmp r31 +#define save_lc r30 +#define ptr0 r29 +#define ptr1 r28 +#define ptr2 r27 +#define ptr3 r26 +#define ptr9 r24 +#define loopcnt r23 +#define linecnt r22 +#define bytecnt r21 + +/* This routine uses only scratch predicate registers (p6 - p15) */ +#define p_scr p6 /* default register for same-cycle branches */ +#define p_unalgn p9 +#define p_y p11 +#define p_n p12 +#define p_yy p13 +#define p_nn p14 + +#define movi0 mov + +#define MIN1 15 +#define MIN1P1HALF 8 +#define LINE_SIZE 128 +#define LSIZE_SH 7 /* shift amount */ +#define PREF_AHEAD 8 + +#define USE_FLP +#if defined(USE_INT) +#define store st8 +#define myval r0 +#elif defined(USE_FLP) +#define store stf8 +#define myval f0 +#endif + +.align 64 +ENTRY(bzero) +{ .mmi + .prologue + alloc tmp = ar.pfs, 2, 0, 0, 0 + lfetch.nt1 [dest] + .save ar.lc, save_lc + movi0 save_lc = ar.lc +} { .mmi + .body + mov ret0 = dest /* return value */ + nop.m 0 + cmp.eq p_scr, p0 = cnt, r0 +;; } +{ .mmi + and ptr2 = -(MIN1+1), dest /* aligned address */ + and tmp = MIN1, dest /* prepare to check for alignment */ + tbit.nz p_y, p_n = dest, 0 /* Do we have an odd address? (M_B_U) */ +} { .mib + mov ptr1 = dest + nop.i 0 +(p_scr) br.ret.dpnt.many rp /* return immediately if count = 0 */ +;; } +{ .mib + cmp.ne p_unalgn, p0 = tmp, r0 +} { .mib /* NB: # of bytes to move is 1 */ + sub bytecnt = (MIN1+1), tmp /* higher than loopcnt */ + cmp.gt p_scr, p0 = 16, cnt /* is it a minimalistic task? */ +(p_scr) br.cond.dptk.many .move_bytes_unaligned /* go move just a few (M_B_U) */ +;; } +{ .mmi +(p_unalgn) add ptr1 = (MIN1+1), ptr2 /* after alignment */ +(p_unalgn) add ptr2 = MIN1P1HALF, ptr2 /* after alignment */ +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 3 /* should we do a st8 ? */ +;; } +{ .mib +(p_y) add cnt = -8, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 2 /* should we do a st4 ? */ +} { .mib +(p_y) st8 [ptr2] = r0,-4 +(p_n) add ptr2 = 4, ptr2 +;; } +{ .mib +(p_yy) add cnt = -4, cnt +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 1 /* should we do a st2 ? */ +} { .mib +(p_yy) st4 [ptr2] = r0,-2 +(p_nn) add ptr2 = 2, ptr2 +;; } +{ .mmi + mov tmp = LINE_SIZE+1 /* for compare */ +(p_y) add cnt = -2, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 0 /* should we do a st1 ? */ +} { .mmi + nop.m 0 +(p_y) st2 [ptr2] = r0,-1 +(p_n) add ptr2 = 1, ptr2 +;; } + +{ .mmi +(p_yy) st1 [ptr2] = r0 + cmp.gt p_scr, p0 = tmp, cnt /* is it a minimalistic task? */ +} { .mbb +(p_yy) add cnt = -1, cnt +(p_scr) br.cond.dpnt.many .fraction_of_line /* go move just a few */ +;; } +{ .mib + nop.m 0 + shr.u linecnt = cnt, LSIZE_SH + nop.b 0 +;; } + + .align 32 +.l1b: /* ------------------ L1B: store ahead into cache lines; fill later */ +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt + add ptr2 = 16, ptr1 /* start of stores (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total range */ +;; } +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1b: +{ .mib + stf.spill [ptr9] = f0, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1b +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1bx: + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 64 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + stf.spill [ptr2] = f0, 32 +(p_scr) stf.spill [ptr9] = f0, 128 + br.cloop.dptk.few .l1bx +;; } +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment +;; } + +.fraction_of_line: +{ .mib + add ptr2 = 16, ptr1 + shr.u loopcnt = cnt, 5 /* loopcnt = cnt / 32 */ +;; } +{ .mib + cmp.eq p_scr, p0 = loopcnt, r0 + add loopcnt = -1, loopcnt +(p_scr) br.cond.dpnt.many .store_words +;; } +{ .mib + and cnt = 0x1f, cnt /* compute the remaining cnt */ + movi0 ar.lc = loopcnt +;; } + .align 32 +.l2: /* ----------------------------- L2A: store 32B in 2 cycles */ +{ .mmb + store [ptr1] = myval, 8 + store [ptr2] = myval, 8 +;; } { .mmb + store [ptr1] = myval, 24 + store [ptr2] = myval, 24 + br.cloop.dptk.many .l2 +;; } +.store_words: +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment /* Branch */ +;; } + +{ .mmi + store [ptr1] = myval, 8 /* store */ + cmp.le p_y, p_n = 16, cnt /* */ + add cnt = -8, cnt /* subtract */ +;; } +{ .mmi +(p_y) store [ptr1] = myval, 8 /* store */ +(p_y) cmp.le.unc p_yy, p_nn = 16, cnt +(p_y) add cnt = -8, cnt /* subtract */ +;; } +{ .mmi /* store */ +(p_yy) store [ptr1] = myval, 8 +(p_yy) add cnt = -8, cnt /* subtract */ +;; } + +.move_bytes_from_alignment: +{ .mib + cmp.eq p_scr, p0 = cnt, r0 + tbit.nz.unc p_y, p0 = cnt, 2 /* should we terminate with a st4 ? */ +(p_scr) br.cond.dpnt.few .restore_and_exit +;; } +{ .mib +(p_y) st4 [ptr1] = r0,4 + tbit.nz.unc p_yy, p0 = cnt, 1 /* should we terminate with a st2 ? */ +;; } +{ .mib +(p_yy) st2 [ptr1] = r0,2 + tbit.nz.unc p_y, p0 = cnt, 0 /* should we terminate with a st1 ? */ +;; } + +{ .mib +(p_y) st1 [ptr1] = r0 +;; } +.restore_and_exit: +{ .mib + nop.m 0 + movi0 ar.lc = save_lc + br.ret.sptk.many rp +;; } + +.move_bytes_unaligned: +{ .mmi + .pred.rel "mutex",p_y, p_n + .pred.rel "mutex",p_yy, p_nn +(p_n) cmp.le p_yy, p_nn = 4, cnt +(p_y) cmp.le p_yy, p_nn = 5, cnt +(p_n) add ptr2 = 2, ptr1 +} { .mmi +(p_y) add ptr2 = 3, ptr1 +(p_y) st1 [ptr1] = r0, 1 /* fill 1 (odd-aligned) byte */ +(p_y) add cnt = -1, cnt /* [15, 14 (or less) left] */ +;; } +{ .mmi +(p_yy) cmp.le.unc p_y, p0 = 8, cnt + add ptr3 = ptr1, cnt /* prepare last store */ + movi0 ar.lc = save_lc +} { .mmi +(p_yy) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) add cnt = -4, cnt /* [11, 10 (o less) left] */ +;; } +{ .mmi +(p_y) cmp.le.unc p_yy, p0 = 8, cnt + add ptr3 = -1, ptr3 /* last store */ + tbit.nz p_scr, p0 = cnt, 1 /* will there be a st2 at the end ? */ +} { .mmi +(p_y) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_y) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ +(p_y) add cnt = -4, cnt /* [7, 6 (or less) left] */ +;; } +{ .mmi +(p_yy) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ + /* [3, 2 (or less) left] */ + tbit.nz p_y, p0 = cnt, 0 /* will there be a st1 at the end ? */ +} { .mmi +(p_yy) add cnt = -4, cnt +;; } +{ .mmb +(p_scr) st2 [ptr1] = r0 /* fill 2 (aligned) bytes */ +(p_y) st1 [ptr3] = r0 /* fill last byte (using ptr3) */ + br.ret.sptk.many rp +;; } +END(bzero) + +#endif diff --git a/libc/string/ia64/memccpy.S b/libc/string/ia64/memccpy.S new file mode 100644 index 0000000..259d680 --- /dev/null +++ b/libc/string/ia64/memccpy.S @@ -0,0 +1,213 @@ +/* Optimized version of the memccpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: a pointer to the next byte after char in dest or NULL + + Inputs: + in0: dest + in1: src + in2: char + in3: byte count + + This implementation assumes little endian mode (UM.be = 0). + + This implementation assumes that it is safe to do read ahead + in the src block, without getting beyond its limit. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define char r24 +#define charx8 r25 +#define saved_ec r26 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +/* Manually force proper loop-alignment. Note: be sure to + double-check the code-layout after making any changes to + this routine! */ +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +ENTRY(memccpy) + .prologue + alloc r2 = ar.pfs, 4, 40 - 4, 0, 40 + +#include "softpipe.h" + .rotr r[MEMLAT + 7], tmp1[4], tmp2[4], val[4], tmp3[2], pos0[2] + .rotp p[MEMLAT + 6 + 1] + + mov ret0 = r0 /* return NULL if no match */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + mov dest = in0 /* dest */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + mov saved_ec = ar.ec /* save the loop counter */ + .body + mov src = in1 /* src */ + extr.u char = in2, 0, 8 /* char */ + mov len = in3 /* len */ + sub tmp = r0, in0 /* tmp = -dest */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + ;; + and loopcnt = 7, tmp /* loopcnt = -dest % 8 */ + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ + mov ar.ec = 0 /* ec not guaranteed zero on entry */ +(p6) br.cond.spnt .cpyfew /* copy byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 + mux1 charx8 = char, @brcst +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value = [src], 1 /* value = *src++ */ + ;; + st1 [dest] = value, 1 /* *dest++ = value */ + cmp.eq p6, p0 = value, char +(p6) br.cond.spnt .foundit + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp = -8, len /* tmp = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* len = len % 8 */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + mov pr.rot = 1 << 16 ;; /* set rotating predicates */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned ;; + add src = src, tmp /* src += len & -OPSIZ */ + mov ar.ec = MEMLAT + 6 + 1 /* six more passes needed */ + ld8 r[1] = [asrc], 8 /* r[1] = w0 */ + cmp.ne p6, p0 = r0, r0 ;; /* clear p6 */ + ALIGN(32) +.l2: +(p[0]) ld8.s r[0] = [asrc], 8 /* r[0] = w1 */ +(p[MEMLAT]) shr.u tmp1[0] = r[1 + MEMLAT], sh1 /* tmp1 = w0 >> sh1 */ +(p[MEMLAT]) shl tmp2[0] = r[0 + MEMLAT], sh2 /* tmp2 = w1 << sh2 */ +(p[MEMLAT+4]) xor tmp3[0] = val[1], charx8 +(p[MEMLAT+5]) czx1.r pos0[0] = tmp3[1] +(p[MEMLAT+6]) chk.s r[6 + MEMLAT], .recovery1 /* our data isn't */ + /* valid - rollback! */ +(p[MEMLAT+6]) cmp.ne p6, p0 = 8, pos0[1] +(p6) br.cond.spnt .gotit +(p[MEMLAT+6]) st8 [dest] = val[3], 8 /* store val to dest */ +(p[MEMLAT+3]) or val[0] = tmp1[3], tmp2[3] /* val = tmp1 | tmp2 */ + br.ctop.sptk .l2 + br.cond.sptk .cpyfew + +.src_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + mov ar.ec = MEMLAT + 2 + 1 ;; /* set EC */ +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) xor tmp3[0] = r[MEMLAT], charx8 +(p[MEMLAT+1]) czx1.r pos0[0] = tmp3[1] +(p[MEMLAT+2]) cmp.ne p7, p0 = 8, pos0[1] +(p[MEMLAT+2]) chk.s r[MEMLAT+2], .recovery2 +(p7) br.cond.spnt .gotit +.back2: +(p[MEMLAT+2]) st8 [dest] = r[MEMLAT+2], 8 + br.ctop.dptk .l3 +.cpyfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value = [src], 1 + ;; + st1 [dest] = value, 1 + cmp.eq p6, p0 = value, char +(p6) br.cond.spnt .foundit + br.cloop.dptk .l4 ;; +.foundit: +(p6) mov ret0 = dest +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + mov ar.ec = saved_ec ;; /* restore the epilog counter */ + br.ret.sptk.many b0 +.gotit: + .pred.rel "mutex" p6, p7 +(p6) mov value = val[3] /* if coming from l2 */ +(p7) mov value = r[MEMLAT+2] /* if coming from l3 */ + mov ar.lc = pos0[1] ;; +.l5: + extr.u tmp = value, 0, 8 ;; + st1 [dest] = tmp, 1 + shr.u value = value, 8 + br.cloop.sptk .l5 ;; + mov ret0 = dest + mov pr = saved_pr, -1 + mov ar.lc = saved_lc + br.ret.sptk.many b0 + +.recovery1: + adds src = -(MEMLAT + 6 + 1) * 8, asrc + mov loopcnt = ar.lc + mov tmp = ar.ec ;; + sub sh1 = (MEMLAT + 6 + 1), tmp + shr.u sh2 = sh2, 3 + ;; + shl loopcnt = loopcnt, 3 + sub src = src, sh2 + shl sh1 = sh1, 3 + shl tmp = tmp, 3 + ;; + add len = len, loopcnt + add src = sh1, src ;; + add len = tmp, len +.back1: + br.cond.sptk .cpyfew + +.recovery2: + add tmp = -(MEMLAT + 3) * 8, src +(p7) br.cond.spnt .gotit + ;; + ld8 r[MEMLAT+2] = [tmp] ;; + xor pos0[1] = r[MEMLAT+2], charx8 ;; + czx1.r pos0[1] = pos0[1] ;; + cmp.ne p7, p6 = 8, pos0[1] +(p7) br.cond.spnt .gotit + br.cond.sptk .back2 +END(memccpy) diff --git a/libc/string/ia64/memchr.S b/libc/string/ia64/memchr.S new file mode 100644 index 0000000..0246b59 --- /dev/null +++ b/libc/string/ia64/memchr.S @@ -0,0 +1,133 @@ +/* Optimized version of the standard memchr() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the address of the first occurence of chr in str or NULL + + Inputs: + in0: str + in1: chr + in2: byte count + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. + + The algorithm is fairly straightforward: search byte by byte until we + we get to a word aligned address, then search word by word as much as + possible; the remaining few bytes are searched one at a time. + + The word by word search is performed by xor-ing the word with a word + containing chr in every byte. If there is a hit, the result will + contain a zero byte in the corresponding position. The presence and + position of that zero byte is detected with a czx instruction. + + All the loops in this function could have had the internal branch removed + if br.ctop and br.cloop could be predicated :-(. */ + +#include "sysdep.h" +#undef ret + +#define saved_pr r15 +#define saved_lc r16 +#define chr r17 +#define len r18 +#define pos0 r20 +#define val r21 +#define tmp r24 +#define chrx8 r25 +#define loopcnt r30 + +#define str in0 + +ENTRY(__memchr) + .prologue + alloc r2 = ar.pfs, 3, 0, 29, 32 +#include "softpipe.h" + .rotr value[MEMLAT+1], addr[MEMLAT+3], aux[2], poschr[2] + .rotp p[MEMLAT+3] + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicates */ + .body + mov ret0 = str + and tmp = 7, str /* tmp = str % 8 */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + extr.u chr = in1, 0, 8 /* chr = (unsigned char) in1 */ + mov len = in2 + cmp.gtu p6, p0 = 16, in2 /* use a simple loop for short */ +(p6) br.cond.spnt .srchfew ;; /* searches */ + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + sub len = len, loopcnt + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val = [ret0], 1 + ;; + cmp.eq p6, p0 = val, chr +(p6) br.cond.spnt .foundit + br.cloop.sptk .l1 ;; +.str_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* remaining len = len & 7 */ + adds loopcnt = -1, loopcnt + mov ar.ec = MEMLAT + 3 + mux1 chrx8 = chr, @brcst ;; /* get a word full of chr */ + mov ar.lc = loopcnt + mov pr.rot = 1 << 16 ;; +.l2: +(p[0]) mov addr[0] = ret0 +(p[0]) ld8 value[0] = [ret0], 8 +(p[MEMLAT]) xor aux[0] = value[MEMLAT], chrx8 +(p[MEMLAT+1]) czx1.r poschr[0] = aux[1] +(p[MEMLAT+2]) cmp.ne p7, p0 = 8, poschr[1] +(p7) br.cond.dpnt .foundit + br.ctop.dptk .l2 +.srchfew: + adds loopcnt = -1, len + cmp.eq p6, p0 = len, r0 +(p6) br.cond.spnt .notfound ;; + mov ar.lc = loopcnt +.l3: + ld1 val = [ret0], 1 + ;; + cmp.eq p6, p0 = val, chr +(p6) br.cond.dpnt .foundit + br.cloop.sptk .l3 ;; +.notfound: + cmp.ne p6, p0 = r0, r0 /* clear p6 (p7 was already 0 when we got here) */ + mov ret0 = r0 ;; /* return NULL */ +.foundit: + .pred.rel "mutex" p6, p7 +(p6) adds ret0 = -1, ret0 /* if we got here from l1 or l3 */ +(p7) add ret0 = addr[MEMLAT+2], poschr[1] /* if we got here from l2 */ + mov pr = saved_pr, -1 + mov ar.lc = saved_lc + br.ret.sptk.many b0 + +END(__memchr) + +weak_alias (__memchr, memchr) +#if !__BOUNDED_POINTERS__ +weak_alias (__memchr, __ubp_memchr) +#endif +libc_hidden_def (memchr) diff --git a/libc/string/ia64/memcmp.S b/libc/string/ia64/memcmp.S new file mode 100644 index 0000000..adb1a20 --- /dev/null +++ b/libc/string/ia64/memcmp.S @@ -0,0 +1,166 @@ +/* Optimized version of the standard memcmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: dest (aka s1) + in1: src (aka s2) + in2: byte count + + In this form, it assumes little endian mode. For big endian mode, the + the two shifts in .l2 must be inverted: + + shl tmp1[0] = r[1 + MEMLAT], sh1 // tmp1 = w0 << sh1 + shr.u tmp2[0] = r[0 + MEMLAT], sh2 // tmp2 = w1 >> sh2 + + and all the mux1 instructions should be replaced by plain mov's. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 +#define MEMLAT 2 + +#define start r15 +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define value1 r24 +#define value2 r25 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 + +ENTRY(memcmp) + .prologue + alloc r2 = ar.pfs, 3, 37, 0, 40 + + .rotr r[MEMLAT + 2], q[MEMLAT + 5], tmp1[4], tmp2[4], val[2] + .rotp p[MEMLAT + 4 + 1] + + mov ret0 = r0 /* by default return value = 0 */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov dest = in0 /* dest */ + mov src = in1 /* src */ + mov len = in2 /* len */ + sub tmp = r0, in0 /* tmp = -dest */ + ;; + and loopcnt = 7, tmp /* loopcnt = -dest % 8 */ + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ +(p6) br.cond.spnt .cmpfew /* compare byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value1 = [src], 1 /* value = *src++ */ + ld1 value2 = [dest], 1 + ;; + cmp.ne p6, p0 = value1, value2 +(p6) br.cond.spnt .done + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp = -8, len /* tmp = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* len = len % 8 */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + mov pr.rot = 1 << 16 ;; /* set rotating predicates */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + add src = src, tmp /* src += len & -OPSIZ */ + mov ar.ec = MEMLAT + 4 + 1 /* four more passes needed */ + ld8 r[1] = [asrc], 8 ;; /* r[1] = w0 */ + .align 32 + +/* We enter this loop with p6 cleared by the above comparison */ + +.l2: +(p[0]) ld8 r[0] = [asrc], 8 /* r[0] = w1 */ +(p[0]) ld8 q[0] = [dest], 8 +(p[MEMLAT]) shr.u tmp1[0] = r[1 + MEMLAT], sh1 /* tmp1 = w0 >> sh1 */ +(p[MEMLAT]) shl tmp2[0] = r[0 + MEMLAT], sh2 /* tmp2 = w1 << sh2 */ +(p[MEMLAT+4]) cmp.ne p6, p0 = q[MEMLAT + 4], val[1] +(p[MEMLAT+3]) or val[0] = tmp1[3], tmp2[3] /* val = tmp1 | tmp2 */ +(p6) br.cond.spnt .l2exit + br.ctop.sptk .l2 + br.cond.sptk .cmpfew +.l3exit: + mux1 value1 = r[MEMLAT], @rev + mux1 value2 = q[MEMLAT], @rev + cmp.ne p6, p0 = r0, r0 ;; /* clear p6 */ +.l2exit: +(p6) mux1 value1 = val[1], @rev +(p6) mux1 value2 = q[MEMLAT + 4], @rev ;; + cmp.ltu p6, p7 = value2, value1 ;; +(p6) mov ret0 = -1 +(p7) mov ret0 = 1 + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.src_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + mov ar.ec = MEMLAT + 1 ;; /* set EC */ +.l3: +(p[0]) ld8 r[0] = [src], 8 +(p[0]) ld8 q[0] = [dest], 8 +(p[MEMLAT]) cmp.ne p6, p0 = r[MEMLAT], q[MEMLAT] +(p6) br.cond.spnt .l3exit + br.ctop.dptk .l3 ;; +.cmpfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value1 = [src], 1 + ld1 value2 = [dest], 1 + ;; + cmp.ne p6, p0 = value1, value2 +(p6) br.cond.spnt .done + br.cloop.dptk .l4 ;; +.done: +(p6) sub ret0 = value2, value1 /* don't execute it if falling thru */ +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +END(memcmp) +libc_hidden_def (memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (memcmp, bcmp) +#endif diff --git a/libc/string/ia64/memcpy.S b/libc/string/ia64/memcpy.S new file mode 100644 index 0000000..6c48a72 --- /dev/null +++ b/libc/string/ia64/memcpy.S @@ -0,0 +1,436 @@ +/* Optimized version of the standard memcpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: byte count + + An assembly implementation of the algorithm used by the generic C + version from glibc. The case when source and sest are aligned is + treated separately, for extra performance. + + In this form, memcpy assumes little endian mode. For big endian mode, + sh1 must be computed using an extra instruction: sub sh1 = 64, sh1 + and the order of r[MEMLAT] and r[MEMLAT+1] must be reverted in the + shrp instruction. */ + +#define USE_LFETCH +#define USE_FLP +#include "sysdep.h" +#undef ret + +#define LFETCH_DIST 500 + +#define ALIGN_UNROLL_no 4 /* no. of elements */ +#define ALIGN_UNROLL_sh 2 /* (shift amount) */ + +#define MEMLAT 8 +#define Nrot ((4*(MEMLAT+2) + 7) & ~7) + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define loopcnt r14 +#define elemcnt r15 +#define saved_pr r16 +#define saved_lc r17 +#define adest r18 +#define dest r19 +#define asrc r20 +#define src r21 +#define len r22 +#define tmp2 r23 +#define tmp3 r24 +#define tmp4 r25 +#define ptable r26 +#define ploop56 r27 +#define loopaddr r28 +#define sh1 r29 +#define ptr1 r30 +#define ptr2 r31 + +#define movi0 mov + +#define p_scr p6 +#define p_xtr p7 +#define p_nxtr p8 +#define p_few p9 + +#if defined(USE_FLP) +#define load ldf8 +#define store stf8 +#define tempreg f6 +#define the_r fr +#define the_s fs +#define the_t ft +#define the_q fq +#define the_w fw +#define the_x fx +#define the_y fy +#define the_z fz +#elif defined(USE_INT) +#define load ld8 +#define store st8 +#define tempreg tmp2 +#define the_r r +#define the_s s +#define the_t t +#define the_q q +#define the_w w +#define the_x x +#define the_y y +#define the_z z +#endif + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +/* Manually force proper loop-alignment. Note: be sure to + double-check the code-layout after making any changes to + this routine! */ +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +#if defined(USE_LFETCH) +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +{ .mmb \ +(p[0]) ld8.nt1 r[0] = [asrc], 8 ; \ +(p[0]) lfetch.nt1 [ptr1], 16 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp3, 8 ; \ +(p[MEMLAT]) shrp tmp3 = r[MEMLAT], s[MEMLAT+1], shift ; \ + nop.b 0 ;; \ + } { .mmb \ +(p[0]) ld8.nt1 s[0] = [asrc], 8 ; \ +(p[0]) lfetch.nt1 [ptr2], 16 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp4, 8 ; \ +(p[MEMLAT]) shrp tmp4 = s[MEMLAT], r[MEMLAT], shift ; \ + br.ctop.sptk.many .loop##shift \ +;; } \ +{ .mib \ + br.cond.sptk.many .copy_bytes ; /* deal with the remaining bytes */ \ +} +#else +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +{ .mmb \ +(p[0]) ld8.nt1 r[0] = [asrc], 8 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp3, 8 ; \ +(p[MEMLAT]) shrp tmp3 = r[MEMLAT], s[MEMLAT+1], shift ; \ + nop.b 0 ;; \ + } { .mmb \ +(p[0]) ld8.nt1 s[0] = [asrc], 8 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp4, 8 ; \ +(p[MEMLAT]) shrp tmp4 = s[MEMLAT], r[MEMLAT], shift ; \ + br.ctop.sptk.many .loop##shift \ +;; } \ +{ .mib \ + br.cond.sptk.many .copy_bytes ; /* deal with the remaining bytes */ \ +} +#endif + + +ENTRY(memcpy) +{ .mmi + .prologue + alloc r2 = ar.pfs, 3, Nrot - 3, 0, Nrot + .rotr r[MEMLAT+1], s[MEMLAT+2], q[MEMLAT+1], t[MEMLAT+1] + .rotp p[MEMLAT+2] + .rotf fr[MEMLAT+1], fq[MEMLAT+1], fs[MEMLAT+1], ft[MEMLAT+1] + mov ret0 = in0 /* return tmp2 = dest */ + .save pr, saved_pr + movi0 saved_pr = pr /* save the predicate registers */ +} { .mmi + and tmp4 = 7, in0 /* check if destination is aligned */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ +;; } +{ .mii + cmp.eq p_scr, p0 = in2, r0 /* if (len == 0) */ + .save ar.lc, saved_lc + movi0 saved_lc = ar.lc /* save the loop counter */ + .body + cmp.ge p_few, p0 = OP_T_THRES, in2 /* is len <= OP_T_THRESH */ +} { .mbb + mov len = in2 /* len */ +(p_scr) br.cond.dpnt.few .restore_and_exit /* Branch no. 1: return dest */ +(p_few) br.cond.dpnt.many .copy_bytes /* Branch no. 2: copy byte by byte */ +;; } +{ .mmi +#if defined(USE_LFETCH) + lfetch.nt1 [dest] /* */ + lfetch.nt1 [src] /* */ +#endif + shr.u elemcnt = len, 3 /* elemcnt = len / 8 */ +} { .mib + cmp.eq p_scr, p0 = tmp4, r0 /* is destination aligned? */ + sub loopcnt = 7, tmp4 /* */ +(p_scr) br.cond.dptk.many .dest_aligned +;; } +{ .mmi + ld1 tmp2 = [src], 1 /* */ + sub len = len, loopcnt, 1 /* reduce len */ + movi0 ar.lc = loopcnt /* */ +} { .mib + cmp.ne p_scr, p0 = 0, loopcnt /* avoid loading beyond end-point */ +;; } + +.l0: /* ---------------------------- L0: Align src on 8-byte boundary */ +{ .mmi + st1 [dest] = tmp2, 1 /* */ +(p_scr) ld1 tmp2 = [src], 1 /* */ +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l0 /* */ +;; } + +.dest_aligned: +{ .mmi + and tmp4 = 7, src /* ready for alignment check */ + shr.u elemcnt = len, 3 /* elemcnt = len / 8 */ +;; } +{ .mib + cmp.ne p_scr, p0 = tmp4, r0 /* is source also aligned */ + tbit.nz p_xtr, p_nxtr = src, 3 /* prepare a separate move if src */ +} { .mib /* is not 16B aligned */ + add ptr2 = LFETCH_DIST, dest /* prefetch address */ + add ptr1 = LFETCH_DIST, src +(p_scr) br.cond.dptk.many .src_not_aligned +;; } + +/* The optimal case, when dest, and src are aligned */ + +.both_aligned: +{ .mmi + .pred.rel "mutex",p_xtr,p_nxtr +(p_xtr) cmp.gt p_scr, p0 = ALIGN_UNROLL_no+1, elemcnt /* Need N + 1 to qualify */ +(p_nxtr) cmp.gt p_scr, p0 = ALIGN_UNROLL_no, elemcnt /* Need only N to qualify */ + movi0 pr.rot = 1 << 16 /* set rotating predicates */ +} { .mib +(p_scr) br.cond.dpnt.many .copy_full_words +;; } + +{ .mmi +(p_xtr) load tempreg = [src], 8 +(p_xtr) add elemcnt = -1, elemcnt + movi0 ar.ec = MEMLAT + 1 /* set the epilog counter */ +;; } +{ .mmi +(p_xtr) add len = -8, len /* */ + add asrc = 16, src /* one bank apart (for USE_INT) */ + shr.u loopcnt = elemcnt, ALIGN_UNROLL_sh /* cater for unrolling */ +;;} +{ .mmi + add loopcnt = -1, loopcnt +(p_xtr) store [dest] = tempreg, 8 /* copy the "extra" word */ + nop.i 0 +;; } +{ .mib + add adest = 16, dest + movi0 ar.lc = loopcnt /* set the loop counter */ +;; } + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO + { nop 0 } +#else + .align 32 +#endif +#if defined(USE_FLP) +.l1: /* ------------------------------- L1: Everything a multiple of 8 */ +{ .mmi +#if defined(USE_LFETCH) +(p[0]) lfetch.nt1 [ptr2],32 +#endif +(p[0]) ldfp8 the_r[0],the_q[0] = [src], 16 +(p[0]) add len = -32, len +} {.mmb +(p[MEMLAT]) store [dest] = the_r[MEMLAT], 8 +(p[MEMLAT]) store [adest] = the_s[MEMLAT], 8 +;; } +{ .mmi +#if defined(USE_LFETCH) +(p[0]) lfetch.nt1 [ptr1],32 +#endif +(p[0]) ldfp8 the_s[0], the_t[0] = [src], 16 +} {.mmb +(p[MEMLAT]) store [dest] = the_q[MEMLAT], 24 +(p[MEMLAT]) store [adest] = the_t[MEMLAT], 24 + br.ctop.dptk.many .l1 +;; } +#elif defined(USE_INT) +.l1: /* ------------------------------- L1: Everything a multiple of 8 */ +{ .mmi +(p[0]) load the_r[0] = [src], 8 +(p[0]) load the_q[0] = [asrc], 8 +(p[0]) add len = -32, len +} {.mmb +(p[MEMLAT]) store [dest] = the_r[MEMLAT], 8 +(p[MEMLAT]) store [adest] = the_q[MEMLAT], 8 +;; } +{ .mmi +(p[0]) load the_s[0] = [src], 24 +(p[0]) load the_t[0] = [asrc], 24 +} {.mmb +(p[MEMLAT]) store [dest] = the_s[MEMLAT], 24 +(p[MEMLAT]) store [adest] = the_t[MEMLAT], 24 +#if defined(USE_LFETCH) +;; } +{ .mmb +(p[0]) lfetch.nt1 [ptr2],32 +(p[0]) lfetch.nt1 [ptr1],32 +#endif + br.ctop.dptk.many .l1 +;; } +#endif + +.copy_full_words: +{ .mib + cmp.gt p_scr, p0 = 8, len /* */ + shr.u elemcnt = len, 3 /* */ +(p_scr) br.cond.dpnt.many .copy_bytes +;; } +{ .mii + load tempreg = [src], 8 + add loopcnt = -1, elemcnt /* */ +;; } +{ .mii + cmp.ne p_scr, p0 = 0, loopcnt /* */ + mov ar.lc = loopcnt /* */ +;; } + +.l2: /* ------------------------------- L2: Max 4 words copied separately */ +{ .mmi + store [dest] = tempreg, 8 +(p_scr) load tempreg = [src], 8 /* */ + add len = -8, len +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l2 +;; } + +.copy_bytes: +{ .mib + cmp.eq p_scr, p0 = len, r0 /* is len == 0 ? */ + add loopcnt = -1, len /* len--; */ +(p_scr) br.cond.spnt .restore_and_exit +;; } +{ .mii + ld1 tmp2 = [src], 1 + movi0 ar.lc = loopcnt + cmp.ne p_scr, p0 = 0, loopcnt /* avoid load beyond end-point */ +;; } + +.l3: /* ------------------------------- L3: Final byte move */ +{ .mmi + st1 [dest] = tmp2, 1 +(p_scr) ld1 tmp2 = [src], 1 +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l3 +;; } + +.restore_and_exit: +{ .mmi + movi0 pr = saved_pr, -1 /* restore the predicate registers */ +;; } +{ .mib + movi0 ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +;; } + + +.src_not_aligned: +{ .mmi + cmp.gt p_scr, p0 = 16, len + and sh1 = 7, src /* sh1 = src % 8 */ + shr.u loopcnt = len, 4 /* element-cnt = len / 16 */ +} { .mib + add tmp4 = @ltoff(.table), gp + add tmp3 = @ltoff(.loop56), gp +(p_scr) br.cond.dpnt.many .copy_bytes /* do byte by byte if too few */ +;; } +{ .mmi + and asrc = -8, src /* asrc = (-8) -- align src for loop */ + add loopcnt = -1, loopcnt /* loopcnt-- */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ +} { .mmi + ld8 ptable = [tmp4] /* ptable = &table */ + ld8 ploop56 = [tmp3] /* ploop56 = &loop56 */ + and tmp2 = -16, len /* tmp2 = len & -OPSIZ */ +;; } +{ .mmi + add tmp3 = ptable, sh1 /* tmp3 = &table + sh1 */ + add src = src, tmp2 /* src += len & (-16) */ + movi0 ar.lc = loopcnt /* set LC */ +;; } +{ .mmi + ld8 tmp4 = [tmp3] /* tmp4 = loop offset */ + sub len = len, tmp2 /* len -= len & (-16) */ + movi0 ar.ec = MEMLAT + 2 /* one more pass needed */ +;; } +{ .mmi + ld8 s[1] = [asrc], 8 /* preload */ + sub loopaddr = ploop56,tmp4 /* loopadd = &loop56 - loop offset */ + movi0 pr.rot = 1 << 16 /* set rotating predicates */ +;; } +{ .mib + nop.m 0 + movi0 b6 = loopaddr + br b6 /* jump to the appropriate loop */ +;; } + + LOOP(8) + LOOP(16) + LOOP(24) + LOOP(32) + LOOP(40) + LOOP(48) + LOOP(56) +END(memcpy) +libc_hidden_def (memcpy) + + .rodata + .align 8 +.table: + data8 0 /* dummy entry */ + data8 .loop56 - .loop8 + data8 .loop56 - .loop16 + data8 .loop56 - .loop24 + data8 .loop56 - .loop32 + data8 .loop56 - .loop40 + data8 .loop56 - .loop48 + data8 .loop56 - .loop56 diff --git a/libc/string/ia64/memmove.S b/libc/string/ia64/memmove.S new file mode 100644 index 0000000..beaada6 --- /dev/null +++ b/libc/string/ia64/memmove.S @@ -0,0 +1,251 @@ +/* Optimized version of the standard memmove() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: byte count + + The core of the function is the memcpy implementation used in memcpy.S. + When bytes have to be copied backwards, only the easy case, when + all arguments are multiples of 8, is optimised. + + In this form, it assumes little endian mode. For big endian mode, + sh1 must be computed using an extra instruction: sub sh1 = 64, sh1 + or the UM.be bit should be cleared at the beginning and set at the end. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define adest r15 +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp2 r23 +#define tmp3 r24 +#define tmp4 r25 +#define ptable r26 +#define ploop56 r27 +#define loopaddr r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +(p[0]) ld8 r[0] = [asrc], 8 ; /* w1 */ \ +(p[MEMLAT+1]) st8 [dest] = value, 8 ; \ +(p[MEMLAT]) shrp value = r[MEMLAT], r[MEMLAT+1], shift ; \ + nop.b 0 ; \ + nop.b 0 ; \ + br.ctop.sptk .loop##shift ; \ + br.cond.sptk .cpyfew ; /* deal with the remaining bytes */ + +#define MEMLAT 21 +#define Nrot (((2*MEMLAT+3) + 7) & ~7) + +ENTRY(memmove) + .prologue + alloc r2 = ar.pfs, 3, Nrot - 3, 0, Nrot + .rotr r[MEMLAT + 2], q[MEMLAT + 1] + .rotp p[MEMLAT + 2] + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + or tmp3 = in0, in1 ;; /* tmp3 = dest | src */ + or tmp3 = tmp3, in2 /* tmp3 = dest | src | len */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + mov len = in2 /* len */ + sub tmp2 = r0, in0 /* tmp2 = -dest */ + cmp.eq p6, p0 = in2, r0 /* if (len == 0) */ +(p6) br.cond.spnt .restore_and_exit;;/* return dest; */ + and tmp4 = 7, tmp3 /* tmp4 = (dest | src | len) & 7 */ + cmp.le p6, p0 = dest, src /* if dest <= src it's always safe */ +(p6) br.cond.spnt .forward /* to copy forward */ + add tmp3 = src, len;; + cmp.lt p6, p0 = dest, tmp3 /* if dest > src && dest < src + len */ +(p6) br.cond.spnt .backward /* we have to copy backward */ + +.forward: + shr.u loopcnt = len, 4 ;; /* loopcnt = len / 16 */ + cmp.ne p6, p0 = tmp4, r0 /* if ((dest | src | len) & 7 != 0) */ +(p6) br.cond.sptk .next /* goto next; */ + +/* The optimal case, when dest, src and len are all multiples of 8 */ + + and tmp3 = 0xf, len + mov pr.rot = 1 << 16 /* set rotating predicates */ + mov ar.ec = MEMLAT + 1 ;; /* set the epilog counter */ + cmp.ne p6, p0 = tmp3, r0 /* do we have to copy an extra word? */ + adds loopcnt = -1, loopcnt;; /* --loopcnt */ +(p6) ld8 value = [src], 8;; +(p6) st8 [dest] = value, 8 /* copy the "odd" word */ + mov ar.lc = loopcnt /* set the loop counter */ + cmp.eq p6, p0 = 8, len +(p6) br.cond.spnt .restore_and_exit;;/* the one-word special case */ + adds adest = 8, dest /* set adest one word ahead of dest */ + adds asrc = 8, src ;; /* set asrc one word ahead of src */ + nop.b 0 /* get the "golden" alignment for */ + nop.b 0 /* the next loop */ +.l0: +(p[0]) ld8 r[0] = [src], 16 +(p[0]) ld8 q[0] = [asrc], 16 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 16 +(p[MEMLAT]) st8 [adest] = q[MEMLAT], 16 + br.ctop.dptk .l0 ;; + + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.next: + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ + and loopcnt = 7, tmp2 /* loopcnt = -dest % 8 */ +(p6) br.cond.spnt .cpyfew /* copy byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value = [src], 1 /* value = *src++ */ + ;; + st1 [dest] = value, 1 /* *dest++ = value */ + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp2 = -8, len /* tmp2 = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len;; /* len = len % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + addl tmp4 = @ltoff(.table), gp + addl tmp3 = @ltoff(.loop56), gp + mov ar.ec = MEMLAT + 1 /* set EC */ + mov pr.rot = 1 << 16;; /* set rotating predicates */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + add src = src, tmp2 /* src += len & -OPSIZ */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + ld8 ploop56 = [tmp3] /* ploop56 = &loop56 */ + ld8 ptable = [tmp4];; /* ptable = &table */ + add tmp3 = ptable, sh1;; /* tmp3 = &table + sh1 */ + mov ar.ec = MEMLAT + 1 + 1 /* one more pass needed */ + ld8 tmp4 = [tmp3];; /* tmp4 = loop offset */ + sub loopaddr = ploop56,tmp4 /* loopadd = &loop56 - loop offset */ + ld8 r[1] = [asrc], 8;; /* w0 */ + mov b6 = loopaddr;; + br b6 /* jump to the appropriate loop */ + + LOOP(8) + LOOP(16) + LOOP(24) + LOOP(32) + LOOP(40) + LOOP(48) + LOOP(56) + +.src_aligned: +.l3: +(p[0]) ld8 r[0] = [src], 8 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 +.cpyfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value = [src], 1 + ;; + st1 [dest] = value, 1 + br.cloop.dptk .l4 ;; +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 + +/* In the case of a backward copy, optimise only the case when everything + is a multiple of 8, otherwise copy byte by byte. The backward copy is + used only when the blocks are overlapping and dest > src. +*/ +.backward: + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + add src = src, len /* src points one byte past the end */ + add dest = dest, len ;; /* dest points one byte past the end */ + mov ar.ec = MEMLAT + 1 /* set the epilog counter */ + mov pr.rot = 1 << 16 /* set rotating predicates */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + cmp.ne p6, p0 = tmp4, r0 /* if ((dest | src | len) & 7 != 0) */ +(p6) br.cond.sptk .bytecopy ;; /* copy byte by byte backward */ + adds src = -8, src /* src points to the last word */ + adds dest = -8, dest /* dest points to the last word */ + mov ar.lc = loopcnt;; /* set the loop counter */ +.l5: +(p[0]) ld8 r[0] = [src], -8 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], -8 + br.ctop.dptk .l5 + br.cond.sptk .restore_and_exit +.bytecopy: + adds src = -1, src /* src points to the last byte */ + adds dest = -1, dest /* dest points to the last byte */ + adds loopcnt = -1, len;; /* loopcnt = len - 1 */ + mov ar.lc = loopcnt;; /* set the loop counter */ +.l6: +(p[0]) ld1 r[0] = [src], -1 +(p[MEMLAT]) st1 [dest] = r[MEMLAT], -1 + br.ctop.dptk .l6 + br.cond.sptk .restore_and_exit +END(memmove) + + .rodata + .align 8 +.table: + data8 0 /* dummy entry */ + data8 .loop56 - .loop8 + data8 .loop56 - .loop16 + data8 .loop56 - .loop24 + data8 .loop56 - .loop32 + data8 .loop56 - .loop40 + data8 .loop56 - .loop48 + data8 .loop56 - .loop56 + +libc_hidden_def (memmove) diff --git a/libc/string/ia64/memset.S b/libc/string/ia64/memset.S new file mode 100644 index 0000000..45df583 --- /dev/null +++ b/libc/string/ia64/memset.S @@ -0,0 +1,400 @@ +/* Optimized version of the standard memset() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: value + in2: count + + The algorithm is fairly straightforward: set byte by byte until we + we get to a 16B-aligned address, then loop on 128 B chunks using an + early store as prefetching, then loop on 32B chucks, then clear remaining + words, finally clear remaining bytes. + Since a stf.spill f0 can store 16B in one go, we use this instruction + to get peak speed when value = 0. */ + +#include "sysdep.h" +#undef ret + +#define dest in0 +#define value in1 +#define cnt in2 + +#define tmp r31 +#define save_lc r30 +#define ptr0 r29 +#define ptr1 r28 +#define ptr2 r27 +#define ptr3 r26 +#define ptr9 r24 +#define loopcnt r23 +#define linecnt r22 +#define bytecnt r21 + +#define fvalue f6 + +/* This routine uses only scratch predicate registers (p6 - p15) */ +#define p_scr p6 /* default register for same-cycle branches */ +#define p_nz p7 +#define p_zr p8 +#define p_unalgn p9 +#define p_y p11 +#define p_n p12 +#define p_yy p13 +#define p_nn p14 + +#define movi0 mov + +#define MIN1 15 +#define MIN1P1HALF 8 +#define LINE_SIZE 128 +#define LSIZE_SH 7 /* shift amount */ +#define PREF_AHEAD 8 + +#define USE_FLP +#if defined(USE_INT) +#define store st8 +#define myval value +#elif defined(USE_FLP) +#define store stf8 +#define myval fvalue +#endif + +.align 64 +ENTRY(memset) +{ .mmi + .prologue + alloc tmp = ar.pfs, 3, 0, 0, 0 + lfetch.nt1 [dest] + .save ar.lc, save_lc + movi0 save_lc = ar.lc +} { .mmi + .body + mov ret0 = dest /* return value */ + cmp.ne p_nz, p_zr = value, r0 /* use stf.spill if value is zero */ + cmp.eq p_scr, p0 = cnt, r0 +;; } +{ .mmi + and ptr2 = -(MIN1+1), dest /* aligned address */ + and tmp = MIN1, dest /* prepare to check for alignment */ + tbit.nz p_y, p_n = dest, 0 /* Do we have an odd address? (M_B_U) */ +} { .mib + mov ptr1 = dest + mux1 value = value, @brcst /* create 8 identical bytes in word */ +(p_scr) br.ret.dpnt.many rp /* return immediately if count = 0 */ +;; } +{ .mib + cmp.ne p_unalgn, p0 = tmp, r0 +} { .mib /* NB: # of bytes to move is 1 higher */ + sub bytecnt = (MIN1+1), tmp /* than loopcnt */ + cmp.gt p_scr, p0 = 16, cnt /* is it a minimalistic task? */ +(p_scr) br.cond.dptk.many .move_bytes_unaligned /* go move just a few (M_B_U) */ +;; } +{ .mmi +(p_unalgn) add ptr1 = (MIN1+1), ptr2 /* after alignment */ +(p_unalgn) add ptr2 = MIN1P1HALF, ptr2 /* after alignment */ +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 3 /* should we do a st8 ? */ +;; } +{ .mib +(p_y) add cnt = -8, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 2 /* should we do a st4 ? */ +} { .mib +(p_y) st8 [ptr2] = value, -4 +(p_n) add ptr2 = 4, ptr2 +;; } +{ .mib +(p_yy) add cnt = -4, cnt +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 1 /* should we do a st2 ? */ +} { .mib +(p_yy) st4 [ptr2] = value, -2 +(p_nn) add ptr2 = 2, ptr2 +;; } +{ .mmi + mov tmp = LINE_SIZE+1 /* for compare */ +(p_y) add cnt = -2, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 0 /* should we do a st1 ? */ +} { .mmi + setf.sig fvalue=value /* transfer value to FLP side */ +(p_y) st2 [ptr2] = value, -1 +(p_n) add ptr2 = 1, ptr2 +;; } + +{ .mmi +(p_yy) st1 [ptr2] = value + cmp.gt p_scr, p0 = tmp, cnt /* is it a minimalistic task? */ +} { .mbb +(p_yy) add cnt = -1, cnt +(p_scr) br.cond.dpnt.many .fraction_of_line /* go move just a few */ +;; } + +{ .mib + nop.m 0 + shr.u linecnt = cnt, LSIZE_SH +(p_zr) br.cond.dptk.many .l1b /* Jump to use stf.spill */ +;; } + +#ifndef GAS_ALIGN_BREAKS_UNWIND_INFO + .align 32 /* -------- L1A: store ahead into cache lines; fill later */ +#endif +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt /* start of stores */ + add ptr2 = 8, ptr1 /* (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total */ +;; } /* range */ +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1a: +{ .mib + store [ptr9] = myval, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1a +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1ax: + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 32 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + store [ptr2] = myval, 24 +(p_scr) store [ptr9] = myval, 128 + br.cloop.dptk.few .l1ax +;; } +{ .mbb + cmp.le p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .fraction_of_line /* Branch no. 2 */ + br.cond.dpnt.many .move_bytes_from_alignment /* Branch no. 3 */ +;; } + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO + { nop 0 } +#else + .align 32 +#endif +.l1b: /* ------------------ L1B: store ahead into cache lines; fill later */ +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt + add ptr2 = 16, ptr1 /* start of stores (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total range */ +;; } +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1b: +{ .mib + stf.spill [ptr9] = f0, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1b +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1bx: + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 64 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + stf.spill [ptr2] = f0, 32 +(p_scr) stf.spill [ptr9] = f0, 128 + br.cloop.dptk.few .l1bx +;; } +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment +;; } + +.fraction_of_line: +{ .mib + add ptr2 = 16, ptr1 + shr.u loopcnt = cnt, 5 /* loopcnt = cnt / 32 */ +;; } +{ .mib + cmp.eq p_scr, p0 = loopcnt, r0 + add loopcnt = -1, loopcnt +(p_scr) br.cond.dpnt.many store_words +;; } +{ .mib + and cnt = 0x1f, cnt /* compute the remaining cnt */ + movi0 ar.lc = loopcnt +;; } +#ifndef GAS_ALIGN_BREAKS_UNWIND_INFO + .align 32 +#endif +.l2: /* ---------------------------- L2A: store 32B in 2 cycles */ +{ .mmb + store [ptr1] = myval, 8 + store [ptr2] = myval, 8 +;; } { .mmb + store [ptr1] = myval, 24 + store [ptr2] = myval, 24 + br.cloop.dptk.many .l2 +;; } +store_words: +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment /* Branch */ +;; } + +{ .mmi + store [ptr1] = myval, 8 /* store */ + cmp.le p_y, p_n = 16, cnt /* */ + add cnt = -8, cnt /* subtract */ +;; } +{ .mmi +(p_y) store [ptr1] = myval, 8 /* store */ +(p_y) cmp.le.unc p_yy, p_nn = 16, cnt /* */ +(p_y) add cnt = -8, cnt /* subtract */ +;; } +{ .mmi /* store */ +(p_yy) store [ptr1] = myval, 8 /* */ +(p_yy) add cnt = -8, cnt /* subtract */ +;; } + +.move_bytes_from_alignment: +{ .mib + cmp.eq p_scr, p0 = cnt, r0 + tbit.nz.unc p_y, p0 = cnt, 2 /* should we terminate with a st4 ? */ +(p_scr) br.cond.dpnt.few .restore_and_exit +;; } +{ .mib +(p_y) st4 [ptr1] = value, 4 + tbit.nz.unc p_yy, p0 = cnt, 1 /* should we terminate with a st2 ? */ +;; } +{ .mib +(p_yy) st2 [ptr1] = value, 2 + tbit.nz.unc p_y, p0 = cnt, 0 +;; } + +{ .mib +(p_y) st1 [ptr1] = value +;; } +.restore_and_exit: +{ .mib + nop.m 0 + movi0 ar.lc = save_lc + br.ret.sptk.many rp +;; } + +.move_bytes_unaligned: +{ .mmi + .pred.rel "mutex",p_y, p_n + .pred.rel "mutex",p_yy, p_nn +(p_n) cmp.le p_yy, p_nn = 4, cnt +(p_y) cmp.le p_yy, p_nn = 5, cnt +(p_n) add ptr2 = 2, ptr1 +} { .mmi +(p_y) add ptr2 = 3, ptr1 +(p_y) st1 [ptr1] = value, 1 /* fill 1 (odd-aligned) byte */ +(p_y) add cnt = -1, cnt /* [15, 14 (or less) left] */ +;; } +{ .mmi +(p_yy) cmp.le.unc p_y, p0 = 8, cnt + add ptr3 = ptr1, cnt /* prepare last store */ + movi0 ar.lc = save_lc +} { .mmi +(p_yy) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) add cnt = -4, cnt /* [11, 10 (o less) left] */ +;; } +{ .mmi +(p_y) cmp.le.unc p_yy, p0 = 8, cnt + add ptr3 = -1, ptr3 /* last store */ + tbit.nz p_scr, p0 = cnt, 1 /* will there be a st2 at the end ? */ +} { .mmi +(p_y) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_y) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ +(p_y) add cnt = -4, cnt /* [7, 6 (or less) left] */ +;; } +{ .mmi +(p_yy) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ + /* [3, 2 (or less) left] */ + tbit.nz p_y, p0 = cnt, 0 /* will there be a st1 at the end ? */ +} { .mmi +(p_yy) add cnt = -4, cnt +;; } +{ .mmb +(p_scr) st2 [ptr1] = value /* fill 2 (aligned) bytes */ +(p_y) st1 [ptr3] = value /* fill last byte (using ptr3) */ + br.ret.sptk.many rp +;; } +END(memset) +libc_hidden_def (memset) diff --git a/libc/string/ia64/softpipe.h b/libc/string/ia64/softpipe.h new file mode 100644 index 0000000..d71af73 --- /dev/null +++ b/libc/string/ia64/softpipe.h @@ -0,0 +1,29 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2000 Free Software Foundation, Inc. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The latency of a memory load assumed by the assembly implementation + of the mem and str functions. Since we don't have any clue about + where the data might be, let's assume it's in the L2 cache. + Assuming L3 would be too pessimistic :-) + + Some functions define MEMLAT as 2, because they expect their data + to be in the L1D cache. */ + +#ifndef MEMLAT +# define MEMLAT 6 +#endif diff --git a/libc/string/ia64/strchr.S b/libc/string/ia64/strchr.S new file mode 100644 index 0000000..66703f2 --- /dev/null +++ b/libc/string/ia64/strchr.S @@ -0,0 +1,113 @@ +/* Optimized version of the standard strchr() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the address of the first occurence of chr in str or NULL + + Inputs: + in0: str + in1: chr + + A modified version of memchr.S, the search ends when the character is + found or the terminating null character is encountered. + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r18 +#define poschr r19 +#define pos0 r20 +#define val1 r21 +#define val2 r22 +#define tmp r24 +#define chrx8 r25 +#define loopcnt r30 + +#define str in0 +#define chr in1 + +ENTRY(strchr) + .prologue + alloc r2 = ar.pfs, 2, 0, 0, 0 + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov ret0 = str + and tmp = 7, str /* tmp = str % 8 */ + mux1 chrx8 = chr, @brcst + extr.u chr = chr, 0, 8 /* retain only the last byte */ + cmp.ne p8, p0 = r0, r0 /* clear p8 */ + ;; + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val2 = [ret0], 1 + ;; + cmp.eq p6, p0 = val2, chr + cmp.eq p7, p0 = val2, r0 +(p6) br.cond.spnt .restore_and_exit +(p7) br.cond.spnt .notfound + br.cloop.sptk .l1 +.str_aligned: + ld8 val1 = [ret0], 8;; + nop.b 0 + nop.b 0 +.l2: + ld8.s val2 = [ret0], 8 /* don't bomb out here */ + czx1.r pos0 = val1 + xor tmp = val1, chrx8 /* if val1 contains chr, tmp will */ + ;; /* contain a zero in its position */ + czx1.r poschr = tmp + cmp.ne p6, p0 = 8, pos0 + ;; + cmp.ne p7, p0 = 8, poschr +(p7) br.cond.spnt .foundit +(p6) br.cond.spnt .notfound + chk.s val2, .recovery +.back: + mov val1 = val2 + br.cond.dptk .l2 +.foundit: +(p6) cmp.lt p8, p0 = pos0, poschr /* we found chr and null in the word */ +(p8) br.cond.spnt .notfound /* null was found before chr */ + add ret0 = ret0, poschr ;; + adds ret0 = -15, ret0 ;; /* should be -16, but we decrement */ +.restore_and_exit: /* ret0 in the next instruction */ + adds ret0 = -1, ret0 /* ret0 was pointing 1 char too far */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.notfound: + mov ret0 = r0 /* return NULL if null was found */ + mov ar.lc = saved_lc + br.ret.sptk.many b0 +.recovery: + adds ret0 = -8, ret0;; + ld8 val2 = [ret0], 8 /* bomb out here */ + br.cond.sptk .back +END(strchr) +libc_hidden_def (strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (strchr, index) +#endif diff --git a/libc/string/ia64/strcmp.S b/libc/string/ia64/strcmp.S new file mode 100644 index 0000000..4da72fa --- /dev/null +++ b/libc/string/ia64/strcmp.S @@ -0,0 +1,59 @@ +/* Optimized version of the standard strcmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: s1 + in1: s2 + + Unlike memcmp(), this function is optimized for mismatches within the + first few characters. */ + +#include "sysdep.h" +#undef ret + +#define s1 in0 +#define s2 in1 + +#define val1 r15 +#define val2 r16 + + +ENTRY(strcmp) + alloc r2 = ar.pfs, 2, 0, 0, 0 +.loop: + ld1 val1 = [s1], 1 + ld1 val2 = [s2], 1 + cmp.eq p6, p0 = r0, r0 /* set p6 */ + ;; + cmp.ne.and p6, p0 = val1, r0 + cmp.ne.and p6, p0 = val2, r0 + cmp.eq.and p6, p0 = val1, val2 +(p6) br.cond.sptk .loop + sub ret0 = val1, val2 + br.ret.sptk.many b0 +END(strcmp) +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/ia64/strcpy.S b/libc/string/ia64/strcpy.S new file mode 100644 index 0000000..7b002f6 --- /dev/null +++ b/libc/string/ia64/strcpy.S @@ -0,0 +1,145 @@ +/* Optimized version of the standard strcpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + + In this form, it assumes little endian mode. For big endian mode, the + the two shifts in .l2 must be inverted: + + shl value = r[1], sh1 // value = w0 << sh1 + shr.u tmp = r[0], sh2 // tmp = w1 >> sh2 + */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r15 +#define saved_pr r16 +#define thresh r17 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define pos r24 +#define w0 r25 +#define w1 r26 +#define c r27 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +ENTRY(strcpy) + .prologue + alloc r2 = ar.pfs, 2, 0, 30, 32 + +#define MEMLAT 2 + .rotr r[MEMLAT + 2] + .rotp p[MEMLAT + 1] + + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + sub tmp = r0, in0 ;; /* tmp = -dest */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + and loopcnt = 7, tmp ;; /* loopcnt = -dest % 8 */ + cmp.eq p6, p0 = loopcnt, r0 + adds loopcnt = -1, loopcnt /* --loopcnt */ +(p6) br.cond.sptk .dest_aligned ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 c = [src], 1 /* c = *src++ */ + ;; + st1 [dest] = c, 1 /* *dest++ = c */ + cmp.eq p6, p0 = c, r0 +(p6) br.cond.dpnt .restore_and_exit + br.cloop.dptk .l1 ;; +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + mov ar.lc = -1 /* "infinite" loop */ + and asrc = -8, src ;; /* asrc = src & -OPSIZ -- align src */ + sub thresh = 8, sh1 + mov pr.rot = 1 << 16 /* set rotating predicates */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + shl sh1 = sh1, 3 ;; /* sh1 = 8 * (src % 8) */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned ;; + ld8 r[1] = [asrc],8 ;; + + .align 32 +.l2: + ld8.s r[0] = [asrc], 8 + shr.u value = r[1], sh1 ;; /* value = w0 >> sh1 */ + czx1.r pos = value ;; /* do we have an "early" zero */ + cmp.lt p7, p0 = pos, thresh /* in w0 >> sh1? */ +(p7) br.cond.dpnt .found0 + chk.s r[0], .recovery2 /* it is safe to do that only */ +.back2: /* after the previous test */ + shl tmp = r[0], sh2 /* tmp = w1 << sh2 */ + ;; + or value = value, tmp ;; /* value |= tmp */ + czx1.r pos = value ;; + cmp.ne p7, p0 = 8, pos +(p7) br.cond.dpnt .found0 + st8 [dest] = value, 8 /* store val to dest */ + br.ctop.dptk .l2 ;; +.src_aligned: +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) chk.s r[MEMLAT], .recovery3 +.back3: +(p[MEMLAT]) mov value = r[MEMLAT] +(p[MEMLAT]) czx1.r pos = r[MEMLAT] ;; +(p[MEMLAT]) cmp.ne p7, p0 = 8, pos +(p7) br.cond.dpnt .found0 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 ;; +.found0: + mov ar.lc = pos +.l4: + extr.u c = value, 0, 8 /* c = value & 0xff */ + shr.u value = value, 8 + ;; + st1 [dest] = c, 1 + br.cloop.dptk .l4 ;; +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 +.recovery2: + add tmp = -8, asrc ;; + ld8 r[0] = [tmp] + br.cond.sptk .back2 +.recovery3: + add tmp = -(MEMLAT + 1) * 8, src ;; + ld8 r[MEMLAT] = [tmp] + br.cond.sptk .back3 +END(strcpy) +libc_hidden_def (strcpy) diff --git a/libc/string/ia64/strlen.S b/libc/string/ia64/strlen.S new file mode 100644 index 0000000..edbe843 --- /dev/null +++ b/libc/string/ia64/strlen.S @@ -0,0 +1,98 @@ +/* Optimized version of the standard strlen() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the length of the input string + + Input: + in0: str + + Look for the null character byte by byte, until we reach a word aligned + address, then search word by word, using the czx instruction. We're + also doing one word of read ahead, which could cause problems if the + null character is on the last word of a page and the next page is not + mapped in the process address space. Hence the use of the speculative + load. + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r18 +#define str r19 +#define pos0 r20 +#define val1 r21 +#define val2 r22 +#define origadd r23 +#define tmp r24 +#define loopcnt r30 +#define len ret0 + +ENTRY(strlen) + .prologue + alloc r2 = ar.pfs, 1, 0, 0, 0 + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov str = in0 + mov len = r0 /* len = 0 */ + and tmp = 7, in0 /* tmp = str % 8 */ + ;; + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val2 = [str], 1 + ;; + cmp.eq p6, p0 = val2, r0 +(p6) br.cond.spnt .restore_and_exit + adds len = 1, len + br.cloop.dptk .l1 +.str_aligned: + mov origadd = str /* origadd = orig */ + ld8 val1 = [str], 8;; + nop.b 0 + nop.b 0 +.l2: ld8.s val2 = [str], 8 /* don't bomb out here */ + czx1.r pos0 = val1 + ;; + cmp.ne p6, p0 = 8, pos0 +(p6) br.cond.spnt .foundit + chk.s val2, .recovery +.back: + mov val1 = val2 + br.cond.dptk .l2 +.foundit: + sub tmp = str, origadd /* tmp = crt address - orig */ + add len = len, pos0;; + add len = len, tmp;; + adds len = -16, len +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.recovery: + adds str = -8, str;; + ld8 val2 = [str], 8 /* bomb out here */ + br.cond.sptk .back +END(strlen) +libc_hidden_def (strlen) diff --git a/libc/string/ia64/strncmp.S b/libc/string/ia64/strncmp.S new file mode 100644 index 0000000..e31f8fb --- /dev/null +++ b/libc/string/ia64/strncmp.S @@ -0,0 +1,62 @@ +/* Optimized version of the standard strncmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: s1 + in1: s2 + in2: n + + Unlike memcmp(), this function is optimized for mismatches within the + first few characters. */ + +#include "sysdep.h" +#undef ret + +#define s1 in0 +#define s2 in1 +#define n in2 + +#define val1 r15 +#define val2 r16 + + +ENTRY(strncmp) + alloc r2 = ar.pfs, 3, 0, 0, 0 + mov ret0 = r0 + cmp.eq p6, p0 = r0, r0 /* set p6 */ + cmp.eq p7, p0 = n, r0 /* return immediately if n == 0 */ +(p7) br.cond.spnt .restore_and_exit ;; +.loop: + ld1 val1 = [s1], 1 + ld1 val2 = [s2], 1 + adds n = -1, n /* n-- */ + ;; + cmp.ne.and p6, p0 = val1, r0 + cmp.ne.and p6, p0 = val2, r0 + cmp.ne.and p6, p0 = n, r0 + cmp.eq.and p6, p0 = val1, val2 +(p6) br.cond.sptk .loop + sub ret0 = val1, val2 +.restore_and_exit: + br.ret.sptk.many b0 +END(strncmp) +libc_hidden_weak (strncmp) diff --git a/libc/string/ia64/strncpy.S b/libc/string/ia64/strncpy.S new file mode 100644 index 0000000..3f29bbd --- /dev/null +++ b/libc/string/ia64/strncpy.S @@ -0,0 +1,232 @@ +/* Optimized version of the standard strncpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop + and Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: len + + In this form, it assumes little endian mode. + */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r15 +#define saved_pr r16 +#define thresh r17 +#define dest r18 +#define dest2 r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define pos r24 +#define w0 r25 +#define w1 r26 +#define c r27 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +ENTRY(strncpy) + .prologue + alloc r2 = ar.pfs, 3, 0, 29, 32 + +#define MEMLAT 2 + .rotr r[MEMLAT + 2] + .rotp p[MEMLAT + 1] + + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + mov ar.ec = 0 /* ec is not guaranteed to */ + /* be zero upon function entry */ + .body + cmp.geu p6, p5 = 24, in2 +(p6) br.cond.spnt .short_len + sub tmp = r0, in0 ;; /* tmp = -dest */ + mov len = in2 /* len */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + and tmp = 7, tmp ;; /* loopcnt = -dest % 8 */ + cmp.eq p6, p7 = tmp, r0 + adds loopcnt = -1, tmp /* --loopcnt */ +(p6) br.cond.sptk .dest_aligned ;; + sub len = len, tmp /* len -= -dest % 8 */ + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ +(p5) ld1 c = [src], 1 /* c = *src++ */ + ;; + st1 [dest] = c, 1 /* *dest++ = c */ + cmp.ne p5, p7 = c, r0 + br.cloop.dptk .l1 ;; +(p7) br.cond.dpnt .found0_align + +.dest_aligned: /* p7 should be cleared here */ + shr.u c = len, 3 /* c = len / 8 */ + and sh1 = 7, src /* sh1 = src % 8 */ + and asrc = -8, src ;; /* asrc = src & -OPSIZ -- align src */ + adds c = (MEMLAT-1), c /* c = (len / 8) + MEMLAT - 1 */ + sub thresh = 8, sh1 + mov pr.rot = 1 << 16 /* set rotating predicates */ + shl sh1 = sh1, 3 ;; /* sh1 = 8 * (src % 8) */ + mov ar.lc = c /* "infinite" loop */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + adds c = -(MEMLAT-1), c ;; /* c = (len / 8) */ + ld8 r[1] = [asrc],8 + mov ar.lc = c ;; + + .align 32 +.l2: +(p6) st8 [dest] = value, 8 /* store val to dest */ + ld8.s r[0] = [asrc], 8 + shr.u value = r[1], sh1 ;; /* value = w0 >> sh1 */ + czx1.r pos = value ;; /* do we have an "early" zero */ + cmp.lt p7, p0 = pos, thresh /* in w0 >> sh1? */ + adds len = -8, len /* len -= 8 */ +(p7) br.cond.dpnt .nonalign_found0 + chk.s r[0], .recovery2 /* it is safe to do that only */ +.back2: /* after the previous test */ + shl tmp = r[0], sh2 /* tmp = w1 << sh2 */ + ;; + or value = value, tmp ;; /* value |= tmp */ + czx1.r pos = value ;; + cmp.ne p7, p6 = 8, pos +(p7) br.cond.dpnt .nonalign_found0 + br.ctop.dptk .l2 ;; + adds len = 8, len + br.cond.sptk .not_found0 ;; +.nonalign_found0: + cmp.gtu p6, p0 = -8, len +(p6) br.cond.dptk .found0 + adds len = 8, len + br.cond.sptk .not_found0 ;; + + .align 32 +.src_aligned: +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) chk.s r[MEMLAT], .recovery3 +.back3: +(p[MEMLAT]) mov value = r[MEMLAT] +(p[MEMLAT]) czx1.r pos = r[MEMLAT] ;; +(p[MEMLAT]) cmp.ne p7, p0 = 8, pos +(p[MEMLAT]) adds len = -8, len /* len -= 8 */ +(p7) br.cond.dpnt .found0 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 ;; + + chk.s r[MEMLAT-1], .recovery4 +.back4: + mov value = r[MEMLAT-1] + +.not_found0: + cmp.eq p5, p6 = len, r0 + adds len = -1, len +(p5) br.cond.dptk .restore_and_exit ;; + mov ar.lc = len +.l4: +(p6) extr.u c = value, 0, 8 /* c = value & 0xff */ +(p6) shr.u value = value, 8 ;; + st1 [dest] = c, 1 + cmp.ne p6, p0 = c, r0 + br.cloop.dptk .l4 + br.cond.sptk .restore_and_exit + +.found0_align: + mov pos = 0 + adds len = -8, len + mov value = 0 ;; +.found0: + shl tmp = pos, 3 + shr.u loopcnt = len, 4 /* loopcnt = len / 16 */ + mov c = -1 ;; + cmp.eq p6, p0 = loopcnt, r0 + adds loopcnt = -1, loopcnt + shl c = c, tmp ;; + and len = 0xf, len + andcm value = value, c + mov ar.lc = loopcnt ;; + cmp.le p7, p0 = 8, len + adds dest2 = 16, dest + st8 [dest] = value, 8 + and len = 0x7, len +(p6) br.cond.dpnt .l6 ;; +.l5: + st8 [dest] = r0, 16 + st8 [dest2] = r0, 16 + br.cloop.dptk .l5 ;; +.l6: +(p7) st8 [dest] = r0, 8 + cmp.eq p5, p0 = len, r0 + adds len = -1, len +(p5) br.cond.dptk .restore_and_exit ;; + mov ar.lc = len ;; +.l7: + st1 [dest] = r0, 1 + br.cloop.dptk .l7 ;; +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 + +.short_len: + cmp.eq p5, p0 = in2, r0 + adds loopcnt = -1, in2 +(p5) br.cond.spnt .restore_and_exit ;; + mov ar.lc = loopcnt /* p6 should be set when we get here */ +.l8: +(p6) ld1 c = [in1], 1 /* c = *src++ */ + ;; + st1 [in0] = c, 1 /* *dest++ = c */ +(p6) cmp.ne p6, p0 = c, r0 + br.cloop.dptk .l8 + ;; + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 +.recovery2: + add c = 8, len + add tmp = -8, asrc ;; + cmp.gtu p8, p5 = c, thresh ;; +(p8) ld8 r[0] = [tmp] +(p5) mov r[0] = r0 + br.cond.sptk .back2 +.recovery3: + add tmp = -(MEMLAT + 1) * 8, src ;; + ld8 r[MEMLAT] = [tmp] + br.cond.sptk .back3 +.recovery4: + cmp.eq p5, p6 = len, r0 + add tmp = -MEMLAT * 8, src ;; +(p6) ld8 r[MEMLAT - 1] = [tmp] +(p5) mov r[MEMLAT - 1] = r0 + br.cond.sptk .back4 +END(strncpy) +libc_hidden_def (strncpy) diff --git a/libc/string/ia64/sysdep.h b/libc/string/ia64/sysdep.h new file mode 100644 index 0000000..d10020a --- /dev/null +++ b/libc/string/ia64/sysdep.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_IA64_SYSDEP_H +#define _LINUX_IA64_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Macros to help writing .prologue directives in assembly code. */ +#define ASM_UNW_PRLG_RP 0x8 +#define ASM_UNW_PRLG_PFS 0x4 +#define ASM_UNW_PRLG_PSP 0x2 +#define ASM_UNW_PRLG_PR 0x1 +#define ASM_UNW_PRLG_GRSAVE(ninputs) (32+(ninputs)) + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define CALL_MCOUNT + +#define ENTRY(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global C_SYMBOL_NAME(name); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define LEAF(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global name; \ + C_LABEL(name) + +/* Mark the end of function SYM. */ +#undef END +#define END(sym) .endp C_SYMBOL_NAME(sym) + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +/* Linux uses a negative return value to indicate syscall errors, unlike + most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be negative + even if the call succeeded. E.g., the `lseek' system call might return + a large offset. Therefore we must not anymore test for < 0, but test + for a real error by making sure the value in %d0 is a real error + number. Linus said he will make sure the no syscall returns a value + in -1 .. -4095 as a valid result so we can savely test with -4095. */ + +/* We don't want the label for the error handler to be visible in the symbol + table when we define it here. */ +#define SYSCALL_ERROR_LABEL __syscall_error + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; + +#define DO_CALL_VIA_BREAK(num) \ + mov r15=num; \ + break __BREAK_SYSCALL + +#ifdef IA64_USE_NEW_STUB +# ifdef SHARED +# define DO_CALL(num) \ + .prologue; \ + adds r2 = SYSINFO_OFFSET, r13;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov r15 = num; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# else /* !SHARED */ +# define DO_CALL(num) \ + .prologue; \ + mov r15 = num; \ + movl r2 = _dl_sysinfo;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# endif +#else +# define DO_CALL(num) DO_CALL_VIA_BREAK(num) +#endif + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) mov r10=r8; + + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) .endp C_SYMBOL_NAME(name); + +#undef END +#define END(name) \ + .size C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ; \ + .endp C_SYMBOL_NAME(name) + +#define ret br.ret.sptk.few b0 +#define ret_NOERRNO ret +#define ret_ERRVAL ret + +#endif /* not __ASSEMBLER__ */ + +#endif /* linux/ia64/sysdep.h */ diff --git a/libc/string/memccpy.c b/libc/string/memccpy.c new file mode 100644 index 0000000..076bdac --- /dev/null +++ b/libc/string/memccpy.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* No wide analog. */ + +#include "_string.h" + +void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n) +{ + register char *r1 = s1; + register const char *r2 = s2; + + while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c))); + + return (n == (size_t) -1) ? NULL : r1; +} +libc_hidden_def(memccpy) diff --git a/libc/string/memchr.c b/libc/string/memchr.c new file mode 100644 index 0000000..4139997 --- /dev/null +++ b/libc/string/memchr.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemchr wmemchr +#else +# define Wmemchr memchr +#endif + +libc_hidden_proto(Wmemchr) + +Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n) +{ + register const Wuchar *r = (const Wuchar *) s; +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *np = (const char *) n; +#else +# define np n +#endif + + while (np) { + if (*r == ((Wuchar)c)) { + return (Wvoid *) r; /* silence the warning */ + } + ++r; + --np; + } + + return NULL; +} +#undef np + +libc_hidden_def(Wmemchr) diff --git a/libc/string/memcmp.c b/libc/string/memcmp.c new file mode 100644 index 0000000..762fc23 --- /dev/null +++ b/libc/string/memcmp.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemcmp wmemcmp +#else +/* Experimentally off - libc_hidden_proto(memcmp) */ +# define Wmemcmp memcmp +#endif + +int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n) +{ + register const Wuchar *r1 = (const Wuchar *) s1; + register const Wuchar *r2 = (const Wuchar *) s2; + +#ifdef WANT_WIDE + while (n && (*r1 == *r2)) { + ++r1; + ++r2; + --n; + } + + return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1); +#else + int r = 0; + + while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0)); + + return r; +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(memcmp) +# ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +# endif +#endif diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c new file mode 100644 index 0000000..dc29867 --- /dev/null +++ b/libc/string/memcpy.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemcpy wmemcpy +#else +# define Wmemcpy memcpy +#endif + +libc_hidden_proto(Wmemcpy) + +Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n) +{ + register Wchar *r1 = s1; + register const Wchar *r2 = s2; + +#ifdef __BCC__ + while (n--) { + *r1++ = *r2++; + } +#else + while (n) { + *r1++ = *r2++; + --n; + } +#endif + + return s1; +} +libc_hidden_def(Wmemcpy) diff --git a/libc/string/memmem.c b/libc/string/memmem.c new file mode 100644 index 0000000..9dcd4c4 --- /dev/null +++ b/libc/string/memmem.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(memmem) */ +void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + register const char *ph; + register const char *pn; + const char *plast; + size_t n; + + if (needlelen == 0) { + return (void *) haystack; + } + + if (haystacklen >= needlelen) { + ph = (const char *) haystack; + pn = (const char *) needle; + plast = ph + (haystacklen - needlelen); + + do { + n = 0; + while (ph[n] == pn[n]) { + if (++n == needlelen) { + return (void *) ph; + } + } + } while (++ph <= plast); + } + + return NULL; +} +libc_hidden_def(memmem) +#endif diff --git a/libc/string/memmove.c b/libc/string/memmove.c new file mode 100644 index 0000000..0bea9b4 --- /dev/null +++ b/libc/string/memmove.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemmove wmemmove +#else +/* Experimentally off - libc_hidden_proto(memmove) */ +# define Wmemmove memmove +#endif + +Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n) +{ +#ifdef __BCC__ + register Wchar *s = (Wchar *) s1; + register const Wchar *p = (const Wchar *) s2; + + if (p >= s) { + while (n--) { + *s++ = *p++; + } + } else { + s += n; + p += n; + while (n--) { + *--s = *--p; + } + } + + return s1; +#else + register Wchar *s = (Wchar *) s1; + register const Wchar *p = (const Wchar *) s2; + + if (p >= s) { + while (n) { + *s++ = *p++; + --n; + } + } else { + while (n) { + --n; + s[n] = p[n]; + } + } + + return s1; +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(Wmemmove) +#endif diff --git a/libc/string/mempcpy.c b/libc/string/mempcpy.c new file mode 100644 index 0000000..9189643 --- /dev/null +++ b/libc/string/mempcpy.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wmempcpy wmempcpy +#else +# define Wmempcpy mempcpy +#endif + +libc_hidden_proto(Wmempcpy) + +Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n) +{ + register Wchar *r1 = s1; + register const Wchar *r2 = s2; + +#ifdef __BCC__ + while (n--) { + *r1++ = *r2++; + } +#else + while (n) { + *r1++ = *r2++; + --n; + } +#endif + + return r1; +} + +libc_hidden_weak(Wmempcpy) +#endif diff --git a/libc/string/memrchr.c b/libc/string/memrchr.c new file mode 100644 index 0000000..48ec50a --- /dev/null +++ b/libc/string/memrchr.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +/* Experimentally off - libc_hidden_proto(memrchr) */ + +void *memrchr(const void *s, int c, size_t n) +{ + register const unsigned char *r; +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *np = (const char *) n; +#else +#define np n +#endif + + r = ((unsigned char *)s) + ((size_t) np); + + while (np) { + if (*--r == ((unsigned char)c)) { + return (void *) r; /* silence the warning */ + } + --np; + } + + return NULL; +} +#undef np + +libc_hidden_def(memrchr) +#endif diff --git a/libc/string/memset.c b/libc/string/memset.c new file mode 100644 index 0000000..6dd20d6 --- /dev/null +++ b/libc/string/memset.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemset wmemset +#else +/* Experimentally off - libc_hidden_proto(memset) */ +# define Wmemset memset +#endif + +Wvoid *Wmemset(Wvoid *s, Wint c, size_t n) +{ + register Wuchar *p = (Wuchar *) s; +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *np = (const char *) n; +#else +# define np n +#endif + + while (np) { + *p++ = (Wuchar) c; + --np; + } + + return s; +} +#undef np + +#ifndef WANT_WIDE +libc_hidden_def(memset) +#endif diff --git a/libc/string/mips/Makefile b/libc/string/mips/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/mips/memcpy.S b/libc/string/mips/memcpy.S new file mode 100644 index 0000000..9b05ee6 --- /dev/null +++ b/libc/string/mips/memcpy.S @@ -0,0 +1,257 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/*#include */ +#include +#include "sysdep.h" + +/* void *memcpy(void *s1, const void *s2, size_t n); */ + +#ifdef __mips64 + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define LDHI ldl /* high part is left in big-endian */ +# define SDHI sdl /* high part is left in big-endian */ +# define LDLO ldr /* low part is right in big-endian */ +# define SDLO sdr /* low part is right in big-endian */ +#else +# define LDHI ldr /* high part is right in little-endian */ +# define SDHI sdr /* high part is right in little-endian */ +# define LDLO ldl /* low part is left in little-endian */ +# define SDLO sdl /* low part is left in little-endian */ +#endif + +ENTRY (memcpy) + .set noreorder + + slti t0, a2, 16 # Less than 16? + bne t0, zero, L(last16) + move v0, a0 # Setup exit value before too late + + xor t0, a1, a0 # Find a0/a1 displacement + andi t0, 0x7 + bne t0, zero, L(shift) # Go handle the unaligned case + PTR_SUBU t1, zero, a1 + andi t1, 0x7 # a0/a1 are aligned, but are we + beq t1, zero, L(chk8w) # starting in the middle of a word? + PTR_SUBU a2, t1 + LDHI t0, 0(a1) # Yes we are... take care of that + PTR_ADDU a1, t1 + SDHI t0, 0(a0) + PTR_ADDU a0, t1 + +L(chk8w): + andi t0, a2, 0x3f # 64 or more bytes left? + beq t0, a2, L(chk1w) + PTR_SUBU a3, a2, t0 # Yes + PTR_ADDU a3, a1 # a3 = end address of loop + move a2, t0 # a2 = what will be left after loop +L(lop8w): + ld t0, 0(a1) # Loop taking 8 words at a time + ld t1, 8(a1) + ld t2, 16(a1) + ld t3, 24(a1) + ld ta0, 32(a1) + ld ta1, 40(a1) + ld ta2, 48(a1) + ld ta3, 56(a1) + PTR_ADDIU a0, 64 + PTR_ADDIU a1, 64 + sd t0, -64(a0) + sd t1, -56(a0) + sd t2, -48(a0) + sd t3, -40(a0) + sd ta0, -32(a0) + sd ta1, -24(a0) + sd ta2, -16(a0) + bne a1, a3, L(lop8w) + sd ta3, -8(a0) + +L(chk1w): + andi t0, a2, 0x7 # 8 or more bytes left? + beq t0, a2, L(last16) + PTR_SUBU a3, a2, t0 # Yes, handle them one dword at a time + PTR_ADDU a3, a1 # a3 again end address + move a2, t0 +L(lop1w): + ld t0, 0(a1) + PTR_ADDIU a0, 8 + PTR_ADDIU a1, 8 + bne a1, a3, L(lop1w) + sd t0, -8(a0) + +L(last16): + blez a2, L(lst16e) # Handle last 16 bytes, one at a time + PTR_ADDU a3, a2, a1 +L(lst16l): + lb t0, 0(a1) + PTR_ADDIU a0, 1 + PTR_ADDIU a1, 1 + bne a1, a3, L(lst16l) + sb t0, -1(a0) +L(lst16e): + jr ra # Bye, bye + nop + +L(shift): + PTR_SUBU a3, zero, a0 # Src and Dest unaligned + andi a3, 0x7 # (unoptimized case...) + beq a3, zero, L(shft1) + PTR_SUBU a2, a3 # a2 = bytes left + LDHI t0, 0(a1) # Take care of first odd part + LDLO t0, 7(a1) + PTR_ADDU a1, a3 + SDHI t0, 0(a0) + PTR_ADDU a0, a3 +L(shft1): + andi t0, a2, 0x7 + PTR_SUBU a3, a2, t0 + PTR_ADDU a3, a1 +L(shfth): + LDHI t1, 0(a1) # Limp through, dword by dword + LDLO t1, 7(a1) + PTR_ADDIU a0, 8 + PTR_ADDIU a1, 8 + bne a1, a3, L(shfth) + sd t1, -8(a0) + b L(last16) # Handle anything which may be left + move a2, t0 + + .set reorder +END (memcpy) + +#else /* !__mips64 */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define LWHI lwl /* high part is left in big-endian */ +# define SWHI swl /* high part is left in big-endian */ +# define LWLO lwr /* low part is right in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#else +# define LWHI lwr /* high part is right in little-endian */ +# define SWHI swr /* high part is right in little-endian */ +# define LWLO lwl /* low part is left in little-endian */ +# define SWLO swl /* low part is left in little-endian */ +#endif + +ENTRY (memcpy) + .set noreorder + + slti t0, a2, 8 # Less than 8? + bne t0, zero, L(last8) + move v0, a0 # Setup exit value before too late + + xor t0, a1, a0 # Find a0/a1 displacement + andi t0, 0x3 + bne t0, zero, L(shift) # Go handle the unaligned case + subu t1, zero, a1 + andi t1, 0x3 # a0/a1 are aligned, but are we + beq t1, zero, L(chk8w) # starting in the middle of a word? + subu a2, t1 + LWHI t0, 0(a1) # Yes we are... take care of that + addu a1, t1 + SWHI t0, 0(a0) + addu a0, t1 + +L(chk8w): + andi t0, a2, 0x1f # 32 or more bytes left? + beq t0, a2, L(chk1w) + subu a3, a2, t0 # Yes + addu a3, a1 # a3 = end address of loop + move a2, t0 # a2 = what will be left after loop +L(lop8w): + lw t0, 0(a1) # Loop taking 8 words at a time + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a0, 32 + addiu a1, 32 + sw t0, -32(a0) + sw t1, -28(a0) + sw t2, -24(a0) + sw t3, -20(a0) + sw t4, -16(a0) + sw t5, -12(a0) + sw t6, -8(a0) + bne a1, a3, L(lop8w) + sw t7, -4(a0) + +L(chk1w): + andi t0, a2, 0x3 # 4 or more bytes left? + beq t0, a2, L(last8) + subu a3, a2, t0 # Yes, handle them one word at a time + addu a3, a1 # a3 again end address + move a2, t0 +L(lop1w): + lw t0, 0(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(lop1w) + sw t0, -4(a0) + +L(last8): + blez a2, L(lst8e) # Handle last 8 bytes, one at a time + addu a3, a2, a1 +L(lst8l): + lb t0, 0(a1) + addiu a0, 1 + addiu a1, 1 + bne a1, a3, L(lst8l) + sb t0, -1(a0) +L(lst8e): + jr ra # Bye, bye + nop + +L(shift): + subu a3, zero, a0 # Src and Dest unaligned + andi a3, 0x3 # (unoptimized case...) + beq a3, zero, L(shft1) + subu a2, a3 # a2 = bytes left + LWHI t0, 0(a1) # Take care of first odd part + LWLO t0, 3(a1) + addu a1, a3 + SWHI t0, 0(a0) + addu a0, a3 +L(shft1): + andi t0, a2, 0x3 + subu a3, a2, t0 + addu a3, a1 +L(shfth): + LWHI t1, 0(a1) # Limp through, word by word + LWLO t1, 3(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(shfth) + sw t1, -4(a0) + b L(last8) # Handle anything which may be left + move a2, t0 + + .set reorder +END (memcpy) + +#endif /* !__mips64 */ + +libc_hidden_def(memcpy) diff --git a/libc/string/mips/memset.S b/libc/string/mips/memset.S new file mode 100644 index 0000000..ff0554f --- /dev/null +++ b/libc/string/mips/memset.S @@ -0,0 +1,159 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/*#include */ +#include +#include "sysdep.h" + +/* void *memset(void *s, int c, size_t n). */ + +#ifdef __mips64 + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SDHI sdl /* high part is left in big-endian */ +#else +# define SDHI sdr /* high part is right in little-endian */ +#endif + +ENTRY (memset) + .set noreorder + + slti ta1, a2, 16 # Less than 16? + bne ta1, zero, L(last16) + move v0, a0 # Setup exit value before too late + + beq a1, zero, L(ueven) # If zero pattern, no need to extend + andi a1, 0xff # Avoid problems with bogus arguments + dsll ta0, a1, 8 + or a1, ta0 + dsll ta0, a1, 16 + or a1, ta0 # a1 is now pattern in full word + dsll ta0, a1, 32 + or a1, ta0 # a1 is now pattern in double word + +L(ueven): + PTR_SUBU ta0, zero, a0 # Unaligned address? + andi ta0, 0x7 + beq ta0, zero, L(chkw) + PTR_SUBU a2, ta0 + SDHI a1, 0(a0) # Yes, handle first unaligned part + PTR_ADDU a0, ta0 # Now both a0 and a2 are updated + +L(chkw): + andi ta0, a2, 0xf # Enough left for one loop iteration? + beq ta0, a2, L(chkl) + PTR_SUBU a3, a2, ta0 + PTR_ADDU a3, a0 # a3 is last loop address +1 + move a2, ta0 # a2 is now # of bytes left after loop +L(loopw): + PTR_ADDIU a0, 16 # Handle 2 dwords pr. iteration + sd a1, -16(a0) + bne a0, a3, L(loopw) + sd a1, -8(a0) + +L(chkl): + andi ta0, a2, 0x8 # Check if there is at least a double + beq ta0, zero, L(last16) # word remaining after the loop + PTR_SUBU a2, ta0 + sd a1, 0(a0) # Yes... + PTR_ADDIU a0, 8 + +L(last16): + blez a2, L(exit) # Handle last 16 bytes (if cnt>0) + PTR_ADDU a3, a2, a0 # a3 is last address +1 +L(lst16l): + PTR_ADDIU a0, 1 + bne a0, a3, L(lst16l) + sb a1, -1(a0) +L(exit): + j ra # Bye, bye + nop + + .set reorder +END (memset) + +#else /* !__mips64 */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SWHI swl /* high part is left in big-endian */ +#else +# define SWHI swr /* high part is right in little-endian */ +#endif + +ENTRY (memset) + .set noreorder + + slti t1, a2, 8 # Less than 8? + bne t1, zero, L(last8) + move v0, a0 # Setup exit value before too late + + beq a1, zero, L(ueven) # If zero pattern, no need to extend + andi a1, 0xff # Avoid problems with bogus arguments + sll t0, a1, 8 + or a1, t0 + sll t0, a1, 16 + or a1, t0 # a1 is now pattern in full word + +L(ueven): + subu t0, zero, a0 # Unaligned address? + andi t0, 0x3 + beq t0, zero, L(chkw) + subu a2, t0 + SWHI a1, 0(a0) # Yes, handle first unaligned part + addu a0, t0 # Now both a0 and a2 are updated + +L(chkw): + andi t0, a2, 0x7 # Enough left for one loop iteration? + beq t0, a2, L(chkl) + subu a3, a2, t0 + addu a3, a0 # a3 is last loop address +1 + move a2, t0 # a2 is now # of bytes left after loop +L(loopw): + addiu a0, 8 # Handle 2 words pr. iteration + sw a1, -8(a0) + bne a0, a3, L(loopw) + sw a1, -4(a0) + +L(chkl): + andi t0, a2, 0x4 # Check if there is at least a full + beq t0, zero, L(last8) # word remaining after the loop + subu a2, t0 + sw a1, 0(a0) # Yes... + addiu a0, 4 + +L(last8): + blez a2, L(exit) # Handle last 8 bytes (if cnt>0) + addu a3, a2, a0 # a3 is last address +1 +L(lst8l): + addiu a0, 1 + bne a0, a3, L(lst8l) + sb a1, -1(a0) +L(exit): + j ra # Bye, bye + nop + + .set reorder +END (memset) + +#endif /* !__mips64 */ + +libc_hidden_def(memset) diff --git a/libc/string/mips/sysdep.h b/libc/string/mips/sysdep.h new file mode 100644 index 0000000..5dad834 --- /dev/null +++ b/libc/string/mips/sysdep.h @@ -0,0 +1,45 @@ +/* Adapted from glibc's sysdeps/unix/mips/sysdep.h */ + +/* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +#include +#include + +#define ENTRY(name) \ + .globl name; \ + .align 2; \ + .ent name,0; \ + name/* use a comment rather than ## to workaround bug in gcc-3.4.x */: + +#undef END +#define END(function) \ + .end function; \ + .size function,.-function + +#if _MIPS_SIM == _MIPS_SIM_ABI32 || _MIPS_SIM == _MIPS_SIM_ABIO64 +# define L(label) $L ## label +#else +# define L(label) .L ## label +#endif + +#endif diff --git a/libc/string/powerpc/Makefile b/libc/string/powerpc/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/powerpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/powerpc/memcpy.c b/libc/string/powerpc/memcpy.c new file mode 100644 index 0000000..22794ec --- /dev/null +++ b/libc/string/powerpc/memcpy.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + +/* PPC can do pre increment and load/store, but not post increment and + load/store. Therefore use *++ptr instead of *ptr++. */ +void *memcpy(void *to, const void *from, size_t len) +{ + unsigned long rem, chunks, tmp1, tmp2; + unsigned char *tmp_to; + unsigned char *tmp_from = (unsigned char *)from; + + chunks = len / 8; + tmp_from -= 4; + tmp_to = to - 4; + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + /* make gcc to load all data, then store it */ + tmp1 = *(unsigned long *)(tmp_from+4); + tmp_from += 8; + tmp2 = *(unsigned long *)tmp_from; + *(unsigned long *)(tmp_to+4) = tmp1; + tmp_to += 8; + *(unsigned long *)tmp_to = tmp2; + } while (--chunks); + lessthan8: + len = len % 8; + if (len >= 4) { + tmp_from += 4; + tmp_to += 4; + *(unsigned long *)(tmp_to) = *(unsigned long *)(tmp_from); + len -= 4; + } + if (!len) + return to; + tmp_from += 3; + tmp_to += 3; + do { + *++tmp_to = *++tmp_from; + } while (--len); + + return to; + align: + /* ???: Do we really need to generate the carry flag here? If not, then: + rem -= 4; */ + rem = 4 - rem; + len -= rem; + do { + *(tmp_to+4) = *(tmp_from+4); + ++tmp_from; + ++tmp_to; + } while (--rem); + chunks = len / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memcpy) diff --git a/libc/string/powerpc/memmove.c b/libc/string/powerpc/memmove.c new file mode 100644 index 0000000..8badae3 --- /dev/null +++ b/libc/string/powerpc/memmove.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* Experimentally off - libc_hidden_proto(memmove) */ +void *memmove(void *to, const void *from, size_t n) +{ + unsigned long rem, chunks, tmp1, tmp2; + unsigned char *tmp_to; + unsigned char *tmp_from = (unsigned char *)from; + + if (tmp_from >= (unsigned char *)to) + return memcpy(to, from, n); + chunks = n / 8; + tmp_from += n; + tmp_to = to + n; + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + /* make gcc to load all data, then store it */ + tmp1 = *(unsigned long *)(tmp_from-4); + tmp_from -= 8; + tmp2 = *(unsigned long *)tmp_from; + *(unsigned long *)(tmp_to-4) = tmp1; + tmp_to -= 8; + *(unsigned long *)tmp_to = tmp2; + } while (--chunks); + lessthan8: + n = n % 8; + if (n >= 4) { + *(unsigned long *)(tmp_to-4) = *(unsigned long *)(tmp_from-4); + tmp_from -= 4; + tmp_to -= 4; + n = n-4; + } + if (!n ) return to; + do { + *--tmp_to = *--tmp_from; + } while (--n); + + return to; + align: + rem = 4 - rem; + n = n - rem; + do { + *--tmp_to = *--tmp_from; + } while (--rem); + chunks = n / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memmove) diff --git a/libc/string/powerpc/memset.c b/libc/string/powerpc/memset.c new file mode 100644 index 0000000..1cbfd04 --- /dev/null +++ b/libc/string/powerpc/memset.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +static __inline__ int expand_byte_word(int c){ + /* this does: + c = c << 8 | c; + c = c << 16 | c ; + */ + __asm__("rlwimi %0,%0,8,16,23\n" + "\trlwimi %0,%0,16,0,15\n" + : "=r" (c) : "0" (c)); + return c; +} + +void *memset(void *to, int c, size_t n) +{ + unsigned long rem, chunks; + unsigned char *tmp_to; + + chunks = n / 8; + tmp_to = to - 4; + c = expand_byte_word(c); + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + } while (--chunks); + lessthan8: + n = n % 8; + if (n >= 4) { + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + n = n-4; + } + if (!n ) return to; + tmp_to += 3; + do { + *++tmp_to = c; + } while (--n); + + return to; + align: + rem = 4 - rem; + n = n-rem; + do { + *(tmp_to+4) = c; + ++tmp_to; + } while (--rem); + chunks = n / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memset) diff --git a/libc/string/psignal.c b/libc/string/psignal.c new file mode 100644 index 0000000..1ca8725 --- /dev/null +++ b/libc/string/psignal.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(fprintf) +/* Experimentally off - libc_hidden_proto(strsignal) */ + +/* TODO: make this threadsafe with a reentrant version of strsignal? */ + +void psignal(int signum, register const char *message) +{ + /* If the program is calling psignal, it's a safe bet that printf and + * friends are used as well. It is also possible that the calling + * program could buffer stderr, or reassign it. */ + + register const char *sep; + + sep = ": "; + if (!(message && *message)) { /* Caller did not supply a prefix message */ + message = (sep += 2); /* or passed an empty string. */ + } + + fprintf(stderr, "%s%s%s\n", message, sep, strsignal(signum)); +} diff --git a/libc/string/rawmemchr.c b/libc/string/rawmemchr.c new file mode 100644 index 0000000..3cddefa --- /dev/null +++ b/libc/string/rawmemchr.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +/* Experimentally off - libc_hidden_proto(rawmemchr) */ +void *rawmemchr(const void *s, int c) +{ + register const unsigned char *r = s; + + while (*r != ((unsigned char)c)) ++r; + + return (void *) r; /* silence the warning */ +} +libc_hidden_def(rawmemchr) +#endif diff --git a/libc/string/sh/sh4/memcpy.S b/libc/string/sh/sh4/memcpy.S new file mode 100644 index 0000000..2d91829 --- /dev/null +++ b/libc/string/sh/sh4/memcpy.S @@ -0,0 +1,808 @@ +/* + * "memcpy" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * Copyright (c) 2002 STMicroelectronics Ltd + * Modified from memcpy.S and micro-optimised for SH4 + * Stuart Menefy (stuart.menefy@st.com) + * + */ + +/* + * void *memcpy(void *dst, const void *src, size_t n); + * + * It is assumed that there is no overlap between src and dst. + * If there is an overlap, then the results are undefined. + */ + +#include + + ! + ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR. + ! + + ! Size is 16 or greater, and may have trailing bytes + + .balign 32 +.Lcase1: + ! Read a long word and write a long word at once + ! At the start of each iteration, r7 contains last long load + add #-1,r5 ! 79 EX + mov r4,r2 ! 5 MT (0 cycles latency) + + mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency) + add #-4,r5 ! 50 EX + + add #7,r2 ! 79 EX + ! +#ifdef __LITTLE_ENDIAN__ + ! 6 cycles, 4 bytes per iteration +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK + mov r7, r3 ! 5 MT (latency=0) ! RQPO + + cmp/hi r2,r0 ! 57 MT + shll16 r3 ! 103 EX + + mov r1,r6 ! 5 MT (latency=0) + shll8 r3 ! 102 EX ! Oxxx + + shlr8 r6 ! 106 EX ! xNML + mov r1, r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! ONML + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#else +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! KLMN + mov r7,r3 ! 5 MT (latency=0) ! OPQR + + cmp/hi r2,r0 ! 57 MT + shlr16 r3 ! 107 EX + + shlr8 r3 ! 106 EX ! xxxO + mov r1,r6 ! 5 MT (latency=0) + + shll8 r6 ! 102 EX ! LMNx + mov r1,r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! LMNO + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#endif + ! Finally, copy a byte at once, if necessary + + add #4,r5 ! 50 EX + cmp/eq r4,r0 ! 54 MT + + add #-6,r2 ! 50 EX + bt 9f ! 109 BR + +8: cmp/hi r2,r0 ! 57 MT + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + + bt/s 8b ! 109 BR + + mov.b r1,@-r0 ! 29 LS + +9: rts + nop + + + ! + ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R... + ! + + ! Size is 16 or greater, and may have trailing bytes + + .balign 32 +.Lcase3: + ! Read a long word and write a long word at once + ! At the start of each iteration, r7 contains last long load + add #-3,r5 ! 79 EX + mov r4,r2 ! 5 MT (0 cycles latency) + + mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency) + add #-4,r5 ! 50 EX + + add #7,r2 ! 79 EX + ! +#ifdef __LITTLE_ENDIAN__ + ! 6 cycles, 4 bytes per iteration +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK + mov r7, r3 ! 5 MT (latency=0) ! RQPO + + cmp/hi r2,r0 ! 57 MT + shll8 r3 ! 102 EX ! QPOx + + mov r1,r6 ! 5 MT (latency=0) + shlr16 r6 ! 107 EX + + shlr8 r6 ! 106 EX ! xxxN + mov r1, r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! QPON + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#else +3: mov r1,r3 ! OPQR + shlr8 r3 ! xOPQ + mov.l @(r0,r5),r1 ! KLMN + mov r1,r6 + shll16 r6 + shll8 r6 ! Nxxx + or r6,r3 ! NOPQ + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#endif + + ! Finally, copy a byte at once, if necessary + + add #6,r5 ! 50 EX + cmp/eq r4,r0 ! 54 MT + + add #-6,r2 ! 50 EX + bt 9f ! 109 BR + +8: cmp/hi r2,r0 ! 57 MT + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + + bt/s 8b ! 109 BR + + mov.b r1,@-r0 ! 29 LS + +9: rts + nop + +/* void * memcpy(void *dst, const void *src, size_t len) */ +.text +.align 4 +.type memcpy,@function +.globl memcpy; +memcpy: + + ! Calculate the invariants which will be used in the remainder + ! of the code: + ! + ! r4 --> [ ... ] DST [ ... ] SRC + ! [ ... ] [ ... ] + ! : : + ! r0 --> [ ... ] r0+r5 --> [ ... ] + ! + ! + + ! Short circuit the common case of src, dst and len being 32 bit aligned + ! and test for zero length move + + mov r6, r0 ! 5 MT (0 cycle latency) + or r4, r0 ! 82 EX + + or r5, r0 ! 82 EX + tst r6, r6 ! 86 MT + + bt/s 99f ! 111 BR (zero len) + tst #3, r0 ! 87 MT + + mov r4, r0 ! 5 MT (0 cycle latency) + add r6, r0 ! 49 EX + + mov #16, r1 ! 6 EX + bt/s .Lcase00 ! 111 BR (aligned) + + sub r4, r5 ! 75 EX + + ! Arguments are not nicely long word aligned or zero len. + ! Check for small copies, and if so do a simple byte at a time copy. + ! + ! Deciding on an exact value of 'small' is not easy, as the point at which + ! using the optimised routines become worthwhile varies (these are the + ! cycle counts for differnet sizes using byte-at-a-time vs. optimised): + ! size byte-at-time long word byte + ! 16 42 39-40 46-50 50-55 + ! 24 58 43-44 54-58 62-67 + ! 36 82 49-50 66-70 80-85 + ! However the penalty for getting it 'wrong' is much higher for long word + ! aligned data (and this is more common), so use a value of 16. + + cmp/gt r6,r1 ! 56 MT + + add #-1,r5 ! 50 EX + bf/s 6f ! 108 BR (not small) + + mov r5, r3 ! 5 MT (latency=0) + shlr r6 ! 104 EX + + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + bf/s 4f ! 111 BR + + add #-1,r3 ! 50 EX + tst r6, r6 ! 86 MT + + bt/s 98f ! 110 BR + mov.b r1,@-r0 ! 29 LS + + ! 4 cycles, 2 bytes per iteration +3: mov.b @(r0,r5),r1 ! 20 LS (latency=2) + +4: mov.b @(r0,r3),r2 ! 20 LS (latency=2) + dt r6 ! 67 EX + + mov.b r1,@-r0 ! 29 LS + bf/s 3b ! 111 BR + + mov.b r2,@-r0 ! 29 LS +98: + rts + nop + +99: rts + mov r4, r0 + + ! Size is not small, so its worthwhile looking for optimisations. + ! First align destination to a long word boundary. + ! + ! r5 = normal value -1 + +6: tst #3, r0 ! 87 MT + mov #3, r3 ! 6 EX + + bt/s 2f ! 111 BR + and r0,r3 ! 78 EX + + ! 3 cycles, 1 byte per iteration +1: dt r3 ! 67 EX + mov.b @(r0,r5),r1 ! 19 LS (latency=2) + + add #-1, r6 ! 79 EX + bf/s 1b ! 109 BR + + mov.b r1,@-r0 ! 28 LS + +2: add #1, r5 ! 79 EX + + ! Now select the appropriate bulk transfer code based on relative + ! alignment of src and dst. + + mov r0, r3 ! 5 MT (latency=0) + + mov r5, r0 ! 5 MT (latency=0) + tst #1, r0 ! 87 MT + + bf/s 1f ! 111 BR + mov #64, r7 ! 6 EX + + ! bit 0 clear + + cmp/ge r7, r6 ! 55 MT + + bt/s 2f ! 111 BR + tst #2, r0 ! 87 MT + + ! small + bt/s .Lcase0 + mov r3, r0 + + bra .Lcase2 + nop + + ! big +2: bt/s .Lcase0b + mov r3, r0 + + bra .Lcase2b + nop + + ! bit 0 set +1: tst #2, r0 ! 87 MT + + bt/s .Lcase1 + mov r3, r0 + + bra .Lcase3 + nop + + + ! + ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR + ! + + ! src, dst and size are all long word aligned + ! size is non-zero + + .balign 32 +.Lcase00: + mov #64, r1 ! 6 EX + mov r5, r3 ! 5 MT (latency=0) + + cmp/gt r6, r1 ! 56 MT + add #-4, r5 ! 50 EX + + bf .Lcase00b ! 108 BR (big loop) + shlr2 r6 ! 105 EX + + shlr r6 ! 104 EX + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + + bf/s 4f ! 111 BR + add #-8, r3 ! 50 EX + + tst r6, r6 ! 86 MT + bt/s 5f ! 110 BR + + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + dt r6 ! 67 EX + + mov.l r1, @-r0 ! 30 LS + bf/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + +5: rts + nop + + + ! Size is 16 or greater and less than 64, but may have trailing bytes + + .balign 32 +.Lcase0: + add #-4, r5 ! 50 EX + mov r4, r7 ! 5 MT (latency=0) + + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + mov #4, r2 ! 6 EX + + add #11, r7 ! 50 EX + tst r2, r6 ! 86 MT + + mov r5, r3 ! 5 MT (latency=0) + bt/s 4f ! 111 BR + + add #-4, r3 ! 50 EX + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + cmp/hi r7, r0 + + mov.l r1, @-r0 ! 30 LS + bt/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + + ! Copy the final 0-3 bytes + + add #3,r5 ! 50 EX + + cmp/eq r0, r4 ! 54 MT + add #-10, r7 ! 50 EX + + bt 9f ! 110 BR + + ! 3 cycles, 1 byte per iteration +1: mov.b @(r0,r5),r1 ! 19 LS + cmp/hi r7,r0 ! 57 MT + + bt/s 1b ! 111 BR + mov.b r1,@-r0 ! 28 LS + +9: rts + nop + + ! Size is at least 64 bytes, so will be going round the big loop at least once. + ! + ! r2 = rounded up r4 + ! r3 = rounded down r0 + + .balign 32 +.Lcase0b: + add #-4, r5 ! 50 EX + +.Lcase00b: + mov r0, r3 ! 5 MT (latency=0) + mov #(~0x1f), r1 ! 6 EX + + and r1, r3 ! 78 EX + mov r4, r2 ! 5 MT (latency=0) + + cmp/eq r3, r0 ! 54 MT + add #0x1f, r2 ! 50 EX + + bt/s 1f ! 110 BR + and r1, r2 ! 78 EX + + ! copy initial words until cache line aligned + + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + tst #4, r0 ! 87 MT + + mov r5, r6 ! 5 MT (latency=0) + add #-4, r6 ! 50 EX + + bt/s 4f ! 111 BR + add #8, r3 ! 50 EX + + tst #0x18, r0 ! 87 MT + + bt/s 1f ! 109 BR + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r6), r7 ! 21 LS (latency=2) + cmp/eq r3, r0 ! 54 MT + + mov.l r1, @-r0 ! 30 LS + bf/s 3b ! 109 BR + + mov.l r7, @-r0 ! 30 LS + + ! Copy the cache line aligned blocks + ! + ! In use: r0, r2, r4, r5 + ! Scratch: r1, r3, r6, r7 + ! + ! We could do this with the four scratch registers, but if src + ! and dest hit the same cache line, this will thrash, so make + ! use of additional registers. + ! + ! We also need r0 as a temporary (for movca), so 'undo' the invariant: + ! r5: src (was r0+r5) + ! r1: dest (was r0) + ! this can be reversed at the end, so we don't need to save any extra + ! state. + ! +1: mov.l r8, @-r15 ! 30 LS + add r0, r5 ! 49 EX + + mov.l r9, @-r15 ! 30 LS + mov r0, r1 ! 5 MT (latency=0) + + mov.l r10, @-r15 ! 30 LS + add #-0x1c, r5 ! 50 EX + + mov.l r11, @-r15 ! 30 LS + + ! 16 cycles, 32 bytes per iteration +2: mov.l @(0x00,r5),r0 ! 18 LS (latency=2) + add #-0x20, r1 ! 50 EX + mov.l @(0x04,r5),r3 ! 18 LS (latency=2) + mov.l @(0x08,r5),r6 ! 18 LS (latency=2) + mov.l @(0x0c,r5),r7 ! 18 LS (latency=2) + mov.l @(0x10,r5),r8 ! 18 LS (latency=2) + mov.l @(0x14,r5),r9 ! 18 LS (latency=2) + mov.l @(0x18,r5),r10 ! 18 LS (latency=2) + mov.l @(0x1c,r5),r11 ! 18 LS (latency=2) + movca.l r0,@r1 ! 40 LS (latency=3-7) + mov.l r3,@(0x04,r1) ! 33 LS + mov.l r6,@(0x08,r1) ! 33 LS + mov.l r7,@(0x0c,r1) ! 33 LS + + mov.l r8,@(0x10,r1) ! 33 LS + add #-0x20, r5 ! 50 EX + + mov.l r9,@(0x14,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10,@(0x18,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11,@(0x1c,r1) ! 33 LS + + mov r1, r0 ! 5 MT (latency=0) + + mov.l @r15+, r11 ! 15 LS + sub r1, r5 ! 75 EX + + mov.l @r15+, r10 ! 15 LS + cmp/eq r4, r0 ! 54 MT + + bf/s 1f ! 109 BR + mov.l @r15+, r9 ! 15 LS + + rts +1: mov.l @r15+, r8 ! 15 LS + sub r4, r1 ! 75 EX (len remaining) + + ! number of trailing bytes is non-zero + ! + ! invariants restored (r5 already decremented by 4) + ! also r1=num bytes remaining + + mov #4, r2 ! 6 EX + mov r4, r7 ! 5 MT (latency=0) + + add #0x1c, r5 ! 50 EX (back to -4) + cmp/hs r2, r1 ! 58 MT + + bf/s 5f ! 108 BR + add #11, r7 ! 50 EX + + mov.l @(r0, r5), r6 ! 21 LS (latency=2) + tst r2, r1 ! 86 MT + + mov r5, r3 ! 5 MT (latency=0) + bt/s 4f ! 111 BR + + add #-4, r3 ! 50 EX + cmp/hs r2, r1 ! 58 MT + + bt/s 5f ! 111 BR + mov.l r6,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r6 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + cmp/hi r7, r0 + + mov.l r6, @-r0 ! 30 LS + bt/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + + ! Copy the final 0-3 bytes + +5: cmp/eq r0, r4 ! 54 MT + add #-10, r7 ! 50 EX + + bt 9f ! 110 BR + add #3,r5 ! 50 EX + + ! 3 cycles, 1 byte per iteration +1: mov.b @(r0,r5),r1 ! 19 LS + cmp/hi r7,r0 ! 57 MT + + bt/s 1b ! 111 BR + mov.b r1,@-r0 ! 28 LS + +9: rts + nop + + ! + ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR.. + ! + + .balign 32 +.Lcase2: + ! Size is 16 or greater and less then 64, but may have trailing bytes + +2: mov r5, r6 ! 5 MT (latency=0) + add #-2,r5 ! 50 EX + + mov r4,r2 ! 5 MT (latency=0) + add #-4,r6 ! 50 EX + + add #7,r2 ! 50 EX +3: mov.w @(r0,r5),r1 ! 20 LS (latency=2) + + mov.w @(r0,r6),r3 ! 20 LS (latency=2) + cmp/hi r2,r0 ! 57 MT + + mov.w r1,@-r0 ! 29 LS + bt/s 3b ! 111 BR + + mov.w r3,@-r0 ! 29 LS + + bra 10f + nop + + + .balign 32 +.Lcase2b: + ! Size is at least 64 bytes, so will be going round the big loop at least once. + ! + ! r2 = rounded up r4 + ! r3 = rounded down r0 + + mov r0, r3 ! 5 MT (latency=0) + mov #(~0x1f), r1 ! 6 EX + + and r1, r3 ! 78 EX + mov r4, r2 ! 5 MT (latency=0) + + cmp/eq r3, r0 ! 54 MT + add #0x1f, r2 ! 50 EX + + add #-2, r5 ! 50 EX + bt/s 1f ! 110 BR + and r1, r2 ! 78 EX + + ! Copy a short word one at a time until we are cache line aligned + ! Normal values: r0, r2, r3, r4 + ! Unused: r1, r6, r7 + ! Mod: r5 (=r5-2) + ! + add #2, r3 ! 50 EX + +2: mov.w @(r0,r5),r1 ! 20 LS (latency=2) + cmp/eq r3,r0 ! 54 MT + + bf/s 2b ! 111 BR + + mov.w r1,@-r0 ! 29 LS + + ! Copy the cache line aligned blocks + ! + ! In use: r0, r2, r4, r5 (=r5-2) + ! Scratch: r1, r3, r6, r7 + ! + ! We could do this with the four scratch registers, but if src + ! and dest hit the same cache line, this will thrash, so make + ! use of additional registers. + ! + ! We also need r0 as a temporary (for movca), so 'undo' the invariant: + ! r5: src (was r0+r5) + ! r1: dest (was r0) + ! this can be reversed at the end, so we don't need to save any extra + ! state. + ! +1: mov.l r8, @-r15 ! 30 LS + add r0, r5 ! 49 EX + + mov.l r9, @-r15 ! 30 LS + mov r0, r1 ! 5 MT (latency=0) + + mov.l r10, @-r15 ! 30 LS + add #-0x1e, r5 ! 50 EX + + mov.l r11, @-r15 ! 30 LS + + mov.l r12, @-r15 ! 30 LS + + ! 17 cycles, 32 bytes per iteration +#ifdef __LITTLE_ENDIAN__ +2: mov.w @r5+, r0 ! 14 LS (latency=2) ..JI + add #-0x20, r1 ! 50 EX + + mov.l @r5+, r3 ! 15 LS (latency=2) NMLK + + mov.l @r5+, r6 ! 15 LS (latency=2) RQPO + shll16 r0 ! 103 EX JI.. + + mov.l @r5+, r7 ! 15 LS (latency=2) + xtrct r3, r0 ! 48 EX LKJI + + mov.l @r5+, r8 ! 15 LS (latency=2) + xtrct r6, r3 ! 48 EX PONM + + mov.l @r5+, r9 ! 15 LS (latency=2) + xtrct r7, r6 ! 48 EX + + mov.l @r5+, r10 ! 15 LS (latency=2) + xtrct r8, r7 ! 48 EX + + mov.l @r5+, r11 ! 15 LS (latency=2) + xtrct r9, r8 ! 48 EX + + mov.w @r5+, r12 ! 15 LS (latency=2) + xtrct r10, r9 ! 48 EX + + movca.l r0,@r1 ! 40 LS (latency=3-7) + xtrct r11, r10 ! 48 EX + + mov.l r3, @(0x04,r1) ! 33 LS + xtrct r12, r11 ! 48 EX + + mov.l r6, @(0x08,r1) ! 33 LS + + mov.l r7, @(0x0c,r1) ! 33 LS + + mov.l r8, @(0x10,r1) ! 33 LS + add #-0x40, r5 ! 50 EX + + mov.l r9, @(0x14,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10, @(0x18,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11, @(0x1c,r1) ! 33 LS +#else +2: mov.w @(0x1e,r5), r0 ! 17 LS (latency=2) + add #-2, r5 ! 50 EX + + mov.l @(0x1c,r5), r3 ! 18 LS (latency=2) + add #-4, r1 ! 50 EX + + mov.l @(0x18,r5), r6 ! 18 LS (latency=2) + shll16 r0 ! 103 EX + + mov.l @(0x14,r5), r7 ! 18 LS (latency=2) + xtrct r3, r0 ! 48 EX + + mov.l @(0x10,r5), r8 ! 18 LS (latency=2) + xtrct r6, r3 ! 48 EX + + mov.l @(0x0c,r5), r9 ! 18 LS (latency=2) + xtrct r7, r6 ! 48 EX + + mov.l @(0x08,r5), r10 ! 18 LS (latency=2) + xtrct r8, r7 ! 48 EX + + mov.l @(0x04,r5), r11 ! 18 LS (latency=2) + xtrct r9, r8 ! 48 EX + + mov.w @(0x02,r5), r12 ! 18 LS (latency=2) + xtrct r10, r9 ! 48 EX + + movca.l r0,@r1 ! 40 LS (latency=3-7) + add #-0x1c, r1 ! 50 EX + + mov.l r3, @(0x1c,r1) ! 33 LS + xtrct r11, r10 ! 48 EX + + mov.l r6, @(0x18,r1) ! 33 LS + xtrct r12, r11 ! 48 EX + + mov.l r7, @(0x14,r1) ! 33 LS + + mov.l r8, @(0x10,r1) ! 33 LS + add #-0x3e, r5 ! 50 EX + + mov.l r9, @(0x0c,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10, @(0x08,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11, @(0x04,r1) ! 33 LS +#endif + + mov.l @r15+, r12 + mov r1, r0 ! 5 MT (latency=0) + + mov.l @r15+, r11 ! 15 LS + sub r1, r5 ! 75 EX + + mov.l @r15+, r10 ! 15 LS + cmp/eq r4, r0 ! 54 MT + + bf/s 1f ! 109 BR + mov.l @r15+, r9 ! 15 LS + + rts +1: mov.l @r15+, r8 ! 15 LS + + add #0x1e, r5 ! 50 EX + + ! Finish off a short word at a time + ! r5 must be invariant - 2 +10: mov r4,r2 ! 5 MT (latency=0) + add #1,r2 ! 50 EX + + cmp/hi r2, r0 ! 57 MT + bf/s 1f ! 109 BR + + add #2, r2 ! 50 EX + +3: mov.w @(r0,r5),r1 ! 20 LS + cmp/hi r2,r0 ! 57 MT + + bt/s 3b ! 109 BR + + mov.w r1,@-r0 ! 29 LS +1: + + ! + ! Finally, copy the last byte if necessary + cmp/eq r4,r0 ! 54 MT + bt/s 9b + add #1,r5 + mov.b @(r0,r5),r1 + rts + mov.b r1,@-r0 + +.size memcpy,.-memcpy; + +libc_hidden_def (memcpy) diff --git a/libc/string/sh64/Makefile b/libc/string/sh64/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/sh64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/sh64/memcpy.S b/libc/string/sh64/memcpy.S new file mode 100644 index 0000000..470784e --- /dev/null +++ b/libc/string/sh64/memcpy.S @@ -0,0 +1,205 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! +! Fast SH memcpy +! +! by Toshiyasu Morita (tm@netcom.com) +! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut) +! SH5 code Copyright 2002 SuperH Ltd. +! +! Entry: ARG0: destination pointer +! ARG1: source pointer +! ARG2: byte count +! +! Exit: RESULT: destination pointer +! any other registers in the range r0-r7: trashed +! +! Notes: Usually one wants to do small reads and write a longword, but +! unfortunately it is difficult in some cases to concatanate bytes +! into a longword on the SH, so this does a longword read and small +! writes. +! +! This implementation makes two assumptions about how it is called: +! +! 1.: If the byte count is nonzero, the address of the last byte to be +! copied is unsigned greater than the address of the first byte to +! be copied. This could be easily swapped for a signed comparison, +! but the algorithm used needs some comparison. +! +! 2.: When there are two or three bytes in the last word of an 11-or-more +! bytes memory chunk to b copied, the rest of the word can be read +! without side effects. +! This could be easily changed by increasing the minumum size of +! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, +! however, this would cost a few extra cyles on average. +! For SHmedia, the assumption is that any quadword can be read in its +! enirety if at least one byte is included in the copy. +! + +#include + + .section .text..SHmedia32,"ax" + .globl memcpy + .type memcpy, @function + .align 5 + +memcpy: + +#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1 +#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1 +#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1 +#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1 + + ld.b r3,0,r63 + pta/l Large,tr0 + movi 25,r0 + bgeu/u r4,r0,tr0 + nsb r4,r0 + shlli r0,5,r0 + movi (L1-L0+63*32 + 1) & 0xffff,r1 + sub r1, r0, r0 +L0: ptrel r0,tr0 + add r2,r4,r5 + ptabs r18,tr1 + add r3,r4,r6 + blink tr0,r63 + +/* Rearranged to make cut2 safe */ + .balign 8 +L4_7: /* 4..7 byte memcpy cntd. */ + stlo.l r2, 0, r0 + or r6, r7, r6 + sthi.l r5, -1, r6 + stlo.l r5, -4, r6 + blink tr1,r63 + + .balign 8 +L1: /* 0 byte memcpy */ + nop + blink tr1,r63 + nop + nop + nop + nop + +L2_3: /* 2 or 3 byte memcpy cntd. */ + st.b r5,-1,r6 + blink tr1,r63 + + /* 1 byte memcpy */ + ld.b r3,0,r0 + st.b r2,0,r0 + blink tr1,r63 + +L8_15: /* 8..15 byte memcpy cntd. */ + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + + /* 2 or 3 byte memcpy */ + ld.b r3,0,r0 + ld.b r2,0,r63 + ld.b r3,1,r1 + st.b r2,0,r0 + pta/l L2_3,tr0 + ld.b r6,-1,r6 + st.b r2,1,r1 + blink tr0, r63 + + /* 4 .. 7 byte memcpy */ + LDUAL (r3, 0, r0, r1) + pta L4_7, tr0 + ldlo.l r6, -4, r7 + or r0, r1, r0 + sthi.l r2, 3, r0 + ldhi.l r6, -1, r6 + blink tr0, r63 + + /* 8 .. 15 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + pta L8_15, tr0 + ldlo.q r6, -8, r7 + or r0, r1, r0 + sthi.q r2, 7, r0 + ldhi.q r6, -1, r6 + blink tr0, r63 + + /* 16 .. 24 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + LDUAQ (r3, 8, r8, r9) + or r0, r1, r0 + sthi.q r2, 7, r0 + or r8, r9, r8 + sthi.q r2, 15, r8 + ldlo.q r6, -8, r7 + ldhi.q r6, -1, r6 + stlo.q r2, 8, r8 + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + +Large: + ld.b r2, 0, r63 + pta/l Loop_ua, tr1 + ori r3, -8, r7 + sub r2, r7, r22 + sub r3, r2, r6 + add r2, r4, r5 + ldlo.q r3, 0, r0 + addi r5, -16, r5 + movi 64+8, r27 /* could subtract r7 from that. */ + stlo.q r2, 0, r0 + sthi.q r2, 7, r0 + ldx.q r22, r6, r0 + bgtu/l r27, r4, tr1 + + addi r5, -48, r27 + pta/l Loop_line, tr0 + addi r6, 64, r36 + addi r6, -24, r19 + addi r6, -16, r20 + addi r6, -8, r21 + +Loop_line: + ldx.q r22, r36, r63 + alloco r22, 32 + addi r22, 32, r22 + ldx.q r22, r19, r23 + sthi.q r22, -25, r0 + ldx.q r22, r20, r24 + ldx.q r22, r21, r25 + stlo.q r22, -32, r0 + ldx.q r22, r6, r0 + sthi.q r22, -17, r23 + sthi.q r22, -9, r24 + sthi.q r22, -1, r25 + stlo.q r22, -24, r23 + stlo.q r22, -16, r24 + stlo.q r22, -8, r25 + bgeu r27, r22, tr0 + +Loop_ua: + addi r22, 8, r22 + sthi.q r22, -1, r0 + stlo.q r22, -8, r0 + ldx.q r22, r6, r0 + bgtu/l r5, r22, tr1 + + add r3, r4, r7 + ldlo.q r7, -8, r1 + sthi.q r22, 7, r0 + ldhi.q r7, -1, r7 + ptabs r18,tr1 + stlo.q r22, 0, r0 + or r1, r7, r1 + sthi.q r5, 15, r1 + stlo.q r5, 8, r1 + blink tr1, r63 + + .size memcpy,.-memcpy + +libc_hidden_def(memcpy) diff --git a/libc/string/sh64/memset.S b/libc/string/sh64/memset.S new file mode 100644 index 0000000..1b8812c --- /dev/null +++ b/libc/string/sh64/memset.S @@ -0,0 +1,97 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! +! Fast SH memset +! +! by Toshiyasu Morita (tm@netcom.com) +! +! SH5 code by J"orn Rennecke (joern.rennecke@superh.com) +! Copyright 2002 SuperH Ltd. +! + +#include +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SHHI shlld +#define SHLO shlrd +#else +#define SHHI shlrd +#define SHLO shlld +#endif + + .section .text..SHmedia32,"ax" + .globl memset + .type memset, @function + + .align 5 + +memset: + pta/l multiquad, tr0 + andi r2, 7, r22 + ptabs r18, tr2 + mshflo.b r3,r3,r3 + add r4, r22, r23 + mperm.w r3, r63, r3 /* Fill pattern now in every byte of r3 */ + + movi 8, r9 + bgtu/u r23, r9, tr0 /* multiquad */ + + beqi/u r4, 0, tr2 /* Return with size 0 - ensures no mem accesses */ + ldlo.q r2, 0, r7 + shlli r4, 2, r4 + movi -1, r8 + SHHI r8, r4, r8 + SHHI r8, r4, r8 + mcmv r7, r8, r3 + stlo.q r2, 0, r3 + blink tr2, r63 + +multiquad: + pta/l lastquad, tr0 + stlo.q r2, 0, r3 + shlri r23, 3, r24 + add r2, r4, r5 + beqi/u r24, 1, tr0 /* lastquad */ + pta/l loop, tr1 + sub r2, r22, r25 + andi r5, -8, r20 /* calculate end address and */ + addi r20, -7*8, r8 /* loop end address; This might overflow, so we need + to use a different test before we start the loop + */ + bge/u r24, r9, tr1 /* loop */ + st.q r25, 8, r3 + st.q r20, -8, r3 + shlri r24, 1, r24 + beqi/u r24, 1, tr0 /* lastquad */ + st.q r25, 16, r3 + st.q r20, -16, r3 + beqi/u r24, 2, tr0 /* lastquad */ + st.q r25, 24, r3 + st.q r20, -24, r3 +lastquad: + sthi.q r5, -1, r3 + blink tr2,r63 + +loop: +!!! alloco r25, 32 /* QQQ comment out for short-term fix to SHUK #3895. + QQQ commenting out is locically correct, but sub-optimal + QQQ Sean McGoogan - 4th April 2003. */ + st.q r25, 8, r3 + st.q r25, 16, r3 + st.q r25, 24, r3 + st.q r25, 32, r3 + addi r25, 32, r25 + bgeu/l r8, r25, tr1 /* loop */ + + st.q r20, -40, r3 + st.q r20, -32, r3 + st.q r20, -24, r3 + st.q r20, -16, r3 + st.q r20, -8, r3 + sthi.q r5, -1, r3 + blink tr2,r63 + + .size memset,.-memset + +libc_hidden_def(memset) diff --git a/libc/string/sh64/strcpy.S b/libc/string/sh64/strcpy.S new file mode 100644 index 0000000..f317707 --- /dev/null +++ b/libc/string/sh64/strcpy.S @@ -0,0 +1,102 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! Entry: arg0: destination +! arg1: source +! Exit: result: destination +! +! SH5 code Copyright 2002 SuperH Ltd. + +#include +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SHHI shlld +#define SHLO shlrd +#else +#define SHHI shlrd +#define SHLO shlld +#endif + + .section .text..SHmedia32,"ax" + .globl strcpy + .type strcpy, @function + .align 5 + +strcpy: + + pta/l shortstring,tr1 + ldlo.q r3,0,r4 + ptabs r18,tr4 + shlli r3,3,r7 + addi r2, 8, r0 + mcmpeq.b r4,r63,r6 + SHHI r6,r7,r6 + bnei/u r6,0,tr1 /* shortstring */ + pta/l no_lddst, tr2 + ori r3,-8,r23 + sub r2, r23, r0 + sub r3, r2, r21 + addi r21, 8, r20 + ldx.q r0, r21, r5 + pta/l loop, tr0 + ori r2,-8,r22 + mcmpeq.b r5, r63, r6 + bgt/u r22, r23, tr2 /* no_lddst */ + + /* r22 < r23 : Need to do a load from the destination. */ + /* r22 == r23 : Doesn't actually need to load from destination, */ + /* but still can be handled here. */ + ldlo.q r2, 0, r9 + movi -1, r8 + SHLO r8, r7, r8 + mcmv r4, r8, r9 + stlo.q r2, 0, r9 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 + blink tr1, r63 /* shortstring */ +no_lddst: + /* r22 > r23: note that for r22 == r23 the sthi.q would clobber */ + /* bytes before the destination region. */ + stlo.q r2, 0, r4 + SHHI r4, r7, r4 + sthi.q r0, -1, r4 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 +shortstring: +#if __BYTE_ORDER != __LITTLE_ENDIAN + pta/l shortstring2,tr1 + byterev r4,r4 +#endif +shortstring2: + st.b r0,-8,r4 + andi r4,0xff,r5 + shlri r4,8,r4 + addi r0,1,r0 + bnei/l r5,0,tr1 + blink tr4,r63 /* return */ + + .balign 8 +loop: + stlo.q r0, 0, r5 + ldx.q r0, r20, r4 + addi r0, 16, r0 + sthi.q r0, -9, r5 + mcmpeq.b r4, r63, r6 + bnei/u r6, 0, tr1 /* shortstring */ + ldx.q r0, r21, r5 + stlo.q r0, -8, r4 + sthi.q r0, -1, r4 + mcmpeq.b r5, r63, r6 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 + blink tr1, r63 /* shortstring */ + + .size strcpy,.-strcpy + +libc_hidden_def(strcpy) diff --git a/libc/string/sh64/strlen.S b/libc/string/sh64/strlen.S new file mode 100644 index 0000000..18f4164 --- /dev/null +++ b/libc/string/sh64/strlen.S @@ -0,0 +1,63 @@ +/* vi: set sw=8 ts=8: */ +/* + * libc/string/sh64/strlen.S + * + * Simplistic strlen() implementation for SHmedia. + * + * Copyright (C) 2003 Paul Mundt + * + * 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. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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 CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + + .section .text..SHmedia32,"ax" + .globl strlen + .type strlen,@function + + .balign 16 +strlen: + ptabs r18, tr4 + + /* + * Note: We could easily deal with the NULL case here with a simple + * sanity check, though it seems that the behavior we want is to fault + * in the event that r2 == NULL, so we don't bother. + */ +/* beqi r2, 0, tr4 */ ! Sanity check + + movi -1, r0 + pta/l loop, tr0 +loop: + ld.b r2, 0, r1 + addi r2, 1, r2 + addi r0, 1, r0 + bnei/l r1, 0, tr0 + + or r0, r63, r2 + blink tr4, r63 + + .size strlen,.-strlen + +libc_hidden_def(strlen) diff --git a/libc/string/sparc/Makefile b/libc/string/sparc/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/sparc/_glibc_inc.h b/libc/string/sparc/_glibc_inc.h new file mode 100644 index 0000000..e0aef52 --- /dev/null +++ b/libc/string/sparc/_glibc_inc.h @@ -0,0 +1,27 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +/* Is alignment really needed? */ + +#if __WORDSIZE == 32 +# define ENTRY_ALIGN 4 +#else +# define ENTRY_ALIGN 2 +#endif + +#define ENTRY(sym) \ + .global sym; \ + .align ENTRY_ALIGN; \ + .type sym,%function; \ + sym: + +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/libc/string/sparc/bcopy.c b/libc/string/sparc/bcopy.c new file mode 100644 index 0000000..9a455f3 --- /dev/null +++ b/libc/string/sparc/bcopy.c @@ -0,0 +1 @@ +/* bcopy is in memcpy.S */ diff --git a/libc/string/sparc/bzero.c b/libc/string/sparc/bzero.c new file mode 100644 index 0000000..37f0f6f --- /dev/null +++ b/libc/string/sparc/bzero.c @@ -0,0 +1 @@ +/* bzero is in memset.S */ diff --git a/libc/string/sparc/memchr.S b/libc/string/sparc/memchr.S new file mode 100644 index 0000000..73e5101 --- /dev/null +++ b/libc/string/sparc/memchr.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memchr.S" +# else +# include "sparc32/memchr.S" +# endif + +#else +# include "sparc64/memchr.S" +#endif diff --git a/libc/string/sparc/memcpy.S b/libc/string/sparc/memcpy.S new file mode 100644 index 0000000..478cb10 --- /dev/null +++ b/libc/string/sparc/memcpy.S @@ -0,0 +1,19 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memcpy.S" +# else +# include "sparc32/memcpy.S" +# endif + +#else + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc64/sparcv9b/memcpy.S" +# else +# include "sparc64/memcpy.S" +#endif + +#endif diff --git a/libc/string/sparc/memmove.c b/libc/string/sparc/memmove.c new file mode 100644 index 0000000..a8d2d49 --- /dev/null +++ b/libc/string/sparc/memmove.c @@ -0,0 +1 @@ +/* memmove is in memcpy.S */ diff --git a/libc/string/sparc/memset.S b/libc/string/sparc/memset.S new file mode 100644 index 0000000..4aed774 --- /dev/null +++ b/libc/string/sparc/memset.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memset.S" +# else +# include "sparc32/memset.S" +# endif + +#else +# include "sparc64/memset.S" +#endif diff --git a/libc/string/sparc/sparc32/memchr.S b/libc/string/sparc/sparc32/memchr.S new file mode 100644 index 0000000..4d57a55 --- /dev/null +++ b/libc/string/sparc/sparc32/memchr.S @@ -0,0 +1,144 @@ +/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in STR less + than N. + For SPARC v7. + Copyright (C) 1996, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + David S. Miller . + This version is developed using the same algorithm as the fast C + version which carries the following introduction: + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .text + .align 4 +0: cmp %o2, 0 + be 9f + sethi %hi(0x80808080), %o4 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + be 9f + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + be 9f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o5 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + bne,a 7f + and %o2, 3, %g1 + retl + clr %o0 +1: retl + sub %o0, 1, %o0 + +ENTRY(memchr) + andcc %o1, 0xff, %o1 + sll %o1, 8, %g6 + andcc %o0, 3, %g0 + or %o1, %g6, %g6 + sll %g6, 16, %o3 + bne 0b + or %o3, %g6, %g2 + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o5 +5: and %o2, 3, %g1 +7: andcc %o2, 0xfffffffc, %o2 + be 0f + or %o5, %lo(0x01010101), %g6 + ld [%o0], %g4 +6: xor %g4, %g2, %g5 + add %o0, 4, %o0 + sub %g5, %g6, %g5 + andcc %g5, %o3, %g0 + bne 8f + subcc %o2, 4, %o2 + bne,a 6b + ld [%o0], %g4 +0: cmp %g1, 0 +1: be 9f + add %o0, 4, %o0 + ldub [%o0 - 4], %g4 + cmp %g4, %o1 + be 4f + cmp %g1, 1 + be 9f + ldub [%o0 - 3], %g4 + cmp %g4, %o1 + be 3f + cmp %g1, 2 + be 9f + ldub [%o0 - 2], %g4 + cmp %g4, %o1 + be 2f + nop +9: retl + clr %o0 + + /* Check every byte. */ +8: srl %g4, 24, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 4f + srl %g4, 16, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 3f + srl %g4, 8, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 2f + and %g4, 0xff, %g5 + cmp %g5, %o1 + be 1f + cmp %o2, 0 + bne,a 6b + ld [%o0], %g4 + b 1b + cmp %g1, 0 +1: retl + sub %o0, 1, %o0 +2: retl + sub %o0, 2, %o0 +3: retl + sub %o0, 3, %o0 +4: retl + sub %o0, 4, %o0 +END(memchr) +libc_hidden_def(memchr) + +#if !__BOUNDED_POINTERS__ +weak_alias(memchr,__ubp_memchr) +#endif diff --git a/libc/string/sparc/sparc32/memcpy.S b/libc/string/sparc/sparc32/memcpy.S new file mode 100644 index 0000000..25a4884 --- /dev/null +++ b/libc/string/sparc/sparc32/memcpy.S @@ -0,0 +1,973 @@ +/* Copy SIZE bytes from SRC to DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller , + Eddie C. Dost and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Both these macros have to start with exactly the same insn */ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + ldd [%src + offset + 0x10], %t4; \ + ldd [%src + offset + 0x18], %t6; \ + st %t0, [%dst + offset + 0x00]; \ + st %t1, [%dst + offset + 0x04]; \ + st %t2, [%dst + offset + 0x08]; \ + st %t3, [%dst + offset + 0x0c]; \ + st %t4, [%dst + offset + 0x10]; \ + st %t5, [%dst + offset + 0x14]; \ + st %t6, [%dst + offset + 0x18]; \ + st %t7, [%dst + offset + 0x1c]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + ldd [%src + offset + 0x10], %t4; \ + ldd [%src + offset + 0x18], %t6; \ + std %t0, [%dst + offset + 0x00]; \ + std %t2, [%dst + offset + 0x08]; \ + std %t4, [%dst + offset + 0x10]; \ + std %t6, [%dst + offset + 0x18]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - offset - 0x10], %t0; \ + ldd [%src - offset - 0x08], %t2; \ + st %t0, [%dst - offset - 0x10]; \ + st %t1, [%dst - offset - 0x0c]; \ + st %t2, [%dst - offset - 0x08]; \ + st %t3, [%dst - offset - 0x04]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - offset - 0x10], %t0; \ + ldd [%src - offset - 0x08], %t2; \ + std %t0, [%dst - offset - 0x10]; \ + std %t2, [%dst - offset - 0x08]; + +#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src - offset - 0x02], %t0; \ + ldub [%src - offset - 0x01], %t1; \ + stb %t0, [%dst - offset - 0x02]; \ + stb %t1, [%dst - offset - 0x01]; + +/* Both these macros have to start with exactly the same insn */ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - offset - 0x20], %t0; \ + ldd [%src - offset - 0x18], %t2; \ + ldd [%src - offset - 0x10], %t4; \ + ldd [%src - offset - 0x08], %t6; \ + st %t0, [%dst - offset - 0x20]; \ + st %t1, [%dst - offset - 0x1c]; \ + st %t2, [%dst - offset - 0x18]; \ + st %t3, [%dst - offset - 0x14]; \ + st %t4, [%dst - offset - 0x10]; \ + st %t5, [%dst - offset - 0x0c]; \ + st %t6, [%dst - offset - 0x08]; \ + st %t7, [%dst - offset - 0x04]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - offset - 0x20], %t0; \ + ldd [%src - offset - 0x18], %t2; \ + ldd [%src - offset - 0x10], %t4; \ + ldd [%src - offset - 0x08], %t6; \ + std %t0, [%dst - offset - 0x20]; \ + std %t2, [%dst - offset - 0x18]; \ + std %t4, [%dst - offset - 0x10]; \ + std %t6, [%dst - offset - 0x08]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + st %t0, [%dst + offset + 0x00]; \ + st %t1, [%dst + offset + 0x04]; \ + st %t2, [%dst + offset + 0x08]; \ + st %t3, [%dst + offset + 0x0c]; + +#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src + offset + 0x00], %t0; \ + ldub [%src + offset + 0x01], %t1; \ + stb %t0, [%dst + offset + 0x00]; \ + stb %t1, [%dst + offset + 0x01]; + +#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + srl %t0, shir, %t5; \ + srl %t1, shir, %t6; \ + sll %t0, shil, %t0; \ + or %t5, %prev, %t5; \ + sll %t1, shil, %prev; \ + or %t6, %t0, %t0; \ + srl %t2, shir, %t1; \ + srl %t3, shir, %t6; \ + sll %t2, shil, %t2; \ + or %t1, %prev, %t1; \ + std %t4, [%dst + offset + offset2 - 0x04]; \ + std %t0, [%dst + offset + offset2 + 0x04]; \ + sll %t3, shil, %prev; \ + or %t6, %t2, %t4; + +#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + srl %t0, shir, %t4; \ + srl %t1, shir, %t5; \ + sll %t0, shil, %t6; \ + or %t4, %prev, %t0; \ + sll %t1, shil, %prev; \ + or %t5, %t6, %t1; \ + srl %t2, shir, %t4; \ + srl %t3, shir, %t5; \ + sll %t2, shil, %t6; \ + or %t4, %prev, %t2; \ + sll %t3, shil, %prev; \ + or %t5, %t6, %t3; \ + std %t0, [%dst + offset + offset2 + 0x00]; \ + std %t2, [%dst + offset + offset2 + 0x08]; + + .text + .align 4 + +70: andcc %o1, 1, %g0 + be 4f + andcc %o1, 2, %g0 + + ldub [%o1 - 1], %g2 + sub %o1, 1, %o1 + stb %g2, [%o0 - 1] + sub %o2, 1, %o2 + be 3f + sub %o0, 1, %o0 +4: lduh [%o1 - 2], %g2 + sub %o1, 2, %o1 + sth %g2, [%o0 - 2] + sub %o2, 2, %o2 + b 3f + sub %o0, 2, %o0 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + mov %o0, %o3 + mov %o1, %o0 + mov %o3, %o1 +END(bcopy) +#endif + +ENTRY(memmove) + cmp %o0, %o1 + st %o0, [%sp + 64] + bleu 9f + sub %o0, %o1, %o4 + + add %o1, %o2, %o3 + cmp %o3, %o0 + bleu 0f + andcc %o4, 3, %o5 + + add %o1, %o2, %o1 + add %o0, %o2, %o0 + bne 77f + cmp %o2, 15 + bleu 91f + andcc %o1, 3, %g0 + bne 70b +3: andcc %o1, 4, %g0 + + be 2f + mov %o2, %g1 + + ld [%o1 - 4], %o4 + sub %g1, 4, %g1 + st %o4, [%o0 - 4] + sub %o1, 4, %o1 + sub %o0, 4, %o0 +2: andcc %g1, 0xffffff80, %g6 + be 3f + andcc %o0, 4, %g0 + + be 74f + 4 +5: RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + sub %o1, 128, %o1 + bne 5b + sub %o0, 128, %o0 + +3: andcc %g1, 0x70, %g6 + be 72f + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 +101: call 100f + sub %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (72f - 101b), %g0 + sub %o0, %g6, %o0 + +71: RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) +72: be 73f + andcc %g1, 4, %g0 + + ldd [%o1 - 0x08], %g2 + sub %o0, 8, %o0 + sub %o1, 8, %o1 + st %g2, [%o0] + st %g3, [%o0 + 0x04] +73: be 1f + andcc %g1, 2, %g0 + + ld [%o1 - 4], %g2 + sub %o1, 4, %o1 + st %g2, [%o0 - 4] + sub %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1 - 2], %g2 + sub %o1, 2, %o1 + sth %g2, [%o0 - 2] + sub %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1 - 1], %g2 + stb %g2, [%o0 - 1] +1: retl + ld [%sp + 64], %o0 + +74: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + sub %o1, 128, %o1 + bne 74b + sub %o0, 128, %o0 + + andcc %g1, 0x70, %g6 + be 72b + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 +102: call 100f + sub %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (72b - 102b), %g0 + sub %o0, %g6, %o0 + +75: and %o2, 0xe, %o3 + mov %o7, %g2 + sll %o3, 3, %o4 + sub %o0, %o3, %o0 +103: call 100f + sub %o1, %o3, %o1 + mov %g2, %o7 + jmpl %o5 + (76f - 103b), %g0 + andcc %o2, 1, %g0 + + RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) + +76: be 1f + nop + ldub [%o1 - 1], %g2 + stb %g2, [%o0 - 1] +1: retl + ld [%sp + 64], %o0 + +91: bne 75b + andcc %o2, 8, %g0 + + be 1f + andcc %o2, 4, %g0 + + ld [%o1 - 0x08], %g2 + ld [%o1 - 0x04], %g3 + sub %o1, 8, %o1 + st %g2, [%o0 - 0x08] + st %g3, [%o0 - 0x04] + sub %o0, 8, %o0 +1: b 73b + mov %o2, %g1 + +77: cmp %o2, 15 + bleu 75b + andcc %o0, 3, %g0 + be 64f + andcc %o0, 1, %g0 + be 63f + andcc %o0, 2, %g0 + ldub [%o1 - 1], %g5 + sub %o1, 1, %o1 + stb %g5, [%o0 - 1] + sub %o0, 1, %o0 + be 64f + sub %o2, 1, %o2 + +63: ldub [%o1 - 1], %g5 + sub %o1, 2, %o1 + stb %g5, [%o0 - 1] + sub %o0, 2, %o0 + ldub [%o1], %g5 + sub %o2, 2, %o2 + stb %g5, [%o0] +64: and %o1, 3, %g2 + and %o1, -4, %o1 + and %o2, 0xc, %g3 + add %o1, 4, %o1 + cmp %g3, 4 + sll %g2, 3, %g4 + mov 32, %g2 + be 4f + sub %g2, %g4, %g6 + + blu 3f + cmp %g3, 8 + + be 2f + srl %o2, 2, %g3 + + ld [%o1 - 4], %o3 + add %o0, -8, %o0 + ld [%o1 - 8], %o4 + add %o1, -16, %o1 + b 7f + add %g3, 1, %g3 +2: ld [%o1 - 4], %o4 + add %o0, -4, %o0 + ld [%o1 - 8], %g1 + add %o1, -12, %o1 + b 8f + add %g3, 2, %g3 +3: ld [%o1 - 4], %o5 + add %o0, -12, %o0 + ld [%o1 - 8], %o3 + add %o1, -20, %o1 + b 6f + srl %o2, 2, %g3 +4: ld [%o1 - 4], %g1 + srl %o2, 2, %g3 + ld [%o1 - 8], %o5 + add %o1, -24, %o1 + add %o0, -16, %o0 + add %g3, -1, %g3 + + ld [%o1 + 12], %o3 +5: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 12] +6: ld [%o1 + 8], %o4 + sll %o3, %g4, %g2 + srl %o5, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 8] +7: ld [%o1 + 4], %g1 + sll %o4, %g4, %g2 + srl %o3, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 4] +8: ld [%o1], %o5 + sll %g1, %g4, %g2 + srl %o4, %g6, %g5 + addcc %g3, -4, %g3 + or %g2, %g5, %g2 + add %o1, -16, %o1 + st %g2, [%o0] + add %o0, -16, %o0 + bne,a 5b + ld [%o1 + 12], %o3 + sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + srl %g4, 3, %g3 + or %g2, %g5, %g2 + add %o1, %g3, %o1 + andcc %o2, 2, %g0 + st %g2, [%o0 + 12] + be 1f + andcc %o2, 1, %g0 + + ldub [%o1 + 15], %g5 + add %o1, -2, %o1 + stb %g5, [%o0 + 11] + add %o0, -2, %o0 + ldub [%o1 + 16], %g5 + stb %g5, [%o0 + 12] +1: be 1f + nop + ldub [%o1 + 15], %g5 + stb %g5, [%o0 + 11] +1: retl + ld [%sp + 64], %o0 + +78: andcc %o1, 1, %g0 + be 4f + andcc %o1, 2, %g0 + + ldub [%o1], %g2 + add %o1, 1, %o1 + stb %g2, [%o0] + sub %o2, 1, %o2 + bne 3f + add %o0, 1, %o0 +4: lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + sub %o2, 2, %o2 + b 3f + add %o0, 2, %o0 +END(memmove) +libc_hidden_def(memmove) + +ENTRY(memcpy) /* %o0=dst %o1=src %o2=len */ + sub %o0, %o1, %o4 + st %o0, [%sp + 64] +9: andcc %o4, 3, %o5 +0: bne 86f + cmp %o2, 15 + + bleu 90f + andcc %o1, 3, %g0 + + bne 78b +3: andcc %o1, 4, %g0 + + be 2f + mov %o2, %g1 + + ld [%o1], %o4 + sub %g1, 4, %g1 + st %o4, [%o0] + add %o1, 4, %o1 + add %o0, 4, %o0 +2: andcc %g1, 0xffffff80, %g6 + be 3f + andcc %o0, 4, %g0 + + be 82f + 4 +5: MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + add %o1, 128, %o1 + bne 5b + add %o0, 128, %o0 +3: andcc %g1, 0x70, %g6 + be 80f + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 + add %o1, %g6, %o1 +104: call 100f + add %o0, %g6, %o0 + jmpl %o5 + (80f - 104b), %g0 + mov %g2, %o7 + +79: MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) + +80: be 81f + andcc %g1, 4, %g0 + + ldd [%o1], %g2 + add %o0, 8, %o0 + st %g2, [%o0 - 0x08] + add %o1, 8, %o1 + st %g3, [%o0 - 0x04] + +81: be 1f + andcc %g1, 2, %g0 + + ld [%o1], %g2 + add %o1, 4, %o1 + st %g2, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + add %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +82: /* ldd_std */ + MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + add %o1, 128, %o1 + bne 82b + add %o0, 128, %o0 + + andcc %g1, 0x70, %g6 + be 84f + andcc %g1, 8, %g0 + + mov %o7, %g2 +111: call 110f + add %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (84f - 111b), %g0 + add %o0, %g6, %o0 + +83: MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5) + +84: be 85f + andcc %g1, 4, %g0 + + ldd [%o1], %g2 + add %o0, 8, %o0 + std %g2, [%o0 - 0x08] + add %o1, 8, %o1 +85: be 1f + andcc %g1, 2, %g0 + + ld [%o1], %g2 + add %o1, 4, %o1 + st %g2, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + add %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +86: cmp %o2, 6 + bleu 88f + + cmp %o2, 256 + bcc 87f + + andcc %o0, 3, %g0 + be 61f + andcc %o0, 1, %g0 + be 60f + andcc %o0, 2, %g0 + + ldub [%o1], %g5 + add %o1, 1, %o1 + stb %g5, [%o0] + sub %o2, 1, %o2 + bne 61f + add %o0, 1, %o0 +60: ldub [%o1], %g3 + add %o1, 2, %o1 + stb %g3, [%o0] + sub %o2, 2, %o2 + ldub [%o1 - 1], %g3 + add %o0, 2, %o0 + stb %g3, [%o0 - 1] +61: and %o1, 3, %g2 + and %o2, 0xc, %g3 + and %o1, -4, %o1 + cmp %g3, 4 + sll %g2, 3, %g4 + mov 32, %g2 + be 4f + sub %g2, %g4, %g6 + + blu 3f + cmp %g3, 0x8 + + be 2f + srl %o2, 2, %g3 + + ld [%o1], %o3 + add %o0, -8, %o0 + ld [%o1 + 4], %o4 + b 8f + add %g3, 1, %g3 +2: ld [%o1], %o4 + add %o0, -12, %o0 + ld [%o1 + 4], %o5 + add %g3, 2, %g3 + b 9f + add %o1, -4, %o1 +3: ld [%o1], %g1 + add %o0, -4, %o0 + ld [%o1 + 4], %o3 + srl %o2, 2, %g3 + b 7f + add %o1, 4, %o1 +4: ld [%o1], %o5 + cmp %o2, 7 + ld [%o1 + 4], %g1 + srl %o2, 2, %g3 + bleu 10f + add %o1, 8, %o1 + + ld [%o1], %o3 + add %g3, -1, %g3 +5: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0] +7: ld [%o1 + 4], %o4 + sll %g1, %g4, %g2 + srl %o3, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 4] +8: ld [%o1 + 8], %o5 + sll %o3, %g4, %g2 + srl %o4, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 8] +9: ld [%o1 + 12], %g1 + sll %o4, %g4, %g2 + srl %o5, %g6, %g5 + addcc %g3, -4, %g3 + or %g2, %g5, %g2 + add %o1, 16, %o1 + st %g2, [%o0 + 12] + add %o0, 16, %o0 + bne,a 5b + ld [%o1], %o3 +10: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + srl %g6, 3, %g3 + or %g2, %g5, %g2 + sub %o1, %g3, %o1 + andcc %o2, 2, %g0 + st %g2, [%o0] + be 1f + andcc %o2, 1, %g0 + + ldub [%o1], %g2 + add %o1, 2, %o1 + stb %g2, [%o0 + 4] + add %o0, 2, %o0 + ldub [%o1 - 1], %g2 + stb %g2, [%o0 + 3] +1: be 1f + nop + ldub [%o1], %g2 + stb %g2, [%o0 + 4] +1: retl + ld [%sp + 64], %o0 + +87: andcc %o1, 3, %g0 + be 3f + andcc %o1, 1, %g0 + + be 4f + andcc %o1, 2, %g0 + + ldub [%o1], %g2 + add %o1, 1, %o1 + stb %g2, [%o0] + sub %o2, 1, %o2 + bne 3f + add %o0, 1, %o0 +4: lduh [%o1], %g2 + add %o1, 2, %o1 + srl %g2, 8, %g3 + sub %o2, 2, %o2 + stb %g3, [%o0] + add %o0, 2, %o0 + stb %g2, [%o0 - 1] +3: andcc %o1, 4, %g0 + + bne 2f + cmp %o5, 1 + + ld [%o1], %o4 + srl %o4, 24, %g2 + stb %g2, [%o0] + srl %o4, 16, %g3 + stb %g3, [%o0 + 1] + srl %o4, 8, %g2 + stb %g2, [%o0 + 2] + sub %o2, 4, %o2 + stb %o4, [%o0 + 3] + add %o1, 4, %o1 + add %o0, 4, %o0 +2: be 33f + cmp %o5, 2 + be 32f + sub %o2, 4, %o2 +31: ld [%o1], %g2 + add %o1, 4, %o1 + srl %g2, 24, %g3 + and %o0, 7, %g5 + stb %g3, [%o0] + cmp %g5, 7 + sll %g2, 8, %g1 + add %o0, 4, %o0 + be 41f + and %o2, 0xffffffc0, %o3 + ld [%o0 - 7], %o4 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: st %o4, [%o0 - 7] + sth %g2, [%o0 - 3] + srl %g1, 8, %g4 + b 88f + stb %g4, [%o0 - 1] +32: ld [%o1], %g2 + add %o1, 4, %o1 + srl %g2, 16, %g3 + and %o0, 7, %g5 + sth %g3, [%o0] + cmp %g5, 6 + sll %g2, 16, %g1 + add %o0, 4, %o0 + be 42f + and %o2, 0xffffffc0, %o3 + ld [%o0 - 6], %o4 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: st %o4, [%o0 - 6] + b 88f + sth %g2, [%o0 - 2] +33: ld [%o1], %g2 + sub %o2, 4, %o2 + srl %g2, 24, %g3 + and %o0, 7, %g5 + stb %g3, [%o0] + cmp %g5, 5 + srl %g2, 8, %g4 + sll %g2, 24, %g1 + sth %g4, [%o0 + 1] + add %o1, 4, %o1 + be 43f + and %o2, 0xffffffc0, %o3 + + ld [%o0 - 1], %o4 + add %o0, 4, %o0 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 24, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 24, %g2 +1: st %o4, [%o0 - 5] + b 88f + stb %g2, [%o0 - 1] +41: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 41b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: sth %g2, [%o0 - 3] + srl %g1, 8, %g4 + b 88f + stb %g4, [%o0 - 1] +43: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 43b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 24, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 24, %g2 +1: stb %g2, [%o0 + 3] + b 88f + add %o0, 4, %o0 +42: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 42b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: sth %g2, [%o0 - 2] + + /* Fall through */ + +88: and %o2, 0xe, %o3 + mov %o7, %g2 + sll %o3, 3, %o4 + add %o0, %o3, %o0 +106: call 100f + add %o1, %o3, %o1 + mov %g2, %o7 + jmpl %o5 + (89f - 106b), %g0 + andcc %o2, 1, %g0 + + MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) + +89: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +90: bne 88b + andcc %o2, 8, %g0 + + be 1f + andcc %o2, 4, %g0 + + ld [%o1 + 0x00], %g2 + ld [%o1 + 0x04], %g3 + add %o1, 8, %o1 + st %g2, [%o0 + 0x00] + st %g3, [%o0 + 0x04] + add %o0, 8, %o0 +1: b 81b + mov %o2, %g1 + +100: retl + sub %o7, %o4, %o5 +110: retl + sub %o7, %g6, %o5 +END(memcpy) +libc_hidden_def(memcpy) diff --git a/libc/string/sparc/sparc32/memset.S b/libc/string/sparc/sparc32/memset.S new file mode 100644 index 0000000..6c6424c --- /dev/null +++ b/libc/string/sparc/sparc32/memset.S @@ -0,0 +1,157 @@ +/* Set a block of memory to some byte value. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + /* Store 64 bytes at (BASE + OFFSET) using value SOURCE. */ +#define ZERO_BIG_BLOCK(base, offset, source) \ + std source, [base + offset + 0x00]; \ + std source, [base + offset + 0x08]; \ + std source, [base + offset + 0x10]; \ + std source, [base + offset + 0x18]; \ + std source, [base + offset + 0x20]; \ + std source, [base + offset + 0x28]; \ + std source, [base + offset + 0x30]; \ + std source, [base + offset + 0x38]; + +#define ZERO_LAST_BLOCKS(base, offset, source) \ + std source, [base - offset - 0x38]; \ + std source, [base - offset - 0x30]; \ + std source, [base - offset - 0x28]; \ + std source, [base - offset - 0x20]; \ + std source, [base - offset - 0x18]; \ + std source, [base - offset - 0x10]; \ + std source, [base - offset - 0x08]; \ + std source, [base - offset - 0x00]; + + .text + .align 4 +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bzero) + b 1f + mov %g0, %g3 +#endif + +3: cmp %o2, 3 + be 2f + stb %g3, [%o0] + + cmp %o2, 2 + be 2f + stb %g3, [%o0 + 0x01] + + stb %g3, [%o0 + 0x02] +2: sub %o2, 4, %o2 + add %o1, %o2, %o1 + b 4f + sub %o0, %o2, %o0 +#ifdef __UCLIBC_SUSV3_LEGACY__ +END(bzero) +#endif + +ENTRY(memset) + and %o1, 0xff, %g3 + sll %g3, 8, %g2 + or %g3, %g2, %g3 + sll %g3, 16, %g2 + or %g3, %g2, %g3 + orcc %o2, %g0, %o1 +1: cmp %o1, 7 + bleu 7f + mov %o0, %g1 + + andcc %o0, 3, %o2 + bne 3b +4: andcc %o0, 4, %g0 + + be 2f + mov %g3, %g2 + + st %g3, [%o0] + sub %o1, 4, %o1 + add %o0, 4, %o0 +2: andcc %o1, 0xffffff80, %o3 + be 9f + andcc %o1, 0x78, %o2 +4: ZERO_BIG_BLOCK (%o0, 0x00, %g2) + subcc %o3, 128, %o3 + ZERO_BIG_BLOCK (%o0, 0x40, %g2) + bne 4b + add %o0, 128, %o0 + + orcc %o2, %g0, %g0 +9: be 6f + andcc %o1, 7, %o1 + + mov %o7, %g4 +101: call 100f + srl %o2, 1, %o3 + mov %g4, %o7 + jmpl %o4 + (20f + 64 - 101b), %g0 + add %o0, %o2, %o0 + +100: retl + sub %o7, %o3, %o4 + +20: ZERO_LAST_BLOCKS(%o0, 0x48, %g2) + ZERO_LAST_BLOCKS(%o0, 0x08, %g2) + +6: be 8f + andcc %o1, 4, %g0 + be 1f + andcc %o1, 2, %g0 + st %g3, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %o1, 1, %g0 + sth %g3, [%o0] + add %o0, 2, %o0 +1: bne,a 8f + stb %g3, [%o0] +8: retl + mov %g1, %o0 +7: orcc %o1, 0, %g0 + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 1] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 2] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 3] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 4] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 5] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 6] +0: retl + nop +END(memset) +libc_hidden_def(memset) diff --git a/libc/string/sparc/sparc32/sparcv9b/memchr.S b/libc/string/sparc/sparc32/sparcv9b/memchr.S new file mode 100644 index 0000000..43a16ff --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/memchr.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/memchr.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/memcpy.S b/libc/string/sparc/sparc32/sparcv9b/memcpy.S new file mode 100644 index 0000000..2024869 --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/memcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/sparcv9b/memcpy.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/memset.S b/libc/string/sparc/sparc32/sparcv9b/memset.S new file mode 100644 index 0000000..e491731 --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/memset.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/memset.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/stpcpy.S b/libc/string/sparc/sparc32/sparcv9b/stpcpy.S new file mode 100644 index 0000000..17ffa5e --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/stpcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/stpcpy.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/strcat.S b/libc/string/sparc/sparc32/sparcv9b/strcat.S new file mode 100644 index 0000000..9ed125a --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/strcat.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcat.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/strchr.S b/libc/string/sparc/sparc32/sparcv9b/strchr.S new file mode 100644 index 0000000..6b2727a --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/strchr.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strchr.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/strcmp.S b/libc/string/sparc/sparc32/sparcv9b/strcmp.S new file mode 100644 index 0000000..854403f --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/strcmp.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcmp.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/strcpy.S b/libc/string/sparc/sparc32/sparcv9b/strcpy.S new file mode 100644 index 0000000..e8102bd --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/strcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcpy.S" diff --git a/libc/string/sparc/sparc32/sparcv9b/strlen.S b/libc/string/sparc/sparc32/sparcv9b/strlen.S new file mode 100644 index 0000000..8673333 --- /dev/null +++ b/libc/string/sparc/sparc32/sparcv9b/strlen.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strlen.S" diff --git a/libc/string/sparc/sparc32/stpcpy.S b/libc/string/sparc/sparc32/stpcpy.S new file mode 100644 index 0000000..daf116e --- /dev/null +++ b/libc/string/sparc/sparc32/stpcpy.S @@ -0,0 +1,161 @@ +/* Copy SRC to DEST returning the address of the terminating '\0' in DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + b 6f + or %o4, %lo(0x01010101), %o2 +1: retl + add %o0, -1, %o0 + +ENTRY(stpcpy) + andcc %o1, 3, %g0 + bne 10b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: andcc %o0, 3, %g0 + bne 16f + sub %g0, 4, %g1 + +11: add %g1, 4, %g1 + ld [%o1 + %g1], %o5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be,a 11b + st %o5, [%o0 + %g1] + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 14f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 13f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 12f + andcc %o5, 0xff, %g0 + bne 11b + st %o5, [%o0 + %g1] + add %o0, %g1, %o0 + retl + add %o0, 3, %o0 +12: srl %o5, 16, %o5 + sth %o5, [%o0 + %g1] + add %g1, 2, %g1 + stb %g0, [%o0 + %g1] + retl + add %o0, %g1, %o0 +13: srl %o5, 16, %o5 + sth %o5, [%o0 + %g1] + add %g1, 1, %g1 + retl + add %o0, %g1, %o0 +14: stb %g0, [%o0 + %g1] + retl + add %o0, %g1, %o0 + +15: srl %o5, 24, %o4 + srl %o5, 16, %g1 + stb %o4, [%o0] + srl %o5, 8, %g4 + stb %g1, [%o0 + 1] + stb %g4, [%o0 + 2] + stb %o5, [%o0 + 3] + add %o0, 4, %o0 +16: ld [%o1], %o5 + sub %o5, %o2, %o4 + andcc %o4, %o3, %g0 + be 15b + add %o1, 4, %o1 + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g4 + be 19f + stb %g4, [%o0] + srl %o5, 16, %g5 + andcc %g5, 0xff, %g4 + be 18f + stb %g4, [%o0 + 1] + srl %o5, 8, %g5 + andcc %g5, 0xff, %g4 + be 17f + stb %g4, [%o0 + 2] + andcc %o5, 0xff, %g4 + stb %g4, [%o0 + 3] + bne 16b + add %o0, 4, %o0 + retl + sub %o0, 1, %o0 +17: retl + add %o0, 2, %o0 +18: retl + add %o0, 1, %o0 +19: retl + nop +END(stpcpy) + +libc_hidden_def(stpcpy) diff --git a/libc/string/sparc/sparc32/strcat.S b/libc/string/sparc/sparc32/strcat.S new file mode 100644 index 0000000..eda029a --- /dev/null +++ b/libc/string/sparc/sparc32/strcat.S @@ -0,0 +1,348 @@ +/* strcat (dest, src) -- Append SRC on the end of DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: cmp %o4, 2 + be 1f + cmp %o4, 3 + ldub [%o1], %o5 + add %o1, 1, %o1 + stb %o5, [%o0] + be 3f + cmp %o5, 0 + be 0f + add %o0, 1, %o0 +1: lduh [%o1], %o5 + add %o1, 2, %o1 + srl %o5, 8, %o4 + cmp %o4, 0 + stb %o4, [%o0] + bne,a 2f + stb %o5, [%o0 + 1] + retl + mov %g2, %o0 +2: andcc %o5, 0xff, %o5 + bne 4f + add %o0, 2, %o0 + retl + mov %g2, %o0 +3: bne 4f + add %o0, 1, %o0 + retl + mov %g2, %o0 + +11: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 7f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 2f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 8f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 3f + add %o0, 1, %o0 + b 9f + or %o4, %lo(0x01010101), %o2 +1: or %o4, %lo(0x80808080), %o3 +2: sethi %hi(0x01010101), %o4 +3: or %o4, %lo(0x01010101), %o2 + b 3f + sub %o0, 1, %o0 + +ENTRY(strcat) + mov %o0, %g2 + andcc %o0, 3, %g0 + bne 11b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +7: sethi %hi(0x01010101), %o4 +8: or %o4, %lo(0x01010101), %o2 +9: ld [%o0], %o5 +7: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 9b + add %o0, 4, %o0 + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, -4, %o0 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, 1, %o0 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, 1, %o0 + andcc %o5, 0xff, %g0 + add %o0, 2, %o0 + bne,a 7b + ld [%o0], %o5 + sub %o0, 1, %o0 +3: andcc %o1, 3, %o4 + bne 10b +4: andcc %o0, 3, %g3 + bne 12f +1: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + add %o0, 4, %o0 + andcc %o4, %o3, %g0 + be,a 1b + st %o5, [%o0 - 4] + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 1f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 2f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + andcc %o5, 0xff, %g0 + bne 1b + st %o5, [%o0 - 4] + retl + mov %g2, %o0 +3: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + stb %g0, [%o0 - 2] + retl + mov %g2, %o0 +2: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + retl + mov %g2, %o0 +1: stb %g0, [%o0 - 4] + retl + mov %g2, %o0 + +12: add %o1, 4, %o1 + sub %o5, %o2, %o4 + cmp %g3, 2 + be 2f + cmp %g3, 3 + be 3f + andcc %o4, %o3, %g0 + bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 1, %o0 + srl %o5, 8, %g5 + sth %g5, [%o0 + 2] +1: add %o0, 4, %o0 +4: sll %o5, 24, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 8, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 6f + srl %o5, 16, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 8, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0f + andcc %o5, 0xff, %g0 +1: bne 4b + add %o0, 4, %o0 +9: stb %g0, [%o0] +0: retl + mov %g2, %o0 + +6: srl %g5, 16, %g5 + sth %g5, [%o0] + retl + mov %g2, %o0 + +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 + +5: andcc %g5, 0xff, %g4 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 7f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + stb %g4, [%o0] + sth %g5, [%o0 + 1] + sub %o0, 1, %o0 + bne 1b + andcc %o5, 0xff, %g0 + retl + mov %g2, %o0 + +7: stb %g4, [%o0] + stb %g0, [%o0 + 1] + retl + mov %g2, %o0 + +2: andcc %o4, %o3, %g0 + bne 5f + srl %o5, 16, %g5 + sth %g5, [%o0] + sub %o0, 2, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 16, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 16, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 16, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 8, %o4 +1: andcc %o4, 0xff, %g0 + be 8f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + sth %o5, [%o0] + retl + mov %g2, %o0 + +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 + +8: stb %g0, [%o0 + 4] + retl + mov %g2, %o0 + +5: srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + sth %g5, [%o0] + sub %o0, 2, %o0 + bne 1b + srl %o5, 8, %o4 + retl + mov %g2, %o0 + +3: bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 3, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 8, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 24, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 16, %o4 +1: andcc %o4, 0xff, %g0 + be 8b + srl %o5, 8, %o4 + andcc %o4, 0xff, %g0 + be 9f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + srl %o5, 8, %o5 + sth %o5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +9: srl %o5, 8, %o5 + sth %o5, [%o0 + 4] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g0 + stb %g5, [%o0] + sub %o0, 3, %o0 + bne 1b + srl %o5, 16, %o4 + retl + mov %g2, %o0 +END(strcat) + +libc_hidden_def(strcat) diff --git a/libc/string/sparc/sparc32/strchr.S b/libc/string/sparc/sparc32/strchr.S new file mode 100644 index 0000000..16710d4 --- /dev/null +++ b/libc/string/sparc/sparc32/strchr.S @@ -0,0 +1,287 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + David S. Miller . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + +#include + + .text + .align 4 +10: ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o5 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + or %o5, %lo(0x01010101), %o2 + b 6f + ld [%o0], %g4 +1: retl + sub %o0, 1, %o0 + +ENTRY(strchr) + andcc %o1, 0xff, %o1 + be 12f + sll %o1, 8, %o2 + andcc %o0, 3, %g0 + or %o1, %o2, %o2 + sethi %hi(0x80808080), %o4 + sll %o2, 16, %o3 + bne 10b + or %o3, %o2, %g2 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o5 +5: or %o5, %lo(0x01010101), %o2 +7: ld [%o0], %g4 +6: xor %g4, %g2, %g5 + sub %g4, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + sub %g5, %o2, %g6 + andn %o4, %g4, %o4 + andn %g6, %g5, %g5 +#else + sub %g5, %o2, %g5 +#endif + or %g5, %o4, %o4 + andcc %o4, %o3, %g0 + be 7b + add %o0, 4, %o0 + + /* Check every byte. */ +8: srl %g4, 24, %g5 +7: andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 4f + srl %g4, 16, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 3f + srl %g4, 8, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 2f + andcc %g4, 0xff, %g5 + be 9f + cmp %g5, %o1 + bne,a 6b + ld [%o0], %g4 + retl + sub %o0, 1, %o0 +2: retl + sub %o0, 2, %o0 +3: retl + sub %o0, 3, %o0 +4: retl + sub %o0, 4, %o0 +9: retl + clr %o0 + +11: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + b 6f + or %o4, %lo(0x01010101), %o2 +1: retl + sub %o0, 1, %o0 + +12: andcc %o0, 3, %g0 + bne 11b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: ld [%o0], %o5 +7: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 6b + add %o0, 4, %o0 + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o0, -4, %o4 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o4, 1, %o4 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o4, 1, %o4 + andcc %o5, 0xff, %g0 + bne,a 7b + ld [%o0], %o5 + add %o4, 1, %o4 +8: retl + mov %o4, %o0 + +13: ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: or %o4, %lo(0x01010101), %o2 + b 7f + ld [%o0], %g4 +END(strchr) +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif + +ENTRY(strrchr) + andcc %o1, 0xff, %o1 + clr %o5 + be 12b + sll %o1, 8, %o2 + andcc %o0, 3, %g0 + or %o1, %o2, %o2 + sethi %hi(0x80808080), %o4 + sll %o2, 16, %o3 + bne 13b + or %o3, %o2, %g2 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: ld [%o0], %g4 +7: xor %g4, %g2, %g5 + sub %g4, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + sub %g5, %o2, %g6 + andn %o4, %g4, %o4 + andn %g6, %g5, %g5 +#else + sub %g5, %o2, %g5 +#endif + or %g5, %o4, %o4 + andcc %o4, %o3, %g0 + be 6b + add %o0, 4, %o0 + + /* Check every byte. */ +3: srl %g4, 24, %g5 +8: andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 4, %o5 +1: srl %g4, 16, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 3, %o5 +1: srl %g4, 8, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 2, %o5 +1: andcc %g4, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 1, %o5 +1: b 7b + ld [%o0], %g4 +9: retl + mov %o5, %o0 +END(strrchr) +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/libc/string/sparc/sparc32/strcmp.S b/libc/string/sparc/sparc32/strcmp.S new file mode 100644 index 0000000..d43883d --- /dev/null +++ b/libc/string/sparc/sparc32/strcmp.S @@ -0,0 +1,256 @@ +/* Compare two strings for differences. + For SPARC v7. + Copyright (C) 1996, 97, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o0, 3, %g0 + be 4f + or %g1, %lo(0x80808080), %o3 + ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %g1 + ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o1, 3, %g2 + bne 12f + or %g1, %lo(0x01010101), %o2 + b 1f + ld [%o0], %o4 +2: retl + mov %o4, %o0 + +ENTRY(strcmp) + andcc %o0, 3, %g0 + bne 10b + sethi %hi(0x80808080), %g1 + or %g1, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %g1 +5: andcc %o1, 3, %g2 + bne 12f + or %g1, %lo(0x01010101), %o2 + +0: ld [%o0], %o4 +1: ld [%o1], %o5 + sub %o4, %o2, %g1 + add %o0, 4, %o0 + cmp %o4, %o5 +#ifdef EIGHTBIT_NOT_RARE + andn %g1, %o4, %g1 +#endif + bne 11f + andcc %g1, %o3, %g0 + be 0b + add %o1, 4, %o1 + + srl %o4, 24, %g4 + andcc %g4, 0xff, %g0 + be 2f + srl %o4, 16, %g4 + andcc %g4, 0xff, %g0 + be 2f + srl %o4, 8, %g4 + andcc %g4, 0xff, %g0 + be 2f + andcc %o4, 0xff, %g0 + bne,a 1b + ld [%o0], %o4 +2: retl + clr %o0 + +11: srl %o4, 24, %g4 + srl %o5, 24, %g5 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + srl %o5, 16, %g5 + srl %o4, 16, %g4 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + srl %o5, 8, %g5 + srl %o4, 8, %g4 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + subcc %o4, %o5, %o4 + retl + mov %o4, %o0 +3: retl + mov %g4, %o0 + +12: save %sp, -64, %sp + ld [%i0], %i4 + sll %g2, 3, %g3 + andn %i1, 3, %i1 + mov 32, %l1 + ld [%i1], %l2 + mov -1, %g6 + add %i1, 4, %i1 + sub %l1, %g3, %l1 + sll %g6, %g3, %g6 + +1: sll %l2, %g3, %g5 + and %i4, %g6, %l3 + sub %i4, %i2, %g1 +#ifdef EIGHTBIT_NOT_RARE + andn %g1, %i4, %g1 +#endif + andcc %g1, %i3, %g1 + bne 3f + cmp %g5, %l3 + bne 2f + add %i0, 4, %i0 + ld [%i1], %l2 + add %i1, 4, %i1 + srl %l2, %l1, %l4 + or %l4, %g5, %l4 + cmp %l4, %i4 + be,a 1b + ld [%i0], %i4 + restore %l4, %g0, %o3 + retl + sub %o4, %o3, %o0 + +2: sll %l2, %g3, %i2 + srl %i4, %g3, %i3 + srl %i2, %g3, %i2 + restore + retl + sub %o3, %o2, %o0 + +3: srl %i4, 24, %g4 + srl %g5, 24, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + cmp %g2, 3 + be 6f + srl %i4, 16, %g4 + srl %g5, 16, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + cmp %g2, 2 + be 5f + srl %i4, 8, %g4 + srl %g5, 8, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + add %i0, 4, %i0 + ld [%i1], %l2 + add %i1, 4, %i1 + srl %l2, 24, %g5 + andcc %i4, 0xff, %g4 + be 4f + subcc %g4, %g5, %g4 + be,a 1b + ld [%i0], %i4 +4: jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 + +5: ld [%i1], %l2 + add %i1, 4, %i1 + add %i0, 4, %i0 + srl %l2, 24, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 16, %l6 + andcc %i4, 0xff, %g4 + and %l6, 0xff, %l6 + be 4b + subcc %g4, %l6, %g4 + be,a 1b + ld [%i0], %i4 + jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 + +6: ld [%i1], %l2 + add %i1, 4, %i1 + add %i0, 4, %i0 + srl %l2, 24, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 16, %l6 + srl %i4, 8, %g4 + and %l6, 0xff, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 8, %l6 + andcc %i4, 0xff, %g4 + and %l6, 0xff, %l6 + be 4b + subcc %g4, %l6, %g4 + be,a 1b + ld [%i0], %i4 + jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 +END(strcmp) +libc_hidden_def(strcmp) diff --git a/libc/string/sparc/sparc32/strcpy.S b/libc/string/sparc/sparc32/strcpy.S new file mode 100644 index 0000000..4d7742e --- /dev/null +++ b/libc/string/sparc/sparc32/strcpy.S @@ -0,0 +1,273 @@ +/* Copy SRC to DEST returning DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +1: ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + b 6f + andcc %o0, 3, %g3 + +ENTRY(strcpy) + mov %o0, %g2 + andcc %o1, 3, %g0 + bne 1b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: andcc %o0, 3, %g3 +6: bne 10f + or %o4, %lo(0x01010101), %o2 +1: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 + add %o0, 4, %o0 + andcc %o4, %o3, %g0 + be,a 1b + st %o5, [%o0 - 4] + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 1f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 2f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + andcc %o5, 0xff, %g0 + bne 1b + st %o5, [%o0 - 4] + retl + mov %g2, %o0 +3: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + stb %g0, [%o0 - 2] + retl + mov %g2, %o0 +2: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + retl + mov %g2, %o0 +1: stb %g0, [%o0 - 4] + retl + mov %g2, %o0 + +10: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 + cmp %g3, 2 + be 2f + cmp %g3, 3 + be 3f + andcc %o4, %o3, %g0 + bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 1, %o0 + srl %o5, 8, %g5 + sth %g5, [%o0 + 2] +1: add %o0, 4, %o0 +4: sll %o5, 24, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 8, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 6f + srl %o5, 16, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 8, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0f + andcc %o5, 0xff, %g0 +1: bne 4b + add %o0, 4, %o0 +9: stb %g0, [%o0] +0: retl + mov %g2, %o0 +6: srl %g5, 16, %g5 + sth %g5, [%o0] + retl + mov %g2, %o0 +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g4 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 7f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + stb %g4, [%o0] + sth %g5, [%o0 + 1] + sub %o0, 1, %o0 + bne 1b + andcc %o5, 0xff, %g0 + retl + mov %g2, %o0 +7: stb %g4, [%o0] + stb %g0, [%o0 + 1] + retl + mov %g2, %o0 + +2: andcc %o4, %o3, %g0 + bne 5f + srl %o5, 16, %g5 + sth %g5, [%o0] + sub %o0, 2, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 16, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 16, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 16, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 8, %o4 +1: andcc %o4, 0xff, %g0 + be 8f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + sth %o5, [%o0] + retl + mov %g2, %o0 +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +8: stb %g0, [%o0 + 4] + retl + mov %g2, %o0 +5: srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + sth %g5, [%o0] + sub %o0, 2, %o0 + bne 1b + srl %o5, 8, %o4 + retl + mov %g2, %o0 + +3: bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 3, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 8, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 24, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 16, %o4 +1: andcc %o4, 0xff, %g0 + be 8b + srl %o5, 8, %o4 + andcc %o4, 0xff, %g0 + be 9f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + srl %o5, 8, %o5 + sth %o5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +9: srl %o5, 8, %o5 + sth %o5, [%o0 + 4] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g0 + stb %g5, [%o0] + sub %o0, 3, %o0 + bne 1b + srl %o5, 16, %o4 + retl + mov %g2, %o0 +END(strcpy) +libc_hidden_def(strcpy) diff --git a/libc/string/sparc/sparc32/strlen.S b/libc/string/sparc/sparc32/strlen.S new file mode 100644 index 0000000..4edfe7e --- /dev/null +++ b/libc/string/sparc/sparc32/strlen.S @@ -0,0 +1,102 @@ +/* Determine the length of a string. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 2f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 3f + add %o0, 1, %o0 + b 11f + or %o4, %lo(0x01010101), %o2 +1: retl + mov 0, %o0 +2: retl + mov 1, %o0 +3: retl + mov 2, %o0 + +ENTRY(strlen) + mov %o0, %o1 + andcc %o0, 3, %g0 + bne 10b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +11: ld [%o0], %o5 +12: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 11b + add %o0, 4, %o0 + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o0, -4, %o4 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o4, 1, %o4 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o4, 1, %o4 + andcc %o5, 0xff, %g0 + bne,a 12b + ld [%o0], %o5 + add %o4, 1, %o4 +13: retl + sub %o4, %o1, %o0 +END(strlen) +libc_hidden_def(strlen) diff --git a/libc/string/sparc/sparc64/memchr.S b/libc/string/sparc/sparc64/memchr.S new file mode 100644 index 0000000..6096cc2 --- /dev/null +++ b/libc/string/sparc/sparc64/memchr.S @@ -0,0 +1,261 @@ +/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in STR less + than N. + For SPARC v9. + Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + This version is developed using the same algorithm as the fast C + version which carries the following introduction: + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(memchr) + and %o1, 0xff, %o1 /* IEU0 Group */ +#ifdef USE_BPR + brz,pn %o2, 12f /* CTI+IEU1 */ +#else + tst %o2 /* IEU1 */ + be,pn %XCC, 12f /* CTI */ +#endif + sll %o1, 8, %g3 /* IEU0 Group */ + add %o0, %o2, %o2 /* IEU1 */ + + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + or %g3, %o1, %g3 /* IEU1 */ + ldub [%o0], %o3 /* Load */ + sllx %g3, 16, %g5 /* IEU0 Group */ + + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + or %g3, %g5, %g3 /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + + cmp %o3, %o1 /* IEU1 */ + be,pn %xcc, 13f /* CTI */ + or %g1, %g2, %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + + bne,a,pn %icc, 21f /* CTI */ + add %o0, 1, %o0 /* IEU0 Group */ + ldx [%o0], %o3 /* Load Group */ + sllx %g1, 7, %g2 /* IEU0 */ + + or %g3, %g5, %g3 /* IEU1 */ +1: add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: cmp %o0, %o2 /* IEU1 Group */ + + bg,pn %XCC, 11f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + sub %o4, %g1, %o5 /* IEU0 Group */ + add %o0, 8, %o0 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o5, %o4, %o5 /* IEU0 Group */ +#endif + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o4, 56, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 3f /* CTI */ + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + bne,pt %icc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + retl /* CTI+IEU1 Group */ + + add %o0, -9, %o0 /* IEU0 */ + + .align 16 +3: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ +4: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ + +5: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ +6: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ + +7: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ +8: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ + +9: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ +11: sub %o4, %g1, %o5 /* IEU0 Group */ + sub %o0, 8, %o0 /* IEU1 */ + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 12f /* CTI */ + sub %o2, %o0, %o2 /* IEU0 */ + tst %o2 /* IEU1 Group */ + + be,pn %XCC, 12f /* CTI */ + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 13f /* CTI */ + + cmp %o2, 1 /* IEU0 */ + be,pn %XCC, 12f /* CTI Group */ + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 14f /* CTI */ + cmp %o2, 2 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 15f /* CTI */ + cmp %o2, 3 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + cmp %o2, 4 /* IEU1 Group */ + + be,pn %XCC, 12f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 17f /* CTI */ + + cmp %o2, 5 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 18f /* CTI */ + cmp %o2, 6 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + nop /* IEU0 */ +12: retl /* CTI+IEU1 Group */ + + clr %o0 /* IEU0 */ + nop /* Stub */ +13: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + +14: retl /* CTI+IEU1 Group */ + add %o0, 1, %o0 /* IEU0 */ +15: retl /* CTI+IEU1 Group */ + add %o0, 2, %o0 /* IEU0 */ + +16: retl /* CTI+IEU1 Group */ + add %o0, 3, %o0 /* IEU0 */ +17: retl /* CTI+IEU1 Group */ + add %o0, 4, %o0 /* IEU0 */ + +18: retl /* CTI+IEU1 Group */ + add %o0, 5, %o0 /* IEU0 */ +19: retl /* CTI+IEU1 Group */ + add %o0, 6, %o0 /* IEU0 */ + +21: cmp %o0, %o2 /* IEU1 */ + be,pn %XCC, 12b /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + + or %g3, %g5, %g3 /* IEU1 */ +22: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 1b /* CTI */ + ldx [%o0], %o3 /* Load */ + + cmp %o3, %o1 /* IEU1 Group */ + be,pn %xcc, 23f /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + cmp %o0, %o2 /* IEU1 Group */ + + bne,a,pt %XCC, 22b /* CTI */ + ldub [%o0], %o3 /* Load */ + retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ + +23: retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ +END(memchr) + +libc_hidden_def(memchr) +#if !__BOUNDED_POINTERS__ +weak_alias(memchr,__ubp_memchr) +#endif diff --git a/libc/string/sparc/sparc64/memcpy.S b/libc/string/sparc/sparc64/memcpy.S new file mode 100644 index 0000000..db63d1d --- /dev/null +++ b/libc/string/sparc/sparc64/memcpy.S @@ -0,0 +1,923 @@ +/* Copy SIZE bytes from SRC to DEST. + For UltraSPARC. + Copyright (C) 1996, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@caip.rutgers.edu) and + Jakub Jelinek (jakub@redhat.com). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#define XCC xcc +#endif +#define FPRS_FEF 4 + +#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + faligndata %f1, %f2, %f48; \ + faligndata %f2, %f3, %f50; \ + faligndata %f3, %f4, %f52; \ + faligndata %f4, %f5, %f54; \ + faligndata %f5, %f6, %f56; \ + faligndata %f6, %f7, %f58; \ + faligndata %f7, %f8, %f60; \ + faligndata %f8, %f9, %f62; + +#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ + ldda [%src] %asi, %fdest; \ + add %src, 0x40, %src; \ + add %dest, 0x40, %dest; \ + subcc %len, 0x40, %len; \ + be,pn %xcc, jmptgt; \ + stda %fsrc, [%dest - 0x40] %asi; + +#define LOOP_CHUNK1(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) +#define LOOP_CHUNK2(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) +#define LOOP_CHUNK3(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) + +#define STORE_SYNC(dest, fsrc) \ + stda %fsrc, [%dest] %asi; \ + add %dest, 0x40, %dest; + +#define STORE_JUMP(dest, fsrc, target) \ + stda %fsrc, [%dest] %asi; \ + add %dest, 0x40, %dest; \ + ba,pt %xcc, target; + +#define VISLOOP_PAD nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; + +#define FINISH_VISCHUNK(dest, f0, f1, left) \ + subcc %left, 8, %left; \ + bl,pn %xcc, 205f; \ + faligndata %f0, %f1, %f48; \ + std %f48, [%dest]; \ + add %dest, 8, %dest; + +#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ + subcc %left, 8, %left; \ + bl,pn %xcc, 205f; \ + fsrc1 %f0, %f1; \ + ba,a,pt %xcc, 204f; + + /* Macros for non-VIS memcpy code. */ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + ldx [%src + offset + 0x10], %t2; \ + ldx [%src + offset + 0x18], %t3; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst + offset + 0x08]; \ + stw %t2, [%dst + offset + 0x14]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst + offset + 0x10]; \ + stw %t3, [%dst + offset + 0x1c]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst + offset + 0x18]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + ldx [%src + offset + 0x10], %t2; \ + ldx [%src + offset + 0x18], %t3; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; \ + stx %t2, [%dst + offset + 0x10]; \ + stx %t3, [%dst + offset + 0x18]; \ + ldx [%src + offset + 0x20], %t0; \ + ldx [%src + offset + 0x28], %t1; \ + ldx [%src + offset + 0x30], %t2; \ + ldx [%src + offset + 0x38], %t3; \ + stx %t0, [%dst + offset + 0x20]; \ + stx %t1, [%dst + offset + 0x28]; \ + stx %t2, [%dst + offset + 0x30]; \ + stx %t3, [%dst + offset + 0x38]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x10], %t0; \ + ldx [%src - offset - 0x08], %t1; \ + stw %t0, [%dst - offset - 0x0c]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t1, [%dst - offset - 0x04]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src - offset - 0x10], %t0; \ + ldx [%src - offset - 0x08], %t1; \ + stx %t0, [%dst - offset - 0x10]; \ + stx %t1, [%dst - offset - 0x08]; + + /* Macros for non-VIS memmove code. */ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stw %t0, [%dst - offset - 0x1c]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst - offset - 0x20]; \ + stw %t1, [%dst - offset - 0x14]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst - offset - 0x18]; \ + stw %t2, [%dst - offset - 0x0c]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t3, [%dst - offset - 0x04]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stx %t0, [%dst - offset - 0x20]; \ + stx %t1, [%dst - offset - 0x18]; \ + stx %t2, [%dst - offset - 0x10]; \ + stx %t3, [%dst - offset - 0x08]; \ + ldx [%src - offset - 0x40], %t0; \ + ldx [%src - offset - 0x38], %t1; \ + ldx [%src - offset - 0x30], %t2; \ + ldx [%src - offset - 0x28], %t3; \ + stx %t0, [%dst - offset - 0x40]; \ + stx %t1, [%dst - offset - 0x38]; \ + stx %t2, [%dst - offset - 0x30]; \ + stx %t3, [%dst - offset - 0x28]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst + offset + 0x08]; + +#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; + + .text + .align 32 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + sub %o1, %o0, %o4 /* IEU0 Group */ + mov %o0, %g3 /* IEU1 */ + cmp %o4, %o2 /* IEU1 Group */ + mov %o1, %o0 /* IEU0 */ + bgeu,pt %XCC, 210f /* CTI */ + mov %g3, %o1 /* IEU0 Group */ +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 */ +#endif + brnz,pn %o2, 220f /* CTI Group */ + add %o0, %o2, %o0 /* IEU0 */ + retl + nop +END(bcopy) +#endif + + .align 32 +200: be,pt %xcc, 201f /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + mov 8, %g1 /* IEU0 */ + sub %g1, %g2, %g2 /* IEU0 Group */ + andcc %o0, 1, %g0 /* IEU1 */ + be,pt %icc, 2f /* CTI */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1], %o5 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + be,pn %xcc, 3f /* CTI */ + stb %o5, [%o0 - 1] /* Store */ +2: ldub [%o1], %o5 /* Load Group */ + add %o0, 2, %o0 /* IEU0 */ + ldub [%o1 + 1], %g3 /* Load Group */ + subcc %g2, 2, %g2 /* IEU1 Group */ + stb %o5, [%o0 - 2] /* Store */ + add %o1, 2, %o1 /* IEU0 */ + bne,pt %xcc, 2b /* CTI Group */ + stb %g3, [%o0 - 1] /* Store */ +3: andcc %o0, 0x38, %g5 /* IEU1 Group */ +201: be,pt %icc, 202f /* CTI */ + mov 64, %g1 /* IEU0 */ + fmovd %f0, %f2 /* FPU */ + sub %g1, %g5, %g5 /* IEU0 Group */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ + sub %o2, %g5, %o2 /* IEU0 */ +1: ldd [%g1 + 0x8], %f6 /* Load Group */ + add %g1, 0x8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 202f /* CTI */ + add %o0, 8, %o0 /* IEU1 */ + ldd [%g1 + 0x8], %f4 /* Load Group */ + add %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 */ + bne,pt %xcc, 1b /* CTI Group */ + add %o0, 8, %o0 /* IEU0 */ +202: membar #LoadStore | #StoreStore | #StoreLoad /* LSU Group */ + wr %g0, ASI_BLK_P, %asi /* LSU Group */ + subcc %o2, 0x40, %g6 /* IEU1 Group */ + mov %o1, %g1 /* IEU0 */ + andncc %g6, (0x40 - 1), %g6 /* IEU1 Group */ + srl %g1, 3, %g2 /* IEU0 */ + sub %o2, %g6, %g3 /* IEU0 Group */ + andn %o1, (0x40 - 1), %o1 /* IEU1 */ + and %g2, 7, %g2 /* IEU0 Group */ + andncc %g3, 0x7, %g3 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + sub %g3, 0x10, %g3 /* IEU0 Group */ + sub %o2, %g6, %o2 /* IEU1 */ + alignaddr %g1, %g0, %g0 /* GRU Group */ + add %g1, %g6, %g1 /* IEU0 Group */ + subcc %o2, %g3, %o2 /* IEU1 */ + ldda [%o1 + 0x00] %asi, %f0 /* LSU Group */ + add %g1, %g3, %g1 /* IEU0 */ + ldda [%o1 + 0x40] %asi, %f16 /* LSU Group */ + sub %g6, 0x80, %g6 /* IEU0 */ + ldda [%o1 + 0x80] %asi, %f32 /* LSU Group */ + /* Clk1 Group 8-( */ + /* Clk2 Group 8-( */ + /* Clk3 Group 8-( */ + /* Clk4 Group 8-( */ +203: rd %pc, %g5 /* PDU Group 8-( */ + addcc %g5, %lo(300f - 203b), %g5 /* IEU1 Group */ + sll %g2, 9, %g2 /* IEU0 */ + jmpl %g5 + %g2, %g0 /* CTI Group brk forced*/ + addcc %o1, 0xc0, %o1 /* IEU1 Group */ + + .align 512 /* OK, here comes the fun part... */ +300: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g6, 301f) + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g6, 302f) + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) LOOP_CHUNK3(o1, o0, g6, 303f) + b,pt %xcc, 300b+4; faligndata %f0, %f2, %f48 +301: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_JUMP(o0, f48, 400f) membar #Sync +302: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, 416f) membar #Sync +303: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, 432f) membar #Sync + VISLOOP_PAD +310: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g6, 311f) + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g6, 312f) + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) LOOP_CHUNK3(o1, o0, g6, 313f) + b,pt %xcc, 310b+4; faligndata %f2, %f4, %f48 +311: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_JUMP(o0, f48, 402f) membar #Sync +312: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, 418f) membar #Sync +313: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, 434f) membar #Sync + VISLOOP_PAD +320: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g6, 321f) + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g6, 322f) + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) LOOP_CHUNK3(o1, o0, g6, 323f) + b,pt %xcc, 320b+4; faligndata %f4, %f6, %f48 +321: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_JUMP(o0, f48, 404f) membar #Sync +322: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, 420f) membar #Sync +323: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, 436f) membar #Sync + VISLOOP_PAD +330: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g6, 331f) + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g6, 332f) + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) LOOP_CHUNK3(o1, o0, g6, 333f) + b,pt %xcc, 330b+4; faligndata %f6, %f8, %f48 +331: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_JUMP(o0, f48, 406f) membar #Sync +332: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, 422f) membar #Sync +333: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, 438f) membar #Sync + VISLOOP_PAD +340: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g6, 341f) + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g6, 342f) + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) LOOP_CHUNK3(o1, o0, g6, 343f) + b,pt %xcc, 340b+4; faligndata %f8, %f10, %f48 +341: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_JUMP(o0, f48, 408f) membar #Sync +342: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, 424f) membar #Sync +343: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, 440f) membar #Sync + VISLOOP_PAD +350: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g6, 351f) + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g6, 352f) + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g6, 353f) + b,pt %xcc, 350b+4; faligndata %f10, %f12, %f48 +351: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, 410f) membar #Sync +352: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, 426f) membar #Sync +353: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, 442f) membar #Sync + VISLOOP_PAD +360: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g6, 361f) + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g6, 362f) + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g6, 363f) + b,pt %xcc, 360b+4; faligndata %f12, %f14, %f48 +361: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, 412f) membar #Sync +362: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, 428f) membar #Sync +363: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, 444f) membar #Sync + VISLOOP_PAD +370: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g6, 371f) + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g6, 372f) + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g6, 373f) + b,pt %xcc, 370b+4; faligndata %f14, %f16, %f48 +371: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, 414f) membar #Sync +372: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, 430f) membar #Sync +373: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, 446f) membar #Sync + VISLOOP_PAD +400: FINISH_VISCHUNK(o0, f0, f2, g3) +402: FINISH_VISCHUNK(o0, f2, f4, g3) +404: FINISH_VISCHUNK(o0, f4, f6, g3) +406: FINISH_VISCHUNK(o0, f6, f8, g3) +408: FINISH_VISCHUNK(o0, f8, f10, g3) +410: FINISH_VISCHUNK(o0, f10, f12, g3) +412: FINISH_VISCHUNK(o0, f12, f14, g3) +414: UNEVEN_VISCHUNK(o0, f14, f0, g3) +416: FINISH_VISCHUNK(o0, f16, f18, g3) +418: FINISH_VISCHUNK(o0, f18, f20, g3) +420: FINISH_VISCHUNK(o0, f20, f22, g3) +422: FINISH_VISCHUNK(o0, f22, f24, g3) +424: FINISH_VISCHUNK(o0, f24, f26, g3) +426: FINISH_VISCHUNK(o0, f26, f28, g3) +428: FINISH_VISCHUNK(o0, f28, f30, g3) +430: UNEVEN_VISCHUNK(o0, f30, f0, g3) +432: FINISH_VISCHUNK(o0, f32, f34, g3) +434: FINISH_VISCHUNK(o0, f34, f36, g3) +436: FINISH_VISCHUNK(o0, f36, f38, g3) +438: FINISH_VISCHUNK(o0, f38, f40, g3) +440: FINISH_VISCHUNK(o0, f40, f42, g3) +442: FINISH_VISCHUNK(o0, f42, f44, g3) +444: FINISH_VISCHUNK(o0, f44, f46, g3) +446: UNEVEN_VISCHUNK(o0, f46, f0, g3) +204: ldd [%o1], %f2 /* Load Group */ + add %o1, 8, %o1 /* IEU0 */ + subcc %g3, 8, %g3 /* IEU1 */ + faligndata %f0, %f2, %f8 /* GRU Group */ + std %f8, [%o0] /* Store */ + bl,pn %xcc, 205f /* CTI */ + add %o0, 8, %o0 /* IEU0 Group */ + ldd [%o1], %f0 /* Load Group */ + add %o1, 8, %o1 /* IEU0 */ + subcc %g3, 8, %g3 /* IEU1 */ + faligndata %f2, %f0, %f8 /* GRU Group */ + std %f8, [%o0] /* Store */ + bge,pt %xcc, 204b /* CTI */ + add %o0, 8, %o0 /* IEU0 Group */ +205: brz,pt %o2, 207f /* CTI Group */ + mov %g1, %o1 /* IEU0 */ +206: ldub [%o1], %g5 /* LOAD */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 206b /* CTI */ + stb %g5, [%o0 - 1] /* Store Group */ +207: membar #StoreLoad | #StoreStore /* LSU Group */ + wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 + +208: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1], %g5 /* LOAD Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 209f /* CTI */ + stb %g5, [%o0 - 1] /* Store */ +2: ldub [%o1], %g5 /* LOAD Group */ + add %o0, 2, %o0 /* IEU0 */ + ldub [%o1 + 1], %o5 /* LOAD Group */ + add %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %g5, [%o0 - 2] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %o5, [%o0 - 1] /* Store */ +209: retl + mov %g4, %o0 + +#ifdef USE_BPR + + /* void *__align_cpy_4(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 3)) + */ + + .align 32 +ENTRY(__align_cpy_4) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, 15 /* IEU1 */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 200b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + ba,pt %xcc, 216f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ +END(__align_cpy_4) + + /* void *__align_cpy_8(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 7)) + */ + + .align 32 +ENTRY(__align_cpy_8) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, 15 /* IEU1 */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 201b /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + andcc %o2, -128, %g6 /* IEU1 Group */ + bne,a,pt %xcc, 82f + 4 /* CTI */ + ldx [%o1], %g1 /* Load */ + ba,pt %xcc, 41f /* CTI Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ +END(__align_cpy_8) + + /* void *__align_cpy_16(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 15)) + */ + + .align 32 +ENTRY(__align_cpy_16) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, (64 * 6) /* IEU1 */ + bgeu,pn %xcc, 201b /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + andcc %o2, -128, %g6 /* IEU1 Group */ + bne,a,pt %xcc, 82f + 4 /* CTI */ + ldx [%o1], %g1 /* Load */ + ba,pt %xcc, 41f /* CTI Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ +END(__align_cpy_16) + +#endif + + .align 32 +ENTRY(memcpy) +210: +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, 209b /* CTI Group */ + mov %o0, %g4 /* IEU0 */ +218: cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 200b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 212f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 216f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1], %g2 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + bne,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0 - 1] /* Store */ +4: lduh [%o1], %g2 /* Load Group */ + add %o1, 2, %o1 /* IEU0 */ + add %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +216: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1], %g5 /* Load Group */ + add %o1, 4, %o1 /* IEU0 */ + add %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0 - 4] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 215f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 82f + 4 /* CTI Group */ +5: MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) +35: subcc %g6, 128, %g6 /* IEU1 Group */ + add %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + add %o0, 128, %o0 /* IEU0 Group */ +215: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 80f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +79: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + add %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(80f - 79b), %g0 /* CTI Group brk forced*/ + add %o0, %g6, %o0 /* IEU0 Group */ +36: MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +80: be,pt %xcc, 81f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1], %g2 /* Load Group */ + add %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 - 0x4] /* Store Group */ + add %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0 - 0x8] /* Store */ +81: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1], %g2 /* Load Group */ + add %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0] /* Store Group */ + add %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1], %g2 /* Load Group */ + add %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0] /* Store Group */ + add %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1], %g2 /* Load Group */ + stb %g2, [%o0] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +82: MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) +37: subcc %g6, 128, %g6 /* IEU1 Group */ + add %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 82b /* CTI */ + add %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 84f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +83: rd %pc, %o5 /* PDU Group */ + add %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(84f - 83b), %g0 /* CTI Group brk forced*/ + add %o0, %g6, %o0 /* IEU0 Group */ +38: MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +84: be,pt %xcc, 85f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1], %g2 /* Load Group */ + add %o0, 8, %o0 /* IEU0 */ + add %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0 - 0x8] /* Store */ +85: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1], %g2 /* Load Group */ + add %o0, 4, %o0 /* IEU0 */ + add %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0 - 0x4] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1], %g2 /* Load Group */ + add %o0, 2, %o0 /* IEU0 */ + add %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0 - 0x2] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1], %g2 /* Load Group */ + stb %g2, [%o0] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +212: brz,pt %g2, 2f /* CTI Group */ + mov 8, %g1 /* IEU0 */ + sub %g1, %g2, %g2 /* IEU0 Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1], %g5 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0 - 1] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 + 0x8], %f6 /* Load Group */ + add %g1, 0x8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 213f /* CTI */ + add %o0, 8, %o0 /* IEU1 */ + ldd [%g1 + 0x8], %f4 /* Load Group */ + add %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + add %o0, 8, %o0 /* IEU0 */ +213: brz,pn %o2, 214f /* CTI Group */ + nop /* IEU0 */ + ldub [%o1], %g5 /* LOAD */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 206b /* CTI */ + stb %g5, [%o0 - 1] /* Store Group */ +214: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memcpy) +libc_hidden_def(memcpy) + + .align 32 +228: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 229f /* CTI */ + stb %o5, [%o0] /* Store */ +2: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o0, 2, %o0 /* IEU0 */ + ldub [%o1 - 2], %g5 /* LOAD Group */ + sub %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %o5, [%o0 + 1] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %g5, [%o0] /* Store */ +229: retl + mov %g4, %o0 +219: retl + nop + + .align 32 +ENTRY(memmove) +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, 219b /* CTI Group */ + sub %o0, %o1, %o4 /* IEU0 */ + cmp %o4, %o2 /* IEU1 Group */ + bgeu,pt %XCC, 218b /* CTI */ + mov %o0, %g4 /* IEU0 */ + add %o0, %o2, %o0 /* IEU0 Group */ +220: add %o1, %o2, %o1 /* IEU1 */ + cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 228b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 232f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 236f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + be,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0] /* Store */ +4: lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sub %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +236: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1 - 4], %g5 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + sub %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 235f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 282f + 4 /* CTI Group */ +5: RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ +235: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 280f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +279: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + sub %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(280f - 279b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +280: be,pt %xcc, 281f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 + 4] /* Store Group */ + sub %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +281: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0 - 4] /* Store Group */ + sub %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group */ + sub %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +282: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 282b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 284f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +283: rd %pc, %o5 /* PDU Group */ + sub %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(284f - 283b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +284: be,pt %xcc, 285f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + sub %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0] /* Store */ +285: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o0, 4, %o0 /* IEU0 */ + sub %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o0, 2, %o0 /* IEU0 */ + sub %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +232: brz,pt %g2, 2f /* CTI Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1 - 1], %g5 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 - 8], %f6 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 233f /* CTI */ + sub %o0, 8, %o0 /* IEU1 */ + ldd [%g1 - 8], %f4 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + sub %o0, 8, %o0 /* IEU0 */ +233: brz,pn %o2, 234f /* CTI Group */ + nop /* IEU0 */ +237: ldub [%o1 - 1], %g5 /* LOAD */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 237b /* CTI */ + stb %g5, [%o0] /* Store Group */ +234: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memmove) +libc_hidden_def(memmove) + +#ifdef USE_BPR +weak_alias(memcpy,__align_cpy_1) +weak_alias(memcpy,__align_cpy_2) +#endif diff --git a/libc/string/sparc/sparc64/memset.S b/libc/string/sparc/sparc64/memset.S new file mode 100644 index 0000000..50e404b --- /dev/null +++ b/libc/string/sparc/sparc64/memset.S @@ -0,0 +1,317 @@ +/* Set a block of memory to some byte value. + For UltraSPARC. + Copyright (C) 1996, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@caip.rutgers.edu) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR +#endif +#define FPRS_FEF 4 + +#define SET_BLOCKS(base, offset, source) \ + stx source, [base - offset - 0x18]; \ + stx source, [base - offset - 0x10]; \ + stx source, [base - offset - 0x08]; \ + stx source, [base - offset - 0x00]; + + /* Well, memset is a lot easier to get right than bcopy... */ + .text + .align 32 +ENTRY(memset) + andcc %o1, 0xff, %o1 + mov %o0, %o5 + be,a,pt %icc, 50f +#ifndef USE_BPR + srl %o2, 0, %o1 +#else + mov %o2, %o1 +#endif + cmp %o2, 7 +#ifndef USE_BPR + srl %o2, 0, %o2 +#endif + bleu,pn %XCC, 17f + andcc %o0, 3, %g5 + be,pt %xcc, 4f + and %o1, 0xff, %o1 + cmp %g5, 3 + be,pn %xcc, 2f + stb %o1, [%o0 + 0x00] + cmp %g5, 2 + be,pt %xcc, 2f + stb %o1, [%o0 + 0x01] + stb %o1, [%o0 + 0x02] +2: sub %g5, 4, %g5 + sub %o0, %g5, %o0 + add %o2, %g5, %o2 +4: sllx %o1, 8, %g1 + andcc %o0, 4, %g0 + or %o1, %g1, %o1 + sllx %o1, 16, %g1 + or %o1, %g1, %o1 + be,pt %xcc, 2f + sllx %o1, 32, %g1 + stw %o1, [%o0] + sub %o2, 4, %o2 + add %o0, 4, %o0 +2: cmp %o2, 128 + or %o1, %g1, %o1 + blu,pn %xcc, 9f + andcc %o0, 0x38, %g5 + be,pn %icc, 6f + mov 64, %o4 + andcc %o0, 8, %g0 + be,pn %icc, 1f + sub %o4, %g5, %o4 + stx %o1, [%o0] + add %o0, 8, %o0 +1: andcc %o4, 16, %g0 + be,pn %icc, 1f + sub %o2, %o4, %o2 + stx %o1, [%o0] + stx %o1, [%o0 + 8] + add %o0, 16, %o0 +1: andcc %o4, 32, %g0 + be,pn %icc, 7f + andncc %o2, 0x3f, %o3 + stw %o1, [%o0] + stw %o1, [%o0 + 4] + stw %o1, [%o0 + 8] + stw %o1, [%o0 + 12] + stw %o1, [%o0 + 16] + stw %o1, [%o0 + 20] + stw %o1, [%o0 + 24] + stw %o1, [%o0 + 28] + add %o0, 32, %o0 +7: be,pn %xcc, 9f + nop + ldd [%o0 - 8], %f0 +18: wr %g0, ASI_BLK_P, %asi + membar #StoreStore | #LoadStore + andcc %o3, 0xc0, %g5 + and %o2, 0x3f, %o2 + fmovd %f0, %f2 + fmovd %f0, %f4 + andn %o3, 0xff, %o3 + fmovd %f0, %f6 + cmp %g5, 64 + fmovd %f0, %f8 + fmovd %f0, %f10 + fmovd %f0, %f12 + brz,pn %g5, 10f + fmovd %f0, %f14 + be,pn %icc, 2f + stda %f0, [%o0 + 0x00] %asi + cmp %g5, 128 + be,pn %icc, 2f + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi +2: brz,pn %o3, 12f + add %o0, %g5, %o0 +10: stda %f0, [%o0 + 0x00] %asi + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi + stda %f0, [%o0 + 0xc0] %asi +11: subcc %o3, 256, %o3 + bne,pt %xcc, 10b + add %o0, 256, %o0 +12: wr %g0, FPRS_FEF, %fprs + membar #StoreLoad | #StoreStore +9: andcc %o2, 0x78, %g5 + be,pn %xcc, 13f + andcc %o2, 7, %o2 +14: rd %pc, %o4 + srl %g5, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + (13f - 14b), %g0 + add %o0, %g5, %o0 +12: SET_BLOCKS (%o0, 0x68, %o1) + SET_BLOCKS (%o0, 0x48, %o1) + SET_BLOCKS (%o0, 0x28, %o1) + SET_BLOCKS (%o0, 0x08, %o1) +13: be,pn %xcc, 8f + andcc %o2, 4, %g0 + be,pn %xcc, 1f + andcc %o2, 2, %g0 + stw %o1, [%o0] + add %o0, 4, %o0 +1: be,pn %xcc, 1f + andcc %o2, 1, %g0 + sth %o1, [%o0] + add %o0, 2, %o0 +1: bne,a,pn %xcc, 8f + stb %o1, [%o0] +8: retl + mov %o5, %o0 +17: brz,pn %o2, 0f +8: add %o0, 1, %o0 + subcc %o2, 1, %o2 + bne,pt %xcc, 8b + stb %o1, [%o0 - 1] +0: retl + mov %o5, %o0 + +6: stx %o1, [%o0] + andncc %o2, 0x3f, %o3 + be,pn %xcc, 9b + nop + ba,pt %xcc, 18b + ldd [%o0], %f0 +END(memset) +libc_hidden_def(memset) + +#define ZERO_BLOCKS(base, offset, source) \ + stx source, [base - offset - 0x38]; \ + stx source, [base - offset - 0x30]; \ + stx source, [base - offset - 0x28]; \ + stx source, [base - offset - 0x20]; \ + stx source, [base - offset - 0x18]; \ + stx source, [base - offset - 0x10]; \ + stx source, [base - offset - 0x08]; \ + stx source, [base - offset - 0x00]; + + .text + .align 32 +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bzero) +#ifndef USE_BPR + srl %o1, 0, %o1 +#endif + mov %o0, %o5 +#endif +50: cmp %o1, 7 + bleu,pn %xcc, 17f + andcc %o0, 3, %o2 + be,a,pt %xcc, 4f + andcc %o0, 4, %g0 + cmp %o2, 3 + be,pn %xcc, 2f + stb %g0, [%o0 + 0x00] + cmp %o2, 2 + be,pt %xcc, 2f + stb %g0, [%o0 + 0x01] + stb %g0, [%o0 + 0x02] +2: sub %o2, 4, %o2 + sub %o0, %o2, %o0 + add %o1, %o2, %o1 + andcc %o0, 4, %g0 +4: be,pt %xcc, 2f + cmp %o1, 128 + stw %g0, [%o0] + sub %o1, 4, %o1 + add %o0, 4, %o0 +2: blu,pn %xcc, 9f + andcc %o0, 0x38, %o2 + be,pn %icc, 6f + mov 64, %o4 + andcc %o0, 8, %g0 + be,pn %icc, 1f + sub %o4, %o2, %o4 + stx %g0, [%o0] + add %o0, 8, %o0 +1: andcc %o4, 16, %g0 + be,pn %icc, 1f + sub %o1, %o4, %o1 + stx %g0, [%o0] + stx %g0, [%o0 + 8] + add %o0, 16, %o0 +1: andcc %o4, 32, %g0 + be,pn %icc, 7f + andncc %o1, 0x3f, %o3 + stx %g0, [%o0] + stx %g0, [%o0 + 8] + stx %g0, [%o0 + 16] + stx %g0, [%o0 + 24] + add %o0, 32, %o0 +6: andncc %o1, 0x3f, %o3 +7: be,pn %xcc, 9f + wr %g0, ASI_BLK_P, %asi + membar #StoreLoad | #StoreStore | #LoadStore + fzero %f0 + andcc %o3, 0xc0, %o2 + and %o1, 0x3f, %o1 + fzero %f2 + andn %o3, 0xff, %o3 + faddd %f0, %f2, %f4 + fmuld %f0, %f2, %f6 + cmp %o2, 64 + faddd %f0, %f2, %f8 + fmuld %f0, %f2, %f10 + faddd %f0, %f2, %f12 + brz,pn %o2, 10f + fmuld %f0, %f2, %f14 + be,pn %icc, 2f + stda %f0, [%o0 + 0x00] %asi + cmp %o2, 128 + be,pn %icc, 2f + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi +2: brz,pn %o3, 12f + add %o0, %o2, %o0 +10: stda %f0, [%o0 + 0x00] %asi + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi + stda %f0, [%o0 + 0xc0] %asi +11: subcc %o3, 256, %o3 + bne,pt %xcc, 10b + add %o0, 256, %o0 +12: wr %g0, FPRS_FEF, %fprs + membar #StoreLoad | #StoreStore +9: andcc %o1, 0xf8, %o2 + be,pn %xcc, 13f + andcc %o1, 7, %o1 +14: rd %pc, %o4 + srl %o2, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + (13f - 14b), %g0 + add %o0, %o2, %o0 +12: ZERO_BLOCKS (%o0, 0xc8, %g0) + ZERO_BLOCKS (%o0, 0x88, %g0) + ZERO_BLOCKS (%o0, 0x48, %g0) + ZERO_BLOCKS (%o0, 0x08, %g0) +13: be,pn %xcc, 8f + andcc %o1, 4, %g0 + be,pn %xcc, 1f + andcc %o1, 2, %g0 + stw %g0, [%o0] + add %o0, 4, %o0 +1: be,pn %xcc, 1f + andcc %o1, 1, %g0 + sth %g0, [%o0] + add %o0, 2, %o0 +1: bne,a,pn %xcc, 8f + stb %g0, [%o0] +8: retl + mov %o5, %o0 +17: be,pn %xcc, 13b + orcc %o1, 0, %g0 + be,pn %xcc, 0f +8: add %o0, 1, %o0 + subcc %o1, 1, %o1 + bne,pt %xcc, 8b + stb %g0, [%o0 - 1] +0: retl + mov %o5, %o0 +#ifdef __UCLIBC_SUSV3_LEGACY__ +END(bzero) +#endif diff --git a/libc/string/sparc/sparc64/sparcv9b/memcpy.S b/libc/string/sparc/sparc64/sparcv9b/memcpy.S new file mode 100644 index 0000000..64f6a92 --- /dev/null +++ b/libc/string/sparc/sparc64/sparcv9b/memcpy.S @@ -0,0 +1,612 @@ +/* Copy SIZE bytes from SRC to DEST. + For UltraSPARC-III. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@redhat.com) + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define ASI_BLK_P 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs + +#ifndef XCC +#define USE_BPR +#define XCC xcc +#endif + + .register %g2,#scratch + .register %g3,#scratch + .register %g6,#scratch + + .text + .align 32 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + sub %o1, %o0, %o4 + mov %o0, %g4 + cmp %o4, %o2 + mov %o1, %o0 + bgeu,pt %XCC, 100f + mov %g4, %o1 +#ifndef USE_BPR + srl %o2, 0, %o2 +#endif + brnz,pn %o2, 220f + add %o0, %o2, %o0 + retl + nop +END(bcopy) +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + * + * The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + .align 32 +ENTRY(memcpy) + +100: /* %o0=dst, %o1=src, %o2=len */ + mov %o0, %g5 + cmp %o2, 0 + be,pn %XCC, out +218: or %o0, %o1, %o3 + cmp %o2, 16 + bleu,a,pn %XCC, small_copy + or %o3, %o2, %o3 + + cmp %o2, 256 + blu,pt %XCC, medium_copy + andcc %o3, 0x7, %g0 + + ba,pt %xcc, enter + andcc %o0, 0x3f, %g2 + + /* Here len >= 256 and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %XCC, 2f + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + + bg,pt %XCC, 1b + stb %o3, [%o0 + -1] + +2: VISEntryHalf + and %o1, 0x7, %g1 + ba,pt %xcc, begin + alignaddr %o1, %g0, %o1 + + .align 64 +begin: + prefetch [%o1 + 0x000], #one_read + prefetch [%o1 + 0x040], #one_read + andn %o2, (0x40 - 1), %o4 + prefetch [%o1 + 0x080], #one_read + prefetch [%o1 + 0x0c0], #one_read + ldd [%o1 + 0x000], %f0 + prefetch [%o1 + 0x100], #one_read + ldd [%o1 + 0x008], %f2 + prefetch [%o1 + 0x140], #one_read + ldd [%o1 + 0x010], %f4 + prefetch [%o1 + 0x180], #one_read + faligndata %f0, %f2, %f16 + ldd [%o1 + 0x018], %f6 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x020], %f8 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x028], %f10 + faligndata %f6, %f8, %f22 + + ldd [%o1 + 0x030], %f12 + faligndata %f8, %f10, %f24 + ldd [%o1 + 0x038], %f14 + faligndata %f10, %f12, %f26 + ldd [%o1 + 0x040], %f0 + + sub %o4, 0x80, %o4 + add %o1, 0x40, %o1 + ba,pt %xcc, loop + srl %o4, 6, %o3 + + .align 64 +loop: + ldd [%o1 + 0x008], %f2 + faligndata %f12, %f14, %f28 + ldd [%o1 + 0x010], %f4 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + ldd [%o1 + 0x018], %f6 + faligndata %f0, %f2, %f16 + + ldd [%o1 + 0x020], %f8 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x028], %f10 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x030], %f12 + faligndata %f6, %f8, %f22 + ldd [%o1 + 0x038], %f14 + faligndata %f8, %f10, %f24 + + ldd [%o1 + 0x040], %f0 + prefetch [%o1 + 0x180], #one_read + faligndata %f10, %f12, %f26 + subcc %o3, 0x01, %o3 + add %o1, 0x40, %o1 + bg,pt %XCC, loop + add %o0, 0x40, %o0 + + /* Finally we copy the last full 64-byte block. */ +loopfini: + ldd [%o1 + 0x008], %f2 + faligndata %f12, %f14, %f28 + ldd [%o1 + 0x010], %f4 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + ldd [%o1 + 0x018], %f6 + faligndata %f0, %f2, %f16 + ldd [%o1 + 0x020], %f8 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x028], %f10 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x030], %f12 + faligndata %f6, %f8, %f22 + ldd [%o1 + 0x038], %f14 + faligndata %f8, %f10, %f24 + cmp %g1, 0 + be,pt %XCC, 1f + add %o0, 0x40, %o0 + ldd [%o1 + 0x040], %f0 +1: faligndata %f10, %f12, %f26 + faligndata %f12, %f14, %f28 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + add %o0, 0x40, %o0 + add %o1, 0x40, %o1 + membar #Sync + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer. + */ +loopend: + and %o2, 0x3f, %o2 + andcc %o2, 0x38, %g2 + be,pn %XCC, endcruft + subcc %g2, 0x8, %g2 + be,pn %XCC, endcruft + cmp %g1, 0 + + be,a,pt %XCC, 1f + ldd [%o1 + 0x00], %f0 + +1: ldd [%o1 + 0x08], %f2 + add %o1, 0x8, %o1 + sub %o2, 0x8, %o2 + subcc %g2, 0x8, %g2 + faligndata %f0, %f2, %f8 + std %f8, [%o0 + 0x00] + be,pn %XCC, endcruft + add %o0, 0x8, %o0 + ldd [%o1 + 0x08], %f0 + add %o1, 0x8, %o1 + sub %o2, 0x8, %o2 + subcc %g2, 0x8, %g2 + faligndata %f2, %f0, %f8 + std %f8, [%o0 + 0x00] + bne,pn %XCC, 1b + add %o0, 0x8, %o0 + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %XCC, out + sub %o0, %o1, %o3 + + andcc %g1, 0x7, %g0 + bne,pn %icc, small_copy_unaligned + andcc %o2, 0x8, %g0 + be,pt %icc, 1f + nop + ldx [%o1], %o5 + stx %o5, [%o1 + %o3] + add %o1, 0x8, %o1 + +1: andcc %o2, 0x4, %g0 + be,pt %icc, 1f + nop + lduw [%o1], %o5 + stw %o5, [%o1 + %o3] + add %o1, 0x4, %o1 + +1: andcc %o2, 0x2, %g0 + be,pt %icc, 1f + nop + lduh [%o1], %o5 + sth %o5, [%o1 + %o3] + add %o1, 0x2, %o1 + +1: andcc %o2, 0x1, %g0 + be,pt %icc, out + nop + ldub [%o1], %o5 + ba,pt %xcc, out + stb %o5, [%o1 + %o3] + +medium_copy: /* 16 < len <= 64 */ + bne,pn %XCC, small_copy_unaligned + sub %o0, %o1, %o3 + +medium_copy_aligned: + andn %o2, 0x7, %o4 + and %o2, 0x7, %o2 +1: subcc %o4, 0x8, %o4 + ldx [%o1], %o5 + stx %o5, [%o1 + %o3] + bgu,pt %XCC, 1b + add %o1, 0x8, %o1 + andcc %o2, 0x4, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x4, %o2 + lduw [%o1], %o5 + stw %o5, [%o1 + %o3] + add %o1, 0x4, %o1 +1: cmp %o2, 0 + be,pt %XCC, out + nop + ba,pt %xcc, small_copy_unaligned + nop + +small_copy: /* 0 < len <= 16 */ + andcc %o3, 0x3, %g0 + bne,pn %XCC, small_copy_unaligned + sub %o0, %o1, %o3 + +small_copy_aligned: + subcc %o2, 4, %o2 + lduw [%o1], %g1 + stw %g1, [%o1 + %o3] + bgu,pt %XCC, small_copy_aligned + add %o1, 4, %o1 + +out: retl + mov %g5, %o0 + + .align 32 +small_copy_unaligned: + subcc %o2, 1, %o2 + ldub [%o1], %g1 + stb %g1, [%o1 + %o3] + bgu,pt %XCC, small_copy_unaligned + add %o1, 1, %o1 + retl + mov %g5, %o0 + +END(memcpy) +libc_hidden_def(memcpy) + +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stw %t0, [%dst - offset - 0x1c]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst - offset - 0x20]; \ + stw %t1, [%dst - offset - 0x14]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst - offset - 0x18]; \ + stw %t2, [%dst - offset - 0x0c]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t3, [%dst - offset - 0x04]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stx %t0, [%dst - offset - 0x20]; \ + stx %t1, [%dst - offset - 0x18]; \ + stx %t2, [%dst - offset - 0x10]; \ + stx %t3, [%dst - offset - 0x08]; \ + ldx [%src - offset - 0x40], %t0; \ + ldx [%src - offset - 0x38], %t1; \ + ldx [%src - offset - 0x30], %t2; \ + ldx [%src - offset - 0x28], %t3; \ + stx %t0, [%dst - offset - 0x40]; \ + stx %t1, [%dst - offset - 0x38]; \ + stx %t2, [%dst - offset - 0x30]; \ + stx %t3, [%dst - offset - 0x28]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst + offset + 0x08]; + +#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; + + .align 32 +228: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 229f /* CTI */ + stb %o5, [%o0] /* Store */ +2: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o0, 2, %o0 /* IEU0 */ + ldub [%o1 - 2], %g5 /* LOAD Group */ + sub %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %o5, [%o0 + 1] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %g5, [%o0] /* Store */ +229: retl + mov %g4, %o0 + + .align 32 +ENTRY(memmove) + mov %o0, %g5 +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, out /* CTI Group */ + sub %o0, %o1, %o4 /* IEU0 */ + cmp %o4, %o2 /* IEU1 Group */ + bgeu,pt %XCC, 218b /* CTI */ + mov %o0, %g4 /* IEU0 */ + add %o0, %o2, %o0 /* IEU0 Group */ +220: add %o1, %o2, %o1 /* IEU1 */ + cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 228b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 232f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 236f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + be,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0] /* Store */ +4: lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sub %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +236: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1 - 4], %g5 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + sub %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 235f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 282f + 4 /* CTI Group */ +5: RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ +235: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 280f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +279: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + sub %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(280f - 279b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +280: be,pt %xcc, 281f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 + 4] /* Store Group */ + sub %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +281: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0 - 4] /* Store Group */ + sub %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group */ + sub %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +282: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 282b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 284f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +283: rd %pc, %o5 /* PDU Group */ + sub %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(284f - 283b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +284: be,pt %xcc, 285f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + sub %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0] /* Store */ +285: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o0, 4, %o0 /* IEU0 */ + sub %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o0, 2, %o0 /* IEU0 */ + sub %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +232: brz,pt %g2, 2f /* CTI Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1 - 1], %g5 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 - 8], %f6 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 233f /* CTI */ + sub %o0, 8, %o0 /* IEU1 */ + ldd [%g1 - 8], %f4 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + sub %o0, 8, %o0 /* IEU0 */ +233: brz,pn %o2, 234f /* CTI Group */ + nop /* IEU0 */ +237: ldub [%o1 - 1], %g5 /* LOAD */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 237b /* CTI */ + stb %g5, [%o0] /* Store Group */ +234: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memmove) +libc_hidden_def(memmove) + +#ifdef USE_BPR +weak_alias(memcpy,__align_cpy_1) +weak_alias(memcpy,__align_cpy_2) +weak_alias(memcpy,__align_cpy_4) +weak_alias(memcpy,__align_cpy_8) +weak_alias(memcpy,__align_cpy_16) +#endif diff --git a/libc/string/sparc/sparc64/stpcpy.S b/libc/string/sparc/sparc64/stpcpy.S new file mode 100644 index 0000000..8c26c6b --- /dev/null +++ b/libc/string/sparc/sparc64/stpcpy.S @@ -0,0 +1,271 @@ +/* Copy SRC to DEST returning the address of the terminating '\0' in DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(stpcpy) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + bne,pn %icc, 12f /* CTI */ + andcc %o1, 7, %g3 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 14f /* CTI */ + + sllx %g1, 7, %g2 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ +2: mov %o3, %g3 /* IEU0 Group */ + + sub %o3, %g1, %o2 /* IEU1 */ +3: ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + andcc %o2, %g2, %g0 /* IEU1 */ + + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + srlx %g3, 56, %g5 /* IEU0 Group */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ + + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + srlx %g3, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + bne,pt %icc, 3b /* CTI */ + + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + sub %o0, 1, %o0 /* IEU0 */ + + .align 16 +6: ba,pt %xcc, 23f /* CTI Group */ + sub %o0, 3, %g6 /* IEU0 */ +5: sub %o0, 2, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 2] /* Store */ + + srlx %g3, 16, %g4 /* IEU0 Group */ +23: sth %g4, [%o0 - 4] /* Store */ + srlx %g3, 32, %g4 /* IEU0 Group */ + stw %g4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +8: ba,pt %xcc, 24f /* CTI Group */ + sub %o0, 5, %g6 /* IEU0 */ + +7: sub %o0, 4, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 4] /* Store */ + srlx %g3, 32, %g4 /* IEU0 Group */ +24: stw %g4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +10: ba,pt %xcc, 25f /* CTI Group */ + sub %o0, 7, %g6 /* IEU0 */ + +9: sub %o0, 6, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 6] /* Store */ + srlx %g3, 48, %g4 /* IEU0 */ +25: sth %g4, [%o0 - 8] /* Store Group */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, 8, %o0 /* IEU0 */ + + .align 16 +12: or %g1, %g2, %g1 /* IEU0 Group */ + ldub [%o1], %o3 /* Load */ + sllx %g1, 7, %g2 /* IEU0 Group */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ +14: orcc %g0, 64, %g4 /* IEU1 Group */ + + sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + sub %o0, 1, %o0 /* IEU0 */ + + .align 16 +17: ba,pt %xcc, 26f /* CTI Group */ + subcc %o0, 3, %g6 /* IEU1 */ +18: ba,pt %xcc, 27f /* CTI Group */ + subcc %o0, 4, %g6 /* IEU1 */ + +19: ba,pt %xcc, 28f /* CTI Group */ + subcc %o0, 5, %g6 /* IEU1 */ +16: subcc %o0, 2, %g6 /* IEU1 Group */ + srlx %o3, 8, %o4 /* IEU0 */ + + stb %o4, [%o0 - 2] /* Store */ +26: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ +27: srlx %o3, 24, %o4 /* IEU0 Group */ + + stb %o4, [%o0 - 4] /* Store */ +28: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +21: ba,pt %xcc, 29f /* CTI Group */ + subcc %o0, 7, %g6 /* IEU1 */ +22: ba,pt %xcc, 30f /* CTI Group */ + subcc %o0, 8, %g6 /* IEU1 */ + +20: subcc %o0, 6, %g6 /* IEU1 Group */ + srlx %o3, 40, %o4 /* IEU0 */ + stb %o4, [%o0 - 6] /* Store */ +29: srlx %o3, 48, %o4 /* IEU0 Group */ + + stb %o4, [%o0 - 7] /* Store */ +30: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +END(stpcpy) +libc_hidden_def(stpcpy) diff --git a/libc/string/sparc/sparc64/strcat.S b/libc/string/sparc/sparc64/strcat.S new file mode 100644 index 0000000..fcc4ba5 --- /dev/null +++ b/libc/string/sparc/sparc64/strcat.S @@ -0,0 +1,339 @@ +/* strcat (dest, src) -- Append SRC on the end of DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + Jan Vondrak . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcat) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %g6 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 32f /* CTI */ + + sllx %g1, 7, %g2 /* IEU0 Group */ + brz,pn %o3, 30f /* CTI+IEU1 */ + ldx [%o0], %o3 /* Load */ +48: add %o0, 8, %o0 /* IEU0 Group */ + +49: sub %o3, %g1, %o2 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g5 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %g5, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 49b /* CTI */ + + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g3 /* IEU1 Group */ + srlx %o2, 32, %o2 /* IEU0 */ +50: andcc %o2, %g2, %g0 /* IEU1 Group */ + + be,pn %xcc, 51f /* CTI */ + srlx %g3, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 29f /* CTI */ + + srlx %g3, 48, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 28f /* CTI */ + srlx %g3, 40, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 27f /* CTI */ + srlx %g3, 32, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 26f /* CTI */ +51: srlx %g3, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 25f /* CTI */ + + srlx %g3, 16, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + srlx %g3, 8, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 23f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 52f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 49b /* CTI */ + + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g3 /* IEU1 Group */ + ba,pt %xcc, 50b /* CTI */ + srlx %o2, 32, %o2 /* IEU0 */ + + .align 16 +52: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -9, %o0 /* IEU0 */ +23: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -10, %o0 /* IEU0 */ + +24: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -11, %o0 /* IEU0 */ +25: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -12, %o0 /* IEU0 */ + +26: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -13, %o0 /* IEU0 */ +27: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -14, %o0 /* IEU0 */ + +28: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -15, %o0 /* IEU0 */ +29: add %o0, -16, %o0 /* IEU0 Group */ +30: andcc %o1, 7, %g3 /* IEU1 */ + +31: bne,pn %icc, 14f /* CTI */ + orcc %g0, 64, %g4 /* IEU1 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ + +2: mov %o3, %g3 /* IEU0 Group */ +3: sub %o3, %g1, %o2 /* IEU1 */ + ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + + andcc %o2, %g2, %g0 /* IEU1 */ + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + + srlx %g3, 56, %g5 /* IEU0 Group */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 9f /* CTI */ + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + + srlx %g3, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + + bne,pt %icc, 3b /* CTI */ + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +5: stb %g5, [%o0 - 2] /* Store Group */ + srlx %g3, 16, %g4 /* IEU0 */ +6: sth %g4, [%o0 - 4] /* Store Group */ + srlx %g3, 32, %g4 /* IEU0 */ + + stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +7: stb %g5, [%o0 - 4] /* Store Group */ + + srlx %g3, 32, %g4 /* IEU0 */ +8: stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +9: stb %g5, [%o0 - 6] /* Store Group */ + srlx %g3, 48, %g4 /* IEU0 */ +10: sth %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +32: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 48b /* CTI */ + ldx [%o0], %o3 /* Load */ + add %o0, 1, %o0 /* IEU0 Group */ + + brnz,a,pt %o3, 32b /* CTI+IEU1 */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + add %o0, -1, %o0 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + be,a,pn %icc, 31b /* CTI */ + andcc %o1, 7, %g3 /* IEU1 Group */ +12: ldub [%o1], %o3 /* Load */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ + orcc %g0, 64, %g4 /* IEU1 Group */ + +14: sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +16: srlx %o3, 8, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 2] /* Store */ +17: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ + +18: srlx %o3, 24, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 4] /* Store */ +19: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + nop + nop + +20: srlx %o3, 40, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 6] /* Store */ +21: srlx %o3, 48, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 7] /* Store */ + +22: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +END(strcat) +libc_hidden_def(strcat) diff --git a/libc/string/sparc/sparc64/strchr.S b/libc/string/sparc/sparc64/strchr.S new file mode 100644 index 0000000..da26d1f --- /dev/null +++ b/libc/string/sparc/sparc64/strchr.S @@ -0,0 +1,486 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strchr) + andcc %o1, 0xff, %o1 /* IEU1 Group */ + be,pn %icc, 17f /* CTI */ + sllx %o1, 8, %g3 /* IEU0 Group */ + sethi %hi(0x01010101), %g1 /* IEU1 */ + + or %g3, %o1, %g3 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + sllx %g3, 16, %g5 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + brz,pn %o3, 5f /* CTI+IEU1 */ + orcc %g3, %g5, %g3 /* IEU1 Group */ + sllx %g3, 32, %g5 /* IEU0 */ + + cmp %o3, %o1 /* IEU1 Group */ + be,pn %xcc, 14f /* CTI */ + or %g1, %g2, %g1 /* IEU0 */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + bne,a,pn %icc, 15f /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + ldx [%o0], %o3 /* Load Group */ +1: sllx %g1, 7, %g2 /* IEU0 */ + + or %g3, %g5, %g3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ + + sub %o4, %g1, %o5 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + andn %o5, %o4, %o5 /* IEU1 */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + or %o5, %g6, %o5 /* IEU0 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + or %o5, %o2, %o5 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU1 */ + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o5, 32, %g5 /* IEU0 Group */ + + add %o2, %g1, %o2 /* IEU1 */ +3: andcc %g5, %g2, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + srlx %o2, 56, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 6f /* CTI */ + srlx %o2, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %o2, 40, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %o2, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ +4: srlx %o2, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 10f /* CTI */ + srlx %o2, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %o2, 8, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 13f /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + ldxa [%o0] ASI_PNF, %o3 /* Load Group */ + + sub %o4, %g1, %o5 /* IEU0 */ + or %o5, %o2, %o5 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + andcc %o5, %g2, %g0 /* IEU1 */ + + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 Group */ + srlx %o5, 32, %g5 /* IEU0 Group */ + ba,pt %xcc, 3b /* CTI */ + + add %o2, %g1, %o2 /* IEU1 */ + + .align 16 +5: retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ +6: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ + +7: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ +8: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ + +9: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ +10: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ + +11: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ +12: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ + +13: retl /* CTI+IEU1 Group */ + add %o0, -9, %o0 /* IEU0 */ +14: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + + .align 16 +15: ldub [%o0], %o3 /* Load Group */ +16: andcc %o0, 7, %g0 /* IEU1 */ + be,a,pn %icc, 1b /* CTI */ + ldx [%o0], %o3 /* Load Group */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5b /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + cmp %o3, %o1 /* IEU1 Group */ + + bne,a,pn %icc, 16b /* CTI */ + ldub [%o0], %o3 /* Load */ + retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ + + /* strchr (str, 0) */ + .align 32 + nop + .align 16 +17: sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 32f /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ + + brz,pn %o3, 30f /* CTI+IEU1 */ + ldx [%o0], %o3 /* Load */ +18: add %o0, 8, %o0 /* IEU0 Group */ +19: sub %o3, %g1, %o2 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %g6, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 19b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + + addcc %o2, %g1, %g3 /* IEU1 Group */ + srlx %o2, 32, %o2 /* IEU0 */ +20: andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pn %xcc, 21f /* CTI */ + + srlx %g3, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 29f /* CTI */ + srlx %g3, 48, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 28f /* CTI */ + srlx %g3, 40, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 27f /* CTI */ + srlx %g3, 32, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 26f /* CTI */ + +21: srlx %g3, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 25f /* CTI */ + srlx %g3, 16, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + srlx %g3, 8, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 23f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 19b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + + addcc %o2, %g1, %g3 /* IEU1 Group */ + ba,pt %xcc, 20b /* CTI */ + srlx %o2, 32, %o2 /* IEU0 */ + + .align 16 +22: retl /* CTI+IEU1 Group */ + add %o0, -9, %o0 /* IEU0 */ +23: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ + +24: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ +25: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ + +26: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ +27: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ + +28: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ +29: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ + +30: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + + .align 16 +32: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 18b /* CTI */ + ldx [%o0], %o3 /* Load */ + add %o0, 1, %o0 /* IEU0 Group */ + + brnz,a,pt %o3, 32b /* CTI+IEU1 */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ +END(strchr) +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif + + .align 32 +ENTRY(strrchr) + andcc %o1, 0xff, %o1 /* IEU1 Group */ + be,pn %icc, 17b /* CTI */ + clr %g4 /* IEU0 */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + bne,pn %icc, 13f /* CTI */ + sllx %o1, 8, %g3 /* IEU0 */ + ldx [%o0], %o3 /* Load Group */ +1: sethi %hi(0x01010101), %g1 /* IEU0 */ + + or %g3, %o1, %g3 /* IEU1 */ + sllx %g3, 16, %g5 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + or %g3, %g5, %g3 /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + or %g1, %g2, %g1 /* IEU1 */ + sllx %g1, 7, %g2 /* IEU0 Group */ + + or %g3, %g5, %g3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ + +3: sub %o4, %g1, %o5 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + andn %o5, %o4, %o5 /* IEU1 */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + + or %o5, %g6, %o5 /* IEU0 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + + or %o5, %o2, %o5 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU1 */ + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o5, 32, %g5 /* IEU0 Group */ + add %o2, %g1, %o2 /* IEU1 */ + andcc %g5, %g2, %g0 /* IEU1 Group */ + + be,pn %xcc, 7f /* CTI */ + srlx %o2, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 48, %g5 /* IEU0 */ + be,a,pn %icc, 4f /* CTI */ + + add %o0, -16, %g4 /* IEU0 Group */ +4: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 48, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 40, %g5 /* IEU0 */ + be,a,pn %icc, 5f /* CTI */ + add %o0, -15, %g4 /* IEU0 Group */ + +5: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + srlx %o2, 32, %g5 /* IEU0 */ + be,a,pn %icc, 6f /* CTI */ + add %o0, -14, %g4 /* IEU0 Group */ +6: andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,a,pn %icc, 7f /* CTI */ + + add %o0, -13, %g4 /* IEU0 */ +7: srlx %o2, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 16, %g5 /* IEU0 */ + be,a,pn %icc, 8f /* CTI */ + + add %o0, -12, %g4 /* IEU0 Group */ +8: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 8, %g5 /* IEU0 */ + be,a,pn %icc, 9f /* CTI */ + add %o0, -11, %g4 /* IEU0 Group */ + +9: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,a,pn %icc, 10f /* CTI */ + add %o0, -10, %g4 /* IEU0 */ +10: andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + sub %o3, %g1, %o2 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,a,pn %icc, 11f /* CTI */ + add %o0, -9, %g4 /* IEU0 */ + +11: ba,pt %xcc, 3b /* CTI Group */ + xor %o3, %g3, %o4 /* IEU0 Group */ +12: retl /* CTI+IEU1 Group */ + mov %g4, %o0 /* IEU0 */ + + .align 16 +13: ldub [%o0], %o3 /* Load Group */ + add %o0, 1, %o0 /* IEU0 */ +14: andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12b /* CTI */ + + cmp %o3, %o1 /* IEU1 Group */ + ldub [%o0], %o3 /* Load */ + be,a,pn %icc, 15f /* CTI */ + add %o0, -1, %g4 /* IEU0 Group */ + +15: andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 14b /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + ba,pt %xcc, 1b /* CTI Group */ + + ldx [%o0], %o3 /* Load */ +END(strrchr) +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/libc/string/sparc/sparc64/strcmp.S b/libc/string/sparc/sparc64/strcmp.S new file mode 100644 index 0000000..df9e691 --- /dev/null +++ b/libc/string/sparc/sparc64/strcmp.S @@ -0,0 +1,279 @@ +/* Compare two strings for differences. + For SPARC v9. + Copyright (C) 1997, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcmp) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + bne,pn %icc, 7f /* CTI */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + + andcc %o1, 7, %g3 /* IEU1 */ + bne,pn %icc, 9f /* CTI */ + sllx %g1, 32, %g2 /* IEU0 Group */ + ldx [%o0], %o2 /* Load */ + + or %g1, %g2, %g1 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + sub %o1, %o0, %o1 /* IEU1 */ + sllx %g1, 7, %g2 /* IEU0 Group */ + +2: add %o0, 8, %o0 /* IEU1 */ + sub %o2, %g1, %g3 /* IEU0 Group */ + subcc %o2, %o3, %g0 /* IEU1 */ + bne,pn %xcc, 13f /* CTI */ + +#ifdef EIGHTBIT_NOT_RARE + andn %g3, %o2, %g4 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o2 /* Load */ + andcc %g4, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o2 /* Load Group */ + andcc %g3, %g2, %g0 /* IEU1 */ +#endif + be,a,pt %xcc, 2b /* CTI */ + ldxa [%o1 + %o0] ASI_PNF, %o3 /* Load Group */ + + addcc %g3, %g1, %o4 /* IEU1 */ + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 3f /* CTI */ + + srlx %o4, 56, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 48, %o5 /* IEU0 */ + + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 40, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + srlx %o4, 32, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + +3: srlx %o4, 24, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 16, %o5 /* IEU0 */ + + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 8, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + bne,a,pn %icc, 2b /* CTI */ + ldxa [%o1 + %o0] ASI_PNF, %o3 /* Load */ + +4: retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ + + .align 32 +13: mov 0xff, %g6 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andcc %g4, %g2, %g0 /* IEU1 */ +#else + andcc %g3, %g2, %g0 /* IEU1 */ +#endif + be,pt %xcc, 25f /* CTI */ + addcc %g3, %g1, %o4 /* IEU1 Group */ + + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 23f /* CTI */ + sllx %g6, 56, %o5 /* IEU0 */ + + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ + sllx %g6, 48, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + + be,pn %xcc, 24f /* CTI */ + sllx %g6, 40, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ + + sllx %g6, 32, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ +23: sllx %g6, 24, %o5 /* IEU0 */ + + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + sllx %g6, 16, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + + be,pn %icc, 24f /* CTI */ + sllx %g6, 8, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + + mov %g6, %o5 /* IEU0 */ +25: cmp %o4, %o3 /* IEU1 Group */ +5: mov -1, %o0 /* IEU0 */ + retl /* CTI+IEU1 Group */ + + movgu %xcc, 1, %o0 /* Single Group */ + + .align 16 +24: sub %o5, 1, %g6 /* IEU0 Group */ + clr %o0 /* IEU1 */ + or %o5, %g6, %o5 /* IEU0 Group */ + andn %o4, %o5, %o4 /* IEU0 Group */ + + andn %o3, %o5, %o3 /* IEU1 */ + cmp %o4, %o3 /* IEU1 Group */ + movgu %xcc, 1, %o0 /* Single Group */ + retl /* CTI+IEU1 Group */ + + movlu %xcc, -1, %o0 /* Single Group */ +6: retl /* CTI+IEU1 Group */ + mov %o4, %o0 /* IEU0 */ + + .align 16 +7: ldub [%o0], %o2 /* Load */ + add %o0, 1, %o0 /* IEU1 */ + ldub [%o1], %o3 /* Load Group */ + sllx %g1, 32, %g2 /* IEU0 */ + +8: add %o1, 1, %o1 /* IEU1 */ + subcc %o2, %o3, %o4 /* IEU1 Group */ + bne,pn %xcc, 6b /* CTI */ + lduba [%o0] ASI_PNF, %o2 /* Load */ + + brz,pn %o3, 4b /* CTI+IEU1 Group */ + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pn %icc, 8b /* CTI */ + + add %o0, 1, %o0 /* IEU0 */ + or %g1, %g2, %g1 /* IEU0 Group */ + andcc %o1, 7, %g3 /* IEU1 */ + be,a,pn %icc, 1b /* CTI */ + + ldxa [%o0] ASI_PNF, %o2 /* Load Group */ +9: sllx %g3, 3, %g5 /* IEU0 */ + mov 64, %o5 /* IEU1 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + + sub %o5, %g5, %o5 /* IEU1 */ + ldxa [%o1] ASI_PNF, %g6 /* Load Group */ + or %g1, %g2, %g1 /* IEU0 */ + sub %o1, %o0, %o1 /* IEU1 */ + + sllx %g1, 7, %g2 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + /* %g1 = 0101010101010101 + * %g2 = 8080808080800880 + * %g5 = number of bits to shift left + * %o5 = number of bits to shift right */ +10: sllx %g6, %g5, %o3 /* IEU0 Group */ + ldxa [%o1 + %o0] ASI_PNF, %g6 /* Load */ + +11: srlx %g6, %o5, %o4 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o2 /* Load */ + or %o3, %o4, %o3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + + subcc %o2, %o3, %g0 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + sub %o2, %g1, %g3 /* IEU0 Group */ + bne,pn %xcc, 13b /* CTI */ + andn %g3, %o2, %g4 /* IEU0 Group */ + + andcc %g4, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 10b /* CTI */ + srlx %g4, 32, %g4 /* IEU0 */ + andcc %g4, %g2, %g0 /* IEU1 Group */ +#else + bne,pn %xcc, 13b /* CTI */ + sub %o2, %g1, %g3 /* IEU0 Group */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + + be,pt %xcc, 10b /* CTI */ + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 12f /* CTI */ + + srlx %o2, 56, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 48, %g3 /* IEU0 */ + + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 40, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4b /* CTI */ + srlx %o2, 32, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + +12: srlx %o2, 24, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 16, %g3 /* IEU0 */ + + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 8, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4b /* CTI */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + sllx %g6, %g5, %o3 /* IEU0 */ + + ba,pt %xcc, 11b /* CTI Group */ + ldxa [%o1 + %o0] ASI_PNF, %g6 /* Load */ +END(strcmp) +libc_hidden_def(strcmp) diff --git a/libc/string/sparc/sparc64/strcpy.S b/libc/string/sparc/sparc64/strcpy.S new file mode 100644 index 0000000..1317d54 --- /dev/null +++ b/libc/string/sparc/sparc64/strcpy.S @@ -0,0 +1,245 @@ +/* Copy SRC to DEST returning DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcpy) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %g6 /* IEU1 */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + bne,pn %icc, 12f /* CTI */ + andcc %o1, 7, %g3 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + + bne,pn %icc, 14f /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ + +2: mov %o3, %g3 /* IEU0 Group */ +3: sub %o3, %g1, %o2 /* IEU1 */ + ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + + andcc %o2, %g2, %g0 /* IEU1 */ + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + + srlx %g3, 56, %g5 /* IEU0 Group */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 9f /* CTI */ + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + + srlx %g3, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + + bne,pt %icc, 3b /* CTI */ + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +5: stb %g5, [%o0 - 2] /* Store Group */ + srlx %g3, 16, %g4 /* IEU0 */ +6: sth %g4, [%o0 - 4] /* Store Group */ + srlx %g3, 32, %g4 /* IEU0 */ + + stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +7: stb %g5, [%o0 - 4] /* Store Group */ + + srlx %g3, 32, %g4 /* IEU0 */ +8: stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +9: stb %g5, [%o0 - 6] /* Store Group */ + srlx %g3, 48, %g4 /* IEU0 */ +10: sth %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +12: or %g1, %g2, %g1 /* IEU0 Group */ + ldub [%o1], %o3 /* Load */ + sllx %g1, 7, %g2 /* IEU0 Group */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ +14: orcc %g0, 64, %g4 /* IEU1 Group */ + + sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +16: srlx %o3, 8, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 2] /* Store */ +17: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ + +18: srlx %o3, 24, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 4] /* Store */ +19: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + nop + nop + +20: srlx %o3, 40, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 6] /* Store */ +21: srlx %o3, 48, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 7] /* Store */ + +22: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +END(strcpy) + +libc_hidden_def(strcpy) diff --git a/libc/string/sparc/sparc64/strlen.S b/libc/string/sparc/sparc64/strlen.S new file mode 100644 index 0000000..1fe8549 --- /dev/null +++ b/libc/string/sparc/sparc64/strlen.S @@ -0,0 +1,173 @@ +/* Determine the length of a string. For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strlen) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %o1 /* IEU1 */ + + sllx %g1, 32, %g4 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g4, %g1 /* IEU0 Group */ + brz,pn %o3, 13f /* CTI+IEU1 */ + + sllx %g1, 7, %g4 /* IEU0 Group */ + bne,a,pn %icc, 15f /* CTI */ + add %o0, 1, %o0 /* IEU1 */ + /* %g1 = 0x0101010101010101 * + * %g4 = 0x8080808080808080 * + * %o0 = string pointer * + * %o1 = start of string */ +1: ldx [%o0], %o3 /* Load Group */ + + add %o0, 8, %o0 /* IEU1 */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %o5 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o5, %g4, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g4, %g0 /* IEU1 Group */ +#endif + + be,pt %xcc, 2b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g5 /* IEU1 Group */ +#ifdef EIGHTBIT_NOT_RARE + srlx %o5, 32, %o5 /* IEU0 */ + +3: andcc %o5, %g4, %g0 /* IEU1 Group */ +#else + srlx %o2, 32, %o2 /* IEU0 */ + +3: andcc %o2, %g4, %g0 /* IEU1 Group */ +#endif + be,pn %xcc, 4f /* CTI */ + srlx %g5, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + srlx %g5, 48, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + + srlx %g5, 40, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g5, 32, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ +4: srlx %g5, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %g5, 16, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + + srlx %g5, 8, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g4, %g0 /* IEU1 Group */ + + be,pt %xcc, 2b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g5 /* IEU1 Group */ + ba,pt %xcc, 3b /* CTI */ + + srlx %o2, 32, %o2 /* IEU0 */ +5: add %o0, -9, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ + +6: add %o0, -10, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +7: add %o0, -11, %o0 /* IEU0 Group */ + + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +8: add %o0, -12, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, %o1, %o0 /* IEU0 */ +9: add %o0, -13, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ + +10: add %o0, -14, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +11: add %o0, -15, %o0 /* IEU0 Group */ + + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +12: add %o0, -16, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, %o1, %o0 /* IEU0 */ +13: retl /* CTI+IEU1 Group */ + mov 0, %o0 /* IEU0 */ + nop + +15: ldub [%o0], %o3 /* Load Group */ +16: andcc %o0, 7, %g0 /* IEU1 */ + be,pn %icc, 1b /* CTI */ + nop /* IEU0 Group */ + + add %o0, 1, %o0 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,a,pt %icc, 16b /* CTI */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + + add %o0, -1, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +END(strlen) +libc_hidden_def(strlen) diff --git a/libc/string/sparc/stpcpy.S b/libc/string/sparc/stpcpy.S new file mode 100644 index 0000000..2d27393 --- /dev/null +++ b/libc/string/sparc/stpcpy.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/stpcpy.S" +# else +# include "sparc32/stpcpy.S" +# endif + +#else +# include "sparc64/stpcpy.S" +#endif diff --git a/libc/string/sparc/strcat.S b/libc/string/sparc/strcat.S new file mode 100644 index 0000000..ae18e4e --- /dev/null +++ b/libc/string/sparc/strcat.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcat.S" +# else +# include "sparc32/strcat.S" +# endif + +#else +# include "sparc64/strcat.S" +#endif diff --git a/libc/string/sparc/strchr.S b/libc/string/sparc/strchr.S new file mode 100644 index 0000000..99b5119 --- /dev/null +++ b/libc/string/sparc/strchr.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strchr.S" +# else +# include "sparc32/strchr.S" +# endif + +#else +# include "sparc64/strchr.S" +#endif diff --git a/libc/string/sparc/strcmp.S b/libc/string/sparc/strcmp.S new file mode 100644 index 0000000..556537c --- /dev/null +++ b/libc/string/sparc/strcmp.S @@ -0,0 +1,18 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcmp.S" +# else +# include "sparc32/strcmp.S" +# endif + +#else +# include "sparc64/strcmp.S" +#endif + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/sparc/strcpy.S b/libc/string/sparc/strcpy.S new file mode 100644 index 0000000..6dbbf5a --- /dev/null +++ b/libc/string/sparc/strcpy.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcpy.S" +# else +# include "sparc32/strcpy.S" +# endif + +#else +# include "sparc64/strcpy.S" +#endif diff --git a/libc/string/sparc/strlen.S b/libc/string/sparc/strlen.S new file mode 100644 index 0000000..0bfa3f5 --- /dev/null +++ b/libc/string/sparc/strlen.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strlen.S" +# else +# include "sparc32/strlen.S" +# endif + +#else +# include "sparc64/strlen.S" +#endif diff --git a/libc/string/sparc/strrchr.c b/libc/string/sparc/strrchr.c new file mode 100644 index 0000000..ec608d6 --- /dev/null +++ b/libc/string/sparc/strrchr.c @@ -0,0 +1 @@ +/* strrchr is in strchr.S */ diff --git a/libc/string/stpcpy.c b/libc/string/stpcpy.c new file mode 100644 index 0000000..8a48758 --- /dev/null +++ b/libc/string/stpcpy.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstpcpy wcpcpy +#else +/* Experimentally off - libc_hidden_proto(stpcpy) */ +# define Wstpcpy stpcpy +#endif + +Wchar *Wstpcpy(register Wchar * __restrict s1, const Wchar * __restrict s2) +{ +#ifdef __BCC__ + do { + *s1 = *s2++; + } while (*s1++ != 0); +#else + while ( (*s1++ = *s2++) != 0 ); +#endif + + return s1 - 1; +} + +#ifndef WANT_WIDE +libc_hidden_def(stpcpy) +#endif diff --git a/libc/string/stpncpy.c b/libc/string/stpncpy.c new file mode 100644 index 0000000..dac8471 --- /dev/null +++ b/libc/string/stpncpy.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstpncpy wcpncpy +#else +/* Experimentally off - libc_hidden_proto(stpncpy) */ +# define Wstpncpy stpncpy +#endif + +Wchar *Wstpncpy(register Wchar * __restrict s1, + register const Wchar * __restrict s2, + size_t n) +{ + Wchar *s = s1; + const Wchar *p = s2; + +#ifdef __BCC__ + while (n--) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + } + return s1 + (s2 - p); +#else + while (n) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + --n; + } + return s1 + (s2 - p); +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(stpncpy) +#endif diff --git a/libc/string/strcasecmp.c b/libc/string/strcasecmp.c new file mode 100644 index 0000000..f985223 --- /dev/null +++ b/libc/string/strcasecmp.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include +#include + +#ifdef WANT_WIDE +# define strcasecmp wcscasecmp +# define strcasecmp_l wcscasecmp_l +libc_hidden_proto(wcscasecmp) +# if defined(__USE_GNU) && defined(__UCLIBC_HAS_XLOCALE__) +libc_hidden_proto(wcscasecmp_l) +# endif +# ifdef __UCLIBC_DO_XLOCALE +libc_hidden_proto(towlower_l) +# define TOLOWER(C) towlower_l((C), locale_arg) +# else +libc_hidden_proto(towlower) +# define TOLOWER(C) towlower((C)) +# endif +#else +/* Experimentally off - libc_hidden_proto(strcasecmp) */ +/* Experimentally off - libc_hidden_proto(strcasecmp_l) */ +# ifdef __UCLIBC_DO_XLOCALE +libc_hidden_proto(tolower_l) +# define TOLOWER(C) tolower_l((C), locale_arg) +# else +#if !defined __UCLIBC_HAS_XLOCALE__ && defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_tolower) +#endif +libc_hidden_proto(tolower) +# define TOLOWER(C) tolower((C)) +# endif +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +int strcasecmp(register const Wchar *s1, register const Wchar *s2) +{ + return strcasecmp_l(s1, s2, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strcasecmp) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* Experimentally off - libc_hidden_proto(__XL_NPP(strcasecmp)) */ +int __XL_NPP(strcasecmp)(register const Wchar *s1, register const Wchar *s2 + __LOCALE_PARAM ) +{ +#ifdef WANT_WIDE + while ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2))) { + if (!*s1++) { + return 0; + } + ++s2; + } + + return (((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1; + /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */ +#else + int r = 0; + + while ( ((s1 == s2) || + !(r = ((int)( TOLOWER(*((Wuchar *)s1)))) + - TOLOWER(*((Wuchar *)s2)))) + && (++s2, *s1++)); + + return r; +#endif +} +libc_hidden_def(__XL_NPP(strcasecmp)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ diff --git a/libc/string/strcasecmp_l.c b/libc/string/strcasecmp_l.c new file mode 100644 index 0000000..a3f74c4 --- /dev/null +++ b/libc/string/strcasecmp_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_DO_XLOCALE +#include "strcasecmp.c" diff --git a/libc/string/strcasestr.c b/libc/string/strcasestr.c new file mode 100644 index 0000000..2671b4b --- /dev/null +++ b/libc/string/strcasestr.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_tolower_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_tolower) +#endif +libc_hidden_proto(tolower) + +char *strcasestr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + +#if 1 + do { + if (!*p) { + return (char *) s1;; + } + if ((*p == *s) + || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s))) + ) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +#else + while (*p && *s) { + if ((*p == *s) + || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s))) + ) { + ++p; + ++s; + } else { + p = s2; + s = ++s1; + } + } + + return (*p) ? NULL : (char *) s1; +#endif +} +libc_hidden_def(strcasestr) diff --git a/libc/string/strcat.c b/libc/string/strcat.c new file mode 100644 index 0000000..40a9be1 --- /dev/null +++ b/libc/string/strcat.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcat wcscat +#else +# define Wstrcat strcat +#endif + +libc_hidden_proto(Wstrcat) + +Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2) +{ + register Wchar *s = s1; + + while (*s++); + --s; + while ((*s++ = *s2++) != 0); + + return s1; +} +libc_hidden_def(Wstrcat) diff --git a/libc/string/strchr.c b/libc/string/strchr.c new file mode 100644 index 0000000..329545e --- /dev/null +++ b/libc/string/strchr.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrchr wcschr +#else +# define Wstrchr strchr +#endif + +libc_hidden_proto(Wstrchr) + +Wchar *Wstrchr(register const Wchar *s, Wint c) +{ + do { + if (*s == ((Wchar)c)) { + return (Wchar *) s; /* silence the warning */ + } + } while (*s++); + + return NULL; +} +libc_hidden_def(Wstrchr) + +#if !defined WANT_WIDE && defined __UCLIBC_SUSV3_LEGACY__ +weak_alias(strchr,index) +#endif diff --git a/libc/string/strchrnul.c b/libc/string/strchrnul.c new file mode 100644 index 0000000..6fe7f6c --- /dev/null +++ b/libc/string/strchrnul.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wstrchrnul wcschrnul +#else +# define Wstrchrnul strchrnul +#endif + +libc_hidden_proto(Wstrchrnul) + +Wchar *Wstrchrnul(register const Wchar *s, Wint c) +{ + --s; + while (*++s && (*s != ((Wchar)c))); + return (Wchar *) s; +} +libc_hidden_def(Wstrchrnul) +#endif diff --git a/libc/string/strcmp.c b/libc/string/strcmp.c new file mode 100644 index 0000000..5477adf --- /dev/null +++ b/libc/string/strcmp.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcmp wcscmp +# define Wstrcoll wcscoll +#else +# define Wstrcmp strcmp +# define Wstrcoll strcoll +#endif + +libc_hidden_proto(Wstrcmp) + +int Wstrcmp(register const Wchar *s1, register const Wchar *s2) +{ +#ifdef WANT_WIDE + while (*((Wuchar *)s1) == *((Wuchar *)s2)) { + if (!*s1++) { + return 0; + } + ++s2; + } + + return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1; +#else + int r; + + while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++)) + == 0) && *s1++); + + return r; +#endif +} +libc_hidden_def(Wstrcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(Wstrcoll) +strong_alias(Wstrcmp,Wstrcoll) +libc_hidden_def(Wstrcoll) +#endif diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c new file mode 100644 index 0000000..cda4094 --- /dev/null +++ b/libc/string/strcpy.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcpy wcscpy +#else +# define Wstrcpy strcpy +#endif + +libc_hidden_proto(Wstrcpy) + +Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2) +{ + register Wchar *s = s1; + +#ifdef __BCC__ + do { + *s = *s2++; + } while (*s++ != 0); +#else + while ( (*s++ = *s2++) != 0 ); +#endif + + return s1; +} +libc_hidden_def(Wstrcpy) diff --git a/libc/string/strcspn.c b/libc/string/strcspn.c new file mode 100644 index 0000000..1ec460a --- /dev/null +++ b/libc/string/strcspn.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcspn wcscspn +#else +/* Experimentally off - libc_hidden_proto(strcspn) */ +# define Wstrcspn strcspn +#endif + +size_t Wstrcspn(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s; + register const Wchar *p; + + for ( s=s1 ; *s ; s++ ) { + for ( p=s2 ; *p ; p++ ) { + if (*p == *s) goto done; + } + } + done: + return s - s1; +} + +#ifndef WANT_WIDE +libc_hidden_def(strcspn) +#endif diff --git a/libc/string/strdup.c b/libc/string/strdup.c new file mode 100644 index 0000000..61fc186 --- /dev/null +++ b/libc/string/strdup.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +#ifdef WANT_WIDE +libc_hidden_proto(wcslen) +# define Wstrdup wcsdup +# define Wstrlen wcslen +#else +/* Experimentally off - libc_hidden_proto(strdup) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +# define Wstrdup strdup +# define Wstrlen strlen +#endif +/* Experimentally off - libc_hidden_proto(memcpy) */ + +Wchar *Wstrdup(register const Wchar *s1) +{ + register Wchar *s; + register size_t l = (Wstrlen(s1) + 1) * sizeof(Wchar); + + if ((s = malloc(l)) != NULL) { + memcpy(s, s1, l); + } + + return s; +} + +#ifndef WANT_WIDE +libc_hidden_weak(strdup) +#endif diff --git a/libc/string/strerror.c b/libc/string/strerror.c new file mode 100644 index 0000000..355c7bd --- /dev/null +++ b/libc/string/strerror.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "_syserrmsg.h" + +/* Experimentally off - libc_hidden_proto(strerror) */ +libc_hidden_proto(__xpg_strerror_r) + +char *strerror(int errnum) +{ + static char buf[_STRERROR_BUFSIZE]; + + __xpg_strerror_r(errnum, buf, sizeof(buf)); + + return buf; +} +libc_hidden_def(strerror) diff --git a/libc/string/strlcat.c b/libc/string/strlcat.c new file mode 100644 index 0000000..d55761d --- /dev/null +++ b/libc/string/strlcat.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* OpenBSD function: + * Append at most n-1-strlen(dst) chars from src to dst and nul-terminate dst. + * Returns strlen(src) + strlen({original} dst), so truncation occurred if the + * return val is >= n. + * Note: If dst doesn't contain a nul in the first n chars, strlen(dst) is + * taken as n. */ + +#include "_string.h" + +size_t strlcat(register char *__restrict dst, + register const char *__restrict src, + size_t n) +{ + size_t len; + char dummy[1]; + + len = 0; + + while (1) { + if (len >= n) { + dst = dummy; + break; + } + if (!*dst) { + break; + } + ++dst; + ++len; + } + + while ((*dst = *src) != 0) { + if (++len < n) { + ++dst; + } + ++src; + } + + return len; +} +libc_hidden_def(strlcat) diff --git a/libc/string/strlcpy.c b/libc/string/strlcpy.c new file mode 100644 index 0000000..cdad4dc --- /dev/null +++ b/libc/string/strlcpy.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrlcpy __wcslcpy +# define Wstrxfrm wcsxfrm +#else +/* Experimentally off - libc_hidden_proto(strlcpy) */ +# define Wstrlcpy strlcpy +# define Wstrxfrm strxfrm +#endif + + +/* OpenBSD function: + * Copy at most n-1 chars from src to dst and nul-terminate dst. + * Returns strlen(src), so truncation occurred if the return value is >= n. */ + +#ifdef WANT_WIDE +size_t Wstrlcpy(register Wchar *__restrict dst, + register const Wchar *__restrict src, + size_t n) attribute_hidden; +#endif +size_t Wstrlcpy(register Wchar *__restrict dst, + register const Wchar *__restrict src, + size_t n) +{ + const Wchar *src0 = src; + Wchar dummy[1]; + + if (!n) { + dst = dummy; + } else { + --n; + } + + while ((*dst = *src) != 0) { + if (n) { + --n; + ++dst; + } + ++src; + } + + return src - src0; +} +#ifndef WANT_WIDE +libc_hidden_def(strlcpy) +#ifndef __UCLIBC_HAS_LOCALE__ +/* Experimentally off - libc_hidden_proto(strxfrm) */ +strong_alias(strlcpy,strxfrm) +libc_hidden_def(strxfrm) +#endif +#else +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(__wcslcpy,wcsxfrm) +#endif +#endif diff --git a/libc/string/strlen.c b/libc/string/strlen.c new file mode 100644 index 0000000..2edb6e4 --- /dev/null +++ b/libc/string/strlen.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrlen wcslen +#else +# define Wstrlen strlen +#endif + +libc_hidden_proto(Wstrlen) + +size_t Wstrlen(const Wchar *s) +{ + register const Wchar *p; + + for (p=s ; *p ; p++); + + return p - s; +} +libc_hidden_weak(Wstrlen) diff --git a/libc/string/strncasecmp.c b/libc/string/strncasecmp.c new file mode 100644 index 0000000..ed052fa --- /dev/null +++ b/libc/string/strncasecmp.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include +#include + +#ifdef WANT_WIDE +# define strncasecmp wcsncasecmp +# define strncasecmp_l wcsncasecmp_l +libc_hidden_proto(wcsncasecmp) +# if defined(__USE_GNU) && defined(__UCLIBC_HAS_XLOCALE__) +libc_hidden_proto(wcsncasecmp_l) +# endif +# ifdef __UCLIBC_DO_XLOCALE +libc_hidden_proto(towlower_l) +# define TOLOWER(C) towlower_l((C), locale_arg) +# else +libc_hidden_proto(towlower) +# define TOLOWER(C) towlower((C)) +# endif +#else +/* Experimentally off - libc_hidden_proto(strncasecmp) */ +/* Experimentally off - libc_hidden_proto(strncasecmp_l) */ +# ifdef __UCLIBC_DO_XLOCALE +libc_hidden_proto(tolower_l) +# define TOLOWER(C) tolower_l((C), locale_arg) +# else +#if !defined __UCLIBC_HAS_XLOCALE__ && defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_tolower) +#endif +libc_hidden_proto(tolower) +# define TOLOWER(C) tolower((C)) +# endif +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +int strncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strncasecmp) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* Experimentally off - libc_hidden_proto(__XL_NPP(strncasecmp)) */ +int __XL_NPP(strncasecmp)(register const Wchar *s1, register const Wchar *s2, + size_t n __LOCALE_PARAM ) +{ +#ifdef WANT_WIDE + while (n && ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2)))) { + if (!*s1++) { + return 0; + } + ++s2; + --n; + } + + return (n == 0) + ? 0 + : ((((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1); + /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */ +#else + int r = 0; + + while ( n + && ((s1 == s2) || + !(r = ((int)( TOLOWER(*((unsigned char *)s1)))) + - TOLOWER(*((unsigned char *)s2)))) + && (--n, ++s2, *s1++)); + return r; +#endif +} +libc_hidden_def(__XL_NPP(strncasecmp)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ diff --git a/libc/string/strncasecmp_l.c b/libc/string/strncasecmp_l.c new file mode 100644 index 0000000..7f251ba --- /dev/null +++ b/libc/string/strncasecmp_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_DO_XLOCALE +#include "strncasecmp.c" diff --git a/libc/string/strncat.c b/libc/string/strncat.c new file mode 100644 index 0000000..0180d13 --- /dev/null +++ b/libc/string/strncat.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncat wcsncat +#else +/* Experimentally off - libc_hidden_proto(strncat) */ +# define Wstrncat strncat +#endif + +Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2, + size_t n) +{ + register Wchar *s = s1; + + while (*s++); + --s; +#ifdef __BCC__ + while (n-- && ((*s = *s2++) != 0)) ++s; +#else + while (n && ((*s = *s2++) != 0)) { + --n; + ++s; + } +#endif + *s = 0; + + return s1; +} + +#ifndef WANT_WIDE +libc_hidden_def(strncat) +#endif diff --git a/libc/string/strncmp.c b/libc/string/strncmp.c new file mode 100644 index 0000000..59e4a2c --- /dev/null +++ b/libc/string/strncmp.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncmp wcsncmp +#else +/* Experimentally off - libc_hidden_proto(strncmp) */ +# define Wstrncmp strncmp +#endif + +int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n) +{ +#ifdef WANT_WIDE + while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) { + if (!*s1++) { + return 0; + } + ++s2; + --n; + } + + return (n == 0) ? 0 : (*((Wuchar *)s1) - *((Wuchar *)s2)); +#else + int r = 0; + + while (n-- + && ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++)) + == 0) + && *s1++); + + return r; +#endif +} +#ifndef WANT_WIDE +libc_hidden_weak(strncmp) +#endif diff --git a/libc/string/strncpy.c b/libc/string/strncpy.c new file mode 100644 index 0000000..d935612 --- /dev/null +++ b/libc/string/strncpy.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncpy wcsncpy +#else +/* Experimentally off - libc_hidden_proto(strncpy) */ +# define Wstrncpy strncpy +#endif + +Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2, + size_t n) +{ + register Wchar *s = s1; + +#ifdef __BCC__ + while (n--) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + } +#else + while (n) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + --n; + } +#endif + + return s1; +} +#ifndef WANT_WIDE +libc_hidden_def(strncpy) +#endif diff --git a/libc/string/strndup.c b/libc/string/strndup.c new file mode 100644 index 0000000..96a36d4 --- /dev/null +++ b/libc/string/strndup.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +/* Experimentally off - libc_hidden_proto(strndup) */ +/* Experimentally off - libc_hidden_proto(strnlen) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ + +char *strndup(register const char *s1, size_t n) +{ + register char *s; + + n = strnlen(s1,n); /* Avoid problems if s1 not nul-terminated. */ + + if ((s = malloc(n + 1)) != NULL) { + memcpy(s, s1, n); + s[n] = 0; + } + + return s; +} +libc_hidden_def(strndup) diff --git a/libc/string/strnlen.c b/libc/string/strnlen.c new file mode 100644 index 0000000..8fbc25c --- /dev/null +++ b/libc/string/strnlen.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wstrnlen wcsnlen +#else +# define Wstrnlen strnlen +#endif + +libc_hidden_proto(Wstrnlen) + +size_t Wstrnlen(const Wchar *s, size_t max) +{ + register const Wchar *p = s; +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *maxp = (const char *) max; +#else +# define maxp max +#endif + + while (maxp && *p) { + ++p; + --maxp; + } + + return p - s; +} +#undef maxp + +libc_hidden_def(Wstrnlen) +#endif diff --git a/libc/string/strpbrk.c b/libc/string/strpbrk.c new file mode 100644 index 0000000..abeb843 --- /dev/null +++ b/libc/string/strpbrk.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrpbrk wcspbrk +#else +# define Wstrpbrk strpbrk +#endif + +libc_hidden_proto(Wstrpbrk) + +Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s; + register const Wchar *p; + + for ( s=s1 ; *s ; s++ ) { + for ( p=s2 ; *p ; p++ ) { + if (*p == *s) return (Wchar *) s; /* silence the warning */ + } + } + return NULL; +} +libc_hidden_def(Wstrpbrk) diff --git a/libc/string/strrchr.c b/libc/string/strrchr.c new file mode 100644 index 0000000..253c416 --- /dev/null +++ b/libc/string/strrchr.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrrchr wcsrchr +#else +/* Experimentally off - libc_hidden_proto(strrchr) */ +# define Wstrrchr strrchr +#endif + +Wchar *Wstrrchr(register const Wchar *s, Wint c) +{ + register const Wchar *p; + + p = NULL; + do { + if (*s == (Wchar) c) { + p = s; + } + } while (*s++); + + return (Wchar *) p; /* silence the warning */ +} +#ifndef WANT_WIDE +libc_hidden_weak(strrchr) +# ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strrchr,rindex) +# endif +#endif diff --git a/libc/string/strsep.c b/libc/string/strsep.c new file mode 100644 index 0000000..373b00a --- /dev/null +++ b/libc/string/strsep.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_BSD + +/* Experimentally off - libc_hidden_proto(strpbrk) */ +/* Experimentally off - libc_hidden_proto(strcspn) */ + +/* Experimentally off - libc_hidden_proto(strsep) */ +char *strsep(char ** __restrict s1, const char * __restrict s2) +{ + register char *s = *s1; + register char *p; + +#if 1 + p = NULL; + if (s && *s && (p = strpbrk(s, s2))) { + *p++ = 0; + } +#else + if (s && *s && *(p = s + strcspn(s, s2))) { + *p++ = 0; + } else { + p = NULL; + } +#endif + *s1 = p; + return s; +} +libc_hidden_def(strsep) +#endif diff --git a/libc/string/strsignal.c b/libc/string/strsignal.c new file mode 100644 index 0000000..ee083d6 --- /dev/null +++ b/libc/string/strsignal.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Sep 11, 2003 + * Patch by Atsushi Nemoto to do arch-required + * mapping of signal strings (alpha, mips, hppa, sparc). + */ + +/* TODO: make a threadsafe version? */ + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strsignal) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ + +#define _SYS_NSIG 32 + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ +# define _SYS_SIGMSG_MAXLEN 25 +#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ +# define _SYS_SIGMSG_MAXLEN 0 +#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ + +#if _SYS_SIGMSG_MAXLEN < __UIM_BUFLEN_INT + 15 +# define _STRSIGNAL_BUFSIZE (__UIM_BUFLEN_INT + 15) +#else +# define _STRSIGNAL_BUFSIZE _SYS_SIGMSG_MAXLEN +#endif + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ + +extern const char _string_syssigmsgs[] attribute_hidden; + +#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__) +static const unsigned char sstridx[] = { + 0, + SIGHUP, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + SIGIOT, + SIGBUS, + SIGFPE, + SIGKILL, + SIGUSR1, + SIGSEGV, + SIGUSR2, + SIGPIPE, + SIGALRM, + SIGTERM, +#if defined SIGSTKFLT + SIGSTKFLT, +#else + 0, +#endif + SIGCHLD, + SIGCONT, + SIGSTOP, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGURG, + SIGXCPU, + SIGXFSZ, + SIGVTALRM, + SIGPROF, + SIGWINCH, + SIGIO, + SIGPWR, + SIGSYS, +#if defined SIGEMT + SIGEMT, +#endif +}; +#endif + +char *strsignal(int signum) +{ + register char *s; + int i; + static char buf[_STRSIGNAL_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' ' + }; + +#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__) + /* Need to translate signum to string index. */ + for (i = 0 ; i < sizeof(sstridx)/sizeof(sstridx[0]) ; i++) { + if (sstridx[i] == signum) { + goto GOT_SSTRIDX; + } + } + i = INT_MAX; /* Failed. */ + GOT_SSTRIDX: +#else + /* No signum to string index translation needed. */ + i = signum; +#endif + + if (((unsigned int) signum) < _SYS_NSIG) { + /* Trade time for space. This function should rarely be called + * so rather than keeping an array of pointers for the different + * messages, just run through the buffer until we find the + * correct string. */ + for (s = (char *) _string_syssigmsgs ; i ; ++s) { + if (!*s) { + --i; + } + } + if (*s) { /* Make sure we have an actual message. */ + goto DONE; + } + } + + s = _int10tostr(buf+sizeof(buf)-1, signum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + DONE: + return s; +} + +#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ + +char *strsignal(int signum) +{ + static char buf[_STRSIGNAL_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' ' + }; + + return (char *) memcpy(_int10tostr(buf+sizeof(buf)-1, signum) + - sizeof(unknown), + unknown, sizeof(unknown)); +} + +#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ + +libc_hidden_def(strsignal) diff --git a/libc/string/strspn.c b/libc/string/strspn.c new file mode 100644 index 0000000..ca83ef9 --- /dev/null +++ b/libc/string/strspn.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrspn wcsspn +#else +# define Wstrspn strspn +#endif + +libc_hidden_proto(Wstrspn) + +size_t Wstrspn(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s = s1; + register const Wchar *p = s2; + + while (*p) { + if (*p++ == *s) { + ++s; + p = s2; + } + } + return s - s1; +} +libc_hidden_def(Wstrspn) diff --git a/libc/string/strstr.c b/libc/string/strstr.c new file mode 100644 index 0000000..05712e6 --- /dev/null +++ b/libc/string/strstr.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrstr wcsstr +#else +/* Experimentally off - libc_hidden_proto(strstr) */ +# define Wstrstr strstr +#endif + +/* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */ + +Wchar *Wstrstr(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s = s1; + register const Wchar *p = s2; + + do { + if (!*p) { + return (Wchar *) s1;; + } + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +} +#ifndef WANT_WIDE +libc_hidden_def(strstr) +#else +strong_alias(wcsstr,wcswcs) +#endif diff --git a/libc/string/strtok.c b/libc/string/strtok.c new file mode 100644 index 0000000..159dd6b --- /dev/null +++ b/libc/string/strtok.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#if 0 /*def WANT_WIDE*/ +# define Wstrtok wcstok +# define Wstrtok_r wcstok_r +#else +# define Wstrtok strtok +# define Wstrtok_r strtok_r +#endif + +/* Experimentally off - libc_hidden_proto(Wstrtok_r) */ + +Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2) +{ + static Wchar *next_start; /* Initialized to 0 since in bss. */ + return Wstrtok_r(s1, s2, &next_start); +} +libc_hidden_def(Wstrtok) diff --git a/libc/string/strtok_r.c b/libc/string/strtok_r.c new file mode 100644 index 0000000..2ad7746 --- /dev/null +++ b/libc/string/strtok_r.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +libc_hidden_proto(wcsspn) +libc_hidden_proto(wcspbrk) +# define Wstrtok_r wcstok +# define Wstrspn wcsspn +# define Wstrpbrk wcspbrk +#else +/* Experimentally off - libc_hidden_proto(strtok_r) */ +/* Experimentally off - libc_hidden_proto(strspn) */ +/* Experimentally off - libc_hidden_proto(strpbrk) */ +# define Wstrtok_r strtok_r +# define Wstrspn strspn +# define Wstrpbrk strpbrk +#endif + +Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2, + Wchar ** __restrict next_start) +{ + register Wchar *s; + register Wchar *p; + +#if 1 + if (((s = s1) != NULL) || ((s = *next_start) != NULL)) { + if (*(s += Wstrspn(s, s2))) { + if ((p = Wstrpbrk(s, s2)) != NULL) { + *p++ = 0; + } + } else { + p = s = NULL; + } + *next_start = p; + } + return s; +#else + if (!(s = s1)) { + s = *next_start; + } + if (s && *(s += Wstrspn(s, s2))) { + if (*(p = s + Wstrcspn(s, s2))) { + *p++ = 0; + } + *next_start = p; + return s; + } + return NULL; /* TODO: set *next_start = NULL for safety? */ +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(strtok_r) +#endif diff --git a/libc/string/strxfrm.c b/libc/string/strxfrm.c new file mode 100644 index 0000000..037d47b --- /dev/null +++ b/libc/string/strxfrm.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define L_strxfrm +#include "_collate.c" diff --git a/libc/string/strxfrm_l.c b/libc/string/strxfrm_l.c new file mode 100644 index 0000000..85e1cdf --- /dev/null +++ b/libc/string/strxfrm_l.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#define L_strxfrm_l +#include "_collate.c" diff --git a/libc/string/sys_errlist.c b/libc/string/sys_errlist.c new file mode 100644 index 0000000..17ed4d6 --- /dev/null +++ b/libc/string/sys_errlist.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern const char _string_syserrmsgs[] attribute_hidden; + +#ifdef __UCLIBC_HAS_SYS_ERRLIST__ + +link_warning(_sys_errlist, "sys_nerr and sys_errlist are obsolete and uClibc support for them (in at least some configurations) will probably be unavailable in the near future.") + +const char *const sys_errlist[] = { + [0] = _string_syserrmsgs + 0, + [EPERM] = _string_syserrmsgs + 8, + [ENOENT] = _string_syserrmsgs + 32, + [ESRCH] = _string_syserrmsgs + 58, + [EINTR] = _string_syserrmsgs + 74, + [EIO] = _string_syserrmsgs + 98, + [ENXIO] = _string_syserrmsgs + 117, + [E2BIG] = _string_syserrmsgs + 143, + [ENOEXEC] = _string_syserrmsgs + 166, + [EBADF] = _string_syserrmsgs + 184, + [ECHILD] = _string_syserrmsgs + 204, + [EAGAIN] = _string_syserrmsgs + 223, + [ENOMEM] = _string_syserrmsgs + 256, + [EACCES] = _string_syserrmsgs + 279, + [EFAULT] = _string_syserrmsgs + 297, + [ENOTBLK] = _string_syserrmsgs + 309, + [EBUSY] = _string_syserrmsgs + 331, + [EEXIST] = _string_syserrmsgs + 355, + [EXDEV] = _string_syserrmsgs + 367, + [ENODEV] = _string_syserrmsgs + 393, + [ENOTDIR] = _string_syserrmsgs + 408, + [EISDIR] = _string_syserrmsgs + 424, + [EINVAL] = _string_syserrmsgs + 439, + [ENFILE] = _string_syserrmsgs + 456, + [EMFILE] = _string_syserrmsgs + 486, + [ENOTTY] = _string_syserrmsgs + 506, + [ETXTBSY] = _string_syserrmsgs + 537, + [EFBIG] = _string_syserrmsgs + 552, + [ENOSPC] = _string_syserrmsgs + 567, + [ESPIPE] = _string_syserrmsgs + 591, + [EROFS] = _string_syserrmsgs + 604, + [EMLINK] = _string_syserrmsgs + 626, + [EPIPE] = _string_syserrmsgs + 641, + [EDOM] = _string_syserrmsgs + 653, + [ERANGE] = _string_syserrmsgs + 686, + [EDEADLK] = _string_syserrmsgs + 716, + [ENAMETOOLONG] = _string_syserrmsgs + 742, + [ENOLCK] = _string_syserrmsgs + 761, + [ENOSYS] = _string_syserrmsgs + 780, + [ENOTEMPTY] = _string_syserrmsgs + 805, + [ELOOP] = _string_syserrmsgs + 825, + /* _string_syserrmsgs + 859, */ + [ENOMSG] = _string_syserrmsgs + 860, + [EIDRM] = _string_syserrmsgs + 887, + [ECHRNG] = _string_syserrmsgs + 906, + [EL2NSYNC] = _string_syserrmsgs + 934, + [EL3HLT] = _string_syserrmsgs + 959, + [EL3RST] = _string_syserrmsgs + 974, + [ELNRNG] = _string_syserrmsgs + 988, + [EUNATCH] = _string_syserrmsgs + 1013, + [ENOCSI] = _string_syserrmsgs + 1042, + [EL2HLT] = _string_syserrmsgs + 1069, + [EBADE] = _string_syserrmsgs + 1084, + [EBADR] = _string_syserrmsgs + 1101, + [EXFULL] = _string_syserrmsgs + 1128, + [ENOANO] = _string_syserrmsgs + 1142, + [EBADRQC] = _string_syserrmsgs + 1151, + [EBADSLT] = _string_syserrmsgs + 1172, + /* _string_syserrmsgs + 1185, */ + [EBFONT] = _string_syserrmsgs + 1186, + [ENOSTR] = _string_syserrmsgs + 1207, + [ENODATA] = _string_syserrmsgs + 1227, + [ETIME] = _string_syserrmsgs + 1245, + [ENOSR] = _string_syserrmsgs + 1259, + [ENONET] = _string_syserrmsgs + 1284, + [ENOPKG] = _string_syserrmsgs + 1314, + [EREMOTE] = _string_syserrmsgs + 1336, + [ENOLINK] = _string_syserrmsgs + 1353, + [EADV] = _string_syserrmsgs + 1375, + [ESRMNT] = _string_syserrmsgs + 1391, + [ECOMM] = _string_syserrmsgs + 1405, + [EPROTO] = _string_syserrmsgs + 1433, + [EMULTIHOP] = _string_syserrmsgs + 1448, + [EDOTDOT] = _string_syserrmsgs + 1467, + [EBADMSG] = _string_syserrmsgs + 1486, + [EOVERFLOW] = _string_syserrmsgs + 1498, + [ENOTUNIQ] = _string_syserrmsgs + 1536, + [EBADFD] = _string_syserrmsgs + 1563, + [EREMCHG] = _string_syserrmsgs + 1592, + [ELIBACC] = _string_syserrmsgs + 1615, + [ELIBBAD] = _string_syserrmsgs + 1654, + [ELIBSCN] = _string_syserrmsgs + 1691, + [ELIBMAX] = _string_syserrmsgs + 1723, + [ELIBEXEC] = _string_syserrmsgs + 1771, + [EILSEQ] = _string_syserrmsgs + 1809, + [ERESTART] = _string_syserrmsgs + 1859, + [ESTRPIPE] = _string_syserrmsgs + 1903, + [EUSERS] = _string_syserrmsgs + 1922, + [ENOTSOCK] = _string_syserrmsgs + 1937, + [EDESTADDRREQ] = _string_syserrmsgs + 1968, + [EMSGSIZE] = _string_syserrmsgs + 1997, + [EPROTOTYPE] = _string_syserrmsgs + 2014, + [ENOPROTOOPT] = _string_syserrmsgs + 2045, + [EPROTONOSUPPORT] = _string_syserrmsgs + 2068, + [ESOCKTNOSUPPORT] = _string_syserrmsgs + 2091, + [EOPNOTSUPP] = _string_syserrmsgs + 2117, + [EPFNOSUPPORT] = _string_syserrmsgs + 2141, + [EAFNOSUPPORT] = _string_syserrmsgs + 2171, + [EADDRINUSE] = _string_syserrmsgs + 2212, + [EADDRNOTAVAIL] = _string_syserrmsgs + 2235, + [ENETDOWN] = _string_syserrmsgs + 2267, + [ENETUNREACH] = _string_syserrmsgs + 2283, + [ENETRESET] = _string_syserrmsgs + 2306, + [ECONNABORTED] = _string_syserrmsgs + 2342, + [ECONNRESET] = _string_syserrmsgs + 2375, + [ENOBUFS] = _string_syserrmsgs + 2400, + [EISCONN] = _string_syserrmsgs + 2426, + [ENOTCONN] = _string_syserrmsgs + 2466, + [ESHUTDOWN] = _string_syserrmsgs + 2502, + [ETOOMANYREFS] = _string_syserrmsgs + 2548, + [ETIMEDOUT] = _string_syserrmsgs + 2583, + [ECONNREFUSED] = _string_syserrmsgs + 2604, + [EHOSTDOWN] = _string_syserrmsgs + 2623, + [EHOSTUNREACH] = _string_syserrmsgs + 2636, + [EALREADY] = _string_syserrmsgs + 2653, + [EINPROGRESS] = _string_syserrmsgs + 2683, + [ESTALE] = _string_syserrmsgs + 2709, + [EUCLEAN] = _string_syserrmsgs + 2731, + [ENOTNAM] = _string_syserrmsgs + 2756, + [ENAVAIL] = _string_syserrmsgs + 2784, + [EISNAM] = _string_syserrmsgs + 2814, + [EREMOTEIO] = _string_syserrmsgs + 2835, + [EDQUOT] = _string_syserrmsgs + 2852, + [ENOMEDIUM] = _string_syserrmsgs + 2872, + [EMEDIUMTYPE] = _string_syserrmsgs + 2888, + +#if EDEADLOCK != EDEADLK + [EDEADLOCK] = _string_syserrmsgs + 2906, +#endif + +#if EWOULDBLOCK != EAGAIN +#error EWOULDBLOCK does not equal EAGAIN +#endif + + /* For now, ignore the other arch-specific errors. glibc only maps EPROCLIM. */ + + /* some other mips errors */ +#ifdef ECANCELED +#endif +#ifdef EINIT +#endif +#ifdef EREMDEV +#endif + + /* some other sparc errors */ +#ifdef EPROCLIM +#endif +#ifdef ERREMOTE +#endif +}; + +int sys_nerr = sizeof(sys_errlist)/sizeof(sys_errlist[0]); + +#endif diff --git a/libc/string/sys_siglist.c b/libc/string/sys_siglist.c new file mode 100644 index 0000000..8443375 --- /dev/null +++ b/libc/string/sys_siglist.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#define __need_NULL +#include +#include + +extern const char _string_syssigmsgs[] attribute_hidden; + +#ifdef __UCLIBC_HAS_SYS_SIGLIST__ + +const char *const sys_siglist[_NSIG] = { + [0] = NULL, + [SIGHUP] = _string_syssigmsgs + 1, + [SIGINT] = _string_syssigmsgs + 8, + [SIGQUIT] = _string_syssigmsgs + 18, + [SIGILL] = _string_syssigmsgs + 23, + [SIGTRAP] = _string_syssigmsgs + 43, + [SIGABRT] = _string_syssigmsgs + 65, + [SIGBUS] = _string_syssigmsgs + 73, + [SIGFPE] = _string_syssigmsgs + 83, + [SIGKILL] = _string_syssigmsgs + 108, + [SIGUSR1] = _string_syssigmsgs + 115, + [SIGSEGV] = _string_syssigmsgs + 137, + [SIGUSR2] = _string_syssigmsgs + 156, + [SIGPIPE] = _string_syssigmsgs + 178, + [SIGALRM] = _string_syssigmsgs + 190, + [SIGTERM] = _string_syssigmsgs + 202, +#if defined SIGSTKFLT /* not all arches define this, yeah ! */ + [SIGSTKFLT] = _string_syssigmsgs + 213, +#endif + [SIGCHLD] = _string_syssigmsgs + 225, + [SIGCONT] = _string_syssigmsgs + 238, + [SIGSTOP] = _string_syssigmsgs + 248, + [SIGTSTP] = _string_syssigmsgs + 265, + [SIGTTIN] = _string_syssigmsgs + 273, + [SIGTTOU] = _string_syssigmsgs + 293, + [SIGURG] = _string_syssigmsgs + 314, + [SIGXCPU] = _string_syssigmsgs + 335, + [SIGXFSZ] = _string_syssigmsgs + 359, + [SIGVTALRM] = _string_syssigmsgs + 384, + [SIGPROF] = _string_syssigmsgs + 406, + [SIGWINCH] = _string_syssigmsgs + 430, + [SIGIO] = _string_syssigmsgs + 445, + [SIGPWR] = _string_syssigmsgs + 458, + [SIGSYS] = _string_syssigmsgs + 472, +#if defined SIGEMT /* only some arches define this, yeah ! */ + [SIGEMT] = _string_syssigmsgs + 488, +#endif +}; + +#endif diff --git a/libc/string/wcpcpy.c b/libc/string/wcpcpy.c new file mode 100644 index 0000000..b4fc8e6 --- /dev/null +++ b/libc/string/wcpcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "stpcpy.c" diff --git a/libc/string/wcpncpy.c b/libc/string/wcpncpy.c new file mode 100644 index 0000000..c5e5a76 --- /dev/null +++ b/libc/string/wcpncpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "stpncpy.c" diff --git a/libc/string/wcscasecmp.c b/libc/string/wcscasecmp.c new file mode 100644 index 0000000..95291b1 --- /dev/null +++ b/libc/string/wcscasecmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcasecmp.c" diff --git a/libc/string/wcscasecmp_l.c b/libc/string/wcscasecmp_l.c new file mode 100644 index 0000000..99e5723 --- /dev/null +++ b/libc/string/wcscasecmp_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#include "strcasecmp.c" diff --git a/libc/string/wcscat.c b/libc/string/wcscat.c new file mode 100644 index 0000000..36b4b63 --- /dev/null +++ b/libc/string/wcscat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcat.c" diff --git a/libc/string/wcschr.c b/libc/string/wcschr.c new file mode 100644 index 0000000..d16650a --- /dev/null +++ b/libc/string/wcschr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strchr.c" diff --git a/libc/string/wcschrnul.c b/libc/string/wcschrnul.c new file mode 100644 index 0000000..dc1b1bc --- /dev/null +++ b/libc/string/wcschrnul.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strchrnul.c" diff --git a/libc/string/wcscmp.c b/libc/string/wcscmp.c new file mode 100644 index 0000000..a33ed83 --- /dev/null +++ b/libc/string/wcscmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcmp.c" diff --git a/libc/string/wcscpy.c b/libc/string/wcscpy.c new file mode 100644 index 0000000..3479984 --- /dev/null +++ b/libc/string/wcscpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcpy.c" diff --git a/libc/string/wcscspn.c b/libc/string/wcscspn.c new file mode 100644 index 0000000..945ecef --- /dev/null +++ b/libc/string/wcscspn.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcspn.c" diff --git a/libc/string/wcsdup.c b/libc/string/wcsdup.c new file mode 100644 index 0000000..8885a2b --- /dev/null +++ b/libc/string/wcsdup.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strdup.c" diff --git a/libc/string/wcslcpy.c b/libc/string/wcslcpy.c new file mode 100644 index 0000000..f62ea14 --- /dev/null +++ b/libc/string/wcslcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strlcpy.c" diff --git a/libc/string/wcslen.c b/libc/string/wcslen.c new file mode 100644 index 0000000..ac4637e --- /dev/null +++ b/libc/string/wcslen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strlen.c" diff --git a/libc/string/wcsncasecmp.c b/libc/string/wcsncasecmp.c new file mode 100644 index 0000000..230efda --- /dev/null +++ b/libc/string/wcsncasecmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncasecmp.c" diff --git a/libc/string/wcsncasecmp_l.c b/libc/string/wcsncasecmp_l.c new file mode 100644 index 0000000..acdb26b --- /dev/null +++ b/libc/string/wcsncasecmp_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#include "strncasecmp.c" diff --git a/libc/string/wcsncat.c b/libc/string/wcsncat.c new file mode 100644 index 0000000..776f1b7 --- /dev/null +++ b/libc/string/wcsncat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncat.c" diff --git a/libc/string/wcsncmp.c b/libc/string/wcsncmp.c new file mode 100644 index 0000000..224844f --- /dev/null +++ b/libc/string/wcsncmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncmp.c" diff --git a/libc/string/wcsncpy.c b/libc/string/wcsncpy.c new file mode 100644 index 0000000..ac267e8 --- /dev/null +++ b/libc/string/wcsncpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncpy.c" diff --git a/libc/string/wcsnlen.c b/libc/string/wcsnlen.c new file mode 100644 index 0000000..917a2c9 --- /dev/null +++ b/libc/string/wcsnlen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strnlen.c" diff --git a/libc/string/wcspbrk.c b/libc/string/wcspbrk.c new file mode 100644 index 0000000..b416f7c --- /dev/null +++ b/libc/string/wcspbrk.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strpbrk.c" diff --git a/libc/string/wcsrchr.c b/libc/string/wcsrchr.c new file mode 100644 index 0000000..3290820 --- /dev/null +++ b/libc/string/wcsrchr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strrchr.c" diff --git a/libc/string/wcsspn.c b/libc/string/wcsspn.c new file mode 100644 index 0000000..9716315 --- /dev/null +++ b/libc/string/wcsspn.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strspn.c" diff --git a/libc/string/wcsstr.c b/libc/string/wcsstr.c new file mode 100644 index 0000000..69a94e5 --- /dev/null +++ b/libc/string/wcsstr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strstr.c" diff --git a/libc/string/wcstok.c b/libc/string/wcstok.c new file mode 100644 index 0000000..591c214 --- /dev/null +++ b/libc/string/wcstok.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strtok_r.c" diff --git a/libc/string/wcsxfrm.c b/libc/string/wcsxfrm.c new file mode 100644 index 0000000..8b37495 --- /dev/null +++ b/libc/string/wcsxfrm.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define L_wcsxfrm +#include "_collate.c" diff --git a/libc/string/wcsxfrm_l.c b/libc/string/wcsxfrm_l.c new file mode 100644 index 0000000..67e2f17 --- /dev/null +++ b/libc/string/wcsxfrm_l.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#define L_wcsxfrm_l +#include "_collate.c" diff --git a/libc/string/wmemchr.c b/libc/string/wmemchr.c new file mode 100644 index 0000000..f4069e4 --- /dev/null +++ b/libc/string/wmemchr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memchr.c" diff --git a/libc/string/wmemcmp.c b/libc/string/wmemcmp.c new file mode 100644 index 0000000..9168705 --- /dev/null +++ b/libc/string/wmemcmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memcmp.c" diff --git a/libc/string/wmemcpy.c b/libc/string/wmemcpy.c new file mode 100644 index 0000000..6991ece --- /dev/null +++ b/libc/string/wmemcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memcpy.c" diff --git a/libc/string/wmemmove.c b/libc/string/wmemmove.c new file mode 100644 index 0000000..1727049 --- /dev/null +++ b/libc/string/wmemmove.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memmove.c" diff --git a/libc/string/wmempcpy.c b/libc/string/wmempcpy.c new file mode 100644 index 0000000..d995a80 --- /dev/null +++ b/libc/string/wmempcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "mempcpy.c" diff --git a/libc/string/wmemset.c b/libc/string/wmemset.c new file mode 100644 index 0000000..0efe178 --- /dev/null +++ b/libc/string/wmemset.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memset.c" diff --git a/libc/string/x86_64/Makefile b/libc/string/x86_64/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/x86_64/_glibc_inc.h b/libc/string/x86_64/_glibc_inc.h new file mode 100644 index 0000000..415ce90 --- /dev/null +++ b/libc/string/x86_64/_glibc_inc.h @@ -0,0 +1,21 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +#define ENTRY(sym) \ + .global sym; \ + .type sym,%function; \ + sym: + +#define BP_SYM(sym) sym + +#define L(sym) LOC(sym) +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/libc/string/x86_64/bzero.S b/libc/string/x86_64/bzero.S new file mode 100644 index 0000000..4d179ec --- /dev/null +++ b/libc/string/x86_64/bzero.S @@ -0,0 +1,5 @@ +#include +#ifdef __UCLIBC_SUSV3_LEGACY__ +# define memset bzero +# include "memset.S" +#endif diff --git a/libc/string/x86_64/memcpy.S b/libc/string/x86_64/memcpy.S new file mode 100644 index 0000000..697b992 --- /dev/null +++ b/libc/string/x86_64/memcpy.S @@ -0,0 +1,98 @@ +/* Highly optimized version for x86-64. + Copyright (C) 1997, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on i586 version contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* BEWARE: `#ifdef memcpy' means that memcpy is redefined as `mempcpy', + and the return value is the byte after the last one copied in + the destination. */ +#define MEMPCPY_P (defined memcpy) + + .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memcpy_chk) + cmpq %rdx, %rcx + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memcpy_chk) +#endif +ENTRY (BP_SYM (memcpy)) + /* Cutoff for the big loop is a size of 32 bytes since otherwise + the loop will never be entered. */ + cmpq $32, %rdx + movq %rdx, %rcx +#if !MEMPCPY_P + movq %rdi, %r10 /* Save value. */ +#endif + + /* We need this in any case. */ + cld + + jbe 1f + + /* Align destination. */ + movq %rdi, %rax + negq %rax + andq $7, %rax + subq %rax, %rcx + xchgq %rax, %rcx + + rep; movsb + + movq %rax, %rcx + subq $32, %rcx + js 2f + + /* Next 3 insns are 11 bytes total, make sure we decode them in one go */ + .p2align 4,,11 +3: + /* Now correct the loop counter. Please note that in the following + code the flags are not changed anymore. */ + subq $32, %rcx + + movq (%rsi), %rax + movq 8(%rsi), %rdx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + + leaq 32(%rsi), %rsi + leaq 32(%rdi), %rdi + + jns 3b + + /* Correct extra loop counter modification. */ +2: addq $32, %rcx +1: rep; movsb + +#if MEMPCPY_P + movq %rdi, %rax /* Set return value. */ +#else + movq %r10, %rax /* Set return value. */ + +#endif + ret + +END (BP_SYM (memcpy)) +#if !MEMPCPY_P +libc_hidden_def(memcpy) +#endif diff --git a/libc/string/x86_64/mempcpy.S b/libc/string/x86_64/mempcpy.S new file mode 100644 index 0000000..3816d9f --- /dev/null +++ b/libc/string/x86_64/mempcpy.S @@ -0,0 +1,3 @@ +#define memcpy mempcpy +#include "memcpy.S" +libc_hidden_def(mempcpy) diff --git a/libc/string/x86_64/memset.S b/libc/string/x86_64/memset.S new file mode 100644 index 0000000..4675100 --- /dev/null +++ b/libc/string/x86_64/memset.S @@ -0,0 +1,147 @@ +/* memset/bzero -- set memory area to CH/0 + Optimized version for x86-64. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* BEWARE: `#ifdef memset' means that memset is redefined as `bzero' */ +#define BZERO_P (defined memset) + +/* This is somehow experimental and could made dependend on the cache + size. */ +#define LARGE $120000 + + .text +#if !BZERO_P && defined PIC && !defined NOT_IN_libc +ENTRY (__memset_chk) + cmpq %rdx, %rcx + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memset_chk) +#endif +ENTRY (memset) +#if BZERO_P + mov %rsi,%rdx /* Adjust parameter. */ + xorl %esi,%esi /* Fill with 0s. */ +#endif + cmp $0x7,%rdx /* Check for small length. */ + mov %rdi,%rcx /* Save ptr as return value. */ + jbe 7f + +#if BZERO_P + mov %rsi,%r8 /* Just copy 0. */ +#else + /* Populate 8 bit data to full 64-bit. */ + movabs $0x0101010101010101,%r8 + movzbl %sil,%eax + imul %rax,%r8 +#endif + test $0x7,%edi /* Check for alignment. */ + jz 2f + + /* Next 3 insns are 9 bytes total, make sure we decode them in one go */ + .p2align 4,,9 +1: + /* Align ptr to 8 byte. */ + mov %sil,(%rcx) + dec %rdx + inc %rcx + test $0x7,%cl + jnz 1b + +2: /* Check for really large regions. */ + mov %rdx,%rax + shr $0x6,%rax + je 4f + cmp LARGE, %rdx + jae 11f + + /* Next 3 insns are 11 bytes total, make sure we decode them in one go */ + .p2align 4,,11 +3: + /* Fill 64 bytes. */ + mov %r8,(%rcx) + mov %r8,0x8(%rcx) + mov %r8,0x10(%rcx) + mov %r8,0x18(%rcx) + mov %r8,0x20(%rcx) + mov %r8,0x28(%rcx) + mov %r8,0x30(%rcx) + mov %r8,0x38(%rcx) + add $0x40,%rcx + dec %rax + jne 3b + +4: /* Fill final bytes. */ + and $0x3f,%edx + mov %rdx,%rax + shr $0x3,%rax + je 6f + +5: /* First in chunks of 8 bytes. */ + mov %r8,(%rcx) + add $0x8,%rcx + dec %rax + jne 5b +6: + and $0x7,%edx +7: + test %rdx,%rdx + je 9f +8: /* And finally as bytes (up to 7). */ + mov %sil,(%rcx) + inc %rcx + dec %rdx + jne 8b +9: +#if BZERO_P + /* nothing */ +#else + /* Load result (only if used as memset). */ + mov %rdi,%rax /* start address of destination is result */ +#endif + retq + + /* Next 3 insns are 14 bytes total, make sure we decode them in one go */ + .p2align 4,,14 +11: + /* Fill 64 bytes without polluting the cache. */ + /* We could use movntdq %xmm0,(%rcx) here to further + speed up for large cases but let's not use XMM registers. */ + movnti %r8,(%rcx) + movnti %r8,0x8(%rcx) + movnti %r8,0x10(%rcx) + movnti %r8,0x18(%rcx) + movnti %r8,0x20(%rcx) + movnti %r8,0x28(%rcx) + movnti %r8,0x30(%rcx) + movnti %r8,0x38(%rcx) + add $0x40,%rcx + dec %rax + jne 11b + jmp 4b + +END (memset) +#if !BZERO_P +libc_hidden_def(memset) +#endif + +#if !BZERO_P && defined PIC && !defined NOT_IN_libc +strong_alias (__memset_chk, __memset_zero_constant_len_parameter) +#endif diff --git a/libc/string/x86_64/stpcpy.S b/libc/string/x86_64/stpcpy.S new file mode 100644 index 0000000..138d0fb --- /dev/null +++ b/libc/string/x86_64/stpcpy.S @@ -0,0 +1,4 @@ +#define USE_AS_STPCPY +#define STRCPY stpcpy +#include "strcpy.S" +libc_hidden_def(stpcpy) diff --git a/libc/string/x86_64/strcat.S b/libc/string/x86_64/strcat.S new file mode 100644 index 0000000..23d068f --- /dev/null +++ b/libc/string/x86_64/strcat.S @@ -0,0 +1,268 @@ +/* strcat(dest, src) -- Append SRC on the end of DEST. + Optimized for x86-64. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (BP_SYM (strcat)) + movq %rdi, %rcx /* Dest. register. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rax /* Duplicate destination pointer. */ + movq $0xfefefefefefefeff,%r8 + + /* First step: Find end of destination. */ + jz 4f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: cmpb $0x0,(%rax) /* is byte NUL? */ + je 2f /* yes => start copy */ + incq %rax /* increment pointer */ + decl %ecx + jnz 0b + + + + /* Now the source is aligned. Scan for NUL byte. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => continue loop */ + + /* Align, it is a jump target. */ + /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ + .p2align 3,,8 +3: + subq $8,%rax /* correct pointer increment. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0x00ff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + testl $0xff000000, %ecx /* is fourth byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + shrq $32, %rcx /* look at other half. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0xff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + +2: + /* Second step: Copy source to destination. */ + + movq %rsi, %rcx /* duplicate */ + andl $7,%ecx /* mask alignment bits */ + movq %rax, %rdx /* move around */ + jz 22f /* aligned => start loop */ + + neg %ecx /* align to 8 bytes. */ + addl $8, %ecx + /* Align the source pointer. */ +21: + movb (%rsi), %al /* Fetch a byte */ + testb %al, %al /* Is it NUL? */ + movb %al, (%rdx) /* Store it */ + jz 24f /* If it was NUL, done! */ + incq %rsi + incq %rdx + decl %ecx + jnz 21b + + /* Now the sources is aligned. Unfortunatly we cannot force + to have both source and destination aligned, so ignore the + alignment of the destination. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +22: + /* 1st unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 2nd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 3rd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 4th unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + jmp 22b /* Next iteration. */ + + /* Do the last few bytes. %rax contains the value to write. + The loop is unrolled twice. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +23: + movb %al, (%rdx) /* 1st byte. */ + testb %al, %al /* Is it NUL. */ + jz 24f /* yes, finish. */ + incq %rdx /* Increment destination. */ + movb %ah, (%rdx) /* 2nd byte. */ + testb %ah, %ah /* Is it NUL?. */ + jz 24f /* yes, finish. */ + incq %rdx /* Increment destination. */ + shrq $16, %rax /* Shift... */ + jmp 23b /* and look at next two bytes in %rax. */ + + +24: + movq %rdi, %rax /* Source is return value. */ + retq +END (BP_SYM (strcat)) + +libc_hidden_def(strcat) diff --git a/libc/string/x86_64/strchr.S b/libc/string/x86_64/strchr.S new file mode 100644 index 0000000..9ef46b7 --- /dev/null +++ b/libc/string/x86_64/strchr.S @@ -0,0 +1,295 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For AMD x86-64. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (BP_SYM (strchr)) + + /* Before we start with the main loop we process single bytes + until the source pointer is aligned. This has two reasons: + 1. aligned 64-bit memory access is faster + and (more important) + 2. we process in the main loop 64 bit in one step although + we don't know the end of the string. But accessing at + 8-byte alignment guarantees that we never access illegal + memory if this would not also be done by the trivial + implementation (this is because all processor inherent + boundaries are multiples of 8). */ + + movq %rdi, %rdx + andl $7, %edx /* Mask alignment bits */ + movq %rdi, %rax /* duplicate destination. */ + jz 1f /* aligned => start loop */ + neg %edx + addl $8, %edx /* Align to 8 bytes. */ + + /* Search the first bytes directly. */ +0: movb (%rax), %cl /* load byte */ + cmpb %cl,%sil /* compare byte. */ + je 6f /* target found */ + testb %cl,%cl /* is byte NUL? */ + je 7f /* yes => return NULL */ + incq %rax /* increment pointer */ + decl %edx + jnz 0b + + +1: + /* At the moment %rsi contains C. What we need for the + algorithm is C in all bytes of the register. Avoid + operations on 16 bit words because these require an + prefix byte (and one more cycle). */ + /* Populate 8 bit data to full 64-bit. */ + movabs $0x0101010101010101,%r9 + movzbl %sil,%edx + imul %rdx,%r9 + + movq $0xfefefefefefefeff, %r8 /* Save magic. */ + + /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to + change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of QUARDWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24 tec.. If one of bits 54-63 is set, there will be a carry + into bit 64 (=carry flag), so all of the hole bits will + be changed. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* Main Loop is unrolled 4 times. */ + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => restart loop */ + + +7: /* Return NULL. */ + xorl %eax, %eax + retq + + + /* We now scan for the byte in which the character was matched. + But we have to take care of the case that a NUL char is + found before this in the dword. Note that we XORed %rcx + with the byte we're looking for, therefore the tests below look + reversed. */ + + + /* Align, it's a jump target. */ + /* Next 3 insns are 9 bytes total, make sure we decode them in one go */ + .p2align 4,,9 +3: + movq %r9,%rdx /* move to %rdx so that we can access bytes */ + subq $8,%rax /* correct pointer increment. */ + testb %cl, %cl /* is first byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is first byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is second byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is third byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is third byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is fourth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is fourth byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is fifth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is fifth byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is sixth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is sixth byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is seventh byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is seventh byte NUL? */ + je 7b /* yes => return NULL */ + + /* It must be in the eigth byte and it cannot be NUL. */ + incq %rax + +6: + /* nop - huh?? */ + retq +END (BP_SYM (strchr)) + +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (BP_SYM (strchr), BP_SYM (index)) +#endif diff --git a/libc/string/x86_64/strcmp.S b/libc/string/x86_64/strcmp.S new file mode 100644 index 0000000..437e145 --- /dev/null +++ b/libc/string/x86_64/strcmp.S @@ -0,0 +1,47 @@ +/* Highly optimized version for x86-64. + Copyright (C) 1999, 2000, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on i686 version contributed by Ulrich Drepper + , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + + .text +ENTRY (BP_SYM (strcmp)) +L(oop): movb (%rdi), %al + cmpb (%rsi), %al + jne L(neq) + incq %rdi + incq %rsi + testb %al, %al + jnz L(oop) + + xorl %eax, %eax + ret + +L(neq): movl $1, %eax + movl $-1, %ecx + cmovbl %ecx, %eax + ret +END (BP_SYM (strcmp)) + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/libc/string/x86_64/strcpy.S b/libc/string/x86_64/strcpy.S new file mode 100644 index 0000000..612a30d --- /dev/null +++ b/libc/string/x86_64/strcpy.S @@ -0,0 +1,162 @@ +/* strcpy/stpcpy implementation for x86-64. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + +#ifndef USE_AS_STPCPY +# define STRCPY strcpy +#endif + + .text +ENTRY (BP_SYM (STRCPY)) + movq %rsi, %rcx /* Source register. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rdx /* Duplicate destination pointer. */ + + jz 5f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: + movb (%rsi), %al /* Fetch a byte */ + testb %al, %al /* Is it NUL? */ + movb %al, (%rdx) /* Store it */ + jz 4f /* If it was NUL, done! */ + incq %rsi + incq %rdx + decl %ecx + jnz 0b + +5: + movq $0xfefefefefefefeff,%r8 + + /* Now the sources is aligned. Unfortunatly we cannot force + to have both source and destination aligned, so ignore the + alignment of the destination. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +1: + /* 1st unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 2nd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 3rd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 4th unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + jmp 1b /* Next iteration. */ + + /* Do the last few bytes. %rax contains the value to write. + The loop is unrolled twice. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +3: + /* Note that stpcpy needs to return with the value of the NUL + byte. */ + movb %al, (%rdx) /* 1st byte. */ + testb %al, %al /* Is it NUL. */ + jz 4f /* yes, finish. */ + incq %rdx /* Increment destination. */ + movb %ah, (%rdx) /* 2nd byte. */ + testb %ah, %ah /* Is it NUL?. */ + jz 4f /* yes, finish. */ + incq %rdx /* Increment destination. */ + shrq $16, %rax /* Shift... */ + jmp 3b /* and look at next two bytes in %rax. */ + +4: +#ifdef USE_AS_STPCPY + movq %rdx, %rax /* Destination is return value. */ +#else + movq %rdi, %rax /* Source is return value. */ +#endif + retq +END (BP_SYM (STRCPY)) +#ifndef USE_AS_STPCPY +libc_hidden_def(strcpy) +#endif diff --git a/libc/string/x86_64/strcspn.S b/libc/string/x86_64/strcspn.S new file mode 100644 index 0000000..fd9b09c --- /dev/null +++ b/libc/string/x86_64/strcspn.S @@ -0,0 +1,137 @@ +/* strcspn (str, ss) -- Return the length of the initial segment of STR + which contains no characters from SS. + For AMD x86-64. + Copyright (C) 1994-1997, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + Bug fixes by Alan Modra . + Adopted for x86-64 by Andreas Jaeger . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + +/* BEWARE: `#ifdef strcspn' means that strcspn is redefined as `strpbrk' */ +#define STRPBRK_P (defined strcspn) + + .text +ENTRY (strcspn) + + movq %rdi, %rdx /* Save SRC. */ + + /* First we create a table with flags for all possible characters. + For the ASCII (7bit/8bit) or ISO-8859-X character sets which are + supported by the C string functions we have 256 characters. + Before inserting marks for the stop characters we clear the whole + table. */ + movq %rdi, %r8 /* Save value. */ + subq $256, %rsp /* Make space for 256 bytes. */ + movl $32, %ecx /* 32*8 bytes = 256 bytes. */ + movq %rsp, %rdi + xorl %eax, %eax /* We store 0s. */ + cld + rep + stosq + + movq %rsi, %rax /* Setup skipset. */ + +/* For understanding the following code remember that %rcx == 0 now. + Although all the following instruction only modify %cl we always + have a correct zero-extended 64-bit value in %rcx. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 + +L(2): movb (%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 1(%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 2(%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 3(%rax), %cl /* get byte from skipset */ + addq $4, %rax /* increment skipset pointer */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + testb %cl, %cl /* is NUL char? */ + jnz L(2) /* no => process next dword from skipset */ + +L(1): leaq -4(%rdx), %rax /* prepare loop */ + + /* We use a neat trick for the following loop. Normally we would + have to test for two termination conditions + 1. a character in the skipset was found + and + 2. the end of the string was found + But as a sign that the character is in the skipset we store its + value in the table. But the value of NUL is NUL so the loop + terminates for NUL in every case. */ + + /* Next 3 insns are 9 bytes total. */ + /* .p2align 4,,9 would make sure we decode them in one go, */ + /* but it will also align entire function to 16 bytes, */ + /* potentially creating largish padding at link time. */ + /* We are aligning to 8 bytes instead: */ + .p2align 3,,8 + +L(3): addq $4, %rax /* adjust pointer for full loop round */ + + movb (%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + je L(4) /* yes => return */ + + movb 1(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + je L(5) /* yes => return */ + + movb 2(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(6) /* yes => return */ + + movb 3(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jne L(3) /* no => start loop again */ + + incq %rax /* adjust pointer */ +L(6): incq %rax +L(5): incq %rax + +L(4): addq $256, %rsp /* remove skipset */ +#if STRPBRK_P + xorl %edx,%edx + orb %cl, %cl /* was last character NUL? */ + cmovzq %rdx, %rax /* Yes: return NULL */ +#else + subq %rdx, %rax /* we have to return the number of valid + characters, so compute distance to first + non-valid character */ +#endif + ret +END (strcspn) + +#if !STRPBRK_P +libc_hidden_def(strcspn) +#endif diff --git a/libc/string/x86_64/strlen.S b/libc/string/x86_64/strlen.S new file mode 100644 index 0000000..4213f0a --- /dev/null +++ b/libc/string/x86_64/strlen.S @@ -0,0 +1,144 @@ +/* strlen(str) -- determine the length of the string STR. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + Based on i486 version contributed by Ulrich Drepper . + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (strlen) + movq %rdi, %rcx /* Duplicate source pointer. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rax /* duplicate destination. */ + jz 1f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: cmpb $0x0,(%rax) /* is byte NUL? */ + je 2f /* yes => return */ + incq %rax /* increment pointer */ + decl %ecx + jnz 0b + +1: movq $0xfefefefefefefeff,%r8 /* Save magic. */ + + /* Align loop. */ + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* Main Loop is unrolled 4 times. */ + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => continue loop */ + + /* Align, it is a jump target. */ + /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ + .p2align 3,,8 +3: + subq $8,%rax /* correct pointer increment. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0x00ff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + testl $0xff000000, %ecx /* is fourth byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + shrq $32, %rcx /* look at other half. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0xff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ +2: + subq %rdi, %rax /* compute difference to string start */ + ret +END (strlen) + +libc_hidden_def(strlen) diff --git a/libc/string/x86_64/strpbrk.S b/libc/string/x86_64/strpbrk.S new file mode 100644 index 0000000..db6cc24 --- /dev/null +++ b/libc/string/x86_64/strpbrk.S @@ -0,0 +1,3 @@ +#define strcspn strpbrk +#include "strcspn.S" +libc_hidden_def(strpbrk) diff --git a/libc/string/x86_64/strspn.S b/libc/string/x86_64/strspn.S new file mode 100644 index 0000000..41cff04 --- /dev/null +++ b/libc/string/x86_64/strspn.S @@ -0,0 +1,124 @@ +/* strspn (str, ss) -- Return the length of the initial segment of STR + which contains only characters from SS. + For AMD x86-64. + Copyright (C) 1994-1997, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + Bug fixes by Alan Modra . + Adopted for x86-64 by Andreas Jaeger . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + + .text +ENTRY (strspn) + + movq %rdi, %rdx /* Save SRC. */ + + /* First we create a table with flags for all possible characters. + For the ASCII (7bit/8bit) or ISO-8859-X character sets which are + supported by the C string functions we have 256 characters. + Before inserting marks for the stop characters we clear the whole + table. */ + movq %rdi, %r8 /* Save value. */ + subq $256, %rsp /* Make space for 256 bytes. */ + movl $32, %ecx /* 32*8 bytes = 256 bytes. */ + movq %rsp, %rdi + xorl %eax, %eax /* We store 0s. */ + cld + rep + stosq + + movq %rsi, %rax /* Setup stopset. */ + +/* For understanding the following code remember that %rcx == 0 now. + Although all the following instruction only modify %cl we always + have a correct zero-extended 64-bit value in %rcx. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +L(2): + movb (%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 1(%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 2(%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 3(%rax), %cl /* get byte from stopset */ + addq $4, %rax /* increment stopset pointer */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + testb %cl, %cl /* is NUL char? */ + jnz L(2) /* no => process next dword from stopset */ + +L(1): leaq -4(%rdx), %rax /* prepare loop */ + + /* We use a neat trick for the following loop. Normally we would + have to test for two termination conditions + 1. a character in the stopset was found + and + 2. the end of the string was found + But as a sign that the character is in the stopset we store its + value in the table. But the value of NUL is NUL so the loop + terminates for NUL in every case. */ + + /* Next 3 insns are 9 bytes total. */ + /* .p2align 4,,9 would make sure we decode them in one go, */ + /* but it will also align entire function to 16 bytes, */ + /* potentially creating largish padding at link time. */ + /* We are aligning to 8 bytes instead: */ + .p2align 3,,8 +L(3): + addq $4, %rax /* adjust pointer for full loop round */ + + movb (%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(4) /* no => return */ + + movb 1(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(5) /* no => return */ + + movb 2(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(6) /* no => return */ + + movb 3(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jnz L(3) /* yes => start loop again */ + + incq %rax /* adjust pointer */ +L(6): incq %rax +L(5): incq %rax + +L(4): addq $256, %rsp /* remove stopset */ + subq %rdx, %rax /* we have to return the number of valid + characters, so compute distance to first + non-valid character */ + ret +END (strspn) + +libc_hidden_def(strspn) diff --git a/libc/string/xtensa/Makefile b/libc/string/xtensa/Makefile new file mode 100644 index 0000000..0a95346 --- /dev/null +++ b/libc/string/xtensa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/xtensa/memcpy.S b/libc/string/xtensa/memcpy.S new file mode 100644 index 0000000..fc04c02 --- /dev/null +++ b/libc/string/xtensa/memcpy.S @@ -0,0 +1,297 @@ +/* Optimized memcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + + .macro src_b r, w0, w1 +#ifdef __XTENSA_EB__ + src \r, \w0, \w1 +#else + src \r, \w1, \w0 +#endif + .endm + + .macro ssa8 r +#ifdef __XTENSA_EB__ + ssa8b \r +#else + ssa8l \r +#endif + .endm + +/* If the Xtensa Unaligned Load Exception option is not used, this + code can run a few cycles faster by relying on the low address bits + being ignored. However, if the code is then run with an Xtensa ISS + client that checks for unaligned accesses, it will produce a lot of + warning messages. Set this flag to disable the use of unaligned + accesses and keep the ISS happy. */ + +#define UNALIGNED_ADDRESSES_CHECKED 1 + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + + +/* void *memcpy (void *dst, const void *src, size_t len) + + The algorithm is as follows: + + If the destination is unaligned, align it by conditionally + copying 1- and/or 2-byte pieces. + + If the source is aligned, copy 16 bytes with a loop, and then finish up + with 8, 4, 2, and 1-byte copies conditional on the length. + + Else (if source is unaligned), do the same, but use SRC to align the + source data. + + This code tries to use fall-through branches for the common + case of aligned source and destination and multiple of 4 (or 8) length. */ + + +/* Byte by byte copy. */ + + .text + .align 4 + .literal_position +__memcpy_aux: + + /* Skip a byte to get 1 mod 4 alignment for LOOPNEZ + (0 mod 4 alignment for LBEG). */ + .byte 0 + +.Lbytecopy: +#if XCHAL_HAVE_LOOPS + loopnez a4, 2f +#else + beqz a4, 2f + add a7, a3, a4 /* a7 = end address for source */ +#endif +1: l8ui a6, a3, 0 + addi a3, a3, 1 + s8i a6, a5, 0 + addi a5, a5, 1 +#if !XCHAL_HAVE_LOOPS + blt a3, a7, 1b +#endif +2: retw + + +/* Destination is unaligned. */ + + .align 4 +.Ldst1mod2: /* dst is only byte aligned */ + + /* Do short copies byte-by-byte. */ + _bltui a4, 7, .Lbytecopy + + /* Copy 1 byte. */ + l8ui a6, a3, 0 + addi a3, a3, 1 + addi a4, a4, -1 + s8i a6, a5, 0 + addi a5, a5, 1 + + /* Return to main algorithm if dst is now aligned. */ + _bbci.l a5, 1, .Ldstaligned + +.Ldst2mod4: /* dst has 16-bit alignment */ + + /* Do short copies byte-by-byte. */ + _bltui a4, 6, .Lbytecopy + + /* Copy 2 bytes. */ + l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a3, a3, 2 + addi a4, a4, -2 + s8i a6, a5, 0 + s8i a7, a5, 1 + addi a5, a5, 2 + + /* dst is now aligned; return to main algorithm. */ + j .Ldstaligned + + +ENTRY (memcpy) + /* a2 = dst, a3 = src, a4 = len */ + + mov a5, a2 /* copy dst so that a2 is return value */ + _bbsi.l a2, 0, .Ldst1mod2 + _bbsi.l a2, 1, .Ldst2mod4 +.Ldstaligned: + + /* Get number of loop iterations with 16B per iteration. */ + srli a7, a4, 4 + + /* Check if source is aligned. */ + movi a8, 3 + _bany a3, a8, .Lsrcunaligned + + /* Destination and source are word-aligned, use word copy. */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a8, a7, 4 + add a8, a8, a3 /* a8 = end of last 16B source chunk */ +#endif +1: l32i a6, a3, 0 + l32i a7, a3, 4 + s32i a6, a5, 0 + l32i a6, a3, 8 + s32i a7, a5, 4 + l32i a7, a3, 12 + s32i a6, a5, 8 + addi a3, a3, 16 + s32i a7, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a3, a8, 1b +#endif + + /* Copy any leftover pieces smaller than 16B. */ +2: bbci.l a4, 3, 3f + + /* Copy 8 bytes. */ + l32i a6, a3, 0 + l32i a7, a3, 4 + addi a3, a3, 8 + s32i a6, a5, 0 + s32i a7, a5, 4 + addi a5, a5, 8 + +3: bbsi.l a4, 2, 4f + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 4 bytes. */ +4: l32i a6, a3, 0 + addi a3, a3, 4 + s32i a6, a5, 0 + addi a5, a5, 4 + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 2 bytes. */ +5: l16ui a6, a3, 0 + addi a3, a3, 2 + s16i a6, a5, 0 + addi a5, a5, 2 + bbsi.l a4, 0, 6f + retw + + /* Copy 1 byte. */ +6: l8ui a6, a3, 0 + s8i a6, a5, 0 + +.Ldone: + retw + + +/* Destination is aligned; source is unaligned. */ + + .align 4 +.Lsrcunaligned: + /* Avoid loading anything for zero-length copies. */ + _beqz a4, .Ldone + + /* Copy 16 bytes per iteration for word-aligned dst and + unaligned src. */ + ssa8 a3 /* set shift amount from byte offset */ +#if UNALIGNED_ADDRESSES_CHECKED + and a11, a3, a8 /* save unalignment offset for below */ + sub a3, a3, a11 /* align a3 */ +#endif + l32i a6, a3, 0 /* load first word */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a10, a7, 4 + add a10, a10, a3 /* a10 = end of last 16B source chunk */ +#endif +1: l32i a7, a3, 4 + l32i a8, a3, 8 + src_b a6, a6, a7 + s32i a6, a5, 0 + l32i a9, a3, 12 + src_b a7, a7, a8 + s32i a7, a5, 4 + l32i a6, a3, 16 + src_b a8, a8, a9 + s32i a8, a5, 8 + addi a3, a3, 16 + src_b a9, a9, a6 + s32i a9, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a3, a10, 1b +#endif + +2: bbci.l a4, 3, 3f + + /* Copy 8 bytes. */ + l32i a7, a3, 4 + l32i a8, a3, 8 + src_b a6, a6, a7 + s32i a6, a5, 0 + addi a3, a3, 8 + src_b a7, a7, a8 + s32i a7, a5, 4 + addi a5, a5, 8 + mov a6, a8 + +3: bbci.l a4, 2, 4f + + /* Copy 4 bytes. */ + l32i a7, a3, 4 + addi a3, a3, 4 + src_b a6, a6, a7 + s32i a6, a5, 0 + addi a5, a5, 4 + mov a6, a7 +4: +#if UNALIGNED_ADDRESSES_CHECKED + add a3, a3, a11 /* readjust a3 with correct misalignment */ +#endif + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 2 bytes. */ +5: l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a3, a3, 2 + s8i a6, a5, 0 + s8i a7, a5, 1 + addi a5, a5, 2 + bbsi.l a4, 0, 6f + retw + + /* Copy 1 byte. */ +6: l8ui a6, a3, 0 + s8i a6, a5, 0 + retw + +libc_hidden_def (memcpy) diff --git a/libc/string/xtensa/memset.S b/libc/string/xtensa/memset.S new file mode 100644 index 0000000..076b8f0 --- /dev/null +++ b/libc/string/xtensa/memset.S @@ -0,0 +1,165 @@ +/* Optimized memset for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + +/* void *memset (void *dst, int c, size_t length) + + The algorithm is as follows: + + Create a word with c in all byte positions. + + If the destination is aligned, set 16B chunks with a loop, and then + finish up with 8B, 4B, 2B, and 1B stores conditional on the length. + + If the destination is unaligned, align it by conditionally + setting 1B and/or 2B and then go to aligned case. + + This code tries to use fall-through branches for the common + case of an aligned destination (except for the branches to + the alignment labels). */ + + +/* Byte-by-byte set. */ + + .text + .align 4 + .literal_position +__memset_aux: + + /* Skip a byte to get 1 mod 4 alignment for LOOPNEZ + (0 mod 4 alignment for LBEG). */ + .byte 0 + +.Lbyteset: +#if XCHAL_HAVE_LOOPS + loopnez a4, 2f +#else + beqz a4, 2f + add a6, a5, a4 /* a6 = ending address */ +#endif +1: s8i a3, a5, 0 + addi a5, a5, 1 +#if !XCHAL_HAVE_LOOPS + blt a5, a6, 1b +#endif +2: retw + + +/* Destination is unaligned. */ + + .align 4 + +.Ldst1mod2: /* dst is only byte aligned */ + + /* Do short sizes byte-by-byte. */ + bltui a4, 8, .Lbyteset + + /* Set 1 byte. */ + s8i a3, a5, 0 + addi a5, a5, 1 + addi a4, a4, -1 + + /* Now retest if dst is aligned. */ + _bbci.l a5, 1, .Ldstaligned + +.Ldst2mod4: /* dst has 16-bit alignment */ + + /* Do short sizes byte-by-byte. */ + bltui a4, 8, .Lbyteset + + /* Set 2 bytes. */ + s16i a3, a5, 0 + addi a5, a5, 2 + addi a4, a4, -2 + + /* dst is now aligned; return to main algorithm */ + j .Ldstaligned + + +ENTRY (memset) + /* a2 = dst, a3 = c, a4 = length */ + + /* Duplicate character into all bytes of word. */ + extui a3, a3, 0, 8 + slli a7, a3, 8 + or a3, a3, a7 + slli a7, a3, 16 + or a3, a3, a7 + + mov a5, a2 /* copy dst so that a2 is return value */ + + /* Check if dst is unaligned. */ + _bbsi.l a2, 0, .Ldst1mod2 + _bbsi.l a2, 1, .Ldst2mod4 +.Ldstaligned: + + /* Get number of loop iterations with 16B per iteration. */ + srli a7, a4, 4 + + /* Destination is word-aligned. */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a6, a7, 4 + add a6, a6, a5 /* a6 = end of last 16B chunk */ +#endif + /* Set 16 bytes per iteration. */ +1: s32i a3, a5, 0 + s32i a3, a5, 4 + s32i a3, a5, 8 + s32i a3, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a5, a6, 1b +#endif + + /* Set any leftover pieces smaller than 16B. */ +2: bbci.l a4, 3, 3f + + /* Set 8 bytes. */ + s32i a3, a5, 0 + s32i a3, a5, 4 + addi a5, a5, 8 + +3: bbci.l a4, 2, 4f + + /* Set 4 bytes. */ + s32i a3, a5, 0 + addi a5, a5, 4 + +4: bbci.l a4, 1, 5f + + /* Set 2 bytes. */ + s16i a3, a5, 0 + addi a5, a5, 2 + +5: bbci.l a4, 0, 6f + + /* Set 1 byte. */ + s8i a3, a5, 0 +6: retw + +libc_hidden_def (memset) diff --git a/libc/string/xtensa/strcmp.S b/libc/string/xtensa/strcmp.S new file mode 100644 index 0000000..ac058a2 --- /dev/null +++ b/libc/string/xtensa/strcmp.S @@ -0,0 +1,314 @@ +/* Optimized strcmp for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + +#define MASK4 0x40404040 + + .literal .Lmask0, MASK0 + .literal .Lmask1, MASK1 + .literal .Lmask2, MASK2 + .literal .Lmask3, MASK3 + .literal .Lmask4, MASK4 + + .text +ENTRY (strcmp) + /* a2 = s1, a3 = s2 */ + + l8ui a8, a2, 0 /* byte 0 from s1 */ + l8ui a9, a3, 0 /* byte 0 from s2 */ + movi a10, 3 /* mask */ + bne a8, a9, .Lretdiff + + or a11, a2, a3 + bnone a11, a10, .Laligned + + xor a11, a2, a3 /* compare low two bits of s1 and s2 */ + bany a11, a10, .Lunaligned /* if they have different alignment */ + + /* s1/s2 are not word-aligned. */ + addi a2, a2, 1 /* advance s1 */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + bnone a2, a10, .Laligned /* if s1/s2 now aligned */ + l8ui a8, a2, 0 /* byte 1 from s1 */ + l8ui a9, a3, 0 /* byte 1 from s2 */ + addi a2, a2, 1 /* advance s1 */ + bne a8, a9, .Lretdiff /* if different, return difference */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + bnone a2, a10, .Laligned /* if s1/s2 now aligned */ + l8ui a8, a2, 0 /* byte 2 from s1 */ + l8ui a9, a3, 0 /* byte 2 from s2 */ + addi a2, a2, 1 /* advance s1 */ + bne a8, a9, .Lretdiff /* if different, return difference */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + j .Laligned + +/* s1 and s2 have different alignment. + + If the zero-overhead loop option is available, use an (almost) + infinite zero-overhead loop with conditional exits so we only pay + for taken branches when exiting the loop. + + Note: It is important for this unaligned case to come before the + code for aligned strings, because otherwise some of the branches + above cannot reach and have to be transformed to branches around + jumps. The unaligned code is smaller and the branches can reach + over it. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Lunaligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lretdiff /* loop forever (almost anyway) */ +#endif +.Lnextbyte: + l8ui a8, a2, 0 + l8ui a9, a3, 0 + addi a2, a2, 1 + bne a8, a9, .Lretdiff + addi a3, a3, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, .Lretdiff +#else + bnez a8, .Lnextbyte +#endif +.Lretdiff: + sub a2, a8, a9 + retw + +/* s1 is word-aligned; s2 is word-aligned. + + If the zero-overhead loop option is available, use an (almost) + infinite zero-overhead loop with conditional exits so we only pay + for taken branches when exiting the loop. */ + +/* New algorithm, relying on the fact that all normal ASCII is between + 32 and 127. + + Rather than check all bytes for zero: + Take one word (4 bytes). Call it w1. + Shift w1 left by one into w1'. + Or w1 and w1'. For all normal ASCII bit 6 will be 1; for zero it won't. + Check that all 4 bit 6's (one for each byte) are one: + If they are, we are definitely not done. + If they are not, we are probably done, but need to check for zero. */ + + .align 4 +#if XCHAL_HAVE_LOOPS +.Laligned: + .begin no-transform + l32r a4, .Lmask0 /* mask for byte 0 */ + l32r a7, .Lmask4 + /* Loop forever. (a4 is more than than the maximum number + of iterations) */ + loop a4, .Laligned_done + + /* First unrolled loop body. */ + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + bnall a9, a7, .Lprobeq + + /* Second unrolled loop body. */ + l32i a8, a2, 4 /* get word from s1+4 */ + l32i a9, a3, 4 /* get word from s2+4 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + bnall a9, a7, .Lprobeq2 + + addi a2, a2, 8 /* advance s1 pointer */ + addi a3, a3, 8 /* advance s2 pointer */ +.Laligned_done: + or a1, a1, a1 /* nop */ + +.Lprobeq2: + /* Adjust pointers to account for the loop unrolling. */ + addi a2, a2, 4 + addi a3, a3, 4 + +#else /* !XCHAL_HAVE_LOOPS */ + +.Laligned: + movi a4, MASK0 /* mask for byte 0 */ + movi a7, MASK4 + j .Lfirstword +.Lnextword: + addi a2, a2, 4 /* advance s1 pointer */ + addi a3, a3, 4 /* advance s2 pointer */ +.Lfirstword: + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + ball a9, a7, .Lnextword +#endif /* !XCHAL_HAVE_LOOPS */ + + /* align (0 mod 4) */ +.Lprobeq: + /* Words are probably equal, but check for sure. + If not, loop over the rest of string using normal algorithm. */ + + bnone a8, a4, .Leq /* if byte 0 is zero */ + l32r a5, .Lmask1 /* mask for byte 1 */ + l32r a6, .Lmask2 /* mask for byte 2 */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + l32r a7, .Lmask3 /* mask for byte 3 */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bnone a8, a7, .Leq /* if byte 3 is zero */ + addi.n a2, a2, 4 /* advance s1 pointer */ + addi.n a3, a3, 4 /* advance s2 pointer */ +#if XCHAL_HAVE_LOOPS + + /* align (1 mod 4) */ + loop a4, .Leq /* loop forever (a4 is bigger than max iters) */ + .end no-transform + + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + addi a2, a2, 4 /* advance s1 pointer */ + bne a8, a9, .Lwne + bnone a8, a4, .Leq /* if byte 0 is zero */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bnone a8, a7, .Leq /* if byte 3 is zero */ + addi a3, a3, 4 /* advance s2 pointer */ + +#else /* !XCHAL_HAVE_LOOPS */ + + j .Lfirstword2 +.Lnextword2: + addi a3, a3, 4 /* advance s2 pointer */ +.Lfirstword2: + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + addi a2, a2, 4 /* advance s1 pointer */ + bne a8, a9, .Lwne + bnone a8, a4, .Leq /* if byte 0 is zero */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bany a8, a7, .Lnextword2 /* if byte 3 is zero */ +#endif /* !XCHAL_HAVE_LOOPS */ + + /* Words are equal; some byte is zero. */ +.Leq: movi a2, 0 /* return equal */ + retw + +.Lwne2: /* Words are not equal. On big-endian processors, if none of the + bytes are zero, the return value can be determined by a simple + comparison. */ +#ifdef __XTENSA_EB__ + or a10, a8, a5 + bnall a10, a7, .Lsomezero + bgeu a8, a9, .Lposreturn + movi a2, -1 + retw +.Lposreturn: + movi a2, 1 + retw +.Lsomezero: /* There is probably some zero byte. */ +#endif /* __XTENSA_EB__ */ +.Lwne: /* Words are not equal. */ + xor a2, a8, a9 /* get word with nonzero in byte that differs */ + bany a2, a4, .Ldiff0 /* if byte 0 differs */ + movi a5, MASK1 /* mask for byte 1 */ + bnone a8, a4, .Leq /* if byte 0 is zero */ + bany a2, a5, .Ldiff1 /* if byte 1 differs */ + movi a6, MASK2 /* mask for byte 2 */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bany a2, a6, .Ldiff2 /* if byte 2 differs */ + bnone a8, a6, .Leq /* if byte 2 is zero */ +#ifdef __XTENSA_EB__ +.Ldiff3: +.Ldiff2: +.Ldiff1: + /* Byte 0 is equal (at least) and there is a difference before a zero + byte. Just subtract words to get the return value. + The high order equal bytes cancel, leaving room for the sign. */ + sub a2, a8, a9 + retw + +.Ldiff0: + /* Need to make room for the sign, so can't subtract whole words. */ + extui a10, a8, 24, 8 + extui a11, a9, 24, 8 + sub a2, a10, a11 + retw + +#else /* !__XTENSA_EB__ */ + /* Little-endian is a little more difficult because can't subtract + whole words. */ +.Ldiff3: + /* Bytes 0-2 are equal; byte 3 is different. + For little-endian need to have a sign bit for the difference. */ + extui a10, a8, 24, 8 + extui a11, a9, 24, 8 + sub a2, a10, a11 + retw + +.Ldiff0: + /* Byte 0 is different. */ + extui a10, a8, 0, 8 + extui a11, a9, 0, 8 + sub a2, a10, a11 + retw + +.Ldiff1: + /* Byte 0 is equal; byte 1 is different. */ + extui a10, a8, 8, 8 + extui a11, a9, 8, 8 + sub a2, a10, a11 + retw + +.Ldiff2: + /* Bytes 0-1 are equal; byte 2 is different. */ + extui a10, a8, 16, 8 + extui a11, a9, 16, 8 + sub a2, a10, a11 + retw + +#endif /* !__XTENSA_EB */ + +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias (strcmp, strcoll) +libc_hidden_def (strcoll) +#endif diff --git a/libc/string/xtensa/strcpy.S b/libc/string/xtensa/strcpy.S new file mode 100644 index 0000000..dc0a151 --- /dev/null +++ b/libc/string/xtensa/strcpy.S @@ -0,0 +1,150 @@ +/* Optimized strcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + + .text +ENTRY (strcpy) + /* a2 = dst, a3 = src */ + + mov a10, a2 /* leave dst in return value register */ + movi a4, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a3, 0, .Lsrc1mod2 + bbsi.l a3, 1, .Lsrc2mod4 +.Lsrcaligned: + + /* Check if the destination is aligned. */ + movi a8, 3 + bnone a10, a8, .Laligned + + j .Ldstunaligned + +.Lsrc1mod2: /* src address is odd */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a3, a3, 1 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a8, 1f /* if byte 0 is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bbci.l a3, 1, .Lsrcaligned /* if src is now word-aligned */ + +.Lsrc2mod4: /* src address is 2 mod 4 */ + l8ui a8, a3, 0 /* get byte 0 */ + /* 1-cycle interlock */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a8, 1f /* if byte 0 is zero */ + l8ui a8, a3, 1 /* get byte 0 */ + addi a3, a3, 2 /* advance src pointer */ + s8i a8, a10, 1 /* store byte 0 */ + addi a10, a10, 2 /* advance dst pointer */ + bnez a8, .Lsrcaligned +1: retw + + +/* dst is word-aligned; src is word-aligned. */ + + .align 4 +#if XCHAL_HAVE_LOOPS + /* (2 mod 4) alignment for loop instruction */ +.Laligned: + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lz3 /* loop forever (almost anyway) */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + bnone a8, a7, .Lz3 /* if byte 3 is zero */ + addi a10, a10, 4 /* advance dst pointer */ + +#else /* !XCHAL_HAVE_LOOPS */ + +1: addi a10, a10, 4 /* advance dst pointer */ +.Laligned: + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + bany a8, a7, 1b /* if byte 3 is zero */ +#endif /* !XCHAL_HAVE_LOOPS */ + +.Lz3: /* Byte 3 is zero. */ + retw + +.Lz0: /* Byte 0 is zero. */ +#ifdef __XTENSA_EB__ + movi a8, 0 +#endif + s8i a8, a10, 0 + retw + +.Lz1: /* Byte 1 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + retw + +.Lz2: /* Byte 2 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + movi a8, 0 + s8i a8, a10, 2 + retw + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Ldstunaligned: + +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 2f /* loop forever (almost anyway) */ +#endif +1: l8ui a8, a3, 0 + addi a3, a3, 1 + s8i a8, a10, 0 + addi a10, a10, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, 2f +#else + bnez a8, 1b +#endif +2: retw + +libc_hidden_def (strcpy) diff --git a/libc/string/xtensa/strlen.S b/libc/string/xtensa/strlen.S new file mode 100644 index 0000000..9ee4995 --- /dev/null +++ b/libc/string/xtensa/strlen.S @@ -0,0 +1,104 @@ +/* Optimized strlen for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + + .text +ENTRY (strlen) + /* a2 = s */ + + addi a3, a2, -4 /* because we overincrement at the end */ + movi a4, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a2, 0, .L1mod2 + bbsi.l a2, 1, .L2mod4 + j .Laligned + +.L1mod2: /* address is odd */ + l8ui a8, a3, 4 /* get byte 0 */ + addi a3, a3, 1 /* advance string pointer */ + beqz a8, .Lz3 /* if byte 0 is zero */ + bbci.l a3, 1, .Laligned /* if string pointer is now word-aligned */ + +.L2mod4: /* address is 2 mod 4 */ + addi a3, a3, 2 /* advance ptr for aligned access */ + l32i a8, a3, 0 /* get word with first two bytes of string */ + bnone a8, a6, .Lz2 /* if byte 2 (of word, not string) is zero */ + bany a8, a7, .Laligned /* if byte 3 (of word, not string) is nonzero */ + + /* Byte 3 is zero. */ + addi a3, a3, 3 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + + +/* String is word-aligned. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Laligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lz3 /* loop forever (almost anyway) */ +#endif +1: l32i a8, a3, 4 /* get next word of string */ + addi a3, a3, 4 /* advance string pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ +#if XCHAL_HAVE_LOOPS + bnone a8, a7, .Lz3 /* if byte 3 is zero */ +#else + bany a8, a7, 1b /* repeat if byte 3 is non-zero */ +#endif + +.Lz3: /* Byte 3 is zero. */ + addi a3, a3, 3 /* point to zero byte */ + /* Fall through.... */ + +.Lz0: /* Byte 0 is zero. */ + sub a2, a3, a2 /* subtract to get length */ + retw + +.Lz1: /* Byte 1 is zero. */ + addi a3, a3, 1 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + +.Lz2: /* Byte 2 is zero. */ + addi a3, a3, 2 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + +libc_hidden_def (strlen) diff --git a/libc/string/xtensa/strncpy.S b/libc/string/xtensa/strncpy.S new file mode 100644 index 0000000..fe3ec89 --- /dev/null +++ b/libc/string/xtensa/strncpy.S @@ -0,0 +1,241 @@ +/* Optimized strcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + + .text + .align 4 + .literal_position +__strncpy_aux: + +.Lsrc1mod2: /* src address is odd */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a3, a3, 1 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + beqz a8, .Lfill /* if byte 0 is zero */ + bbci.l a3, 1, .Lsrcaligned /* if src is now word-aligned */ + +.Lsrc2mod4: /* src address is 2 mod 4 */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a4, a4, -1 /* decrement n */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + beqz a8, .Lfill /* if byte 0 is zero */ + l8ui a8, a3, 1 /* get byte 0 */ + addi a3, a3, 2 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bnez a8, .Lsrcaligned + j .Lfill + +.Lret: + retw + + +ENTRY (strncpy) + /* a2 = dst, a3 = src */ + + mov a10, a2 /* leave dst in return value register */ + beqz a4, .Lret /* if n is zero */ + + movi a11, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a3, 0, .Lsrc1mod2 + bbsi.l a3, 1, .Lsrc2mod4 +.Lsrcaligned: + + /* Check if the destination is aligned. */ + movi a8, 3 + bnone a10, a8, .Laligned + + j .Ldstunaligned + + +/* Fill the dst with zeros -- n is at least 1. */ + +.Lfill: + movi a9, 0 + bbsi.l a10, 0, .Lfill1mod2 + bbsi.l a10, 1, .Lfill2mod4 +.Lfillaligned: + blti a4, 4, .Lfillcleanup + + /* Loop filling complete words with zero. */ +#if XCHAL_HAVE_LOOPS + + srai a8, a4, 2 + loop a8, 1f + s32i a9, a10, 0 + addi a10, a10, 4 + +1: slli a8, a8, 2 + sub a4, a4, a8 + +#else /* !XCHAL_HAVE_LOOPS */ + +1: s32i a9, a10, 0 + addi a10, a10, 4 + addi a4, a4, -4 + bgei a4, 4, 1b + +#endif /* !XCHAL_HAVE_LOOPS */ + + beqz a4, 2f + +.Lfillcleanup: + /* Fill leftover (1 to 3) bytes with zero. */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + addi a10, a10, 1 + bnez a4, .Lfillcleanup + +2: retw + +.Lfill1mod2: /* dst address is odd */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bbci.l a10, 1, .Lfillaligned /* if dst is now word-aligned */ + +.Lfill2mod4: /* dst address is 2 mod 4 */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + s8i a9, a10, 1 /* store byte 1 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + addi a10, a10, 2 /* advance dst pointer */ + j .Lfillaligned + + +/* dst is word-aligned; src is word-aligned; n is at least 1. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Laligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 1f /* loop forever (almost anyway) */ + blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a11, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + addi a4, a4, -4 /* decrement n */ + addi a10, a10, 4 /* advance dst pointer */ + bnone a8, a7, .Lfill /* if byte 3 is zero */ +1: + +#else /* !XCHAL_HAVE_LOOPS */ + +1: blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a11, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + addi a4, a4, -4 /* decrement n */ + addi a10, a10, 4 /* advance dst pointer */ + bany a8, a7, 1b /* no zeroes */ +#endif /* !XCHAL_HAVE_LOOPS */ + + j .Lfill + +.Lz0: /* Byte 0 is zero. */ +#ifdef __XTENSA_EB__ + movi a8, 0 +#endif + s8i a8, a10, 0 + addi a4, a4, -1 /* decrement n */ + addi a10, a10, 1 /* advance dst pointer */ + j .Lfill + +.Lz1: /* Byte 1 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + addi a4, a4, -2 /* decrement n */ + addi a10, a10, 2 /* advance dst pointer */ + j .Lfill + +.Lz2: /* Byte 2 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + movi a8, 0 + s8i a8, a10, 2 + addi a4, a4, -3 /* decrement n */ + addi a10, a10, 3 /* advance dst pointer */ + j .Lfill + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Ldstunaligned: + +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 2f /* loop forever (almost anyway) */ +#endif +1: l8ui a8, a3, 0 + addi a3, a3, 1 + s8i a8, a10, 0 + addi a4, a4, -1 + beqz a4, 3f + addi a10, a10, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, 2f +#else + bnez a8, 1b +#endif +2: j .Lfill + +3: retw + +libc_hidden_def (strncpy) diff --git a/libc/sysdeps/Makefile b/libc/sysdeps/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/sysdeps/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/Makefile.in b/libc/sysdeps/Makefile.in new file mode 100644 index 0000000..686cb72 --- /dev/null +++ b/libc/sysdeps/Makefile.in @@ -0,0 +1,8 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)libc/sysdeps/linux/Makefile.in diff --git a/libc/sysdeps/README b/libc/sysdeps/README new file mode 100644 index 0000000..6448433 --- /dev/null +++ b/libc/sysdeps/README @@ -0,0 +1,6 @@ +This directory level abstracts out the UN*X-like Operating System dependent +features of uClibc for all UN*X-like operating systems. If you wanted to port +uClibc to some other UN*X-like OS, this is the place to add that support. + +If you want to port uClibc to support some non-UN*X-like Operating System, you +should probably stop using crack. It is bad for you. ;-) diff --git a/libc/sysdeps/linux/Makefile b/libc/sysdeps/linux/Makefile new file mode 100644 index 0000000..4a8f4a0 --- /dev/null +++ b/libc/sysdeps/linux/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/Makefile.commonarch b/libc/sysdeps/linux/Makefile.commonarch new file mode 100644 index 0000000..99d8c85 --- /dev/null +++ b/libc/sysdeps/linux/Makefile.commonarch @@ -0,0 +1,42 @@ +# Makefile template to be included by sysdeps/linux//Makefile.arch +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ARCH_DIR := $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) +ARCH_OUT := $(top_builddir)libc/sysdeps/linux/$(TARGET_ARCH) + +ARCH_CSRC := $(patsubst %.c,$(ARCH_DIR)/%.c,$(CSRC)) +ARCH_COBJ := $(patsubst %.c,$(ARCH_OUT)/%.o,$(CSRC)) +ARCH_SSRC := $(patsubst %.s,$(ARCH_DIR)/%.s,$(patsubst %.S,$(ARCH_DIR)/%.S,$(SSRC))) +ARCH_SOBJ := $(patsubst %.s,$(ARCH_OUT)/%.o,$(patsubst %.S,$(ARCH_OUT)/%.o,$(SSRC))) + +ARCH_OBJS := $(ARCH_COBJ) $(ARCH_SOBJ) + +crt-y := FORCE +libc-y += $(ARCH_OBJS) +libc-nomulti-y += $(ARCH_SOBJ) +objclean-y += arch_objclean + +CFLAGS-crti.S+=$(PICFLAG) +CFLAGS-crtn.S+=$(PICFLAG) + +arch_objclean: + $(do_rm) $(addprefix $(ARCH_OUT)/*., o os oS) $(CTOR_TARGETS) $(CRTS) + +ifneq ($(ARCH_HEADERS),) + +ARCH_HEADERS_IN := $(patsubst %,../libc/sysdeps/linux/$(TARGET_ARCH)/%,$(ARCH_HEADERS)) +ARCH_HEADERS_OUT := $(patsubst %,$(top_builddir)include/%,$(ARCH_HEADERS)) + +$(ARCH_HEADERS_OUT): + $(do_ln) -fs ../libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) $@ + +headers-y += $(ARCH_HEADERS_OUT) +headers_clean-y += arch_headers_clean +arch_headers_clean: + $(RM) $(ARCH_HEADERS_OUT) + +endif diff --git a/libc/sysdeps/linux/Makefile.in b/libc/sysdeps/linux/Makefile.in new file mode 100644 index 0000000..d2a980c --- /dev/null +++ b/libc/sysdeps/linux/Makefile.in @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# order is relevant +-include $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/Makefile.arch +include $(top_srcdir)libc/sysdeps/linux/common/Makefile.in diff --git a/libc/sysdeps/linux/README b/libc/sysdeps/linux/README new file mode 100644 index 0000000..76944f9 --- /dev/null +++ b/libc/sysdeps/linux/README @@ -0,0 +1,7 @@ +This directory level abstracts out the Linux Operating System dependent +features of uClibc for supported Linux architectures/CPUs. If you wanted to +port uClibc to some new Linux architecture (arm, mips, etc), this is the place +to add that support. + +All stuff that is not at all dependent on a particular Linux architecture +goes in the 'common' directory. diff --git a/libc/sysdeps/linux/alpha/Makefile b/libc/sysdeps/linux/alpha/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/alpha/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/alpha/Makefile.arch b/libc/sysdeps/linux/alpha/Makefile.arch new file mode 100644 index 0000000..5097008 --- /dev/null +++ b/libc/sysdeps/linux/alpha/Makefile.arch @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c sigprocmask.c + +SSRC := \ + __longjmp.S brk.S bsd-_setjmp.S bsd-setjmp.S clone.S \ + divl.S divq.S pipe.S reml.S remq.S __syscall_rt_sigaction.S setjmp.S \ + syscall.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/alpha/__longjmp.S b/libc/sysdeps/linux/alpha/__longjmp.S new file mode 100644 index 0000000..910ec07 --- /dev/null +++ b/libc/sysdeps/linux/alpha/__longjmp.S @@ -0,0 +1,57 @@ +/* Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _SETJMP_H +#define __ASSEMBLY__ +#include + +#define a0 $16 + +.globl __longjmp; +.align 3; +.ent __longjmp , 0; + +__longjmp: + .frame $30 , 0, $26 + .prologue 0 + + mov $17, $0 + ldq $9, JB_S0*8(a0) + ldq $10, JB_S1*8(a0) + ldq $11, JB_S2*8(a0) + ldq $12, JB_S3*8(a0) + ldq $13, JB_S4*8(a0) + ldq $14, JB_S5*8(a0) + ldq $26, JB_PC*8(a0) + ldq $15, JB_FP*8(a0) + ldq $1, JB_SP*8(a0) + ldt $f2, JB_F2*8(a0) + ldt $f3, JB_F3*8(a0) + ldt $f4, JB_F4*8(a0) + ldt $f5, JB_F5*8(a0) + ldt $f6, JB_F6*8(a0) + ldt $f7, JB_F7*8(a0) + ldt $f8, JB_F8*8(a0) + ldt $f9, JB_F9*8(a0) + cmoveq $0, 1, $0 + mov $1, $30 + ret + +.end __longjmp +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/alpha/__syscall_error.c b/libc/sysdeps/linux/alpha/__syscall_error.c new file mode 100644 index 0000000..7c081f3 --- /dev/null +++ b/libc/sysdeps/linux/alpha/__syscall_error.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* This routine is jumped to by all the syscall handlers, to stash + an error number into errno. */ +int attribute_hidden __syscall_error (void) +{ + register int err_no __asm__("$0"); + __set_errno (err_no); + return -1; +} diff --git a/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S b/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S new file mode 100644 index 0000000..f7e9e44 --- /dev/null +++ b/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S @@ -0,0 +1,81 @@ +/* Copyright (C) 1998, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1998 + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* On Alpha we desparately want to avoid having to issue an imb. Ordinarily + the kernel would have to issue one after setting up the signal return + stack, but the Linux rt_sigaction syscall is prepared to accept a pointer + to the sigreturn syscall, instead of inlining it on the stack. + + This just about halves signal delivery time. */ + + .text + +.globl __syscall_rt_sigaction +.align 4 +.ent __syscall_rt_sigaction, 0 +__syscall_rt_sigaction: + .frame sp,0,ra,0 + ldgp gp,0(pv) + .prologue 1 + + beq a1, 0f + ldl t0, 8(a1) # sa_flags + + /* The unwinder will subtract one from the return address when + attempting to find the call instruction that led us here. + Since we didn't get here via a normal call, if we do nothing + we would pick up the wrong symbol and the wrong FDE. Account + for this by adding a nop to the start of the function and + then skipping it here by adding 4. */ + ldah a4, __syscall_sigreturn+4(gp) !gprelhigh + ldah t1, __syscall_rt_sigreturn+4(gp) !gprelhigh + lda a4, __syscall_sigreturn+4(a4) !gprellow + lda t1, __syscall_rt_sigreturn+4(t1) !gprellow + and t0, 0x40, t0 # SA_SIGINFO + cmovne t0, t1, a4 + +0: ldi v0, __NR_rt_sigaction + callsys + bne a3, $error + ret + +$error: + jmp zero,__syscall_error + +.end __syscall_rt_sigaction + +__syscall_sigreturn: + nop + mov sp, a0 + ldi v0, __NR_sigreturn + callsys + .size __syscall_sigreturn, .-__syscall_sigreturn + .type __syscall_sigreturn, @function + +__syscall_rt_sigreturn: + nop + mov sp,a0 + ldi v0,__NR_rt_sigreturn + callsys + .size __syscall_rt_sigreturn, .-__syscall_rt_sigreturn + .type __syscall_rt_sigreturn, @function diff --git a/libc/sysdeps/linux/alpha/bits/atomic.h b/libc/sysdeps/linux/alpha/bits/atomic.h new file mode 100644 index 0000000..5ad4c54 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/atomic.h @@ -0,0 +1,369 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifdef UP +# define __MB /* nothing */ +#else +# define __MB " mb\n" +#endif + + +/* Compare and exchange. For all of the "xxx" routines, we expect a + "__prev" and a "__cmp" variable to be provided by the enclosing scope, + in which values are returned. */ + +#define __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2) \ +({ \ + unsigned long __tmp, __snew, __addr64; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr8],7,%[__addr64]\n" \ + " insbl %[__new],%[__addr8],%[__snew]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extbl %[__tmp],%[__addr8],%[__prev]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mskbl %[__tmp],%[__addr8],%[__tmp]\n" \ + " or %[__snew],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__snew] "=&r" (__snew), \ + [__tmp] "=&r" (__tmp), \ + [__cmp] "=&r" (__cmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr8] "r" (mem), \ + [__old] "Ir" ((uint64_t)(uint8_t)(uint64_t)(old)), \ + [__new] "r" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2) \ +({ \ + unsigned long __tmp, __snew, __addr64; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr16],7,%[__addr64]\n" \ + " inswl %[__new],%[__addr16],%[__snew]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extwl %[__tmp],%[__addr16],%[__prev]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mskwl %[__tmp],%[__addr16],%[__tmp]\n" \ + " or %[__snew],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__snew] "=&r" (__snew), \ + [__tmp] "=&r" (__tmp), \ + [__cmp] "=&r" (__cmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr16] "r" (mem), \ + [__old] "Ir" ((uint64_t)(uint16_t)(uint64_t)(old)), \ + [__new] "r" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2) \ +({ \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__prev],%[__mem]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mov %[__new],%[__cmp]\n" \ + " stl_c %[__cmp],%[__mem]\n" \ + " beq %[__cmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__cmp] "=&r" (__cmp) \ + : [__mem] "m" (*(mem)), \ + [__old] "Ir" ((uint64_t)(atomic32_t)(uint64_t)(old)), \ + [__new] "Ir" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2) \ +({ \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__prev],%[__mem]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mov %[__new],%[__cmp]\n" \ + " stq_c %[__cmp],%[__mem]\n" \ + " beq %[__cmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__cmp] "=&r" (__cmp) \ + : [__mem] "m" (*(mem)), \ + [__old] "Ir" ((uint64_t)(old)), \ + [__new] "Ir" (new) \ + : "memory"); \ +}) + +/* For all "bool" routines, we return FALSE if exchange succesful. */ + +#define __arch_compare_and_exchange_bool_8_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_16_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_32_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_64_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +/* For all "val" routines, return the old value whether exchange + successful or not. */ + +#define __arch_compare_and_exchange_val_8_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_16_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_32_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_64_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +/* Compare and exchange with "acquire" semantics, ie barrier after. */ + +#define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, "", __MB) + +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, "", __MB) + +/* Compare and exchange with "release" semantics, ie barrier before. */ + +#define atomic_compare_and_exchange_bool_rel(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, __MB, "") + +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, __MB, "") + + +/* Atomically store value and return the previous value. */ + +#define __arch_exchange_8_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp, __addr64, __sval; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr8],7,%[__addr64]\n" \ + " insbl %[__value],%[__addr8],%[__sval]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extbl %[__tmp],%[__addr8],%[__ret]\n" \ + " mskbl %[__tmp],%[__addr8],%[__tmp]\n" \ + " or %[__sval],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__sval] "=&r" (__sval), \ + [__tmp] "=&r" (__tmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr8] "r" (mem), \ + [__value] "r" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_16_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp, __addr64, __sval; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr16],7,%[__addr64]\n" \ + " inswl %[__value],%[__addr16],%[__sval]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extwl %[__tmp],%[__addr16],%[__ret]\n" \ + " mskwl %[__tmp],%[__addr16],%[__tmp]\n" \ + " or %[__sval],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__sval] "=&r" (__sval), \ + [__tmp] "=&r" (__tmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr16] "r" (mem), \ + [__value] "r" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_32_int(mem, value, mb1, mb2) \ +({ \ + signed int __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__ret],%[__mem]\n" \ + " mov %[__val],%[__tmp]\n" \ + " stl_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_64_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__ret],%[__mem]\n" \ + " mov %[__val],%[__tmp]\n" \ + " stq_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" (value) \ + : "memory"); \ + __ret; }) + +#define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, "", __MB) + +#define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __MB, "") + + +/* Atomically add value and return the previous (unincremented) value. */ + +#define __arch_exchange_and_add_8_int(mem, value, mb1, mb2) \ + ({ __builtin_trap (); 0; }) + +#define __arch_exchange_and_add_16_int(mem, value, mb1, mb2) \ + ({ __builtin_trap (); 0; }) + +#define __arch_exchange_and_add_32_int(mem, value, mb1, mb2) \ +({ \ + signed int __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__ret],%[__mem]\n" \ + " addl %[__ret],%[__val],%[__tmp]\n" \ + " stl_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" ((signed int)(value)) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_and_add_64_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__ret],%[__mem]\n" \ + " addq %[__ret],%[__val],%[__tmp]\n" \ + " stq_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" ((unsigned long)(value)) \ + : "memory"); \ + __ret; }) + +/* ??? Barrier semantics for atomic_exchange_and_add appear to be + undefined. Use full barrier for now, as that's safe. */ +#define atomic_exchange_and_add(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, __MB, __MB) + + +/* ??? Blah, I'm lazy. Implement these later. Can do better than the + compare-and-exchange loop provided by generic code. + +#define atomic_decrement_if_positive(mem) +#define atomic_bit_test_set(mem, bit) + +*/ + +#ifndef UP +# define atomic_full_barrier() __asm__ ("mb" : : : "memory"); +# define atomic_read_barrier() __asm__ ("mb" : : : "memory"); +# define atomic_write_barrier() __asm__ ("wmb" : : : "memory"); +#endif diff --git a/libc/sysdeps/linux/alpha/bits/dirent.h b/libc/sysdeps/linux/alpha/bits/dirent.h new file mode 100644 index 0000000..6ed7478 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/dirent.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_DIRENT_H +#define _BITS_DIRENT_H 1 + +struct dirent + { +#ifdef __USE_FILE_OFFSET64 + __ino64_t d_ino; +#else + __ino_t d_ino; + int __pad; +#endif + __off_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +/* Note dirent64 is the same as dirent. */ +struct dirent64 + { + __ino64_t d_ino; + __off64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE + +#endif /* bits/dirent.h */ diff --git a/libc/sysdeps/linux/alpha/bits/elfclass.h b/libc/sysdeps/linux/alpha/bits/elfclass.h new file mode 100644 index 0000000..e5aa4a0 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/elfclass.h @@ -0,0 +1,14 @@ +/* This file specifies the native word size of the machine, which indicates + the ELF file class used for executables and shared objects on this + machine. */ + +#ifndef _LINK_H +# error "Never use directly; include instead." +#endif + +#include + +#define __ELF_NATIVE_CLASS __WORDSIZE + +/* Linux/Alpha is exceptional as it has .hash section with 64 bit entries. */ +typedef uint64_t Elf_Symndx; diff --git a/libc/sysdeps/linux/alpha/bits/endian.h b/libc/sysdeps/linux/alpha/bits/endian.h new file mode 100644 index 0000000..8a16e14 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/endian.h @@ -0,0 +1,7 @@ +/* Alpha is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/alpha/bits/fcntl.h b/libc/sysdeps/linux/alpha/bits/fcntl.h new file mode 100644 index 0000000..85e0fca --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/fcntl.h @@ -0,0 +1,233 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995-2000,2004,2005,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 01000 /* not fcntl */ +#define O_TRUNC 02000 /* not fcntl */ +#define O_EXCL 04000 /* not fcntl */ +#define O_NOCTTY 010000 /* not fcntl */ + +#define O_NONBLOCK 00004 +#define O_APPEND 00010 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 040000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 /* fcntl, for BSD compatibility */ + +#ifdef __USE_GNU +# define O_DIRECTORY 0100000 /* Must be a directory. */ +# define O_NOFOLLOW 0200000 /* Do not follow links. */ +# define O_DIRECT 02000000 /* Direct disk access. */ +# define O_NOATIME 04000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 010000000 /* Set close_on_exec. */ +# endif +#endif + +#ifdef __USE_LARGEFILE64 +/* Not necessary, files are always with 64bit off_t. */ +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 7 /* Get record locking info. */ +#define F_SETLK 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW 9 /* Set record locking info (blocking). */ +#define F_GETLK64 F_GETLK /* Get record locking info. */ +#define F_SETLK64 F_SETLK /* Set record locking info (non-blocking). */ +#define F_SETLKW64 F_SETLKW /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 5 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 6 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* for F_[GET|SET]FD */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf() */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 8 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 16 /* or 3 */ +#define F_SHLCK 32 /* or 4 */ + +/* Operations for bsd flock(), also used by the kernel implementation */ +#ifdef __USE_BSD +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +/* We don't need to support __USE_FILE_OFFSET64. */ +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/alpha/bits/fenv.h b/libc/sysdeps/linux/alpha/bits/fenv.h new file mode 100644 index 0000000..a9e89b4 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/fenv.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define the bits representing the exception. + + Note that these are the bit positions as defined by the OSF/1 + ieee_{get,set}_control_word interface and not by the hardware fpcr. + + See the Alpha Architecture Handbook section 4.7.7.3 for details, + but in summary, trap shadows mean the hardware register can acquire + extra exception bits so for proper IEEE support the tracking has to + be done in software -- in this case with kernel support. + + As to why the system call interface isn't in the same format as + the hardware register, only those crazy folks at DEC can tell you. */ + +enum + { +#ifdef __USE_GNU + FE_DENORMAL = 1UL << 22, +#define FE_DENORMAL FE_DENORMAL +#endif + + FE_INEXACT = 1UL << 21, +#define FE_INEXACT FE_INEXACT + + FE_UNDERFLOW = 1UL << 20, +#define FE_UNDERFLOW FE_UNDERFLOW + + FE_OVERFLOW = 1UL << 19, +#define FE_OVERFLOW FE_OVERFLOW + + FE_DIVBYZERO = 1UL << 18, +#define FE_DIVBYZERO FE_DIVBYZERO + + FE_INVALID = 1UL << 17, +#define FE_INVALID FE_INVALID + + FE_ALL_EXCEPT = 0x3f << 17 +#define FE_ALL_EXCEPT FE_ALL_EXCEPT + }; + +/* Alpha chips support all four defined rouding modes. + + Note that code must be compiled to use dynamic rounding (/d) instructions + to see these changes. For gcc this is -mfp-rounding-mode=d; for DEC cc + this is -fprm d. The default for both is static rounding to nearest. + + These are shifted down 58 bits from the hardware fpcr because the + functions are declared to take integers. */ + +enum + { + FE_TOWARDZERO = 0, +#define FE_TOWARDZERO FE_TOWARDZERO + + FE_DOWNWARD = 1, +#define FE_DOWNWARD FE_DOWNWARD + + FE_TONEAREST = 2, +#define FE_TONEAREST FE_TONEAREST + + FE_UPWARD = 3, +#define FE_UPWARD FE_UPWARD + }; + +#ifdef __USE_GNU +/* On later hardware, and later kernels for earlier hardware, we can forcibly + underflow denormal inputs and outputs. This can speed up certain programs + significantly, usually without affecting accuracy. */ +enum + { + FE_MAP_DMZ = 1UL << 12, /* Map denorm inputs to zero */ +#define FE_MAP_DMZ FE_MAP_DMZ + + FE_MAP_UMZ = 1UL << 13, /* Map underflowed outputs to zero */ +#define FE_MAP_UMZ FE_MAP_UMZ + }; +#endif + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. Note that due to + architecture-specified page mappings, no user-space pointer will ever + have its two high bits set. Co-opt one. */ +#define FE_DFL_ENV ((__const fenv_t *) 0x8800000000000000UL) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) 0x880000000000003eUL) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. In this case, mapping denormals to zero. */ +# define FE_NONIEEE_ENV ((__const fenv_t *) 0x8800000000003000UL) +#endif + +/* The system calls to talk to the kernel's FP code. */ +extern unsigned long int __ieee_get_fp_control (void) __THROW; +extern void __ieee_set_fp_control (unsigned long int __value) __THROW; diff --git a/libc/sysdeps/linux/alpha/bits/ioctls.h b/libc/sysdeps/linux/alpha/bits/ioctls.h new file mode 100644 index 0000000..c525046 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/ioctls.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('t', 19, char[44]) +#define TCSETS _IOW ('t', 20, char[44]) +#define TCSETSW _IOW ('t', 21, char[44]) +#define TCSETSF _IOW ('t', 22, char[44]) + +#include diff --git a/libc/sysdeps/linux/alpha/bits/ipc.h b/libc/sysdeps/linux/alpha/bits/ipc.h new file mode 100644 index 0000000..77f3c93 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/ipc.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned int uid; /* Owner's user ID. */ + unsigned int gid; /* Owner's group ID. */ + unsigned int cuid; /* Creator's user ID. */ + unsigned int cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h b/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h new file mode 100644 index 0000000..d111a5f --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h @@ -0,0 +1,23 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This is the sigaction struction from the Linux 2.1.20 kernel. */ + +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned int sa_flags; +}; + +/* This is the sigaction structure from the Linux 2.1.68 kernel. */ + +struct kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned int sa_flags; + sigset_t sa_mask; +}; + +extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, + struct kernel_sigaction *__unbounded, size_t) attribute_hidden; + +#endif diff --git a/libc/sysdeps/linux/alpha/bits/kernel_stat.h b/libc/sysdeps/linux/alpha/bits/kernel_stat.h new file mode 100644 index 0000000..649257b --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/kernel_stat.h @@ -0,0 +1,52 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +struct kernel_stat { + unsigned int st_dev; + unsigned int st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + long int st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; + unsigned int st_blksize; + int st_blocks; + unsigned int st_flags; + unsigned int st_gen; +}; + +struct kernel_stat64 { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_rdev; + long st_size; + unsigned long st_blocks; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_blksize; + unsigned int st_nlink; + unsigned int __pad0; + + unsigned long st_atime; + unsigned long st_atimensec; + unsigned long st_mtime; + unsigned long st_mtimensec; + unsigned long st_ctime; + unsigned long st_ctimensec; + long __unused[3]; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/alpha/bits/kernel_types.h b/libc/sysdeps/linux/alpha/bits/kernel_types.h new file mode 100644 index 0000000..d5574c9 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/kernel_types.h @@ -0,0 +1,41 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ALPHA_POSIX_TYPES_H +#define _ALPHA_POSIX_TYPES_H + +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned long __kernel_sigset_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* _ALPHA_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/alpha/bits/mathdef.h b/libc/sysdeps/linux/alpha/bits/mathdef.h new file mode 100644 index 0000000..cbfaf68 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/mathdef.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997,1998,1999,2000,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# ifdef __GNUC__ +# if __STDC__ == 1 + +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ +typedef float float_t; +typedef double double_t; + +# else + +/* For `gcc -traditional', `float' expressions are evaluated as `double'. */ +typedef double float_t; +typedef double double_t; + +# endif +# else + +/* Wild guess at types for float_t and double_t. */ +typedef double float_t; +typedef double double_t; + +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 && MATH_H */ + +#if defined _COMPLEX_H && !defined _COMPLEX_H_MATHDEF +# define _COMPLEX_H_MATHDEF 1 +# if defined(__GNUC__) && !__GNUC_PREREQ(3,4) + +/* Due to an ABI change, we need to remap the complex float symbols. */ +# define _Mdouble_ float +# define __MATHCALL(function, args) \ + __MATHDECL (_Complex float, function, args) +# define __MATHDECL(type, function, args) \ + __MATHDECL_1(type, function##f, args, __c1_##function##f); \ + __MATHDECL_1(type, __##function##f, args, __c1_##function##f) +# define __MATHDECL_1(type, function, args, alias) \ + extern type function args __asm__(#alias) __THROW + +# include + +# undef _Mdouble_ +# undef __MATHCALL +# undef __MATHDECL +# undef __MATHDECL_1 + +# endif /* GNUC before 3.4 */ +#endif /* COMPLEX_H */ diff --git a/libc/sysdeps/linux/alpha/bits/mathinline.h b/libc/sysdeps/linux/alpha/bits/mathinline.h new file mode 100644 index 0000000..3dd38e8 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/mathinline.h @@ -0,0 +1,183 @@ +/* Inline math functions for Alpha. + Copyright (C) 1996, 1997, 1999-2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + +#if defined __USE_ISOC99 && defined __GNUC__ && !__GNUC_PREREQ(3,0) +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# define isunordered(u, v) \ + (__extension__ \ + ({ double __r, __u = (u), __v = (v); \ + __asm__ ("cmptun/su %1,%2,%0\n\ttrapb" \ + : "=&f" (__r) : "f" (__u), "f"(__v)); \ + __r != 0; })) +#endif /* ISO C99 */ + +#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__ + +#if !__GNUC_PREREQ (4, 0) +# define __inline_copysign(NAME, TYPE) \ +__MATH_INLINE TYPE \ +__NTH (NAME (TYPE __x, TYPE __y)) \ +{ \ + TYPE __z; \ + __asm__ ("cpys %1, %2, %0" : "=f" (__z) : "f" (__y), "f" (__x)); \ + return __z; \ +} + +__inline_copysign (__copysignf, float) +__inline_copysign (copysignf, float) +__inline_copysign (__copysign, double) +__inline_copysign (copysign, double) + +# undef __inline_copysign +#endif + + +#if !__GNUC_PREREQ (2, 8) +# define __inline_fabs(NAME, TYPE) \ +__MATH_INLINE TYPE \ +__NTH (NAME (TYPE __x)) \ +{ \ + TYPE __z; \ + __asm__ ("cpys $f31, %1, %0" : "=f" (__z) : "f" (__x)); \ + return __z; \ +} + +__inline_fabs (__fabsf, float) +__inline_fabs (fabsf, float) +__inline_fabs (__fabs, double) +__inline_fabs (fabs, double) + +# undef __inline_fabs +#endif + + +/* Use the -inf rounding mode conversion instructions to implement + floor. We note when the exponent is large enough that the value + must be integral, as this avoids unpleasant integer overflows. */ + +__MATH_INLINE float +__NTH (__floorf (float __x)) +{ + /* Check not zero since floor(-0) == -0. */ + if (__x != 0 && fabsf (__x) < 16777216.0f) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float __tmp1, __tmp2; + + __asm__ ("cvtst/s %3,%2\n\t" +#ifdef _IEEE_FP_INEXACT + "cvttq/svim %2,%1\n\t" +#else + "cvttq/svm %2,%1\n\t" +#endif + "cvtqt/m %1,%0\n\t" + : "=f"(__x), "=&f"(__tmp1), "=&f"(__tmp2) + : "f"(__x)); + } + return __x; +} + +__MATH_INLINE double +__NTH (__floor (double __x)) +{ + if (__x != 0 && fabs (__x) < 9007199254740992.0) /* 1 << DBL_MANT_DIG */ + { + double __tmp1; + __asm__ ( +#ifdef _IEEE_FP_INEXACT + "cvttq/svim %2,%1\n\t" +#else + "cvttq/svm %2,%1\n\t" +#endif + "cvtqt/m %1,%0\n\t" + : "=f"(__x), "=&f"(__tmp1) + : "f"(__x)); + } + return __x; +} + +__MATH_INLINE float __NTH (floorf (float __x)) { return __floorf(__x); } +__MATH_INLINE double __NTH (floor (double __x)) { return __floor(__x); } + + +#ifdef __USE_ISOC99 + +__MATH_INLINE float +__NTH (__fdimf (float __x, float __y)) +{ + return __x <= __y ? 0.0f : __x - __y; +} + +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0.0f : __x - __y; +} + +__MATH_INLINE double +__NTH (__fdim (double __x, double __y)) +{ + return __x <= __y ? 0.0 : __x - __y; +} + +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0.0 : __x - __y; +} + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; long __i; } __u = { __d: __x }; + return __u.__i < 0; +} + +#endif /* C99 */ + +#endif /* __NO_MATH_INLINES */ diff --git a/libc/sysdeps/linux/alpha/bits/mman.h b/libc/sysdeps/linux/alpha/bits/mman.h new file mode 100644 index 0000000..2f0e564 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/mman.h @@ -0,0 +1,118 @@ +/* Definitions for POSIX memory map interface. Linux/Alpha version. + Copyright (C) 1997, 1998, 2000, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x100 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x10 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with + OSF/1 defines. */ +#if 0 && defined __USE_BSD +# define MAP_HASSEMAPHORE 0x0200 +# define MAP_INHERIT 0x0400 +# define MAP_UNALIGNED 0x0800 +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x01000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x02000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x04000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x08000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x10000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x20000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x40000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 2 /* Synchronous memory sync. */ +#define MS_INVALIDATE 4 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 8192 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 16384 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 6 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 6 /* Don't need these pages. */ +#endif + +/* Not used by Linux, but here to make sure we don't clash with + OSF/1 defines. */ +#if 0 && defined __USE_BSD +# define MADV_DONTNEED_COMPAT 4 /* Old version? */ +# define MADV_SPACEAVAIL 5 /* Ensure resources are available. */ +#endif diff --git a/libc/sysdeps/linux/alpha/bits/msq.h b/libc/sysdeps/linux/alpha/bits/msq.h new file mode 100644 index 0000000..ab251ea --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/msq.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + __time_t msg_rtime; /* time of last msgrcv command */ + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/alpha/bits/netdb.h b/libc/sysdeps/linux/alpha/bits/netdb.h new file mode 100644 index 0000000..e3664fd --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/netdb.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETDB_H +# error "Never include directly; use instead." +#endif + + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + /* XXX We should probably use uint32_t for the field and ensure + compatiblity by adding appropriate padding. */ + unsigned long int n_net; /* Network number. */ +}; diff --git a/libc/sysdeps/linux/alpha/bits/resource.h b/libc/sysdeps/linux/alpha/bits/resource.h new file mode 100644 index 0000000..2163745 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/resource.h @@ -0,0 +1,225 @@ +/* Bit values & structures for resource limits. Alpha/Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 6, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 7, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 8, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 9, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +#else +# define RLIM_INFINITY 0x7fffffffffffffffLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffLL +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/libc/sysdeps/linux/alpha/bits/sem.h b/libc/sysdeps/linux/alpha/bits/sem.h new file mode 100644 index 0000000..f63360b --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/sem.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/alpha/bits/setjmp.h b/libc/sysdeps/linux/alpha/bits/setjmp.h new file mode 100644 index 0000000..4471ba9 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/setjmp.h @@ -0,0 +1,87 @@ +/* Define the machine-dependent type `jmp_buf'. Alpha version. + Copyright (C) 1992,1997,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'long int' instead, to make writing the + assembler easier. Naturally, user code should not depend on + either representation. */ + +/* + * Integer registers: + * $0 is the return value (va); + * $1-$8, $22-$25, $28 are call-used (t0-t7, t8-t11, at); + * $9-$14 we save here (s0-s5); + * $15 is the FP and we save it here (fp or s6); + * $16-$21 are input arguments (call-used) (a0-a5); + * $26 is the return PC and we save it here (ra); + * $27 is the procedure value (i.e., the address of __setjmp) (pv or t12); + * $29 is the global pointer, which the caller will reconstruct + * from the return address restored in $26 (gp); + * $30 is the stack pointer and we save it here (sp); + * $31 is always zero (zero). + * + * Floating-point registers: + * $f0 is the floating return value; + * $f1, $f10-$f15, $f22-$f30 are call-used; + * $f2-$f9 we save here; + * $f16-$21 are input args (call-used); + * $f31 is always zero. + * + * Note that even on Alpha hardware that does not have an FPU (there + * isn't such a thing currently) it is required to implement the FP + * registers. + */ + +#if defined __USE_MISC || defined __ASSEMBLY__ +# define JB_S0 0 +# define JB_S1 1 +# define JB_S2 2 +# define JB_S3 3 +# define JB_S4 4 +# define JB_S5 5 +# define JB_PC 6 +# define JB_FP 7 +# define JB_SP 8 +# define JB_F2 9 +# define JB_F3 10 +# define JB_F4 11 +# define JB_F5 12 +# define JB_F6 13 +# define JB_F7 14 +# define JB_F8 15 +# define JB_F9 16 +#endif + +#ifndef __ASSEMBLY__ +typedef long int __jmp_buf[17]; + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) < (void *)((_jmpbuf)[JB_SP])) +#endif + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/alpha/bits/shm.h b/libc/sysdeps/linux/alpha/bits/shm.h new file mode 100644 index 0000000..35226c1 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/shm.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/alpha/bits/sigaction.h b/libc/sysdeps/linux/alpha/bits/sigaction.h new file mode 100644 index 0000000..80feb2f --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/sigaction.h @@ -0,0 +1,74 @@ +/* The proper definitions for Linux/Alpha sigaction. + Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + + /* Special flags. */ + unsigned int sa_flags; + }; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000004 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000020 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000040 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x00000002 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x00000008 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESETHAND 0x00000010 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 3 /* Set the set of blocked signals. */ diff --git a/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h b/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h new file mode 100644 index 0000000..16c5dcb --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) (ctx)->sc_regs[15]) +#define GET_STACK(ctx) ((void *) (ctx)->sc_regs[30]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/alpha/bits/siginfo.h b/libc/sysdeps/linux/alpha/bits/siginfo.h new file mode 100644 index 0000000..a2aacc0 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/siginfo.h @@ -0,0 +1,303 @@ +/* siginfo_t, sigevent and constants. Linux/Alpha version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/libc/sysdeps/linux/alpha/bits/signum.h b/libc/sysdeps/linux/alpha/bits/signum.h new file mode 100644 index 0000000..477c131 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/signum.h @@ -0,0 +1,82 @@ +/* Signal number definitions. Linux/Alpha version. + Copyright (C) 1996, 1997, 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif + +/* + * Linux/AXP has different signal numbers that Linux/i386: I'm trying + * to make it OSF/1 binary compatible, at least for normal binaries. + */ +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGCLD SIGCHLD +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define SIGPOLL SIGIO +#define SIGPWR SIGINFO +#define SIGIOT SIGABRT + +#define _NSIG 65 /* Biggest signal number + 1. */ + +#define SIGRTMIN (__libc_current_sigrtmin ()) +#define SIGRTMAX (__libc_current_sigrtmax ()) + +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#define __SIGRTMIN 32 +#define __SIGRTMAX (_NSIG - 1) + +#endif /* included. */ diff --git a/libc/sysdeps/linux/alpha/bits/sigstack.h b/libc/sysdeps/linux/alpha/bits/sigstack.h new file mode 100644 index 0000000..7faaf98 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + __ptr_t ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + __ptr_t ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/libc/sysdeps/linux/alpha/bits/stackinfo.h b/libc/sysdeps/linux/alpha/bits/stackinfo.h new file mode 100644 index 0000000..0a281bd --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Alpha the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/alpha/bits/stat.h b/libc/sysdeps/linux/alpha/bits/stat.h new file mode 100644 index 0000000..148c6ff --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/stat.h @@ -0,0 +1,151 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2001,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_GLIBC2 1 +#define _STAT_VER_GLIBC2_1 2 +#define _STAT_VER_KERNEL64 3 +#define _STAT_VER_GLIBC2_3_4 3 +#define _STAT_VER _STAT_VER_GLIBC2_3_4 + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + + +/* Nanosecond resolution timestamps are stored in a format equivalent to + 'struct timespec'. This is the type used whenever possible but the + Unix namespace rules do not allow the identifier 'timespec' to appear + in the header. Therefore we have to handle the use of + this header in strictly standard-compliant sources special. + + Use neat tidy anonymous unions and structures when possible. */ + +#if 0 /*def __USE_MISC*/ +# if __GNUC_PREREQ(3,3) +# define __ST_TIME(X) \ + __extension__ union { \ + struct timespec st_##X##tim; \ + struct { \ + __time_t st_##X##time; \ + unsigned long st_##X##timensec; \ + }; \ + } +# else +# define __ST_TIME(X) struct timespec st_##X##tim +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# endif +#else +# define __ST_TIME(X) \ + __time_t st_##X##time; \ + unsigned long st_##X##timensec +#endif + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifdef __USE_FILE_OFFSET64 + __ino64_t st_ino; /* File serial number. */ +#else + __ino_t st_ino; /* File serial number. */ + int __pad0; /* 64-bit st_ino. */ +#endif + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_FILE_OFFSET64 + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#else + __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */ + int __pad1; /* 64-bit st_blocks. */ +#endif + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __nlink_t st_nlink; /* Link count. */ + int __pad2; /* Real padding. */ + __ST_TIME(a); /* Time of last access. */ + __ST_TIME(m); /* Time of last modification. */ + __ST_TIME(c); /* Time of last status change. */ + long __unused[3]; + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 is the same shape as stat. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __nlink_t st_nlink; /* Link count. */ + int __pad0; /* Real padding. */ + __ST_TIME(a); /* Time of last access. */ + __ST_TIME(m); /* Time of last modification. */ + __ST_TIME(c); /* Time of last status change. */ + long __unused[3]; + }; +#endif + +#undef __ST_TIME + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/alpha/bits/statfs.h b/libc/sysdeps/linux/alpha/bits/statfs.h new file mode 100644 index 0000000..d838e6b --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/statfs.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t. */ + +struct statfs + { + int f_type; + int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + int f_namelen; + int f_frsize; + int f_spare[5]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + int f_type; + int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + int f_namelen; + int f_frsize; + int f_spare[5]; + }; +#endif + +/* Tell code we have this member. */ +#define _STATFS_F_NAMELEN +#define _STATFS_F_FRSIZE diff --git a/libc/sysdeps/linux/alpha/bits/statvfs.h b/libc/sysdeps/linux/alpha/bits/statvfs.h new file mode 100644 index 0000000..d37d0ff --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/statvfs.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync which the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/libc/sysdeps/linux/alpha/bits/syscalls.h b/libc/sysdeps/linux/alpha/bits/syscalls.h new file mode 100644 index 0000000..b5e0c16 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/syscalls.h @@ -0,0 +1,192 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#define _syscall_return(type) \ + return (_sc_err ? __set_errno(_sc_ret), _sc_ret = -1L : 0), (type) _sc_ret + +#define _syscall_clobbers \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ + "$22", "$23", "$24", "$25", "$27", "$28" \ + +#define _syscall0(type, name) \ +type name(void) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = __NR_##name; \ + __asm__("callsys # %0 %1 %2" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + __asm__("callsys # %0 %1 %2 %3" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + _sc_17 = (long) (arg2); \ + __asm__("callsys # %0 %1 %2 %3 %4" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + _sc_17 = (long) (arg2); \ + _sc_18 = (long) (arg3); \ + __asm__("callsys # %0 %1 %2 %3 %4 %5" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ + "r"(_sc_18) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + _sc_17 = (long) (arg2); \ + _sc_18 = (long) (arg3); \ + _sc_19 = (long) (arg4); \ + __asm__("callsys # %0 %1 %2 %3 %4 %5 %6" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ + "r"(_sc_18), "1"(_sc_19) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + _sc_17 = (long) (arg2); \ + _sc_18 = (long) (arg3); \ + _sc_19 = (long) (arg4); \ + _sc_20 = (long) (arg5); \ + __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ + "r"(_sc_18), "1"(_sc_19), "r"(_sc_20) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\ +{ \ + long _sc_ret, _sc_err; \ + { \ + register long _sc_0 __asm__("$0"); \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + register long _sc_21 __asm__("$21"); \ + \ + _sc_0 = __NR_##name; \ + _sc_16 = (long) (arg1); \ + _sc_17 = (long) (arg2); \ + _sc_18 = (long) (arg3); \ + _sc_19 = (long) (arg4); \ + _sc_20 = (long) (arg5); \ + _sc_21 = (long) (arg6); \ + __asm__("callsys # %0 %1 %2 %3 %4 %5 %6 %7 %8" \ + : "=r"(_sc_0), "=r"(_sc_19) \ + : "0"(_sc_0), "r"(_sc_16), "r"(_sc_17), \ + "r"(_sc_18), "1"(_sc_19), "r"(_sc_20), "r"(_sc_21) \ + : _syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ + } \ + _syscall_return(type); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/alpha/bits/termios.h b/libc/sysdeps/linux/alpha/bits/termios.h new file mode 100644 index 0000000..966ccf9 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/termios.h @@ -0,0 +1,226 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[33]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VEOF 0 +#define VEOL 1 +#define VEOL2 2 +#define VERASE 3 +#define VWERASE 4 +#define VKILL 5 +#define VREPRINT 6 +#define VSWTC 7 +#define VINTR 8 +#define VQUIT 9 +#define VSUSP 10 +#define VSTART 12 +#define VSTOP 13 +#define VLNEXT 14 +#define VDISCARD 15 +#define VMIN 16 +#define VTIME 17 + +/* c_iflag bits */ +#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 IXON 0001000 +#define IXOFF 0002000 +#ifdef __USE_BSD + /* POSIX.1 doesn't want these... */ +# define IXANY 0004000 +# define IUCLC 0010000 +# define IMAXBEL 0020000 +# define IUTF8 0040000 +#endif + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 00001400 +# define NL0 00000000 +# define NL1 00000400 +# define NL2 00001000 +# define NL3 00001400 +# define TABDLY 00006000 +# define TAB0 00000000 +# define TAB1 00002000 +# define TAB2 00004000 +# define TAB3 00006000 +# define CRDLY 00030000 +# define CR0 00000000 +# define CR1 00010000 +# define CR2 00020000 +# define CR3 00030000 +# define FFDLY 00040000 +# define FF0 00000000 +# define FF1 00040000 +# define BSDLY 00100000 +# define BS0 00000000 +# define BS1 00100000 +#endif + +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +#ifdef __USE_MISC +# define XTABS 01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */ +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0000037 +#endif +#define B0 0000000 /* hang up */ +#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 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +# define CBAUDEX 0000000 +#endif +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 + +#define __MAX_BAUD B4000000 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#ifdef __USE_MISC +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00004000 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#ifdef __USE_MISC +# define ECHOCTL 0x00000040 +# define ECHOPRT 0x00000020 +# define ECHOKE 0x00000001 +# define FLUSHO 0x00800000 +# define PENDIN 0x20000000 +#endif +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/sysdeps/linux/alpha/bits/typesizes.h b/libc/sysdeps/linux/alpha/bits/typesizes.h new file mode 100644 index 0000000..201585a --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/Alpha version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U64_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __U32_TYPE +#define __INO64_T_TYPE __U64_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __S64_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __U64_TYPE +#define __BLKCNT_T_TYPE __U32_TYPE +#define __BLKCNT64_T_TYPE __U64_TYPE +#define __FSBLKCNT_T_TYPE __S32_TYPE +#define __FSBLKCNT64_T_TYPE __S64_TYPE +#define __FSFILCNT_T_TYPE __U32_TYPE +#define __FSFILCNT64_T_TYPE __U64_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S64_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __U32_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h b/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h new file mode 100644 index 0000000..e62375c --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "call_pal 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_SLIGHTLY_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#undef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h b/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h new file mode 100644 index 0000000..f7cd69a --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h @@ -0,0 +1,8 @@ +/* Follow glibc's example and use 1024 for CLK_TCK to implement sysconf and + * clock.c instead of the normal default of 100. + * + * WARNING: It is assumed that this is a constant integer value usable in + * preprocessor conditionals!!! + */ + +#define __UCLIBC_CLK_TCK_CONST 1024 diff --git a/libc/sysdeps/linux/alpha/bits/uClibc_page.h b/libc/sysdeps/linux/alpha/bits/uClibc_page.h new file mode 100644 index 0000000..8219a19 --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/uClibc_page.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 8192 */ +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/alpha/bits/wordsize.h b/libc/sysdeps/linux/alpha/bits/wordsize.h new file mode 100644 index 0000000..029a7df --- /dev/null +++ b/libc/sysdeps/linux/alpha/bits/wordsize.h @@ -0,0 +1,30 @@ +/* Copyright (C) 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 64 + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ && !defined __LONG_DOUBLE_MATH_OPTIONAL + +/* Signal that we didn't used to have a `long double'. The changes all + the `long double' function variants to be redirects to the double + functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# endif +#endif diff --git a/libc/sysdeps/linux/alpha/brk.S b/libc/sysdeps/linux/alpha/brk.S new file mode 100644 index 0000000..42c7368 --- /dev/null +++ b/libc/sysdeps/linux/alpha/brk.S @@ -0,0 +1,82 @@ +/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe , 1993. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* __brk is a special syscall under Linux since it never returns an + error. Instead, the error condition is indicated by returning the old + break value (instead of the new, requested one). */ + +#include +#define _ERRNO_H +#include +#include + +#ifdef __PIC__ +.section .bss + .align 3 + .globl __curbrk + .hidden __curbrk +__curbrk: .skip 8 + .type __curbrk,@object + .size __curbrk,8 +#else +.comm __curbrk, 8 +#endif + + .text +.globl brk; +.align 3; +.ent brk , 0; + +brk: + .frame $30 , 8 , $26 + ldgp $29, 0($27) + subq $30, 8, $30 + .prologue 1 + + /* Save the requested brk across the system call. */ + stq $16, 0($30) + + ldiq $0, __NR_brk + call_pal 131 + + ldq $16, 0($30) + + /* Be prepared for an OSF-style brk. */ + bne $19, $err1 + beq $0, $ok + + /* Correctly handle the brk(0) query case. */ + cmoveq $16, $0, $16 + xor $16, $0, $1 + bne $1, $err0 + + /* Update __curbrk and return cleanly. */ + mov $31, $0 +$ok: stq $16, __curbrk + addq $30, 8, $30 + ret + + /* What a horrible way to die. */ +$err0: ldi $0, ENOMEM +$err1: addq $30, 8, $30 + jmp $31, __syscall_error + + .end brk + +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/alpha/bsd-_setjmp.S b/libc/sysdeps/linux/alpha/bsd-_setjmp.S new file mode 100644 index 0000000..4e6a2da --- /dev/null +++ b/libc/sysdeps/linux/alpha/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/alpha/bsd-setjmp.S b/libc/sysdeps/linux/alpha/bsd-setjmp.S new file mode 100644 index 0000000..1da848d --- /dev/null +++ b/libc/sysdeps/linux/alpha/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/alpha/clone.S b/libc/sysdeps/linux/alpha/clone.S new file mode 100644 index 0000000..79d4511 --- /dev/null +++ b/libc/sysdeps/linux/alpha/clone.S @@ -0,0 +1,95 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ + +.text +.globl clone; +.align 3; +.ent clone , 0; + +clone: + .frame $30 , 0, $26 + .prologue 0 + + /* Sanity check arguments. */ + ldiq v0,EINVAL + beq a0,$error /* no NULL function pointers */ + beq a1,$error /* no NULL stack pointers */ + + /* Save the fn ptr and arg on the new stack. */ + subq a1,16,a1 + stq a0,0(a1) + stq a3,8(a1) + + /* Do the system call */ + mov a2,a0 + ldiq v0,__NR_clone + call_pal 131 + + bne a3,$error + beq v0,thread_start + + /* Successful return from the parent */ + ret + + /* Something bad happened -- no child created */ +$error: + br gp,1f +1: ldgp gp,0(gp) + jmp zero,__syscall_error + +.end clone + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + + .ent thread_start +thread_start: + .frame fp,0,zero,0 + mov zero,fp + .prologue 0 + + /* Load up the arguments. */ + ldq pv,0($30) + ldq a0,8($30) + addq $30,16,$30 + + /* Call the user's function */ + jsr ra,(pv) + ldgp gp,0(ra) + + /* Call _exit rather than doing it inline for breakpoint purposes */ + mov v0,a0 + jsr ra,HIDDEN_JUMPTARGET(_exit) + + /* Die horribly. */ + halt + + .end thread_start diff --git a/libc/sysdeps/linux/alpha/crt1.S b/libc/sysdeps/linux/alpha/crt1.S new file mode 100644 index 0000000..0bf7124 --- /dev/null +++ b/libc/sysdeps/linux/alpha/crt1.S @@ -0,0 +1,97 @@ +/* Startup code for Alpha/ELF. + Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .align 3 + .globl _start + .ent _start, 0 + .type _start,@function +#if defined(__UCLIBC_CTOR_DTOR__) + .type _init,%function + .type _fini,%function +#else + .weak _init + .weak _fini +#endif + .type __uClibc_main,%function + +_start: + .frame $15, 0, $15 + br gp, 1f +1: ldgp gp, 0(gp) + subq sp, 16, sp + mov 0, $15 + .prologue 0 + + /* Load address of the user's main function. */ + lda a0, main + + ldl a1, 16(sp) /* get argc */ + lda a2, 24(sp) /* get argv */ + + /* Load address of our own entry points to .fini and .init. */ + lda a3, _init + lda a4, _fini + + /* Store address of the shared library termination function. */ + mov v0, a5 + + /* Provide the highest stack address to the user code. */ + stq sp, 0(sp) + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + jsr ra, __uClibc_main + + /* Die very horribly if exit returns. Call_pal hlt is callable from + kernel mode only; this will result in an illegal instruction trap. */ + call_pal 0 + .end _start + +/* For ECOFF backwards compatibility. */ +/*weak_alias (_start, __start)*/ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/alpha/crti.S b/libc/sysdeps/linux/alpha/crti.S new file mode 100644 index 0000000..5c25539 --- /dev/null +++ b/libc/sysdeps/linux/alpha/crti.S @@ -0,0 +1,43 @@ + .set noat + .set noreorder + .set nomacro + .set macro + + .section .init + .set nomacro + .align 2 + .globl _init + .ent _init +_init: + .frame $30,0,$26,0 + .mask 0x4000000,0 + ldah $29,0($27) !gpdisp!3 + lda $29,0($29) !gpdisp!3 +$_init..ng: + lda $30,-16($30) + stq $26,0($30) + .prologue 1 + .set macro + + .align 2 + .end _init + + .section .fini + .set nomacro + .align 2 + .globl _fini + .ent _fini +_fini: + .frame $30,0,$26,0 + .mask 0x4000000,0 + ldah $29,0($27) !gpdisp!6 + lda $29,0($29) !gpdisp!6 +$_fini..ng: + lda $30,-16($30) + stq $26,0($30) + .prologue 1 + .set macro + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/alpha/crtn.S b/libc/sysdeps/linux/alpha/crtn.S new file mode 100644 index 0000000..c6fec15 --- /dev/null +++ b/libc/sysdeps/linux/alpha/crtn.S @@ -0,0 +1,30 @@ + .set noat + .set noreorder + .set nomacro + .set macro + + .section .init + .set nomacro + .align 2 + .globl _init + .ent _init + .set nomacro + ldq $26,0($30) + lda $30,16($30) + ret $31,($26),1 + .end _init + .set macro + + .section .fini + .set nomacro + .align 2 + .globl _fini + .ent _fini + .set nomacro + ldq $26,0($30) + lda $30,16($30) + ret $31,($26),1 + .end _fini + .set macro + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/alpha/divl.S b/libc/sysdeps/linux/alpha/divl.S new file mode 100644 index 0000000..fdf053f --- /dev/null +++ b/libc/sysdeps/linux/alpha/divl.S @@ -0,0 +1,6 @@ +#define IS_REM 0 +#define SIZE 4 +#define UFUNC_NAME __divlu +#define SFUNC_NAME __divl + +#include "divrem.h" diff --git a/libc/sysdeps/linux/alpha/divq.S b/libc/sysdeps/linux/alpha/divq.S new file mode 100644 index 0000000..8c88af9 --- /dev/null +++ b/libc/sysdeps/linux/alpha/divq.S @@ -0,0 +1,6 @@ +#define IS_REM 0 +#define SIZE 8 +#define UFUNC_NAME __divqu +#define SFUNC_NAME __divq + +#include "divrem.h" diff --git a/libc/sysdeps/linux/alpha/divrem.h b/libc/sysdeps/linux/alpha/divrem.h new file mode 100644 index 0000000..bd4e2d1 --- /dev/null +++ b/libc/sysdeps/linux/alpha/divrem.h @@ -0,0 +1,198 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The current Alpha chips don't provide hardware for integer + division. The C compiler expects the functions + + __divqu: 64-bit unsigned long divide + __remqu: 64-bit unsigned long remainder + __divqs/__remqs: signed 64-bit + __divlu/__remlu: unsigned 32-bit + __divls/__remls: signed 32-bit + + These are not normal C functions: instead of the normal calling + sequence, these expect their arguments in registers t10 and t11, and + return the result in t12 (aka pv). Register AT may be clobbered + (assembly temporary), anything else must be saved. */ + +#include + +#include +#ifdef __linux__ +# include +# include +#else +# include +#endif + +#define mask v0 +#define divisor t0 +#define compare AT +#define tmp1 t2 +#define tmp2 t3 +#define retaddr t9 +#define arg1 t10 +#define arg2 t11 +#define result t12 + + +#if IS_REM +# define DIV_ONLY(x,y...) +# define REM_ONLY(x,y...) x,##y +# define modulus result +# define quotient t1 +# define GETSIGN(x) mov arg1, x +# define STACK 32 +#else +# define DIV_ONLY(x,y...) x,##y +# define REM_ONLY(x,y...) +# define modulus t1 +# define quotient result +# define GETSIGN(x) xor arg1, arg2, x +# define STACK 48 +#endif + +#if SIZE == 8 +# define LONGIFY(x,y) mov x,y +# define SLONGIFY(x,y) mov x,y +# define _SLONGIFY(x) +# define NEG(x,y) negq x,y +#else +# define LONGIFY(x,y) zapnot x,15,y +# define SLONGIFY(x,y) sextl x,y +# define _SLONGIFY(x) sextl x,x +# define NEG(x,y) negl x,y +#endif + + .set noreorder + .set noat + + .ent UFUNC_NAME + .globl UFUNC_NAME +#ifndef IS_IN_rtld + .hidden UFUNC_NAME +#endif + + .align 3 +UFUNC_NAME: + lda sp, -STACK(sp) + .frame sp, STACK, retaddr, 0 + .prologue 0 + +$udiv: + stq t0, 0(sp) + LONGIFY (arg2, divisor) + stq t1, 8(sp) + LONGIFY (arg1, modulus) + stq v0, 16(sp) + clr quotient + stq tmp1, 24(sp) + ldiq mask, 1 + DIV_ONLY(stq tmp2,32(sp)) + + beq divisor, $divbyzero + + .align 3 +#if SIZE == 8 + /* Shift divisor left. */ +1: cmpult divisor, modulus, compare + blt divisor, 2f + addq divisor, divisor, divisor + addq mask, mask, mask + bne compare, 1b + unop +2: +#else + /* Shift divisor left using 3-bit shifts as we can't overflow. + This results in looping three times less here, but up to + two more times later. Thus using a large shift isn't worth it. */ +1: cmpult divisor, modulus, compare + s8addq divisor, zero, divisor + s8addq mask, zero, mask + bne compare, 1b +#endif + + /* Now go back to the right. */ +3: DIV_ONLY(addq quotient, mask, tmp2) + srl mask, 1, mask + cmpule divisor, modulus, compare + subq modulus, divisor, tmp1 + DIV_ONLY(cmovne compare, tmp2, quotient) + srl divisor, 1, divisor + cmovne compare, tmp1, modulus + bne mask, 3b + +$done: ldq t0, 0(sp) + ldq t1, 8(sp) + ldq v0, 16(sp) + ldq tmp1, 24(sp) + DIV_ONLY(ldq tmp2, 32(sp)) + lda sp, STACK(sp) + ret zero, (retaddr), 1 + +$divbyzero: + mov a0, tmp1 + ldiq a0, GEN_INTDIV + call_pal PAL_gentrap + mov tmp1, a0 + clr result /* If trap returns, return zero. */ + br $done + + .end UFUNC_NAME + + .ent SFUNC_NAME + .globl SFUNC_NAME + + .align 3 +SFUNC_NAME: + lda sp, -STACK(sp) + .frame sp, STACK, retaddr, 0 + .prologue 0 + + or arg1, arg2, AT + _SLONGIFY(AT) + bge AT, $udiv /* don't need to mess with signs */ + + /* Save originals and find absolute values. */ + stq arg1, 0(sp) + NEG (arg1, AT) + stq arg2, 8(sp) + cmovge AT, AT, arg1 + stq retaddr, 16(sp) + NEG (arg2, AT) + stq tmp1, 24(sp) + cmovge AT, AT, arg2 + + /* Do the unsigned division. */ + bsr retaddr, UFUNC_NAME + + /* Restore originals and adjust the sign of the result. */ + ldq arg1, 0(sp) + ldq arg2, 8(sp) + GETSIGN (AT) + NEG (result, tmp1) + _SLONGIFY(AT) + ldq retaddr, 16(sp) + cmovlt AT, tmp1, result + ldq tmp1, 24(sp) + + lda sp, STACK(sp) + ret zero, (retaddr), 1 + + .end SFUNC_NAME diff --git a/libc/sysdeps/linux/alpha/fpu_control.h b/libc/sysdeps/linux/alpha/fpu_control.h new file mode 100644 index 0000000..cdffcfb --- /dev/null +++ b/libc/sysdeps/linux/alpha/fpu_control.h @@ -0,0 +1,108 @@ +/* FPU control word bits. Alpha-mapped-to-Intel version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ALPHA_FPU_CONTROL_H +#define _ALPHA_FPU_CONTROL_H + +/* + * Since many programs seem to hardcode the values passed to __setfpucw() + * (rather than using the manifest constants) we emulate the x87 interface + * here (at least where this makes sense). + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f. I choose 0x1372. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control -- without effect on Alpha */ +#define _FPU_EXTENDED 0x300 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 /* DO NOT USE */ + +/* + * rounding control---notice that on the Alpha this affects only + * instructions with the dynamic rounding mode qualifier (/d). + */ +#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux default: + - extended precision + - rounding to positive infinity. There is no /p instruction + qualifier. By setting the dynamic rounding mode to +infinity, + one can use /d to get round to +infinity with no extra overhead + (so long as the default isn't changed, of course...) + - no exceptions enabled. */ + +#define _FPU_DEFAULT 0x137f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x137f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _ALPHA_FPU_CONTROL */ diff --git a/libc/sysdeps/linux/alpha/pipe.S b/libc/sysdeps/linux/alpha/pipe.S new file mode 100644 index 0000000..8a9236b --- /dev/null +++ b/libc/sysdeps/linux/alpha/pipe.S @@ -0,0 +1,48 @@ +/* Copyright (C) 1993, 1995, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@cs.arizona.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* __pipe is a special syscall since it returns two values. */ + +.globl pipe +.align 4 +.ent pipe, 0 +pipe: + .frame sp, 0, ra + ldgp gp,0(pv) + .prologue 1 + lda v0, __NR_pipe + call_pal PAL_callsys + bne a3, $syscall_error + + stl r0, 0(a0) + stl r1, 4(a0) + mov zero, v0 + ret + +$syscall_error: + jmp zero,__syscall_error + +.end pipe + +libc_hidden_def (pipe) diff --git a/libc/sysdeps/linux/alpha/reml.S b/libc/sysdeps/linux/alpha/reml.S new file mode 100644 index 0000000..8c00365 --- /dev/null +++ b/libc/sysdeps/linux/alpha/reml.S @@ -0,0 +1,6 @@ +#define IS_REM 1 +#define SIZE 4 +#define UFUNC_NAME __remlu +#define SFUNC_NAME __reml + +#include "divrem.h" diff --git a/libc/sysdeps/linux/alpha/remq.S b/libc/sysdeps/linux/alpha/remq.S new file mode 100644 index 0000000..cd1064a --- /dev/null +++ b/libc/sysdeps/linux/alpha/remq.S @@ -0,0 +1,6 @@ +#define IS_REM 1 +#define SIZE 8 +#define UFUNC_NAME __remqu +#define SFUNC_NAME __remq + +#include "divrem.h" diff --git a/libc/sysdeps/linux/alpha/setjmp.S b/libc/sysdeps/linux/alpha/setjmp.S new file mode 100644 index 0000000..105cc82 --- /dev/null +++ b/libc/sysdeps/linux/alpha/setjmp.S @@ -0,0 +1,91 @@ +/* Copyright (C) 1992, 1994, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ASM +#define _SETJMP_H +#define __ASSEMBLY__ +#include + +#define a0 $16 + + .ent __sigsetjmp + .global __sigsetjmp +__sigsetjmp: + ldgp $29, 0($27) + +$sigsetjmp_local: + subq $30, 16, $30 + .frame $26, 16, $26, 0 + stq $26, 0($30) + .mask 0x04000000, -16 + .prologue 1 + + stq $9, JB_S0*8(a0) + stq $10, JB_S1*8(a0) + stq $11, JB_S2*8(a0) + stq $12, JB_S3*8(a0) + stq $13, JB_S4*8(a0) + stq $14, JB_S5*8(a0) + stq $26, JB_PC*8(a0) + addq $30, 16, $1 + stq $15, JB_FP*8(a0) + stq $1, JB_SP*8(a0) + stt $f2, JB_F2*8(a0) + stt $f3, JB_F3*8(a0) + stt $f4, JB_F4*8(a0) + stt $f5, JB_F5*8(a0) + stt $f6, JB_F6*8(a0) + stt $f7, JB_F7*8(a0) + stt $f8, JB_F8*8(a0) + stt $f9, JB_F9*8(a0) + + /* Call to C to (potentially) save our signal mask. */ + jsr $26, __sigjmp_save + + ldq $26, 0($30) + addq $30, 16, $30 + ret + +.end __sigsetjmp + +/* Put these traditional entry points in the same file so that we can + elide much of the nonsense in trying to jmp to the real function. */ + +.globl _setjmp; +.align 3; +.ent _setjmp , 0; +_setjmp: + .frame $30 , 0, $26 + ldgp $29, 0($27) + mov 0, $17 + br $sigsetjmp_local +.end _setjmp + +.globl setjmp; +.align 3; +.ent setjmp , 0; +setjmp: + .frame $30 , 0, $26 + ldgp $29, 0($27) + mov 1, $17 + br $sigsetjmp_local +.end setjmp + +.weak _setjmp +.weak setjmp diff --git a/libc/sysdeps/linux/alpha/sigprocmask.c b/libc/sysdeps/linux/alpha/sigprocmask.c new file mode 100644 index 0000000..32f0275 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sigprocmask.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1993, 1995, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@azstarnet.com). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* When there is kernel support for more than 64 signals, we'll have to + switch to a new system call convention here. */ + +static __inline__ _syscall2(int, osf_sigprocmask, int, how, unsigned long int, setval) + +libc_hidden_proto(sigprocmask) +int +sigprocmask (int how, const sigset_t *set, sigset_t *oset) +{ + unsigned long int setval; + long result; + + if (set) + setval = set->__val[0]; + else + { + setval = 0; + how = SIG_BLOCK; /* ensure blocked mask doesn't get changed */ + } + + result = osf_sigprocmask(how, setval); + if (result == -1) + /* If there are ever more than 63 signals, we need to recode this + in assembler since we wouldn't be able to distinguish a mask of + all 1s from -1, but for now, we're doing just fine... */ + return result; + + if (oset) + { + oset->__val[0] = result; + result = _SIGSET_NWORDS; + while (--result > 0) + oset->__val[result] = 0; + } + return 0; +} +libc_hidden_def(sigprocmask) diff --git a/libc/sysdeps/linux/alpha/sys/acct.h b/libc/sysdeps/linux/alpha/sys/acct.h new file mode 100644 index 0000000..1e00006 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/acct.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ACCT_H + +#define _SYS_ACCT_H 1 +#include + +#define __need_time_t +#include + + +__BEGIN_DECLS + +#define ACCT_COMM 16 + +struct acct + { + char ac_comm[ACCT_COMM]; /* Accounting command name. */ + time_t ac_utime; /* Accounting user time. */ + time_t ac_stime; /* Accounting system time. */ + time_t ac_etime; /* Accounting elapsed time. */ + time_t ac_btime; /* Beginning time. */ + unsigned int ac_uid; /* Accounting user ID. */ + unsigned int ac_gid; /* Accounting group ID. */ + unsigned int ac_tty; /* Controlling tty. */ + /* Please note that the value of the `ac_tty' field, a device number, + is encoded differently in the kernel and for the libc dev_t type. */ + char ac_flag; /* Accounting flag. */ + long int ac_minflt; /* Accounting minor pagefaults. */ + long int ac_majflt; /* Accounting major pagefaults. */ + long int ac_exitcode; /* Accounting process exitcode. */ + }; + +enum + { + AFORK = 0001, /* Has executed fork, but no exec. */ + ASU = 0002, /* Used super-user privileges. */ + ACORE = 0004, /* Dumped core. */ + AXSIG = 0010 /* Killed by a signal. */ + }; + +#define AHZ 100 + + +/* Switch process accounting on and off. */ +extern int acct (__const char *__filename) __THROW; + +__END_DECLS + +#endif /* sys/acct.h */ diff --git a/libc/sysdeps/linux/alpha/sys/io.h b/libc/sysdeps/linux/alpha/sys/io.h new file mode 100644 index 0000000..4334c63 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/io.h @@ -0,0 +1,95 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; + +/* Return the physical address of the DENSE I/O memory or NULL if none + is available (e.g. on a jensen). */ +extern unsigned long int _bus_base (void) __THROW __attribute__ ((const)); +extern unsigned long int bus_base (void) __THROW __attribute__ ((const)); + +/* Return the physical address of the SPARSE I/O memory. */ +extern unsigned long _bus_base_sparse (void) __THROW __attribute__ ((const)); +extern unsigned long bus_base_sparse (void) __THROW __attribute__ ((const)); + +/* Return the HAE shift used by the SPARSE I/O memory. */ +extern int _hae_shift (void) __THROW __attribute__ ((const)); +extern int hae_shift (void) __THROW __attribute__ ((const)); + +/* Previous three are deprecated in favour of the following, which + knows about multiple PCI "hoses". Provide the PCI bus and dfn + numbers just as to pciconfig_read/write. */ + +enum __pciconfig_iobase_which +{ + IOBASE_HOSE = 0, /* Return hose index. */ + IOBASE_SPARSE_MEM = 1, /* Return physical memory addresses. */ + IOBASE_DENSE_MEM = 2, + IOBASE_SPARSE_IO = 3, + IOBASE_DENSE_IO = 4 +}; + +extern long pciconfig_iobase(enum __pciconfig_iobase_which __which, + unsigned long int __bus, + unsigned long int __dfn) + __THROW __attribute__ ((const)); + +/* Access PCI space protected from machine checks. */ +extern int pciconfig_read (unsigned long int __bus, + unsigned long int __dfn, + unsigned long int __off, + unsigned long int __len, + unsigned char *__buf) __THROW; + +extern int pciconfig_write (unsigned long int __bus, + unsigned long int __dfn, + unsigned long int __off, + unsigned long int __len, + unsigned char *__buf) __THROW; + +/* Userspace declarations. */ +extern unsigned int inb (unsigned long __port) __THROW; +extern unsigned int inw (unsigned long __port) __THROW; +extern unsigned int inl (unsigned long __port) __THROW; +extern void outb (unsigned char __b, unsigned long __port) __THROW; +extern void outw (unsigned short __w, unsigned long __port) __THROW; +extern void outl (unsigned int __l, unsigned long __port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/alpha/sys/procfs.h b/libc/sysdeps/linux/alpha/sys/procfs.h new file mode 100644 index 0000000..bee51f9 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/procfs.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/alpha/sys/regdef.h b/libc/sysdeps/linux/alpha/sys/regdef.h new file mode 100644 index 0000000..18fb0d5 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/regdef.h @@ -0,0 +1,47 @@ +#ifndef __alpha_regdef_h__ +#define __alpha_regdef_h__ + +#define v0 $0 /* function return value */ + +#define t0 $1 /* temporary registers (caller-saved) */ +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 + +#define s0 $9 /* saved-registers (callee-saved registers) */ +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define s6 $15 +#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ + +#define a0 $16 /* argument registers (caller-saved) */ +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 + +#define t8 $22 /* more temps (caller-saved) */ +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 /* return address register */ +#define t12 $27 + +#define pv t12 /* procedure-variable register */ +#define AT $at /* assembler temporary */ +#define gp $29 /* global pointer */ +#define sp $30 /* stack pointer */ +#define zero $31 /* reads as zero, writes are noops */ + +#define r0 v0 +#define r1 a4 + +#endif /* __alpha_regdef_h__ */ diff --git a/libc/sysdeps/linux/alpha/sys/ucontext.h b/libc/sysdeps/linux/alpha/sys/ucontext.h new file mode 100644 index 0000000..438293c --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/ucontext.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 33 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Type for floating-point register. */ +typedef long int fpreg_t; + +/* Number of general registers. */ +#define NFPREG 32 + +/* Container for all general registers. */ +typedef fpreg_t fpregset_t[NFPREG]; + + +/* A machine context is exactly a sigcontext. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + unsigned long __uc_osf_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/alpha/sys/user.h b/libc/sysdeps/linux/alpha/sys/user.h new file mode 100644 index 0000000..f9beea0 --- /dev/null +++ b/libc/sysdeps/linux/alpha/sys/user.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for gdb/strace and gdb/strace + only. Don't read too much into it. Don't use it for anything other + than gdb/strace unless you know what you are doing. */ + +#include +#include + +struct user +{ + unsigned long int regs[EF_SIZE / 8 + 32]; /* integer and fp regs */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long int start_code; /* text starting address */ + unsigned long int start_data; /* data starting address */ + unsigned long int start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs *u_ar0; /* help gdb find registers */ + unsigned long int magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/libc/sysdeps/linux/alpha/syscall.S b/libc/sysdeps/linux/alpha/syscall.S new file mode 100644 index 0000000..89901d5 --- /dev/null +++ b/libc/sysdeps/linux/alpha/syscall.S @@ -0,0 +1,71 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* + * This is for COMPATIBILITY with Linux/x86 only. Linux/Alpha system + * calls return an error indication in a3. This allows arbitrary 64bit + * values to be returned in v0 (because negative values are not + * mistaken as error numbers). However, C allows only one value to + * be returned, so the interface below folds the error indication passed in + * a3 back into v0: it sets v0 to -errno if an error occurs. Thus, + * no negative 64bit numbers can be returned. To avoid this problem, + * use assembly stubs wherever possible/convenient. + * + * Usage: + * + * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5) + * + * syscall_number = the index of the system call we're invoking + * arg1-arg5 = up to 5 integer arguments to the system call + * + * We need to do some arg shifting: the kernel expects the + * syscall number in v0 and the first five args in a0-a4. + * + */ + +.globl __syscall; +.align 4; +.ent __syscall, 0; +__syscall: +.frame sp, 0, ra + .prologue 0 + + mov a0, v0 /* Syscall number -> v0 */ + mov a1, a0 /* arg1-arg5 -> a0-a4 */ + mov a2, a1 + mov a3, a2 + mov a4, a3 + mov a5, a4 + + call_pal PAL_callsys /* Invoke system call */ + bne a3, $error + ret + +$error: + br gp, 2f +2: ldgp gp, 0(gp) + jmp zero,__syscall_error + +.end __syscall + +weak_alias (__syscall, syscall) diff --git a/libc/sysdeps/linux/arm/Makefile b/libc/sysdeps/linux/arm/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/arm/Makefile.arch b/libc/sysdeps/linux/arm/Makefile.arch new file mode 100644 index 0000000..a3b6fc4 --- /dev/null +++ b/libc/sysdeps/linux/arm/Makefile.arch @@ -0,0 +1,35 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c ioperm.c iopl.c mmap.c posix_fadvise.c posix_fadvise64.c \ + sigaction.c __syscall_error.c + +SSRC := \ + __longjmp.S vfork.S clone.S setjmp.S bsd-setjmp.S \ + bsd-_setjmp.S sigrestorer.S mmap64.S + +ifeq ($(CONFIG_ARM_EABI),y) +CSRC += aeabi_assert.c aeabi_atexit.c aeabi_errno_addr.c \ + aeabi_localeconv.c aeabi_memclr.c aeabi_memcpy.c \ + aeabi_memmove.c aeabi_memset.c find_exidx.c +SSRC += syscall-eabi.S +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += aeabi_mb_cur_max.c +endif +else +CSRC += syscall.c +endif + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch + +ifeq ($(CONFIG_ARM_EABI),y) +libc-static-y += $(ARCH_OUT)/aeabi_lcsts.o $(ARCH_OUT)/aeabi_math.o \ + $(ARCH_OUT)/aeabi_sighandlers.o +libc-nonshared-y += $(ARCH_OUT)/aeabi_lcsts.os $(ARCH_OUT)/aeabi_math.os \ + $(ARCH_OUT)/aeabi_sighandlers.os +libc-shared-y += $(ARCH_OUT)/aeabi_unwind_cpp_pr1.os +endif diff --git a/libc/sysdeps/linux/arm/__longjmp.S b/libc/sysdeps/linux/arm/__longjmp.S new file mode 100644 index 0000000..5faf4ec --- /dev/null +++ b/libc/sysdeps/linux/arm/__longjmp.S @@ -0,0 +1,114 @@ +/* longjmp for ARM. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define _SETJMP_H +#define _ASM +#include + + +.global __longjmp +.type __longjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +__longjmp: + mov r2, r0 + movs r0, r1 + /* can't let setjmp() return zero! */ + bne 1f + mov r0, #1 +1: + mov r1, r2 + /* Restore registers, shuffling them through low regs. */ + add r2, #(4 * 4) + ldmia r2!, {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov sl, r6 + mov fp, r7 + ldmia r2!, {r4, r5} + mov sp, r4 + mov lr, r5 + ldmia r1!, {r4, r5, r6, r7} + bx lr +#else +__longjmp: + mov ip, r0 /* save jmp_buf pointer */ + + movs r0, r1 /* get the return value in place */ + IT(t, eq) + moveq r0, #1 /* can't let setjmp() return zero! */ + +#if defined(__thumb2__) + /* Thumb-2 does not allow loading sp with ldm. */ + ldmia ip!, {v1-v6, sl, fp} + ldr sp, [ip], #4 + ldr lr, [ip], #4 +#else + ldmia ip!, {v1-v6, sl, fp, sp, lr} +#endif + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#ifdef __VFP_FP__ + /* Restore the VFP registers. */ + /* Following instruction is fldmiax ip!, {d8-d15}. */ + ldc p11, cr8, [r12], #68 + /* Restore the floating-point status register. */ + ldr r1, [ip], #4 + /* Following instruction is fmxr fpscr, r1. */ + mcr p10, 7, r1, cr1, cr0, 0 +# elif defined __MAVERICK__ + cfldrd mvd4, [ip], #8 ; nop + cfldrd mvd5, [ip], #8 ; nop + cfldrd mvd6, [ip], #8 ; nop + cfldrd mvd7, [ip], #8 ; nop + cfldrd mvd8, [ip], #8 ; nop + cfldrd mvd9, [ip], #8 ; nop + cfldrd mvd10, [ip], #8 ; nop + cfldrd mvd11, [ip], #8 ; nop + cfldrd mvd12, [ip], #8 ; nop + cfldrd mvd13, [ip], #8 ; nop + cfldrd mvd14, [ip], #8 ; nop + cfldrd mvd15, [ip], #8 +# else + lfmfd f4, 4, [ip] ! /* load the floating point regs */ +# endif +#endif +#ifdef __IWMMXT__ + /* Restore the call-preserved iWMMXt registers. */ + /* Following instructions are wldrd wr10, [ip], #8 (etc.) */ + ldcl p1, cr10, [r12], #8 + ldcl p1, cr11, [r12], #8 + ldcl p1, cr12, [r12], #8 + ldcl p1, cr13, [r12], #8 + ldcl p1, cr14, [r12], #8 + ldcl p1, cr15, [r12], #8 +#endif + +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/arm/__syscall_error.c b/libc/sysdeps/linux/arm/__syscall_error.c new file mode 100644 index 0000000..2b642e8 --- /dev/null +++ b/libc/sysdeps/linux/arm/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/arm/aeabi_assert.c b/libc/sysdeps/linux/arm/aeabi_assert.c new file mode 100644 index 0000000..e0985b4 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_assert.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#undef NDEBUG +#include +#include + +libc_hidden_proto(__assert) + +void +__aeabi_assert (const char *assertion, const char *file, + unsigned int line) +{ + __assert (assertion, file, line, NULL); +} diff --git a/libc/sysdeps/linux/arm/aeabi_atexit.c b/libc/sysdeps/linux/arm/aeabi_atexit.c new file mode 100644 index 0000000..4a7a6f1 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_atexit.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __cxa_atexit (void (*func) (void *), void *arg, void *dso_handle); +libc_hidden_proto(__cxa_atexit) + +/* Register a function to be called by exit or when a shared library + is unloaded. This routine is like __cxa_atexit, but uses the + calling sequence required by the ARM EABI. */ +int +__aeabi_atexit (void *arg, void (*func) (void *), void *d) +{ + return __cxa_atexit (func, arg, d); +} diff --git a/libc/sysdeps/linux/arm/aeabi_errno_addr.c b/libc/sysdeps/linux/arm/aeabi_errno_addr.c new file mode 100644 index 0000000..09bdc1e --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_errno_addr.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +volatile int * +__aeabi_errno_addr (void) +{ + return &errno; +} diff --git a/libc/sysdeps/linux/arm/aeabi_lcsts.c b/libc/sysdeps/linux/arm/aeabi_lcsts.c new file mode 100644 index 0000000..99c7985 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_lcsts.c @@ -0,0 +1,84 @@ +/* Link-time constants for ARM EABI. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The ARM EABI requires that we provide ISO compile-time constants as + link-time constants. Some portable applications may reference these. */ + +#include +#include +#include +#include +#include +#include +#include + +#define eabi_constant2(X,Y) const int __aeabi_##X attribute_hidden = Y +#define eabi_constant(X) const int __aeabi_##X attribute_hidden = X + +eabi_constant (EDOM); +eabi_constant (ERANGE); +eabi_constant (EILSEQ); + +eabi_constant (MB_LEN_MAX); + +eabi_constant (LC_COLLATE); +eabi_constant (LC_CTYPE); +eabi_constant (LC_MONETARY); +eabi_constant (LC_NUMERIC); +eabi_constant (LC_TIME); +eabi_constant (LC_ALL); + +/* The value of __aeabi_JMP_BUF_SIZE is the number of doublewords in a + jmp_buf. */ +eabi_constant2 (JMP_BUF_SIZE, sizeof (jmp_buf) / 8); + +eabi_constant (SIGABRT); +eabi_constant (SIGFPE); +eabi_constant (SIGILL); +eabi_constant (SIGINT); +eabi_constant (SIGSEGV); +eabi_constant (SIGTERM); + +eabi_constant2 (IOFBF, _IOFBF); +eabi_constant2 (IOLBF, _IOLBF); +eabi_constant2 (IONBF, _IONBF); +eabi_constant (BUFSIZ); +eabi_constant (FOPEN_MAX); +eabi_constant (TMP_MAX); +eabi_constant (FILENAME_MAX); +eabi_constant (L_tmpnam); + +eabi_constant (CLOCKS_PER_SEC); diff --git a/libc/sysdeps/linux/arm/aeabi_localeconv.c b/libc/sysdeps/linux/arm/aeabi_localeconv.c new file mode 100644 index 0000000..c9e9dd2 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_localeconv.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(localeconv) + +struct lconv * +__aeabi_localeconv (void) +{ + return localeconv (); +} diff --git a/libc/sysdeps/linux/arm/aeabi_math.c b/libc/sysdeps/linux/arm/aeabi_math.c new file mode 100644 index 0000000..e7f1dbf --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_math.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +const double __aeabi_HUGE_VAL attribute_hidden = HUGE_VAL; +const long double __aeabi_HUGE_VALL attribute_hidden = HUGE_VALL; +const float __aeabi_HUGE_VALF attribute_hidden = HUGE_VALF; +const float __aeabi_INFINITY attribute_hidden = INFINITY; +const float __aeabi_NAN attribute_hidden = NAN; diff --git a/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c b/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c new file mode 100644 index 0000000..937a7ff --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(_stdlib_mb_cur_max) +#endif + +int +__aeabi_MB_CUR_MAX (void) +{ +#ifdef __UCLIBC_HAS_WCHAR__ + return MB_CUR_MAX; +#else + return 1; +#endif +} diff --git a/libc/sysdeps/linux/arm/aeabi_memclr.c b/libc/sysdeps/linux/arm/aeabi_memclr.c new file mode 100644 index 0000000..c0f9021 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_memclr.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* Clear memory. Can't alias to bzero because it's not defined in the + same translation unit. */ +void +__aeabi_memclr (void *dest, size_t n) +{ + memset (dest, 0, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memclr, __aeabi_memclr4) +strong_alias (__aeabi_memclr, __aeabi_memclr8) diff --git a/libc/sysdeps/linux/arm/aeabi_memcpy.c b/libc/sysdeps/linux/arm/aeabi_memcpy.c new file mode 100644 index 0000000..83eac0b --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_memcpy.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* Copy memory like memcpy, but no return value required. Can't alias + to memcpy because it's not defined in the same translation + unit. */ +void +__aeabi_memcpy (void *dest, const void *src, size_t n) +{ + memcpy (dest, src, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memcpy, __aeabi_memcpy4) +strong_alias (__aeabi_memcpy, __aeabi_memcpy8) diff --git a/libc/sysdeps/linux/arm/aeabi_memmove.c b/libc/sysdeps/linux/arm/aeabi_memmove.c new file mode 100644 index 0000000..164d72b --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_memmove.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(memmove) */ + +/* Copy memory like memmove, but no return value required. Can't + alias to memmove because it's not defined in the same translation + unit. */ +void +__aeabi_memmove (void *dest, const void *src, size_t n) +{ + memmove (dest, src, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memmove, __aeabi_memmove4) +strong_alias (__aeabi_memmove, __aeabi_memmove8) diff --git a/libc/sysdeps/linux/arm/aeabi_memset.c b/libc/sysdeps/linux/arm/aeabi_memset.c new file mode 100644 index 0000000..f1c366f --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_memset.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Experimentally off - libc_hidden_proto(memset) */ + +/* Set memory like memset, but different argument order and no return + value required. */ +void +__aeabi_memset (void *dest, size_t n, int c) +{ + memset (dest, c, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memset, __aeabi_memset4) +strong_alias (__aeabi_memset, __aeabi_memset8) diff --git a/libc/sysdeps/linux/arm/aeabi_sighandlers.S b/libc/sysdeps/linux/arm/aeabi_sighandlers.S new file mode 100644 index 0000000..ba9769f --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_sighandlers.S @@ -0,0 +1,52 @@ +/* Link-time constants for ARM EABI - signal handlers. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The ARM EABI defines these as "functions". */ + + .global __aeabi_SIG_DFL + .hidden __aeabi_SIG_DFL + .type __aeabi_SIG_DFL, %function + .set __aeabi_SIG_DFL, 0 + + .global __aeabi_SIG_IGN + .hidden __aeabi_SIG_IGN + .type __aeabi_SIG_IGN, %function + .set __aeabi_SIG_IGN, 1 + + .global __aeabi_SIG_ERR + .hidden __aeabi_SIG_ERR + .type __aeabi_SIG_ERR, %function + .set __aeabi_SIG_ERR, -1 diff --git a/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c b/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c new file mode 100644 index 0000000..e657d38 --- /dev/null +++ b/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Because some objects in ld.so and libc.so are built with + -fexceptions, we end up with references to this personality + routine. However, these libraries are not linked against + libgcc_eh.a, so we need a dummy definition. This routine will + never actually be called. */ + +#include + +attribute_hidden +void +__aeabi_unwind_cpp_pr0 (void) +{ +} + +attribute_hidden +void +__aeabi_unwind_cpp_pr1 (void) +{ +} + +attribute_hidden +void +__aeabi_unwind_cpp_pr2 (void) +{ +} diff --git a/libc/sysdeps/linux/arm/bits/arm_asm.h b/libc/sysdeps/linux/arm/bits/arm_asm.h new file mode 100644 index 0000000..1d87df6 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/arm_asm.h @@ -0,0 +1,28 @@ +/* Various definitons used the the ARM uClibc assembly code. */ +#ifndef _ARM_ASM_H +#define _ARM_ASM_H + +#ifdef __thumb2__ +.thumb +.syntax unified +#define IT(t, cond) i##t cond +#else +/* XXX: This can be removed if/when we require an assembler that supports + unified assembly syntax. */ +#define IT(t, cond) +/* Code to return from a thumb function stub. */ +#ifdef __ARM_ARCH_4T__ +#define POP_RET pop {r2, pc} +#else +#define POP_RET pop {r2, r3}; bx r3 +#endif +#endif + +#if defined(__ARM_ARCH_6M__) +/* Force arm mode to flush out errors on M profile cores. */ +#undef IT +#define THUMB1_ONLY 1 +#endif + +#endif /* _ARM_ASM_H */ + diff --git a/libc/sysdeps/linux/arm/bits/armsigctx.h b/libc/sysdeps/linux/arm/bits/armsigctx.h new file mode 100644 index 0000000..4530cdb --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/armsigctx.h @@ -0,0 +1,73 @@ +/* Definition of `struct sigcontext' for Linux/ARM + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The format of struct sigcontext changed between 2.0 and 2.1 kernels. + Fortunately 2.0 puts a magic number in the first word and this is not + a legal value for `trap_no', so we can tell them apart. */ + +/* Early 2.2 and 2.3 kernels do not have the `fault_address' member in + the sigcontext structure. Unfortunately there is no reliable way + to test for its presence and this word will contain garbage for too-old + kernels. Versions 2.2.14 and 2.3.35 (plus later versions) are known to + include this element. */ + +#ifndef __ARMSIGCTX_H +#define __ARMSIGCTX_H 1 + +#include + +union k_sigcontext + { + struct + { + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + unsigned long int arm_r0; + unsigned long int arm_r1; + unsigned long int arm_r2; + unsigned long int arm_r3; + unsigned long int arm_r4; + unsigned long int arm_r5; + unsigned long int arm_r6; + unsigned long int arm_r7; + unsigned long int arm_r8; + unsigned long int arm_r9; + unsigned long int arm_r10; + unsigned long int arm_fp; + unsigned long int arm_ip; + unsigned long int arm_sp; + unsigned long int arm_lr; + unsigned long int arm_pc; + unsigned long int arm_cpsr; + unsigned long fault_address; + } v21; + struct + { + unsigned long int magic; + struct pt_regs reg; + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + } v20; +}; + +#define SIGCONTEXT_2_0_MAGIC 0x4B534154 + +#endif /* bits/armsigctx.h */ diff --git a/libc/sysdeps/linux/arm/bits/endian.h b/libc/sysdeps/linux/arm/bits/endian.h new file mode 100644 index 0000000..6e9967d --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/endian.h @@ -0,0 +1,19 @@ +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/* ARM can be either big or little endian. */ +#ifdef __ARMEB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* FPA floating point units are always big-endian, irrespective of the + CPU endianness. VFP floating point units use the same endianness + as the rest of the system. */ +#if defined __VFP_FP__ || defined __MAVERICK__ +# define __FLOAT_WORD_ORDER __BYTE_ORDER +#else +# define __FLOAT_WORD_ORDER __BIG_ENDIAN +#endif diff --git a/libc/sysdeps/linux/arm/bits/fcntl.h b/libc/sysdeps/linux/arm/bits/fcntl.h new file mode 100644 index 0000000..01d2d3d --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/fcntl.h @@ -0,0 +1,240 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995-1998, 2000, 2004, 2006, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/arm/bits/fenv.h b/libc/sysdeps/linux/arm/bits/fenv.h new file mode 100644 index 0000000..3764d77 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/fenv.h @@ -0,0 +1,99 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#ifdef __MAVERICK__ + +/* Define bits representing exceptions in the FPU status word. */ +enum + { + FE_INVALID = 1, +#define FE_INVALID FE_INVALID + FE_OVERFLOW = 4, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 8, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 16, +#define FE_INEXACT FE_INEXACT + }; + +/* Amount to shift by to convert an exception to a mask bit. */ +#define FE_EXCEPT_SHIFT 5 + +/* All supported exceptions. */ +#define FE_ALL_EXCEPT \ + (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +/* IEEE rounding modes. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x400, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 0x800, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0xc00, +#define FE_UPWARD FE_UPWARD + }; + +#define FE_ROUND_MASK (FE_UPWARD) + +#else /* !__MAVERICK__ */ + +/* Define bits representing exceptions in the FPU status word. */ +enum + { + FE_INVALID = 1, +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 2, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 4, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 8, +#define FE_UNDERFLOW FE_UNDERFLOW + }; + +/* Amount to shift by to convert an exception to a mask bit. */ +#define FE_EXCEPT_SHIFT 16 + +/* All supported exceptions. */ +#define FE_ALL_EXCEPT \ + (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) + +/* The ARM FPU basically only supports round-to-nearest. Other rounding + modes exist, but you have to encode them in the actual instruction. */ +#define FE_TONEAREST 0 + +#endif /* __MAVERICK__ */ + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef struct + { + unsigned long int __cw; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1l) diff --git a/libc/sysdeps/linux/arm/bits/huge_val.h b/libc/sysdeps/linux/arm/bits/huge_val.h new file mode 100644 index 0000000..a215f3c --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/huge_val.h @@ -0,0 +1,72 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + ARM version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +#ifndef __CONFIG_ARM_EABI__ +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) +#else +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x7ff0000000000000ULL }).__d) +#endif + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +#ifndef __CONFIG_ARM_EABI__ +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif +#else +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +# endif +#endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/arm/bits/kernel_stat.h b/libc/sysdeps/linux/arm/bits/kernel_stat.h new file mode 100644 index 0000000..ebac6f5 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/kernel_stat.h @@ -0,0 +1,76 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#define STAT_HAVE_NSEC 1 + +struct kernel_stat { +#if defined(__ARMEB__) + unsigned short st_dev; + unsigned short __pad1; +#else + unsigned long st_dev; +#endif + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; +#if defined(__ARMEB__) + unsigned short st_rdev; + unsigned short __pad2; +#else + unsigned long st_rdev; +#endif + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned char __pad0[4]; + +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long long st_ino; +#ifndef __ARM_EABI__ +} __attribute__((packed)); +#else +}; +#endif + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/arm/bits/kernel_types.h b/libc/sysdeps/linux/arm/bits/kernel_types.h new file mode 100644 index 0000000..766a306 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_ARM_POSIX_TYPES_H +#define __ARCH_ARM_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_ARM_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/arm/bits/mathdef.h b/libc/sysdeps/linux/arm/bits/mathdef.h new file mode 100644 index 0000000..22722e3 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/mathdef.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/arm/bits/mman.h b/libc/sysdeps/linux/arm/bits/mman.h new file mode 100644 index 0000000..828ec94 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/mman.h @@ -0,0 +1,103 @@ +/* Definitions for POSIX memory map interface. Linux/ARM version. + Copyright (C) 1997, 2000, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/arm/bits/setjmp.h b/libc/sysdeps/linux/arm/bits/setjmp.h new file mode 100644 index 0000000..ac52f12 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/setjmp.h @@ -0,0 +1,52 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. ARM version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* Jump buffer contains v1-v6, sl, fp, sp and pc. Other registers are not + saved. */ +#ifdef __ARM_EABI__ +/* The exact set of registers saved may depend on the particular core + in use, as some coprocessor registers may need to be saved. The C + Library ABI requires that the buffer be 8-byte aligned, and + recommends that the buffer contain 64 words. The first 28 words + are occupied by v1-v6, sl, fp, sp, pc, d8-d15, and fpscr. (Note + that d8-15 require 17 words, due to the use of fstmx.) */ +typedef int __jmp_buf[64] __attribute__((aligned (8))); +#elif defined __MAVERICK__ || defined __IWMMXT__ +typedef int __jmp_buf[34]; +#else +typedef int __jmp_buf[22]; +#endif +#endif + +#define __JMP_BUF_SP 8 + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP])) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/arm/bits/shm.h b/libc/sysdeps/linux/arm/bits/shm.h new file mode 100644 index 0000000..c89c00a --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize () << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/arm/bits/sigcontextinfo.h b/libc/sysdeps/linux/arm/bits/sigcontextinfo.h new file mode 100644 index 0000000..67167f9 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/sigcontextinfo.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define SIGCONTEXT int _a2, int _a3, int _a4, union k_sigcontext +#define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, + +/* The sigcontext structure changed between 2.0 and 2.1 kernels. On any + modern system we should be able to assume that the "new" format will be + in use. */ +#if LINUX_VERSION_CODE > 131328 + +#define GET_PC(ctx) ((void *) ctx.v21.arm_pc) +#define GET_FRAME(ctx) ADVANCE_STACK_FRAME ((void *) ctx.v21.arm_fp) +#define GET_STACK(ctx) ((void *) ctx.v21.arm_sp) + +#else + +#define GET_PC(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_pc : ctx.v21.arm_pc)) +#define GET_FRAME(ctx) \ + ADVANCE_STACK_FRAME((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_fp : ctx.v21.arm_fp)) +#define GET_STACK(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_sp : ctx.v21.arm_sp)) + +#endif + +#define ADVANCE_STACK_FRAME(frm) \ + ((struct layout *)frm - 1) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/arm/bits/stackinfo.h b/libc/sysdeps/linux/arm/bits/stackinfo.h new file mode 100644 index 0000000..2410ba9 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Arm the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/arm/bits/syscalls.h b/libc/sysdeps/linux/arm/bits/syscalls.h new file mode 100644 index 0000000..2d2e0f0 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/syscalls.h @@ -0,0 +1,203 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc-2.3.2/sysdeps/unix/sysv/linux/arm/sysdep.h +*/ + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifdef __ASSEMBLER__ + +/* Call a given syscall, with arguments loaded. For EABI, we must + save and restore r7 for the syscall number. Unlike the DO_CALL + macro in glibc, this macro does not load syscall arguments. */ +#undef DO_CALL +#if defined(__ARM_EABI__) +#define DO_CALL(syscall_name) \ + mov ip, r7; \ + ldr r7, =SYS_ify (syscall_name); \ + swi 0x0; \ + mov r7, ip; +#else +#define DO_CALL(syscall_name) \ + swi SYS_ify (syscall_name); +#endif + +#else + +#include + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + +#undef _syscall7 +#define _syscall7(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6,type7,arg7) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6,type7 arg7) \ +{ \ +return (type) (INLINE_SYSCALL(name, 7, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); \ +} + + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ + _inline_sys_result = (unsigned int) -1; \ + } \ + (int) _inline_sys_result; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL +#if !defined(__thumb__) +#if defined(__ARM_EABI__) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({unsigned int __sys_result; \ + { \ + register int _a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ + LOAD_ARGS_##nr (args) \ + _nr = SYS_ify(name); \ + __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ + : "=r" (_a1) \ + : "r" (_nr) ASM_ARGS_##nr \ + : "memory"); \ + __sys_result = _a1; \ + } \ + (int) __sys_result; }) +#else /* defined(__ARM_EABI__) */ + +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ unsigned int __sys_result; \ + { \ + register int _a1 __asm__ ("a1"); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("swi %1 @ syscall " #name \ + : "=r" (_a1) \ + : "i" (SYS_ify(name)) ASM_ARGS_##nr \ + : "memory"); \ + __sys_result = _a1; \ + } \ + (int) __sys_result; }) +#endif +#else /* !defined(__thumb__) */ +/* We can't use push/pop inside the asm because that breaks + unwinding (ie. thread cancellation). + */ +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ unsigned int __sys_result; \ + { \ + int _sys_buf[2]; \ + register int _a1 __asm__ ("a1"); \ + register int *_v3 __asm__ ("v3") = _sys_buf; \ + *_v3 = (int) (SYS_ify(name)); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("str r7, [v3, #4]\n" \ + "\tldr r7, [v3]\n" \ + "\tswi 0 @ syscall " #name "\n" \ + "\tldr r7, [v3, #4]" \ + : "=r" (_a1) \ + : "r" (_v3) ASM_ARGS_##nr \ + : "memory"); \ + __sys_result = _a1; \ + } \ + (int) __sys_result; }) +#endif /*!defined(__thumb__)*/ + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#define LOAD_ARGS_0() +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + _a1 = (int) (a1); \ + LOAD_ARGS_0 () +#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) +#define LOAD_ARGS_2(a1, a2) \ + register int _a2 __asm__ ("a2") = (int) (a2); \ + LOAD_ARGS_1 (a1) +#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + register int _a3 __asm__ ("a3") = (int) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + register int _a4 __asm__ ("a4") = (int) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + register int _v1 __asm__ ("v1") = (int) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + register int _v2 __asm__ ("v2") = (int) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2) +#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \ + register int _v3 __asm__ ("v3") = (int) (a7); \ + LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) +#define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3) + + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h new file mode 100644 index 0000000..0e33f9c --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h @@ -0,0 +1,42 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "bl abort" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#ifdef __ARM_EABI__ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +#else +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +#endif + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/arm/bits/wordsize.h b/libc/sysdeps/linux/arm/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/arm/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/arm/brk.c b/libc/sysdeps/linux/arm/brk.c new file mode 100644 index 0000000..4717990 --- /dev/null +++ b/libc/sysdeps/linux/arm/brk.c @@ -0,0 +1,42 @@ +/* brk system call for Linux/ARM. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(brk) + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk = (void*)INTERNAL_SYSCALL(brk, , 1, addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/arm/bsd-_setjmp.S b/libc/sysdeps/linux/arm/bsd-_setjmp.S new file mode 100644 index 0000000..a05570d --- /dev/null +++ b/libc/sysdeps/linux/arm/bsd-_setjmp.S @@ -0,0 +1,61 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global _setjmp +.type _setjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +_setjmp: + mov r1, #0 +#ifdef __PIC__ + ldr r3, .L_GOT + adr r2, .L_GOT + add r3, r2, r3 + + ldr r2, .L_GOT+4 /* __sigsetjmp */ + ldr r2, [r2, r3] + bx r2 + + .align 2 +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word __sigsetjmp(GOT) +#else + ldr r2, =__sigsetjmp + bx r2 +.pool +#endif +#else +_setjmp: + mov r1, #0 +#ifdef __PIC__ + b __sigsetjmp(PLT) +#else + b __sigsetjmp +#endif +#endif + +.size _setjmp,.-_setjmp diff --git a/libc/sysdeps/linux/arm/bsd-setjmp.S b/libc/sysdeps/linux/arm/bsd-setjmp.S new file mode 100644 index 0000000..d7ca72a --- /dev/null +++ b/libc/sysdeps/linux/arm/bsd-setjmp.S @@ -0,0 +1,61 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global setjmp +.type setjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +setjmp: + mov r1, #1 +#ifdef __PIC__ + ldr r3, .L_GOT + adr r2, .L_GOT + add r3, r2, r3 + + ldr r2, .L_GOT+4 /* __sigsetjmp */ + ldr r2, [r2, r3] + bx r2 + + .align 2 +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word __sigsetjmp(GOT) +#else + ldr r2, =__sigsetjmp + bx r2 +.pool +#endif +#else +setjmp: + mov r1, #1 +#ifdef __PIC__ + b __sigsetjmp(PLT) +#else + b __sigsetjmp +#endif +#endif + +.size setjmp,.-setjmp diff --git a/libc/sysdeps/linux/arm/clone.S b/libc/sysdeps/linux/arm/clone.S new file mode 100644 index 0000000..d948373 --- /dev/null +++ b/libc/sysdeps/linux/arm/clone.S @@ -0,0 +1,125 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Pat Beirne + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include +#include +#include + +#if defined(__NR_clone) +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.global clone +.type clone,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +clone: + @ sanity check args + cmp r0, #0 + beq __einval + cmp r1, #0 + beq __einval + + @ insert the args onto the new stack + sub r1, r1, #8 + str r3, [r1, #4] + @ save the function pointer as the 0th element + str r0, [r1] + + @ do the system call + @ get flags + mov r0, r2 + @ new sp is already in r1 + DO_CALL (clone) + movs a1, a1 + blt __error + beq 1f + bx lr +1: + + @ pick the function arg and call address off the stack and execute + ldr r0, [sp, #4] + ldr r1, [sp] + bl 2f @ blx r1 + + @ and we are done, passing the return value through r0 + bl HIDDEN_JUMPTARGET(_exit) + @ Should never return + b . + +2: + bx r1 + +__einval: + ldr r0, =-EINVAL +__error: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else +clone: + @ sanity check args + cmp r0, #0 + IT(te, ne) + cmpne r1, #0 + moveq r0, #-EINVAL + beq __error + + @ insert the args onto the new stack + sub r1, r1, #8 + str r3, [r1, #4] + @ save the function pointer as the 0th element + str r0, [r1] + + @ do the system call + @ get flags + mov r0, r2 + @ new sp is already in r1 + DO_CALL (clone) + movs a1, a1 + blt __error + IT(t, ne) +#if defined(__USE_BX__) + bxne lr +#else + movne pc, lr +#endif + + @ pick the function arg and call address off the stack and execute + ldr r0, [sp, #4] + mov lr, pc + ldr pc, [sp] + + @ and we are done, passing the return value through r0 + b HIDDEN_JUMPTARGET(_exit) + +__error: + b __syscall_error +#endif + +.size clone,.-clone + +#endif diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S new file mode 100644 index 0000000..082348e --- /dev/null +++ b/libc/sysdeps/linux/arm/crt1.S @@ -0,0 +1,254 @@ +/* Startup code for ARM & ELF + Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. + + Note that the code in the .init section has already been run. + This includes _init and _libc_init + + + At this entry point, most registers' values are unspecified, except: + + a1 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ +/* + For uClinux it looks like this: + + argc argument counter (integer) + argv char *argv[] + envp char *envp[] + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + +ARM register quick reference: + + Name Number ARM Procedure Calling Standard Role + + a1 r0 argument 1 / integer result / scratch register / argc + a2 r1 argument 2 / scratch register / argv + a3 r2 argument 3 / scratch register / envp + a4 r3 argument 4 / scratch register + v1 r4 register variable + v2 r5 register variable + v3 r6 register variable + v4 r7 register variable + v5 r8 register variable + sb/v6 r9 static base / register variable + sl/v7 r10 stack limit / stack chunk handle / reg. variable + fp r11 frame pointer + ip r12 scratch register / new-sb in inter-link-unit calls + sp r13 lower end of current stack frame + lr r14 link address / scratch register + pc r15 program counter +*/ + +#include +#include + +.text + .globl _start + .type _start,%function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + +#if defined(THUMB1_ONLY) +.thumb_func +_start: + /* Clear the frame pointer since this is the outermost frame. */ + mov r3, #0 + mov fp, r3 + +#ifdef __ARCH_USE_MMU__ + /* Pop argc off the stack and save a pointer to argv */ + pop {a2} + mov a3, sp +#else + /* + * uClinux/arm stacks look a little different from normal + * MMU-full Linux/arm stacks (for no good reason) + */ + /* pull argc and argv off the stack. We are going to push 3 + * arguments, so pop one here to maintain doubleword alignment. */ + pop {a2} + ldr a3, [sp] +#endif + + /* Push stack limit and rtld_fini */ + push {a1, a3} + +#ifdef __PIC__ + ldr r4, .L_GOT +.L_GOT_OFF: + adr r5, .L_GOT + add r4, r5, r4 + + ldr r5, .L_GOT+4 /* _fini */ + ldr a1, [r4, r5] + push {a1} /* Push _fini */ + + ldr r5, .L_GOT+8 /* _init */ + ldr a4, [r4, r5] + + ldr r5, .L_GOT+12 /* main */ + ldr a1, [r4, r5] + +#else + /* Fetch address of fini */ + ldr r4, =_fini + /* Push fini */ + push {r4} + + /* Set up the other arguments in registers */ + ldr a1, =main + ldr a4, =_init +#endif + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + /* Let the libc call main and exit with its return code. */ + bl __uClibc_main + + /* should never get here....*/ + bl abort +.pool + +#ifdef __PIC__ +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word _fini(GOT) + .word _init(GOT) + .word main(GOT) +#endif +#else /* !THUMB1_ONLY */ +_start: + /* Clear the frame pointer and link register since this is the outermost frame. */ + mov fp, #0 + mov lr, #0 + +#ifdef __ARCH_USE_MMU__ + /* Pop argc off the stack and save a pointer to argv */ + ldr a2, [sp], #4 + mov a3, sp +#else + /* + * uClinux/arm stacks look a little different from normal + * MMU-full Linux/arm stacks (for no good reason) + */ + /* pull argc and argv off the stack. We are going to push 3 + * arguments, so pop one here to maintain doubleword alignment. */ + ldr a2, [sp], #4 + ldr a3, [sp] +#endif + + /* Push stack limit */ + str a3, [sp, #-4]! + + /* Push rtld_fini */ + str a1, [sp, #-4]! + +#ifdef __PIC__ + ldr sl, .L_GOT +.L_GOT_OFF: + add sl, pc, sl + + ldr ip, .L_GOT+4 /* _fini */ + ldr a1, [sl, ip] + str a1, [sp, #-4]! /* Push _fini */ + + ldr ip, .L_GOT+8 /* _init */ + ldr a4, [sl, ip] + + ldr ip, .L_GOT+12 /* main */ + ldr a1, [sl, ip] + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + /* Let the libc call main and exit with its return code. */ + b __uClibc_main(PLT) +#else + /* Fetch address of fini */ + ldr ip, =_fini + /* Push fini */ + str ip, [sp, #-4]! + + /* Set up the other arguments in registers */ + ldr a1, =main + ldr a4, =_init + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + + /* Let the libc call main and exit with its return code. */ + b __uClibc_main +#endif + + /* should never get here....*/ + bl abort + +#ifdef __PIC__ +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-(.L_GOT_OFF+8) + .word _fini(GOT) + .word _init(GOT) + .word main(GOT) +#endif +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/arm/crti.S b/libc/sysdeps/linux/arm/crti.S new file mode 100644 index 0000000..e335b71 --- /dev/null +++ b/libc/sysdeps/linux/arm/crti.S @@ -0,0 +1,87 @@ + .file "initfini.c" + +#include + .section .init + .global _init + .type _init, %function +#if defined __thumb__ + .align 1 + .thumb + .thumb_func +_init: + push {r4-r7, lr} +#else + .align 2 + .arm +_init: + @ gcc 3.3.2 didn't create a stack frame, gcc 3.4.4 does - + @ presumably 3.4.4 can put stuff into .init which requires + @ the arguments to be saved. This code is copied from 3.4.4 + mov ip, sp + stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} + sub fp, ip, #4 +#endif + + + .section .fini + .global _fini + .type _fini, %function +#if defined __thumb__ + .align 1 + .thumb + .thumb_func +_fini: + push {r4-r7, lr} +#else + .align 2 + .arm +_fini: + mov ip, sp + stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} + sub fp, ip, #4 +#endif + + +#if (defined __thumb__ || defined __THUMB_INTERWORK__) && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__) + @ To support thumb code it is currently necessary to have the _call_via_rX + @ functions exposed to the linker for any program or shared library. PLT + @ references are inadequate - the PLT zaps ip and therefore breaks _call_via_ip + @ (and the compiler does generate this). It is simpler to put all the + @ required code in here - it only amounts to 60 bytes overhead. + @NOTE: it would be better to have the compiler generate this stuff as + @ required... + .section ".text" + .align 0 + .force_thumb + +.macro call_via register + .global _call_via_\register + .type _call_via_\register, %function + .weak _call_via_\register + .hidden _call_via_\register + .thumb_func +_call_via_\register: + bx \register + nop + .size _call_via_\register, . - _call_via_\register +.endm + + @ and calls for the 15 general purpose registers (2 bytes each). + call_via r0 + call_via r1 + call_via r2 + call_via r3 + call_via r4 + call_via r5 + call_via r6 + call_via r7 + call_via r8 + call_via r9 + call_via sl + call_via fp + call_via ip + call_via sp + call_via lr +#endif + + .ident "GCC: (GNU) 3.3.2 20031005 (Debian prerelease)" diff --git a/libc/sysdeps/linux/arm/crtn.S b/libc/sysdeps/linux/arm/crtn.S new file mode 100644 index 0000000..de01b38 --- /dev/null +++ b/libc/sysdeps/linux/arm/crtn.S @@ -0,0 +1,35 @@ + .file "initfini.c" + +#include + .section .init + .global _init + .type _init, %function +#if defined __thumb__ + .align 1 + .thumb + @ this will not work on ARMv4T, but lots of stuff + @ in here won't work there anyway... + pop {r4-r7, pc} +#else + .align 2 + .arm + ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} +#endif + .size _init, .-_init + + .section .fini + .global _fini + .type _fini, %function +#if defined __thumb__ + .align 1 + .thumb + pop {r4-r7, pc} +#else + .align 2 + .arm + ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} +#endif + .size _fini, .-_fini + + @ In fact this is modified to 3.4.4 + .ident "GCC: (GNU) 3.3.2 20031005 (Debian prerelease)" diff --git a/libc/sysdeps/linux/arm/find_exidx.c b/libc/sysdeps/linux/arm/find_exidx.c new file mode 100644 index 0000000..9e4f401 --- /dev/null +++ b/libc/sysdeps/linux/arm/find_exidx.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +struct unw_eh_callback_data +{ + _Unwind_Ptr pc; + _Unwind_Ptr exidx_start; + int exidx_len; +}; + + +/* Callback to determins if the PC lies within an object, and remember the + location of the exception index table if it does. */ + +static int +find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr) +{ + struct unw_eh_callback_data * data; + const ElfW(Phdr) *phdr; + int i; + int match; + _Unwind_Ptr load_base; + + data = (struct unw_eh_callback_data *) ptr; + load_base = info->dlpi_addr; + phdr = info->dlpi_phdr; + + match = 0; + for (i = info->dlpi_phnum; i > 0; i--, phdr++) + { + if (phdr->p_type == PT_LOAD) + { + _Unwind_Ptr vaddr = phdr->p_vaddr + load_base; + if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz) + match = 1; + } + else if (phdr->p_type == PT_ARM_EXIDX) + { + data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base); + data->exidx_len = phdr->p_memsz; + } + } + + return match; +} + + +/* Find the exception index table containing PC. */ + +_Unwind_Ptr +__gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount) +{ + struct unw_eh_callback_data data; + + data.pc = pc; + data.exidx_start = 0; + if (dl_iterate_phdr (find_exidx_callback, &data) <= 0) + return 0; + + *pcount = data.exidx_len / 8; + return data.exidx_start; +} diff --git a/libc/sysdeps/linux/arm/fpu_control.h b/libc/sysdeps/linux/arm/fpu_control.h new file mode 100644 index 0000000..1170c9e --- /dev/null +++ b/libc/sysdeps/linux/arm/fpu_control.h @@ -0,0 +1,203 @@ +/* FPU control word definitions. ARM version. + Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#ifdef __VFP_FP__ + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x00000100 /* invalid operation */ +#define _FPU_MASK_ZM 0x00000200 /* divide by zero */ +#define _FPU_MASK_OM 0x00000400 /* overflow */ +#define _FPU_MASK_UM 0x00000800 /* underflow */ +#define _FPU_MASK_PM 0x00001000 /* inexact */ + +/* Some bits in the FPSCR are not yet defined. They must be preserved when + modifying the contents. */ +#define _FPU_RESERVED 0x0e08e0e0 +#define _FPU_DEFAULT 0x00000000 +/* Default + exceptions enabled. */ +#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00) + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +/* This is fmrx %0, fpscr. */ +#define _FPU_GETCW(cw) \ + __asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw)) +/* This is fmxr fpscr, %0. */ +#define _FPU_SETCW(cw) \ + __asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw)) + +#elif defined __MAVERICK__ + +/* DSPSC register: (from EP9312 User's Guide) + * + * bits 31..29 - DAID + * bits 28..26 - HVID + * bits 25..24 - RSVD + * bit 23 - ISAT + * bit 22 - UI + * bit 21 - INT + * bit 20 - AEXC + * bits 19..18 - SAT + * bits 17..16 - FCC + * bit 15 - V + * bit 14 - FWDEN + * bit 13 - Invalid + * bit 12 - Denorm + * bits 11..10 - RM + * bits 9..5 - IXE, UFE, OFE, RSVD, IOE + * bits 4..0 - IX, UF, OF, RSVD, IO + */ + +/* masking of interrupts */ +#define _FPU_MASK_IM (1 << 5) /* invalid operation */ +#define _FPU_MASK_ZM 0 /* divide by zero */ +#define _FPU_MASK_OM (1 << 7) /* overflow */ +#define _FPU_MASK_UM (1 << 8) /* underflow */ +#define _FPU_MASK_PM (1 << 9) /* inexact */ +#define _FPU_MASK_DM 0 /* denormalized operation */ + +#define _FPU_RESERVED 0xfffff000 /* These bits are reserved. */ + +#define _FPU_DEFAULT 0x00b00000 /* Default value. */ +#define _FPU_IEEE 0x00b003a0 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) ({ \ + register int __t1, __t2; \ + \ + __asm__ __volatile__ ( \ + "cfmvr64l %1, mvdx0\n\t" \ + "cfmvr64h %2, mvdx0\n\t" \ + "cfmv32sc mvdx0, dspsc\n\t" \ + "cfmvr64l %0, mvdx0\n\t" \ + "cfmv64lr mvdx0, %1\n\t" \ + "cfmv64hr mvdx0, %2" \ + : "=r" (cw), "=r" (__t1), "=r" (__t2) \ + ); \ +}) + +#define _FPU_SETCW(cw) ({ \ + register int __t0, __t1, __t2; \ + \ + __asm__ __volatile__ ( \ + "cfmvr64l %1, mvdx0\n\t" \ + "cfmvr64h %2, mvdx0\n\t" \ + "cfmv64lr mvdx0, %0\n\t" \ + "cfmvsc32 dspsc, mvdx0\n\t" \ + "cfmv64lr mvdx0, %1\n\t" \ + "cfmv64hr mvdx0, %2" \ + : "=r" (__t0), "=r" (__t1), "=r" (__t2) \ + : "0" (cw) \ + ); \ +}) + +#else /* !__MAVERICK__ */ + +/* We have a slight terminology confusion here. On the ARM, the register + * we're interested in is actually the FPU status word - the FPU control + * word is something different (which is implementation-defined and only + * accessible from supervisor mode.) + * + * The FPSR looks like this: + * + * 31-24 23-16 15-8 7-0 + * | system ID | trap enable | system control | exception flags | + * + * We ignore the system ID bits; for interest's sake they are: + * + * 0000 "old" FPE + * 1000 FPPC hardware + * 0001 FPE 400 + * 1001 FPA hardware + * + * The trap enable and exception flags are both structured like this: + * + * 7 - 5 4 3 2 1 0 + * | reserved | INX | UFL | OFL | DVZ | IVO | + * + * where a `1' bit in the enable byte means that the trap can occur, and + * a `1' bit in the flags byte means the exception has occurred. + * + * The exceptions are: + * + * IVO - invalid operation + * DVZ - divide by zero + * OFL - overflow + * UFL - underflow + * INX - inexact (do not use; implementations differ) + * + * The system control byte looks like this: + * + * 7-5 4 3 2 1 0 + * | reserved | AC | EP | SO | NE | ND | + * + * where the bits mean + * + * ND - no denormalised numbers (force them all to zero) + * NE - enable NaN exceptions + * SO - synchronous operation + * EP - use expanded packed-decimal format + * AC - use alternate definition for C flag on compare operations + */ + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x00010000 /* invalid operation */ +#define _FPU_MASK_ZM 0x00020000 /* divide by zero */ +#define _FPU_MASK_OM 0x00040000 /* overflow */ +#define _FPU_MASK_UM 0x00080000 /* underflow */ +#define _FPU_MASK_PM 0x00100000 /* inexact */ +#define _FPU_MASK_DM 0x00000000 /* denormalized operation */ + +/* The system id bytes cannot be changed. + Only the bottom 5 bits in the trap enable byte can be changed. + Only the bottom 5 bits in the system control byte can be changed. + Only the bottom 5 bits in the exception flags are used. + The exception flags are set by the fpu, but can be zeroed by the user. */ +#define _FPU_RESERVED 0xffe0e0e0 /* These bits are reserved. */ + +/* The fdlibm code requires strict IEEE double precision arithmetic, + no interrupts for exceptions, rounding to nearest. Changing the + rounding mode will break long double I/O. Turn on the AC bit, + the compiler generates code that assumes it is on. */ +#define _FPU_DEFAULT 0x00001000 /* Default value. */ +#define _FPU_IEEE 0x001f1000 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("rfs %0" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("wfs %0" : : "r" (cw)) + +#endif /* __MAVERICK__ */ + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/libc/sysdeps/linux/arm/ioperm.c b/libc/sysdeps/linux/arm/ioperm.c new file mode 100644 index 0000000..708e8ec --- /dev/null +++ b/libc/sysdeps/linux/arm/ioperm.c @@ -0,0 +1,258 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell, based on the Alpha version by + David Mosberger. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* I/O port access on the ARM is something of a fiction. What we do is to + map an appropriate area of /dev/mem into user space so that a program + can blast away at the hardware in such a way as to generate I/O cycles + on the bus. To insulate user code from dependencies on particular + hardware we don't allow calls to inb() and friends to be inlined, but + force them to come through code in here every time. Performance-critical + registers tend to be memory mapped these days so this should be no big + problem. */ + +/* Once upon a time this file used mprotect to enable and disable + access to particular areas of I/O space. Unfortunately the + mprotect syscall also has the side effect of enabling caching for + the area affected (this is a kernel limitation). So we now just + enable all the ports all of the time. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +libc_hidden_proto(ioperm) + +libc_hidden_proto(readlink) +libc_hidden_proto(mmap) +libc_hidden_proto(sscanf) +libc_hidden_proto(fscanf) +libc_hidden_proto(fprintf) +libc_hidden_proto(fgets) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +/* Experimentally off - libc_hidden_proto(strcmp) */ +libc_hidden_proto(open) +libc_hidden_proto(close) + +#include + +#define PATH_ARM_SYSTYPE "/etc/arm_systype" +#define PATH_CPUINFO "/proc/cpuinfo" + +#define MAX_PORT 0x10000 + +static struct { + unsigned long int base; + unsigned long int io_base; + unsigned int shift; + unsigned int initdone; /* since all the above could be 0 */ +} io; + +#define IO_BASE_FOOTBRIDGE 0x7c000000 +#define IO_SHIFT_FOOTBRIDGE 0 + +static struct platform { + const char *name; + unsigned long int io_base; + unsigned int shift; +} platform[] = { + /* All currently supported platforms are in fact the same. :-) */ + {"Chalice-CATS", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"DEC-EBSA285", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Corel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Rebel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, +}; + +#define IO_ADDR(port) (io.base + ((port) << io.shift)) + +/* + * Initialize I/O system. There are several ways to get the information + * we need. Each is tried in turn until one succeeds. + * + * 1. Sysctl (CTL_BUS, BUS_ISA, ISA_*). This is the preferred method + * but not all kernels support it. + * + * 2. Read the value (not the contents) of symlink PATH_ARM_SYSTYPE. + * - If it matches one of the entries in the table above, use the + * corresponding values. + * - If it begins with a number, assume this is a previously + * unsupported system and the values encode, in order, + * ",". + * + * 3. Lookup the "system type" field in /proc/cpuinfo. Again, if it + * matches an entry in the platform[] table, use the corresponding + * values. + * + * 4. BUS_ISA is changed to CTL_BUS_ISA (for kernel since 2.4.23). + */ + +static int +init_iosys (void) +{ + char systype[256]; + int i, n; + +#if LINUX_VERSION_CODE < 132119 + static int iobase_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_BASE }; + static int ioshift_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_SHIFT }; +#else + static int iobase_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_BASE }; + static int ioshift_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_SHIFT }; +#endif + + size_t len = sizeof(io.base); + + if (! sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0) + && ! sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0)) { + io.initdone = 1; + return 0; + } + + n = readlink (PATH_ARM_SYSTYPE, systype, sizeof (systype) - 1); + if (n > 0) { + systype[n] = '\0'; + if (isdigit (systype[0])) { + if (sscanf (systype, "%li,%i", &io.io_base, &io.shift) == 2) { + io.initdone = 1; + return 0; + } + /* else we're likely going to fail with the system match below */ + } + } + else { + FILE * fp; + + fp = fopen (PATH_CPUINFO, "r"); + if (! fp) + return -1; + while ((n = fscanf (fp, "Hardware\t: %256[^\n]\n", systype)) != EOF) { + if (n == 1) + break; + else + fgets (systype, 256, fp); + } + fclose (fp); + + if (n == EOF) { + /* this can happen if the format of /proc/cpuinfo changes... */ + fprintf (stderr, "ioperm: Unable to determine system type.\n" + "\t(May need " PATH_ARM_SYSTYPE " symlink?)\n"); + __set_errno (ENODEV); + return -1; + } + } + + /* translate systype name into i/o system: */ + for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) { + if (strcmp (platform[i].name, systype) == 0) { + io.shift = platform[i].shift; + io.io_base = platform[i].io_base; + io.initdone = 1; + return 0; + } + } + + /* systype is not a known platform name... */ + __set_errno (EINVAL); + return -1; +} + +int ioperm (unsigned long int from, unsigned long int num, int turn_on) +{ + if (! io.initdone && init_iosys () < 0) + return -1; + + /* this test isn't as silly as it may look like; consider overflows! */ + if (from >= MAX_PORT || from + num > MAX_PORT) { + __set_errno (EINVAL); + return -1; + } + + if (turn_on) { + if (! io.base) { + int fd; + + fd = open ("/dev/mem", O_RDWR); + if (fd < 0) + return -1; + + io.base = (unsigned long int) mmap (0, MAX_PORT << io.shift, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, io.io_base); + close (fd); + if ((long) io.base == -1) + return -1; + } + } + + return 0; +} +libc_hidden_def(ioperm) + + +void +outb(unsigned char b, unsigned long int port) +{ + *((__volatile__ unsigned char *)(IO_ADDR (port))) = b; +} + + +void +outw(unsigned short b, unsigned long int port) +{ + *((__volatile__ unsigned short *)(IO_ADDR (port))) = b; +} + + +void +outl(unsigned long b, unsigned long int port) +{ + *((__volatile__ unsigned long *)(IO_ADDR (port))) = b; +} + + +unsigned char +inb (unsigned long int port) +{ + return *((__volatile__ unsigned char *)(IO_ADDR (port))); +} + + +unsigned short int +inw(unsigned long int port) +{ + return *((__volatile__ unsigned short *)(IO_ADDR (port))); +} + + +unsigned long int +inl(unsigned long int port) +{ + return *((__volatile__ unsigned long *)(IO_ADDR (port))); +} diff --git a/libc/sysdeps/linux/arm/iopl.c b/libc/sysdeps/linux/arm/iopl.c new file mode 100644 index 0000000..654a415 --- /dev/null +++ b/libc/sysdeps/linux/arm/iopl.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell, based on the Alpha version by + David Mosberger. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libc_hidden_proto(ioperm) + +#define MAX_PORT 0x10000 + +int iopl(int level) +{ + if (level > 3) { + __set_errno(EINVAL); + return -1; + } + if (level) + return ioperm(0, MAX_PORT, 1); + return 0; +} diff --git a/libc/sysdeps/linux/arm/mmap.c b/libc/sysdeps/linux/arm/mmap.c new file mode 100644 index 0000000..0a74638 --- /dev/null +++ b/libc/sysdeps/linux/arm/mmap.c @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * _mmap() for uClibc + * + * Copyright (C) 2000-2004 by Erik Andersen + * + * GNU Library General Public License (LGPL) version 2 or later. + */ +#include +#include +#include +#include + +#if defined (__NR_mmap) || defined (__NR_mmap2) + +libc_hidden_proto (mmap) +#if defined (__UCLIBC_MMAP_HAS_6_ARGS__) && defined (__NR_mmap) +#define __NR__mmap __NR_mmap +static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, __off_t, offset) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, offset); +} + +#elif defined (__NR_mmap2) +#define __NR__mmap __NR_mmap2 + +#ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +#endif + +static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, __off_t, offset); +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + /* check if offset is page aligned */ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) + { + __set_errno(EINVAL); + return MAP_FAILED; + } +#ifdef __USE_FILE_OFFSET64 + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, ((__u_quad_t) offset >> MMAP2_PAGE_SHIFT)); +#else + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, ((__u_long) offset >> MMAP2_PAGE_SHIFT)); +#endif +} +#elif defined (__NR_mmap) +# define __NR__mmap __NR_mmap +static __inline__ _syscall1(__ptr_t, _mmap, unsigned long *, buffer) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) len; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (__ptr_t) _mmap(buffer); +} +#endif +libc_hidden_def (mmap) +#else +# error "Your architecture doesn't seem to provide mmap() !?" +#endif diff --git a/libc/sysdeps/linux/arm/mmap64.S b/libc/sysdeps/linux/arm/mmap64.S new file mode 100644 index 0000000..7071541 --- /dev/null +++ b/libc/sysdeps/linux/arm/mmap64.S @@ -0,0 +1,142 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 + +/* The mmap2 system call takes six arguments, all in registers. */ +.text +.global mmap64 +.type mmap64,%function +.align 2 + +#ifdef __ARM_EABI__ +#if defined(THUMB1_ONLY) +.thumb_func +mmap64: +#ifdef __ARMEB__ +/* Offsets are after pushing 3 words. */ +# define LOW_OFFSET 12 + 8 + 4 +# define HIGH_OFFSET 12 + 8 + 0 +#else +# define LOW_OFFSET 12 + 8 + 0 +# define HIGH_OFFSET 12 + 8 + 4 +#endif + push {r4, r5, r6} + ldr r6, [sp, $LOW_OFFSET] + ldr r5, [sp, $HIGH_OFFSET] + lsl r4, r6, #20 @ check that offset is page-aligned + bne .Linval + lsr r4, r5, #12 @ check for overflow + bne .Linval + @ compose page offset + lsr r6, r6, #12 + lsl r5, r5, #20 + orr r5, r5, r6 + ldr r4, [sp, #8] @ load fd + DO_CALL (mmap2) + ldr r1, =0xfffff000 + cmp r0, r1 + bcs .Lerror + bx lr +.Linval: + ldr r0, =-EINVAL + pop {r4, r5, r6} +.Lerror: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else /* !THUMB1_ONLY */ +mmap64: +#ifdef __ARMEB__ +# define LOW_OFFSET 8 + 4 +/* The initial + 4 is for the stack postdecrement. */ +# define HIGH_OFFSET 4 + 8 + 0 +#else +# define LOW_OFFSET 8 + 0 +# define HIGH_OFFSET 4 + 8 + 4 +#endif + ldr ip, [sp, $LOW_OFFSET] + str r5, [sp, #-4]! + ldr r5, [sp, $HIGH_OFFSET] + str r4, [sp, #-4]! + movs r4, ip, lsl $20 @ check that offset is page-aligned + mov ip, ip, lsr $12 + IT(t, eq) + moveqs r4, r5, lsr $12 @ check for overflow + bne .Linval + ldr r4, [sp, $8] @ load fd + orr r5, ip, r5, lsl $20 @ compose page offset + DO_CALL (mmap2) + cmn r0, $4096 + ldmfd sp!, {r4, r5} + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + b __syscall_error +.Linval: + mov r0, $-EINVAL + ldmfd sp!, {r4, r5} + b __syscall_error +#endif +#else /* !__ARM_EABI__ */ +mmap64: + stmfd sp!, {r4, r5, lr} + ldr r5, [sp, $16] + ldr r4, [sp, $12] + movs ip, r5, lsl $20 @ check that offset is page-aligned + bne .Linval + ldr ip, [sp, $20] + mov r5, r5, lsr $12 + orr r5, r5, ip, lsl $20 @ compose page offset + movs ip, ip, lsr $12 + bne .Linval @ check for overflow + mov ip, r0 + DO_CALL (mmap2) + cmn r0, $4096 + ldmccfd sp!, {r4, r5, pc} + cmn r0, $ENOSYS + ldmnefd sp!, {r4, r5, lr} + bne __error + /* The current kernel does not support mmap2. Fall back to plain + mmap if the offset is small enough. */ + ldr r5, [sp, $20] + mov r0, ip @ first arg was clobbered + teq r5, $0 + ldmeqfd sp!, {r4, r5, lr} + beq HIDDEN_JUMPTARGET(mmap) +.Linval: + mov r0, $-EINVAL + ldmfd sp!, {r4, r5, lr} + b __error + +__error: + b __syscall_error +#endif +.size mmap64,.-mmap64 + +#endif diff --git a/libc/sysdeps/linux/arm/posix_fadvise.c b/libc/sysdeps/linux/arm/posix_fadvise.c new file mode 100644 index 0000000..bb4ac7b --- /dev/null +++ b/libc/sysdeps/linux/arm/posix_fadvise.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for ARM uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include +#if defined __NR_arm_fadvise64_64 +/* This is for the ARM version of fadvise64_64 which swaps the params + * * about to avoid having ABI compat issues + * */ +#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 +int __libc_posix_fadvise(int fd, off_t offset, off_t len, int advise) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, + __LONG_LONG_PAIR ((long)(offset >> 32), (long)offset), + __LONG_LONG_PAIR ((long)(len >> 32), (long)len)); + + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; + +} +weak_alias(__libc_posix_fadvise, posix_fadvise); +#else +int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) +{ + return ENOSYS; +} +#endif + diff --git a/libc/sysdeps/linux/arm/posix_fadvise64.c b/libc/sysdeps/linux/arm/posix_fadvise64.c new file mode 100644 index 0000000..479b0c5 --- /dev/null +++ b/libc/sysdeps/linux/arm/posix_fadvise64.c @@ -0,0 +1,46 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for ARM uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#if defined __NR_arm_fadvise64_64 +/* This is for the ARM version of fadvise64_64 which swaps the params + * about to avoid having ABI compat issues + */ +#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 +int __libc_posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, + __LONG_LONG_PAIR ((long)(offset >> 32), (long)offset), + __LONG_LONG_PAIR ((long)(len >> 32), (long)len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + if (INTERNAL_SYSCALL_ERRNO (ret, err) != ENOSYS) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} +weak_alias(__libc_posix_fadvise64, posix_fadvise64); +#else +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + return ENOSYS; +} +#endif +#endif diff --git a/libc/sysdeps/linux/arm/setjmp.S b/libc/sysdeps/linux/arm/setjmp.S new file mode 100644 index 0000000..2df7d55 --- /dev/null +++ b/libc/sysdeps/linux/arm/setjmp.S @@ -0,0 +1,101 @@ +/* setjmp for ARM. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +.global __sigsetjmp +.type __sigsetjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +__sigsetjmp: + push {r3, r4, r5, r6, r7, lr} + mov ip, r0 + stmia r0!, {r4, r5, r6, r7} + mov r2, r8 + mov r3, r9 + mov r4, sl + mov r5, fp + add r6, sp, #(6 * 4) + mov r7, lr + stmia r0!, {r2, r3, r4, r5, r6, r7} + + mov r0, ip + bl __sigjmp_save + pop {r3, r4, r5, r6, r7, pc} + +#else +__sigsetjmp: + /* Save registers */ + mov ip, r0 +#if defined(__thumb2__) + stmia ip!, {v1-v6, sl, fp} + movs r2, sp + stmia ip!, {r2, lr} +#else + /* Save registers */ + stmia ip!, {v1-v6, sl, fp, sp, lr} +#endif +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +# ifdef __VFP_FP__ + /* Store the VFP registers. */ + /* Following instruction is fstmiax ip!, {d8-d15}. */ + stc p11, cr8, [r12], #68 + /* Store the floating-point status register. */ + /* Following instruction is fmrx r2, fpscr. */ + mrc p10, 7, r2, cr1, cr0, 0 + str r2, [ip], #4 +# elif defined __MAVERICK__ + cfstrd mvd4, [ip], #8 ; nop + cfstrd mvd5, [ip], #8 ; nop + cfstrd mvd6, [ip], #8 ; nop + cfstrd mvd7, [ip], #8 ; nop + cfstrd mvd8, [ip], #8 ; nop + cfstrd mvd9, [ip], #8 ; nop + cfstrd mvd10, [ip], #8 ; nop + cfstrd mvd11, [ip], #8 ; nop + cfstrd mvd12, [ip], #8 ; nop + cfstrd mvd13, [ip], #8 ; nop + cfstrd mvd14, [ip], #8 ; nop + cfstrd mvd15, [ip], #8 +# else + sfmea f4, 4, [ip]! +# endif +#endif +#ifdef __IWMMXT__ + /* Save the call-preserved iWMMXt registers. */ + /* Following instructions are wstrd wr10, [ip], #8 (etc.) */ + stcl p1, cr10, [r12], #8 + stcl p1, cr11, [r12], #8 + stcl p1, cr12, [r12], #8 + stcl p1, cr13, [r12], #8 + stcl p1, cr14, [r12], #8 + stcl p1, cr15, [r12], #8 +#endif + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + B __sigjmp_save(PLT) +#else + B __sigjmp_save +#endif +#endif + +.size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/arm/sigaction.c b/libc/sysdeps/linux/arm/sigaction.c new file mode 100644 index 0000000..552ac17 --- /dev/null +++ b/libc/sysdeps/linux/arm/sigaction.c @@ -0,0 +1,126 @@ +/* Copyright (C) 1997,1998,1999,2000,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 +extern void __default_sa_restorer(void); +extern void __default_rt_sa_restorer(void); + +extern __typeof(sigaction) __libc_sigaction; + +/* When RT signals are in use we need to use a different return stub. */ +#ifdef __NR_rt_sigreturn +#define choose_restorer(flags) \ + (flags & SA_SIGINFO) ? __default_rt_sa_restorer \ + : __default_sa_restorer +#else +#define choose_restorer(flags) \ + __default_sa_restorer +#endif + +#ifdef __NR_rt_sigaction + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; + } else { + kact.sa_restorer = choose_restorer (kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + } +# endif + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = __syscall_rt_sigaction(sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; +} + + +#else + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; + } else { + kact.sa_restorer = choose_restorer (kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + } +# endif + } + result = __syscall_sigaction(sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; +} + +#endif + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/libc/sysdeps/linux/arm/sigrestorer.S b/libc/sysdeps/linux/arm/sigrestorer.S new file mode 100644 index 0000000..79728fd --- /dev/null +++ b/libc/sysdeps/linux/arm/sigrestorer.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* If no SA_RESTORER function was specified by the application we use + one of these. This avoids the need for the kernel to synthesise a return + instruction on the stack, which would involve expensive cache flushes. + + Nowadays (2.6 series, and somewhat earlier) the kernel uses a high page + for signal trampolines, so the cache flushes are not an issue. But since + we do not have a vDSO, continue to use these so that we can provide + unwind information. + + Start the unwind tables at least one instruction before the signal + trampoline, because the unwinder will assume we are returning after + a call site. + + The signal frame layout changed in 2.6.18. */ + +.global __default_sa_restorer +.type __default_sa_restorer,%function +.align 2 +#ifdef __ARM_EABI__ +#ifdef __thumb__ +.thumb_func +#endif + .fnstart + .save {r0-r15} +#if LINUX_VERSION_CODE >= 0x020612 + .pad #32 +#else + .pad #12 +#endif + nop +__default_sa_restorer: + mov r7, $SYS_ify(sigreturn) + swi 0x0 + .fnend +#else +__default_sa_restorer: + DO_CALL (sigreturn) +#endif + + +#ifdef __NR_rt_sigreturn + +.global __default_rt_sa_restorer +.type __default_rt_sa_restorer,%function +.align 2 +#ifdef __ARM_EABI__ +#ifdef __thumb__ +.thumb_func +#endif + .fnstart + .save {r0-r15} +#if LINUX_VERSION_CODE >= 0x020612 + .pad #160 +#else + .pad #168 +#endif + nop +__default_rt_sa_restorer: + mov r7, $SYS_ify(rt_sigreturn) + swi 0x0 + .fnend +#else +__default_rt_sa_restorer: + DO_CALL (rt_sigreturn) +#endif + +#endif diff --git a/libc/sysdeps/linux/arm/sys/elf.h b/libc/sysdeps/linux/arm/sys/elf.h new file mode 100644 index 0000000..faa7310 --- /dev/null +++ b/libc/sysdeps/linux/arm/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* sys/elf.h */ diff --git a/libc/sysdeps/linux/arm/sys/io.h b/libc/sysdeps/linux/arm/sys/io.h new file mode 100644 index 0000000..6863990 --- /dev/null +++ b/libc/sysdeps/linux/arm/sys/io.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/arm/sys/procfs.h b/libc/sysdeps/linux/arm/sys/procfs.h new file mode 100644 index 0000000..3b37363 --- /dev/null +++ b/libc/sysdeps/linux/arm/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/arm/sys/ucontext.h b/libc/sysdeps/linux/arm/sys/ucontext.h new file mode 100644 index 0000000..9ecff7b --- /dev/null +++ b/libc/sysdeps/linux/arm/sys/ucontext.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1998, 1999, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/ARM ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15 +#define R15 R15 +}; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. This only describes + the core registers; coprocessor registers get saved elsewhere + (e.g. in uc_regspace, or somewhere unspecified on the stack + during non-RT signal handlers). */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + unsigned long uc_regspace[128] __attribute__((__aligned__(8))); + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/arm/sys/user.h b/libc/sysdeps/linux/arm/sys/user.h new file mode 100644 index 0000000..3fae43f --- /dev/null +++ b/libc/sysdeps/linux/arm/sys/user.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +struct user_fpregs +{ + struct fp_reg + { + unsigned int sign1:1; + unsigned int unused:15; + unsigned int sign2:1; + unsigned int exponent:14; + unsigned int j:1; + unsigned int mantissa1:31; + unsigned int mantissa0:32; + } fpregs[8]; + unsigned int fpsr:32; + unsigned int fpcr:32; + unsigned char ftype[8]; + unsigned int init_flag; +}; + +struct user_regs +{ + unsigned long int uregs[18]; +}; + +struct user +{ + struct user_regs regs; /* General registers */ + int u_fpvalid; /* True if math co-processor being used. */ + + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack. */ + + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + struct user_regs *u_ar0; /* help gdb to find the general registers. */ + + unsigned long magic; /* uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ + int u_debugreg[8]; + struct user_fpregs u_fp; /* Floating point registers */ + struct user_fpregs *u_fp0; /* help gdb to find the FP registers. */ +}; + +#endif /* sys/user.h */ diff --git a/libc/sysdeps/linux/arm/syscall-eabi.S b/libc/sysdeps/linux/arm/syscall-eabi.S new file mode 100644 index 0000000..b931882 --- /dev/null +++ b/libc/sysdeps/linux/arm/syscall-eabi.S @@ -0,0 +1,73 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* In the EABI syscall interface, we don't need a special syscall to + implement syscall(). It won't work reliably with 64-bit arguments + (but that is true on many modern platforms). */ + +.text +.global syscall +.type syscall,%function +.align 4 +#if defined(THUMB1_ONLY) +.thumb_func +syscall: + push {r4, r5, r6, r7} + mov ip, r0 + mov r0, r1 + mov r1, r2 + mov r2, r3 + add r7, sp, #(4 * 4) + ldmia r7!, {r3, r4, r5, r6} + mov r7, ip + swi 0x0 + pop {r4, r5, r6, r7} + ldr r1, =0xfffff000 + cmp r0, r1 + bcs 1f + bx lr +1: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else +syscall: + mov ip, sp + stmfd sp!, {r4, r5, r6, r7} + mov r7, r0 + mov r0, r1 + mov r1, r2 + mov r2, r3 + ldmfd ip, {r3, r4, r5, r6} + swi 0x0 + ldmfd sp!, {r4, r5, r6, r7} + cmn r0, #4096 + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + b __syscall_error +#endif + +.size syscall,.-syscall diff --git a/libc/sysdeps/linux/arm/syscall.c b/libc/sysdeps/linux/arm/syscall.c new file mode 100644 index 0000000..60fbcf8 --- /dev/null +++ b/libc/sysdeps/linux/arm/syscall.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* syscall for arm/uClibc + * + * Copyright (C) 2002 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ +#if !defined(__thumb__) + register long _r0 __asm__("r0")=(long)(sysnum); + register long _r6 __asm__("r6")=(long)(f); + register long _r5 __asm__("r5")=(long)(e); + register long _r4 __asm__("r4")=(long)(d); + register long _r3 __asm__("r3")=(long)(c); + register long _r2 __asm__("r2")=(long)(b); + register long _r1 __asm__("r1")=(long)(a); + __asm__ __volatile__( + "swi %1" + : "=r"(_r0) + : "i"(__NR_syscall), "r"(_r0), "r"(_r1), + "r"(_r2), "r"(_r3), "r"(_r4), "r"(_r5), + "r"(_r6) + : "memory"); +#else + register long _r7 __asm__("r7")=(long)(sysnum); + register long _r5 __asm__("r5")=(long)(f); + register long _r4 __asm__("r4")=(long)(e); + register long _r3 __asm__("r3")=(long)(d); + register long _r2 __asm__("r2")=(long)(c); + register long _r1 __asm__("r1")=(long)(b); + register long _r0 __asm__("r0")=(long)(a); + __asm__ __volatile__( + "swi 0" + : "=r"(_r0) + : "r"(_r0), "r"(_r1), "r"(_r2), "r"(_r3), + "r"(_r4), "r"(_r5), "r"(_r7) + : "memory"); +#endif + if(_r0 >=(unsigned long) -4095) { + long err = _r0; + (*__errno_location())=(-err); + _r0=(unsigned long) -1; + } + return (long) _r0; +} diff --git a/libc/sysdeps/linux/arm/vfork.S b/libc/sysdeps/linux/arm/vfork.S new file mode 100644 index 0000000..42595b0 --- /dev/null +++ b/libc/sysdeps/linux/arm/vfork.S @@ -0,0 +1,95 @@ +/* vi: set sw=4 ts=4: */ +/* + * vfork for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define _ERRNO_H +#include +#include + +#ifdef __NR_fork +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +__vfork: +#ifdef __NR_vfork + DO_CALL (vfork) + ldr r1, =0xfffff000 + cmp r0, r1 + bcs 1f + bx lr +1: + + /* Check if vfork even exists. */ + ldr r1, =-ENOSYS + cmp r0, r1 + bne __error + + /* If we don't have vfork, use fork. */ + DO_CALL (fork) + ldr r1, =0xfffff000 + cmp r0, r1 + + /* Syscall worked. Return to child/parent */ + bcs 1f + bx lr +1: + +__error: + push {r3, lr} + bl __syscall_error + POP_RET +.pool + +#endif + +#else +__vfork: + +#ifdef __NR_vfork + DO_CALL (vfork) + cmn r0, #4096 + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + + /* Check if vfork even exists. */ + ldr r1, =-ENOSYS + teq r0, r1 + bne __error +#endif + + /* If we don't have vfork, use fork. */ + DO_CALL (fork) + cmn r0, #4096 + + /* Syscall worked. Return to child/parent */ + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + +__error: + b __syscall_error +#endif + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) +#endif diff --git a/libc/sysdeps/linux/avr32/Makefile b/libc/sysdeps/linux/avr32/Makefile new file mode 100644 index 0000000..338abc0 --- /dev/null +++ b/libc/sysdeps/linux/avr32/Makefile @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs + +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/avr32/Makefile.arch b/libc/sysdeps/linux/avr32/Makefile.arch new file mode 100644 index 0000000..44fc01e --- /dev/null +++ b/libc/sysdeps/linux/avr32/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c clone.c mmap.c sigaction.c + +SSRC := __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + sigrestorer.S syscall.S vfork.S + +include $(top_srcdir)/libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/avr32/__longjmp.S b/libc/sysdeps/linux/avr32/__longjmp.S new file mode 100644 index 0000000..6154bb2 --- /dev/null +++ b/libc/sysdeps/linux/avr32/__longjmp.S @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + .global __longjmp + .type __longjmp,"function" + .align 1 +__longjmp: + ldm r12++, r0-r8,sp,lr + mustr r8 /* restore status register (lower half) */ + cp r11, 0 /* can't return zero */ + frs + moveq r11, 1 + retal r11 + .size __longjmp, . - __longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/avr32/bits/atomic.h b/libc/sysdeps/linux/avr32/bits/atomic.h new file mode 100644 index 0000000..e6be41f --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/atomic.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _AVR32_BITS_ATOMIC_H +#define _AVR32_BITS_ATOMIC_H 1 + +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ \ + __typeof__(*(mem)) __prev; \ + __asm__ __volatile__( \ + "/* __arch_compare_and_exchange_val_32_acq */\n" \ + "1: ssrf 5\n" \ + " ld.w %[result], %[m]\n" \ + " cp.w %[result], %[old]\n" \ + " brne 2f\n" \ + " stcond %[m], %[new]\n" \ + " brne 1b\n" \ + "2:" \ + : [result] "=&r"(__result), [m] "=m"(*(mem)) \ + : "m"(*(mem)), [old] "ir"(oldval), \ + [new] "r"(newval) \ + : "memory", "cc"); \ + __prev; \ + }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_exchange_32_acq(mem, newval) \ + ({ \ + __typeof__(*(mem)) __oldval; \ + __asm__ __volatile__( \ + "/*__arch_exchange_32_acq */\n" \ + " xchg %[old], %[m], %[new]" \ + : [old] "=&r"(__oldval) \ + : [m] "r"(mem), [new] "r"(newval) \ + : "memory"); \ + __oldval; \ + }) + +#define __arch_atomic_exchange_and_add_32(mem, value) \ + ({ \ + __typeof__(*(mem)) __oldval, __tmp; \ + __asm__ __volatile__( \ + "/* __arch_atomic_exchange_and_add_32 */\n" \ + "1: ssrf 5\n" \ + " ld.w %[old], %[m]\n" \ + " add %[tmp], %[old], %[val]\n" \ + " stcond %[m], %[tmp]\n" \ + " brne 1b" \ + : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \ + [m] "=m"(*(mem)) \ + : "m"(*(mem)), [val] "r"(value) \ + : "memory", "cc"); \ + __oldval; \ + }) + +#define __arch_atomic_decrement_if_positive_32(mem) \ + ({ \ + __typeof__(*(mem)) __oldval, __tmp; \ + __asm__ __volatile__( \ + "/* __arch_atomic_decrement_if_positive_32 */\n" \ + "1: ssrf 5\n" \ + " ld.w %[old], %[m]\n" \ + " sub %[tmp], %[old], 1\n" \ + " brlt 2f\n" \ + " stcond %[m], %[tmp]\n" \ + " brne 1b" \ + "2:" \ + : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \ + [m] "=m"(*(mem)) \ + : "m"(*(mem)) \ + : "memory", "cc"); \ + __oldval; \ + }) + +#define atomic_exchange_acq(mem, newval) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_exchange_32_acq(mem, newval); \ + }) + +#define atomic_exchange_and_add(mem, newval) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_atomic_exchange_and_add_32(mem, newval); \ + }) + +#define atomic_decrement_if_positive(mem) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_atomic_decrement_if_positive_32(mem); \ + }) + +#endif /* _AVR32_BITS_ATOMIC_H */ diff --git a/libc/sysdeps/linux/avr32/bits/byteswap.h b/libc/sysdeps/linux/avr32/bits/byteswap.h new file mode 100644 index 0000000..f0bea4c --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/byteswap.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#if defined __GNUC__ +# define __bswap_16(x) (__extension__ __builtin_bswap_16(x)) +#else +/* This is better than nothing. */ +static __inline__ unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); +} +#endif + +/* Swap bytes in 32 bit value. */ +#if defined __GNUC__ +# define __bswap_32(x) (__extension__ __builtin_bswap_32(x)) +#else +static __inline__ unsigned int +__bswap_32 (unsigned int __bsx) +{ + return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); +} +#endif + +#if defined __GNUC__ +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ \ + union { \ + __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; \ + } __w, __r; \ + if (__builtin_constant_p(x)) \ + __r.__ll = __bswap_constant_64(x); \ + else { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32(__w.__l[1]); \ + __r.__l[1] = __bswap_32(__w.__l[0]); \ + } \ + __r.__ll; \ + })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/avr32/bits/endian.h b/libc/sysdeps/linux/avr32/bits/endian.h new file mode 100644 index 0000000..7bb6358 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/endian.h @@ -0,0 +1,7 @@ +/* AVR32 is big-endian */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/avr32/bits/fcntl.h b/libc/sysdeps/linux/avr32/bits/fcntl.h new file mode 100644 index 0000000..df3eae8 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/fcntl.h @@ -0,0 +1,214 @@ +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + +/* + * open/fcntl - O_SYNC is only implemented on blocks devices and on files + * located on an ext2 file system + */ +#define O_ACCMODE 00000003 +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 +#define O_CREAT 00000100 /* not fcntl */ +#define O_EXCL 00000200 /* not fcntl */ +#define O_NOCTTY 00000400 /* not fcntl */ +#define O_TRUNC 00001000 /* not fcntl */ +#define O_APPEND 00002000 +#define O_NONBLOCK 00004000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 00010000 +#define O_ASYNC 00020000 + +#ifdef __USE_GNU +# define O_DIRECT 00040000 /* must be a directory */ +# define O_DIRECTORY 00200000 /* direct disk access */ +# define O_NOFOLLOW 00400000 /* don't follow links */ +# define O_NOATIME 01000000 /* don't set atime */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 00100000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get close_on_exec */ +#define F_SETFD 2 /* set/clear close_on_exec */ +#define F_GETFL 3 /* get file->f_flags */ +#define F_SETFL 4 /* set file->f_flags */ + +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 +# define F_SETLK 6 +# define F_SETLKW 7 +#else +# define F_GETLK F_GETLK64 +# define F_SETLK F_SETLK64 +# define F_SETLKW F_SETLKW64 +#endif +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* for sockets. */ +# define F_GETOWN 9 /* for sockets. */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* for sockets. */ +# define F_GETSIG 11 /* for sockets. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +#endif + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* for leases */ +#define F_INPROGRESS 16 + +#ifdef __USE_BSD +/* operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock */ +# define LOCK_READ 64 /* ... Which allows concurrent + read operations */ +# define LOCK_WRITE 128 /* ... Which allows concurrent + write operations */ +# define LOCK_RW 192 /* ... Which allows concurrent + read & write ops */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock { + short l_type; + short l_whence; +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; + __off_t l_len; +#else + __off64_t l_start; + __off64_t l_len; +#endif + __pid_t l_pid; +}; + +#ifdef __USE_LARGEFILE64 +struct flock64 { + short l_type; + short l_whence; + __off64_t l_start; + __off64_t l_len; + __pid_t l_pid; +}; +#endif + +/* Define some more compatibility macros to be backward compatible with + * BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + +#ifdef __USE_GNU + +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing + the write */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages + in the range after performing the + write */ + +/* Flags for splice() and vmsplice() */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to) */ +# define SPLICE_F_MORE 4 /* Expect more data */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift */ + +__BEGIN_DECLS + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) __THROW; + +/* Selective file content synch'ing */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +__END_DECLS +#endif diff --git a/libc/sysdeps/linux/avr32/bits/kernel_stat.h b/libc/sysdeps/linux/avr32/bits/kernel_stat.h new file mode 100644 index 0000000..f97d23b --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/kernel_stat.h @@ -0,0 +1,67 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* + * This file provides struct stat, taken from kernel 2.6.4. Verified + * to match kernel 2.6.22. + */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +}; + +#define STAT_HAVE_NSEC 1 + +struct kernel_stat64 { + unsigned long long st_dev; + + unsigned long long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + + long long st_size; + unsigned long __pad1; + unsigned long st_blksize; + + unsigned long long st_blocks; + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/avr32/bits/kernel_types.h b/libc/sysdeps/linux/avr32/bits/kernel_types.h new file mode 100644 index 0000000..f7d8b52 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/kernel_types.h @@ -0,0 +1,55 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_AVR32_POSIX_TYPES_H +#define __ASM_AVR32_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_AVR32_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/avr32/bits/mman.h b/libc/sysdeps/linux/avr32/bits/mman.h new file mode 100644 index 0000000..5f6e3c3 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/mman.h @@ -0,0 +1,103 @@ +/* Definitions for POSIX memory map interface. Linux/AVR32 version. + Copyright (C) 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +# define MAP_NONBLOCK 0x10000 /* do not block on IO */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advise to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/avr32/bits/setjmp.h b/libc/sysdeps/linux/avr32/bits/setjmp.h new file mode 100644 index 0000000..78348a3 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/setjmp.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004-2005 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* + * The jump buffer contains r0-r7, sr, sp and lr. Other registers are + * not saved. + */ +typedef int __jmp_buf[11]; +#endif + +#define __JMP_BUF_SP 4 + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP])) + +#endif /* _BITS_SETJMP_H */ diff --git a/libc/sysdeps/linux/avr32/bits/stackinfo.h b/libc/sysdeps/linux/avr32/bits/stackinfo.h new file mode 100644 index 0000000..2c17d30 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On AVR32 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/avr32/bits/syscalls.h b/libc/sysdeps/linux/avr32/bits/syscalls.h new file mode 100644 index 0000000..ff5d1a7 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/syscalls.h @@ -0,0 +1,143 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + * This includes the `__NR_' syscall numbers taken from the + * Linux kernel header files. It also defines the traditional + * `SYS_' macros for older programs. + */ +#include + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall0 +#define _syscall0(type,name) \ + type name(void) \ + { \ + return (type)(INLINE_SYSCALL(name, 0)); \ + } + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ + type name(type1 arg1) \ + { \ + return (type)(INLINE_SYSCALL(name, 1, arg1)); \ + } + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ + type name(type1 arg1, type2 arg2) \ + { \ + return (type)(INLINE_SYSCALL(name, 2, arg1, arg2)); \ + } + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ + type name(type1 arg1, type2 arg2, type3 arg3) \ + { \ + return (type)(INLINE_SYSCALL(name, 3, arg1, \ + arg2, arg3)); \ + } + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3, \ + type4,arg4) \ + type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ + { \ + return (type)(INLINE_SYSCALL(name, 4, arg1, arg2, \ + arg3, arg4)); \ + } + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3, \ + type4,arg4,type5,arg5) \ + type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5) \ + { \ + return (type)(INLINE_SYSCALL(name, 5, arg1, arg2, \ + arg3, arg4, arg5)); \ + } + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3, \ + type4,arg4,type5,arg5,type6,arg6) \ + type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ + type5 arg5, type6 arg6) \ + { \ + return (type)(INLINE_SYSCALL(name, 6, arg1, arg2, arg3, \ + arg4, arg5, arg6)); \ + } + +#undef unlikely +#define unlikely(x) __builtin_expect((x), 0) + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned _sys_result = INTERNAL_SYSCALL(name, , nr, args); \ + if (unlikely(INTERNAL_SYSCALL_ERROR_P(_sys_result, ))) { \ + __set_errno(INTERNAL_SYSCALL_ERRNO(_sys_result, )); \ + _sys_result = (unsigned int) -1; \ + } \ + (int) _sys_result; \ + }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while(0) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ \ + register int _a1 __asm__("r12"); \ + register int _scno __asm__("r8") = SYS_ify(name); \ + LOAD_ARGS_##nr (args); \ + __asm__ __volatile__("scall /* syscall " #name " */" \ + : "=r" (_a1) \ + : "r"(_scno) ASM_ARGS_##nr \ + : "cc", "memory"); \ + _a1; \ + }) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int)(val) >= 0xfffff001U) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, errr) (-(val)) + +#define LOAD_ARGS_0() do { } while(0) +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + _a1 = (int) (a1); \ + LOAD_ARGS_0() +#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1) +#define LOAD_ARGS_2(a1, a2) \ + register int _a2 __asm__("r11") = (int)(a2); \ + LOAD_ARGS_1(a1) +#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + register int _a3 __asm__("r10") = (int)(a3); \ + LOAD_ARGS_2(a1, a2) +#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + register int _a4 __asm__("r9") = (int)(a4); \ + LOAD_ARGS_3(a1, a2, a3) +#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + register int _a5 __asm__("r5") = (int)(a5); \ + LOAD_ARGS_4(a1, a2, a3, a4) +#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + register int _a6 __asm__("r3") = (int)(a6); \ + LOAD_ARGS_5(a1, a2, a3, a4, a5) +#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h new file mode 100644 index 0000000..679be30 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h @@ -0,0 +1,42 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/* trigger illegal instruction exception, same as BUG in Linux */ +#define __UCLIBC_ABORT_INSTRUCTION__ ".short 0x5df0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/avr32/bits/wordsize.h b/libc/sysdeps/linux/avr32/bits/wordsize.h new file mode 100644 index 0000000..1b5842a --- /dev/null +++ b/libc/sysdeps/linux/avr32/bits/wordsize.h @@ -0,0 +1 @@ +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/avr32/brk.c b/libc/sysdeps/linux/avr32/brk.c new file mode 100644 index 0000000..a54b49a --- /dev/null +++ b/libc/sysdeps/linux/avr32/brk.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include + +libc_hidden_proto(brk) + +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + newbrk = (void *)INLINE_SYSCALL(brk, 1, addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/avr32/bsd-_setjmp.S b/libc/sysdeps/linux/avr32/bsd-_setjmp.S new file mode 100644 index 0000000..f23e73b --- /dev/null +++ b/libc/sysdeps/linux/avr32/bsd-_setjmp.S @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + /* This just does a tail-call to __sigsetjmp(env, 0) */ + .global _setjmp + .type _setjmp,"function" + .align 1 +_setjmp: + mov r11, 0 + bral HIDDEN_JUMPTARGET(__sigsetjmp) + .size _setjmp, . - _setjmp diff --git a/libc/sysdeps/linux/avr32/bsd-setjmp.S b/libc/sysdeps/linux/avr32/bsd-setjmp.S new file mode 100644 index 0000000..5247ec3 --- /dev/null +++ b/libc/sysdeps/linux/avr32/bsd-setjmp.S @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + /* This just does a tail-call to __sigsetjmp(env, 1) */ + .global setjmp + .type setjmp,"function" + .align 1 +setjmp: + mov r11, 1 + bral HIDDEN_JUMPTARGET(__sigsetjmp) + .size setjmp, . - setjmp diff --git a/libc/sysdeps/linux/avr32/clone.c b/libc/sysdeps/linux/avr32/clone.c new file mode 100644 index 0000000..06e3388 --- /dev/null +++ b/libc/sysdeps/linux/avr32/clone.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2004 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include + +/* + * I don't know if we can be absolutely certain that the fn and arg + * parameters are preserved when returning as the child. If the + * compiler stores them in registers (r0-r7), they should be. + */ +int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + register int (*_fn)(void *arg) = fn; + register void *_arg = arg; + int err; + + /* Sanity check the arguments */ + err = -EINVAL; + if (!fn) + goto syscall_error; + if (!child_stack) + goto syscall_error; + + err = INLINE_SYSCALL(clone, 2, flags, child_stack); + if (err < 0) + goto syscall_error; + else if (err != 0) + return err; + + _exit(_fn(_arg)); + +syscall_error: + __set_errno (-err); + return -1; +} diff --git a/libc/sysdeps/linux/avr32/crt1.S b/libc/sysdeps/linux/avr32/crt1.S new file mode 100644 index 0000000..ca1fa7a --- /dev/null +++ b/libc/sysdeps/linux/avr32/crt1.S @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * When we enter _start, the stack looks like this: + * argc argument counter + * argv[0] pointer to program name + * argv[1..argc-1] pointers to program args + * NULL + * env[0..N] pointers to environment variables + * NULL + * + * r12 contains a function pointer to be registered with `atexit'. + * This is how the dynamic linker arranges to have DT_FINI functions + * called for shared libraries that have been loaded before this + * code runs. + * + * We're going to call the following function: + * __uClibc_main(int (*main)(int, char **, char **), int argc, + * char **argv, void (*app_init)(void), void (*app_fini)(void), + * void (*rtld_fini)(void), void *stack_end) + * + * So we need to set up things as follows: + * r12 = address of main + * r11 = argc + * r10 = &argv[0] + * r9 = address of _init + * r8 = address of _fini + * sp[0] = whatever we got passed in r12 + */ + +#include + + .text + .global _start + .type _start, @function +_start: + /* Clear the frame pointer and link register since this is the outermost frame. */ + mov r7, 0 + mov lr, 0 + + ld.w r11, sp++ /* argc */ + mov r10, sp /* &argv[0] */ + + st.w --sp, r10 /* stack_end */ + st.w --sp, r12 /* rtld_fini */ + +#ifdef __PIC__ + lddpc r6, .L_GOT +.L_RGOT: + rsub r6, pc + lda.w r9, _init + lda.w r8, _fini + lda.w r12, main + + /* Ok, now run uClibc's main() -- should not return */ + call __uClibc_main + + .align 2 +.L_GOT: + .long .L_RGOT - _GLOBAL_OFFSET_TABLE_ +#else + lddpc r9, __init_addr /* app_init */ + lddpc r8, __fini_addr /* app_fini */ + lddpc r12, __main_addr /* main */ + + /* Ok, now run uClibc's main() -- should not return */ + lddpc pc, ___uClibc_main_addr + + .align 2 +__init_addr: + .long _init +__fini_addr: + .long _fini +__main_addr: + .long main +___uClibc_main_addr: + .long __uClibc_main +#endif + .size _start, . - _start + + /* + * The LSB says we need this. + */ + .section ".note.ABI-tag", "a" + .align 4 + .long 2f - 1f /* namesz */ + .long 4f - 3f /* descsz */ + .long 1 /* type */ +1: .asciz "GNU" /* name */ +2: .align 4 +3: .long 0 /* Linux executable */ + .long 2,6,0 /* Earliest compatible kernel */ +4: .align 4 diff --git a/libc/sysdeps/linux/avr32/crti.S b/libc/sysdeps/linux/avr32/crti.S new file mode 100644 index 0000000..660f47c --- /dev/null +++ b/libc/sysdeps/linux/avr32/crti.S @@ -0,0 +1,26 @@ + + .section .init + .align 2 + .global _init + .type _init, @function +_init: + stm --sp, r6, lr + lddpc r6, 2f +1: rsub r6, pc + rjmp 3f + .align 2 +2: .long 1b - _GLOBAL_OFFSET_TABLE_ +3: + + .section .fini + .align 2 + .global _fini + .type _fini, @function +_fini: + stm --sp, r6, lr + lddpc r6, 2f +1: rsub r6, pc + rjmp 3f + .align 2 +2: .long 1b - _GLOBAL_OFFSET_TABLE_ +3: diff --git a/libc/sysdeps/linux/avr32/crtn.S b/libc/sysdeps/linux/avr32/crtn.S new file mode 100644 index 0000000..f7d1040 --- /dev/null +++ b/libc/sysdeps/linux/avr32/crtn.S @@ -0,0 +1,14 @@ + + .section .init + .align 2 + .global _init + .type _init, @function + ldm sp++, r6, pc + .size _init, . - _init + + .section .fini + .align 2 + .global _fini + .type _fini, @function + ldm sp++, r6, pc + .size _fini, . - _fini diff --git a/libc/sysdeps/linux/avr32/mmap.c b/libc/sysdeps/linux/avr32/mmap.c new file mode 100644 index 0000000..92d3fe4 --- /dev/null +++ b/libc/sysdeps/linux/avr32/mmap.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, pgoff) + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + unsigned long page_size = sysconf(_SC_PAGESIZE); + unsigned long pgoff; + + if (offset & (page_size - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + pgoff = (unsigned long)offset >> (31 - __builtin_clz(page_size)); + + return mmap2(addr, len, prot, flags, fd, pgoff); +} +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/avr32/setjmp.S b/libc/sysdeps/linux/avr32/setjmp.S new file mode 100644 index 0000000..7d0354b --- /dev/null +++ b/libc/sysdeps/linux/avr32/setjmp.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#define _SETJMP_H +#define _ASM +#include + + .text + + .global __sigsetjmp + .type __sigsetjmp,"function" + + .align 1 +__sigsetjmp: + mustr r8 + stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr + + /* + * Make a tail call to __sigjmp_save; it takes the same args + * and is hidden so we don't need to mess around with the GOT. + */ + rjmp __sigjmp_save + .size __sigsetjmp, . - __sigsetjmp + +libc_hidden_def(__sigsetjmp) diff --git a/libc/sysdeps/linux/avr32/sigaction.c b/libc/sysdeps/linux/avr32/sigaction.c new file mode 100644 index 0000000..5a1ec9e --- /dev/null +++ b/libc/sysdeps/linux/avr32/sigaction.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 +extern void __default_rt_sa_restorer(void); + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +extern __typeof(sigaction) __libc_sigaction; + +/* + * If act is not NULL, change the action for sig to *act. + * If oact is not NULL, put the old action for sig in *oact. + */ +int __libc_sigaction(int signum, const struct sigaction *act, + struct sigaction *oldact) +{ + struct kernel_sigaction kact, koact; + int result; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask)); + kact.sa_flags = act->sa_flags; + if (kact.sa_flags & SA_RESTORER) + kact.sa_restorer = act->sa_restorer; + else + kact.sa_restorer = __default_rt_sa_restorer; + kact.sa_flags |= SA_RESTORER; + } + + result = __syscall_rt_sigaction(signum, act ? __ptrvalue(&kact) : NULL, + oldact ? __ptrvalue(&koact) : NULL, + _NSIG / 8); + + if (oldact && result >= 0) { + oldact->sa_handler = koact.k_sa_handler; + memcpy(&oldact->sa_mask, &koact.sa_mask, + sizeof(oldact->sa_mask)); + oldact->sa_flags = koact.sa_flags; + oldact->sa_restorer = koact.sa_restorer; + } + + return result; +} + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction, sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/libc/sysdeps/linux/avr32/sigrestorer.S b/libc/sysdeps/linux/avr32/sigrestorer.S new file mode 100644 index 0000000..df6a1ba --- /dev/null +++ b/libc/sysdeps/linux/avr32/sigrestorer.S @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2004 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include + + .global __default_rt_sa_restorer + .type __default_rt_sa_restorer,"function" + .align 1 +__default_rt_sa_restorer: + mov r8, __NR_rt_sigreturn + scall diff --git a/libc/sysdeps/linux/avr32/sys/elf.h b/libc/sysdeps/linux/avr32/sys/elf.h new file mode 100644 index 0000000..faa7310 --- /dev/null +++ b/libc/sysdeps/linux/avr32/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* sys/elf.h */ diff --git a/libc/sysdeps/linux/avr32/sys/procfs.h b/libc/sysdeps/linux/avr32/sys/procfs.h new file mode 100644 index 0000000..3b37363 --- /dev/null +++ b/libc/sysdeps/linux/avr32/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/avr32/sys/ucontext.h b/libc/sysdeps/linux/avr32/sys/ucontext.h new file mode 100644 index 0000000..82c7fe2 --- /dev/null +++ b/libc/sysdeps/linux/avr32/sys/ucontext.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux/AVR32 ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 16 + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15 +#define R15 R15 +}; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/avr32/sys/user.h b/libc/sysdeps/linux/avr32/sys/user.h new file mode 100644 index 0000000..c0b3d38 --- /dev/null +++ b/libc/sysdeps/linux/avr32/sys/user.h @@ -0,0 +1,46 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H + +struct user_fpregs +{ + +}; + +struct user_regs +{ + unsigned long sr; + unsigned long pc; + unsigned long lr; + unsigned long sp; + unsigned long r12; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long r7; + unsigned long r6; + unsigned long r5; + unsigned long r4; + unsigned long r3; + unsigned long r2; + unsigned long r1; + unsigned long r0; + unsigned long r12_orig; +}; + +struct user +{ + struct user_regs regs; /* general registers */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct user_regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif /* _SYS_USER_H */ diff --git a/libc/sysdeps/linux/avr32/syscall.S b/libc/sysdeps/linux/avr32/syscall.S new file mode 100644 index 0000000..55c1b1f --- /dev/null +++ b/libc/sysdeps/linux/avr32/syscall.S @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include + + .text + + /* + * long int syscall(long int sysno, ...) + */ + .global syscall + .type syscall, @function + .align 2 +syscall: + stm --sp, r3,r5,r6,lr + sub lr, sp, -16 + mov r8, r12 + ldm lr, r3,r5,r9-r12 + scall + cp.w r12, -4095 + brlo .Ldone + +#ifdef __PIC__ + lddpc r6, .Lgot +.Lgotcalc: + rsub r6, pc +# ifdef __UCLIBC_HAS_THREADS__ + rsub r3, r12, 0 + mcall r6[__errno_location@got] + st.w r12[0], r3 +# else + ld.w r3, r6[errno@got] + neg r12 + st.w r3[0], r12 +# endif +#else +# ifdef __UCLIBC_HAS_THREADS__ + rsub r3, r12, 0 + mcall .Lerrno_location + st.w r12[0], r3 +# else + lddpc r3, .Lerrno + neg r12 + st.w r3[0], r12 +# endif +#endif + mov r12, -1 + +.Ldone: + ldm sp++, r3,r5,r6,pc + + .align 2 +#ifdef __PIC__ +.Lgot: + .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_ +#else +# ifdef __UCLIBC_HAS_THREADS__ +.Lerrno_location: + .long __errno_location +# else +.Lerrno: + .long errno +# endif +#endif + + + .size syscall, . - syscall diff --git a/libc/sysdeps/linux/avr32/vfork.S b/libc/sysdeps/linux/avr32/vfork.S new file mode 100644 index 0000000..03ca99f --- /dev/null +++ b/libc/sysdeps/linux/avr32/vfork.S @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +/* + * Clone the process without copying the address space. The + * calling process is suspended until the child either exits + * or calls execve. + * + * This all means that we cannot rely on the stack to store + * away registers, since they will be overwritten by the child + * as soon as it makes another function call (e.g. execve()). + * Fortunately, the Linux kernel preserves LR across system calls. + */ + +#include +#include + + .global __vfork + .type __vfork,@function + .align 1 +__vfork: + mov r8, __NR_vfork + scall + cp.w r12, -4096 + retls r12 + + /* vfork failed, so we may use the stack freely */ + pushm r4-r7,lr +#ifdef __PIC__ + lddpc r6, .L_GOT + rsub r4, r12, 0 +.L_RGOT: + rsub r6, pc + mcall r6[__errno_location@got] +#else + rsub r4, r12, 0 + mcall .L__errno_location +#endif + st.w r12[0], r4 + popm r4-r7,pc,r12=-1 + + .align 2 +#ifdef __PIC__ +.L_GOT: + .long .L_RGOT - _GLOBAL_OFFSET_TABLE_ +#else +.L__errno_location: + .long __errno_location +#endif + .size __vfork, . - __vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/bfin/Makefile b/libc/sysdeps/linux/bfin/Makefile new file mode 100644 index 0000000..3970f62 --- /dev/null +++ b/libc/sysdeps/linux/bfin/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/bfin/Makefile.arch b/libc/sysdeps/linux/bfin/Makefile.arch new file mode 100644 index 0000000..6c27150 --- /dev/null +++ b/libc/sysdeps/linux/bfin/Makefile.arch @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c bsdsetjmp.c clone.c syscall.c \ + sram-alloc.c sram-free.c dma-memcpy.c + +SSRC := __longjmp.S setjmp.S bsd-_setjmp.S vfork.S + +ARCH_HEADERS := bfin_l1layout.h bfin_sram.h + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/bfin/__longjmp.S b/libc/sysdeps/linux/bfin/__longjmp.S new file mode 100644 index 0000000..673cd30 --- /dev/null +++ b/libc/sysdeps/linux/bfin/__longjmp.S @@ -0,0 +1,107 @@ +/* longjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2004 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global ___longjmp; +.type ___longjmp,STT_FUNC; +.align 4; + +___longjmp: + P0 = R0; + R0 = [P0 + 0x00]; + [--SP] = R0; /* Put P0 on the stack */ + + P1 = [P0 + 0x04]; + P2 = [P0 + 0x08]; + P3 = [P0 + 0x0C]; + P4 = [P0 + 0x10]; + P5 = [P0 + 0x14]; + + FP = [P0 + 0x18]; + R0 = [SP++]; /* Grab P0 from old stack */ + SP = [P0 + 0x1C]; /* Update Stack Pointer */ + [--SP] = R0; /* Put P0 on new stack */ + [--SP] = R1; /* Put VAL arg on new stack */ + + R0 = [P0 + 0x20]; /* Data Registers */ + R1 = [P0 + 0x24]; + R2 = [P0 + 0x28]; + R3 = [P0 + 0x2C]; + R4 = [P0 + 0x30]; + R5 = [P0 + 0x34]; + R6 = [P0 + 0x38]; + R7 = [P0 + 0x3C]; + + R0 = [P0 + 0x40]; + ASTAT = R0; + + R0 = [P0 + 0x44]; /* Loop Counters */ + LC0 = R0; + R0 = [P0 + 0x48]; + LC1 = R0; + + R0 = [P0 + 0x4C]; /* Accumulators */ + A0.W = R0; + R0 = [P0 + 0x50]; + A0.X = R0; + R0 = [P0 + 0x54]; + A1.W = R0; + R0 = [P0 + 0x58]; + A1.X = R0; + + R0 = [P0 + 0x5C]; /* Index Registers */ + I0 = R0; + R0 = [P0 + 0x60]; + I1 = R0; + R0 = [P0 + 0x64]; + I2 = R0; + R0 = [P0 + 0x68]; + I3 = R0; + + R0 = [P0 + 0x6C]; /* Modifier Registers */ + M0 = R0; + R0 = [P0 + 0x70]; + M1 = R0; + R0 = [P0 + 0x74]; + M2 = R0; + R0 = [P0 + 0x78]; + M3 = R0; + + R0 = [P0 + 0x7C]; /* Length Registers */ + L0 = R0; + R0 = [P0 + 0x80]; + L1 = R0; + R0 = [P0 + 0x84]; + L2 = R0; + R0 = [P0 + 0x88]; + L3 = R0; + + R0 = [P0 + 0x8C]; /* Base Registers */ + B0 = R0; + R0 = [P0 + 0x90]; + B1 = R0; + R0 = [P0 + 0x94]; + B2 = R0; + R0 = [P0 + 0x98]; + B3 = R0; + + R0 = [P0 + 0x9C]; /* Return Address (PC) */ + RETS = R0; + + R0 = [SP++]; + P0 = [SP++]; + + CC = R0 == 0; + IF !CC JUMP .Lfinished; + R0 = 1; +.Lfinished: + RTS; +.size ___longjmp,.-___longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/bfin/bfin_l1layout.h b/libc/sysdeps/linux/bfin/bfin_l1layout.h new file mode 100644 index 0000000..00efd23 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bfin_l1layout.h @@ -0,0 +1,17 @@ +#define L1_SCRATCH_START 0xFFB00000 + +/* Data that is "mapped" into the process VM at the start of the L1 scratch + memory, so that each process can access it at a fixed address. Used for + stack checking. */ +struct l1_scratch_task_info +{ + /* Points to the start of the stack. */ + void *stack_start; + /* Not updated by the kernel; a user process can modify this to + keep track of the lowest address of the stack pointer during its + runtime. */ + void *lowest_sp; +}; + +/* A pointer to the structure in memory. */ +#define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START) diff --git a/libc/sysdeps/linux/bfin/bfin_sram.h b/libc/sysdeps/linux/bfin/bfin_sram.h new file mode 100644 index 0000000..eea729b --- /dev/null +++ b/libc/sysdeps/linux/bfin/bfin_sram.h @@ -0,0 +1,30 @@ +/* + * bfin_sram.h - userspace interface to L1 memory allocator + * + * Copyright (c) 2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_SRAM_H__ +#define __BFIN_SRAM_H__ + +#include +#include + +__BEGIN_DECLS + +#define L1_INST_SRAM 0x00000001 +#define L1_DATA_A_SRAM 0x00000002 +#define L1_DATA_B_SRAM 0x00000004 +#define L1_DATA_SRAM 0x00000006 + +extern void *sram_alloc(size_t size, unsigned long flags) + __attribute_malloc__ __attribute_warn_unused_result__; +extern int sram_free(const void *addr); +extern void *dma_memcpy(void *dest, const void *src, size_t len) + __nonnull((1, 2)); + +__END_DECLS + +#endif diff --git a/libc/sysdeps/linux/bfin/bits/byteswap.h b/libc/sysdeps/linux/bfin/bits/byteswap.h new file mode 100644 index 0000000..74b87d9 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/byteswap.h @@ -0,0 +1,94 @@ +/* File: libc/sysdeps/linux/bfin/bits/byteswap.h + * + * Copyright 2004-2006 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)) + +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("%0 = PACK (%1.L, %1.L);" \ + "%0 >>= 8;" \ + : "=d" (__v) \ + : "d" (__x)); \ + __v; })) +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ + (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("%1 = %0 >> 8 (V);" \ + "%0 = %0 << 8 (V);" \ + "%0 = %0 | %1;" \ + "%1 = PACK(%0.L, %0.H);" \ + : "+d"(__x), "=&d"(__v)); \ + __v; })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/bfin/bits/elf-fdpic.h b/libc/sysdeps/linux/bfin/bits/elf-fdpic.h new file mode 100644 index 0000000..b7e87b8 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/elf-fdpic.h @@ -0,0 +1,115 @@ +/* Copyright 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. + The kernel passes a process a memory map, such that for every LOAD + segment there is an elf32_fdpic_loadseg entry. A pointer to an + elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to + an additional such map is passed in GR9 for the interpreter, when + there is one. */ + +#include + +/* This data structure represents a PT_LOAD segment. */ +struct elf32_fdpic_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Half version; + /* Number of segments in this map. */ + Elf32_Half nsegs; + /* The actual memory map. */ + struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { + struct elf32_fdpic_loadmap *map; + void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the + load map. */ +static __always_inline void * +__reloc_pointer (void *p, + const struct elf32_fdpic_loadmap *map) +{ + int c; + +#if 0 + if (map->version != 0) + /* Crash. */ + ((void(*)())0)(); +#endif + + /* No special provision is made for NULL. We don't want NULL + addresses to go through relocation, so they shouldn't be in + .rofixup sections, and, if they're present in dynamic + relocations, they shall be mapped to the NULL address without + undergoing relocations. */ + + for (c = 0; + /* Take advantage of the fact that the loadmap is ordered by + virtual addresses. In general there will only be 2 entries, + so it's not profitable to do a binary search. */ + c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; + c++) + { + /* This should be computed as part of the pointer comparison + above, but we want to use the carry in the comparison, so we + can't convert it to an integer type beforehand. */ + unsigned long offset = p - (void*)map->segs[c].p_vaddr; + /* We only check for one-past-the-end for the last segment, + assumed to be the data segment, because other cases are + ambiguous in the absence of padding between segments, and + rofixup already serves as padding between text and data. + Unfortunately, unless we special-case the last segment, we + fail to relocate the _end symbol. */ + if (offset < map->segs[c].p_memsz + || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) + return (char*)map->segs[c].addr + offset; + } + + /* We might want to crash instead. */ + return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ + (__reloc_pointer ((void*)(ptr), \ + (loadaddr).map)) + +#endif /* _BITS_ELF_FDPIC_H */ diff --git a/libc/sysdeps/linux/bfin/bits/endian.h b/libc/sysdeps/linux/bfin/bits/endian.h new file mode 100644 index 0000000..8a36cf7 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/endian.h @@ -0,0 +1,7 @@ +/* Blackfin is Little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/bfin/bits/fcntl.h b/libc/sysdeps/linux/bfin/bits/fcntl.h new file mode 100644 index 0000000..7e32a04 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/fcntl.h @@ -0,0 +1,237 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/bfin/bits/huge_val.h b/libc/sysdeps/linux/bfin/bits/huge_val.h new file mode 100644 index 0000000..9c8b721 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/huge_val.h @@ -0,0 +1,56 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Blackfin version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/bfin/bits/kernel_stat.h b/libc/sysdeps/linux/bfin/bits/kernel_stat.h new file mode 100644 index 0000000..8c7ba05 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/kernel_stat.h @@ -0,0 +1,59 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/bfin/bits/kernel_types.h b/libc/sysdeps/linux/bfin/bits/kernel_types.h new file mode 100644 index 0000000..d69a875 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + +#ifndef __ARCH_BFIN_POSIX_TYPES_H +#define __ARCH_BFIN_POSIX_TYPES_H +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_BFIN_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/bfin/bits/mman.h b/libc/sysdeps/linux/bfin/bits/mman.h new file mode 100644 index 0000000..c572387 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/mman.h @@ -0,0 +1,96 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0x0 /* No further special treatment. */ +# define MADV_RANDOM 0x1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 0x2 /* Expect sequential page references. */ +# define MADV_WILLNEED 0x3 /* Will need these pages. */ +# define MADV_DONTNEED 0x4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/bfin/bits/setjmp.h b/libc/sysdeps/linux/bfin/bits/setjmp.h new file mode 100644 index 0000000..ee3f5e7 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/setjmp.h @@ -0,0 +1,57 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. bfin version. Lineo, Inc. 2001*/ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* Jump buffer contains r7-r4, p5-p3, fp, sp and pc. Other registers are not saved. */ +typedef struct +{ + unsigned long __pregs[6]; + unsigned long fp; + unsigned long sp; + unsigned long __rregs[8]; + unsigned long astat; + unsigned long __lcregs[2]; + unsigned long a0w; + unsigned long a0x; + unsigned long a1w; + unsigned long a1x; + unsigned long __iregs[4]; + unsigned long __mregs[4]; + unsigned long __lregs[4]; + unsigned long __bregs[4]; + unsigned long pc; +}__jmp_buf[1]; + +#endif + +#define __JMP_BUF_SP 8 + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__pregs[6]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h b/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h new file mode 100644 index 0000000..b7e08cf --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/bfin/bits/stackinfo.h b/libc/sysdeps/linux/bfin/bits/stackinfo.h new file mode 100644 index 0000000..9e26de1 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On blackfin the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/bfin/bits/syscalls.h b/libc/sysdeps/linux/bfin/bits/syscalls.h new file mode 100644 index 0000000..0833a1f --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/syscalls.h @@ -0,0 +1,138 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -4095: see */ +#if defined _LIBC && !defined __set_errno +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + extern int __syscall_error (int); \ + return (type) __syscall_error (__sr2); \ + } \ + return (type) (__sr2); \ +} while (0) +#else +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + __set_errno (-__sr2); \ + __sr2 = -1; \ + } \ + return (type) (__sr2); \ +} while (0) +#endif + +#define _syscall0(type,name) \ +type name(void) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + "%0=r0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)), \ + "q1" ((long)(arg2)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)), \ + "q1" ((long)(arg2)), \ + "q2" ((long)(arg3)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)), \ + "q1" ((long)(arg2)), \ + "q2" ((long)(arg3)), \ + "q3" ((long)(arg4)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)), \ + "q1" ((long)(arg2)), \ + "q2" ((long)(arg3)), \ + "q3" ((long)(arg4)), \ + "q4" ((long)(arg5)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (__NR_##name), \ + "q0" ((long)(arg1)), \ + "q1" ((long)(arg2)), \ + "q2" ((long)(arg3)), \ + "q3" ((long)(arg4)), \ + "q4" ((long)(arg5)), \ + "q5" ((long)(arg6)) \ + : "memory","CC"); \ + __syscall_return(type,__res); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/bfin/bits/typesizes.h b/libc/sysdeps/linux/bfin/bits/typesizes.h new file mode 100644 index 0000000..eb61fc9 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SLONGWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h b/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h new file mode 100644 index 0000000..39e71c9 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/bfin/bits/wordsize.h b/libc/sysdeps/linux/bfin/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/bfin/brk.c b/libc/sysdeps/linux/bfin/brk.c new file mode 100644 index 0000000..6448045 --- /dev/null +++ b/libc/sysdeps/linux/bfin/brk.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(brk) + +/* This must be initialized data because commons can't have aliases. */ +void * __curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + __asm__ __volatile__( + "P0 = %2;\n\t" + "excpt 0;\n\t" + : "=q0" (newbrk) + : "q0" (addr), "i" (__NR_brk): "P0" ); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/bfin/bsd-_setjmp.S b/libc/sysdeps/linux/bfin/bsd-_setjmp.S new file mode 100644 index 0000000..61cb53f --- /dev/null +++ b/libc/sysdeps/linux/bfin/bsd-_setjmp.S @@ -0,0 +1,97 @@ +/* __setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2002, David McCullough + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global __setjmp; +.type __setjmp,STT_FUNC; +.align 4; + +__setjmp: + [--SP] = P0; /* Save P0 */ + P0 = R0; + R0 = [SP++]; + [P0 + 0x00] = R0; /* Save saved P0 */ + [P0 + 0x04] = P1; + [P0 + 0x08] = P2; + [P0 + 0x0C] = P3; + [P0 + 0x10] = P4; + [P0 + 0x14] = P5; + + [P0 + 0x18] = FP; /* Frame Pointer */ + [P0 + 0x1C] = SP; /* Stack Pointer */ + + [P0 + 0x20] = P0; /* Data Registers */ + [P0 + 0x24] = R1; + [P0 + 0x28] = R2; + [P0 + 0x2C] = R3; + [P0 + 0x30] = R4; + [P0 + 0x34] = R5; + [P0 + 0x38] = R6; + [P0 + 0x3C] = R7; + + R0 = ASTAT; + [P0 + 0x40] = R0; + + R0 = LC0; /* Loop Counters */ + [P0 + 0x44] = R0; + R0 = LC1; + [P0 + 0x48] = R0; + + R0 = A0.W; /* Accumulators */ + [P0 + 0x4C] = R0; + R0 = A0.X; + [P0 + 0x50] = R0; + R0 = A1.W; + [P0 + 0x54] = R0; + R0 = A1.X; + [P0 + 0x58] = R0; + + R0 = I0; /* Index Registers */ + [P0 + 0x5C] = R0; + R0 = I1; + [P0 + 0x60] = R0; + R0 = I2; + [P0 + 0x64] = R0; + R0 = I3; + [P0 + 0x68] = R0; + + R0 = M0; /* Modifier Registers */ + [P0 + 0x6C] = R0; + R0 = M1; + [P0 + 0x70] = R0; + R0 = M2; + [P0 + 0x74] = R0; + R0 = M3; + [P0 + 0x78] = R0; + + R0 = L0; /* Length Registers */ + [P0 + 0x7c] = R0; + R0 = L1; + [P0 + 0x80] = R0; + R0 = L2; + [P0 + 0x84] = R0; + R0 = L3; + [P0 + 0x88] = R0; + + R0 = B0; /* Base Registers */ + [P0 + 0x8C] = R0; + R0 = B1; + [P0 + 0x90] = R0; + R0 = B2; + [P0 + 0x94] = R0; + R0 = B3; + [P0 + 0x98] = R0; + + R0 = RETS; + [P0 + 0x9C] = R0; + + R0 = [P0 + 0x20]; + R1 = 0; + JUMP.L ___sigjmp_save; + +.size __setjmp,.-__setjmp diff --git a/libc/sysdeps/linux/bfin/bsdsetjmp.c b/libc/sysdeps/linux/bfin/bsdsetjmp.c new file mode 100644 index 0000000..0a57d34 --- /dev/null +++ b/libc/sysdeps/linux/bfin/bsdsetjmp.c @@ -0,0 +1,103 @@ +/* setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2003 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#undef setjmp + +int setjmp(jmp_buf env) +{ + __asm__ __volatile__( + "[--SP] = p0;\n\t" + "p0 = r0;\n\t" + "r0 = [SP++];\n\t" + + "[p0++] = r0;\n\t" /* GP address registers */ + "[p0++] = p1;\n\t" + "[p0++] = p2;\n\t" + "[p0++] = p3;\n\t" + "[p0++] = p4;\n\t" + "[p0++] = p5;\n\t" + + "[p0++] = FP;\n\t" /* frame pointer */ + "[p0++] = SP;\n\t" /* stack pointer */ + + "[p0++] = p0;\n\t" /* data regs */ + "[p0++] = r1;\n\t" + "[p0++] = r2;\n\t" + "[p0++] = r3;\n\t" + "[p0++] = r4;\n\t" + "[p0++] = r5;\n\t" + "[p0++] = r6;\n\t" + "[p0++] = r7;\n\t" + + "r0 = ASTAT;\n\t" + "[p0++] = r0;\n\t" + + "r0 = LC0;\n\t" /* loop counters */ + "[p0++] = r0;\n\t" + "r0 = LC1;\n\t" + "[p0++] = r0;\n\t" + + "r0 = A0.w;\n\t" + "[p0++] = r0;\n\t" + "r0.l = A0.x;\n\t" + "[p0++] = r0;\n\t" + "r0 = A1.w;\n\t" + "[p0++] = r0;\n\t" + "r0.l = A1.x;\n\t" + "[p0++] = r0;\n\t" + + /* Dag regs */ + "r0 = i0;\n\t" /* index registers */ + "[p0++] = r0;\n\t" + "r0 = i1;\n\t" + "[p0++] = r0;\n\t" + "r0 = i2;\n\t" + "[p0++] = r0;\n\t" + "r0 = i3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = m0;\n\t" /* modifier registers */ + "[p0++] = r0;\n\t" + "r0 = m1;\n\t" + "[p0++] = r0;\n\t" + "r0 = m2;\n\t" + "[p0++] = r0;\n\t" + "r0 = m3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = l0;\n\t" /* length registers */ + "[p0++] = r0;\n\t" + "r0 = l1;\n\t" + "[p0++] = r0;\n\t" + "r0 = l2;\n\t" + "[p0++] = r0;\n\t" + "r0 = l3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = b0;\n\t" /* base registers */ + "[p0++] = r0;\n\t" + "r0 = b1;\n\t" + "[p0++] = r0;\n\t" + "r0 = b2;\n\t" + "[p0++] = r0;\n\t" + "r0 = b3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = RETS;\n\t" /* store return address */ + "[p0++] = r0;\n\t" + + "r0 = 0;\n\t" + : + : + ); + + return 0; +} diff --git a/libc/sysdeps/linux/bfin/clone.c b/libc/sysdeps/linux/bfin/clone.c new file mode 100644 index 0000000..899738e --- /dev/null +++ b/libc/sysdeps/linux/bfin/clone.c @@ -0,0 +1,59 @@ +/* + * libc/sysdeps/linux/bfin/clone.c -- `clone' syscall for linux/blackfin + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +int +clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + register long rval = -1; + + if (fn && child_stack) { + +#ifdef __BFIN_FDPIC__ + __asm__ __volatile__ ( + "excpt 0;" /*Call sys_clone*/ + "cc = r0 == 0;" + "if !cc jump .Lxxx;" /* if (rval != 0) skip to parent */ + "r0 = %4;" + "p0 = %5;" + "fp = 0;" + "p1 = [p0];" + "p3 = [p0 + 4];" + "call (p1);" /* Call cloned function */ + "p0 = %6;" + "excpt 0;" /* Call sys_exit */ + ".Lxxx: nop;" + : "=q0" (rval) + : "qA" (__NR_clone), "q1" (child_stack), "q0" (flags), "a" (arg), "a" (fn), "i" (__NR_exit) + : "CC"); +#else + __asm__ __volatile__ ( + "excpt 0;" /*Call sys_clone*/ + "cc = r0 == 0;" + "if !cc jump .Lxxx;" /* if (rval != 0) skip to parent */ + "r0 = %4;" + "p0 = %5;" + "fp = 0;" + "call (p0);" /* Call cloned function */ + "p0 = %6;" + "excpt 0;" /* Call sys_exit */ + ".Lxxx: nop;" + : "=q0" (rval) + : "qA" (__NR_clone), "q1" (child_stack), "q0" (flags), "a" (arg), "a" (fn), "i" (__NR_exit) + : "CC"); +#endif + + } else { + __set_errno(EINVAL); + } + + return rval; +} diff --git a/libc/sysdeps/linux/bfin/crt1.S b/libc/sysdeps/linux/bfin/crt1.S new file mode 100644 index 0000000..38e68c9 --- /dev/null +++ b/libc/sysdeps/linux/bfin/crt1.S @@ -0,0 +1,167 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* When we enter this piece of code, the user stack looks like this: +* argc argument counter (integer) +* argv[0] program name (pointer) +* argv[1...N] program args (pointers) +* NULL +* env[0...N] environment variables (pointers) +* NULL + +* When we are done here, we want +* R0=argc +* R1=*argv[0] +* R2=*envp[0] +*/ + +#include + +#undef USE_GOT +#if defined (__UCLIBC_FORMAT_SHARED_FLAT__) || defined (__UCLIBC_FORMAT_FLAT_SEP_DATA__) +#define USE_GOT +#endif + +#if !(defined L_Scrt1 && defined __UCLIBC_FORMAT_SHARED_FLAT__) + +.text +.align 2 +.global __start; +.type __start,STT_FUNC; +.weak __init; +.weak __fini; +.global ___uClibc_main; +.type ___uClibc_main,STT_FUNC; + +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ + +.type _main,STT_FUNC; + +__start: + +#if defined(__BFIN_FDPIC__) && !defined(L_Scrt1) + /* P0 contains a pointer to the program's load map. */ + call .Lcall; +.Lcall: + R4 = RETS; + SP += -12; + R0.L = .Lcall; + R0.H = .Lcall; + R1.L = __ROFIXUP_LIST__; + R1.H = __ROFIXUP_LIST__; + R2.L = __ROFIXUP_END__; + R2.H = __ROFIXUP_END__; + R1 = R1 - R0; + R1 = R1 + R4; + R2 = R2 - R0; + R2 = R2 + R4; + R0 = P0; + CALL ___self_reloc; + SP += 12; + P3 = R0; +#endif + +/* clear the frame pointer and the L registers. */ + FP = 0; + L0 = 0; + L1 = 0; + L2 = 0; + L3 = 0; + +#ifdef __ID_SHARED_LIB__ + /* We know we have a local copy, so we can avoid the GOT. */ + CALL ___shared_flat_add_library; +#endif +/* Load register R1 (argc) from the stack to its final resting place */ + P0 = SP; + R1 = [P0++]; + +/* Copy argv pointer into R2 -- which its final resting place */ + R2 = P0; + + SP += -28; + +#ifndef __BFIN_FDPIC__ + R7 = 0; +#endif + /* Pass highest stack pointer to the app. */ + [SP + 24] = P2; + /* Store the pointer to ld.so's fini that we got in P1. */ + [SP + 20] = R7; + +/* Ok, now run uClibc's main() -- shouldn't return */ +#if defined L_crt1 && defined __UCLIBC_CTOR_DTOR__ + +#ifdef __BFIN_FDPIC__ + R3 = [P3 + __init@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + P5 = [P5 + _current_shared_library_p5_offset_]; + R3 = [P5 + ___shared_flat_init@GOT]; +#else + R3.H = __init; + R3.L = __init; +#endif + [SP+12] = R3; + + +#ifdef __BFIN_FDPIC__ + R3 = [P3 + __fini@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + R3 = [P5 + ___shared_flat_fini@GOT]; +#else + R3.H = __fini; + R3.L = __fini; +#endif + [SP+16] = R3; +#else /* no ctor/dtor handling */ + R3 = 0; + [SP + 12] = R3; + [SP + 16] = R3; +#endif + +#ifdef __BFIN_FDPIC__ + R0 = [P3 + _main@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + R0 = [P5 + _main@GOT]; +#else + R0.H = _main; + R0.L = _main; +#endif +#ifdef USE_GOT + P0 = [P5 + ___uClibc_main@GOT]; + jump (P0) +#else + jump.l ___uClibc_main; +#endif + +#else + .text + .global lib_main + .hidden lib_main + .type lib_main,@function +lib_main: + RETS = [SP++]; + /* We know we have a local copy, so we can avoid the GOT. */ + JUMP.L ___shared_flat_add_library; + + .hidden _current_shared_library_p5_offset_ +#endif diff --git a/libc/sysdeps/linux/bfin/crti.S b/libc/sysdeps/linux/bfin/crti.S new file mode 100644 index 0000000..7c10392 --- /dev/null +++ b/libc/sysdeps/linux/bfin/crti.S @@ -0,0 +1,62 @@ +/* Specialized code needed to support construction and destruction of + file-scope objects in C++ and Java code, and to support exception handling. + Copyright (C) 1999 Free Software Foundation, Inc. + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* + * This file just supplies function prologues for the .init and .fini + * sections. It is linked in before crtbegin.o. + */ + + .file "crti.o" + .ident "GNU C crti.o" + + .section .init + .globl __init + .type __init,@function +__init: +#if defined __ID_SHARED_LIB__ + [--SP] = P5; +#elif defined __BFIN_FDPIC__ + [--SP] = P3; +#endif + LINK 12; +#if defined __ID_SHARED_LIB__ + P5 = [P5 + _current_shared_library_p5_offset_] +#endif + .section .fini + .globl __fini + .type __fini,@function +__fini: +#if defined __ID_SHARED_LIB__ + [--SP] = P5; +#elif defined __BFIN_FDPIC__ + [--SP] = P3; +#endif + LINK 12; +#if defined __ID_SHARED_LIB__ + P5 = [P5 + _current_shared_library_p5_offset_] +#endif diff --git a/libc/sysdeps/linux/bfin/crtn.S b/libc/sysdeps/linux/bfin/crtn.S new file mode 100644 index 0000000..add0b71 --- /dev/null +++ b/libc/sysdeps/linux/bfin/crtn.S @@ -0,0 +1,53 @@ +/* Specialized code needed to support construction and destruction of + file-scope objects in C++ and Java code, and to support exception handling. + Copyright (C) 1999 Free Software Foundation, Inc. + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* + * This file supplies function epilogues for the .init and .fini sections. + * It is linked in after all other files. + */ + + .file "crtn.o" + .ident "GNU C crtn.o" + + .section .init + unlink; +#if defined __ID_SHARED_LIB__ + P5 = [SP++]; +#elif defined __BFIN_FDPIC__ + P3 = [SP++]; +#endif + rts; + + .section .fini + unlink; +#if defined __ID_SHARED_LIB__ + P5 = [SP++]; +#elif defined __BFIN_FDPIC__ + P3 = [SP++]; +#endif + rts; diff --git a/libc/sysdeps/linux/bfin/crtreloc.c b/libc/sysdeps/linux/bfin/crtreloc.c new file mode 100644 index 0000000..408ded2 --- /dev/null +++ b/libc/sysdeps/linux/bfin/crtreloc.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + written by Alexandre Oliva +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifdef __BFIN_FDPIC__ + +#include +#include + +/* This file is to be compiled into crt object files, to enable + executables to easily self-relocate. */ + +union word { + char c[4]; + void *v; +}; + +/* Compute the runtime address of pointer in the range [p,e), and then + map the pointer pointed by it. */ +static __always_inline void *** +reloc_range_indirect (void ***p, void ***e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + if (*p != (void **)-1) + { + void *ptr = __reloc_pointer (*p, map); + if (ptr != (void *)-1) + { + void *pt; + if ((long)ptr & 3) + { + unsigned char *c = ptr; + int i; + unsigned long v = 0; + for (i = 0; i < 4; i++) + v |= c[i] << 8 * i; + pt = (void *)v; + } + else + pt = *(void**)ptr; + pt = __reloc_pointer (pt, map); + if ((long)ptr & 3) + { + unsigned char *c = ptr; + int i; + unsigned long v = (unsigned long)pt; + for (i = 0; i < 4; i++, v >>= 8) + c[i] = v; + } + else + *(void**)ptr = pt; + } + } + p++; + } + return p; +} + +/* Call __reloc_range_indirect for the given range except for the last + entry, whose contents are only relocated. It's expected to hold + the GOT value. */ +void* attribute_hidden +__self_reloc (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + p = reloc_range_indirect (p, e-1, map); + + if (p >= e) + return (void*)-1; + + return __reloc_pointer (*p, map); +} + +#if 0 +/* These are other functions that might be useful, but that we don't + need. */ + +/* Remap pointers in [p,e). */ +static __always_inline void** +reloc_range (void **p, void **e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + *p = __reloc_pointer (*p, map); + p++; + } + return p; +} + +/* Remap p, adjust e by the same offset, then map the pointers in the + range determined by them. */ +void attribute_hidden +__reloc_range (const struct elf32_fdpic_loadmap *map, + void **p, void **e) +{ + void **old = p; + + p = __reloc_pointer (p, map); + e += p - old; + reloc_range (p, e, map); +} + +/* Remap p, adjust e by the same offset, then map pointers referenced + by the (unadjusted) pointers in the range. Return the relocated + value of the last pointer in the range. */ +void* attribute_hidden +__reloc_range_indirect (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + void ***old = p; + + p = __reloc_pointer (p, map); + e += p - old; + return reloc_range_indirect (p, e, map); +} +#endif + +#endif /* __BFIN_FDPIC__ */ diff --git a/libc/sysdeps/linux/bfin/dma-memcpy.c b/libc/sysdeps/linux/bfin/dma-memcpy.c new file mode 100644 index 0000000..274b99e --- /dev/null +++ b/libc/sysdeps/linux/bfin/dma-memcpy.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall3 (__ptr_t, dma_memcpy, __ptr_t, dest, __ptr_t, src, size_t, len) + diff --git a/libc/sysdeps/linux/bfin/setjmp.S b/libc/sysdeps/linux/bfin/setjmp.S new file mode 100644 index 0000000..1b304f8 --- /dev/null +++ b/libc/sysdeps/linux/bfin/setjmp.S @@ -0,0 +1,96 @@ +/* setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2003 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global ___sigsetjmp; +.type ___sigsetjmp,STT_FUNC; +.align 4; + +___sigsetjmp: + [--SP] = P0; /* Save P0 */ + P0 = R0; + R0 = [SP++]; + [P0 + 0x00] = R0; /* Save saved P0 */ + [P0 + 0x04] = P1; + [P0 + 0x08] = P2; + [P0 + 0x0C] = P3; + [P0 + 0x10] = P4; + [P0 + 0x14] = P5; + + [P0 + 0x18] = FP; /* Frame Pointer */ + [P0 + 0x1C] = SP; /* Stack Pointer */ + + [P0 + 0x20] = P0; /* Data Registers */ + [P0 + 0x24] = R1; + [P0 + 0x28] = R2; + [P0 + 0x2C] = R3; + [P0 + 0x30] = R4; + [P0 + 0x34] = R5; + [P0 + 0x38] = R6; + [P0 + 0x3C] = R7; + + R0 = ASTAT; + [P0 + 0x40] = R0; + + R0 = LC0; /* Loop Counters */ + [P0 + 0x44] = R0; + R0 = LC1; + [P0 + 0x48] = R0; + + R0 = A0.W; /* Accumulators */ + [P0 + 0x4C] = R0; + R0 = A0.X; + [P0 + 0x50] = R0; + R0 = A1.W; + [P0 + 0x54] = R0; + R0 = A1.X; + [P0 + 0x58] = R0; + + R0 = I0; /* Index Registers */ + [P0 + 0x5C] = R0; + R0 = I1; + [P0 + 0x60] = R0; + R0 = I2; + [P0 + 0x64] = R0; + R0 = I3; + [P0 + 0x68] = R0; + + R0 = M0; /* Modifier Registers */ + [P0 + 0x6C] = R0; + R0 = M1; + [P0 + 0x70] = R0; + R0 = M2; + [P0 + 0x74] = R0; + R0 = M3; + [P0 + 0x78] = R0; + + R0 = L0; /* Length Registers */ + [P0 + 0x7c] = R0; + R0 = L1; + [P0 + 0x80] = R0; + R0 = L2; + [P0 + 0x84] = R0; + R0 = L3; + [P0 + 0x88] = R0; + + R0 = B0; /* Base Registers */ + [P0 + 0x8C] = R0; + R0 = B1; + [P0 + 0x90] = R0; + R0 = B2; + [P0 + 0x94] = R0; + R0 = B3; + [P0 + 0x98] = R0; + + R0 = RETS; + [P0 + 0x9C] = R0; + + R0 = [P0 + 0x20]; + JUMP.L ___sigjmp_save; +.size ___sigsetjmp, .-___sigsetjmp diff --git a/libc/sysdeps/linux/bfin/sram-alloc.c b/libc/sysdeps/linux/bfin/sram-alloc.c new file mode 100644 index 0000000..6b33b26 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sram-alloc.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall2 (__ptr_t, sram_alloc, size_t, len, unsigned long, flags) + diff --git a/libc/sysdeps/linux/bfin/sram-free.c b/libc/sysdeps/linux/bfin/sram-free.c new file mode 100644 index 0000000..0fba936 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sram-free.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall1 (__ptr_t, sram_free, __ptr_t, addr) + diff --git a/libc/sysdeps/linux/bfin/sys/elf.h b/libc/sysdeps/linux/bfin/sys/elf.h new file mode 100644 index 0000000..d959cdc --- /dev/null +++ b/libc/sysdeps/linux/bfin/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* _SYS_ELF_H */ diff --git a/libc/sysdeps/linux/bfin/sys/io.h b/libc/sysdeps/linux/bfin/sys/io.h new file mode 100644 index 0000000..6863990 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sys/io.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/bfin/sys/procfs.h b/libc/sysdeps/linux/bfin/sys/procfs.h new file mode 100644 index 0000000..45a65f3 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sys/procfs.h @@ -0,0 +1,125 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. Empty on the Blackfin. */ +typedef struct { } elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/bfin/sys/reg.h b/libc/sysdeps/linux/bfin/sys/reg.h new file mode 100644 index 0000000..4ce6e15 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sys/reg.h @@ -0,0 +1,133 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +enum +{ + PT_IPEND = 0, +#define PT_IPEND PT_IPEND + PT_SYSCFG = 4, +#define PT_SYSCFG PT_SYSCFG + PT_SR = 8, +#define PT_SR PT_SR + PT_RETE = 12, +#define PT_RETE PT_RETE + PT_RETN = 16, +#define PT_RETN PT_RETN + PT_RETX = 20, +#define PT_RETX PT_RETX + PT_PC = 24, +#define PT_PC PT_PC + PT_RETS = 28, +#define PT_RETS PT_RETS + PT_ASTAT = 32, +#define PT_ASTAT PT_ASTAT + PT_LB1 = 40, +#define PT_LB1 PT_LB1 + PT_LB0 = 44, +#define PT_LB0 PT_LB0 + PT_LT1 = 48, +#define PT_LT1 PT_LT1 + PT_LT0 = 52, +#define PT_LT0 PT_LT0 + PT_LC1 = 56, +#define PT_LC1 PT_LC1 + PT_LC0 = 60, +#define PT_LC0 PT_LC0 + PT_A1W = 64, +#define PT_A1W PT_A1W + PT_A1X = 68, +#define PT_A1X PT_A1X + PT_A0W = 72, +#define PT_A0W PT_A0W + PT_A0X = 76, +#define PT_A0X PT_A0X + PT_B3 = 80, +#define PT_B# PT_B3 + PT_B2 = 84, +#define PT_B2 PT_B2 + PT_B1 = 88, +#define PT_B1 PT_B1 + PT_B0 = 92, +#define PT_B0 PT_B0 + PT_L3 = 96, +#define PT_L3 PT_L3 + PT_L2 = 100, +#define PT_L2 PT_L2 + PT_L1 = 104, +#define PT_L1 PT_L1 + PT_L0 = 108, +#define PT_L0 PT_L0 + PT_M3 = 112, +#define PT_M3 PT_M3 + PT_M2 = 116, +#define PT_M2 PT_M2 + PT_M1 = 120, +#define PT_M1 PT_M1 + PT_M0 = 124, +#define PT_M0 PT_M0 + PT_I3 = 128, +#define PT_I3 PT_I3 + PT_I2 = 132, +#define PT_I2 PT_I2 + PT_I1 = 136, +#define PT_I1 PT_I1 + PT_I0 = 140, +#define PT_I0 PT_I0 + PT_USP = 144, +#define PT_USP PT_USP + PT_FP = 148, +#define PT_FP PT_FP + PT_P5 = 152, +#define PT_P5 PT_P5 + PT_P4 = 156, +#define PT_P4 PT_P4 + PT_P3 = 160, +#define PT_P3 PT_P3 + PT_P2 = 164, +#define PT_P2 PT_P2 + PT_P1 = 168, +#define PT_P1 PT_P1 + PT_P0 = 172, +#define PT_P0 PT_P0 + PT_R7 = 176, +#define PT_R7 PT_R7 + PT_R6 = 180, +#define PT_R6 PT_R6 + PT_R5 = 184, +#define PT_R5 PT_R5 + PT_R4 = 188, +#define PT_R4 PT_R4 + PT_R3 = 192, +#define PT_R3 PT_R3 + PT_R2 = 196, +#define PT_R2 PT_R2 + PT_R1 = 200, +#define PT_R1 PT_R1 + PT_R0 = 204, +#define PT_R0 PT_R0 + PT_ORIG_R0 = 208, +#define PT_ORIG_R0 PT_ORIG_R0 +}; + +#endif /* _SYS_REG_H */ diff --git a/libc/sysdeps/linux/bfin/sys/ucontext.h b/libc/sysdeps/linux/bfin/sys/ucontext.h new file mode 100644 index 0000000..ac2ef94 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sys/ucontext.h @@ -0,0 +1,152 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/blackfin ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 47 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_R0 = 0, +#define REG_R0 REG_R0 + REG_R1 = 1, +#define REG_R1 REG_R1 + REG_R2 = 2, +#define REG_R2 REG_R2 + REG_R3 = 3, +#define REG_R3 REG_R3 + REG_R4 = 4, +#define REG_R4 REG_R4 + REG_R5 = 5, +#define REG_R5 REG_R5 + REG_R6 = 6, +#define REG_R6 REG_R6 + REG_R7 = 7, +#define REG_R7 REG_R7 + REG_P0 = 8, +#define REG_P0 REG_P0 + REG_P1 = 9, +#define REG_P1 REG_P1 + REG_P2 = 10, +#define REG_P2 REG_P2 + REG_P3 = 11, +#define REG_P3 REG_P3 + REG_P4 = 12, +#define REG_P4 REG_P4 + REG_P5 = 13, +#define REG_P5 REG_P5 + REG_USP = 14, +#define REG_USP REG_USP + REG_A0W = 15, +#define REG_A0W REG_A0W + REG_A1W = 16, +#define REG_A1W REG_A1W + REG_A0X = 17, +#define REG_A0X REG_A0X + REG_A1X = 18, +#define REG_A1X REG_A1X + REG_ASTAT = 19, +#define REG_ASTAT REG_ASTAT + REG_RETS = 20, +#define REG_RETS REG_RETS + REG_PC= 21, +#define REG_PC REG_PC + REG_RETX = 22, +#define REG_RETX REG_RETX + REG_FP = 23, +#define REG_FP REG_FP + REG_I0 = 24, +#define REG_I0 REG_I0 + REG_I1 = 25, +#define REG_I1 REG_I1 + REG_I2 = 26, +#define REG_I2 REG_I2 + REG_I3 = 27, +#define REG_I3 REG_I3 + REG_M0 = 28, +#define REG_M0 REG_M0 + REG_M1 = 29, +#define REG_M1 REG_M1 + REG_M2 = 30, +#define REG_M2 REG_M2 + REG_M3 = 31, +#define REG_M3 REG_M3 + REG_L0 = 32, +#define REG_L0 REG_L0 + REG_L1 = 33, +#define REG_L1 REG_L1 + REG_L2 = 34, +#define REG_L2 REG_L2 + REG_L3 = 35, +#define REG_L3 REG_L3 + REG_B_0 = 36, +#define REG_B0 REG_B0 + REG_B1 = 37, +#define REG_B1 REG_B1 + REG_B2 = 38, +#define REG_B2 REG_B2 + REG_B3 = 39, +#define REG_B3 REG_B3 + REG_LC0 = 40, +#define REG_LC0 REG_LC0 + REG_LC1 = 41, +#define REG_LC1 REG_LC1 + REG_LT0 = 42, +#define REG_LT0 REG_LT0 + REG_LT1 = 43, +#define REG_LT1 REG_LT1 + REG_LB0 = 44, +#define REG_LB0 REG_LB0 + REG_LB1 = 45, +#define REG_LB1 REG_LB1 + REG_SEQSTAT = 46 +#define REG_SEQSTAT REG_SEQSTAT +}; + +/* Context to describe whole processor state. */ +typedef struct +{ + gregset_t gregs; +} mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/bfin/syscall.c b/libc/sysdeps/linux/bfin/syscall.c new file mode 100644 index 0000000..1db8738 --- /dev/null +++ b/libc/sysdeps/linux/bfin/syscall.c @@ -0,0 +1,57 @@ +/* vi: set sw=4 ts=4: */ +/* syscall for blackfin/uClibc + * + * Copyright (C) 2004-2006 by Analog Devices Inc. + * Copyright (C) 2002 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ + int _r0 = 0; + + __asm__ __volatile__ ( + "R5 = %7;" + "R4 = %6;" + "R3 = %5;" + "R2 = %4;" + "R1 = %3;" + "R0 = %2;" + "P0 = %1;" + "excpt 0;" + "%0 = R0;" + : "=r" (_r0) + : "rm" (sysnum), + "rm" (a), + "rm" (b), + "rm" (c), + "rm" (d), + "rm" (e), + "rm" (f) + : "memory","CC","R0","R1","R2","R3","R4","R5","P0"); + + if (_r0 >= (unsigned long) -4095) { + (*__errno_location()) = (-_r0); + _r0 = (unsigned long) -1; + } + + return (long)_r0; +} diff --git a/libc/sysdeps/linux/bfin/sysdep.h b/libc/sysdeps/linux/bfin/sysdep.h new file mode 100644 index 0000000..4080c22 --- /dev/null +++ b/libc/sysdeps/linux/bfin/sysdep.h @@ -0,0 +1,20 @@ +/* + * libc/sysdeps/linux/bfin/sysdep.h + * + * Copyright (C) 2007 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __BFIN_SYSDEP_H__ +#define __BFIN_SYSDEP_H__ + +#include + +#ifdef __ASSEMBLER__ + +#define ENTRY(sym) .global sym; .type sym, STT_FUNC; sym: + +#endif + +#endif diff --git a/libc/sysdeps/linux/bfin/vfork.S b/libc/sysdeps/linux/bfin/vfork.S new file mode 100644 index 0000000..4e9aa84 --- /dev/null +++ b/libc/sysdeps/linux/bfin/vfork.S @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +.text +.global ___vfork +.hidden ___vfork +.type ___vfork,STT_FUNC; +.align 4 +___vfork: + p0 = __NR_vfork; + excpt 0; + rts; +.size ___vfork,.-___vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/common/.indent.pro b/libc/sysdeps/linux/common/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/sysdeps/linux/common/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/sysdeps/linux/common/Makefile b/libc/sysdeps/linux/common/Makefile new file mode 100644 index 0000000..3ed177a --- /dev/null +++ b/libc/sysdeps/linux/common/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in new file mode 100644 index 0000000..e9fa802 --- /dev/null +++ b/libc/sysdeps/linux/common/Makefile.in @@ -0,0 +1,102 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +COMMON_DIR := $(top_srcdir)libc/sysdeps/linux/common +COMMON_OUT := $(top_builddir)libc/sysdeps/linux/common + +CSRC := $(notdir $(wildcard $(COMMON_DIR)/*.c)) + +ifeq ($(EXCLUDE_BRK),y) +CSRC := $(filter-out sbrk.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_LFS),y) +CSRC_LFS := $(notdir $(wildcard $(COMMON_DIR)/*64.c)) +CSRC := $(filter-out llseek.c $(CSRC_LFS),$(CSRC)) +endif + +CSRC := $(filter-out ssp-local.c,$(CSRC)) +ifneq ($(UCLIBC_HAS_SSP),y) +CSRC := $(filter-out ssp.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_LINUX_MODULE_24),y) +CSRC := $(filter-out create_module.c query_module.c get_kernel_syms.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_LINUX_SPECIFIC),y) +# we need these internally: fstatfs.c statfs.c +CSRC := $(filter-out inotify.c ioperm.c iopl.c madvise.c \ + modify_ldt.c personality.c prctl.c readahead.c reboot.c \ + remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \ + sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \ + splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \ + sync_file_range.c sysctl.c sysinfo.c uselib.c vhangup.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_BSD_SPECIFIC),y) +# we need these internally: getdomainname.c +CSRC := $(filter-out mincore.c setdomainname.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_NTP_LEGACY),y) +CSRC := $(filter-out ntp_gettime.c,$(CSRC)) +endif + + +ifneq ($(UCLIBC_HAS_REALTIME),y) +# aio_cancel|aio_error|aio_fsync|aio_read|aio_return|aio_suspend|aio_write|clock_getres|clock_gettime|clock_settime|clock_settime|fdatasync|lio_listio|mlockall|munlockall|mlock|munlock|mq_close|mq_getattr|mq_notify|mq_open|mq_receive|mq_timedreceive|mq_send|mq_timedsend|mq_setattr|mq_unlink|nanosleep|sched_getparam|sched_get_priority_max|sched_get_priority_min|sched_getscheduler|sched_rr_get_interval|sched_setparam|sched_setscheduler|sem_close|sem_destroy|sem_getvalue|sem_init|sem_open|sem_post|sem_trywait|sem_wait|sem_unlink|sem_wait|shm_open|shm_unlink|sigqueue|sigtimedwait|sigwaitinfo|sigwaitinfo|timer_create|timer_delete|timer_getoverrun|timer_gettime|timer_settime +CSRC := $(filter-out clock_getres.c clock_gettime.c clock_settime.c fdatasync.c Makefile.in mlockall.c mlock.c munlockall.c munlock.c nanosleep.c __rt_sigtimedwait.c sched_getparam.c sched_get_priority_max.c sched_get_priority_min.c sched_getscheduler.c sched_rr_get_interval.c sched_setparam.c sched_setscheduler.c sigqueue.c,$(CSRC)) +endif + + +ifneq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +# clock_getcpuclockid|clock_nanosleep|mq_timedreceive|mq_timedsend|posix_fadvise|posix_fallocate|posix_madvise|posix_memalign|posix_mem_offset|posix_spawnattr_destroy|posix_spawnattr_init|posix_spawnattr_getflags|posix_spawnattr_setflags|posix_spawnattr_getpgroup|posix_spawnattr_setpgroup|posix_spawnattr_getschedparam|posix_spawnattr_setschedparam|posix_spawnattr_getschedpolicy|posix_spawnattr_setschedpolicy|posix_spawnattr_getsigdefault|posix_spawnattr_setsigdefault|posix_spawnattr_getsigmask|posix_spawnattr_setsigmask|posix_spawnattr_init|posix_spawnattr_setflags|posix_spawnattr_setpgroup|posix_spawnattr_setschedparam|posix_spawnattr_setschedpolicy|posix_spawnattr_setsigdefault|posix_spawnattr_setsigmask|posix_spawn_file_actions_addclose|posix_spawn_file_actions_addopen|posix_spawn_file_actions_adddup2|posix_spawn_file_actions_addopen|posix_spawn_file_actions_destroy|posix_spawn_file_actions_init|posix_spawn_file_actions_init|posix_spawn|posix_spawnp|posix_spawnp|posix_typed_mem_get_info|pthread_mutex_timedlock|sem_timedwait +CSRC := $(filter-out posix_fadvise64.c posix_fadvise.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_EPOLL),y) +CSRC := $(filter-out epoll.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_XATTR),y) +CSRC := $(filter-out xattr.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_PROFILING),y) +CSRC := $(filter-out noophooks.c pcprofile.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_SV4_DEPRECATED),y) +CSRC := $(filter-out ustat.c,$(CSRC)) +endif + +# fails for some reason +ifneq ($(strip $(ARCH_OBJS)),) +CSRC := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)),$(CSRC)) +endif + +CFLAGS-ssp.c := $(SSP_DISABLE_FLAGS) +CFLAGS-ssp-local.c := $(SSP_DISABLE_FLAGS) + +COMMON_SRC := $(patsubst %.c,$(COMMON_DIR)/%.c,$(CSRC)) +COMMON_OBJ := $(patsubst %.c,$(COMMON_OUT)/%.o,$(CSRC)) + +libc-y += $(COMMON_OBJ) +libc-static-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp-local.o +libc-nonshared-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp-local.os + +libc-nomulti-y += $(COMMON_OUT)/__syscall_rt_sigaction.o \ + $(COMMON_OUT)/__syscall_sigaction.o \ + $(COMMON_OUT)/mremap.o \ + $(COMMON_OUT)/stat.o +libc-nomulti-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp.o + +objclean-y += common_clean + +common_clean: + $(do_rm) $(addprefix $(COMMON_OUT)/*., o os oS) diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c new file mode 100644 index 0000000..c018043 --- /dev/null +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* + * __rt_sigtimedwait() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#define __need_NULL +#include + +libc_hidden_proto(sigwaitinfo) +libc_hidden_proto(sigtimedwait) + +#ifdef __NR_rt_sigtimedwait +#define __NR___rt_sigtimedwait __NR_rt_sigtimedwait +static _syscall4(int, __rt_sigtimedwait, const sigset_t *, set, siginfo_t *, info, + const struct timespec *, timeout, size_t, setsize) + +int sigwaitinfo(const sigset_t * set, siginfo_t * info) +{ + return __rt_sigtimedwait(set, info, NULL, _NSIG / 8); +} + +int sigtimedwait(const sigset_t * set, siginfo_t * info, + const struct timespec *timeout) +{ + return __rt_sigtimedwait(set, info, timeout, _NSIG / 8); +} +#else +int sigwaitinfo(const sigset_t * set, siginfo_t * info) +{ + if (set == NULL) + __set_errno(EINVAL); + else + __set_errno(ENOSYS); + return -1; +} + +int sigtimedwait(const sigset_t * set, siginfo_t * info, + const struct timespec *timeout) +{ + if (set == NULL) + __set_errno(EINVAL); + else + __set_errno(ENOSYS); + return -1; +} +#endif +libc_hidden_def(sigwaitinfo) +libc_hidden_def(sigtimedwait) diff --git a/libc/sysdeps/linux/common/__socketcall.c b/libc/sysdeps/linux/common/__socketcall.c new file mode 100644 index 0000000..e49fb21 --- /dev/null +++ b/libc/sysdeps/linux/common/__socketcall.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * __socketcall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __NR_socketcall +#define __NR___socketcall __NR_socketcall +int __socketcall(int __call, unsigned long *__args) attribute_hidden; +_syscall2(int, __socketcall, int, call, unsigned long *, args) +#endif diff --git a/libc/sysdeps/linux/common/__syscall_fcntl.c b/libc/sysdeps/linux/common/__syscall_fcntl.c new file mode 100644 index 0000000..a3fb74f --- /dev/null +++ b/libc/sysdeps/linux/common/__syscall_fcntl.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_fcntl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +extern __typeof(fcntl) __libc_fcntl; +libc_hidden_proto(__libc_fcntl) + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 +extern __typeof(fcntl64) __libc_fcntl64; +libc_hidden_proto(__libc_fcntl64) +#endif + +#define __NR___syscall_fcntl __NR_fcntl +static __always_inline +_syscall3(int, __syscall_fcntl, int, fd, int, cmd, long, arg) + +int __libc_fcntl(int fd, int cmd, ...) +{ + long arg; + va_list list; + + va_start(list, cmd); + arg = va_arg(list, long); + va_end(list); + +#if __WORDSIZE == 32 + if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64) { +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + return __libc_fcntl64(fd, cmd, arg); +#else + __set_errno(ENOSYS); + return -1; +#endif + } +#endif + + return (__syscall_fcntl(fd, cmd, arg)); +} +libc_hidden_def(__libc_fcntl) + +libc_hidden_proto(fcntl) +weak_alias(__libc_fcntl,fcntl) +libc_hidden_weak(fcntl) +#if ! defined __NR_fcntl64 && defined __UCLIBC_HAS_LFS__ +strong_alias(__libc_fcntl,__libc_fcntl64) +libc_hidden_proto(fcntl64) +weak_alias(__libc_fcntl,fcntl64) +libc_hidden_weak(fcntl64) +#endif diff --git a/libc/sysdeps/linux/common/__syscall_fcntl64.c b/libc/sysdeps/linux/common/__syscall_fcntl64.c new file mode 100644 index 0000000..579e0e2 --- /dev/null +++ b/libc/sysdeps/linux/common/__syscall_fcntl64.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_fcntl64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 +extern __typeof(fcntl64) __libc_fcntl64; +libc_hidden_proto(__libc_fcntl64) + +#define __NR___syscall_fcntl64 __NR_fcntl64 +static __inline__ _syscall3(int, __syscall_fcntl64, int, fd, int, cmd, long, arg) +int __libc_fcntl64(int fd, int cmd, ...) +{ + long arg; + va_list list; + + va_start(list, cmd); + arg = va_arg(list, long); + va_end(list); + + return (__syscall_fcntl64(fd, cmd, arg)); +} +libc_hidden_def(__libc_fcntl64) + +libc_hidden_proto(fcntl64) +strong_alias(__libc_fcntl64,fcntl64) +libc_hidden_weak(fcntl64) +#endif diff --git a/libc/sysdeps/linux/common/__syscall_rt_sigaction.c b/libc/sysdeps/linux/common/__syscall_rt_sigaction.c new file mode 100644 index 0000000..b4b007d --- /dev/null +++ b/libc/sysdeps/linux/common/__syscall_rt_sigaction.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_rt_sigaction() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_rt_sigaction +#include + +int __syscall_rt_sigaction (int __signum, const struct sigaction *__act, struct sigaction *__oldact, size_t __size) attribute_hidden; +#define __NR___syscall_rt_sigaction __NR_rt_sigaction +_syscall4(int, __syscall_rt_sigaction, int, signum, + const struct sigaction *, act, struct sigaction *, oldact, + size_t, size) +#endif diff --git a/libc/sysdeps/linux/common/__syscall_sigaction.c b/libc/sysdeps/linux/common/__syscall_sigaction.c new file mode 100644 index 0000000..ae0f01e --- /dev/null +++ b/libc/sysdeps/linux/common/__syscall_sigaction.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_sigaction() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_rt_sigaction +#define __NR___syscall_sigaction __NR_sigaction +#include +int __syscall_sigaction (int __signum, const struct sigaction *__act, struct sigaction *__oldact) attribute_hidden; +_syscall3(int, __syscall_sigaction, int, signum, const struct sigaction *, + act, struct sigaction *, oldact) +#endif + diff --git a/libc/sysdeps/linux/common/_exit.c b/libc/sysdeps/linux/common/_exit.c new file mode 100644 index 0000000..4a654a6 --- /dev/null +++ b/libc/sysdeps/linux/common/_exit.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * exit syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(_exit) + +#ifndef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) __syscall_exit (args) +#define __NR___syscall_exit __NR_exit +static __inline__ _syscall1(void, __syscall_exit, int, status) +#endif + +void attribute_noreturn _exit(int status) +{ + /* The loop is added only to keep gcc happy. */ + while(1) + INLINE_SYSCALL(exit, 1, status); +} +libc_hidden_def(_exit) diff --git a/libc/sysdeps/linux/common/access.c b/libc/sysdeps/linux/common/access.c new file mode 100644 index 0000000..a075d42 --- /dev/null +++ b/libc/sysdeps/linux/common/access.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * access() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, access, const char *, pathname, int, mode) diff --git a/libc/sysdeps/linux/common/acct.c b/libc/sysdeps/linux/common/acct.c new file mode 100644 index 0000000..e0a4320 --- /dev/null +++ b/libc/sysdeps/linux/common/acct.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * acct() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall1(int, acct, const char *, filename) +#endif diff --git a/libc/sysdeps/linux/common/adjtimex.c b/libc/sysdeps/linux/common/adjtimex.c new file mode 100644 index 0000000..05e3679 --- /dev/null +++ b/libc/sysdeps/linux/common/adjtimex.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * adjtimex() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(adjtimex) + +_syscall1(int, adjtimex, struct timex *, buf) +libc_hidden_def(adjtimex) +#if defined __UCLIBC_NTP_LEGACY__ +strong_alias(adjtimex,ntp_adjtime) +#endif diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c new file mode 100644 index 0000000..224656c --- /dev/null +++ b/libc/sysdeps/linux/common/alarm.c @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* + * alarm() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(alarm) + +#ifdef __NR_alarm +#define __NR___alarm __NR_alarm +_syscall1(unsigned int, alarm, unsigned int, seconds) +#else +#include + +libc_hidden_proto(setitimer) + +unsigned int alarm(unsigned int seconds) +{ + struct itimerval old, new; + unsigned int retval; + + new.it_value.tv_usec = 0; + new.it_interval.tv_sec = 0; + new.it_interval.tv_usec = 0; + new.it_value.tv_sec = (long int) seconds; + if (setitimer(ITIMER_REAL, &new, &old) < 0) { + return 0; + } + retval = old.it_value.tv_sec; + if (old.it_value.tv_usec) { + ++retval; + } + return retval; +} +#endif +libc_hidden_def(alarm) diff --git a/libc/sysdeps/linux/common/arch_prctl.c b/libc/sysdeps/linux/common/arch_prctl.c new file mode 100644 index 0000000..5816f53 --- /dev/null +++ b/libc/sysdeps/linux/common/arch_prctl.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * arch_prctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_arch_prctl +extern int arch_prctl(int code, unsigned long addr); +_syscall2(int, arch_prctl, int, code, unsigned long, addr) +#endif diff --git a/libc/sysdeps/linux/common/bdflush.c b/libc/sysdeps/linux/common/bdflush.c new file mode 100644 index 0000000..687a8f9 --- /dev/null +++ b/libc/sysdeps/linux/common/bdflush.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * bdflush() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_bdflush +_syscall2(int, bdflush, int, __func, long int, __data) +#else +int bdflush(int __func, long int __data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/bits/atomic.h b/libc/sysdeps/linux/common/bits/atomic.h new file mode 100644 index 0000000..6245130 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/atomic.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +/* We have by default no support for atomic operations. So define + them non-atomic. If this is a problem somebody will have to come + up with real definitions. */ + +/* The only basic operation needed is compare and exchange. */ +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ __typeof (mem) __gmemp = (mem); \ + __typeof (*mem) __gret = *__gmemp; \ + __typeof (*mem) __gnewval = (newval); \ + \ + if (__gret == (oldval)) \ + *__gmemp = __gnewval; \ + __gret; }) + +#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ __typeof (mem) __gmemp = (mem); \ + __typeof (*mem) __gnewval = (newval); \ + \ + *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; }) + +#endif /* bits/atomic.h */ diff --git a/libc/sysdeps/linux/common/bits/byteswap.h b/libc/sysdeps/linux/common/bits/byteswap.h new file mode 100644 index 0000000..949ed0b --- /dev/null +++ b/libc/sysdeps/linux/common/bits/byteswap.h @@ -0,0 +1,87 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997,1998,2000,2001,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)) + +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __bsx = (x); __bswap_constant_16 (__bsx); })) +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ + (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __bsx = (x); __bswap_constant_32 (__bsx); })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/common/bits/cmathcalls.h b/libc/sysdeps/linux/common/bits/cmathcalls.h new file mode 100644 index 0000000..762c1e3 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/cmathcalls.h @@ -0,0 +1,181 @@ +/* Prototype declarations for complex math functions; + helper file for . + Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* NOTE: Because of the special way this file is used by , this + file must NOT be protected from multiple inclusion as header files + usually are. + + This file provides prototype declarations for the math functions. + Most functions are declared using the macro: + + __MATHCALL (NAME, (ARGS...)); + + This means there is a function `NAME' returning `double' and a function + `NAMEf' returning `float'. Each place `_Mdouble_' appears in the + prototype, that is actually `double' in the prototype for `NAME' and + `float' in the prototype for `NAMEf'. Reentrant variant functions are + called `NAME_r' and `NAMEf_r'. + + Functions returning other types like `int' are declared using the macro: + + __MATHDECL (TYPE, NAME, (ARGS...)); + + This is just like __MATHCALL but for a function returning `TYPE' + instead of `_Mdouble_'. In all of these cases, there is still + both a `NAME' and a `NAMEf' that takes `float' arguments. */ + +#ifndef _COMPLEX_H +#error "Never use directly; include instead." +#endif + +#define _Mdouble_complex_ _Mdouble_ _Complex + + +/* Trigonometric functions. */ + +/* Arc cosine of Z. */ +__MATHCALL (cacos, (_Mdouble_complex_ __z)); +libm_hidden_proto(cacos) +/* Arc sine of Z. */ +__MATHCALL (casin, (_Mdouble_complex_ __z)); +libm_hidden_proto(casin) +/* Arc tangent of Z. */ +__MATHCALL (catan, (_Mdouble_complex_ __z)); +libm_hidden_proto(catan) + +/* Cosine of Z. */ +__MATHCALL (ccos, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccos) +/* Sine of Z. */ +__MATHCALL (csin, (_Mdouble_complex_ __z)); +libm_hidden_proto(csin) +/* Tangent of Z. */ +__MATHCALL (ctan, (_Mdouble_complex_ __z)); +libm_hidden_proto(ctan) + + +/* Hyperbolic functions. */ + +/* Hyperbolic arc cosine of Z. */ +__MATHCALL (cacosh, (_Mdouble_complex_ __z)); +libm_hidden_proto(cacosh) +/* Hyperbolic arc sine of Z. */ +__MATHCALL (casinh, (_Mdouble_complex_ __z)); +libm_hidden_proto(casinh) +/* Hyperbolic arc tangent of Z. */ +__MATHCALL (catanh, (_Mdouble_complex_ __z)); +libm_hidden_proto(catanh) + +/* Hyperbolic cosine of Z. */ +__MATHCALL (ccosh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccosh) +/* Hyperbolic sine of Z. */ +__MATHCALL (csinh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccosh) +/* Hyperbolic tangent of Z. */ +__MATHCALL (ctanh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ctanh) + + +/* Exponential and logarithmic functions. */ + +/* Exponential function of Z. */ +__MATHCALL (cexp, (_Mdouble_complex_ __z)); +libm_hidden_proto(cexp) + +/* Natural logarithm of Z. */ +__MATHCALL (clog, (_Mdouble_complex_ __z)); +libm_hidden_proto(clog) + +#ifdef __USE_GNU +/* The base 10 logarithm is not defined by the standard but to implement + the standard C++ library it is handy. */ +__MATHCALL (clog10, (_Mdouble_complex_ __z)); +libm_hidden_proto(clog10) +#endif + +/* Power functions. */ + +/* Return X to the Y power. */ +__MATHCALL (cpow, (_Mdouble_complex_ __x, _Mdouble_complex_ __y)); +libm_hidden_proto(cpow) + +/* Return the square root of Z. */ +__MATHCALL (csqrt, (_Mdouble_complex_ __z)); +libm_hidden_proto(csqrt) + + +/* Absolute value, conjugates, and projection. */ + +/* Absolute value of Z. */ +__MATHDECL (_Mdouble_,cabs, (_Mdouble_complex_ __z)); +libm_hidden_proto(cabs) + +/* Argument value of Z. */ +__MATHDECL (_Mdouble_,carg, (_Mdouble_complex_ __z)); +libm_hidden_proto(carg) + +/* Complex conjugate of Z. */ +__MATHCALL (conj, (_Mdouble_complex_ __z)); +libm_hidden_proto(conj) + +/* Projection of Z onto the Riemann sphere. */ +__MATHCALL (cproj, (_Mdouble_complex_ __z)); +libm_hidden_proto(cproj) + + +/* Decomposing complex values. */ + +/* Imaginary part of Z. */ +__MATHDECL (_Mdouble_,cimag, (_Mdouble_complex_ __z)); +libm_hidden_proto(cimag) + +/* Real part of Z. */ +__MATHDECL (_Mdouble_,creal, (_Mdouble_complex_ __z)); +libm_hidden_proto(creal) + + +/* Now some optimized versions. GCC has handy notations for these + functions. Recent GCC handles these as builtin functions so does + not need inlines. */ +#if defined __GNUC__ && !__GNUC_PREREQ (2, 97) && defined __OPTIMIZE__ + +/* Imaginary part of Z. */ +__extern_inline _Mdouble_ +__MATH_PRECNAME(cimag) (_Mdouble_complex_ __z) __THROW +{ + return __imag__ __z; +} + +/* Real part of Z. */ +__extern_inline _Mdouble_ +__MATH_PRECNAME(creal) (_Mdouble_complex_ __z) __THROW +{ + return __real__ __z; +} + +/* Complex conjugate of Z. */ +__extern_inline _Mdouble_complex_ +__MATH_PRECNAME(conj) (_Mdouble_complex_ __z) __THROW +{ + return __extension__ ~__z; +} + +#endif diff --git a/libc/sysdeps/linux/common/bits/confname.h b/libc/sysdeps/linux/common/bits/confname.h new file mode 100644 index 0000000..ab7fdee --- /dev/null +++ b/libc/sysdeps/linux/common/bits/confname.h @@ -0,0 +1,606 @@ +/* `sysconf', `pathconf', and `confstr' NAME values. Generic version. + Copyright (C) 1993,1995-1998,2000,2001,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never use directly; include instead." +#endif + +/* Values for the NAME argument to `pathconf' and `fpathconf'. */ +enum + { + _PC_LINK_MAX, +#define _PC_LINK_MAX _PC_LINK_MAX + _PC_MAX_CANON, +#define _PC_MAX_CANON _PC_MAX_CANON + _PC_MAX_INPUT, +#define _PC_MAX_INPUT _PC_MAX_INPUT + _PC_NAME_MAX, +#define _PC_NAME_MAX _PC_NAME_MAX + _PC_PATH_MAX, +#define _PC_PATH_MAX _PC_PATH_MAX + _PC_PIPE_BUF, +#define _PC_PIPE_BUF _PC_PIPE_BUF + _PC_CHOWN_RESTRICTED, +#define _PC_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED + _PC_NO_TRUNC, +#define _PC_NO_TRUNC _PC_NO_TRUNC + _PC_VDISABLE, +#define _PC_VDISABLE _PC_VDISABLE + _PC_SYNC_IO, +#define _PC_SYNC_IO _PC_SYNC_IO + _PC_ASYNC_IO, +#define _PC_ASYNC_IO _PC_ASYNC_IO + _PC_PRIO_IO, +#define _PC_PRIO_IO _PC_PRIO_IO + _PC_SOCK_MAXBUF, +#define _PC_SOCK_MAXBUF _PC_SOCK_MAXBUF + _PC_FILESIZEBITS, +#define _PC_FILESIZEBITS _PC_FILESIZEBITS + _PC_REC_INCR_XFER_SIZE, +#define _PC_REC_INCR_XFER_SIZE _PC_REC_INCR_XFER_SIZE + _PC_REC_MAX_XFER_SIZE, +#define _PC_REC_MAX_XFER_SIZE _PC_REC_MAX_XFER_SIZE + _PC_REC_MIN_XFER_SIZE, +#define _PC_REC_MIN_XFER_SIZE _PC_REC_MIN_XFER_SIZE + _PC_REC_XFER_ALIGN, +#define _PC_REC_XFER_ALIGN _PC_REC_XFER_ALIGN + _PC_ALLOC_SIZE_MIN, +#define _PC_ALLOC_SIZE_MIN _PC_ALLOC_SIZE_MIN + _PC_SYMLINK_MAX, +#define _PC_SYMLINK_MAX _PC_SYMLINK_MAX + _PC_2_SYMLINKS +#define _PC_2_SYMLINKS _PC_2_SYMLINKS + }; + +/* Values for the argument to `sysconf'. */ +enum + { + _SC_ARG_MAX, +#define _SC_ARG_MAX _SC_ARG_MAX + _SC_CHILD_MAX, +#define _SC_CHILD_MAX _SC_CHILD_MAX + _SC_CLK_TCK, +#define _SC_CLK_TCK _SC_CLK_TCK + _SC_NGROUPS_MAX, +#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX + _SC_OPEN_MAX, +#define _SC_OPEN_MAX _SC_OPEN_MAX + _SC_STREAM_MAX, +#define _SC_STREAM_MAX _SC_STREAM_MAX + _SC_TZNAME_MAX, +#define _SC_TZNAME_MAX _SC_TZNAME_MAX + _SC_JOB_CONTROL, +#define _SC_JOB_CONTROL _SC_JOB_CONTROL + _SC_SAVED_IDS, +#define _SC_SAVED_IDS _SC_SAVED_IDS + _SC_REALTIME_SIGNALS, +#define _SC_REALTIME_SIGNALS _SC_REALTIME_SIGNALS + _SC_PRIORITY_SCHEDULING, +#define _SC_PRIORITY_SCHEDULING _SC_PRIORITY_SCHEDULING + _SC_TIMERS, +#define _SC_TIMERS _SC_TIMERS + _SC_ASYNCHRONOUS_IO, +#define _SC_ASYNCHRONOUS_IO _SC_ASYNCHRONOUS_IO + _SC_PRIORITIZED_IO, +#define _SC_PRIORITIZED_IO _SC_PRIORITIZED_IO + _SC_SYNCHRONIZED_IO, +#define _SC_SYNCHRONIZED_IO _SC_SYNCHRONIZED_IO + _SC_FSYNC, +#define _SC_FSYNC _SC_FSYNC + _SC_MAPPED_FILES, +#define _SC_MAPPED_FILES _SC_MAPPED_FILES + _SC_MEMLOCK, +#define _SC_MEMLOCK _SC_MEMLOCK + _SC_MEMLOCK_RANGE, +#define _SC_MEMLOCK_RANGE _SC_MEMLOCK_RANGE + _SC_MEMORY_PROTECTION, +#define _SC_MEMORY_PROTECTION _SC_MEMORY_PROTECTION + _SC_MESSAGE_PASSING, +#define _SC_MESSAGE_PASSING _SC_MESSAGE_PASSING + _SC_SEMAPHORES, +#define _SC_SEMAPHORES _SC_SEMAPHORES + _SC_SHARED_MEMORY_OBJECTS, +#define _SC_SHARED_MEMORY_OBJECTS _SC_SHARED_MEMORY_OBJECTS + _SC_AIO_LISTIO_MAX, +#define _SC_AIO_LISTIO_MAX _SC_AIO_LISTIO_MAX + _SC_AIO_MAX, +#define _SC_AIO_MAX _SC_AIO_MAX + _SC_AIO_PRIO_DELTA_MAX, +#define _SC_AIO_PRIO_DELTA_MAX _SC_AIO_PRIO_DELTA_MAX + _SC_DELAYTIMER_MAX, +#define _SC_DELAYTIMER_MAX _SC_DELAYTIMER_MAX + _SC_MQ_OPEN_MAX, +#define _SC_MQ_OPEN_MAX _SC_MQ_OPEN_MAX + _SC_MQ_PRIO_MAX, +#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX + _SC_VERSION, +#define _SC_VERSION _SC_VERSION + _SC_PAGESIZE, +#define _SC_PAGESIZE _SC_PAGESIZE +#define _SC_PAGE_SIZE _SC_PAGESIZE + _SC_RTSIG_MAX, +#define _SC_RTSIG_MAX _SC_RTSIG_MAX + _SC_SEM_NSEMS_MAX, +#define _SC_SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX + _SC_SEM_VALUE_MAX, +#define _SC_SEM_VALUE_MAX _SC_SEM_VALUE_MAX + _SC_SIGQUEUE_MAX, +#define _SC_SIGQUEUE_MAX _SC_SIGQUEUE_MAX + _SC_TIMER_MAX, +#define _SC_TIMER_MAX _SC_TIMER_MAX + + /* Values for the argument to `sysconf' + corresponding to _POSIX2_* symbols. */ + _SC_BC_BASE_MAX, +#define _SC_BC_BASE_MAX _SC_BC_BASE_MAX + _SC_BC_DIM_MAX, +#define _SC_BC_DIM_MAX _SC_BC_DIM_MAX + _SC_BC_SCALE_MAX, +#define _SC_BC_SCALE_MAX _SC_BC_SCALE_MAX + _SC_BC_STRING_MAX, +#define _SC_BC_STRING_MAX _SC_BC_STRING_MAX + _SC_COLL_WEIGHTS_MAX, +#define _SC_COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX + _SC_EQUIV_CLASS_MAX, +#define _SC_EQUIV_CLASS_MAX _SC_EQUIV_CLASS_MAX + _SC_EXPR_NEST_MAX, +#define _SC_EXPR_NEST_MAX _SC_EXPR_NEST_MAX + _SC_LINE_MAX, +#define _SC_LINE_MAX _SC_LINE_MAX + _SC_RE_DUP_MAX, +#define _SC_RE_DUP_MAX _SC_RE_DUP_MAX + _SC_CHARCLASS_NAME_MAX, +#define _SC_CHARCLASS_NAME_MAX _SC_CHARCLASS_NAME_MAX + + _SC_2_VERSION, +#define _SC_2_VERSION _SC_2_VERSION + _SC_2_C_BIND, +#define _SC_2_C_BIND _SC_2_C_BIND + _SC_2_C_DEV, +#define _SC_2_C_DEV _SC_2_C_DEV + _SC_2_FORT_DEV, +#define _SC_2_FORT_DEV _SC_2_FORT_DEV + _SC_2_FORT_RUN, +#define _SC_2_FORT_RUN _SC_2_FORT_RUN + _SC_2_SW_DEV, +#define _SC_2_SW_DEV _SC_2_SW_DEV + _SC_2_LOCALEDEF, +#define _SC_2_LOCALEDEF _SC_2_LOCALEDEF + + _SC_PII, +#define _SC_PII _SC_PII + _SC_PII_XTI, +#define _SC_PII_XTI _SC_PII_XTI + _SC_PII_SOCKET, +#define _SC_PII_SOCKET _SC_PII_SOCKET + _SC_PII_INTERNET, +#define _SC_PII_INTERNET _SC_PII_INTERNET + _SC_PII_OSI, +#define _SC_PII_OSI _SC_PII_OSI + _SC_POLL, +#define _SC_POLL _SC_POLL + _SC_SELECT, +#define _SC_SELECT _SC_SELECT + _SC_UIO_MAXIOV, +#define _SC_UIO_MAXIOV _SC_UIO_MAXIOV + _SC_IOV_MAX = _SC_UIO_MAXIOV, +#define _SC_IOV_MAX _SC_IOV_MAX + _SC_PII_INTERNET_STREAM, +#define _SC_PII_INTERNET_STREAM _SC_PII_INTERNET_STREAM + _SC_PII_INTERNET_DGRAM, +#define _SC_PII_INTERNET_DGRAM _SC_PII_INTERNET_DGRAM + _SC_PII_OSI_COTS, +#define _SC_PII_OSI_COTS _SC_PII_OSI_COTS + _SC_PII_OSI_CLTS, +#define _SC_PII_OSI_CLTS _SC_PII_OSI_CLTS + _SC_PII_OSI_M, +#define _SC_PII_OSI_M _SC_PII_OSI_M + _SC_T_IOV_MAX, +#define _SC_T_IOV_MAX _SC_T_IOV_MAX + + /* Values according to POSIX 1003.1c (POSIX threads). */ + _SC_THREADS, +#define _SC_THREADS _SC_THREADS + _SC_THREAD_SAFE_FUNCTIONS, +#define _SC_THREAD_SAFE_FUNCTIONS _SC_THREAD_SAFE_FUNCTIONS + _SC_GETGR_R_SIZE_MAX, +#define _SC_GETGR_R_SIZE_MAX _SC_GETGR_R_SIZE_MAX + _SC_GETPW_R_SIZE_MAX, +#define _SC_GETPW_R_SIZE_MAX _SC_GETPW_R_SIZE_MAX + _SC_LOGIN_NAME_MAX, +#define _SC_LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX + _SC_TTY_NAME_MAX, +#define _SC_TTY_NAME_MAX _SC_TTY_NAME_MAX + _SC_THREAD_DESTRUCTOR_ITERATIONS, +#define _SC_THREAD_DESTRUCTOR_ITERATIONS _SC_THREAD_DESTRUCTOR_ITERATIONS + _SC_THREAD_KEYS_MAX, +#define _SC_THREAD_KEYS_MAX _SC_THREAD_KEYS_MAX + _SC_THREAD_STACK_MIN, +#define _SC_THREAD_STACK_MIN _SC_THREAD_STACK_MIN + _SC_THREAD_THREADS_MAX, +#define _SC_THREAD_THREADS_MAX _SC_THREAD_THREADS_MAX + _SC_THREAD_ATTR_STACKADDR, +#define _SC_THREAD_ATTR_STACKADDR _SC_THREAD_ATTR_STACKADDR + _SC_THREAD_ATTR_STACKSIZE, +#define _SC_THREAD_ATTR_STACKSIZE _SC_THREAD_ATTR_STACKSIZE + _SC_THREAD_PRIORITY_SCHEDULING, +#define _SC_THREAD_PRIORITY_SCHEDULING _SC_THREAD_PRIORITY_SCHEDULING + _SC_THREAD_PRIO_INHERIT, +#define _SC_THREAD_PRIO_INHERIT _SC_THREAD_PRIO_INHERIT + _SC_THREAD_PRIO_PROTECT, +#define _SC_THREAD_PRIO_PROTECT _SC_THREAD_PRIO_PROTECT + _SC_THREAD_PROCESS_SHARED, +#define _SC_THREAD_PROCESS_SHARED _SC_THREAD_PROCESS_SHARED + + _SC_NPROCESSORS_CONF, +#define _SC_NPROCESSORS_CONF _SC_NPROCESSORS_CONF + _SC_NPROCESSORS_ONLN, +#define _SC_NPROCESSORS_ONLN _SC_NPROCESSORS_ONLN + _SC_PHYS_PAGES, +#define _SC_PHYS_PAGES _SC_PHYS_PAGES + _SC_AVPHYS_PAGES, +#define _SC_AVPHYS_PAGES _SC_AVPHYS_PAGES + _SC_ATEXIT_MAX, +#define _SC_ATEXIT_MAX _SC_ATEXIT_MAX + _SC_PASS_MAX, +#define _SC_PASS_MAX _SC_PASS_MAX + + _SC_XOPEN_VERSION, +#define _SC_XOPEN_VERSION _SC_XOPEN_VERSION + _SC_XOPEN_XCU_VERSION, +#define _SC_XOPEN_XCU_VERSION _SC_XOPEN_XCU_VERSION + _SC_XOPEN_UNIX, +#define _SC_XOPEN_UNIX _SC_XOPEN_UNIX + _SC_XOPEN_CRYPT, +#define _SC_XOPEN_CRYPT _SC_XOPEN_CRYPT + _SC_XOPEN_ENH_I18N, +#define _SC_XOPEN_ENH_I18N _SC_XOPEN_ENH_I18N + _SC_XOPEN_SHM, +#define _SC_XOPEN_SHM _SC_XOPEN_SHM + + _SC_2_CHAR_TERM, +#define _SC_2_CHAR_TERM _SC_2_CHAR_TERM + _SC_2_C_VERSION, +#define _SC_2_C_VERSION _SC_2_C_VERSION + _SC_2_UPE, +#define _SC_2_UPE _SC_2_UPE + + _SC_XOPEN_XPG2, +#define _SC_XOPEN_XPG2 _SC_XOPEN_XPG2 + _SC_XOPEN_XPG3, +#define _SC_XOPEN_XPG3 _SC_XOPEN_XPG3 + _SC_XOPEN_XPG4, +#define _SC_XOPEN_XPG4 _SC_XOPEN_XPG4 + + _SC_CHAR_BIT, +#define _SC_CHAR_BIT _SC_CHAR_BIT + _SC_CHAR_MAX, +#define _SC_CHAR_MAX _SC_CHAR_MAX + _SC_CHAR_MIN, +#define _SC_CHAR_MIN _SC_CHAR_MIN + _SC_INT_MAX, +#define _SC_INT_MAX _SC_INT_MAX + _SC_INT_MIN, +#define _SC_INT_MIN _SC_INT_MIN + _SC_LONG_BIT, +#define _SC_LONG_BIT _SC_LONG_BIT + _SC_WORD_BIT, +#define _SC_WORD_BIT _SC_WORD_BIT + _SC_MB_LEN_MAX, +#define _SC_MB_LEN_MAX _SC_MB_LEN_MAX + _SC_NZERO, +#define _SC_NZERO _SC_NZERO + _SC_SSIZE_MAX, +#define _SC_SSIZE_MAX _SC_SSIZE_MAX + _SC_SCHAR_MAX, +#define _SC_SCHAR_MAX _SC_SCHAR_MAX + _SC_SCHAR_MIN, +#define _SC_SCHAR_MIN _SC_SCHAR_MIN + _SC_SHRT_MAX, +#define _SC_SHRT_MAX _SC_SHRT_MAX + _SC_SHRT_MIN, +#define _SC_SHRT_MIN _SC_SHRT_MIN + _SC_UCHAR_MAX, +#define _SC_UCHAR_MAX _SC_UCHAR_MAX + _SC_UINT_MAX, +#define _SC_UINT_MAX _SC_UINT_MAX + _SC_ULONG_MAX, +#define _SC_ULONG_MAX _SC_ULONG_MAX + _SC_USHRT_MAX, +#define _SC_USHRT_MAX _SC_USHRT_MAX + + _SC_NL_ARGMAX, +#define _SC_NL_ARGMAX _SC_NL_ARGMAX + _SC_NL_LANGMAX, +#define _SC_NL_LANGMAX _SC_NL_LANGMAX + _SC_NL_MSGMAX, +#define _SC_NL_MSGMAX _SC_NL_MSGMAX + _SC_NL_NMAX, +#define _SC_NL_NMAX _SC_NL_NMAX + _SC_NL_SETMAX, +#define _SC_NL_SETMAX _SC_NL_SETMAX + _SC_NL_TEXTMAX, +#define _SC_NL_TEXTMAX _SC_NL_TEXTMAX + + _SC_XBS5_ILP32_OFF32, +#define _SC_XBS5_ILP32_OFF32 _SC_XBS5_ILP32_OFF32 + _SC_XBS5_ILP32_OFFBIG, +#define _SC_XBS5_ILP32_OFFBIG _SC_XBS5_ILP32_OFFBIG + _SC_XBS5_LP64_OFF64, +#define _SC_XBS5_LP64_OFF64 _SC_XBS5_LP64_OFF64 + _SC_XBS5_LPBIG_OFFBIG, +#define _SC_XBS5_LPBIG_OFFBIG _SC_XBS5_LPBIG_OFFBIG + + _SC_XOPEN_LEGACY, +#define _SC_XOPEN_LEGACY _SC_XOPEN_LEGACY + _SC_XOPEN_REALTIME, +#define _SC_XOPEN_REALTIME _SC_XOPEN_REALTIME + _SC_XOPEN_REALTIME_THREADS, +#define _SC_XOPEN_REALTIME_THREADS _SC_XOPEN_REALTIME_THREADS + + _SC_ADVISORY_INFO, +#define _SC_ADVISORY_INFO _SC_ADVISORY_INFO + _SC_BARRIERS, +#define _SC_BARRIERS _SC_BARRIERS + _SC_BASE, +#define _SC_BASE _SC_BASE + _SC_C_LANG_SUPPORT, +#define _SC_C_LANG_SUPPORT _SC_C_LANG_SUPPORT + _SC_C_LANG_SUPPORT_R, +#define _SC_C_LANG_SUPPORT_R _SC_C_LANG_SUPPORT_R + _SC_CLOCK_SELECTION, +#define _SC_CLOCK_SELECTION _SC_CLOCK_SELECTION + _SC_CPUTIME, +#define _SC_CPUTIME _SC_CPUTIME + _SC_THREAD_CPUTIME, +#define _SC_THREAD_CPUTIME _SC_THREAD_CPUTIME + _SC_DEVICE_IO, +#define _SC_DEVICE_IO _SC_DEVICE_IO + _SC_DEVICE_SPECIFIC, +#define _SC_DEVICE_SPECIFIC _SC_DEVICE_SPECIFIC + _SC_DEVICE_SPECIFIC_R, +#define _SC_DEVICE_SPECIFIC_R _SC_DEVICE_SPECIFIC_R + _SC_FD_MGMT, +#define _SC_FD_MGMT _SC_FD_MGMT + _SC_FIFO, +#define _SC_FIFO _SC_FIFO + _SC_PIPE, +#define _SC_PIPE _SC_PIPE + _SC_FILE_ATTRIBUTES, +#define _SC_FILE_ATTRIBUTES _SC_FILE_ATTRIBUTES + _SC_FILE_LOCKING, +#define _SC_FILE_LOCKING _SC_FILE_LOCKING + _SC_FILE_SYSTEM, +#define _SC_FILE_SYSTEM _SC_FILE_SYSTEM + _SC_MONOTONIC_CLOCK, +#define _SC_MONOTONIC_CLOCK _SC_MONOTONIC_CLOCK + _SC_MULTI_PROCESS, +#define _SC_MULTI_PROCESS _SC_MULTI_PROCESS + _SC_SINGLE_PROCESS, +#define _SC_SINGLE_PROCESS _SC_SINGLE_PROCESS + _SC_NETWORKING, +#define _SC_NETWORKING _SC_NETWORKING + _SC_READER_WRITER_LOCKS, +#define _SC_READER_WRITER_LOCKS _SC_READER_WRITER_LOCKS + _SC_SPIN_LOCKS, +#define _SC_SPIN_LOCKS _SC_SPIN_LOCKS + _SC_REGEXP, +#define _SC_REGEXP _SC_REGEXP + _SC_REGEX_VERSION, +#define _SC_REGEX_VERSION _SC_REGEX_VERSION + _SC_SHELL, +#define _SC_SHELL _SC_SHELL + _SC_SIGNALS, +#define _SC_SIGNALS _SC_SIGNALS + _SC_SPAWN, +#define _SC_SPAWN _SC_SPAWN + _SC_SPORADIC_SERVER, +#define _SC_SPORADIC_SERVER _SC_SPORADIC_SERVER + _SC_THREAD_SPORADIC_SERVER, +#define _SC_THREAD_SPORADIC_SERVER _SC_THREAD_SPORADIC_SERVER + _SC_SYSTEM_DATABASE, +#define _SC_SYSTEM_DATABASE _SC_SYSTEM_DATABASE + _SC_SYSTEM_DATABASE_R, +#define _SC_SYSTEM_DATABASE_R _SC_SYSTEM_DATABASE_R + _SC_TIMEOUTS, +#define _SC_TIMEOUTS _SC_TIMEOUTS + _SC_TYPED_MEMORY_OBJECTS, +#define _SC_TYPED_MEMORY_OBJECTS _SC_TYPED_MEMORY_OBJECTS + _SC_USER_GROUPS, +#define _SC_USER_GROUPS _SC_USER_GROUPS + _SC_USER_GROUPS_R, +#define _SC_USER_GROUPS_R _SC_USER_GROUPS_R + _SC_2_PBS, +#define _SC_2_PBS _SC_2_PBS + _SC_2_PBS_ACCOUNTING, +#define _SC_2_PBS_ACCOUNTING _SC_2_PBS_ACCOUNTING + _SC_2_PBS_LOCATE, +#define _SC_2_PBS_LOCATE _SC_2_PBS_LOCATE + _SC_2_PBS_MESSAGE, +#define _SC_2_PBS_MESSAGE _SC_2_PBS_MESSAGE + _SC_2_PBS_TRACK, +#define _SC_2_PBS_TRACK _SC_2_PBS_TRACK + _SC_SYMLOOP_MAX, +#define _SC_SYMLOOP_MAX _SC_SYMLOOP_MAX + _SC_STREAMS, +#define _SC_STREAMS _SC_STREAMS + _SC_2_PBS_CHECKPOINT, +#define _SC_2_PBS_CHECKPOINT _SC_2_PBS_CHECKPOINT + + _SC_V6_ILP32_OFF32, +#define _SC_V6_ILP32_OFF32 _SC_V6_ILP32_OFF32 + _SC_V6_ILP32_OFFBIG, +#define _SC_V6_ILP32_OFFBIG _SC_V6_ILP32_OFFBIG + _SC_V6_LP64_OFF64, +#define _SC_V6_LP64_OFF64 _SC_V6_LP64_OFF64 + _SC_V6_LPBIG_OFFBIG, +#define _SC_V6_LPBIG_OFFBIG _SC_V6_LPBIG_OFFBIG + + _SC_HOST_NAME_MAX, +#define _SC_HOST_NAME_MAX _SC_HOST_NAME_MAX + _SC_TRACE, +#define _SC_TRACE _SC_TRACE + _SC_TRACE_EVENT_FILTER, +#define _SC_TRACE_EVENT_FILTER _SC_TRACE_EVENT_FILTER + _SC_TRACE_INHERIT, +#define _SC_TRACE_INHERIT _SC_TRACE_INHERIT + _SC_TRACE_LOG, +#define _SC_TRACE_LOG _SC_TRACE_LOG + + _SC_LEVEL1_ICACHE_SIZE, +#define _SC_LEVEL1_ICACHE_SIZE _SC_LEVEL1_ICACHE_SIZE + _SC_LEVEL1_ICACHE_ASSOC, +#define _SC_LEVEL1_ICACHE_ASSOC _SC_LEVEL1_ICACHE_ASSOC + _SC_LEVEL1_ICACHE_LINESIZE, +#define _SC_LEVEL1_ICACHE_LINESIZE _SC_LEVEL1_ICACHE_LINESIZE + _SC_LEVEL1_DCACHE_SIZE, +#define _SC_LEVEL1_DCACHE_SIZE _SC_LEVEL1_DCACHE_SIZE + _SC_LEVEL1_DCACHE_ASSOC, +#define _SC_LEVEL1_DCACHE_ASSOC _SC_LEVEL1_DCACHE_ASSOC + _SC_LEVEL1_DCACHE_LINESIZE, +#define _SC_LEVEL1_DCACHE_LINESIZE _SC_LEVEL1_DCACHE_LINESIZE + _SC_LEVEL2_CACHE_SIZE, +#define _SC_LEVEL2_CACHE_SIZE _SC_LEVEL2_CACHE_SIZE + _SC_LEVEL2_CACHE_ASSOC, +#define _SC_LEVEL2_CACHE_ASSOC _SC_LEVEL2_CACHE_ASSOC + _SC_LEVEL2_CACHE_LINESIZE, +#define _SC_LEVEL2_CACHE_LINESIZE _SC_LEVEL2_CACHE_LINESIZE + _SC_LEVEL3_CACHE_SIZE, +#define _SC_LEVEL3_CACHE_SIZE _SC_LEVEL3_CACHE_SIZE + _SC_LEVEL3_CACHE_ASSOC, +#define _SC_LEVEL3_CACHE_ASSOC _SC_LEVEL3_CACHE_ASSOC + _SC_LEVEL3_CACHE_LINESIZE, +#define _SC_LEVEL3_CACHE_LINESIZE _SC_LEVEL3_CACHE_LINESIZE + _SC_LEVEL4_CACHE_SIZE, +#define _SC_LEVEL4_CACHE_SIZE _SC_LEVEL4_CACHE_SIZE + _SC_LEVEL4_CACHE_ASSOC, +#define _SC_LEVEL4_CACHE_ASSOC _SC_LEVEL4_CACHE_ASSOC + _SC_LEVEL4_CACHE_LINESIZE, +#define _SC_LEVEL4_CACHE_LINESIZE _SC_LEVEL4_CACHE_LINESIZE + /* Leave room here, maybe we need a few more cache levels some day. */ + + _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50, +#define _SC_IPV6 _SC_IPV6 + _SC_RAW_SOCKETS +#define _SC_RAW_SOCKETS _SC_RAW_SOCKETS + }; + +#if (defined __USE_POSIX2 || defined __USE_UNIX98 \ + || defined __USE_FILE_OFFSET64 || defined __USE_LARGEFILE64 \ + || defined __USE_LARGEFILE) +/* Values for the NAME argument to `confstr'. */ +enum + { + _CS_PATH, /* The default search path. */ +#define _CS_PATH _CS_PATH + + _CS_V6_WIDTH_RESTRICTED_ENVS, +# define _CS_V6_WIDTH_RESTRICTED_ENVS _CS_V6_WIDTH_RESTRICTED_ENVS + +# if (defined __USE_FILE_OFFSET64 || defined __USE_LARGEFILE64 \ + || defined __USE_LARGEFILE) + _CS_LFS_CFLAGS = 1000, +#define _CS_LFS_CFLAGS _CS_LFS_CFLAGS + _CS_LFS_LDFLAGS, +#define _CS_LFS_LDFLAGS _CS_LFS_LDFLAGS + _CS_LFS_LIBS, +#define _CS_LFS_LIBS _CS_LFS_LIBS + _CS_LFS_LINTFLAGS, +#define _CS_LFS_LINTFLAGS _CS_LFS_LINTFLAGS + _CS_LFS64_CFLAGS, +#define _CS_LFS64_CFLAGS _CS_LFS64_CFLAGS + _CS_LFS64_LDFLAGS, +#define _CS_LFS64_LDFLAGS _CS_LFS64_LDFLAGS + _CS_LFS64_LIBS, +#define _CS_LFS64_LIBS _CS_LFS64_LIBS + _CS_LFS64_LINTFLAGS, +#define _CS_LFS64_LINTFLAGS _CS_LFS64_LINTFLAGS +# endif + +# ifdef __USE_UNIX98 + _CS_XBS5_ILP32_OFF32_CFLAGS = 1100, +#define _CS_XBS5_ILP32_OFF32_CFLAGS _CS_XBS5_ILP32_OFF32_CFLAGS + _CS_XBS5_ILP32_OFF32_LDFLAGS, +#define _CS_XBS5_ILP32_OFF32_LDFLAGS _CS_XBS5_ILP32_OFF32_LDFLAGS + _CS_XBS5_ILP32_OFF32_LIBS, +#define _CS_XBS5_ILP32_OFF32_LIBS _CS_XBS5_ILP32_OFF32_LIBS + _CS_XBS5_ILP32_OFF32_LINTFLAGS, +#define _CS_XBS5_ILP32_OFF32_LINTFLAGS _CS_XBS5_ILP32_OFF32_LINTFLAGS + _CS_XBS5_ILP32_OFFBIG_CFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_CFLAGS _CS_XBS5_ILP32_OFFBIG_CFLAGS + _CS_XBS5_ILP32_OFFBIG_LDFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_LDFLAGS _CS_XBS5_ILP32_OFFBIG_LDFLAGS + _CS_XBS5_ILP32_OFFBIG_LIBS, +#define _CS_XBS5_ILP32_OFFBIG_LIBS _CS_XBS5_ILP32_OFFBIG_LIBS + _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_LINTFLAGS _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + _CS_XBS5_LP64_OFF64_CFLAGS, +#define _CS_XBS5_LP64_OFF64_CFLAGS _CS_XBS5_LP64_OFF64_CFLAGS + _CS_XBS5_LP64_OFF64_LDFLAGS, +#define _CS_XBS5_LP64_OFF64_LDFLAGS _CS_XBS5_LP64_OFF64_LDFLAGS + _CS_XBS5_LP64_OFF64_LIBS, +#define _CS_XBS5_LP64_OFF64_LIBS _CS_XBS5_LP64_OFF64_LIBS + _CS_XBS5_LP64_OFF64_LINTFLAGS, +#define _CS_XBS5_LP64_OFF64_LINTFLAGS _CS_XBS5_LP64_OFF64_LINTFLAGS + _CS_XBS5_LPBIG_OFFBIG_CFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_CFLAGS _CS_XBS5_LPBIG_OFFBIG_CFLAGS + _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_LDFLAGS _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + _CS_XBS5_LPBIG_OFFBIG_LIBS, +#define _CS_XBS5_LPBIG_OFFBIG_LIBS _CS_XBS5_LPBIG_OFFBIG_LIBS + _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS +# endif +# ifdef __USE_XOPEN2K + _CS_POSIX_V6_ILP32_OFF32_CFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS _CS_POSIX_V6_ILP32_OFF32_CFLAGS + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS _CS_POSIX_V6_ILP32_OFF32_LDFLAGS + _CS_POSIX_V6_ILP32_OFF32_LIBS, +#define _CS_POSIX_V6_ILP32_OFF32_LIBS _CS_POSIX_V6_ILP32_OFF32_LIBS + _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_LIBS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS _CS_POSIX_V6_ILP32_OFFBIG_LIBS + _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS + _CS_POSIX_V6_LP64_OFF64_CFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_CFLAGS _CS_POSIX_V6_LP64_OFF64_CFLAGS + _CS_POSIX_V6_LP64_OFF64_LDFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS _CS_POSIX_V6_LP64_OFF64_LDFLAGS + _CS_POSIX_V6_LP64_OFF64_LIBS, +#define _CS_POSIX_V6_LP64_OFF64_LIBS _CS_POSIX_V6_LP64_OFF64_LIBS + _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_LINTFLAGS _CS_POSIX_V6_LP64_OFF64_LINTFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS _CS_POSIX_V6_LPBIG_OFFBIG_LIBS + _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS +#define _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS +# endif + }; +#endif diff --git a/libc/sysdeps/linux/common/bits/dirent.h b/libc/sysdeps/linux/common/bits/dirent.h new file mode 100644 index 0000000..76794b0 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/dirent.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DIRENT_H +# error "Never use directly; include instead." +#endif + +struct dirent + { +#ifndef __USE_FILE_OFFSET64 + __ino_t d_ino; + __off_t d_off; +#else + __ino64_t d_ino; + __off64_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +struct dirent64 + { + __ino64_t d_ino; + __off64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE diff --git a/libc/sysdeps/linux/common/bits/dlfcn.h b/libc/sysdeps/linux/common/bits/dlfcn.h new file mode 100644 index 0000000..4bfbbff --- /dev/null +++ b/libc/sysdeps/linux/common/bits/dlfcn.h @@ -0,0 +1,67 @@ +/* System dependent definitions for run-time dynamic loading. + Copyright (C) 1996-2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +# error "Never use directly; include instead." +#endif + +/* The MODE argument to `dlopen' contains one of the following: */ +#define RTLD_LAZY 0x00001 /* Lazy function call binding. */ +#define RTLD_NOW 0x00002 /* Immediate function call binding. */ +#if 0 /* uClibc doesnt support these */ +#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +#define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ +#endif + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +#define RTLD_GLOBAL 0x00100 + +/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. + The implementation does this by default and so we can define the + value to zero. */ +#define RTLD_LOCAL 0 + +/* Do not delete object when closed. */ +#define RTLD_NODELETE 0x01000 + +#if 0 /*def __USE_GNU*/ +/* To support profiling of shared objects it is a good idea to call + the function found using `dlsym' using the following macro since + these calls do not use the PLT. But this would mean the dynamic + loader has no chance to find out when the function is called. The + macro applies the necessary magic so that profiling is possible. + Rewrite + foo = (*fctp) (arg1, arg2); + into + foo = DL_CALL_FCT (fctp, (arg1, arg2)); +*/ +# define DL_CALL_FCT(fctp, args) \ + (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args) + +__BEGIN_DECLS + +/* This function calls the profiling functions. */ +extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW; + +__END_DECLS + +#endif diff --git a/libc/sysdeps/linux/common/bits/elfclass.h b/libc/sysdeps/linux/common/bits/elfclass.h new file mode 100644 index 0000000..180227d --- /dev/null +++ b/libc/sysdeps/linux/common/bits/elfclass.h @@ -0,0 +1,14 @@ +/* This file specifies the native word size of the machine, which indicates + the ELF file class used for executables and shared objects on this + machine. */ + +#ifndef _LINK_H +# error "Never use directly; include instead." +#endif + +#include + +#define __ELF_NATIVE_CLASS __WORDSIZE + +/* The entries in the .hash table always have a size of 32 bits. */ +typedef uint32_t Elf_Symndx; diff --git a/libc/sysdeps/linux/common/bits/endian.h b/libc/sysdeps/linux/common/bits/endian.h new file mode 100644 index 0000000..0086a1c --- /dev/null +++ b/libc/sysdeps/linux/common/bits/endian.h @@ -0,0 +1,18 @@ +/* This file should define __BYTE_ORDER as appropriate for the machine + in question. See string/endian.h for how to define it. + + If only the stub bits/endian.h applies to a particular configuration, + bytesex.h is generated by running a program on the host machine. + So if cross-compiling to a machine with a different byte order, + the bits/endian.h file for that machine must exist. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#error Machine byte order unknown. + +#if 0 +#define __BYTE_ORDER __BIG_ENDIAN +#define __BYTE_ORDER __LITTLE_ENDIAN +#endif diff --git a/libc/sysdeps/linux/common/bits/environments.h b/libc/sysdeps/linux/common/bits/environments.h new file mode 100644 index 0000000..4617dc4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/environments.h @@ -0,0 +1,78 @@ +/* Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never include this file directly. Use instead" +#endif + +#include + +/* This header should define the following symbols under the described + situations. A value `1' means that the model is always supported, + `-1' means it is never supported. Undefined means it cannot be + statically decided. + + _POSIX_V6_ILP32_OFF32 32bit int, long, pointers, and off_t type + _POSIX_V6_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type + + _POSIX_V6_LP64_OFF32 64bit long and pointers and 32bit off_t type + _POSIX_V6_LPBIG_OFFBIG 64bit long and pointers and large off_t type + + The macros _XBS5_ILP32_OFF32, _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and + _XBS5_LPBIG_OFFBIG were used in previous versions of the Unix standard + and are available only for compatibility. +*/ + +#if __WORDSIZE == 64 + +/* We can never provide environments with 32-bit wide pointers. */ +# define _POSIX_V6_ILP32_OFF32 -1 +# define _POSIX_V6_ILP32_OFFBIG -1 +# define _XBS5_ILP32_OFF32 -1 +# define _XBS5_ILP32_OFFBIG -1 +/* We also have no use (for now) for an environment with bigger pointers + and offsets. */ +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* By default we have 64-bit wide `long int', pointers and `off_t'. */ +# define _POSIX_V6_LP64_OFF64 1 +# define _XBS5_LP64_OFF64 1 + +#else /* __WORDSIZE == 32 */ + +/* By default we have 32-bit wide `int', `long int', pointers and `off_t' + and all platforms support LFS. */ +# define _POSIX_V6_ILP32_OFF32 1 +# define _POSIX_V6_ILP32_OFFBIG 1 +# define _XBS5_ILP32_OFF32 1 +# define _XBS5_ILP32_OFFBIG 1 + +/* We optionally provide an environment with the above size but an 64-bit + side `off_t'. Therefore we don't define _XBS5_ILP32_OFFBIG. */ + +/* We can never provide environments with 64-bit wide pointers. */ +# define _POSIX_V6_LP64_OFF64 -1 +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LP64_OFF64 -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* CFLAGS. */ +#define __ILP32_OFFBIG_CFLAGS "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" + +#endif /* __WORDSIZE == 32 */ diff --git a/libc/sysdeps/linux/common/bits/errno.h b/libc/sysdeps/linux/common/bits/errno.h new file mode 100644 index 0000000..a5ac1a4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/errno.h @@ -0,0 +1,59 @@ +/* Error constants. Linux specific version. + Copyright (C) 1996, 1997, 1998, 1999, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _ERRNO_H + +# undef EDOM +# undef EILSEQ +# undef ERANGE +# include + +/* Linux has no ENOTSUP error code. */ +# define ENOTSUP EOPNOTSUPP + +/* Older Linux versions also had no ECANCELED error code. */ +# ifndef ECANCELED +# define ECANCELED 125 +# endif + +/* Support for error codes to support robust mutexes was added later, too. */ +# ifndef EOWNERDEAD +# define EOWNERDEAD 130 +# define ENOTRECOVERABLE 131 +# endif + +# ifndef __ASSEMBLER__ +/* Function to get address of global `errno' variable. */ +extern int *__errno_location (void) __THROW __attribute__ ((__const__)); + +# ifdef __UCLIBC_HAS_THREADS__ +/* When using threads, errno is a per-thread value. */ +# define errno (*__errno_location ()) +# endif +# endif /* !__ASSEMBLER__ */ +#endif /* _ERRNO_H */ + +#if !defined _ERRNO_H && defined __need_Emath +/* This is ugly but the kernel header is not clean enough. We must + define only the values EDOM, EILSEQ and ERANGE in case __need_Emath is + defined. */ +# define EDOM 33 /* Math argument out of domain of function. */ +# define EILSEQ 84 /* Illegal byte sequence. */ +# define ERANGE 34 /* Math result not representable. */ +#endif /* !_ERRNO_H && __need_Emath */ diff --git a/libc/sysdeps/linux/common/bits/fcntl.h b/libc/sysdeps/linux/common/bits/fcntl.h new file mode 100644 index 0000000..be40350 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/fcntl.h @@ -0,0 +1,3 @@ +/* bits/fcntl.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." + diff --git a/libc/sysdeps/linux/common/bits/fenv.h b/libc/sysdeps/linux/common/bits/fenv.h new file mode 100644 index 0000000..a9cb53b --- /dev/null +++ b/libc/sysdeps/linux/common/bits/fenv.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Here should be the exception be defined: + FE_INVALID + FE_DIVBYZERO + FE_OVERFLOW + FE_UNDERFLOW + FE_INEXACT + We define no macro which signals no exception is supported. */ + +#define FE_ALL_EXCEPT 0 + + +/* Here should the rounding modes be defined: + FE_TONEAREST + FE_DOWNWARD + FE_UPWARD + FE_TOWARDZERO + We define no macro which signals no rounding mode is selectable. */ + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment. */ +typedef struct + { + fexcept_t __excepts; + /* XXX I don't know what else we should save. */ + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1l) diff --git a/libc/sysdeps/linux/common/bits/fenvinline.h b/libc/sysdeps/linux/common/bits/fenvinline.h new file mode 100644 index 0000000..42f77b5 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/fenvinline.h @@ -0,0 +1,8 @@ +/* This file provides inline versions of floating-pint environment + handling functions. If there were any. */ + +#ifndef __NO_MATH_INLINES + +/* Here is where the code would go. */ + +#endif diff --git a/libc/sysdeps/linux/common/bits/getopt.h b/libc/sysdeps/linux/common/bits/getopt.h new file mode 100644 index 0000000..a28d0a4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/getopt.h @@ -0,0 +1,181 @@ +/* Declarations for getopt. + Copyright (C) 1989-1994,1996-1999,2001,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GETOPT_H + +#include + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +/* If __GNU_LIBRARY__ is not already defined, either we are being used + standalone, or this is the first header included in the source file. + If we are being used with glibc, we need to include , but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include , which will pull in for us + if it's from glibc. (Why ctype.h? It's guaranteed to exist and it + doesn't flood the namespace with stuff the way some other headers do.) */ +#if !defined __GNU_LIBRARY__ +# include +#endif + +#ifndef __THROW +# ifndef __GNUC_PREREQ +# define __GNUC_PREREQ(maj, min) (0) +# endif +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __GNU_LIBRARY__ || defined __UCLIBC__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW; +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ + +#if defined __UCLIBC_HAS_GNU_GETOPT__ || defined __UCLIBC_HAS_GETOPT_LONG__ +#ifndef __need_getopt +extern int getopt_long (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW; +extern int getopt_long_only (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW; + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/libc/sysdeps/linux/common/bits/huge_val.h b/libc/sysdeps/linux/common/bits/huge_val.h new file mode 100644 index 0000000..11ca11f --- /dev/null +++ b/libc/sysdeps/linux/common/bits/huge_val.h @@ -0,0 +1,55 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Copyright (C) 1992, 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x7ff0000000000000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/common/bits/huge_valf.h b/libc/sysdeps/linux/common/bits/huge_valf.h new file mode 100644 index 0000000..1785342 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/huge_valf.h @@ -0,0 +1,53 @@ +/* `HUGE_VALF' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Copyright (C) 1992, 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALF (__builtin_huge_valf()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VALF (__extension__ 0x1.0p255f) +#elif defined __GNUC__ + +# define HUGE_VALF \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__SI__))); float __d; }) \ + { __l: 0x7f800000UL }).__d) + +#else /* not GCC */ + +typedef union { unsigned char __c[4]; float __f; } __huge_valf_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VALF_bytes { 0x7f, 0x80, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VALF_bytes { 0, 0, 0x80, 0x7f } +# endif + +static __huge_valf_t __huge_valf = { __HUGE_VALF_bytes }; +# define HUGE_VALF (__huge_valf.__f) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/common/bits/huge_vall.h b/libc/sysdeps/linux/common/bits/huge_vall.h new file mode 100644 index 0000000..d5e8e22 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/huge_vall.h @@ -0,0 +1,29 @@ +/* Default `HUGE_VALL' constant. + Used by and functions for overflow. + Copyright (C) 1992, 1996, 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#else +# define HUGE_VALL ((long double) HUGE_VAL) +#endif diff --git a/libc/sysdeps/linux/common/bits/in.h b/libc/sysdeps/linux/common/bits/in.h new file mode 100644 index 0000000..6880a2e --- /dev/null +++ b/libc/sysdeps/linux/common/bits/in.h @@ -0,0 +1,170 @@ +/* Copyright (C) 1991-1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux version. */ + +#ifndef _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Options for use with `getsockopt' and `setsockopt' at the IP level. + The first word in the comment at the right is the data type used; + "bool" means a boolean value stored in an `int'. */ +#define IP_OPTIONS 4 /* ip_opts; IP per-packet options. */ +#define IP_HDRINCL 3 /* int; Header is included with data. */ +#define IP_TOS 1 /* int; IP type of service and precedence. */ +#define IP_TTL 2 /* int; IP time to live. */ +#define IP_RECVOPTS 6 /* bool; Receive all IP options w/datagram. */ +/* For BSD compatibility. */ +#define IP_RECVRETOPTS IP_RETOPTS /* bool; Receive IP options for response. */ +#define IP_RETOPTS 7 /* ip_opts; Set/get IP per-packet options. */ +#define IP_MULTICAST_IF 32 /* in_addr; set/get IP multicast i/f */ +#define IP_MULTICAST_TTL 33 /* u_char; set/get IP multicast ttl */ +#define IP_MULTICAST_LOOP 34 /* i_char; set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 35 /* ip_mreq; add an IP group membership */ +#define IP_DROP_MEMBERSHIP 36 /* ip_mreq; drop an IP group membership */ +#define IP_UNBLOCK_SOURCE 37 /* ip_mreq_source: unblock data from source */ +#define IP_BLOCK_SOURCE 38 /* ip_mreq_source: block data from source */ +#define IP_ADD_SOURCE_MEMBERSHIP 39 /* ip_mreq_source: join source group */ +#define IP_DROP_SOURCE_MEMBERSHIP 40 /* ip_mreq_source: leave source group */ +#define IP_MSFILTER 41 +#define MCAST_JOIN_GROUP 42 /* group_req: join any-source group */ +#define MCAST_BLOCK_SOURCE 43 /* group_source_req: block from given group */ +#define MCAST_UNBLOCK_SOURCE 44 /* group_source_req: unblock from given group*/ +#define MCAST_LEAVE_GROUP 45 /* group_req: leave any-source group */ +#define MCAST_JOIN_SOURCE_GROUP 46 /* group_source_req: join source-spec gr */ +#define MCAST_LEAVE_SOURCE_GROUP 47 /* group_source_req: leave source-spec gr*/ +#define MCAST_MSFILTER 48 + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +#define IP_ROUTER_ALERT 5 /* bool */ +#define IP_PKTINFO 8 /* bool */ +#define IP_PKTOPTIONS 9 +#define IP_PMTUDISC 10 /* obsolete name? */ +#define IP_MTU_DISCOVER 10 /* int; see below */ +#define IP_RECVERR 11 /* bool */ +#define IP_RECVTTL 12 /* bool */ +#define IP_RECVTOS 13 /* bool */ + + +/* IP_MTU_DISCOVER arguments. */ +#define IP_PMTUDISC_DONT 0 /* Never send DF frames. */ +#define IP_PMTUDISC_WANT 1 /* Use per route hints. */ +#define IP_PMTUDISC_DO 2 /* Always DF. */ + +/* To select the IP level. */ +#define SOL_IP 0 + +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 +#define IP_MAX_MEMBERSHIPS 20 + +/* Structure used to describe IP options for IP_OPTIONS and IP_RETOPTS. + The `ip_dst' field is used for the first-hop gateway when using a + source route (this gets put into the header proper). */ +struct ip_opts + { + struct in_addr ip_dst; /* First hop; zero without source route. */ + char ip_opts[40]; /* Actually variable in size. */ + }; + +/* Like `struct ip_mreq' but including interface specification by index. */ +struct ip_mreqn + { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ + }; + +/* Structure used for IP_PKTINFO. */ +struct in_pktinfo + { + int ipi_ifindex; /* Interface index */ + struct in_addr ipi_spec_dst; /* Routing destination address */ + struct in_addr ipi_addr; /* Header destination address */ + }; + +/* Options for use with `getsockopt' and `setsockopt' at the IPv6 level. + The first word in the comment at the right is the data type used; + "bool" means a boolean value stored in an `int'. */ +#define IPV6_ADDRFORM 1 +#define IPV6_2292PKTINFO 2 +#define IPV6_2292HOPOPTS 3 +#define IPV6_2292DSTOPTS 4 +#define IPV6_2292RTHDR 5 +#define IPV6_2292PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_2292HOPLIMIT 8 + +#define SCM_SRCRT IPV6_RXSRCRT + +#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_JOIN_GROUP 20 +#define IPV6_LEAVE_GROUP 21 +#define IPV6_ROUTER_ALERT 22 +#define IPV6_MTU_DISCOVER 23 +#define IPV6_MTU 24 +#define IPV6_RECVERR 25 +#define IPV6_V6ONLY 26 +#define IPV6_JOIN_ANYCAST 27 +#define IPV6_LEAVE_ANYCAST 28 +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 + +#define IPV6_RECVPKTINFO 49 +#define IPV6_PKTINFO 50 +#define IPV6_RECVHOPLIMIT 51 +#define IPV6_HOPLIMIT 52 +#define IPV6_RECVHOPOPTS 53 +#define IPV6_HOPOPTS 54 +#define IPV6_RTHDRDSTOPTS 55 +#define IPV6_RECVRTHDR 56 +#define IPV6_RTHDR 57 +#define IPV6_RECVDSTOPTS 58 +#define IPV6_DSTOPTS 59 + +#define IPV6_RECVTCLASS 66 +#define IPV6_TCLASS 67 + +/* Obsolete synonyms for the above. */ +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#define IPV6_RXHOPOPTS IPV6_HOPOPTS +#define IPV6_RXDSTOPTS IPV6_DSTOPTS + +/* IPV6_MTU_DISCOVER values. */ +#define IPV6_PMTUDISC_DONT 0 /* Never send DF frames. */ +#define IPV6_PMTUDISC_WANT 1 /* Use per route hints. */ +#define IPV6_PMTUDISC_DO 2 /* Always DF. */ + +/* Socket level values for IPv6. */ +#define SOL_IPV6 41 +#define SOL_ICMPV6 58 + +/* Routing header options for IPv6. */ +#define IPV6_RTHDR_LOOSE 0 /* Hop doesn't need to be neighbour. */ +#define IPV6_RTHDR_STRICT 1 /* Hop must be a neighbour. */ + +#define IPV6_RTHDR_TYPE_0 0 /* IPv6 Routing header type 0. */ diff --git a/libc/sysdeps/linux/common/bits/inf.h b/libc/sysdeps/linux/common/bits/inf.h new file mode 100644 index 0000000..1619f75 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/inf.h @@ -0,0 +1,30 @@ +/* `INFINITY' constant for IEEE 754 machines. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity. */ + +#if __GNUC_PREREQ(3,3) +# define INFINITY (__builtin_inff()) +#else +# define INFINITY HUGE_VALF +#endif diff --git a/libc/sysdeps/linux/common/bits/initspin.h b/libc/sysdeps/linux/common/bits/initspin.h new file mode 100644 index 0000000..a19ec07 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/libc/sysdeps/linux/common/bits/ioctl-types.h b/libc/sysdeps/linux/common/bits/ioctl-types.h new file mode 100644 index 0000000..e856a04 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/ioctl-types.h @@ -0,0 +1,78 @@ +/* Structure types for pre-termios terminal ioctls. Linux version. + Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Get definition of constants for use with `ioctl'. */ +#include + + +struct winsize + { + unsigned short int ws_row; + unsigned short int ws_col; + unsigned short int ws_xpixel; + unsigned short int ws_ypixel; + }; + +#define NCC 8 +struct termio + { + unsigned short int c_iflag; /* input mode flags */ + unsigned short int c_oflag; /* output mode flags */ + unsigned short int c_cflag; /* control mode flags */ + unsigned short int c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* modem lines */ +#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 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + +/* line disciplines */ +#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 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/libc/sysdeps/linux/common/bits/ioctls.h b/libc/sysdeps/linux/common/bits/ioctls.h new file mode 100644 index 0000000..11bb4c4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/ioctls.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1996, 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Routing table calls. */ +#define SIOCADDRT 0x890B /* add routing table entry */ +#define SIOCDELRT 0x890C /* delete routing table entry */ +#define SIOCRTMSG 0x890D /* call to routing system */ + +/* Socket configuration controls. */ +#define SIOCGIFNAME 0x8910 /* get iface name */ +#define SIOCSIFLINK 0x8911 /* set iface channel */ +#define SIOCGIFCONF 0x8912 /* get iface list */ +#define SIOCGIFFLAGS 0x8913 /* get flags */ +#define SIOCSIFFLAGS 0x8914 /* set flags */ +#define SIOCGIFADDR 0x8915 /* get PA address */ +#define SIOCSIFADDR 0x8916 /* set PA address */ +#define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +#define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ +#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +#define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ +#define SIOCGIFNETMASK 0x891b /* get network PA mask */ +#define SIOCSIFNETMASK 0x891c /* set network PA mask */ +#define SIOCGIFMETRIC 0x891d /* get metric */ +#define SIOCSIFMETRIC 0x891e /* set metric */ +#define SIOCGIFMEM 0x891f /* get memory address (BSD) */ +#define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ +#define SIOCGIFMTU 0x8921 /* get MTU size */ +#define SIOCSIFMTU 0x8922 /* set MTU size */ +#define SIOCSIFNAME 0x8923 /* set interface name */ +#define SIOCSIFHWADDR 0x8924 /* set hardware address */ +#define SIOCGIFENCAP 0x8925 /* get/set encapsulations */ +#define SIOCSIFENCAP 0x8926 +#define SIOCGIFHWADDR 0x8927 /* Get hardware address */ +#define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ +#define SIOCSIFSLAVE 0x8930 +#define SIOCADDMULTI 0x8931 /* Multicast address lists */ +#define SIOCDELMULTI 0x8932 +#define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ +#define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ +#define SIOCSIFPFLAGS 0x8934 /* set/get extended flags set */ +#define SIOCGIFPFLAGS 0x8935 +#define SIOCDIFADDR 0x8936 /* delete PA address */ +#define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ +#define SIOCGIFCOUNT 0x8938 /* get number of devices */ + +#define SIOCGIFBR 0x8940 /* Bridging support */ +#define SIOCSIFBR 0x8941 /* Set bridging options */ + +#define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ +#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ + + +/* ARP cache control calls. */ + /* 0x8950 - 0x8952 * obsolete calls, don't re-use */ +#define SIOCDARP 0x8953 /* delete ARP table entry */ +#define SIOCGARP 0x8954 /* get ARP table entry */ +#define SIOCSARP 0x8955 /* set ARP table entry */ + +/* RARP cache control calls. */ +#define SIOCDRARP 0x8960 /* delete RARP table entry */ +#define SIOCGRARP 0x8961 /* get RARP table entry */ +#define SIOCSRARP 0x8962 /* set RARP table entry */ + +/* Driver configuration calls */ + +#define SIOCGIFMAP 0x8970 /* Get device parameters */ +#define SIOCSIFMAP 0x8971 /* Set device parameters */ + +/* DLCI configuration calls */ + +#define SIOCADDDLCI 0x8980 /* Create new DLCI device */ +#define SIOCDELDLCI 0x8981 /* Delete DLCI device */ + +/* Device private ioctl calls. */ + +/* These 16 ioctls are available to devices via the do_ioctl() device + vector. Each device should include this file and redefine these + names as their own. Because these are device dependent it is a good + idea _NOT_ to issue them to random objects and hope. */ + +#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ + +/* + * These 16 ioctl calls are protocol private + */ + +#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ diff --git a/libc/sysdeps/linux/common/bits/ipc.h b/libc/sysdeps/linux/common/bits/ipc.h new file mode 100644 index 0000000..f1a043f --- /dev/null +++ b/libc/sysdeps/linux/common/bits/ipc.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad1; + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad2; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/libc/sysdeps/linux/common/bits/kernel_sigaction.h b/libc/sysdeps/linux/common/bits/kernel_sigaction.h new file mode 100644 index 0000000..99148e6 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/kernel_sigaction.h @@ -0,0 +1,68 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This file provides whatever this particular arch's kernel thinks + * the sigaction struct should look like... */ + +#undef NO_OLD_SIGACTION + +#if defined(__mips__) +#undef HAVE_SA_RESTORER +/* This is the sigaction structure from the Linux 2.1.24 kernel. */ +#include +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned int sa_flags; + unsigned long sa_mask; +}; +#define _KERNEL_NSIG 128 +#define _KERNEL_NSIG_BPW 32 +#define _KERNEL_NSIG_WORDS (_KERNEL_NSIG / _KERNEL_NSIG_BPW) + +typedef struct { + unsigned long sig[_KERNEL_NSIG_WORDS]; +} kernel_sigset_t; + +/* This is the sigaction structure from the Linux 2.1.68 kernel. */ +struct kernel_sigaction { + unsigned int sa_flags; + __sighandler_t k_sa_handler; + kernel_sigset_t sa_mask; + void (*sa_restorer)(void); + int s_resv[1]; /* reserved */ +}; +#elif defined(__ia64__) +#define NO_OLD_SIGACTION +#undef HAVE_SA_RESTORER +struct kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; +#else +#define HAVE_SA_RESTORER +/* This is the sigaction structure from the Linux 2.1.20 kernel. */ +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned long sa_flags; + void (*sa_restorer) (void); +}; +/* This is the sigaction structure from the Linux 2.1.68 kernel. */ +struct kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_flags; + void (*sa_restorer) (void); + sigset_t sa_mask; +}; +#endif + +#ifndef NO_OLD_SIGACTION +extern int __syscall_sigaction (int, const struct old_kernel_sigaction *__unbounded, + struct old_kernel_sigaction *__unbounded) attribute_hidden; +#endif + +extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, + struct kernel_sigaction *__unbounded, size_t) attribute_hidden; + +#endif /* _BITS_SIGACTION_STRUCT_H */ diff --git a/libc/sysdeps/linux/common/bits/kernel_stat.h b/libc/sysdeps/linux/common/bits/kernel_stat.h new file mode 100644 index 0000000..571c08f --- /dev/null +++ b/libc/sysdeps/linux/common/bits/kernel_stat.h @@ -0,0 +1,2 @@ +/* bits/kernel_stat.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." diff --git a/libc/sysdeps/linux/common/bits/kernel_types.h b/libc/sysdeps/linux/common/bits/kernel_types.h new file mode 100644 index 0000000..1c23ebf --- /dev/null +++ b/libc/sysdeps/linux/common/bits/kernel_types.h @@ -0,0 +1,20 @@ +#ifndef _BITS_KERNEL_TYPES_H +#define _BITS_KERNEL_TYPES_H + +/* Sigh. We need to carefully wrap this one... No guarantees + * that the asm/posix_types.h kernel header is working. Many + * arches have broken headers that introduce tons of gratuitous + * conflicts with uClibc's namespace. See bits/kernel_types.h + * for i386, arm, etc for examples... */ +#warning You really should include a proper bits/kernel_types.h for your architecture + +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +#endif /* _BITS_KERNEL_TYPES_H */ diff --git a/libc/sysdeps/linux/common/bits/local_lim.h b/libc/sysdeps/linux/common/bits/local_lim.h new file mode 100644 index 0000000..023ebf3 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/local_lim.h @@ -0,0 +1,87 @@ +/* Minimum guaranteed maximum values for system limits. Linux version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 16384 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/libc/sysdeps/linux/common/bits/locale.h b/libc/sysdeps/linux/common/bits/locale.h new file mode 100644 index 0000000..5d51783 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/locale.h @@ -0,0 +1,46 @@ +/* Definition of locale category symbol values. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _LOCALE_H && !defined _LANGINFO_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_LOCALE_H +#define _BITS_LOCALE_H 1 + +enum +{ + __LC_CTYPE = 0, + __LC_NUMERIC = 1, + __LC_TIME = 2, + __LC_COLLATE = 3, + __LC_MONETARY = 4, + __LC_MESSAGES = 5, + __LC_ALL = 6, +#if 0 + __LC_PAPER = 7, + __LC_NAME = 8, + __LC_ADDRESS = 9, + __LC_TELEPHONE = 10, + __LC_MEASUREMENT = 11, + __LC_IDENTIFICATION = 12 +#endif +}; + +#endif /* bits/locale.h */ diff --git a/libc/sysdeps/linux/common/bits/mathcalls.h b/libc/sysdeps/linux/common/bits/mathcalls.h new file mode 100644 index 0000000..e30b04a --- /dev/null +++ b/libc/sysdeps/linux/common/bits/mathcalls.h @@ -0,0 +1,444 @@ +/* Prototype declarations for math functions; helper file for . + Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* NOTE: Because of the special way this file is used by , this + file must NOT be protected from multiple inclusion as header files + usually are. + + This file provides prototype declarations for the math functions. + Most functions are declared using the macro: + + __MATHCALL (NAME,[_r], (ARGS...)); + + This means there is a function `NAME' returning `double' and a function + `NAMEf' returning `float'. Each place `_Mdouble_' appears in the + prototype, that is actually `double' in the prototype for `NAME' and + `float' in the prototype for `NAMEf'. Reentrant variant functions are + called `NAME_r' and `NAMEf_r'. + + Functions returning other types like `int' are declared using the macro: + + __MATHDECL (TYPE, NAME,[_r], (ARGS...)); + + This is just like __MATHCALL but for a function returning `TYPE' + instead of `_Mdouble_'. In all of these cases, there is still + both a `NAME' and a `NAMEf' that takes `float' arguments. + + Note that there must be no whitespace before the argument passed for + NAME, to make token pasting work with -traditional. */ + +#ifndef _MATH_H +# error "Never include directly; include instead." +#endif + + +/* Trigonometric functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Arc cosine of X. */ +__MATHCALL (acos,, (_Mdouble_ __x)); +libm_hidden_proto(acos) +/* Arc sine of X. */ +__MATHCALL (asin,, (_Mdouble_ __x)); +libm_hidden_proto(asin) +/* Arc tangent of X. */ +__MATHCALL (atan,, (_Mdouble_ __x)); +libm_hidden_proto(atan) +/* Arc tangent of Y/X. */ +__MATHCALL (atan2,, (_Mdouble_ __y, _Mdouble_ __x)); +libm_hidden_proto(atan2) + +/* Cosine of X. */ +__MATHCALL (cos,, (_Mdouble_ __x)); +libm_hidden_proto(cos) +/* Sine of X. */ +__MATHCALL (sin,, (_Mdouble_ __x)); +libm_hidden_proto(sin) +/* Tangent of X. */ +__MATHCALL (tan,, (_Mdouble_ __x)); +libm_hidden_proto(tan) + +/* Hyperbolic functions. */ + +/* Hyperbolic cosine of X. */ +__MATHCALL (cosh,, (_Mdouble_ __x)); +libm_hidden_proto(cosh) +/* Hyperbolic sine of X. */ +__MATHCALL (sinh,, (_Mdouble_ __x)); +libm_hidden_proto(sinh) +/* Hyperbolic tangent of X. */ +__MATHCALL (tanh,, (_Mdouble_ __x)); +libm_hidden_proto(tanh) +_Mdouble_END_NAMESPACE + +#if 0 /*def __USE_GNU*/ +/* Cosine and sine of X. */ +__MATHDECL (void,sincos,, + (_Mdouble_ __x, _Mdouble_ *__sinx, _Mdouble_ *__cosx)); +libm_hidden_proto(sincos) +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Hyperbolic arc cosine of X. */ +__MATHCALL (acosh,, (_Mdouble_ __x)); +libm_hidden_proto(acosh) +/* Hyperbolic arc sine of X. */ +__MATHCALL (asinh,, (_Mdouble_ __x)); +libm_hidden_proto(asinh) +/* Hyperbolic arc tangent of X. */ +__MATHCALL (atanh,, (_Mdouble_ __x)); +libm_hidden_proto(atanh) +__END_NAMESPACE_C99 +#endif + +/* Exponential and logarithmic functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Exponential function of X. */ +__MATHCALL (exp,, (_Mdouble_ __x)); +libm_hidden_proto(exp) + +/* Break VALUE into a normalized fraction and an integral power of 2. */ +__MATHCALL (frexp,, (_Mdouble_ __x, int *__exponent)); +libm_hidden_proto(frexp) + +/* X times (two to the EXP power). */ +__MATHCALL (ldexp,, (_Mdouble_ __x, int __exponent)); +libm_hidden_proto(ldexp) + +/* Natural logarithm of X. */ +__MATHCALL (log,, (_Mdouble_ __x)); +libm_hidden_proto(log) + +/* Base-ten logarithm of X. */ +__MATHCALL (log10,, (_Mdouble_ __x)); +libm_hidden_proto(log10) + +/* Break VALUE into integral and fractional parts. */ +__MATHCALL (modf,, (_Mdouble_ __x, _Mdouble_ *__iptr)); +libm_hidden_proto(modf) +_Mdouble_END_NAMESPACE + +#if 0 /*def __USE_GNU*/ +/* A function missing in all standards: compute exponent to base ten. */ +__MATHCALL (exp10,, (_Mdouble_ __x)); +libm_hidden_proto(exp10) +/* Another name occasionally used. */ +__MATHCALL (pow10,, (_Mdouble_ __x)); +libm_hidden_proto(pow10) +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return exp(X) - 1. */ +__MATHCALL (expm1,, (_Mdouble_ __x)); +libm_hidden_proto(expm1) + +/* Return log(1 + X). */ +__MATHCALL (log1p,, (_Mdouble_ __x)); +libm_hidden_proto(log1p) + +/* Return the base 2 signed integral exponent of X. */ +__MATHCALL (logb,, (_Mdouble_ __x)); +libm_hidden_proto(logb) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Compute base-2 exponential of X. */ +__MATHCALL (exp2,, (_Mdouble_ __x)); +libm_hidden_proto(exp2) + +/* Compute base-2 logarithm of X. */ +__MATHCALL (log2,, (_Mdouble_ __x)); +libm_hidden_proto(log2) +__END_NAMESPACE_C99 +#endif + + +/* Power functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Return X to the Y power. */ +__MATHCALL (pow,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(pow) + +/* Return the square root of X. */ +__MATHCALL (sqrt,, (_Mdouble_ __x)); +libm_hidden_proto(sqrt) +_Mdouble_END_NAMESPACE + +#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return `sqrt(X*X + Y*Y)'. */ +__MATHCALL (hypot,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(hypot) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return the cube root of X. */ +__MATHCALL (cbrt,, (_Mdouble_ __x)); +libm_hidden_proto(cbrt) +__END_NAMESPACE_C99 +#endif + + +/* Nearest integer, absolute value, and remainder functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Smallest integral value not less than X. */ +__MATHCALLX (ceil,, (_Mdouble_ __x), (__const__)); +libm_hidden_proto(ceil) + +/* Absolute value of X. */ +__MATHCALLX (fabs,, (_Mdouble_ __x), (__const__)); +libm_hidden_proto(fabs) + +/* Largest integer not greater than X. */ +__MATHCALLX (floor,, (_Mdouble_ __x), (__const__)); +libm_hidden_proto(floor) + +/* Floating-point modulo remainder of X/Y. */ +__MATHCALL (fmod,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(fmod) + + +/* Return 0 if VALUE is finite or NaN, +1 if it + is +Infinity, -1 if it is -Infinity. */ +__MATHDECL_1 (int,__isinf,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(__isinf) + +/* Return nonzero if VALUE is finite and not NaN. */ +__MATHDECL_1 (int,__finite,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(__finite) +_Mdouble_END_NAMESPACE + +#ifdef __USE_MISC +/* Return 0 if VALUE is finite or NaN, +1 if it + is +Infinity, -1 if it is -Infinity. */ +__MATHDECL_1 (int,isinf,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(isinf) + +/* Return nonzero if VALUE is finite and not NaN. */ +__MATHDECL_1 (int,finite,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(finite) + +/* Return the remainder of X/Y. */ +__MATHCALL (drem,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(drem) + + +/* Return the fractional part of X after dividing out `ilogb (X)'. */ +__MATHCALL (significand,, (_Mdouble_ __x)); +libm_hidden_proto(significand) +#endif /* Use misc. */ + +#if defined __USE_MISC || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return X with its signed changed to Y's. */ +__MATHCALLX (copysign,, (_Mdouble_ __x, _Mdouble_ __y), (__const__)); +libm_hidden_proto(copysign) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return representation of NaN for double type. */ +__MATHCALLX (nan,, (__const char *__tagb), (__const__)); +libm_hidden_proto(nan) +__END_NAMESPACE_C99 +#endif + + +/* Return nonzero if VALUE is not a number. */ +__MATHDECL_1 (int,__isnan,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(__isnan) + +#if defined __USE_MISC || defined __USE_XOPEN +/* Return nonzero if VALUE is not a number. */ +__MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__)); +libm_hidden_proto(isnan) + +/* Bessel functions. */ +__MATHCALL (j0,, (_Mdouble_)); +libm_hidden_proto(j0) +__MATHCALL (j1,, (_Mdouble_)); +libm_hidden_proto(j1) +__MATHCALL (jn,, (int, _Mdouble_)); +libm_hidden_proto(jn) +__MATHCALL (y0,, (_Mdouble_)); +libm_hidden_proto(y0) +__MATHCALL (y1,, (_Mdouble_)); +libm_hidden_proto(y1) +__MATHCALL (yn,, (int, _Mdouble_)); +libm_hidden_proto(yn) +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Error and gamma functions. */ +__MATHCALL (erf,, (_Mdouble_)); +libm_hidden_proto(erf) +__MATHCALL (erfc,, (_Mdouble_)); +libm_hidden_proto(erfc) +__MATHCALL (lgamma,, (_Mdouble_)); +libm_hidden_proto(lgamma) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* True gamma function. */ +__MATHCALL (tgamma,, (_Mdouble_)); +libm_hidden_proto(tgamma) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN +/* Obsolete alias for `lgamma'. */ +__MATHCALL (gamma,, (_Mdouble_)); +libm_hidden_proto(gamma) +#endif + +#ifdef __USE_MISC +/* Reentrant version of lgamma. This function uses the global variable + `signgam'. The reentrant version instead takes a pointer and stores + the value through it. */ +__MATHCALL (lgamma,_r, (_Mdouble_, int *__signgamp)); +libm_hidden_proto(lgamma_r) +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return the integer nearest X in the direction of the + prevailing rounding mode. */ +__MATHCALL (rint,, (_Mdouble_ __x)); +libm_hidden_proto(rint) + +/* Return X + epsilon if X < Y, X - epsilon if X > Y. */ +__MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__)); +libm_hidden_proto(nextafter) +# if defined __USE_ISOC99 && !defined __LDBL_COMPAT +__MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__)); +libm_hidden_proto(nexttoward) +# endif + +/* Return the remainder of integer divison X / Y with infinite precision. */ +__MATHCALL (remainder,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(remainder) + +# if defined __USE_MISC || defined __USE_ISOC99 +/* Return X times (2 to the Nth power). */ +__MATHCALL (scalbn,, (_Mdouble_ __x, int __n)); +libm_hidden_proto(scalbn) +# endif + +/* Return the binary exponent of X, which must be nonzero. */ +__MATHDECL (int,ilogb,, (_Mdouble_ __x)); +libm_hidden_proto(ilogb) +#endif + +#ifdef __USE_ISOC99 +/* Return X times (2 to the Nth power). */ +__MATHCALL (scalbln,, (_Mdouble_ __x, long int __n)); +libm_hidden_proto(scalbln) + +/* Round X to integral value in floating-point format using current + rounding direction, but do not raise inexact exception. */ +__MATHCALL (nearbyint,, (_Mdouble_ __x)); +libm_hidden_proto(nearbyint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +__MATHCALLX (round,, (_Mdouble_ __x), (__const__)); +libm_hidden_proto(round) + +/* Round X to the integral value in floating-point format nearest but + not larger in magnitude. */ +__MATHCALLX (trunc,, (_Mdouble_ __x), (__const__)); +libm_hidden_proto(trunc) + +/* Compute remainder of X and Y and put in *QUO a value with sign of x/y + and magnitude congruent `mod 2^n' to the magnitude of the integral + quotient x/y, with n >= 3. */ +__MATHCALL (remquo,, (_Mdouble_ __x, _Mdouble_ __y, int *__quo)); +libm_hidden_proto(remquo) + + +/* Conversion functions. */ + +/* Round X to nearest integral value according to current rounding + direction. */ +__MATHDECL (long int,lrint,, (_Mdouble_ __x)); +libm_hidden_proto(lrint) +__MATHDECL (long long int,llrint,, (_Mdouble_ __x)); +libm_hidden_proto(llrint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +__MATHDECL (long int,lround,, (_Mdouble_ __x)); +libm_hidden_proto(lround) +__MATHDECL (long long int,llround,, (_Mdouble_ __x)); +libm_hidden_proto(llround) + + +/* Return positive difference between X and Y. */ +__MATHCALL (fdim,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(fdim) + +/* Return maximum numeric value from X and Y. */ +__MATHCALL (fmax,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(fmax) + +/* Return minimum numeric value from X and Y. */ +__MATHCALL (fmin,, (_Mdouble_ __x, _Mdouble_ __y)); +libm_hidden_proto(fmin) + + +/* Classify given number. */ +__MATHDECL_1 (int, __fpclassify,, (_Mdouble_ __value)) + __attribute__ ((__const__)); +libm_hidden_proto(__fpclassify) + +/* Test for negative number. */ +__MATHDECL_1 (int, __signbit,, (_Mdouble_ __value)) + __attribute__ ((__const__)); +libm_hidden_proto(__signbit) + + +/* Multiply-add function computed as a ternary operation. */ +__MATHCALL (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z)); +libm_hidden_proto(fma) +#endif /* Use ISO C99. */ + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +/* Return X times (2 to the Nth power). */ +__MATHCALL (scalb,, (_Mdouble_ __x, _Mdouble_ __n)); +libm_hidden_proto(scalb) +#endif diff --git a/libc/sysdeps/linux/common/bits/mathdef.h b/libc/sysdeps/linux/common/bits/mathdef.h new file mode 100644 index 0000000..1927299 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/mathdef.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Normally, there is no long double type and the `float' and `double' + expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/common/bits/mathinline.h b/libc/sysdeps/linux/common/bits/mathinline.h new file mode 100644 index 0000000..5498af6 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/mathinline.h @@ -0,0 +1,12 @@ +/* This file should provide inline versions of math functions. + + Surround GCC-specific parts with #ifdef __GNUC__, and use `extern __inline'. + + This file should define __MATH_INLINES if functions are actually defined as + inlines. */ + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +/* Here goes the real code. */ + +#endif diff --git a/libc/sysdeps/linux/common/bits/mman.h b/libc/sysdeps/linux/common/bits/mman.h new file mode 100644 index 0000000..0c15902 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/mman.h @@ -0,0 +1,97 @@ +/* Definitions for BSD-style memory management. + Copyright (C) 1994-1998,2000,01,02,05 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* These are the bits used by 4.4 BSD and its derivatives. On systems + (such as GNU) where these facilities are not system services but can be + emulated in the C library, these are the definitions we emulate. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x04 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x01 /* Pages can be executed. */ + +/* Flags contain mapping type, sharing type and options. */ + +/* Mapping type (must choose one and only one of these). */ +#ifdef __USE_BSD +# define MAP_FILE 0x0001 /* Mapped from a file or device. */ +# define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */ +# define MAP_TYPE 0x000f /* Mask for type field. */ +# ifdef __USE_MISC +# define MAP_ANONYMOUS MAP_ANON /* Linux name. */ +# endif +#endif + +/* Sharing types (must choose one and only one of these). */ +#ifdef __USE_BSD +# define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */ +#endif +#define MAP_SHARED 0x0010 /* Share changes. */ +#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */ + +/* Other flags. */ +#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ +#ifdef __USE_BSD +# define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */ +# define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */ +# define MAP_INHERIT 0x0800 /* Region is retained after exec. */ +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 0 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 /* Mapping address may change. */ +# define MREMAP_FIXED 2 /* Fifth argument sets new address. */ +#endif + +/* Flags for `mlockall' (can be OR'd together). */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ diff --git a/libc/sysdeps/linux/common/bits/mqueue.h b/libc/sysdeps/linux/common/bits/mqueue.h new file mode 100644 index 0000000..df528f8 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/mqueue.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MQUEUE_H +# error "Never use directly; include instead." +#endif + +typedef int mqd_t; + +struct mq_attr +{ + long int mq_flags; /* Message queue flags. */ + long int mq_maxmsg; /* Maximum number of messages. */ + long int mq_msgsize; /* Maximum message size. */ + long int mq_curmsgs; /* Number of messages currently queued. */ + long int __pad[4]; +}; diff --git a/libc/sysdeps/linux/common/bits/msq.h b/libc/sysdeps/linux/common/bits/msq.h new file mode 100644 index 0000000..32a49b5 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/msq.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused1; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused2; + __time_t msg_ctime; /* time of last change */ + unsigned long int __unused3; + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/common/bits/nan.h b/libc/sysdeps/linux/common/bits/nan.h new file mode 100644 index 0000000..bae97f2 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/nan.h @@ -0,0 +1,53 @@ +/* `NAN' constant for IEEE 754 machines. + Copyright (C) 1992,1996,1997,1999,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + + +/* IEEE Not A Number. */ + +#if __GNUC_PREREQ(3,3) + +# define NAN (__builtin_nanf ("")) + +#elif defined __GNUC__ + +# define NAN \ + (__extension__ \ + ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; }) \ + { __l: 0x7fc00000UL }).__d) + +#else + +# include + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __nan_bytes { 0x7f, 0xc0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __nan_bytes { 0, 0, 0xc0, 0x7f } +# endif + +static union { unsigned char __c[4]; float __d; } __nan_union + __attribute_used__ = { __nan_bytes }; +# define NAN (__nan_union.__d) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/common/bits/netdb.h b/libc/sysdeps/linux/common/bits/netdb.h new file mode 100644 index 0000000..41dc731 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/netdb.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETDB_H +# error "Never include directly; use instead." +#endif + + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + uint32_t n_net; /* Network number. */ +}; diff --git a/libc/sysdeps/linux/common/bits/poll.h b/libc/sysdeps/linux/common/bits/poll.h new file mode 100644 index 0000000..d7996b4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM 0x100 /* Writing now will not block. */ +# define POLLWRBAND 0x200 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x400 +# define POLLREMOVE 0x1000 +# define POLLRDHUP 0x2000 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/common/bits/posix1_lim.h b/libc/sysdeps/linux/common/bits/posix1_lim.h new file mode 100644 index 0000000..3c86dce --- /dev/null +++ b/libc/sysdeps/linux/common/bits/posix1_lim.h @@ -0,0 +1,169 @@ +/* Copyright (C) 1991-1993,96,98,2000-2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.9.2 Minimum Values Added to + * + * Never include this file directly; use instead. + */ + +#ifndef _BITS_POSIX1_LIM_H +#define _BITS_POSIX1_LIM_H 1 + + +/* These are the standard-mandated minimum values. */ + +/* Minimum number of operations in one list I/O call. */ +#define _POSIX_AIO_LISTIO_MAX 2 + +/* Minimal number of outstanding asynchronous I/O operations. */ +#define _POSIX_AIO_MAX 1 + +/* Maximum length of arguments to `execve', including environment. */ +#define _POSIX_ARG_MAX 4096 + +/* Maximum simultaneous processes per real user ID. */ +#ifdef __USE_XOPEN2K +# define _POSIX_CHILD_MAX 25 +#else +# define _POSIX_CHILD_MAX 6 +#endif + +/* Minimal number of timer expiration overruns. */ +#define _POSIX_DELAYTIMER_MAX 32 + +/* Maximum length of a host name (not including the terminating null) + as returned from the GETHOSTNAME function. */ +#define _POSIX_HOST_NAME_MAX 255 + +/* Maximum link count of a file. */ +#define _POSIX_LINK_MAX 8 + +/* Maximum length of login name. */ +#define _POSIX_LOGIN_NAME_MAX 9 + +/* Number of bytes in a terminal canonical input queue. */ +#define _POSIX_MAX_CANON 255 + +/* Number of bytes for which space will be + available in a terminal input queue. */ +#define _POSIX_MAX_INPUT 255 + +/* Maximum number of message queues open for a process. */ +#define _POSIX_MQ_OPEN_MAX 8 + +/* Maximum number of supported message priorities. */ +#define _POSIX_MQ_PRIO_MAX 32 + +/* Number of bytes in a filename. */ +#define _POSIX_NAME_MAX 14 + +/* Number of simultaneous supplementary group IDs per process. */ +#ifdef __USE_XOPEN2K +# define _POSIX_NGROUPS_MAX 8 +#else +# define _POSIX_NGROUPS_MAX 0 +#endif + +/* Number of files one process can have open at once. */ +#ifdef __USE_XOPEN2K +# define _POSIX_OPEN_MAX 20 +#else +# define _POSIX_OPEN_MAX 16 +#endif + +/* Number of descriptors that a process may examine with `pselect' or + `select'. */ +#define _POSIX_FD_SETSIZE _POSIX_OPEN_MAX + +/* Number of bytes in a pathname. */ +#define _POSIX_PATH_MAX 256 + +/* Number of bytes than can be written atomically to a pipe. */ +#define _POSIX_PIPE_BUF 512 + +/* The number of repeated occurrences of a BRE permitted by the + REGEXEC and REGCOMP functions when using the interval notation. */ +#define _POSIX_RE_DUP_MAX 255 + +/* Minimal number of realtime signals reserved for the application. */ +#define _POSIX_RTSIG_MAX 8 + +/* Number of semaphores a process can have. */ +#define _POSIX_SEM_NSEMS_MAX 256 + +/* Maximal value of a semaphore. */ +#define _POSIX_SEM_VALUE_MAX 32767 + +/* Number of pending realtime signals. */ +#define _POSIX_SIGQUEUE_MAX 32 + +/* Largest value of a `ssize_t'. */ +#define _POSIX_SSIZE_MAX 32767 + +/* Number of streams a process can have open at once. */ +#define _POSIX_STREAM_MAX 8 + +/* The number of bytes in a symbolic link. */ +#define _POSIX_SYMLINK_MAX 255 + +/* The number of symbolic links that can be traversed in the + resolution of a pathname in the absence of a loop. */ +#define _POSIX_SYMLOOP_MAX 8 + +/* Number of timer for a process. */ +#define _POSIX_TIMER_MAX 32 + +/* Maximum number of characters in a tty name. */ +#define _POSIX_TTY_NAME_MAX 9 + +/* Maximum length of a timezone name (element of `tzname'). */ +#define _POSIX_TZNAME_MAX 6 + +/* Maximum number of connections that can be queued on a socket. */ +#define _POSIX_QLIMIT 1 + +/* Maximum number of bytes that can be buffered on a socket for send + or receive. */ +#define _POSIX_HIWAT _POSIX_PIPE_BUF + +/* Maximum number of elements in an `iovec' array. */ +#define _POSIX_UIO_MAXIOV 16 + +/* Maximum clock resolution in nanoseconds. */ +#define _POSIX_CLOCKRES_MIN 20000000 + + +/* Get the implementation-specific values for the above. */ +#include +#include + + +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif + + +/* This value is a guaranteed minimum maximum. + The current maximum can be got from `sysconf'. */ + +#ifndef NGROUPS_MAX +# define NGROUPS_MAX 8 +#endif + +#endif /* bits/posix1_lim.h */ diff --git a/libc/sysdeps/linux/common/bits/posix2_lim.h b/libc/sysdeps/linux/common/bits/posix2_lim.h new file mode 100644 index 0000000..24483a0 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/posix2_lim.h @@ -0,0 +1,91 @@ +/* Copyright (C) 1991, 1996, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; include instead. + */ + +#ifndef _BITS_POSIX2_LIM_H +#define _BITS_POSIX2_LIM_H 1 + + +/* The maximum `ibase' and `obase' values allowed by the `bc' utility. */ +#define _POSIX2_BC_BASE_MAX 99 + +/* The maximum number of elements allowed in an array by the `bc' utility. */ +#define _POSIX2_BC_DIM_MAX 2048 + +/* The maximum `scale' value allowed by the `bc' utility. */ +#define _POSIX2_BC_SCALE_MAX 99 + +/* The maximum length of a string constant accepted by the `bc' utility. */ +#define _POSIX2_BC_STRING_MAX 1000 + +/* The maximum number of weights that can be assigned to an entry of + the LC_COLLATE `order' keyword in the locale definition file. */ +#define _POSIX2_COLL_WEIGHTS_MAX 2 + +/* The maximum number of expressions that can be nested + within parentheses by the `expr' utility. */ +#define _POSIX2_EXPR_NEST_MAX 32 + +/* The maximum length, in bytes, of an input line. */ +#define _POSIX2_LINE_MAX 2048 + +/* The maximum number of repeated occurrences of a regular expression + permitted when using the interval notation `\{M,N\}'. */ +#define _POSIX2_RE_DUP_MAX 255 + +/* The maximum number of bytes in a character class name. We have no + fixed limit, 2048 is a high number. */ +#define _POSIX2_CHARCLASS_NAME_MAX 14 + + +/* These values are implementation-specific, + and may vary within the implementation. + Their precise values can be obtained from sysconf. */ + +#ifndef BC_BASE_MAX +#define BC_BASE_MAX _POSIX2_BC_BASE_MAX +#endif +#ifndef BC_DIM_MAX +#define BC_DIM_MAX _POSIX2_BC_DIM_MAX +#endif +#ifndef BC_SCALE_MAX +#define BC_SCALE_MAX _POSIX2_BC_SCALE_MAX +#endif +#ifndef BC_STRING_MAX +#define BC_STRING_MAX _POSIX2_BC_STRING_MAX +#endif +#ifndef COLL_WEIGHTS_MAX +#define COLL_WEIGHTS_MAX 255 +#endif +#ifndef EXPR_NEST_MAX +#define EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX +#endif +#ifndef LINE_MAX +#define LINE_MAX _POSIX2_LINE_MAX +#endif +#ifndef CHARCLASS_NAME_MAX +#define CHARCLASS_NAME_MAX 2048 +#endif + +/* This value is defined like this in regex.h. */ +#define RE_DUP_MAX (0x7fff) + +#endif /* bits/posix2_lim.h */ diff --git a/libc/sysdeps/linux/common/bits/posix_opt.h b/libc/sysdeps/linux/common/bits/posix_opt.h new file mode 100644 index 0000000..dfe259b --- /dev/null +++ b/libc/sysdeps/linux/common/bits/posix_opt.h @@ -0,0 +1,180 @@ +/* Define POSIX options for Linux. + Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _POSIX_OPT_H +#define _POSIX_OPT_H 1 + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Priority scheduling is supported. */ +#define _POSIX_PRIORITY_SCHEDULING 200112L + +/* Synchronizing file data is supported. */ +#define _POSIX_SYNCHRONIZED_IO 200112L + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200112L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200112L + +/* Locking of all memory is supported. */ +#define _POSIX_MEMLOCK 200112L + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200112L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200112L + +/* Only root can change owner of file. */ +#define _POSIX_CHOWN_RESTRICTED 1 + +/* `c_cc' member of 'struct termios' structure can be disabled by + using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE '\0' + +/* Filenames are not silently truncated. */ +#define _POSIX_NO_TRUNC 1 + +/* X/Open realtime support is available. */ +#define _XOPEN_REALTIME 1 + +/* XPG4.2 shared memory is supported. */ +#define _XOPEN_SHM 1 + +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200112L + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +/* We provide priority scheduling for threads. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200112L + +/* We support POSIX.1b semaphores. */ +#define _POSIX_SEMAPHORES 200112L + +/* Real-time signals are supported. */ +#define _POSIX_REALTIME_SIGNALS 200112L + +/* We support asynchronous I/O. */ +#define _POSIX_ASYNCHRONOUS_IO 200112L +#define _POSIX_ASYNC_IO 1 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO 1 +/* Support for prioritization is also available. */ +#define _POSIX_PRIORITIZED_IO 200112L + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO 1 + +#ifdef __UCLIBC_HAS_LFS__ +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 +#endif + +/* POSIX shared memory objects are implemented. */ +#define _POSIX_SHARED_MEMORY_OBJECTS 200112L + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 + +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200112L + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200112L + +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200112L + +/* The `spawn' function family is supported. */ +#define _POSIX_SPAWN 200112L + +/* We have POSIX timers. */ +#define _POSIX_TIMERS 200112L + +/* The barrier functions are available. */ +#define _POSIX_BARRIERS 200112L + +/* POSIX message queues are available. */ +#define _POSIX_MESSAGE_PASSING 200112L + +/* Thread process-shared synchronization is supported. */ +#define _POSIX_THREAD_PROCESS_SHARED 200112L + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200112L + +/* Advisory information interfaces are available. */ +#define _POSIX_ADVISORY_INFO 200112L + +/* IPv6 support is available. */ +#define _POSIX_IPV6 200112L + +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200112L + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200112L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +/* No support for priority inheritance or protection so far. */ +#define _POSIX_THREAD_PRIO_INHERIT -1 +#define _POSIX_THREAD_PRIO_PROTECT -1 + +#endif /* posix_opt.h */ diff --git a/libc/sysdeps/linux/common/bits/resource.h b/libc/sysdeps/linux/common/bits/resource.h new file mode 100644 index 0000000..526cdaf --- /dev/null +++ b/libc/sysdeps/linux/common/bits/resource.h @@ -0,0 +1,225 @@ +/* Bit values & structures for resource limits. Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 7, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit. */ + RLIMIT_AS = 9, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 6, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 8, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/libc/sysdeps/linux/common/bits/sched.h b/libc/sysdeps/linux/common/bits/sched.h new file mode 100644 index 0000000..b48a0c8 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sched.h @@ -0,0 +1,132 @@ +/* Definitions of constants and data structure for POSIX 1003.1b-1993 + scheduling interface. + Copyright (C) 1996-1999,2001-2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __need_schedparam + +#ifndef _SCHED_H +# error "Never include directly; use instead." +#endif + + +/* Scheduling algorithms. */ +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#ifdef __USE_GNU +# define SCHED_BATCH 3 +#endif + +#ifdef __USE_MISC +/* Cloning flags. */ +# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */ +# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */ +# define CLONE_FS 0x00000200 /* Set if fs info shared between processes. */ +# define CLONE_FILES 0x00000400 /* Set if open files shared between processes. */ +# define CLONE_SIGHAND 0x00000800 /* Set if signal handlers shared. */ +# define CLONE_PTRACE 0x00002000 /* Set if tracing continues on the child. */ +# define CLONE_VFORK 0x00004000 /* Set if the parent wants the child to + wake it up on mm_release. */ +# define CLONE_PARENT 0x00008000 /* Set if we want to have the same + parent as the cloner. */ +# define CLONE_THREAD 0x00010000 /* Set to add to same thread group. */ +# define CLONE_NEWNS 0x00020000 /* Set to create new namespace. */ +# define CLONE_SYSVSEM 0x00040000 /* Set to shared SVID SEM_UNDO semantics. */ +# define CLONE_SETTLS 0x00080000 /* Set TLS info. */ +# define CLONE_PARENT_SETTID 0x00100000 /* Store TID in userlevel buffer + before MM copy. */ +# define CLONE_CHILD_CLEARTID 0x00200000 /* Register exit futex and memory + location to clear. */ +# define CLONE_DETACHED 0x00400000 /* Create clone detached. */ +# define CLONE_UNTRACED 0x00800000 /* Set if the tracing process can't + force CLONE_PTRACE on this clone. */ +# define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in + the child. */ +# define CLONE_STOPPED 0x02000000 /* Start in stopped state. */ +#endif + +/* The official definition. */ +struct sched_param + { + int __sched_priority; + }; + +__BEGIN_DECLS + +#ifdef __USE_MISC +/* Clone current process. */ +extern int clone (int (*__fn) (void *__arg), void *__child_stack, + int __flags, void *__arg, ...) __THROW; + +#if 0 +/* Unshare the specified resources. */ +extern int unshare (int __flags) __THROW; +#endif +#endif + +__END_DECLS + +#endif /* need schedparam */ + +#if !defined __defined_schedparam \ + && (defined __need_schedparam || defined _SCHED_H) +# define __defined_schedparam 1 +/* Data structure to describe a process' schedulability. */ +struct __sched_param + { + int __sched_priority; + }; +# undef __need_schedparam +#endif + + +#if defined _SCHED_H && !defined __cpu_set_t_defined +# define __cpu_set_t_defined +/* Size definition for CPU sets. */ +# define __CPU_SETSIZE 1024 +# define __NCPUBITS (8 * sizeof (__cpu_mask)) + +/* Type for array elements in 'cpu_set'. */ +typedef unsigned long int __cpu_mask; + +/* Basic access functions. */ +# define __CPUELT(cpu) ((cpu) / __NCPUBITS) +# define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS)) + +/* Data structure to describe CPU mask. */ +typedef struct +{ + __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS]; +} cpu_set_t; + +/* Access functions for CPU masks. */ +# define __CPU_ZERO(cpusetp) \ + do { \ + unsigned int __i; \ + cpu_set_t *__arr = (cpusetp); \ + for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i) \ + __arr->__bits[__i] = 0; \ + } while (0) +# define __CPU_SET(cpu, cpusetp) \ + ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu)) +# define __CPU_CLR(cpu, cpusetp) \ + ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu)) +# define __CPU_ISSET(cpu, cpusetp) \ + (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0) +#endif diff --git a/libc/sysdeps/linux/common/bits/select.h b/libc/sysdeps/linux/common/bits/select.h new file mode 100644 index 0000000..47e7ded --- /dev/null +++ b/libc/sysdeps/linux/common/bits/select.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h new file mode 100644 index 0000000..6193501 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/common/bits/setjmp.h b/libc/sysdeps/linux/common/bits/setjmp.h new file mode 100644 index 0000000..ad9f04d --- /dev/null +++ b/libc/sysdeps/linux/common/bits/setjmp.h @@ -0,0 +1,2 @@ +/* bits/setjmp.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." diff --git a/libc/sysdeps/linux/common/bits/shm.h b/libc/sysdeps/linux/common/bits/shm.h new file mode 100644 index 0000000..318d601 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/common/bits/sigaction.h b/libc/sysdeps/linux/common/bits/sigaction.h new file mode 100644 index 0000000..48cc531 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigaction.h @@ -0,0 +1,77 @@ +/* The proper definitions for Linux's sigaction. + Copyright (C) 1993-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + + /* Special flags. */ + int sa_flags; + + /* Restore handler. */ + void (*sa_restorer) (void); + }; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 2 /* Don't create zombie on child death. */ +#define SA_SIGINFO 4 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal when + its handler is being executed. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* Block signals. */ +#define SIG_UNBLOCK 1 /* Unblock signals. */ +#define SIG_SETMASK 2 /* Set the set of blocked signals. */ diff --git a/libc/sysdeps/linux/common/bits/sigcontext.h b/libc/sysdeps/linux/common/bits/sigcontext.h new file mode 100644 index 0000000..67dcf94 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigcontext.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. */ +# define sigcontext_struct sigcontext + +# include +#endif diff --git a/libc/sysdeps/linux/common/bits/sigcontextinfo.h b/libc/sysdeps/linux/common/bits/sigcontextinfo.h new file mode 100644 index 0000000..40305b4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* In general we cannot provide any information. */ +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) 0) +#define GET_FRAME(ctx) ((void *) 0) +#define GET_STACK(ctx) ((void *) 0) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/common/bits/siginfo.h b/libc/sysdeps/linux/common/bits/siginfo.h new file mode 100644 index 0000000..4ce319d --- /dev/null +++ b/libc/sysdeps/linux/common/bits/siginfo.h @@ -0,0 +1,313 @@ +/* siginfo_t, sigevent and constants. Linux version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + long int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# if __WORDSIZE == 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/libc/sysdeps/linux/common/bits/signum.h b/libc/sysdeps/linux/common/bits/signum.h new file mode 100644 index 0000000..a18ac11 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/signum.h @@ -0,0 +1,80 @@ +/* Signal number definitions. Linux version. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif + + +/* Signals. */ +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +#define _NSIG 65 /* Biggest signal number + 1 + (including real-time signals). */ + +#define SIGRTMIN (__libc_current_sigrtmin ()) +#define SIGRTMAX (__libc_current_sigrtmax ()) + +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#define __SIGRTMIN 32 +#define __SIGRTMAX (_NSIG - 1) + +#endif /* included. */ diff --git a/libc/sysdeps/linux/common/bits/sigset.h b/libc/sysdeps/linux/common/bits/sigset.h new file mode 100644 index 0000000..7ccadda --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigset.h @@ -0,0 +1,125 @@ +/* __sig_atomic_t, __sigset_t, and related definitions. Linux version. + Copyright (C) 1991, 1992, 1994, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGSET_H_types +# define _SIGSET_H_types 1 + +typedef int __sig_atomic_t; + +/* A `sigset_t' has a bit for each signal. */ + +# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int))) +typedef struct + { + unsigned long int __val[_SIGSET_NWORDS]; + } __sigset_t; + +#endif + + +/* We only want to define these functions if was actually + included; otherwise we were included just to define the types. Since we + are namespace-clean, it wouldn't hurt to define extra macros. But + trouble can be caused by functions being defined (e.g., any global + register vars declared later will cause compilation errors). */ + +#if !defined _SIGSET_H_fns && defined _SIGNAL_H +# define _SIGSET_H_fns 1 + +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif + +/* Return a mask that includes the bit for SIG only. */ +# define __sigmask(sig) \ + (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int)))) + +/* Return the word index for SIG. */ +# define __sigword(sig) (((sig) - 1) / (8 * sizeof (unsigned long int))) + +# if defined __GNUC__ && __GNUC__ >= 2 +# define __sigemptyset(set) \ + (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ + sigset_t *__set = (set); \ + while (--__cnt >= 0) __set->__val[__cnt] = 0; \ + 0; })) +# define __sigfillset(set) \ + (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ + sigset_t *__set = (set); \ + while (--__cnt >= 0) __set->__val[__cnt] = ~0UL; \ + 0; })) + +# ifdef __USE_GNU +/* The POSIX does not specify for handling the whole signal set in one + command. This is often wanted and so we define three more functions + here. */ +# define __sigisemptyset(set) \ + (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ + const sigset_t *__set = (set); \ + int __ret = __set->__val[--__cnt]; \ + while (!__ret && --__cnt >= 0) \ + __ret = __set->__val[__cnt]; \ + __ret == 0; })) +# define __sigandset(dest, left, right) \ + (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + & __right->__val[__cnt]); \ + 0; })) +# define __sigorset(dest, left, right) \ + (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + | __right->__val[__cnt]); \ + 0; })) +# endif +# endif + +/* These functions needn't check for a bogus signal number -- error + checking is done in the non __ versions. */ + +extern int __sigismember (__const __sigset_t *, int); +extern int __sigaddset (__sigset_t *, int); +extern int __sigdelset (__sigset_t *, int); + +# ifdef __USE_EXTERN_INLINES +# define __SIGSETFN(NAME, BODY, CONST) \ + _EXTERN_INLINE int \ + NAME (CONST __sigset_t *__set, int __sig) \ + { \ + unsigned long int __mask = __sigmask (__sig); \ + unsigned long int __word = __sigword (__sig); \ + return BODY; \ + } + +__SIGSETFN (__sigismember, (__set->__val[__word] & __mask) ? 1 : 0, __const) +__SIGSETFN (__sigaddset, ((__set->__val[__word] |= __mask), 0), ) +__SIGSETFN (__sigdelset, ((__set->__val[__word] &= ~__mask), 0), ) + +# undef __SIGSETFN +# endif + + +#endif /* ! _SIGSET_H_fns. */ diff --git a/libc/sysdeps/linux/common/bits/sigstack.h b/libc/sysdeps/linux/common/bits/sigstack.h new file mode 100644 index 0000000..7f26036 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 2048 + +/* System default stack size. */ +#define SIGSTKSZ 8192 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/libc/sysdeps/linux/common/bits/sigthread.h b/libc/sysdeps/linux/common/bits/sigthread.h new file mode 100644 index 0000000..960bde1 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sigthread.h @@ -0,0 +1,38 @@ +/* Signal handling function for threaded programs. + Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_SIGTHREAD_H +#define _BITS_SIGTHREAD_H 1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly. Use instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread. The arguments have + the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, + __const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#endif /* bits/sigthread.h */ diff --git a/libc/sysdeps/linux/common/bits/sockaddr.h b/libc/sysdeps/linux/common/bits/sockaddr.h new file mode 100644 index 0000000..3e1d131 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/sockaddr.h @@ -0,0 +1,40 @@ +/* Definition of `struct sockaddr_*' common members. Generic/4.2 BSD version. + Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_SOCKADDR_H +#define _BITS_SOCKADDR_H 1 + + +/* POSIX.1g specifies this type name for the `sa_family' member. */ +typedef unsigned short int sa_family_t; + +/* This macro is used to declare the initial common members + of the data types used for socket addresses, `struct sockaddr', + `struct sockaddr_in', `struct sockaddr_un', etc. */ + +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) + +#endif /* bits/sockaddr.h */ diff --git a/libc/sysdeps/linux/common/bits/socket.h b/libc/sysdeps/linux/common/bits/socket.h new file mode 100644 index 0000000..c352a17 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/socket.h @@ -0,0 +1,333 @@ +/* System-specific socket constants and types. Linux version. + Copyright (C) 1991,1992,1994-2001,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_PACKET = 10 /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#if ULONG_MAX > 0xffffffff +# define __ss_aligntype __uint64_t +#else +# define __ss_aligntype __uint32_t +#endif +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000 /* Sender will send more. */ +#define MSG_MORE MSG_MORE + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#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)) + +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +#endif /* bits/socket.h */ diff --git a/libc/sysdeps/linux/common/bits/stab.def b/libc/sysdeps/linux/common/bits/stab.def new file mode 100644 index 0000000..3d54774 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/stab.def @@ -0,0 +1,234 @@ +/* Table of DBX symbol codes for the GNU system. + Copyright (C) 1988, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This contains contribution from Cygnus Support. */ + +/* Global variable. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_GSYM, 0x20, "GSYM") + +/* Function name for BSD Fortran. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_FNAME, 0x22, "FNAME") + +/* Function name or text-segment variable for C. Value is its address. + Desc is supposedly starting line number, but GCC doesn't set it + and DBX seems not to miss it. */ +__define_stab (N_FUN, 0x24, "FUN") + +/* Data-segment variable with internal linkage. Value is its address. + "Static Sym". */ +__define_stab (N_STSYM, 0x26, "STSYM") + +/* BSS-segment variable with internal linkage. Value is its address. */ +__define_stab (N_LCSYM, 0x28, "LCSYM") + +/* Name of main routine. Only the name is significant. + This is not used in C. */ +__define_stab (N_MAIN, 0x2a, "MAIN") + +/* Global symbol in Pascal. + Supposedly the value is its line number; I'm skeptical. */ +__define_stab (N_PC, 0x30, "PC") + +/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ +__define_stab (N_NSYMS, 0x32, "NSYMS") + +/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ +__define_stab (N_NOMAP, 0x34, "NOMAP") + +/* New stab from Solaris. I don't know what it means, but it + don't seem to contain useful information. */ +__define_stab (N_OBJ, 0x38, "OBJ") + +/* New stab from Solaris. I don't know what it means, but it + don't seem to contain useful information. Possibly related to the + optimization flags used in this module. */ +__define_stab (N_OPT, 0x3c, "OPT") + +/* Register variable. Value is number of register. */ +__define_stab (N_RSYM, 0x40, "RSYM") + +/* Modula-2 compilation unit. Can someone say what info it contains? */ +__define_stab (N_M2C, 0x42, "M2C") + +/* Line number in text segment. Desc is the line number; + value is corresponding address. */ +__define_stab (N_SLINE, 0x44, "SLINE") + +/* Similar, for data segment. */ +__define_stab (N_DSLINE, 0x46, "DSLINE") + +/* Similar, for bss segment. */ +__define_stab (N_BSLINE, 0x48, "BSLINE") + +/* Sun's source-code browser stabs. ?? Don't know what the fields are. + Supposedly the field is "path to associated .cb file". THIS VALUE + OVERLAPS WITH N_BSLINE! */ +__define_stab (N_BROWS, 0x48, "BROWS") + +/* GNU Modula-2 definition module dependency. Value is the modification time + of the definition file. Other is non-zero if it is imported with the + GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there + are enough empty fields? */ +__define_stab(N_DEFD, 0x4a, "DEFD") + +/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 + and one is for C++. Still,... */ +/* GNU C++ exception variable. Name is variable name. */ +__define_stab (N_EHDECL, 0x50, "EHDECL") +/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ +__define_stab (N_MOD2, 0x50, "MOD2") + +/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if + this entry is immediately followed by a CAUGHT stab saying what exception + was caught. Multiple CAUGHT stabs means that multiple exceptions + can be caught here. If Desc is 0, it means all exceptions are caught + here. */ +__define_stab (N_CATCH, 0x54, "CATCH") + +/* Structure or union element. Value is offset in the structure. */ +__define_stab (N_SSYM, 0x60, "SSYM") + +/* Name of main source file. + Value is starting text address of the compilation. */ +__define_stab (N_SO, 0x64, "SO") + +/* Automatic variable in the stack. Value is offset from frame pointer. + Also used for type descriptions. */ +__define_stab (N_LSYM, 0x80, "LSYM") + +/* Beginning of an include file. Only Sun uses this. + In an object file, only the name is significant. + The Sun linker puts data into some of the other fields. */ +__define_stab (N_BINCL, 0x82, "BINCL") + +/* Name of sub-source file (#include file). + Value is starting text address of the compilation. */ +__define_stab (N_SOL, 0x84, "SOL") + +/* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ +__define_stab (N_PSYM, 0xa0, "PSYM") + +/* End of an include file. No name. + This and N_BINCL act as brackets around the file's output. + In an object file, there is no significant data in this entry. + The Sun linker puts data into some of the fields. */ +__define_stab (N_EINCL, 0xa2, "EINCL") + +/* Alternate entry point. Value is its address. */ +__define_stab (N_ENTRY, 0xa4, "ENTRY") + +/* Beginning of lexical block. + The desc is the nesting level in lexical blocks. + The value is the address of the start of the text for the block. + The variables declared inside the block *precede* the N_LBRAC symbol. */ +__define_stab (N_LBRAC, 0xc0, "LBRAC") + +/* Place holder for deleted include file. Replaces a N_BINCL and everything + up to the corresponding N_EINCL. The Sun linker generates these when + it finds multiple identical copies of the symbols from an include file. + This appears only in output from the Sun linker. */ +__define_stab (N_EXCL, 0xc2, "EXCL") + +/* Modula-2 scope information. Can someone say what info it contains? */ +__define_stab (N_SCOPE, 0xc4, "SCOPE") + +/* End of a lexical block. Desc matches the N_LBRAC's desc. + The value is the address of the end of the text for the block. */ +__define_stab (N_RBRAC, 0xe0, "RBRAC") + +/* Begin named common block. Only the name is significant. */ +__define_stab (N_BCOMM, 0xe2, "BCOMM") + +/* End named common block. Only the name is significant + (and it should match the N_BCOMM). */ +__define_stab (N_ECOMM, 0xe4, "ECOMM") + +/* End common (local name): value is address. + I'm not sure how this is used. */ +__define_stab (N_ECOML, 0xe8, "ECOML") + +/* These STAB's are used on Gould systems for Non-Base register symbols + or something like that. FIXME. I have assigned the values at random + since I don't have a Gould here. Fixups from Gould folk welcome... */ +__define_stab (N_NBTEXT, 0xF0, "NBTEXT") +__define_stab (N_NBDATA, 0xF2, "NBDATA") +__define_stab (N_NBBSS, 0xF4, "NBBSS") +__define_stab (N_NBSTS, 0xF6, "NBSTS") +__define_stab (N_NBLCS, 0xF8, "NBLCS") + +/* Second symbol entry containing a length-value for the preceding entry. + The value is the length. */ +__define_stab (N_LENG, 0xfe, "LENG") + +/* The above information, in matrix format. + + STAB MATRIX + _________________________________________________ + | 00 - 1F are not dbx stab symbols | + | In most cases, the low bit is the EXTernal bit| + + | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | + | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | + + | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | + | 09 |EXT | 0B | 0D | 0F | + + | 10 | 12 COMM | 14 SETA | 16 SETT | + | 11 | 13 | 15 | 17 | + + | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| + | 19 | 1B | 1D | 1F FN | + + |_______________________________________________| + | Debug entries with bit 01 set are unused. | + | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | + | 28 LCSYM | 2A MAIN | 2C | 2E | + | 30 PC | 32 NSYMS | 34 NOMAP | 36 | + | 38 OBJ | 3A | 3C OPT | 3E | + | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | + | 48 BSLINE*| 4A DEFD | 4C | 4E | + | 50 EHDECL*| 52 | 54 CATCH | 56 | + | 58 | 5A | 5C | 5E | + | 60 SSYM | 62 | 64 SO | 66 | + | 68 | 6A | 6C | 6E | + | 70 | 72 | 74 | 76 | + | 78 | 7A | 7C | 7E | + | 80 LSYM | 82 BINCL | 84 SOL | 86 | + | 88 | 8A | 8C | 8E | + | 90 | 92 | 94 | 96 | + | 98 | 9A | 9C | 9E | + | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | + | A8 | AA | AC | AE | + | B0 | B2 | B4 | B6 | + | B8 | BA | BC | BE | + | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | + | C8 | CA | CC | CE | + | D0 | D2 | D4 | D6 | + | D8 | DA | DC | DE | + | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | + | E8 ECOML | EA | EC | EE | + | F0 | F2 | F4 | F6 | + | F8 | FA | FC | FE LENG | + +-----------------------------------------------+ + * 50 EHDECL is also MOD2. + * 48 BSLINE is also BROWS. + */ diff --git a/libc/sysdeps/linux/common/bits/stackinfo.h b/libc/sysdeps/linux/common/bits/stackinfo.h new file mode 100644 index 0000000..1ed7b95 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/stackinfo.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. Since there is no general truth we can't say + anything here. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#error Machine stack direction unknown. +#if 0 +#define _STACK_GROWS_DOWN 1 +#define _STACK_GROWS_UP 1 +#endif + +#endif /* stackinfo.h */ + + diff --git a/libc/sysdeps/linux/common/bits/stat.h b/libc/sysdeps/linux/common/bits/stat.h new file mode 100644 index 0000000..bd5aae2 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/stat.h @@ -0,0 +1,165 @@ +/* Copyright (C) 1992, 1995-2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifndef __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +#else + unsigned int __pad1; + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + unsigned short int __pad2; + __off_t st_size; /* Size of file, in bytes. */ +#else + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/common/bits/statfs.h b/libc/sysdeps/linux/common/bits/statfs.h new file mode 100644 index 0000000..0e27865 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/statfs.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include + +struct statfs + { + __SWORD_TYPE f_type; + __SWORD_TYPE f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + __SWORD_TYPE f_namelen; + __SWORD_TYPE f_frsize; + __SWORD_TYPE f_spare[5]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + __SWORD_TYPE f_type; + __SWORD_TYPE f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + __SWORD_TYPE f_namelen; + __SWORD_TYPE f_frsize; + __SWORD_TYPE f_spare[5]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATFS_F_NAMELEN +#define _STATFS_F_FRSIZE diff --git a/libc/sysdeps/linux/common/bits/statvfs.h b/libc/sysdeps/linux/common/bits/statvfs.h new file mode 100644 index 0000000..cca0871 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/statvfs.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +#if __WORDSIZE == 32 +#define _STATVFSBUF_F_UNUSED +#endif + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync with the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2 /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + , + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME = 2048 /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/libc/sysdeps/linux/common/bits/stdio.h b/libc/sysdeps/linux/common/bits/stdio.h new file mode 100644 index 0000000..d0ba463 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/stdio.h @@ -0,0 +1,23 @@ +/* Optimizing macros and inline functions for stdio functions. + Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STDIO_H +# error "Never include directly; use instead." +#endif + diff --git a/libc/sysdeps/linux/common/bits/stdio_lim.h b/libc/sysdeps/linux/common/bits/stdio_lim.h new file mode 100644 index 0000000..c35ee60 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/stdio_lim.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1994, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _STDIO_H && !defined __need_FOPEN_MAX && !defined __need_IOV_MAX +# error "Never include directly; use instead." +#endif + +#ifdef _STDIO_H +# define L_tmpnam 20 +# define TMP_MAX 238328 +# define FILENAME_MAX 4095 + +# ifdef __USE_POSIX +# define L_ctermid 9 +# define L_cuserid 9 +# endif +#endif + +#if defined __need_FOPEN_MAX || defined _STDIO_H +# undef FOPEN_MAX +# define FOPEN_MAX 16 +#endif + +#if defined __need_IOV_MAX && !defined IOV_MAX +# define IOV_MAX 1024 +#endif diff --git a/libc/sysdeps/linux/common/bits/syscalls.h b/libc/sysdeps/linux/common/bits/syscalls.h new file mode 100644 index 0000000..ceba568 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/syscalls.h @@ -0,0 +1,8 @@ +/* Unlike the asm/unistd.h kernel header file (which this is partly based on), + * this file must be able to cope with PIC and non-PIC code. For some arches + * there is no difference. For x86 (which has far too few registers) there is + * a difference. Regardless, including asm/unistd.h is hereby officially + * forbidden. Don't do it. It is bad for you. + */ + +#error You have not provided architecture specific _syscall[0-6] macros diff --git a/libc/sysdeps/linux/common/bits/termios.h b/libc/sysdeps/linux/common/bits/termios.h new file mode 100644 index 0000000..b648d80 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/termios.h @@ -0,0 +1,219 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#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 + +/* c_iflag bits */ +#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 IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# 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 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#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 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#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 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define BOTHER 0010000 +#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 __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/sysdeps/linux/common/bits/time.h b/libc/sysdeps/linux/common/bits/time.h new file mode 100644 index 0000000..7ed54bf --- /dev/null +++ b/libc/sysdeps/linux/common/bits/time.h @@ -0,0 +1,79 @@ +/* System-dependent timing definitions. Generic version. + Copyright (C) 1996,1997,1999-2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef __need_timeval +# ifndef _BITS_TIME_H +# define _BITS_TIME_H 1 + +/* ISO/IEC 9899:1990 7.12.1: + The macro `CLOCKS_PER_SEC' is the number per second of the value + returned by the `clock' function. */ +/* CAE XSH, Issue 4, Version 2: + The value of CLOCKS_PER_SEC is required to be 1 million on all + XSI-conformant systems. */ +# define CLOCKS_PER_SEC 1000000l + +/* Get the arch-specific value of __UCLIBC_CLK_TCK_CONST used for CLK_TCK + * in sysconf() and clock(). */ +#include + +# if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K +/* Even though CLOCKS_PER_SEC has such a strange value CLK_TCK + presents the real value for clock ticks per second for the system. */ +# include +/* Note (uClibc): glibc #defines CLK_TCK as a sysconf() call. */ +# define CLK_TCK ((__clock_t) __UCLIBC_CLK_TCK_CONST) +# endif + +# ifdef __USE_POSIX199309 +/* Identifier for system-wide realtime clock. */ +# define CLOCK_REALTIME 0 +/* Monotonic system-wide clock. */ +# define CLOCK_MONOTONIC 1 +/* High-resolution timer from the CPU. */ +# define CLOCK_PROCESS_CPUTIME_ID 2 +/* Thread-specific CPU-time clock. */ +# define CLOCK_THREAD_CPUTIME_ID 3 + +/* Flag to indicate time is absolute. */ +# define TIMER_ABSTIME 1 +# endif + +# endif /* bits/time.h */ +#endif + +#ifdef __need_timeval +# undef __need_timeval +# ifndef _STRUCT_TIMEVAL +# define _STRUCT_TIMEVAL 1 +# include + +/* A time value that is accurate to the nearest + microsecond but also has a range of years. */ +struct timeval + { + __time_t tv_sec; /* Seconds. */ + __suseconds_t tv_usec; /* Microseconds. */ + }; +# endif /* struct timeval */ +#endif /* need timeval */ diff --git a/libc/sysdeps/linux/common/bits/types.h b/libc/sysdeps/linux/common/bits/types.h new file mode 100644 index 0000000..755af2e --- /dev/null +++ b/libc/sysdeps/linux/common/bits/types.h @@ -0,0 +1,209 @@ +/* bits/types.h -- definitions of __*_t types underlying *_t types. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_TYPES_H +#define _BITS_TYPES_H 1 + +#include +#include + +#define __need_size_t +#include +#include + +/* Convenience types. */ +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; + +/* Fixed-size types, underlying types depend on word size and compiler. */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; +#if __WORDSIZE == 64 +typedef signed long int __int64_t; +typedef unsigned long int __uint64_t; +#elif defined(__GNUC__) +__extension__ typedef signed long long int __int64_t; +__extension__ typedef unsigned long long int __uint64_t; +#endif + +/* quad_t is also 64 bits. */ +#if __WORDSIZE == 64 +typedef long int __quad_t; +typedef unsigned long int __u_quad_t; +#elif defined(__GNUC__) +__extension__ typedef long long int __quad_t; +__extension__ typedef unsigned long long int __u_quad_t; +#else +typedef struct +{ + long __val[2]; +} __quad_t; +typedef struct +{ + __u_long __val[2]; +} __u_quad_t; +#endif + + +/* The machine-dependent file defines __*_T_TYPE + macros for each of the OS types we define below. The definitions + of those macros must use the following macros for underlying types. + We define __S_TYPE and __U_TYPE for the signed and unsigned + variants of each of the following integer types on this machine. + + 16 -- "natural" 16-bit type (always short) + 32 -- "natural" 32-bit type (always int) + 64 -- "natural" 64-bit type (long or long long) + LONG32 -- 32-bit type, traditionally long + QUAD -- 64-bit type, always long long + WORD -- natural type of __WORDSIZE bits (int or long) + LONGWORD -- type of __WORDSIZE bits, traditionally long + + We distinguish WORD/LONGWORD, 32/LONG32, and 64/QUAD so that the + conventional uses of `long' or `long long' type modifiers match the + types we define, even when a less-adorned type would be the same size. + This matters for (somewhat) portably writing printf/scanf formats for + these types, where using the appropriate l or ll format modifiers can + make the typedefs and the formats match up across all GNU platforms. If + we used `long' when it's 64 bits where `long long' is expected, then the + compiler would warn about the formats not matching the argument types, + and the programmer changing them to shut up the compiler would break the + program's portability. + + Here we assume what is presently the case in all the GCC configurations + we support: long long is always 64 bits, long is always word/address size, + and int is always 32 bits. */ + +#define __S16_TYPE short int +#define __U16_TYPE unsigned short int +#define __S32_TYPE int +#define __U32_TYPE unsigned int +#define __SLONGWORD_TYPE long int +#define __ULONGWORD_TYPE unsigned long int +#if __WORDSIZE == 32 +# define __SQUAD_TYPE __quad_t +# define __UQUAD_TYPE __u_quad_t +# define __SWORD_TYPE int +# define __UWORD_TYPE unsigned int +# define __SLONG32_TYPE long int +# define __ULONG32_TYPE unsigned long int +# define __S64_TYPE __quad_t +# define __U64_TYPE __u_quad_t +/* We want __extension__ before typedef's that use nonstandard base types + such as `long long' in C89 mode. */ +# define __STD_TYPE __extension__ typedef +#elif __WORDSIZE == 64 +# define __SQUAD_TYPE long int +# define __UQUAD_TYPE unsigned long int +# define __SWORD_TYPE long int +# define __UWORD_TYPE unsigned long int +# define __SLONG32_TYPE int +# define __ULONG32_TYPE unsigned int +# define __S64_TYPE long int +# define __U64_TYPE unsigned long int +/* No need to mark the typedef with __extension__. */ +# define __STD_TYPE typedef +#else +# error +#endif +#include /* Defines __*_T_TYPE macros. */ + + +__STD_TYPE __DEV_T_TYPE __dev_t; /* Type of device numbers. */ +__STD_TYPE __UID_T_TYPE __uid_t; /* Type of user identifications. */ +__STD_TYPE __GID_T_TYPE __gid_t; /* Type of group identifications. */ +__STD_TYPE __INO_T_TYPE __ino_t; /* Type of file serial numbers. */ +__STD_TYPE __INO64_T_TYPE __ino64_t; /* Type of file serial numbers (LFS).*/ +__STD_TYPE __MODE_T_TYPE __mode_t; /* Type of file attribute bitmasks. */ +__STD_TYPE __NLINK_T_TYPE __nlink_t; /* Type of file link counts. */ +__STD_TYPE __OFF_T_TYPE __off_t; /* Type of file sizes and offsets. */ +__STD_TYPE __OFF64_T_TYPE __off64_t; /* Type of file sizes and offsets (LFS). */ +__STD_TYPE __PID_T_TYPE __pid_t; /* Type of process identifications. */ +__STD_TYPE __FSID_T_TYPE __fsid_t; /* Type of file system IDs. */ +__STD_TYPE __CLOCK_T_TYPE __clock_t; /* Type of CPU usage counts. */ +__STD_TYPE __RLIM_T_TYPE __rlim_t; /* Type for resource measurement. */ +__STD_TYPE __RLIM64_T_TYPE __rlim64_t; /* Type for resource measurement (LFS). */ +__STD_TYPE __ID_T_TYPE __id_t; /* General type for IDs. */ +__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */ +__STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds. */ +__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds. */ + +__STD_TYPE __DADDR_T_TYPE __daddr_t; /* The type of a disk address. */ +__STD_TYPE __SWBLK_T_TYPE __swblk_t; /* Type of a swap block maybe? */ +__STD_TYPE __KEY_T_TYPE __key_t; /* Type of an IPC key. */ + +/* Clock ID used in clock and timer functions. */ +__STD_TYPE __CLOCKID_T_TYPE __clockid_t; + +/* Timer ID returned by `timer_create'. */ +__STD_TYPE __TIMER_T_TYPE __timer_t; + +/* Type to represent block size. */ +__STD_TYPE __BLKSIZE_T_TYPE __blksize_t; + +/* Types from the Large File Support interface. */ + +/* Type to count number of disk blocks. */ +__STD_TYPE __BLKCNT_T_TYPE __blkcnt_t; +__STD_TYPE __BLKCNT64_T_TYPE __blkcnt64_t; + +/* Type to count file system blocks. */ +__STD_TYPE __FSBLKCNT_T_TYPE __fsblkcnt_t; +__STD_TYPE __FSBLKCNT64_T_TYPE __fsblkcnt64_t; + +/* Type to count file system nodes. */ +__STD_TYPE __FSFILCNT_T_TYPE __fsfilcnt_t; +__STD_TYPE __FSFILCNT64_T_TYPE __fsfilcnt64_t; + +__STD_TYPE __SSIZE_T_TYPE __ssize_t; /* Type of a byte count, or error. */ + +/* These few don't really vary by system, they always correspond + to one of the other defined types. */ +typedef __off64_t __loff_t; /* Type of file sizes and offsets (LFS). */ +typedef __quad_t *__qaddr_t; +typedef char *__caddr_t; + +/* Duplicates info from stdint.h but this is used in unistd.h. */ +__STD_TYPE __SWORD_TYPE __intptr_t; + +/* Duplicate info from sys/socket.h. */ +__STD_TYPE __U32_TYPE __socklen_t; + + +#undef __STD_TYPE + +/* Used in `struct shmid_ds'. */ +typedef __kernel_ipc_pid_t __ipc_pid_t; + +/* Now add the thread types. */ +#if defined __UCLIBC_HAS_THREADS__ && (defined __USE_POSIX199506 || defined __USE_UNIX98) +# include +#endif + +#endif /* bits/types.h */ diff --git a/libc/sysdeps/linux/common/bits/typesizes.h b/libc/sysdeps/linux/common/bits/typesizes.h new file mode 100644 index 0000000..e9226c4 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_arch_features.h b/libc/sysdeps/linux/common/bits/uClibc_arch_features.h new file mode 100644 index 0000000..66186ed --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_arch_features.h @@ -0,0 +1,44 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +#error "You should copy this to your arch/bits/ dir and customize" + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h b/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h new file mode 100644 index 0000000..00b77bf --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h @@ -0,0 +1,8 @@ +/* Use a default of 100 for CLK_TCK to implement sysconf() and clock(). + * Override this by supplying an arch-specific version of this header file. + * + * WARNING: It is assumed that this is a constant integer value usable in + * preprocessor conditionals!!! + */ + +#define __UCLIBC_CLK_TCK_CONST 100 diff --git a/libc/sysdeps/linux/common/bits/uClibc_ctype.h b/libc/sysdeps/linux/common/bits/uClibc_ctype.h new file mode 100644 index 0000000..0b02c5d --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_ctype.h @@ -0,0 +1,279 @@ +/* Copyright (C) 2002 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#if !defined(_CTYPE_H) && !defined(_WCTYPE_H) +#error Always include <{w}ctype.h> rather than +#endif + +#ifndef _BITS_CTYPE_H +#define _BITS_CTYPE_H + +#ifdef __UCLIBC_GEN_LOCALE + +/* Taking advantage of the C99 mutual-exclusion guarantees for the various + * (w)ctype classes, including the descriptions of printing and control + * (w)chars, we can place each in one of the following mutually-exlusive + * subsets. Since there are less than 16, we can store the data for + * each (w)chars in a nibble. In contrast, glibc uses an unsigned int + * per (w)char, with one bit flag for each is* type. While this allows + * a simple '&' operation to determine the type vs. a range test and a + * little special handling for the "blank" and "xdigit" types in my + * approach, it also uses 8 times the space for the tables on the typical + * 32-bit archs we supported.*/ +enum { + __CTYPE_unclassified = 0, + __CTYPE_alpha_nonupper_nonlower, + __CTYPE_alpha_lower, + __CTYPE_alpha_upper_lower, + __CTYPE_alpha_upper, + __CTYPE_digit, + __CTYPE_punct, + __CTYPE_graph, + __CTYPE_print_space_nonblank, + __CTYPE_print_space_blank, + __CTYPE_space_nonblank_noncntrl, + __CTYPE_space_blank_noncntrl, + __CTYPE_cntrl_space_nonblank, + __CTYPE_cntrl_space_blank, + __CTYPE_cntrl_nonspace +}; + +/* Some macros that test for various (w)ctype classes when passed one of the + * designator values enumerated above. */ +#define __CTYPE_isalnum(D) ((unsigned int)(D-1) <= (__CTYPE_digit-1)) +#define __CTYPE_isalpha(D) ((unsigned int)(D-1) <= (__CTYPE_alpha_upper-1)) +#define __CTYPE_isblank(D) \ + ((((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5) && (D & 1)) +#define __CTYPE_iscntrl(D) (((unsigned int)(D - __CTYPE_cntrl_space_nonblank)) <= 2) +#define __CTYPE_isdigit(D) (D == __CTYPE_digit) +#define __CTYPE_isgraph(D) ((unsigned int)(D-1) <= (__CTYPE_graph-1)) +#define __CTYPE_islower(D) (((unsigned int)(D - __CTYPE_alpha_lower)) <= 1) +#define __CTYPE_isprint(D) ((unsigned int)(D-1) <= (__CTYPE_print_space_blank-1)) +#define __CTYPE_ispunct(D) (D == __CTYPE_punct) +#define __CTYPE_isspace(D) (((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5) +#define __CTYPE_isupper(D) (((unsigned int)(D - __CTYPE_alpha_upper_lower)) <= 1) +/* #define __CTYPE_isxdigit(D) -- isxdigit is untestable this way. + * But that's ok as isxdigit() (and isdigit() too) are locale-invariant. */ + +#else /* __UCLIBC_GEN_LOCALE *****************************************/ + +/* Define some ctype macros valid for the C/POSIX locale. */ + +/* ASCII ords of \t, \f, \n, \r, and \v are 9, 12, 10, 13, 11 respectively. */ +#define __C_isspace(c) \ + ((sizeof(c) == sizeof(char)) \ + ? ((((c) == ' ') || (((unsigned char)((c) - 9)) <= (13 - 9)))) \ + : ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))) +#define __C_isblank(c) (((c) == ' ') || ((c) == '\t')) +#define __C_isdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((unsigned int)((c) - '0')) < 10)) +#define __C_isxdigit(c) \ + (__C_isdigit(c) \ + || ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \ + : (((unsigned int)((((c)) | 0x20) - 'a')) < 6))) +#define __C_iscntrl(c) \ + ((sizeof(c) == sizeof(char)) \ + ? ((((unsigned char)(c)) < 0x20) || ((c) == 0x7f)) \ + : ((((unsigned int)(c)) < 0x20) || ((c) == 0x7f))) +#define __C_isalpha(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \ + : (((unsigned int)(((c) | 0x20) - 'a')) < 26)) +#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c)) +#define __C_isprint(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 0x20)) <= (0x7e - 0x20)) \ + : (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))) +#define __C_islower(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 'a')) < 26) \ + : (((unsigned int)((c) - 'a')) < 26)) +#define __C_isupper(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 'A')) < 26) \ + : (((unsigned int)((c) - 'A')) < 26)) +#define __C_ispunct(c) \ + ((!__C_isalnum(c)) \ + && ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 0x21)) <= (0x7e - 0x21)) \ + : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21)))) +#define __C_isgraph(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21)) \ + : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21))) + +#define __C_tolower(c) (__C_isupper(c) ? ((c) | 0x20) : (c)) +#define __C_toupper(c) (__C_islower(c) ? ((c) ^ 0x20) : (c)) + +/**********************************************************************/ +__BEGIN_DECLS + +extern int isalnum(int c) __THROW; +extern int isalpha(int c) __THROW; +#ifdef __USE_ISOC99 +extern int isblank(int c) __THROW; +#endif +extern int iscntrl(int c) __THROW; +extern int isdigit(int c) __THROW; +extern int isgraph(int c) __THROW; +extern int islower(int c) __THROW; +extern int isprint(int c) __THROW; +extern int ispunct(int c) __THROW; +extern int isspace(int c) __THROW; +extern int isupper(int c) __THROW; +extern int isxdigit(int c) __THROW; + +extern int tolower(int c) __THROW; +extern int toupper(int c) __THROW; + +#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN +extern int isascii(int c) __THROW; +extern int toascii(int c) __THROW; +#endif + +#if defined _LIBC && (defined NOT_IN_libc || defined IS_IN_libc) +/* isdigit() is really locale-invariant, so provide some small fast macros. + * These are uClibc-specific. */ +#define __isdigit_char(C) (((unsigned char)((C) - '0')) <= 9) +#define __isdigit_int(C) (((unsigned int)((C) - '0')) <= 9) +#endif + +/* Next, some ctype macros which are valid for all supported locales. */ +/* WARNING: isspace and isblank need to be reverified if more 8-bit codesets + * are added!!! But isdigit and isxdigit are always valid. */ + +/* #define __isspace(c) __C_isspace(c) */ +/* #define __isblank(c) __C_isblank(c) */ + +/* #define __isdigit(c) __C_isdigit(c) */ +/* #define __isxdigit(c) __C_isxdigit(c) */ + +/* Now some non-ansi/iso c99 macros. */ + +#define __isascii(c) (((c) & ~0x7f) == 0) +#define __toascii(c) ((c) & 0x7f) +#define _toupper(c) ((c) ^ 0x20) +#define _tolower(c) ((c) | 0x20) + +__END_DECLS + +/**********************************************************************/ +#ifdef __GNUC__ + +#define __isbody_C_macro(f,args) __C_ ## f args + +#define __isbody(f,c) \ + (__extension__ ({ \ + int __res; \ + if (sizeof(c) > sizeof(char)) { \ + int __c = (c); \ + __res = __isbody_C_macro(f,(__c)); \ + } else { \ + unsigned char __c = (c); \ + __res = __isbody_C_macro(f,(__c)); \ + } \ + __res; \ + })) + +#define __body_C_macro(f,args) __C_ ## f args + +#define __body(f,c) \ + (__extension__ ({ \ + int __res; \ + if (sizeof(c) > sizeof(char)) { \ + int __c = (c); \ + __res = __body_C_macro(f,(__c)); \ + } else { \ + unsigned char __c = (c); \ + __res = __body_C_macro(f,(__c)); \ + } \ + __res; \ + })) + +#define __isspace(c) __body(isspace,c) +#define __isblank(c) __body(isblank,c) +#define __isdigit(c) __body(isdigit,c) +#define __isxdigit(c) __body(isxdigit,c) +#define __iscntrl(c) __body(iscntrl,c) +#define __isalpha(c) __body(isalpha,c) +#define __isalnum(c) __body(isalnum,c) +#define __isprint(c) __body(isprint,c) +#define __islower(c) __body(islower,c) +#define __isupper(c) __body(isupper,c) +#define __ispunct(c) __body(ispunct,c) +#define __isgraph(c) __body(isgraph,c) + +#define __tolower(c) __body(tolower,c) +#define __toupper(c) __body(toupper,c) + +#if !defined __NO_CTYPE && !defined __cplusplus + +#define isspace(c) __isspace(c) +#define isblank(c) __isblank(c) +#define isdigit(c) __isdigit(c) +#define isxdigit(c) __isxdigit(c) +#define iscntrl(c) __iscntrl(c) +#define isalpha(c) __isalpha(c) +#define isalnum(c) __isalnum(c) +#define isprint(c) __isprint(c) +#define islower(c) __islower(c) +#define isupper(c) __isupper(c) +#define ispunct(c) __ispunct(c) +#define isgraph(c) __isgraph(c) + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + + +#endif + +#else /* _GNUC__ ***************************************************/ + +#if !defined __NO_CTYPE && !defined __cplusplus + +/* These macros should be safe from side effects. */ + +#define isdigit(c) __C_isdigit(c) +#define isalpha(c) __C_isalpha(c) +#define isprint(c) __C_isprint(c) +#define islower(c) __C_islower(c) +#define isupper(c) __C_isupper(c) +#define isgraph(c) __C_isgraph(c) + +#endif + +#endif /* __GNUC__ */ +/**********************************************************************/ + +#endif /* __UCLIBC_GEN_LOCALE */ + +#endif /* _BITS_CTYPE_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_errno.h b/libc/sysdeps/linux/common/bits/uClibc_errno.h new file mode 100644 index 0000000..9c15618 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_errno.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#ifndef _BITS_UCLIBC_ERRNO_H +#define _BITS_UCLIBC_ERRNO_H 1 + +#ifdef IS_IN_rtld +# undef errno +# define errno _dl_errno +extern int _dl_errno; /* attribute_hidden; */ +#elif defined __UCLIBC_HAS_THREADS__ +# include +# if defined USE___THREAD && USE___THREAD +# undef errno +# ifndef NOT_IN_libc +# define errno __libc_errno +# else +# define errno errno +# endif +extern __thread int errno attribute_tls_model_ie; +# endif /* USE___THREAD */ +#endif /* IS_IN_rtld */ + +#define __set_errno(val) (errno = (val)) + +#ifndef __ASSEMBLER__ +extern int *__errno_location (void) __THROW __attribute__ ((__const__)) +# ifdef IS_IN_rtld + attribute_hidden +# endif +; +# if defined __UCLIBC_HAS_THREADS__ +# include +# if defined USE___THREAD && USE___THREAD +libc_hidden_proto(__errno_location) +# endif +# endif + +#endif /* !__ASSEMBLER__ */ + +#endif diff --git a/libc/sysdeps/linux/common/bits/uClibc_fpmax.h b/libc/sysdeps/linux/common/bits/uClibc_fpmax.h new file mode 100644 index 0000000..e1721bf --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_fpmax.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Define a maximal floating point type, and the associated constants + * that are defined for the floating point types in float.h. + * + * This is to support archs that are missing long double, or even double. + */ + +#ifndef _UCLIBC_FPMAX_H +#define _UCLIBC_FPMAX_H + +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE 1 +#endif + +#include +#include + +#ifdef __UCLIBC_HAS_FLOATS__ + +#if defined(LDBL_MANT_DIG) + +typedef long double __fpmax_t; +#define FPMAX_TYPE 3 + +#define FPMAX_MANT_DIG LDBL_MANT_DIG +#define FPMAX_DIG LDBL_DIG +#define FPMAX_EPSILON LDBL_EPSILON +#define FPMAX_MIN_EXP LDBL_MIN_EXP +#define FPMAX_MIN LDBL_MIN +#define FPMAX_MIN_10_EXP LDBL_MIN_10_EXP +#define FPMAX_MAX_EXP LDBL_MAX_EXP +#define FPMAX_MAX LDBL_MAX +#define FPMAX_MAX_10_EXP LDBL_MAX_10_EXP + +#elif defined(DBL_MANT_DIG) + +typedef double __fpmax_t; +#define FPMAX_TYPE 2 + +#define FPMAX_MANT_DIG DBL_MANT_DIG +#define FPMAX_DIG DBL_DIG +#define FPMAX_EPSILON DBL_EPSILON +#define FPMAX_MIN_EXP DBL_MIN_EXP +#define FPMAX_MIN DBL_MIN +#define FPMAX_MIN_10_EXP DBL_MIN_10_EXP +#define FPMAX_MAX_EXP DBL_MAX_EXP +#define FPMAX_MAX DBL_MAX +#define FPMAX_MAX_10_EXP DBL_MAX_10_EXP + +#elif defined(FLT_MANT_DIG) + +typedef float __fpmax_t; +#define FPMAX_TYPE 1 + +#define FPMAX_MANT_DIG FLT_MANT_DIG +#define FPMAX_DIG FLT_DIG +#define FPMAX_EPSILON FLT_EPSILON +#define FPMAX_MIN_EXP FLT_MIN_EXP +#define FPMAX_MIN FLT_MIN +#define FPMAX_MIN_10_EXP FLT_MIN_10_EXP +#define FPMAX_MAX_EXP FLT_MAX_EXP +#define FPMAX_MAX FLT_MAX +#define FPMAX_MAX_10_EXP FLT_MAX_10_EXP + +#else +#error unable to determine appropriate type for __fpmax_t! +#endif + +#ifndef DECIMAL_DIG + +#ifdef L___strtofpmax +/* Emit warning only once. */ +#warning DECIMAL_DIG is not defined! If you are using gcc, it may not be defining __STDC_VERSION__ as it should. +#endif +#if !defined(FLT_RADIX) || (FLT_RADIX != 2) +#error unable to compensate for missing DECIMAL_DIG! +#endif + +/* ceil (1 + #mantissa * log10 (FLT_RADIX)) */ +#define DECIMAL_DIG (1 + (((FPMAX_MANT_DIG * 100) + 331) / 332)) + +#endif /* DECIMAL_DIG */ + +#if defined _LIBC && defined IS_IN_libc +extern __fpmax_t __strtofpmax(const char *str, char **endptr, int exp_adjust) attribute_hidden; + +#ifdef __UCLIBC_HAS_XLOCALE__ +extern __fpmax_t __strtofpmax_l(const char *str, char **endptr, int exp_adjust, + __locale_t locale_arg) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern __fpmax_t __wcstofpmax(const wchar_t *wcs, wchar_t **endptr, + int exp_adjust) attribute_hidden; + +#ifdef __UCLIBC_HAS_XLOCALE__ +extern __fpmax_t __wcstofpmax_l(const wchar_t *wcs, wchar_t **endptr, + int exp_adjust, __locale_t locale_arg) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* _LIBC */ + +/* The following checks in an __fpmax_t is either 0 or +/- infinity. + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * This only works if __fpmax_t is the actual maximal floating point type used + * in intermediate calculations. Otherwise, excess precision in the + * intermediate values can cause the test to fail. + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + */ + +#define __FPMAX_ZERO_OR_INF_CHECK(x) ((x) == ((x)/4) ) + +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#endif /* _UCLIBC_FPMAX_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_local_lim.h b/libc/sysdeps/linux/common/bits/uClibc_local_lim.h new file mode 100644 index 0000000..6c23f39 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_local_lim.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_UCLIBC_LOCAL_LIM_H +#define _BITS_UCLIBC_LOCAL_LIM_H 1 + +/* This file works correctly only if local_lim.h is the NPTL version */ +#if !defined PTHREAD_KEYS_MAX || defined TIMER_MAX +# error local_lim.h was incorrectly updated, use the NPTL version from glibc +#endif + +/* This should really be moved to thread specific directories */ +#if defined __UCLIBC_HAS_THREADS__ +# define PTHREAD_THREADS_MAX 1024 +# define TIMER_MAX 256 +#endif + +#ifndef __UCLIBC_HAS_THREADS__ +# undef _POSIX_THREAD_KEYS_MAX +# undef PTHREAD_KEYS_MAX +# undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +# undef PTHREAD_DESTRUCTOR_ITERATIONS +# undef PTHREAD_STACK_MIN +# undef DELAYTIMER_MAX +#endif + +#endif /* bits/uClibc_local_lim.h */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_locale.h b/libc/sysdeps/linux/common/bits/uClibc_locale.h new file mode 100644 index 0000000..a6b381c --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_locale.h @@ -0,0 +1,380 @@ +/* Copyright (C) 2002, 2003 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UCLIBC_LOCALE_H +#define _UCLIBC_LOCALE_H + +/**********************************************************************/ +/* uClibc compatibilty stuff */ + +#ifdef __UCLIBC_HAS_LOCALE__ + +#undef __LOCALE_C_ONLY + +#else /* __UCLIBC_HAS_LOCALE__ */ + +#define __LOCALE_C_ONLY + +#define __XL_NPP(N) N +#define __LOCALE_PARAM +#define __LOCALE_ARG + +#endif /* __UCLIBC_HAS_LOCALE__ */ + +/**********************************************************************/ + +#define __NL_ITEM_CATEGORY_SHIFT (8) +#define __NL_ITEM_INDEX_MASK (0xff) + +/* TODO: Make sure these agree with the locale mmap file gererator! */ + +#define __LC_CTYPE 0 +#define __LC_NUMERIC 1 +#define __LC_MONETARY 2 +#define __LC_TIME 3 +#define __LC_COLLATE 4 +#define __LC_MESSAGES 5 +#define __LC_ALL 6 + +/**********************************************************************/ +#ifndef __LOCALE_C_ONLY + +#if defined _LIBC /* && (defined IS_IN_libc || defined NOT_IN_libc) */ +#include +#include +#include + +#ifndef __UCLIBC_GEN_LOCALE +#include +#endif +#endif + +/* extern void _locale_set(const unsigned char *p); */ +/* extern void _locale_init(void); */ + +enum { + __ctype_encoding_7_bit, /* C/POSIX */ + __ctype_encoding_utf8, /* UTF-8 */ + __ctype_encoding_8_bit /* for 8-bit codeset locales */ +}; + +#define LOCALE_STRING_SIZE (2 * __LC_ALL + 2) + + /* + * '#' + 2_per_category + '\0' + * {locale row # : 0 = C|POSIX} + 0x8001 + * encoded in two chars as (((N+1) >> 8) | 0x80) and ((N+1) & 0xff) + * so decode is ((((uint16_t)(*s & 0x7f)) << 8) + s[1]) - 1 + * + * Note: 0s are not used as they are nul-terminators for strings. + * Note: 0xff, 0xff is the encoding for a non-selected locale. + * (see setlocale() below). + * In particular, C/POSIX locale is '#' + "\x80\x01"}*LC_ALL + nul. + */ + +#if defined _LIBC && !defined __UCLIBC_GEN_LOCALE /* && (defined IS_IN_libc || defined NOT_IN_libc) */ +typedef struct { + uint16_t num_weights; + uint16_t num_starters; + uint16_t ii_shift; + uint16_t ti_shift; + uint16_t ii_len; + uint16_t ti_len; + uint16_t max_weight; + uint16_t num_col_base; + uint16_t max_col_index; + uint16_t undefined_idx; + uint16_t range_low; + uint16_t range_count; + uint16_t range_base_weight; + uint16_t range_rule_offset; /* change name to index? */ + + uint16_t ii_mask; + uint16_t ti_mask; + + const uint16_t *index2weight_tbl; + const uint16_t *index2ruleidx_tbl; + const uint16_t *multistart_tbl; + /* uint16_t wcs2colidt_offset_low; */ + /* uint16_t wcs2colidt_offset_hi; */ + const uint16_t *wcs2colidt_tbl; + + /* uint16_t undefined_idx; */ + const uint16_t *overrides_tbl; + /* uint16_t *multistart_tbl; */ + + const uint16_t *weightstr; + const uint16_t *ruletable; + + + uint16_t *index2weight; + uint16_t *index2ruleidx; + + uint16_t MAX_WEIGHTS; +} __collate_t; + + +/* static unsigned char cur_locale[LOCALE_STRING_SIZE]; */ + +typedef struct __uclibc_locale_struct { +#ifdef __UCLIBC_HAS_XLOCALE__ + const __ctype_mask_t *__ctype_b; + const __ctype_touplow_t *__ctype_tolower; + const __ctype_touplow_t *__ctype_toupper; +#endif + + /* For now, just embed this in the structure. */ + __ctype_mask_t __ctype_b_data[256 + __UCLIBC_CTYPE_B_TBL_OFFSET]; + __ctype_touplow_t __ctype_tolower_data[256 + __UCLIBC_CTYPE_TO_TBL_OFFSET]; + __ctype_touplow_t __ctype_toupper_data[256 + __UCLIBC_CTYPE_TO_TBL_OFFSET]; + +/* int tables_loaded; */ +/* unsigned char lctypes[LOCALE_STRING_SIZE]; */ + unsigned char cur_locale[LOCALE_STRING_SIZE]; + + /* NL_LANGINFO stuff. BEWARE ORDERING!!! must agree with NL_* constants! */ + /* Also, numeric must be followed by monetary and the items must be in + * the "struct lconv" order. */ + + uint16_t category_offsets[__LC_ALL]; /* TODO -- fix? */ + unsigned char category_item_count[__LC_ALL]; /* TODO - fix */ + + /* ctype */ + unsigned char encoding; /* C/POSIX, 8-bit, UTF-8 */ + unsigned char mb_cur_max; /* determined by encoding _AND_ translit!!! */ + const unsigned char outdigit_length[10]; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const unsigned char *idx8ctype; + const unsigned char *tbl8ctype; + const unsigned char *idx8uplow; + const unsigned char *tbl8uplow; +#ifdef __UCLIBC_HAS_WCHAR__ + const unsigned char *idx8c2wc; + const uint16_t *tbl8c2wc; /* char > 0x7f to wide char */ + const unsigned char *idx8wc2c; + const unsigned char *tbl8wc2c; + /* translit */ +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __UCLIBC_HAS_WCHAR__ + + const uint16_t *code2flag; + + const unsigned char *tblwctype; + const unsigned char *tblwuplow; +/* const unsigned char *tblwcomb; */ + const int16_t *tblwuplow_diff; /* yes... signed */ + /* width?? */ + + wchar_t decimal_point_wc; + wchar_t thousands_sep_wc; + int decimal_point_len; + int thousands_sep_len; + +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* ctype */ + const char *outdigit0_mb; + const char *outdigit1_mb; + const char *outdigit2_mb; + const char *outdigit3_mb; + const char *outdigit4_mb; + const char *outdigit5_mb; + const char *outdigit6_mb; + const char *outdigit7_mb; + const char *outdigit8_mb; + const char *outdigit9_mb; + const char *codeset; /* MUST BE LAST!!! */ + + /* numeric */ + const char *decimal_point; + const char *thousands_sep; + const char *grouping; + + /* monetary */ + const char *int_curr_symbol; + const char *currency_symbol; + const char *mon_decimal_point; + const char *mon_thousands_sep; + const char *mon_grouping; + const char *positive_sign; + const char *negative_sign; + const char *int_frac_digits; + const char *frac_digits; + const char *p_cs_precedes; + const char *p_sep_by_space; + const char *n_cs_precedes; + const char *n_sep_by_space; + const char *p_sign_posn; + const char *n_sign_posn; + const char *int_p_cs_precedes; + const char *int_p_sep_by_space; + const char *int_n_cs_precedes; + const char *int_n_sep_by_space; + const char *int_p_sign_posn; + const char *int_n_sign_posn; + + const char *crncystr; /* not returned by localeconv */ + + /* time */ + const char *abday_1; + const char *abday_2; + const char *abday_3; + const char *abday_4; + const char *abday_5; + const char *abday_6; + const char *abday_7; + + const char *day_1; + const char *day_2; + const char *day_3; + const char *day_4; + const char *day_5; + const char *day_6; + const char *day_7; + + const char *abmon_1; + const char *abmon_2; + const char *abmon_3; + const char *abmon_4; + const char *abmon_5; + const char *abmon_6; + const char *abmon_7; + const char *abmon_8; + const char *abmon_9; + const char *abmon_10; + const char *abmon_11; + const char *abmon_12; + + const char *mon_1; + const char *mon_2; + const char *mon_3; + const char *mon_4; + const char *mon_5; + const char *mon_6; + const char *mon_7; + const char *mon_8; + const char *mon_9; + const char *mon_10; + const char *mon_11; + const char *mon_12; + + const char *am_str; + const char *pm_str; + + const char *d_t_fmt; + const char *d_fmt; + const char *t_fmt; + const char *t_fmt_ampm; + const char *era; + + const char *era_year; /* non SUSv3 */ + const char *era_d_fmt; + const char *alt_digits; + const char *era_d_t_fmt; + const char *era_t_fmt; + + /* collate is at the end */ + + /* messages */ + const char *yesexpr; + const char *noexpr; + const char *yesstr; + const char *nostr; + + /* collate is at the end */ + __collate_t collate; + +} __uclibc_locale_t; + +extern __uclibc_locale_t __global_locale_data; +extern struct __uclibc_locale_struct * __global_locale; +#endif /* _LIBC */ + +typedef struct __uclibc_locale_struct *__locale_t; + +/* if we need to leave only _LIBC, then attribute_hidden is not usable */ +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) +extern int __locale_mbrtowc_l(wchar_t *__restrict dst, + const char *__restrict src, + __locale_t loc ) attribute_hidden; +#endif + +#ifdef L_setlocale +/* so we only get the warning once... */ +#warning need thread version of CUR_LOCALE! +#endif +/**********************************************************************/ +#ifdef __UCLIBC_HAS_XLOCALE__ + +extern __locale_t __curlocale_var; + +#ifdef __UCLIBC_HAS_THREADS__ + +extern __locale_t __curlocale(void) __THROW __attribute__ ((__const__)); +extern __locale_t __curlocale_set(__locale_t newloc); +#define __UCLIBC_CURLOCALE (__curlocale()) +#define __UCLIBC_CURLOCALE_DATA (*__curlocale()) + +#else /* __UCLIBC_HAS_THREADS__ */ + +#define __UCLIBC_CURLOCALE (__curlocale_var) +#define __UCLIBC_CURLOCALE_DATA (*__curlocale_var) + +#endif /* __UCLIBC_HAS_THREADS__ */ + +#elif defined(__UCLIBC_HAS_LOCALE__) + +#define __UCLIBC_CURLOCALE (__global_locale) +#define __UCLIBC_CURLOCALE_DATA (*__global_locale) + +#endif +/**********************************************************************/ +#if defined(__UCLIBC_HAS_XLOCALE__) && defined(__UCLIBC_DO_XLOCALE) + +#define __XL_NPP(N) N ## _l +#define __LOCALE_PARAM , __locale_t locale_arg +#define __LOCALE_ARG , locale_arg +#define __LOCALE_PTR locale_arg + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && defined(__UCLIBC_DO_XLOCALE) */ + +#define __XL_NPP(N) N +#define __LOCALE_PARAM +#define __LOCALE_ARG +#define __LOCALE_PTR __UCLIBC_CURLOCALE + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && defined(__UCLIBC_DO_XLOCALE) */ +/**********************************************************************/ + +#endif /* !defined(__LOCALE_C_ONLY) */ +/**********************************************************************/ + +#endif /* _UCLIBC_LOCALE_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_mutex.h b/libc/sysdeps/linux/common/bits/uClibc_mutex.h new file mode 100644 index 0000000..14aeb9c --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_mutex.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2006 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#ifndef _UCLIBC_MUTEX_H +#define _UCLIBC_MUTEX_H + +#include + +#ifdef __UCLIBC_HAS_THREADS__ + +#include +#include + +#define __UCLIBC_MUTEX_TYPE pthread_mutex_t + +#define __UCLIBC_MUTEX(M) pthread_mutex_t M +#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I +#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I +#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M + +#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_lock(&(M)) + +#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_unlock(&(M)) + +#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_trylock(&(M)) + +#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \ + do { \ + struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \ + if (C) { \ + _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \ + (void (*) (void *))__pthread_mutex_unlock, \ + &(M)); \ + __pthread_mutex_lock(&(M)); \ + } \ + ((void)0) + +#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \ + if (C) { \ + _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1); \ + } \ + } while (0) + +#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A + +#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \ + __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0)) + +#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \ + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0)) + +#define __UCLIBC_MUTEX_LOCK(M) \ + __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) + +#define __UCLIBC_MUTEX_UNLOCK(M) \ + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) + +#else + +#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_STATIC(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M + +#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0) +#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0) +#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */ + +#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0) +#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0) + +#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0) +#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0) +#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0) + +#define __UCLIBC_MUTEX_LOCK(M) ((void)0) +#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0) + +#endif + +#endif /* _UCLIBC_MUTEX_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_page.h b/libc/sysdeps/linux/common/bits/uClibc_page.h new file mode 100644 index 0000000..1340945 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_page.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Erik Andersen + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_pthread.h b/libc/sysdeps/linux/common/bits/uClibc_pthread.h new file mode 100644 index 0000000..1d6209f --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_pthread.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply prototypes for the internal thread functions used by the + * uClibc library code. + */ + +#ifndef _UCLIBC_PTHREAD_H +#define _UCLIBC_PTHREAD_H + +#ifndef _PTHREAD_H +# error "Always include rather than " +#endif + +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) +/* Threading functions internal to uClibc. Make these thread functions + * weak so that we can elide them from single-threaded processes. */ +extern int weak_function __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int weak_function __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int weak_function __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int weak_function __pthread_mutex_unlock (pthread_mutex_t *__mutex); +extern void __uclibc_mutex_unlock (void *) attribute_hidden; +extern int weak_function __pthread_mutex_trylock (pthread_mutex_t *__mutex); +# ifndef __UCLIBC_HAS_THREADS_NATIVE__ +extern void weak_function _pthread_cleanup_push_defer ( + struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), void *__arg); +extern void weak_function _pthread_cleanup_pop_restore ( + struct _pthread_cleanup_buffer *__buffer, + int __execute); +# endif +#endif + +#endif diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h new file mode 100644 index 0000000..843a2f2 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h @@ -0,0 +1,517 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#ifndef _STDIO_H +#error Always include rather than +#endif + +/**********************************************************************/ + +#define __STDIO_BUFFERS +/* ANSI/ISO mandate at least 256. */ +#if defined(__UCLIBC_HAS_STDIO_BUFSIZ_NONE__) +/* Fake this because some apps use stdio.h BUFSIZ. */ +#define __STDIO_BUFSIZ 256 +#undef __STDIO_BUFFERS +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_256__) +#define __STDIO_BUFSIZ 256 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_512__) +#define __STDIO_BUFSIZ 512 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_1024__) +#define __STDIO_BUFSIZ 1024 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_2048__) +#define __STDIO_BUFSIZ 2048 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_4096__) +#define __STDIO_BUFSIZ 4096 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_8192__) +#define __STDIO_BUFSIZ 8192 +#else +#error config seems to be out of sync regarding bufsiz options +#endif + +#ifdef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __STDIO_BUILTIN_BUF_SIZE 0 +#else /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */ +#if defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__) +#define __STDIO_BUILTIN_BUF_SIZE 0 +#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__) +#define __STDIO_BUILTIN_BUF_SIZE 4 +#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__) +#define __STDIO_BUILTIN_BUF_SIZE 8 +#else +#error config seems to be out of sync regarding builtin buffer size +#endif +#endif + +#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) || defined(__UCLIBC_HAS_THREADS__) +#define __STDIO_HAS_OPENLIST 1 +#else +#undef __STDIO_HAS_OPENLIST +#endif + +/**********************************************************************/ +/* Make sure defines related to large files are consistent. */ +#ifdef _LIBC + +#ifdef __UCLIBC_HAS_LFS__ +#undef __USE_LARGEFILE +#undef __USE_LARGEFILE64 +#undef __USE_FILE_OFFSET64 +/* If we're actually building uClibc with large file support, only define... */ +#define __USE_LARGEFILE64 1 +#endif /* __UCLIBC_HAS_LFS__ */ + +#else /* not _LIBC */ + +#ifndef __UCLIBC_HAS_LFS__ +#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) || defined(__USE_FILE_OFFSET64) +#error Sorry... uClibc was built without large file support! +#endif +#endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* _LIBC */ +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __need_wchar_t +#include + +/* Note: we don't really need mbstate for 8-bit locales. We do for UTF-8. + * For now, always use it. */ +#define __STDIO_MBSTATE +#define __need_mbstate_t +#include + +#endif +/**********************************************************************/ +/* Currently unimplemented/untested */ +/* #define __STDIO_FLEXIBLE_SETVBUF */ + +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ +#define __STDIO_GETC_MACRO +#endif + +#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ +#define __STDIO_PUTC_MACRO +#endif + + +/* These are consistency checks on the different options */ + +#ifndef __STDIO_BUFFERS +#undef __STDIO_GETC_MACRO +#undef __STDIO_PUTC_MACRO +#endif + +#ifdef __BCC__ +#undef __UCLIBC_HAS_LFS__ +#endif + +#ifndef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#endif + +/**********************************************************************/ +#include + +/* user_locking + * 0 : do auto locking/unlocking + * 1 : user does locking/unlocking + * 2 : initial state prior to thread initialization + * with no auto locking/unlocking + * + * When threading is initialized, walk the stdio open stream list + * and do "if (user_locking == 2) user_locking = 0;". + * + * This way, we avoid calling the weak lock/unlock functions. + */ + +#define __STDIO_AUTO_THREADLOCK_VAR \ + __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking) + +#define __STDIO_AUTO_THREADLOCK(__stream) \ + __UCLIBC_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \ + (__stream)->__user_locking) + +#define __STDIO_AUTO_THREADUNLOCK(__stream) \ + __UCLIBC_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking) + +#define __STDIO_ALWAYS_THREADLOCK(__stream) \ + __UCLIBC_MUTEX_LOCK((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ + __UCLIBC_MUTEX_UNLOCK((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock) + +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) +#else +#define __STDIO_SET_USER_LOCKING(__stream) ((void)0) +#endif + +/**********************************************************************/ + +#define __STDIO_IOFBF 0 /* Fully buffered. */ +#define __STDIO_IOLBF 1 /* Line buffered. */ +#define __STDIO_IONBF 2 /* No buffering. */ + +typedef struct { + __off_t __pos; +#ifdef __STDIO_MBSTATE + __mbstate_t __mbstate; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + int __mblen_pending; +#endif +} __STDIO_fpos_t; + +#ifdef __UCLIBC_HAS_LFS__ +typedef struct { + __off64_t __pos; +#ifdef __STDIO_MBSTATE + __mbstate_t __mbstate; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + int __mblen_pending; +#endif +} __STDIO_fpos64_t; +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_LFS__ +typedef __off64_t __offmax_t; /* TODO -- rename this? */ +#else +typedef __off_t __offmax_t; /* TODO -- rename this? */ +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + +typedef __ssize_t __io_read_fn(void *__cookie, char *__buf, size_t __bufsize); +typedef __ssize_t __io_write_fn(void *__cookie, + __const char *__buf, size_t __bufsize); +/* NOTE: GLIBC difference!!! -- fopencookie seek function + * For glibc, the type of pos is always (__off64_t *) but in our case + * it is type (__off_t *) when the lib is built without large file support. + */ +typedef int __io_seek_fn(void *__cookie, __offmax_t *__pos, int __whence); +typedef int __io_close_fn(void *__cookie); + +typedef struct { + __io_read_fn *read; + __io_write_fn *write; + __io_seek_fn *seek; + __io_close_fn *close; +} _IO_cookie_io_functions_t; + +#if defined(_LIBC) || defined(_GNU_SOURCE) + +typedef __io_read_fn cookie_read_function_t; +typedef __io_write_fn cookie_write_function_t; +typedef __io_seek_fn cookie_seek_function_t; +typedef __io_close_fn cookie_close_function_t; + +typedef _IO_cookie_io_functions_t cookie_io_functions_t; + +#endif + +#endif +/**********************************************************************/ + +struct __STDIO_FILE_STRUCT { + unsigned short __modeflags; + /* There could be a hole here, but modeflags is used most.*/ +#ifdef __UCLIBC_HAS_WCHAR__ + unsigned char __ungot_width[2]; /* 0: current (building) char; 1: scanf */ + /* Move the following futher down to avoid problems with getc/putc + * macros breaking shared apps when wchar config support is changed. */ + /* wchar_t ungot[2]; */ +#else /* __UCLIBC_HAS_WCHAR__ */ + unsigned char __ungot[2]; +#endif /* __UCLIBC_HAS_WCHAR__ */ + int __filedes; +#ifdef __STDIO_BUFFERS + unsigned char *__bufstart; /* pointer to buffer */ + unsigned char *__bufend; /* pointer to 1 past end of buffer */ + unsigned char *__bufpos; + unsigned char *__bufread; /* pointer to 1 past last buffered read char */ + +#ifdef __STDIO_GETC_MACRO + unsigned char *__bufgetc_u; /* 1 past last readable by getc_unlocked */ +#endif /* __STDIO_GETC_MACRO */ +#ifdef __STDIO_PUTC_MACRO + unsigned char *__bufputc_u; /* 1 past last writeable by putc_unlocked */ +#endif /* __STDIO_PUTC_MACRO */ + +#endif /* __STDIO_BUFFERS */ + +#ifdef __STDIO_HAS_OPENLIST + struct __STDIO_FILE_STRUCT *__nextopen; +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + void *__cookie; + _IO_cookie_io_functions_t __gcs; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t __ungot[2]; +#endif +#ifdef __STDIO_MBSTATE + __mbstate_t __state; +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ + void *__unused; /* Placeholder for codeset binding. */ +#endif +#ifdef __UCLIBC_HAS_THREADS__ + int __user_locking; + __UCLIBC_MUTEX(__lock); +#endif +/* Everything after this is unimplemented... and may be trashed. */ +#if __STDIO_BUILTIN_BUF_SIZE > 0 + unsigned char __builtinbuf[__STDIO_BUILTIN_BUF_SIZE]; +#endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */ +}; + + +/***********************************************************************/ +/* Having ungotten characters implies the stream is reading. + * The scheme used here treats the least significant 2 bits of + * the stream's modeflags member as follows: + * 0 0 Not currently reading. + * 0 1 Reading, but no ungetc() or scanf() push back chars. + * 1 0 Reading with one ungetc() char (ungot[1] is 1) + * or one scanf() pushed back char (ungot[1] is 0). + * 1 1 Reading with both an ungetc() char and a scanf() + * pushed back char. Note that this must be the result + * of a scanf() push back (in ungot[0]) _followed_ by + * an ungetc() call (in ungot[1]). + * + * Notes: + * scanf() can NOT use ungetc() to push back characters. + * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.) + */ + +#define __MASK_READING 0x0003U /* (0x0001 | 0x0002) */ +#define __FLAG_READING 0x0001U +#define __FLAG_UNGOT 0x0002U +#define __FLAG_EOF 0x0004U +#define __FLAG_ERROR 0x0008U +#define __FLAG_WRITEONLY 0x0010U +#define __FLAG_READONLY 0x0020U /* (__FLAG_WRITEONLY << 1) */ +#define __FLAG_WRITING 0x0040U +#define __FLAG_NARROW 0x0080U + +#define __FLAG_FBF 0x0000U /* must be 0 */ +#define __FLAG_LBF 0x0100U +#define __FLAG_NBF 0x0200U /* (__FLAG_LBF << 1) */ +#define __MASK_BUFMODE 0x0300U /* (__FLAG_LBF|__FLAG_NBF) */ +#define __FLAG_APPEND 0x0400U /* fixed! == O_APPEND for linux */ +#define __FLAG_WIDE 0x0800U +/* available slot 0x1000U */ +#define __FLAG_FREEFILE 0x2000U +#define __FLAG_FREEBUF 0x4000U +#define __FLAG_LARGEFILE 0x8000U /* fixed! == 0_LARGEFILE for linux */ +#define __FLAG_FAILED_FREOPEN __FLAG_LARGEFILE + +/* Note: In no-buffer mode, it would be possible to pack the necessary + * flags into one byte. Since we wouldn't be buffering and there would + * be no support for wchar, the only flags we would need would be: + * 2 bits : ungot count + * 2 bits : eof + error + * 2 bits : readonly + writeonly + * 1 bit : freefile + * 1 bit : appending + * So, for a very small system (< 128 files) we might have a + * 4-byte FILE struct of: + * unsigned char flags; + * signed char filedes; + * unsigned char ungot[2]; + */ +/********************************************************************** + * PROTOTYPES OF INTERNAL FUNCTIONS + **********************************************************************/ +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) + +extern void _stdio_init(void) attribute_hidden; +extern void _stdio_term(void) attribute_hidden; + +#ifdef __STDIO_HAS_OPENLIST + +extern struct __STDIO_FILE_STRUCT *_stdio_openlist; + +#ifdef __UCLIBC_HAS_THREADS__ +__UCLIBC_MUTEX_EXTERN(_stdio_openlist_add_lock); +#ifdef __STDIO_BUFFERS +__UCLIBC_MUTEX_EXTERN(_stdio_openlist_del_lock); +extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */ +extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */ +#endif +extern int _stdio_user_locking; +extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) attribute_hidden; +#endif + +#endif + +#endif +/**********************************************************************/ + +#define __CLEARERR_UNLOCKED(__stream) \ + ((void)((__stream)->__modeflags &= ~(__FLAG_EOF|__FLAG_ERROR))) +#define __FEOF_UNLOCKED(__stream) ((__stream)->__modeflags & __FLAG_EOF) +#define __FERROR_UNLOCKED(__stream) ((__stream)->__modeflags & __FLAG_ERROR) + +#ifdef __UCLIBC_HAS_THREADS__ +# define __CLEARERR(__stream) (clearerr)(__stream) +# define __FERROR(__stream) (ferror)(__stream) +# define __FEOF(__stream) (feof)(__stream) +#else +# define __CLEARERR(__stream) __CLEARERR_UNLOCKED(__stream) +# define __FERROR(__stream) __FERROR_UNLOCKED(__stream) +# define __FEOF(__stream) __FEOF_UNLOCKED(__stream) +#endif + +extern int __fgetc_unlocked(FILE *__stream); +extern int __fputc_unlocked(int __c, FILE *__stream); + +/* First define the default definitions. + They are overridden below as necessary. */ +#define __FGETC_UNLOCKED(__stream) (__fgetc_unlocked)((__stream)) +#define __FGETC(__stream) (fgetc)((__stream)) +#define __GETC_UNLOCKED_MACRO(__stream) (__fgetc_unlocked)((__stream)) +#define __GETC_UNLOCKED(__stream) (__fgetc_unlocked)((__stream)) +#define __GETC(__stream) (fgetc)((__stream)) + +#define __FPUTC_UNLOCKED(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __FPUTC(__c, __stream) (fputc)((__c),(__stream)) +#define __PUTC_UNLOCKED_MACRO(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __PUTC_UNLOCKED(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __PUTC(__c, __stream) (fputc)((__c),(__stream)) + + +#ifdef __STDIO_GETC_MACRO + +extern FILE *__stdin; /* For getchar() macro. */ + +# undef __GETC_UNLOCKED_MACRO +# define __GETC_UNLOCKED_MACRO(__stream) \ + ( ((__stream)->__bufpos < (__stream)->__bufgetc_u) \ + ? (*(__stream)->__bufpos++) \ + : __fgetc_unlocked(__stream) ) + +# if 0 + /* Classic macro approach. getc{_unlocked} can have side effects. */ +# undef __GETC_UNLOCKED +# define __GETC_UNLOCKED(__stream) __GETC_UNLOCKED_MACRO((__stream)) +# ifndef __UCLIBC_HAS_THREADS__ +# undef __GETC +# define __GETC(__stream) __GETC_UNLOCKED_MACRO((__stream)) +# endif + +# else + /* Using gcc extension for safety and additional inlining. */ +# undef __FGETC_UNLOCKED +# define __FGETC_UNLOCKED(__stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + __GETC_UNLOCKED_MACRO(__S); \ + }) ) + +# undef __GETC_UNLOCKED +# define __GETC_UNLOCKED(__stream) __FGETC_UNLOCKED((__stream)) + +# ifdef __UCLIBC_HAS_THREADS__ +# undef __FGETC +# define __FGETC(__stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + ((__S->__user_locking ) \ + ? __GETC_UNLOCKED_MACRO(__S) \ + : (fgetc)(__S)); \ + }) ) + +# undef __GETC +# define __GETC(__stream) __FGETC((__stream)) + +# else + +# undef __FGETC +# define __FGETC(__stream) __FGETC_UNLOCKED((__stream)) +# undef __GETC +# define __GETC(__stream) __FGETC_UNLOCKED((__stream)) + +# endif +# endif + +#else + +#endif /* __STDIO_GETC_MACRO */ + + +#ifdef __STDIO_PUTC_MACRO + +extern FILE *__stdout; /* For putchar() macro. */ + +# undef __PUTC_UNLOCKED_MACRO +# define __PUTC_UNLOCKED_MACRO(__c, __stream) \ + ( ((__stream)->__bufpos < (__stream)->__bufputc_u) \ + ? (*(__stream)->__bufpos++) = (__c) \ + : __fputc_unlocked((__c),(__stream)) ) + +# if 0 + /* Classic macro approach. putc{_unlocked} can have side effects.*/ +# undef __PUTC_UNLOCKED +# define __PUTC_UNLOCKED(__c, __stream) \ + __PUTC_UNLOCKED_MACRO((__c), (__stream)) +# ifndef __UCLIBC_HAS_THREADS__ +# undef __PUTC +# define __PUTC(__c, __stream) __PUTC_UNLOCKED_MACRO((__c), (__stream)) +# endif + +# else + /* Using gcc extension for safety and additional inlining. */ + +# undef __FPUTC_UNLOCKED +# define __FPUTC_UNLOCKED(__c, __stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + __PUTC_UNLOCKED_MACRO((__c),__S); \ + }) ) + +# undef __PUTC_UNLOCKED +# define __PUTC_UNLOCKED(__c, __stream) __FPUTC_UNLOCKED((__c), (__stream)) + +# ifdef __UCLIBC_HAS_THREADS__ +# undef __FPUTC +# define __FPUTC(__c, __stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + ((__S->__user_locking) \ + ? __PUTC_UNLOCKED_MACRO((__c),__S) \ + : (fputc)((__c),__S)); \ + }) ) + +# undef __PUTC +# define __PUTC(__c, __stream) __FPUTC((__c), (__stream)) + +# else + +# undef __FPUTC +# define __FPUTC(__c, __stream) __FPUTC_UNLOCKED((__c),(__stream)) +# undef __PUTC +# define __PUTC(__c, __stream) __FPUTC_UNLOCKED((__c),(__stream)) + +# endif +# endif + +#endif /* __STDIO_PUTC_MACRO */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_touplow.h b/libc/sysdeps/linux/common/bits/uClibc_touplow.h new file mode 100644 index 0000000..28d4e2f --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_touplow.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UCLIBC_TOUPLOW_H +#define _UCLIBC_TOUPLOW_H + +#include +#include + +/* glibc uses the equivalent of - typedef __int32_t __ctype_touplow_t; */ + +typedef __uint16_t __ctype_mask_t; + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + +typedef __int16_t __ctype_touplow_t; +#define __UCLIBC_CTYPE_B_TBL_OFFSET 128 +#define __UCLIBC_CTYPE_TO_TBL_OFFSET 128 + +#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +typedef unsigned char __ctype_touplow_t; +#define __UCLIBC_CTYPE_B_TBL_OFFSET 1 +#define __UCLIBC_CTYPE_TO_TBL_OFFSET 0 + +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +#endif /* _UCLIBC_TOUPLOW_H */ + diff --git a/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h b/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h new file mode 100644 index 0000000..92633ff --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UINTMAXTOSTR_H +#define _UINTMAXTOSTR_H 1 + +#ifdef _FEATURES_H +# ifndef __USE_ISOC99 +# error features was included without defining _ISOC99_SOURCE! +# endif +#else +# ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE +# endif +#endif + +#include +#include +#include + +#if INTMAX_MAX <= 2147483647L +#define __UIM_BUFLEN 12 /* 10 digits + 1 nul + 1 sign */ +#elif INTMAX_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for intmax_t! +#endif + +#ifdef LLONG_MAX /* --------------- */ +#if LLONG_MAX <= 2147483647L +#define __UIM_BUFLEN_LLONG 12 /* 10 digits + 1 nul + 1 sign */ +#elif LLONG_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN_LLONG 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for long long! +#endif +#endif /* ULLONG_MAX ----------------------------- */ + +#if LONG_MAX <= 2147483647L +#define __UIM_BUFLEN_LONG 12 /* 10 digits + 1 nul + 1 sign */ +#elif LONG_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN_LONG 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for long! +#endif + +#if INT_MAX <= 32767 +#define __UIM_BUFLEN_INT 7 /* 10 digits + 1 nul + 1 sign */ +#elif INT_MAX <= 2147483647L +#define __UIM_BUFLEN_INT 12 /* 10 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for int! +#endif + +typedef enum { + __UIM_DECIMAL = 0, + __UIM_GROUP = ',', /* Base 10 locale-dependent grouping. */ + __UIM_LOWER = 'a' - 10, + __UIM_UPPER = 'A' - 10, +} __UIM_CASE; + +/* Convert the int val to a string in base abs(base). val is treated as + * an unsigned ??? int type if base > 0, and signed if base < 0. This + * is an internal function with _no_ error checking done unless assert()s + * are enabled. + * + * Note: bufend is a pointer to the END of the buffer passed. + * Call like this: + * char buf[SIZE], *p; + * p = _xltostr(buf + sizeof(buf) - 1, {unsigned int}, 10, __UIM_DECIMAL) + * p = _xltostr(buf + sizeof(buf) - 1, {int}, -10, __UIM_DECIMAL) + * + * WARNING: If base > 10, case _must_be_ either __UIM_LOWER or __UIM_UPPER + * for lower and upper case alphas respectively. + * WARNING: If val is really a signed type, make sure base is negative! + * Otherwise, you could overflow your buffer. + */ +extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval, + int base, __UIM_CASE alphacase) attribute_hidden; + +/* TODO -- make this either a (possibly inline) function? */ +#ifndef __BCC__ +#define _int10tostr(bufend, intval) \ + _uintmaxtostr((bufend), (intval), -10, __UIM_DECIMAL) +#else /* bcc doesn't do prototypes, we need to explicitly cast */ +#define _int10tostr(bufend, intval) \ + _uintmaxtostr((bufend), (uintmax_t)(intval), -10, __UIM_DECIMAL) +#endif + +#define __BUFLEN_INT10TOSTR __UIM_BUFLEN_INT + +#endif /* _UINTMAXTOSTR_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_uwchar.h b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h new file mode 100644 index 0000000..ba2c42d --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* Define an internal unsigned int type __uwchar_t just large enough + * to hold a wchar_t. + */ + +#ifndef _UCLIBC_UWCHAR_H +#define _UCLIBC_UWCHAR_H + +#include +#include + +#if WCHAR_MIN == 0 +typedef wchar_t __uwchar_t; +#elif WCHAR_MAX <= USHRT_MAX +typedef unsigned short __uwchar_t; +#elif WCHAR_MAX <= UINT_MAX +typedef unsigned int __uwchar_t; +#elif WCHAR_MAX <= ULONG_MAX +typedef unsigned long __uwchar_t; +#elif defined(ULLONG_MAX) && (WCHAR_MAX <= ULLONG_MAX) +typedef unsigned long long __uwchar_t; +#elif WCHAR_MAX <= UINTMAX_MAX +typedef uintmax_t __uwchar_t; +#else +#error Can not determine an appropriate type for __uwchar_t! +#endif + +#endif /* _UCLIBC_UWCHAR_H */ diff --git a/libc/sysdeps/linux/common/bits/uClibc_va_copy.h b/libc/sysdeps/linux/common/bits/uClibc_va_copy.h new file mode 100644 index 0000000..98663fc --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uClibc_va_copy.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2005 Manuel Novoa III + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +#ifndef _UCLIBC_VA_COPY_H +#define _UCLIBC_VA_COPY_H 1 + +#include + +/* Deal with pre-C99 compilers. */ +#ifndef va_copy + +#ifdef __va_copy +#define va_copy(A,B) __va_copy(A,B) +#else +#warning Neither va_copy (C99/SUSv3) or __va_copy is defined. Using a simple copy instead. But you should really check that this is appropriate and supply an arch-specific override if necessary. + /* the glibc manual suggests that this will usually suffice when + __va_copy doesn't exist. */ +#define va_copy(A,B) A = B +#endif + +#endif /* va_copy */ + +#endif /* _UCLIBC_VA_COPY_H */ diff --git a/libc/sysdeps/linux/common/bits/uio.h b/libc/sysdeps/linux/common/bits/uio.h new file mode 100644 index 0000000..6a283ed --- /dev/null +++ b/libc/sysdeps/linux/common/bits/uio.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1996, 1997, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_UIO_H && !defined _FCNTL_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_UIO_H +#define _BITS_UIO_H 1 + +#include + + +/* We should normally use the Linux kernel header file to define this + type and macros but this calls for trouble because of the header + includes other kernel headers. */ + +/* Size of object which can be written atomically. + + This macro has different values in different kernel versions. The + latest versions of the kernel use 1024 and this is good choice. Since + the C library implementation of readv/writev is able to emulate the + functionality even if the currently running kernel does not support + this large value the readv/writev call will not fail because of this. */ +#define UIO_MAXIOV 1024 + + +/* Structure for scatter/gather I/O. */ +struct iovec + { + void *iov_base; /* Pointer to data. */ + size_t iov_len; /* Length of data. */ + }; + +#endif diff --git a/libc/sysdeps/linux/common/bits/ustat.h b/libc/sysdeps/linux/common/bits/ustat.h new file mode 100644 index 0000000..69c6b72 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/ustat.h @@ -0,0 +1,31 @@ +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USTAT_H +# error "Never include directly; use instead." +#endif + +#include + +struct ustat + { + __daddr_t f_tfree; /* Number of free blocks. */ + __ino_t f_tinode; /* Number of free inodes. */ + char f_fname[6]; + char f_fpack[6]; + }; diff --git a/libc/sysdeps/linux/common/bits/utmp.h b/libc/sysdeps/linux/common/bits/utmp.h new file mode 100644 index 0000000..e855ad7 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/utmp.h @@ -0,0 +1,125 @@ +/* The `struct utmp' type, describing entries in the utmp file. GNU version. + Copyright (C) 1993, 1996, 1997, 1998, 1999, 2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMP_H +# error "Never include directly; use instead." +#endif + +#include +#include +#include +#include + + +#define UT_LINESIZE 32 +#define UT_NAMESIZE 32 +#define UT_HOSTSIZE 256 + + +/* The structure describing an entry in the database of + previous logins. */ +struct lastlog + { +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + int32_t ll_time; +#else + __time_t ll_time; +#endif + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; + + +/* The structure describing the status of a terminated process. This + type is used in `struct utmp' below. */ +struct exit_status + { + short int e_termination; /* Process termination status. */ + short int e_exit; /* Process exit status. */ + }; + + +/* The structure describing an entry in the user accounting database. */ +struct utmp +{ + short int ut_type; /* Type of login. */ + pid_t ut_pid; /* Process ID of login process. */ + char ut_line[UT_LINESIZE]; /* Devicename. */ + char ut_id[4]; /* Inittab ID. */ + char ut_user[UT_NAMESIZE]; /* Username. */ + char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ + struct exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ +/* The ut_session and ut_tv fields must be the same size when compiled + 32- and 64-bit. This allows data files and shared memory to be + shared between 32- and 64-bit applications. */ +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + int32_t ut_session; /* Session ID, used for windowing. */ + struct + { + int32_t tv_sec; /* Seconds. */ + int32_t tv_usec; /* Microseconds. */ + } ut_tv; /* Time entry was made. */ +#else + long int ut_session; /* Session ID, used for windowing. */ + struct timeval ut_tv; /* Time entry was made. */ +#endif + + int32_t ut_addr_v6[4]; /* Internet address of remote host. */ + char __unused[20]; /* Reserved for future use. */ +}; + +/* Backwards compatibility hacks. */ +#define ut_name ut_user +#ifndef _NO_UT_TIME +/* We have a problem here: `ut_time' is also used otherwise. Define + _NO_UT_TIME if the compiler complains. */ +# define ut_time ut_tv.tv_sec +#endif +#define ut_xtime ut_tv.tv_sec +#define ut_addr ut_addr_v6[0] + + +/* Values for the `ut_type' field of a `struct utmp'. */ +#define EMPTY 0 /* No valid user accounting information. */ + +#define RUN_LVL 1 /* The system's runlevel. */ +#define BOOT_TIME 2 /* Time of system boot. */ +#define NEW_TIME 3 /* Time after system clock changed. */ +#define OLD_TIME 4 /* Time when system clock changed. */ + +#define INIT_PROCESS 5 /* Process spawned by the init process. */ +#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ +#define USER_PROCESS 7 /* Normal process. */ +#define DEAD_PROCESS 8 /* Terminated process. */ + +#define ACCOUNTING 9 + +/* Old Linux name for the EMPTY type. */ +#define UT_UNKNOWN EMPTY + + +/* Tell the user that we have a modern system with UT_HOST, UT_PID, + UT_TYPE, UT_ID and UT_TV fields. */ +#define _HAVE_UT_TYPE 1 +#define _HAVE_UT_PID 1 +#define _HAVE_UT_ID 1 +#define _HAVE_UT_TV 1 +#define _HAVE_UT_HOST 1 diff --git a/libc/sysdeps/linux/common/bits/utmpx.h b/libc/sysdeps/linux/common/bits/utmpx.h new file mode 100644 index 0000000..c84cda6 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/utmpx.h @@ -0,0 +1,103 @@ +/* Structures and definitions for the user accounting database. GNU version. + Copyright (C) 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMPX_H +# error "Never include directly; use instead." +#endif + +#include +#include +#include + + +#ifdef __USE_GNU +# include +# define _PATH_UTMPX _PATH_UTMP +# define _PATH_WTMPX _PATH_WTMP +#endif + + +#define __UT_LINESIZE 32 +#define __UT_NAMESIZE 32 +#define __UT_HOSTSIZE 256 + + +/* The structure describing the status of a terminated process. This + type is used in `struct utmpx' below. */ +struct __exit_status + { +#ifdef __USE_GNU + short int e_termination; /* Process termination status. */ + short int e_exit; /* Process exit status. */ +#else + short int __e_termination; /* Process termination status. */ + short int __e_exit; /* Process exit status. */ +#endif + }; + + +/* The structure describing an entry in the user accounting database. */ +struct utmpx +{ + short int ut_type; /* Type of login. */ + __pid_t ut_pid; /* Process ID of login process. */ + char ut_line[__UT_LINESIZE]; /* Devicename. */ + char ut_id[4]; /* Inittab ID. */ + char ut_user[__UT_NAMESIZE]; /* Username. */ + char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ + struct __exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + +/* The fields ut_session and ut_tv must be the same size when compiled + 32- and 64-bit. This allows files and shared memory to be shared + between 32- and 64-bit applications. */ +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + __int32_t ut_session; /* Session ID, used for windowing. */ + struct + { + __int32_t tv_sec; /* Seconds. */ + __int32_t tv_usec; /* Microseconds. */ + } ut_tv; /* Time entry was made. */ +#else + long int ut_session; /* Session ID, used for windowing. */ + struct timeval ut_tv; /* Time entry was made. */ +#endif + __int32_t ut_addr_v6[4]; /* Internet address of remote host. */ + char __unused[20]; /* Reserved for future use. */ +}; + + +/* Values for the `ut_type' field of a `struct utmpx'. */ +#define EMPTY 0 /* No valid user accounting information. */ + +#ifdef __USE_GNU +# define RUN_LVL 1 /* The system's runlevel. */ +#endif +#define BOOT_TIME 2 /* Time of system boot. */ +#define NEW_TIME 3 /* Time after system clock changed. */ +#define OLD_TIME 4 /* Time when system clock changed. */ + +#define INIT_PROCESS 5 /* Process spawned by the init process. */ +#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ +#define USER_PROCESS 7 /* Normal process. */ +#define DEAD_PROCESS 8 /* Terminated process. */ + +#ifdef __USE_GNU +# define ACCOUNTING 9 /* System accounting. */ +#endif diff --git a/libc/sysdeps/linux/common/bits/utsname.h b/libc/sysdeps/linux/common/bits/utsname.h new file mode 100644 index 0000000..35e71e3 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/utsname.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UTSNAME_H +# error "Never include directly; use instead." +#endif + +/* Length of the entries in `struct utsname' is 65. */ +#define _UTSNAME_LENGTH 65 + +/* Linux provides as additional information in the `struct utsname' + the name of the current domain. Define _UTSNAME_DOMAIN_LENGTH + to a value != 0 to activate this entry. */ +#define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH diff --git a/libc/sysdeps/linux/common/bits/waitflags.h b/libc/sysdeps/linux/common/bits/waitflags.h new file mode 100644 index 0000000..464cedb --- /dev/null +++ b/libc/sysdeps/linux/common/bits/waitflags.h @@ -0,0 +1,38 @@ +/* Definitions of flag bits for `waitpid' et al. + Copyright (C) 1992,1996,1997,2000,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_WAIT_H && !defined _STDLIB_H +# error "Never include directly; use instead." +#endif + + +/* Bits in the third argument to `waitpid'. */ +#define WNOHANG 1 /* Don't block waiting. */ +#define WUNTRACED 2 /* Report status of stopped children. */ + +/* Bits in the fourth argument to `waitid'. */ +#define WSTOPPED 2 /* Report stopped child (same as WUNTRACED). */ +#define WEXITED 4 /* Report dead child. */ +#define WCONTINUED 8 /* Report continued child. */ +#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */ + +#define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads + in this group */ +#define __WALL 0x40000000 /* Wait for any child. */ +#define __WCLONE 0x80000000 /* Wait for cloned process. */ diff --git a/libc/sysdeps/linux/common/bits/waitstatus.h b/libc/sysdeps/linux/common/bits/waitstatus.h new file mode 100644 index 0000000..699c224 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/waitstatus.h @@ -0,0 +1,106 @@ +/* Definitions of status bits for `wait' et al. + Copyright (C) 1992,1994,1996,1997,2000,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_WAIT_H && !defined _STDLIB_H +# error "Never include directly; use instead." +#endif + + +/* Everything extant so far uses these same bits. */ + + +/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ +#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) + +/* If WIFSIGNALED(STATUS), the terminating signal. */ +#define __WTERMSIG(status) ((status) & 0x7f) + +/* If WIFSTOPPED(STATUS), the signal that stopped the child. */ +#define __WSTOPSIG(status) __WEXITSTATUS(status) + +/* Nonzero if STATUS indicates normal termination. */ +#define __WIFEXITED(status) (__WTERMSIG(status) == 0) + +/* Nonzero if STATUS indicates termination by a signal. */ +#define __WIFSIGNALED(status) \ + (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) + +/* Nonzero if STATUS indicates the child is stopped. */ +#define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) + +/* Nonzero if STATUS indicates the child continued after a stop. We only + define this if provides the WCONTINUED flag bit. */ +#ifdef WCONTINUED +# define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif + +/* Nonzero if STATUS indicates the child dumped core. */ +#define __WCOREDUMP(status) ((status) & __WCOREFLAG) + +/* Macros for constructing status values. */ +#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +#define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#define __W_CONTINUED 0xffff +#define __WCOREFLAG 0x80 + + +#ifdef __USE_BSD + +# include + +union wait + { + int w_status; + struct + { +# if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int __w_termsig:7; /* Terminating signal. */ + unsigned int __w_coredump:1; /* Set if dumped core. */ + unsigned int __w_retcode:8; /* Return code if exited normally. */ + unsigned int:16; +# endif /* Little endian. */ +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned int:16; + unsigned int __w_retcode:8; + unsigned int __w_coredump:1; + unsigned int __w_termsig:7; +# endif /* Big endian. */ + } __wait_terminated; + struct + { +# if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ + unsigned int __w_stopsig:8; /* Stopping signal. */ + unsigned int:16; +# endif /* Little endian. */ +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned int:16; + unsigned int __w_stopsig:8; /* Stopping signal. */ + unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ +# endif /* Big endian. */ + } __wait_stopped; + }; + +# define w_termsig __wait_terminated.__w_termsig +# define w_coredump __wait_terminated.__w_coredump +# define w_retcode __wait_terminated.__w_retcode +# define w_stopsig __wait_stopped.__w_stopsig +# define w_stopval __wait_stopped.__w_stopval + +#endif /* Use BSD. */ diff --git a/libc/sysdeps/linux/common/bits/wchar.h b/libc/sysdeps/linux/common/bits/wchar.h new file mode 100644 index 0000000..ef1f563 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/wchar.h @@ -0,0 +1,26 @@ +/* wchar_t type related definitions. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_WCHAR_H +#define _BITS_WCHAR_H 1 + +#define __WCHAR_MIN (-2147483647 - 1) +#define __WCHAR_MAX (2147483647) + +#endif /* bits/wchar.h */ diff --git a/libc/sysdeps/linux/common/bits/wordsize.h b/libc/sysdeps/linux/common/bits/wordsize.h new file mode 100644 index 0000000..2d8e2b9 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/wordsize.h @@ -0,0 +1,6 @@ +#error "This file must be written based on the data type sizes of the target" + +#if 0 +#define __WORDSIZE 32 +#define __WORDSIZE 64 +#endif diff --git a/libc/sysdeps/linux/common/bits/xopen_lim.h b/libc/sysdeps/linux/common/bits/xopen_lim.h new file mode 100644 index 0000000..c2363ab --- /dev/null +++ b/libc/sysdeps/linux/common/bits/xopen_lim.h @@ -0,0 +1,150 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +/* Additional definitions from X/Open Portability Guide, Issue 4, Version 2 + System Interfaces and Headers, 4.16 + + Please note only the values which are not greater than the minimum + stated in the standard document are listed. The `sysconf' functions + should be used to obtain the actual value. */ + +#ifndef _XOPEN_LIM_H +#define _XOPEN_LIM_H 1 + +#define __need_IOV_MAX +#include + +/* We do not provide fixed values for + + ARG_MAX Maximum length of argument to the `exec' function + including environment data. + + ATEXIT_MAX Maximum number of functions that may be registered + with `atexit'. + + CHILD_MAX Maximum number of simultaneous processes per real + user ID. + + OPEN_MAX Maximum number of files that one process can have open + at anyone time. + + PAGESIZE + PAGE_SIZE Size of bytes of a page. + + PASS_MAX Maximum number of significant bytes in a password. + + We only provide a fixed limit for + + IOV_MAX Maximum number of `iovec' structures that one process has + available for use with `readv' or writev'. + + if this is indeed fixed by the underlying system. +*/ + + +/* Maximum number of `iovec' structures that one process has available + for use with `readv' or writev'. */ +#define _XOPEN_IOV_MAX _POSIX_UIO_MAXIOV + + +/* Maximum value of `digit' in calls to the `printf' and `scanf' + functions. Posix dictates this should be a minimum of 9 */ +#if !defined(__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__) || (__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ <= 1) +#undef NL_ARGMAX +#elif __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ < 9 +#define NL_ARGMAX 9 +#else +#define NL_ARGMAX __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ +#endif + +/* Maximum number of bytes in a `LANG' name. We have no limit. */ +#define NL_LANGMAX _POSIX2_LINE_MAX + +/* Maximum message number. We have no limit. */ +#define NL_MSGMAX INT_MAX + +/* Maximum number of bytes in N-to-1 collation mapping. We have no + limit. */ +#define NL_NMAX INT_MAX + +/* Maximum set number. We have no limit. */ +#define NL_SETMAX INT_MAX + +/* Maximum number of bytes in a message. We have no limit. */ +#define NL_TEXTMAX INT_MAX + +/* Default process priority. */ +#define NZERO 20 + + +/* Number of bits in a word of type `int'. */ +#ifdef INT_MAX +# if INT_MAX == 32767 +# define WORD_BIT 16 +# else +# if INT_MAX == 2147483647 +# define WORD_BIT 32 +# else +/* Safe assumption. */ +# define WORD_BIT 64 +# endif +# endif +#elif defined __INT_MAX__ +# if __INT_MAX__ == 32767 +# define WORD_BIT 16 +# else +# if __INT_MAX__ == 2147483647 +# define WORD_BIT 32 +# else +/* Safe assumption. */ +# define WORD_BIT 64 +# endif +# endif +#else +# define WORD_BIT 32 +#endif + +/* Number of bits in a word of type `long int'. */ +#ifdef LONG_MAX +# if LONG_MAX == 2147483647 +# define LONG_BIT 32 +# else +/* Safe assumption. */ +# define LONG_BIT 64 +# endif +#elif defined __LONG_MAX__ +# if __LONG_MAX__ == 2147483647 +# define LONG_BIT 32 +# else +/* Safe assumption. */ +# define LONG_BIT 64 +# endif +#else +# include +# if __WORDSIZE == 64 +# define LONG_BIT 64 +# else +# define LONG_BIT 32 +# endif +#endif + +#endif /* bits/xopen_lim.h */ diff --git a/libc/sysdeps/linux/common/capget.c b/libc/sysdeps/linux/common/capget.c new file mode 100644 index 0000000..361de84 --- /dev/null +++ b/libc/sysdeps/linux/common/capget.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * capget() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int capget(void *header, void *data); +#ifdef __NR_capget +_syscall2(int, capget, void *, header, void *, data) +#else +int capget(void *header, void *data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/capset.c b/libc/sysdeps/linux/common/capset.c new file mode 100644 index 0000000..f893628 --- /dev/null +++ b/libc/sysdeps/linux/common/capset.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * capset() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int capset(void *header, const void *data); +#ifdef __NR_capset +_syscall2(int, capset, void *, header, const void *, data) +#else +int capset(void *header, const void *data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/chdir.c b/libc/sysdeps/linux/common/chdir.c new file mode 100644 index 0000000..ee889ba --- /dev/null +++ b/libc/sysdeps/linux/common/chdir.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * chdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(chdir) + +#define __NR___syscall_chdir __NR_chdir +static __inline__ _syscall1(int, __syscall_chdir, const char *, path) +int chdir(const char *path) +{ + return __syscall_chdir(path); +} +libc_hidden_def(chdir) diff --git a/libc/sysdeps/linux/common/chmod.c b/libc/sysdeps/linux/common/chmod.c new file mode 100644 index 0000000..da0dff6 --- /dev/null +++ b/libc/sysdeps/linux/common/chmod.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * chmod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(chmod) + +#define __NR___syscall_chmod __NR_chmod +static __inline__ _syscall2(int, __syscall_chmod, const char *, path, __kernel_mode_t, mode) + +int chmod(const char *path, mode_t mode) +{ + return __syscall_chmod(path, mode); +} +libc_hidden_def(chmod) diff --git a/libc/sysdeps/linux/common/chown.c b/libc/sysdeps/linux/common/chown.c new file mode 100644 index 0000000..f325071 --- /dev/null +++ b/libc/sysdeps/linux/common/chown.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * chown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(chown) + +#if (__WORDSIZE == 32 && defined(__NR_chown32)) || __WORDSIZE == 64 +# ifdef __NR_chown32 +# undef __NR_chown +# define __NR_chown __NR_chown32 +# endif + +_syscall3(int, chown, const char *, path, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_chown __NR_chown +static __inline__ _syscall3(int, __syscall_chown, const char *, path, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int chown(const char *path, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_chown(path, owner, group)); +} +#endif + +libc_hidden_def(chown) diff --git a/libc/sysdeps/linux/common/chroot.c b/libc/sysdeps/linux/common/chroot.c new file mode 100644 index 0000000..4c085f2 --- /dev/null +++ b/libc/sysdeps/linux/common/chroot.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * chroot() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +#define __NR___syscall_chroot __NR_chroot +static __inline__ _syscall1(int, __syscall_chroot, const char *, path) + +int chroot(const char *path) +{ + return __syscall_chroot(path); +} +#endif diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c new file mode 100644 index 0000000..e0eb1b6 --- /dev/null +++ b/libc/sysdeps/linux/common/clock_getres.c @@ -0,0 +1,44 @@ +/* + * clock_getres() for uClibc + * + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_getres +_syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res) +#else +libc_hidden_proto(sysconf) + +int clock_getres(clockid_t clock_id, struct timespec* res) +{ + int retval = -1; + + switch (clock_id) { + case CLOCK_REALTIME: + if (res) { + long clk_tck; + + if ((clk_tck = sysconf(_SC_CLK_TCK)) < 0) + clk_tck = 100; + res->tv_sec = 0; + res->tv_nsec = 1000000000 / clk_tck; + } + retval = 0; + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif +libc_hidden_def(clock_getres) diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c new file mode 100644 index 0000000..f0f1ae4 --- /dev/null +++ b/libc/sysdeps/linux/common/clock_gettime.c @@ -0,0 +1,40 @@ +/* + * clock_gettime() for uClibc + * + * Copyright (C) 2003 by Justus Pendleton + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_gettime +_syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) +#else +libc_hidden_proto(gettimeofday) + +int clock_gettime(clockid_t clock_id, struct timespec* tp) +{ + struct timeval tv; + int retval = -1; + + switch (clock_id) { + case CLOCK_REALTIME: + retval = gettimeofday(&tv, NULL); + if (retval == 0) { + TIMEVAL_TO_TIMESPEC(&tv, tp); + } + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c new file mode 100644 index 0000000..652bceb --- /dev/null +++ b/libc/sysdeps/linux/common/clock_settime.c @@ -0,0 +1,42 @@ +/* + * clock_settime() for uClibc + * + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_settime +_syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) +#else +libc_hidden_proto(settimeofday) + +int clock_settime(clockid_t clock_id, const struct timespec* tp) +{ + struct timeval tv; + int retval = -1; + + if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) { + errno = EINVAL; + return -1; + } + + switch (clock_id) { + case CLOCK_REALTIME: + TIMESPEC_TO_TIMEVAL(&tv, tp); + retval = settimeofday(&tv, NULL); + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif diff --git a/libc/sysdeps/linux/common/close.c b/libc/sysdeps/linux/common/close.c new file mode 100644 index 0000000..c6ddbed --- /dev/null +++ b/libc/sysdeps/linux/common/close.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * close() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(close) __libc_close; +#define __NR___libc_close __NR_close +_syscall1(int, __libc_close, int, fd) +libc_hidden_proto(close) +weak_alias(__libc_close,close) +libc_hidden_weak(close) diff --git a/libc/sysdeps/linux/common/cmsg_nxthdr.c b/libc/sysdeps/linux/common/cmsg_nxthdr.c new file mode 100644 index 0000000..8350c3a --- /dev/null +++ b/libc/sysdeps/linux/common/cmsg_nxthdr.c @@ -0,0 +1,43 @@ +/* Return point to next ancillary data entry in message header. + Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include + +libc_hidden_proto(__cmsg_nxthdr) + +struct cmsghdr * +__cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg) +{ + if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return NULL; + + cmsg = (struct cmsghdr *) ((unsigned char *) cmsg + + CMSG_ALIGN (cmsg->cmsg_len)); + if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control + + mhdr->msg_controllen) + || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len) + > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen))) + /* No more entries. */ + return NULL; + return cmsg; +} +libc_hidden_def(__cmsg_nxthdr) diff --git a/libc/sysdeps/linux/common/creat64.c b/libc/sysdeps/linux/common/creat64.c new file mode 100644 index 0000000..f5f0018 --- /dev/null +++ b/libc/sysdeps/linux/common/creat64.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#ifdef __UCLIBC_HAS_LFS__ +#include +#include + +extern __typeof(open64) __libc_open64; +libc_hidden_proto(__libc_open64) +extern __typeof(creat64) __libc_creat64; + +/* Create FILE with protections MODE. */ +int __libc_creat64 (const char *file, mode_t mode) +{ + return __libc_open64 (file, O_WRONLY|O_CREAT|O_TRUNC, mode); +} +weak_alias(__libc_creat64,creat64) +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/create_module.c b/libc/sysdeps/linux/common/create_module.c new file mode 100644 index 0000000..d8f2446 --- /dev/null +++ b/libc/sysdeps/linux/common/create_module.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * create_module syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#ifdef __NR_create_module + +unsigned long create_module(const char *name, size_t size); + +#if defined(__UCLIBC_BROKEN_CREATE_MODULE__) +# define __NR___create_module __NR_create_module +static __inline__ _syscall2(long, __create_module, const char *, name, size_t, size) +/* By checking the value of errno, we know if we have been fooled + * by the syscall2 macro making a very high address look like a + * negative, so we we fix it up here. */ +unsigned long create_module(const char *name, size_t size) +{ + long ret = __create_module(name, size); + + /* Jump through hoops to fixup error return codes */ + if (ret == -1 && errno > 125) { + ret = -errno; + __set_errno(0); + } + return ret; +} +#elif defined(__UCLIBC_SLIGHTLY_BROKEN_CREATE_MODULE__) +# define __NR___create_module __NR_create_module +/* Alpha doesn't have the same problem, exactly, but a bug in older + kernels fails to clear the error flag. Clear it here explicitly. */ +static __inline__ _syscall4(unsigned long, __create_module, const char *, name, + size_t, size, size_t, dummy, size_t, err) +unsigned long create_module(const char *name, size_t size) +{ + return __create_module(name, size, 0, 0); +} +#else +/* Sparc, MIPS, etc don't mistake return values for errors. */ +_syscall2(unsigned long, create_module, const char *, name, size_t, size) +#endif + +#else /* !__NR_create_module */ +caddr_t create_module(const char *name attribute_unused, size_t size attribute_unused); +caddr_t create_module(const char *name attribute_unused, size_t size attribute_unused) +{ + __set_errno(ENOSYS); + return (caddr_t)-1; +} +#endif diff --git a/libc/sysdeps/linux/common/delete_module.c b/libc/sysdeps/linux/common/delete_module.c new file mode 100644 index 0000000..44f9b30 --- /dev/null +++ b/libc/sysdeps/linux/common/delete_module.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * delete_module() for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int delete_module(const char *name, unsigned int flags); +#ifdef __NR_delete_module +_syscall2(int, delete_module, const char *, name, unsigned int, flags) +#elif defined __UCLIBC_HAS_STUBS__ +int delete_module(const char *name, unsigned int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/dl-osinfo.h b/libc/sysdeps/linux/common/dl-osinfo.h new file mode 100644 index 0000000..5155322 --- /dev/null +++ b/libc/sysdeps/linux/common/dl-osinfo.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _DL_OSINFO_H +#define _DL_OSINFO_H 1 + +#include + +#ifdef __UCLIBC_HAS_SSP__ +# if defined IS_IN_libc || defined IS_IN_rtld + +# if defined __SSP__ || defined __SSP_ALL__ +# error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector" +# endif + +# include +# include + +# ifdef IS_IN_libc +#include +libc_hidden_proto(open) +libc_hidden_proto(read) +libc_hidden_proto(close) +libc_hidden_proto(gettimeofday) +# define OPEN open +# define READ read +# define CLOSE close +# define GETTIMEOFDAY gettimeofday +# else +# define OPEN _dl_open +# define READ _dl_read +# define CLOSE _dl_close +# define GETTIMEOFDAY _dl_gettimeofday +# endif + +static __always_inline uintptr_t _dl_setup_stack_chk_guard(void) +{ + uintptr_t ret; +# ifndef __SSP_QUICK_CANARY__ + { + int fd = OPEN("/dev/urandom", O_RDONLY, 0); + if (fd >= 0) { + size_t size = READ(fd, &ret, sizeof(ret)); + CLOSE(fd); + if (size == (size_t) sizeof(ret)) + return ret; + } + } +# endif /* !__SSP_QUICK_CANARY__ */ + + /* Start with the "terminator canary". */ + ret = 0xFF0A0D00UL; + + /* Everything failed? Or we are using a weakened model of the + * terminator canary */ + { + struct timeval tv; + if (GETTIMEOFDAY(&tv, NULL) != (-1)) + ret ^= tv.tv_usec ^ tv.tv_sec; + } + return ret; +} +# endif /* libc || rtld */ +#endif /* __UCLIBC_HAS_SSP__ */ + +#endif /* _DL_OSINFO_H */ diff --git a/libc/sysdeps/linux/common/dup.c b/libc/sysdeps/linux/common/dup.c new file mode 100644 index 0000000..d351766 --- /dev/null +++ b/libc/sysdeps/linux/common/dup.c @@ -0,0 +1,11 @@ +/* vi: set sw=4 ts=4: */ +/* + * dup() for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, dup, int, oldfd) diff --git a/libc/sysdeps/linux/common/dup2.c b/libc/sysdeps/linux/common/dup2.c new file mode 100644 index 0000000..da885a9 --- /dev/null +++ b/libc/sysdeps/linux/common/dup2.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * dup2() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(dup2) + +_syscall2(int, dup2, int, oldfd, int, newfd) +libc_hidden_def(dup2) diff --git a/libc/sysdeps/linux/common/epoll.c b/libc/sysdeps/linux/common/epoll.c new file mode 100644 index 0000000..86272d9 --- /dev/null +++ b/libc/sysdeps/linux/common/epoll.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * epoll_create() / epoll_ctl() / epoll_wait() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* + * epoll_create() + */ +#ifdef __NR_epoll_create +_syscall1(int, epoll_create, int, size) +#else +int epoll_create(int size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* + * epoll_ctl() + */ +#ifdef __NR_epoll_ctl +_syscall4(int,epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event) +#else +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* + * epoll_wait() + */ +#ifdef __NR_epoll_wait +_syscall4(int, epoll_wait, int, epfd, struct epoll_event *, events, int, maxevents, int, timeout) +#else +int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/execve.c b/libc/sysdeps/linux/common/execve.c new file mode 100644 index 0000000..5e947d6 --- /dev/null +++ b/libc/sysdeps/linux/common/execve.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * execve() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(execve) +_syscall3(int, execve, const char *, filename, + char *const *, argv, char *const *, envp) +libc_hidden_def(execve) diff --git a/libc/sysdeps/linux/common/fchdir.c b/libc/sysdeps/linux/common/fchdir.c new file mode 100644 index 0000000..00a857c --- /dev/null +++ b/libc/sysdeps/linux/common/fchdir.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(fchdir) + +_syscall1(int, fchdir, int, fd) +libc_hidden_def(fchdir) diff --git a/libc/sysdeps/linux/common/fchmod.c b/libc/sysdeps/linux/common/fchmod.c new file mode 100644 index 0000000..791f530 --- /dev/null +++ b/libc/sysdeps/linux/common/fchmod.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchmod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_fchmod __NR_fchmod +static __inline__ _syscall2(int, __syscall_fchmod, + int, fildes, __kernel_mode_t, mode) + +int fchmod(int fildes, mode_t mode) +{ + return (__syscall_fchmod(fildes, mode)); +} diff --git a/libc/sysdeps/linux/common/fchown.c b/libc/sysdeps/linux/common/fchown.c new file mode 100644 index 0000000..61618dc --- /dev/null +++ b/libc/sysdeps/linux/common/fchown.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_fchown32)) || __WORDSIZE == 64 +# ifdef __NR_fchown32 +# undef __NR_fchown +# define __NR_fchown __NR_fchown32 +# endif + +_syscall3(int, fchown, int, fd, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_fchown __NR_fchown +static __inline__ _syscall3(int, __syscall_fchown, int, fd, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int fchown(int fd, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_fchown(fd, owner, group)); +} + +#endif diff --git a/libc/sysdeps/linux/common/fdatasync.c b/libc/sysdeps/linux/common/fdatasync.c new file mode 100644 index 0000000..07433bc --- /dev/null +++ b/libc/sysdeps/linux/common/fdatasync.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * fdatasync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_osf_fdatasync +# define __NR_fdatasync __NR_osf_fdatasync +#endif + +_syscall1(int, fdatasync, int, fd) diff --git a/libc/sysdeps/linux/common/flock.c b/libc/sysdeps/linux/common/flock.c new file mode 100644 index 0000000..3dcd1ae --- /dev/null +++ b/libc/sysdeps/linux/common/flock.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * flock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_flock __NR_flock +static __inline__ _syscall2(int, __syscall_flock, int, fd, int, operation) + +int flock(int fd, int operation) +{ + return (__syscall_flock(fd, operation)); +} diff --git a/libc/sysdeps/linux/common/fork.c b/libc/sysdeps/linux/common/fork.c new file mode 100644 index 0000000..7c12814 --- /dev/null +++ b/libc/sysdeps/linux/common/fork.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __ARCH_USE_MMU__ + +#ifdef __NR_fork +extern __typeof(fork) __libc_fork; +#define __NR___libc_fork __NR_fork +_syscall0(pid_t, __libc_fork) +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) +#endif + +#elif defined __UCLIBC_HAS_STUBS__ + +pid_t __libc_fork(void) +{ + __set_errno(ENOSYS); + return -1; +} +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) +link_warning(fork, "fork: this function is not implemented on no-mmu systems") + +#endif diff --git a/libc/sysdeps/linux/common/fpu_control.h b/libc/sysdeps/linux/common/fpu_control.h new file mode 100644 index 0000000..de261c2 --- /dev/null +++ b/libc/sysdeps/linux/common/fpu_control.h @@ -0,0 +1,41 @@ +/* FPU control word definitions. Stub version. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#define _FPU_RESERVED 0xffffffff /* These bits are reserved and not changed. */ + +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 /* Default value. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) 0 +#define _FPU_SETCW(cw) do { } while (0) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c new file mode 100644 index 0000000..8d1cfdc --- /dev/null +++ b/libc/sysdeps/linux/common/fstat.c @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* need to hide the 64bit prototype or the strong_alias() + * will fail when __NR_fstat64 doesnt exist */ +#define fstat64 __hidefstat64 + +#include +#include +#include +#include "xstatconv.h" + +#undef fstat64 + +libc_hidden_proto(fstat) + +#define __NR___syscall_fstat __NR_fstat +static __inline__ _syscall2(int, __syscall_fstat, int, fd, struct kernel_stat *, buf) + +int fstat(int fd, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_fstat(fd, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(fstat) + +#if ! defined __NR_fstat64 && defined __UCLIBC_HAS_LFS__ +extern __typeof(fstat) fstat64; +libc_hidden_proto(fstat64) +strong_alias(fstat,fstat64) +libc_hidden_def(fstat64) +#endif diff --git a/libc/sysdeps/linux/common/fstat64.c b/libc/sysdeps/linux/common/fstat64.c new file mode 100644 index 0000000..5dfb23d --- /dev/null +++ b/libc/sysdeps/linux/common/fstat64.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fstat64 +#include +#include +#include "xstatconv.h" + +libc_hidden_proto(fstat64) + +#define __NR___syscall_fstat64 __NR_fstat64 +static __inline__ _syscall2(int, __syscall_fstat64, + int, filedes, struct kernel_stat64 *, buf) + +int fstat64(int fd, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_fstat64(fd, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(fstat64) +#endif diff --git a/libc/sysdeps/linux/common/fstatfs.c b/libc/sysdeps/linux/common/fstatfs.c new file mode 100644 index 0000000..af90bbe --- /dev/null +++ b/libc/sysdeps/linux/common/fstatfs.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstatfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs; +libc_hidden_proto(__libc_fstatfs) +#define __NR___libc_fstatfs __NR_fstatfs +_syscall2(int, __libc_fstatfs, int, fd, struct statfs *, buf) +libc_hidden_def(__libc_fstatfs) + +#if defined __UCLIBC_LINUX_SPECIFIC__ +libc_hidden_proto(fstatfs) +weak_alias(__libc_fstatfs,fstatfs) +libc_hidden_weak(fstatfs) +#endif diff --git a/libc/sysdeps/linux/common/fsync.c b/libc/sysdeps/linux/common/fsync.c new file mode 100644 index 0000000..1066770 --- /dev/null +++ b/libc/sysdeps/linux/common/fsync.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * fsync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(fsync) __libc_fsync; +#define __NR___libc_fsync __NR_fsync +_syscall1(int, __libc_fsync, int, fd) +weak_alias(__libc_fsync, fsync) diff --git a/libc/sysdeps/linux/common/ftruncate.c b/libc/sysdeps/linux/common/ftruncate.c new file mode 100644 index 0000000..3449d80 --- /dev/null +++ b/libc/sysdeps/linux/common/ftruncate.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * ftruncate() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(ftruncate) + +_syscall2(int, ftruncate, int, fd, __off_t, length) +libc_hidden_def(ftruncate) diff --git a/libc/sysdeps/linux/common/ftruncate64.c b/libc/sysdeps/linux/common/ftruncate64.c new file mode 100644 index 0000000..4876087 --- /dev/null +++ b/libc/sysdeps/linux/common/ftruncate64.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * ftruncate64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include + +#ifdef __UCLIBC_HAS_LFS__ + +# include +# include +# include +# include +# include +# include + +libc_hidden_proto(ftruncate64) + +# ifdef __NR_ftruncate64 + +# if __WORDSIZE == 64 + +/* For a 64 bit machine, life is simple... */ +_syscall2(int, ftruncate64, int, fd, __off64_t, length) + +# elif __WORDSIZE == 32 + +# ifndef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) __syscall_ftruncate64 (args) +# define __NR___syscall_ftruncate64 __NR_ftruncate64 +# if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) +static __inline__ _syscall4(int, __syscall_ftruncate64, int, fd, uint32_t, pad, + unsigned long, high_length, unsigned long, low_length) +# else +static __inline__ _syscall3(int, __syscall_ftruncate64, int, fd, + unsigned long, high_length, unsigned long, low_length) +# endif +# endif + +/* The exported ftruncate64 function. */ +int ftruncate64 (int fd, __off64_t length) +{ + uint32_t low = length & 0xffffffff; + uint32_t high = length >> 32; +# if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) + return INLINE_SYSCALL(ftruncate64, + 4, fd, 0, __LONG_LONG_PAIR (high, low)); +# else + return INLINE_SYSCALL(ftruncate64, 3, fd, + __LONG_LONG_PAIR (high, low)); +# endif +} + +# else /* __WORDSIZE */ +# error Your machine is not 64 bit or 32 bit, I am dazed and confused. +# endif /* __WORDSIZE */ + +# else /* __NR_ftruncate64 */ + +libc_hidden_proto(ftruncate) + +int ftruncate64 (int fd, __off64_t length) +{ + __off_t x = (__off_t) length; + + if (x == length) { + return ftruncate(fd, x); + } + + __set_errno((x < 0) ? EINVAL : EFBIG); + + return -1; +} + +# endif /* __NR_ftruncate64 */ +libc_hidden_def(ftruncate64) + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/get_kernel_syms.c b/libc/sysdeps/linux/common/get_kernel_syms.c new file mode 100644 index 0000000..d6595ea --- /dev/null +++ b/libc/sysdeps/linux/common/get_kernel_syms.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * get_kernel_syms() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +struct kernel_sym; +int get_kernel_syms(struct kernel_sym *table attribute_unused); +#ifdef __NR_get_kernel_syms +_syscall1(int, get_kernel_syms, struct kernel_sym *, table) +#else +int get_kernel_syms(struct kernel_sym *table attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/getcwd.c b/libc/sysdeps/linux/common/getcwd.c new file mode 100644 index 0000000..ddeb483 --- /dev/null +++ b/libc/sysdeps/linux/common/getcwd.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These functions find the absolute path to the current working directory. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(getcwd) +libc_hidden_proto(getpagesize) + +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(opendir) +libc_hidden_proto(readdir) +libc_hidden_proto(closedir) +libc_hidden_proto(stat) + +#ifdef __NR_getcwd + +# define __NR___syscall_getcwd __NR_getcwd +static __always_inline +_syscall2(int, __syscall_getcwd, char *, buf, unsigned long, size) + +#else + +/* If the syscall is not present, we have to walk up the + * directory tree till we hit the root. Now we _could_ + * use /proc/self/cwd if /proc is mounted... That approach + * is left an an exercise for the reader... */ + + +/* Seems a few broken filesystems (like coda) don't like this */ +/* #undef FAST_DIR_SEARCH_POSSIBLE on Linux */ + + +/* Routine to find the step back down */ +static char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, int path_size) +{ + DIR *dp; + struct dirent *d; + char *ptr; + int slen; + struct stat st; + +# ifdef FAST_DIR_SEARCH_POSSIBLE + /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */ + int slow_search = (sizeof(ino_t) != sizeof(d->d_ino)); +# endif + + if (stat(path_buf, &st) < 0) { + goto oops; + } +# ifdef FAST_DIR_SEARCH_POSSIBLE + if (this_dev != st.st_dev) + slow_search = 1; +# endif + + slen = strlen(path_buf); + ptr = path_buf + slen - 1; + if (*ptr != '/') { + if (slen + 2 > path_size) { + goto oops; + } + strcpy(++ptr, "/"); + slen++; + } + slen++; + + dp = opendir(path_buf); + if (dp == 0) { + goto oops; + } + + while ((d = readdir(dp)) != 0) { +# ifdef FAST_DIR_SEARCH_POSSIBLE + if (slow_search || this_ino == d->d_ino) { +# endif + if (slen + strlen(d->d_name) > path_size) { + goto oops; + } + strcpy(ptr + 1, d->d_name); + if (stat(path_buf, &st) < 0) + continue; + if (st.st_ino == this_ino && st.st_dev == this_dev) { + closedir(dp); + return path_buf; + } +# ifdef FAST_DIR_SEARCH_POSSIBLE + } +# endif + } + + closedir(dp); + return 0; + +oops: + __set_errno(ERANGE); + return 0; +} + +/* Routine to go up tree */ +static char *recurser(char *path_buf, int path_size, dev_t root_dev, ino_t root_ino) +{ + struct stat st; + dev_t this_dev; + ino_t this_ino; + + if (stat(path_buf, &st) < 0) { + if (errno != EFAULT) + goto oops; + return 0; + } + this_dev = st.st_dev; + this_ino = st.st_ino; + if (this_dev == root_dev && this_ino == root_ino) { + if (path_size < 2) { + goto oops; + } + strcpy(path_buf, "/"); + return path_buf; + } + if (strlen(path_buf) + 4 > path_size) { + goto oops; + } + strcat(path_buf, "/.."); + if (recurser(path_buf, path_size, root_dev, root_ino) == 0) + return 0; + + return search_dir(this_dev, this_ino, path_buf, path_size); +oops: + __set_errno(ERANGE); + return 0; +} + +static __always_inline +int __syscall_getcwd(char * buf, unsigned long size) +{ + int len; + char *cwd; + struct stat st; + int olderrno; + + olderrno = errno; + len = -1; + + /* get stat for root to have a valid parameters for the terminating condition */ + if (stat("/", &st) < 0) { + /* root dir not found! */ + return -1; + } + /* start with actual dir */ + if (buf) strncpy(buf, ".", size); + + cwd = recurser(buf, size, st.st_dev, st.st_ino); + if (cwd) { + len = strlen(buf) + 1; + __set_errno(olderrno); + } + return len; +} + +#endif /* __NR_getcwd */ + +char *getcwd(char *buf, size_t size) +{ + int ret; + char *path; + size_t alloc_size = size; + + if (size == 0) { + if (buf != NULL) { + __set_errno(EINVAL); + return NULL; + } + alloc_size = MAX (PATH_MAX, getpagesize ()); + } + path=buf; + if (buf == NULL) { + path = malloc(alloc_size); + if (path == NULL) + return NULL; + } + ret = __syscall_getcwd(path, alloc_size); + if (ret >= 0) + { + if (buf == NULL && size == 0) + buf = realloc(path, ret); + if (buf == NULL) + buf = path; + return buf; + } + if (buf == NULL) + free (path); + return NULL; +} +libc_hidden_def(getcwd) diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c new file mode 100644 index 0000000..17f1ddc --- /dev/null +++ b/libc/sysdeps/linux/common/getdents.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* With newer versions of linux, the getdents syscall returns d_type + * information after the name field. + * + * See __ASSUME_GETDENTS32_D_TYPE in glibc's kernel-features.h for specific + * version / arch details. + */ + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +struct kernel_dirent +{ + long int d_ino; + __kernel_off_t d_off; + unsigned short int d_reclen; + char d_name[256]; +}; + +ssize_t __getdents (int fd, char *buf, size_t nbytes) attribute_hidden; + +#define __NR___syscall_getdents __NR_getdents +static __always_inline _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count) + +#ifdef __ASSUME_GETDENTS32_D_TYPE +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + ssize_t retval; + + retval = __syscall_getdents(fd, (unsigned char *)buf, nbytes); + + /* The kernel added the d_type value after the name. Change + this now. */ + if (retval != -1) { + union { + struct kernel_dirent k; + struct dirent u; + } *kbuf = (void *) buf; + + while ((char *) kbuf < buf + retval) { + char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); + memmove (kbuf->u.d_name, kbuf->k.d_name, + strlen (kbuf->k.d_name) + 1); + kbuf->u.d_type = d_type; + + kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); + } + } + + return retval; +} + +#elif ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64 + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(lseek) + +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + off_t last_offset = -1; + ssize_t retval; + size_t red_nbytes; + struct kernel_dirent *skdp, *kdp; + const size_t size_diff = (offsetof (struct dirent, d_name) + - offsetof (struct kernel_dirent, d_name)); + + red_nbytes = MIN (nbytes - ((nbytes / + (offsetof (struct dirent, d_name) + 14)) * size_diff), + nbytes - size_diff); + + dp = (struct dirent *) buf; + skdp = kdp = alloca (red_nbytes); + + retval = __syscall_getdents(fd, (unsigned char *)kdp, red_nbytes); + if (retval == -1) + return -1; + + while ((char *) kdp < (char *) skdp + retval) { + const size_t alignment = __alignof__ (struct dirent); + /* Since kdp->d_reclen is already aligned for the kernel structure + this may compute a value that is bigger than necessary. */ + size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1) + & ~(alignment - 1)); + if ((char *) dp + new_reclen > buf + nbytes) { + /* Our heuristic failed. We read too many entries. Reset + the stream. */ + assert (last_offset != -1); + lseek(fd, last_offset, SEEK_SET); + + if ((char *) dp == buf) { + /* The buffer the user passed in is too small to hold even + one entry. */ + __set_errno (EINVAL); + return -1; + } + break; + } + + last_offset = kdp->d_off; + dp->d_ino = kdp->d_ino; + dp->d_off = kdp->d_off; + dp->d_reclen = new_reclen; + dp->d_type = DT_UNKNOWN; + memcpy (dp->d_name, kdp->d_name, + kdp->d_reclen - offsetof (struct kernel_dirent, d_name)); + dp = (struct dirent *) ((char *) dp + new_reclen); + kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen); + } + return (char *) dp - buf; +} + +#if defined __UCLIBC_HAS_LFS__ && ! defined __NR_getdents64 +attribute_hidden strong_alias(__getdents,__getdents64) +#endif + +#elif __WORDSIZE == 32 + +/* Experimentally off - libc_hidden_proto(memmove) */ + +extern __typeof(__getdents) __getdents64 attribute_hidden; +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + struct dirent64 *dp64; + ssize_t ret = __getdents64 (fd, buf, nbytes); + + if (ret <= 0) + return ret; + + dp64 = (struct dirent64 *) buf; + buf += ret; + while ((void *) dp64 < (void *) buf) { + dp = (struct dirent *) dp64; + dp->d_ino = dp64->d_ino; + dp->d_off = dp64->d_off; + dp->d_reclen = dp64->d_reclen; + dp->d_type = dp64->d_type; + memmove (dp->d_name, dp64->d_name, dp->d_reclen - offsetof (struct dirent64, d_name)); + memmove (dp64, dp, dp->d_reclen); + dp64 = ((void *) dp64) + dp->d_reclen; + } + + return ret; +} + +#endif diff --git a/libc/sysdeps/linux/common/getdents64.c b/libc/sysdeps/linux/common/getdents64.c new file mode 100644 index 0000000..d789d0f --- /dev/null +++ b/libc/sysdeps/linux/common/getdents64.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_getdents64 + +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(lseek64) + +# ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +# endif + +struct kernel_dirent64 +{ + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + + +# define __NR___syscall_getdents64 __NR_getdents64 +static __inline__ _syscall3(int, __syscall_getdents64, int, fd, unsigned char *, dirp, size_t, count) + +ssize_t __getdents64 (int fd, char *buf, size_t nbytes) attribute_hidden; +ssize_t __getdents64 (int fd, char *buf, size_t nbytes) +{ + struct dirent64 *dp; + off64_t last_offset = -1; + ssize_t retval; + size_t red_nbytes; + struct kernel_dirent64 *skdp, *kdp; + const size_t size_diff = (offsetof (struct dirent64, d_name) + - offsetof (struct kernel_dirent64, d_name)); + + red_nbytes = MIN (nbytes - ((nbytes / + (offsetof (struct dirent64, d_name) + 14)) * size_diff), + nbytes - size_diff); + + dp = (struct dirent64 *) buf; + skdp = kdp = alloca (red_nbytes); + + retval = __syscall_getdents64(fd, (unsigned char *)kdp, red_nbytes); + if (retval == -1) + return -1; + + while ((char *) kdp < (char *) skdp + retval) { + const size_t alignment = __alignof__ (struct dirent64); + /* Since kdp->d_reclen is already aligned for the kernel structure + this may compute a value that is bigger than necessary. */ + size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1) + & ~(alignment - 1)); + if ((char *) dp + new_reclen > buf + nbytes) { + /* Our heuristic failed. We read too many entries. Reset + the stream. */ + assert (last_offset != -1); + lseek64(fd, last_offset, SEEK_SET); + + if ((char *) dp == buf) { + /* The buffer the user passed in is too small to hold even + one entry. */ + __set_errno (EINVAL); + return -1; + } + break; + } + + last_offset = kdp->d_off; + dp->d_ino = kdp->d_ino; + dp->d_off = kdp->d_off; + dp->d_reclen = new_reclen; + dp->d_type = kdp->d_type; + memcpy (dp->d_name, kdp->d_name, + kdp->d_reclen - offsetof (struct kernel_dirent64, d_name)); + dp = (struct dirent64 *) ((char *) dp + new_reclen); + kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen); + } + return (char *) dp - buf; +} + +#if __WORDSIZE == 64 +/* since getdents doesnt give us d_type but getdents64 does, try and + * use getdents64 as much as possible */ +attribute_hidden strong_alias(__getdents64,__getdents) +#endif + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/getdirname.c b/libc/sysdeps/linux/common/getdirname.c new file mode 100644 index 0000000..5938d72 --- /dev/null +++ b/libc/sysdeps/linux/common/getdirname.c @@ -0,0 +1,67 @@ +/* vi: set sw=4 ts=4: */ +/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_GNU +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strdup) */ +libc_hidden_proto(getcwd) +libc_hidden_proto(getenv) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(stat64) +#else +libc_hidden_proto(stat) +#endif + +/* Return a malloc'd string containing the current directory name. + If the environment variable `PWD' is set, and its value is correct, + that value is used. */ + +char * +get_current_dir_name (void) +{ + char *pwd; +#ifdef __UCLIBC_HAS_LFS__ + struct stat64 dotstat, pwdstat; +#else + struct stat dotstat, pwdstat; +#endif + + pwd = getenv ("PWD"); + if (pwd != NULL +#ifdef __UCLIBC_HAS_LFS__ + && stat64 (".", &dotstat) == 0 + && stat64 (pwd, &pwdstat) == 0 +#else + && stat (".", &dotstat) == 0 + && stat (pwd, &pwdstat) == 0 +#endif + && pwdstat.st_dev == dotstat.st_dev + && pwdstat.st_ino == dotstat.st_ino) + /* The PWD value is correct. Use it. */ + return strdup (pwd); + + return getcwd ((char *) NULL, 0); +} +#endif diff --git a/libc/sysdeps/linux/common/getdomainname.c b/libc/sysdeps/linux/common/getdomainname.c new file mode 100644 index 0000000..86f6dfd --- /dev/null +++ b/libc/sysdeps/linux/common/getdomainname.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +libc_hidden_proto(uname) + +#if !defined __UCLIBC_BSD_SPECIFIC__ +extern int getdomainname (char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; +#endif +extern __typeof(getdomainname) __libc_getdomainname; +libc_hidden_proto(__libc_getdomainname) +int __libc_getdomainname(char *name, size_t len) +{ + struct utsname uts; + + if (name == NULL) { + __set_errno(EINVAL); + return -1; + } + + if (uname(&uts) == -1) return -1; + +#ifdef __USE_GNU + if (strlen(uts.domainname)+1 > len) { +#else + if (strlen(uts.__domainname)+1 > len) { +#endif + __set_errno(EINVAL); + return -1; + } +#ifdef __USE_GNU + strcpy(name, uts.domainname); +#else + strcpy(name, uts.__domainname); +#endif + return 0; +} +libc_hidden_def(__libc_getdomainname) +#if defined __UCLIBC_BSD_SPECIFIC__ +libc_hidden_proto(getdomainname) +weak_alias(__libc_getdomainname,getdomainname) +libc_hidden_weak(getdomainname) +#endif /* __UCLIBC_BSD_SPECIFIC__ */ +#endif diff --git a/libc/sysdeps/linux/common/getdtablesize.c b/libc/sysdeps/linux/common/getdtablesize.c new file mode 100644 index 0000000..44d2186 --- /dev/null +++ b/libc/sysdeps/linux/common/getdtablesize.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +/* XXX: _BSD || _XOPEN_SOURCE >= 500 */ +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +libc_hidden_proto(getdtablesize) + +libc_hidden_proto(getrlimit) + +#define __LOCAL_OPEN_MAX 256 + +/* Return the maximum number of file descriptors + the current process could possibly have. */ +int getdtablesize (void) +{ + struct rlimit ru; + + /* This should even work if `getrlimit' is not implemented. POSIX.1 + does not define this function but we will generate a stub which + returns -1. */ + return getrlimit (RLIMIT_NOFILE, &ru) < 0 ? __LOCAL_OPEN_MAX : ru.rlim_cur; +} +libc_hidden_def(getdtablesize) +#endif diff --git a/libc/sysdeps/linux/common/getegid.c b/libc/sysdeps/linux/common/getegid.c new file mode 100644 index 0000000..ad80e3a --- /dev/null +++ b/libc/sysdeps/linux/common/getegid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * getegid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(getegid) + +#if defined(__NR_getegid32) +# undef __NR_getegid +# define __NR_getegid __NR_getegid32 +_syscall0(gid_t, getegid) + +#elif defined(__NR_getegid) +# define __NR___syscall_getegid __NR_getegid +static __inline__ _syscall0(int, __syscall_getegid) +gid_t getegid(void) +{ + return (__syscall_getegid()); +} +#else +libc_hidden_proto(getgid) + +gid_t getegid(void) +{ + return (getgid()); +} +#endif +libc_hidden_def(getegid) diff --git a/libc/sysdeps/linux/common/geteuid.c b/libc/sysdeps/linux/common/geteuid.c new file mode 100644 index 0000000..63ee1da --- /dev/null +++ b/libc/sysdeps/linux/common/geteuid.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * geteuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(geteuid) + +#if defined(__NR_geteuid32) +# undef __NR_geteuid +# define __NR_geteuid __NR_geteuid32 +_syscall0(uid_t, geteuid) + +#elif defined(__NR_geteuid) +# define __NR___syscall_geteuid __NR_geteuid +static __inline__ _syscall0(int, __syscall_geteuid) +uid_t geteuid(void) +{ + return (__syscall_geteuid()); +} + +#else +libc_hidden_proto(getuid) +uid_t geteuid(void) +{ + return (getuid()); +} +#endif + +libc_hidden_def(geteuid) diff --git a/libc/sysdeps/linux/common/getgid.c b/libc/sysdeps/linux/common/getgid.c new file mode 100644 index 0000000..8fb633b --- /dev/null +++ b/libc/sysdeps/linux/common/getgid.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * getgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_getxgid +# undef __NR_getgid +# define __NR_getgid __NR_getxgid +#endif +#ifdef __NR_getgid32 +# undef __NR_getgid +# define __NR_getgid __NR_getgid32 +#endif + +libc_hidden_proto(getgid) +_syscall0(gid_t, getgid) +libc_hidden_def(getgid) diff --git a/libc/sysdeps/linux/common/getgroups.c b/libc/sysdeps/linux/common/getgroups.c new file mode 100644 index 0000000..ed02de1 --- /dev/null +++ b/libc/sysdeps/linux/common/getgroups.c @@ -0,0 +1,62 @@ +/* vi: set sw=4 ts=4: */ +/* + * getgroups() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(getgroups) + +#if defined(__NR_getgroups32) +# undef __NR_getgroups +# define __NR_getgroups __NR_getgroups32 +_syscall2(int, getgroups, int, size, gid_t *, list) + +#elif __WORDSIZE == 64 +_syscall2(int, getgroups, int, size, gid_t *, list) + +#else + +libc_hidden_proto(sysconf) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#define __NR___syscall_getgroups __NR_getgroups +static __inline__ _syscall2(int, __syscall_getgroups, + int, size, __kernel_gid_t *, list) + +int getgroups(int size, gid_t groups[]) +{ + if (unlikely(size < 0)) { +ret_error: + __set_errno(EINVAL); + return -1; + } else { + int i, ngids; + __kernel_gid_t *kernel_groups; + + size = MIN(size, sysconf(_SC_NGROUPS_MAX)); + kernel_groups = (__kernel_gid_t *)malloc(sizeof(*kernel_groups) * size); + if (size && kernel_groups == NULL) + goto ret_error; + + ngids = __syscall_getgroups(size, kernel_groups); + if (size != 0 && ngids > 0) { + for (i = 0; i < ngids; i++) { + groups[i] = kernel_groups[i]; + } + } + + free(kernel_groups); + return ngids; + } +} +#endif + +libc_hidden_def(getgroups) diff --git a/libc/sysdeps/linux/common/gethostname.c b/libc/sysdeps/linux/common/gethostname.c new file mode 100644 index 0000000..8fc14ff --- /dev/null +++ b/libc/sysdeps/linux/common/gethostname.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(gethostname) + +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +libc_hidden_proto(uname) + +int +gethostname(char *name, size_t len) +{ + struct utsname uts; + + if (name == NULL) { + __set_errno(EINVAL); + return -1; + } + + if (uname(&uts) == -1) return -1; + + if (strlen(uts.nodename)+1 > len) { + __set_errno(EINVAL); + return -1; + } + strcpy(name, uts.nodename); + return 0; +} +libc_hidden_def(gethostname) diff --git a/libc/sysdeps/linux/common/getitimer.c b/libc/sysdeps/linux/common/getitimer.c new file mode 100644 index 0000000..b324233 --- /dev/null +++ b/libc/sysdeps/linux/common/getitimer.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * getitimer() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, getitimer, __itimer_which_t, which, struct itimerval *, value) diff --git a/libc/sysdeps/linux/common/getpagesize.c b/libc/sysdeps/linux/common/getpagesize.c new file mode 100644 index 0000000..efb5fcb --- /dev/null +++ b/libc/sysdeps/linux/common/getpagesize.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991,1992,1995-1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +extern size_t __pagesize; + +/* Return the system page size. */ +/* couldn't make __getpagesize hidden, because shm.h uses it in a macro */ +extern __typeof(getpagesize) __getpagesize; +int __getpagesize(void) +{ + if (__pagesize != 0) + return __pagesize; + +#ifdef EXEC_PAGESIZE + return EXEC_PAGESIZE; +#else /* No EXEC_PAGESIZE. */ +#ifdef NBPG +#ifndef CLSIZE +#define CLSIZE 1 +#endif /* No CLSIZE. */ + return NBPG * CLSIZE; +#else /* No NBPG. */ + return NBPC; +#endif /* NBPG. */ +#endif /* EXEC_PAGESIZE. */ +} +libc_hidden_proto(getpagesize) +strong_alias(__getpagesize,getpagesize) +libc_hidden_def(getpagesize) diff --git a/libc/sysdeps/linux/common/getpgid.c b/libc/sysdeps/linux/common/getpgid.c new file mode 100644 index 0000000..cf1c0fc --- /dev/null +++ b/libc/sysdeps/linux/common/getpgid.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_UNIX98 +#include + +#define __NR___syscall_getpgid __NR_getpgid +static __inline__ _syscall1(__kernel_pid_t, __syscall_getpgid, __kernel_pid_t, pid) + +pid_t getpgid(pid_t pid) +{ + return (__syscall_getpgid(pid)); +} +#endif diff --git a/libc/sysdeps/linux/common/getpgrp.c b/libc/sysdeps/linux/common/getpgrp.c new file mode 100644 index 0000000..c9de68c --- /dev/null +++ b/libc/sysdeps/linux/common/getpgrp.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpgrp() for uClibc + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_getpgrp +/* According to the manpage the POSIX.1 version is favoured */ +_syscall0(pid_t, getpgrp) +#endif diff --git a/libc/sysdeps/linux/common/getpid.c b/libc/sysdeps/linux/common/getpid.c new file mode 100644 index 0000000..47fc967 --- /dev/null +++ b/libc/sysdeps/linux/common/getpid.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpid() for uClibc + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(getpid) __libc_getpid; +#if defined __NR_getxpid +# define __NR_getpid __NR_getxpid +#endif +#define __NR___libc_getpid __NR_getpid +_syscall0(pid_t, __libc_getpid) +libc_hidden_proto(getpid) +weak_alias(__libc_getpid, getpid) +libc_hidden_weak(getpid) diff --git a/libc/sysdeps/linux/common/getppid.c b/libc/sysdeps/linux/common/getppid.c new file mode 100644 index 0000000..a167750 --- /dev/null +++ b/libc/sysdeps/linux/common/getppid.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * getppid() for uClibc + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#ifdef __NR_getppid +_syscall0(pid_t, getppid) +#else +libc_hidden_proto(getpid) +pid_t getppid(void) +{ + return getpid(); +} +#endif diff --git a/libc/sysdeps/linux/common/getpriority.c b/libc/sysdeps/linux/common/getpriority.c new file mode 100644 index 0000000..089d9b1 --- /dev/null +++ b/libc/sysdeps/linux/common/getpriority.c @@ -0,0 +1,31 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpriority() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(getpriority) + +#define __NR___syscall_getpriority __NR_getpriority +static __inline__ _syscall2(int, __syscall_getpriority, + __priority_which_t, which, id_t, who) + +/* The return value of __syscall_getpriority is biased by this value + * to avoid returning negative values. */ +#define PZERO 20 +int getpriority(__priority_which_t which, id_t who) +{ + int res; + + res = __syscall_getpriority(which, who); + if (res >= 0) + res = PZERO - res; + return res; +} +libc_hidden_def(getpriority) diff --git a/libc/sysdeps/linux/common/getresgid.c b/libc/sysdeps/linux/common/getresgid.c new file mode 100644 index 0000000..425263e --- /dev/null +++ b/libc/sysdeps/linux/common/getresgid.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * getresgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_getresgid32) +# undef __NR_getresgid +# define __NR_getresgid __NR_getresgid32 +_syscall3(int, getresgid, gid_t *, rgid, gid_t *, egid, gid_t *, sgid) + +#elif defined(__NR_getresgid) +# define __NR___syscall_getresgid __NR_getresgid +static __inline__ _syscall3(int, __syscall_getresgid, __kernel_gid_t *, rgid, + __kernel_gid_t *, egid, __kernel_gid_t *, sgid) + +int getresgid(gid_t * rgid, gid_t * egid, gid_t * sgid) +{ + int result; + __kernel_gid_t k_rgid, k_egid, k_sgid; + + result = __syscall_getresgid(&k_rgid, &k_egid, &k_sgid); + if (result == 0) { + *rgid = (gid_t) k_rgid; + *egid = (gid_t) k_egid; + *sgid = (gid_t) k_sgid; + } + return result; +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/getresuid.c b/libc/sysdeps/linux/common/getresuid.c new file mode 100644 index 0000000..87cf6d6 --- /dev/null +++ b/libc/sysdeps/linux/common/getresuid.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * getresuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_getresuid32) +# undef __NR_getresuid +# define __NR_getresuid __NR_getresuid32 +_syscall3(int, getresuid, uid_t *, ruid, uid_t *, euid, uid_t *, suid) + +#elif defined(__NR_getresuid) +# define __NR___syscall_getresuid __NR_getresuid +static __inline__ _syscall3(int, __syscall_getresuid, __kernel_uid_t *, ruid, + __kernel_uid_t *, euid, __kernel_uid_t *, suid) + +int getresuid(uid_t * ruid, uid_t * euid, uid_t * suid) +{ + int result; + __kernel_uid_t k_ruid, k_euid, k_suid; + + result = __syscall_getresuid(&k_ruid, &k_euid, &k_suid); + if (result == 0) { + *ruid = (uid_t) k_ruid; + *euid = (uid_t) k_euid; + *suid = (uid_t) k_suid; + } + return result; +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/getrlimit.c b/libc/sysdeps/linux/common/getrlimit.c new file mode 100644 index 0000000..40b3c73 --- /dev/null +++ b/libc/sysdeps/linux/common/getrlimit.c @@ -0,0 +1,68 @@ +/* vi: set sw=4 ts=4: */ +/* + * getrlimit() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define getrlimit64 __hide_getrlimit64 +#include +#include +#include +#undef getrlimit64 + +libc_hidden_proto(getrlimit) + +/* Only wrap getrlimit if the new ugetrlimit is not present and getrlimit sucks */ + +#if defined __NR_ugetrlimit + +/* just call ugetrlimit() */ +# define __NR___syscall_ugetrlimit __NR_ugetrlimit +static __always_inline +_syscall2(int, __syscall_ugetrlimit, enum __rlimit_resource, resource, + struct rlimit *, rlim) +int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + return (__syscall_ugetrlimit(resource, rlimits)); +} + +#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) + +/* We don't need to wrap getrlimit() */ +_syscall2(int, getrlimit, __rlimit_resource_t, resource, + struct rlimit *, rlim) + +#else + +/* we have to handle old style getrlimit() */ +# define __NR___syscall_getrlimit __NR_getrlimit +static __always_inline +_syscall2(int, __syscall_getrlimit, int, resource, struct rlimit *, rlim) + +int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + int result; + + result = __syscall_getrlimit(resource, rlimits); + + if (result == -1) + return result; + + /* We might have to correct the limits values. Since the old values + * were signed the infinity value is too small. */ + if (rlimits->rlim_cur == RLIM_INFINITY >> 1) + rlimits->rlim_cur = RLIM_INFINITY; + if (rlimits->rlim_max == RLIM_INFINITY >> 1) + rlimits->rlim_max = RLIM_INFINITY; + return result; +} +#endif + +libc_hidden_def(getrlimit) + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 64 +strong_alias(getrlimit, getrlimit64) +#endif diff --git a/libc/sysdeps/linux/common/getrlimit64.c b/libc/sysdeps/linux/common/getrlimit64.c new file mode 100644 index 0000000..ca7aa73 --- /dev/null +++ b/libc/sysdeps/linux/common/getrlimit64.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + +/* the regular getrlimit will work just fine for 64bit users */ + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 32 + +libc_hidden_proto(getrlimit) + +/* Put the soft and hard limits for RESOURCE in *RLIMITS. + Returns 0 if successful, -1 if not (and sets errno). */ +int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits) +{ + struct rlimit rlimits32; + + if (getrlimit (resource, &rlimits32) < 0) + return -1; + + if (rlimits32.rlim_cur == RLIM_INFINITY) + rlimits->rlim_cur = RLIM64_INFINITY; + else + rlimits->rlim_cur = rlimits32.rlim_cur; + if (rlimits32.rlim_max == RLIM_INFINITY) + rlimits->rlim_max = RLIM64_INFINITY; + else + rlimits->rlim_max = rlimits32.rlim_max; + + return 0; +} +#endif diff --git a/libc/sysdeps/linux/common/getrusage.c b/libc/sysdeps/linux/common/getrusage.c new file mode 100644 index 0000000..3e719f2 --- /dev/null +++ b/libc/sysdeps/linux/common/getrusage.c @@ -0,0 +1,13 @@ +/* vi: set sw=4 ts=4: */ +/* + * getrusage() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +_syscall2(int, getrusage, __rusage_who_t, who, struct rusage *, usage) diff --git a/libc/sysdeps/linux/common/getsid.c b/libc/sysdeps/linux/common/getsid.c new file mode 100644 index 0000000..9c011f6 --- /dev/null +++ b/libc/sysdeps/linux/common/getsid.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * getsid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_XOPEN_EXTENDED +libc_hidden_proto(getsid) + +#define __NR___syscall_getsid __NR_getsid +static __inline__ _syscall1(__kernel_pid_t, __syscall_getsid, __kernel_pid_t, pid) + +pid_t getsid(pid_t pid) +{ + return (__syscall_getsid(pid)); +} +libc_hidden_def(getsid) +#endif diff --git a/libc/sysdeps/linux/common/gettimeofday.c b/libc/sysdeps/linux/common/gettimeofday.c new file mode 100644 index 0000000..620eed3 --- /dev/null +++ b/libc/sysdeps/linux/common/gettimeofday.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * gettimeofday() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(gettimeofday) +#ifdef __USE_BSD +_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz) +#else +_syscall2(int, gettimeofday, struct timeval *, tv, void *, tz) +#endif +libc_hidden_def(gettimeofday) diff --git a/libc/sysdeps/linux/common/getuid.c b/libc/sysdeps/linux/common/getuid.c new file mode 100644 index 0000000..07ebf88 --- /dev/null +++ b/libc/sysdeps/linux/common/getuid.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * getuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_getxuid +# undef __NR_getuid +# define __NR_getuid __NR_getxuid +#endif +#ifdef __NR_getuid32 +# undef __NR_getuid +# define __NR_getuid __NR_getuid32 +#endif + +libc_hidden_proto(getuid) +_syscall0(uid_t, getuid) +libc_hidden_def(getuid) diff --git a/libc/sysdeps/linux/common/hp-timing.h b/libc/sysdeps/linux/common/hp-timing.h new file mode 100644 index 0000000..099342d --- /dev/null +++ b/libc/sysdeps/linux/common/hp-timing.h @@ -0,0 +1,83 @@ +/* High precision, low overhead timing functions. Generic version. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + + +/* There are no generic definitions for the times. We could write something + using the `gettimeofday' system call where available but the overhead of + the system call might be too high. + + In case a platform supports timers in the hardware the following macros + and types must be defined: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* Provide dummy definitions. */ +#define HP_TIMING_AVAIL (0) +#define HP_TIMING_INLINE (0) +typedef int hp_timing_t; +#define HP_TIMING_ZERO(Var) +#define HP_TIMING_NOW(var) +#define HP_TIMING_DIFF_INIT() +#define HP_TIMING_DIFF(Diff, Start, End) +#define HP_TIMING_ACCUM(Sum, Diff) +#define HP_TIMING_ACCUM_NT(Sum, Diff) +#define HP_TIMING_PRINT(Buf, Len, Val) + +/* Since this implementation is not available we tell the user about it. */ +#define HP_TIMING_NONAVAIL 1 + +#endif /* hp-timing.h */ diff --git a/libc/sysdeps/linux/common/init_module.c b/libc/sysdeps/linux/common/init_module.c new file mode 100644 index 0000000..8a6e941 --- /dev/null +++ b/libc/sysdeps/linux/common/init_module.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * init_module() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int init_module(void *first, void *second, void *third, void *fourth, void *fifth); +#ifdef __NR_init_module +/* This may have 5 arguments (for old 2.0 kernels) or 2 arguments + * (for 2.2 and 2.4 kernels). Use the greatest common denominator, + * and let the kernel cope with whatever it gets. It's good at that. */ +_syscall5(int, init_module, void *, first, void *, second, void *, third, + void *, fourth, void *, fifth) +#else +int init_module(void *first, void *second, void *third, void *fourth, void *fifth) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + diff --git a/libc/sysdeps/linux/common/inotify.c b/libc/sysdeps/linux/common/inotify.c new file mode 100644 index 0000000..e5a6120 --- /dev/null +++ b/libc/sysdeps/linux/common/inotify.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * inotify interface for uClibc + * + * Copyright (C) 2006 Austin Morgan + * Copyright (C) 2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_inotify_init +_syscall0(int, inotify_init) +#endif + +#ifdef __NR_inotify_add_watch +_syscall3(int, inotify_add_watch, int, fd, const char *, path, uint32_t, mask) +#endif + +#ifdef __NR_inotify_rm_watch +_syscall2(int, inotify_rm_watch, int, fd, uint32_t, wd) +#endif diff --git a/libc/sysdeps/linux/common/ioctl.c b/libc/sysdeps/linux/common/ioctl.c new file mode 100644 index 0000000..51f83a3 --- /dev/null +++ b/libc/sysdeps/linux/common/ioctl.c @@ -0,0 +1,31 @@ +/* vi: set sw=4 ts=4: */ +/* + * ioctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(ioctl) + +#define __NR___syscall_ioctl __NR_ioctl +static __always_inline +_syscall3(int, __syscall_ioctl, int, fd, int, request, void *, arg) + +int ioctl(int fd, unsigned long int request, ...) +{ + void *arg; + va_list list; + + va_start(list, request); + arg = va_arg(list, void *); + va_end(list); + + return __syscall_ioctl(fd, request, arg); +} +libc_hidden_def(ioctl) diff --git a/libc/sysdeps/linux/common/ioperm.c b/libc/sysdeps/linux/common/ioperm.c new file mode 100644 index 0000000..65414fc --- /dev/null +++ b/libc/sysdeps/linux/common/ioperm.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * ioperm() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __ARCH_USE_MMU__ && defined __NR_ioperm +/* psm: can't #include , some archs miss it */ +extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on) __THROW; +_syscall3(int, ioperm, unsigned long, from, unsigned long, num, int, turn_on) +#endif diff --git a/libc/sysdeps/linux/common/iopl.c b/libc/sysdeps/linux/common/iopl.c new file mode 100644 index 0000000..4d9c458 --- /dev/null +++ b/libc/sysdeps/linux/common/iopl.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * iopl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __ARCH_USE_MMU__ && defined __NR_iopl +/* psm: can't #include , some archs miss it */ +extern int iopl(int __level) __THROW; +_syscall1(int, iopl, int, level) +#endif diff --git a/libc/sysdeps/linux/common/kill.c b/libc/sysdeps/linux/common/kill.c new file mode 100644 index 0000000..1ee1cff --- /dev/null +++ b/libc/sysdeps/linux/common/kill.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * kill() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(kill) + +#define __NR___syscall_kill __NR_kill +static __inline__ _syscall2(int, __syscall_kill, __kernel_pid_t, pid, int, sig) + +int kill(pid_t pid, int sig) +{ + return (__syscall_kill(pid, sig)); +} +libc_hidden_def(kill) diff --git a/libc/sysdeps/linux/common/klogctl.c b/libc/sysdeps/linux/common/klogctl.c new file mode 100644 index 0000000..58467df --- /dev/null +++ b/libc/sysdeps/linux/common/klogctl.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * klogctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#define __NR__syslog __NR_syslog +static __inline__ _syscall3(int, _syslog, int, type, char *, buf, int, len) +int klogctl(int type, char *buf, int len) +{ + return (_syslog(type, buf, len)); +} diff --git a/libc/sysdeps/linux/common/lchown.c b/libc/sysdeps/linux/common/lchown.c new file mode 100644 index 0000000..c0f8ce7 --- /dev/null +++ b/libc/sysdeps/linux/common/lchown.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * lchown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_lchown32)) || __WORDSIZE == 64 +# ifdef __NR_lchown32 +# undef __NR_lchown +# define __NR_lchown __NR_lchown32 +# endif + +_syscall3(int, lchown, const char *, path, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_lchown __NR_lchown +static __inline__ _syscall3(int, __syscall_lchown, const char *, path, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int lchown(const char *path, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return __syscall_lchown(path, owner, group); +} + +#endif diff --git a/libc/sysdeps/linux/common/link.c b/libc/sysdeps/linux/common/link.c new file mode 100644 index 0000000..b5e5536 --- /dev/null +++ b/libc/sysdeps/linux/common/link.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * link() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, link, const char *, oldpath, const char *, newpath) diff --git a/libc/sysdeps/linux/common/llseek.c b/libc/sysdeps/linux/common/llseek.c new file mode 100644 index 0000000..4761b33 --- /dev/null +++ b/libc/sysdeps/linux/common/llseek.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* + * llseek/lseek64 syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern __typeof(lseek64) __libc_lseek64; + +#if defined __NR__llseek && defined __UCLIBC_HAS_LFS__ + +# ifndef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) __syscall_llseek (args) +# define __NR___syscall_llseek __NR__llseek +static __inline__ _syscall5(int, __syscall_llseek, int, fd, off_t, offset_hi, + off_t, offset_lo, loff_t *, result, int, whence) +# endif + +loff_t __libc_lseek64(int fd, loff_t offset, int whence) +{ + loff_t result; + return(loff_t)(INLINE_SYSCALL (_llseek, 5, fd, (off_t) (offset >> 32), + (off_t) (offset & 0xffffffff), &result, whence) ?: result); +} +#else +extern __typeof(lseek) __libc_lseek; +libc_hidden_proto(__libc_lseek) + +loff_t __libc_lseek64(int fd, loff_t offset, int whence) +{ + return(loff_t)(__libc_lseek(fd, (off_t) (offset), whence)); +} +#endif +libc_hidden_proto(lseek64) +weak_alias(__libc_lseek64,lseek64) +libc_hidden_weak(lseek64) +/*strong_alias(__libc_lseek64,_llseek) */ diff --git a/libc/sysdeps/linux/common/longjmp.c b/libc/sysdeps/linux/common/longjmp.c new file mode 100644 index 0000000..a54f01f --- /dev/null +++ b/libc/sysdeps/linux/common/longjmp.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1991, 92, 94, 95, 97, 98, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(sigprocmask) + +extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; +libc_hidden_proto(__longjmp) + +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +/* Set the signal mask to the one specified in ENV, and jump + to the position specified in ENV, causing the setjmp + call there to return VAL, or 1 if VAL is 0. */ +void __libc_longjmp (sigjmp_buf env, int val) +{ +#if 0 + /* Perform any cleanups needed by the frames being unwound. */ + _longjmp_unwind (env, val); +#endif + + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask, + (sigset_t *) NULL); + + /* Call the machine-dependent function to restore machine state. */ + __longjmp (env[0].__jmpbuf, val ?: 1); +} + +weak_alias(__libc_longjmp,longjmp) +weak_alias(__libc_longjmp,siglongjmp) +strong_alias(__libc_longjmp,__libc_siglongjmp) +strong_alias(__libc_longjmp,_longjmp) diff --git a/libc/sysdeps/linux/common/lseek.c b/libc/sysdeps/linux/common/lseek.c new file mode 100644 index 0000000..61675cf --- /dev/null +++ b/libc/sysdeps/linux/common/lseek.c @@ -0,0 +1,31 @@ +/* vi: set sw=4 ts=4: */ +/* + * lseek() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(lseek) __libc_lseek; +libc_hidden_proto(__libc_lseek) + +#ifdef __NR_lseek +#define __NR___libc_lseek __NR_lseek +_syscall3(__off_t, __libc_lseek, int, fildes, __off_t, offset, int, whence) +#else +extern __typeof(lseek64) __libc_lseek64; +libc_hidden_proto(__libc_lseek64) +__off_t __libc_lseek(int fildes, __off_t offset, int whence) +{ + return __libc_lseek64(fildes, offset, whence); +} +#endif +libc_hidden_def(__libc_lseek) + +libc_hidden_proto(lseek) +weak_alias(__libc_lseek,lseek) +libc_hidden_weak(lseek) diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c new file mode 100644 index 0000000..4c67c19 --- /dev/null +++ b/libc/sysdeps/linux/common/lstat.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * lstat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* need to hide the 64bit prototype or the strong_alias() + * will fail when __NR_lstat64 doesnt exist */ +#define lstat64 __hidelstat64 + +#include +#include +#include +#include "xstatconv.h" + +#undef lstat64 + +libc_hidden_proto(lstat) + +#define __NR___syscall_lstat __NR_lstat +static __inline__ _syscall2(int, __syscall_lstat, + const char *, file_name, struct kernel_stat *, buf) + +int lstat(const char *file_name, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_lstat(file_name, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(lstat) + +#if ! defined __NR_lstat64 && defined __UCLIBC_HAS_LFS__ +extern __typeof(lstat) lstat64; +libc_hidden_proto(lstat64) +strong_alias(lstat,lstat64) +libc_hidden_def(lstat64) +#endif diff --git a/libc/sysdeps/linux/common/lstat64.c b/libc/sysdeps/linux/common/lstat64.c new file mode 100644 index 0000000..97e9528 --- /dev/null +++ b/libc/sysdeps/linux/common/lstat64.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * lstat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_lstat64 +# include +# include +# include "xstatconv.h" + +libc_hidden_proto(lstat64) + +# define __NR___syscall_lstat64 __NR_lstat64 +static __inline__ _syscall2(int, __syscall_lstat64, const char *, file_name, + struct kernel_stat64 *, buf) + +int lstat64(const char *file_name, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_lstat64(file_name, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(lstat64) + +#endif diff --git a/libc/sysdeps/linux/common/madvise.c b/libc/sysdeps/linux/common/madvise.c new file mode 100644 index 0000000..e953d7b --- /dev/null +++ b/libc/sysdeps/linux/common/madvise.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * madvise() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __NR_madvise && defined __USE_BSD +_syscall3(int, madvise, void *, __addr, size_t, __len, int, __advice) +#endif diff --git a/libc/sysdeps/linux/common/mincore.c b/libc/sysdeps/linux/common/mincore.c new file mode 100644 index 0000000..f1f3557 --- /dev/null +++ b/libc/sysdeps/linux/common/mincore.c @@ -0,0 +1,15 @@ +/* + * This file provides the mincore() system call to uClibc. + * Copyright (C) 20041215 - + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __NR_mincore && (defined __USE_BSD || defined __USE_SVID) +#include +#include +_syscall3(int, mincore, void *, start, size_t, length, unsigned char *, vec) +#endif diff --git a/libc/sysdeps/linux/common/mkdir.c b/libc/sysdeps/linux/common/mkdir.c new file mode 100644 index 0000000..8591c49 --- /dev/null +++ b/libc/sysdeps/linux/common/mkdir.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * mkdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(mkdir) + +#define __NR___syscall_mkdir __NR_mkdir +static __inline__ _syscall2(int, __syscall_mkdir, const char *, pathname, + __kernel_mode_t, mode) + +int mkdir(const char *pathname, mode_t mode) +{ + return (__syscall_mkdir(pathname, mode)); +} +libc_hidden_def(mkdir) diff --git a/libc/sysdeps/linux/common/mkfifo.c b/libc/sysdeps/linux/common/mkfifo.c new file mode 100644 index 0000000..cbde71e --- /dev/null +++ b/libc/sysdeps/linux/common/mkfifo.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(mknod) + +/* Create a named pipe (FIFO) named PATH with protections MODE. */ +int +mkfifo (const char *path, mode_t mode) +{ + return mknod (path, mode | S_IFIFO, 0); +} diff --git a/libc/sysdeps/linux/common/mknod.c b/libc/sysdeps/linux/common/mknod.c new file mode 100644 index 0000000..b0f07b1 --- /dev/null +++ b/libc/sysdeps/linux/common/mknod.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * mknod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(mknod) + +#define __NR___syscall_mknod __NR_mknod +static __inline__ _syscall3(int, __syscall_mknod, const char *, path, + __kernel_mode_t, mode, __kernel_dev_t, dev) + +int mknod(const char *path, mode_t mode, dev_t dev) +{ + /* We must convert the dev_t value to a __kernel_dev_t */ + __kernel_dev_t k_dev; + + k_dev = ((major(dev) & 0xff) << 8) | (minor(dev) & 0xff); + return __syscall_mknod(path, mode, k_dev); +} +libc_hidden_def(mknod) diff --git a/libc/sysdeps/linux/common/mlock.c b/libc/sysdeps/linux/common/mlock.c new file mode 100644 index 0000000..12120d8 --- /dev/null +++ b/libc/sysdeps/linux/common/mlock.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mlock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_mlock +_syscall2(int, mlock, const void *, addr, size_t, len) +#endif diff --git a/libc/sysdeps/linux/common/mlockall.c b/libc/sysdeps/linux/common/mlockall.c new file mode 100644 index 0000000..99f7201 --- /dev/null +++ b/libc/sysdeps/linux/common/mlockall.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mlockall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_mlockall +_syscall1(int, mlockall, int, flags) +#endif diff --git a/libc/sysdeps/linux/common/mmap.c b/libc/sysdeps/linux/common/mmap.c new file mode 100644 index 0000000..af9685a --- /dev/null +++ b/libc/sysdeps/linux/common/mmap.c @@ -0,0 +1,73 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#ifdef __NR_mmap + +libc_hidden_proto(mmap) + +#ifdef __UCLIBC_MMAP_HAS_6_ARGS__ + +_syscall6(void *, mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset) + +#else + +# define __NR__mmap __NR_mmap +static __inline__ _syscall1(__ptr_t, _mmap, unsigned long *, buffer) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) len; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (__ptr_t) _mmap(buffer); +} + +#endif + +libc_hidden_def(mmap) + +#elif defined(__NR_mmap2) + +libc_hidden_proto(mmap) + +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + return __syscall_mmap2(addr, len, prot, flags, fd, offset >> MMAP2_PAGE_SHIFT); +} + +libc_hidden_def(mmap) + +#endif diff --git a/libc/sysdeps/linux/common/mmap64.c b/libc/sysdeps/linux/common/mmap64.c new file mode 100644 index 0000000..3abfd56 --- /dev/null +++ b/libc/sysdeps/linux/common/mmap64.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Massivly hacked up for uClibc by Erik Andersen */ + +#include <_lfs_64.h> + +#ifdef __UCLIBC_HAS_LFS__ + +#include +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +# if !defined __NR_mmap2 || !defined _syscall6 + +/* + * This version is a stub that just chops off everything at the mmap 32 bit + * mmap() address space... You will probably need to add in an arch specific + * implementation to override this as there is not a generic way for me to + * implement this particular syscall if your arch lacks _syscall6... + * + */ + +__ptr_t mmap64(__ptr_t addr, size_t len, int prot, int flags, int fd, __off64_t offset) +{ + if (offset != (off_t) offset || + (offset + len) != (off_t) (offset + len)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + return mmap(addr, len, prot, flags, fd, (off_t) offset); +} + +# else + +# define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, + off_t, offset) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap64(__ptr_t addr, size_t len, int prot, int flags, int fd, __off64_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + +# ifdef __USE_FILE_OFFSET64 + return __syscall_mmap2(addr, len, prot, flags, + fd, ((__u_quad_t) offset >> MMAP2_PAGE_SHIFT)); +# else + return __syscall_mmap2(addr, len, prot, flags, + fd, ((__u_long) offset >> MMAP2_PAGE_SHIFT)); +# endif +} + +# endif +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/modify_ldt.c b/libc/sysdeps/linux/common/modify_ldt.c new file mode 100644 index 0000000..d70bd40 --- /dev/null +++ b/libc/sysdeps/linux/common/modify_ldt.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * modify_ldt() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +int modify_ldt (int func, void *ptr, unsigned long bytecount); +#ifdef __NR_modify_ldt +_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) +#endif diff --git a/libc/sysdeps/linux/common/mount.c b/libc/sysdeps/linux/common/mount.c new file mode 100644 index 0000000..39e5db1 --- /dev/null +++ b/libc/sysdeps/linux/common/mount.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mount() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall5(int, mount, const char *, specialfile, const char *, dir, + const char *, filesystemtype, unsigned long, rwflag, + const void *, data) diff --git a/libc/sysdeps/linux/common/mprotect.c b/libc/sysdeps/linux/common/mprotect.c new file mode 100644 index 0000000..a0e7610 --- /dev/null +++ b/libc/sysdeps/linux/common/mprotect.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * mprotect() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __ARCH_USE_MMU__ && defined __NR_mprotect +_syscall3(int, mprotect, void *, addr, size_t, len, int, prot) +#endif diff --git a/libc/sysdeps/linux/common/mremap.c b/libc/sysdeps/linux/common/mremap.c new file mode 100644 index 0000000..e7c1caa --- /dev/null +++ b/libc/sysdeps/linux/common/mremap.c @@ -0,0 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * mremap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mremap + +#define mremap _hidemremap +#include +#undef mremap + +void *mremap(void *, size_t, size_t, int, void *); + +libc_hidden_proto(mremap) +_syscall5(void *, mremap, void *, old_address, size_t, old_size, size_t, + new_size, int, may_move, void *, new_address) +libc_hidden_def(mremap) + +#endif diff --git a/libc/sysdeps/linux/common/msync.c b/libc/sysdeps/linux/common/msync.c new file mode 100644 index 0000000..0b33fb6 --- /dev/null +++ b/libc/sysdeps/linux/common/msync.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * msync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_msync && defined __ARCH_USE_MMU__ + +#include + +extern __typeof(msync) __libc_msync; +#define __NR___libc_msync __NR_msync +_syscall3(int, __libc_msync, void *, addr, size_t, length, int, flags) +weak_alias(__libc_msync,msync) + +#endif diff --git a/libc/sysdeps/linux/common/munlock.c b/libc/sysdeps/linux/common/munlock.c new file mode 100644 index 0000000..07f9376 --- /dev/null +++ b/libc/sysdeps/linux/common/munlock.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * munlock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_munlock +_syscall2(int, munlock, const void *, addr, size_t, len) +#endif diff --git a/libc/sysdeps/linux/common/munlockall.c b/libc/sysdeps/linux/common/munlockall.c new file mode 100644 index 0000000..cc15264 --- /dev/null +++ b/libc/sysdeps/linux/common/munlockall.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * munlockall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __NR_munlockall && defined __ARCH_USE_MMU__ +#include + +_syscall0(int, munlockall) +#endif diff --git a/libc/sysdeps/linux/common/munmap.c b/libc/sysdeps/linux/common/munmap.c new file mode 100644 index 0000000..81a65fb --- /dev/null +++ b/libc/sysdeps/linux/common/munmap.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * munmap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(munmap) + +_syscall2(int, munmap, void *, start, size_t, length) +libc_hidden_def(munmap) diff --git a/libc/sysdeps/linux/common/nanosleep.c b/libc/sysdeps/linux/common/nanosleep.c new file mode 100644 index 0000000..30a27dc --- /dev/null +++ b/libc/sysdeps/linux/common/nanosleep.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * nanosleep() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __USE_POSIX199309 && defined __NR_nanosleep + +extern __typeof(nanosleep) __libc_nanosleep; +#define __NR___libc_nanosleep __NR_nanosleep +_syscall2(int, __libc_nanosleep, const struct timespec *, req, + struct timespec *, rem) +libc_hidden_proto(nanosleep) +weak_alias(__libc_nanosleep,nanosleep) +libc_hidden_weak(nanosleep) +#endif diff --git a/libc/sysdeps/linux/common/nice.c b/libc/sysdeps/linux/common/nice.c new file mode 100644 index 0000000..86765a9 --- /dev/null +++ b/libc/sysdeps/linux/common/nice.c @@ -0,0 +1,77 @@ +/* vi: set sw=4 ts=4: */ +/* + * nice() for uClibc + * + * Copyright (C) 2005 by Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(getpriority) + +#ifdef __NR_nice + +# define __NR___syscall_nice __NR_nice +static __inline__ _syscall1(int, __syscall_nice, int, incr) + +#else + +# include + +libc_hidden_proto(setpriority) + +static __inline__ int int_add_no_wrap(int a, int b) +{ + int s = a + b; + + if (b < 0) { + if (s > a) s = INT_MIN; + } else { + if (s < a) s = INT_MAX; + } + + return s; +} + +static __inline__ int __syscall_nice(int incr) +{ + int old_priority; +# if 1 + /* This should never fail. */ + old_priority = getpriority(PRIO_PROCESS, 0); +# else + /* But if you want to be paranoid... */ + int old_errno; + + old_errno = errno; + __set_errno(0); + old_priority = getpriority(PRIO_PROCESS, 0); + if ((old_priority == -1) && errno) { + return -1; + } + __set_errno(old_errno); +# endif + + if (setpriority(PRIO_PROCESS, 0, int_add_no_wrap(old_priority, incr))) { + __set_errno(EPERM); /* SUSv3 mandates EPERM for nice failure. */ + return -1; + } + + return 0; +} + +#endif + +int nice(int incr) +{ + if (__syscall_nice(incr)) { + return -1; + } + + return getpriority(PRIO_PROCESS, 0); +} diff --git a/libc/sysdeps/linux/common/noophooks.c b/libc/sysdeps/linux/common/noophooks.c new file mode 100644 index 0000000..a6c9d76 --- /dev/null +++ b/libc/sysdeps/linux/common/noophooks.c @@ -0,0 +1,29 @@ +/* Noop hooks for the instrumenting functions. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +void +__cyg_profile_func_enter (attribute_unused void *this_fn, attribute_unused void *call_site); +void +__cyg_profile_func_enter (attribute_unused void *this_fn, attribute_unused void *call_site) +{ +} +strong_alias (__cyg_profile_func_enter, __cyg_profile_func_exit) diff --git a/libc/sysdeps/linux/common/ntp_gettime.c b/libc/sysdeps/linux/common/ntp_gettime.c new file mode 100644 index 0000000..f32e054 --- /dev/null +++ b/libc/sysdeps/linux/common/ntp_gettime.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libc_hidden_proto(adjtimex) + +int ntp_gettime(struct ntptimeval *ntv) +{ + struct timex tntx; + int result; + + tntx.modes = 0; + result = adjtimex(&tntx); + ntv->time = tntx.time; + ntv->maxerror = tntx.maxerror; + ntv->esterror = tntx.esterror; + return result; +} diff --git a/libc/sysdeps/linux/common/open.c b/libc/sysdeps/linux/common/open.c new file mode 100644 index 0000000..f9b10d8 --- /dev/null +++ b/libc/sysdeps/linux/common/open.c @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: */ +/* + * open() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +extern __typeof(open) __libc_open; +extern __typeof(creat) __libc_creat; + +#define __NR___syscall_open __NR_open +static __inline__ _syscall3(int, __syscall_open, const char *, file, + int, flags, __kernel_mode_t, mode) + +libc_hidden_proto(__libc_open) +int __libc_open(const char *file, int oflag, ...) +{ + mode_t mode = 0; + + if (oflag & O_CREAT) { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, mode_t); + va_end (arg); + } + + return __syscall_open(file, oflag, mode); +} +libc_hidden_def(__libc_open) + +libc_hidden_proto(open) +weak_alias(__libc_open,open) +libc_hidden_weak(open) + +int __libc_creat(const char *file, mode_t mode) +{ + return __libc_open(file, O_WRONLY | O_CREAT | O_TRUNC, mode); +} +weak_alias(__libc_creat,creat) diff --git a/libc/sysdeps/linux/common/open64.c b/libc/sysdeps/linux/common/open64.c new file mode 100644 index 0000000..1c40b3e --- /dev/null +++ b/libc/sysdeps/linux/common/open64.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#ifndef O_LARGEFILE +# define O_LARGEFILE 0100000 +#endif + +extern __typeof(open64) __libc_open64; +extern __typeof(open) __libc_open; +libc_hidden_proto(__libc_open) + +/* Open FILE with access OFLAG. If OFLAG includes O_CREAT, + a third argument is the file protection. */ +libc_hidden_proto(__libc_open64) +int __libc_open64 (const char *file, int oflag, ...) +{ + mode_t mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, mode_t); + va_end (arg); + } + + return __libc_open(file, oflag | O_LARGEFILE, mode); +} +libc_hidden_def(__libc_open64) + +libc_hidden_proto(open64) +weak_alias(__libc_open64,open64) +libc_hidden_weak(open64) +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/pause.c b/libc/sysdeps/linux/common/pause.c new file mode 100644 index 0000000..877717a --- /dev/null +++ b/libc/sysdeps/linux/common/pause.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * pause() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +extern __typeof(pause) __libc_pause; +#ifdef __NR_pause +#define __NR___libc_pause __NR_pause +_syscall0(int, __libc_pause) +#else +#include +libc_hidden_proto(__sigpause) +libc_hidden_proto(sigblock) + +int __libc_pause(void) +{ + return (__sigpause(sigblock(0), 0)); +} +#endif +weak_alias(__libc_pause,pause) diff --git a/libc/sysdeps/linux/common/personality.c b/libc/sysdeps/linux/common/personality.c new file mode 100644 index 0000000..fa304de --- /dev/null +++ b/libc/sysdeps/linux/common/personality.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * personality() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, personality, unsigned long int, __persona) diff --git a/libc/sysdeps/linux/common/pipe.c b/libc/sysdeps/linux/common/pipe.c new file mode 100644 index 0000000..fa0c211 --- /dev/null +++ b/libc/sysdeps/linux/common/pipe.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * pipe() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(pipe) + +_syscall1(int, pipe, int *, filedes) +libc_hidden_def(pipe) diff --git a/libc/sysdeps/linux/common/pivot_root.c b/libc/sysdeps/linux/common/pivot_root.c new file mode 100644 index 0000000..3e97059 --- /dev/null +++ b/libc/sysdeps/linux/common/pivot_root.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * pivot_root() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +int pivot_root(const char *new_root, const char *put_old); +#ifdef __NR_pivot_root +_syscall2(int, pivot_root, const char *, new_root, const char *, put_old) +#else +int pivot_root(const char *new_root, const char *put_old) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/poll.c b/libc/sysdeps/linux/common/poll.c new file mode 100644 index 0000000..256581c --- /dev/null +++ b/libc/sysdeps/linux/common/poll.c @@ -0,0 +1,234 @@ +/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +extern __typeof(poll) __libc_poll; + +#ifdef __NR_poll + +# define __NR___libc_poll __NR_poll +_syscall3(int, __libc_poll, struct pollfd *, fds, + unsigned long int, nfds, int, timeout) + +#elif defined(__NR_ppoll) && defined __UCLIBC_LINUX_SPECIFIC__ + +libc_hidden_proto(ppoll) +int __libc_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + struct timespec *ts = NULL, tval; + if (timeout > 0) { + tval.tv_sec = timeout / 1000; + tval.tv_nsec = (timeout % 1000) * 1000000; + ts = &tval; + } else if (timeout == 0) { + tval.tv_sec = 0; + tval.tv_nsec = 0; + ts = &tval; + } + return ppoll(fds, nfds, ts, NULL); +} + +#else +/* ugh, this arch lacks poll, so we need to emulate this crap ... */ + +#include +#include +#include +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +libc_hidden_proto(getdtablesize) +libc_hidden_proto(select) + +/* uClinux 2.0 doesn't have poll, emulate it using select */ + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +int __libc_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + static int max_fd_size; + struct timeval tv; + fd_set *rset, *wset, *xset; + struct pollfd *f; + int ready; + int maxfd = 0; + int bytes; + + if (!max_fd_size) + max_fd_size = getdtablesize (); + + bytes = howmany (max_fd_size, __NFDBITS); + rset = alloca (bytes); + wset = alloca (bytes); + xset = alloca (bytes); + + /* We can't call FD_ZERO, since FD_ZERO only works with sets + of exactly __FD_SETSIZE size. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); + + for (f = fds; f < &fds[nfds]; ++f) + { + f->revents = 0; + if (f->fd >= 0) + { + if (f->fd >= max_fd_size) + { + /* The user provides a file descriptor number which is higher + than the maximum we got from the `getdtablesize' call. + Maybe this is ok so enlarge the arrays. */ + fd_set *nrset, *nwset, *nxset; + int nbytes; + + max_fd_size = roundup (f->fd, __NFDBITS); + nbytes = howmany (max_fd_size, __NFDBITS); + + nrset = alloca (nbytes); + nwset = alloca (nbytes); + nxset = alloca (nbytes); + + memset ((char *) nrset + bytes, 0, nbytes - bytes); + memset ((char *) nwset + bytes, 0, nbytes - bytes); + memset ((char *) nxset + bytes, 0, nbytes - bytes); + + rset = memcpy (nrset, rset, bytes); + wset = memcpy (nwset, wset, bytes); + xset = memcpy (nxset, xset, bytes); + + bytes = nbytes; + } + + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + } + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + while (1) + { + ready = select (maxfd + 1, rset, wset, xset, + timeout == -1 ? NULL : &tv); + + /* It might be that one or more of the file descriptors is invalid. + We now try to find and mark them and then try again. */ + if (ready == -1 && errno == EBADF) + { + fd_set *sngl_rset = alloca (bytes); + fd_set *sngl_wset = alloca (bytes); + fd_set *sngl_xset = alloca (bytes); + struct timeval sngl_tv; + + /* Clear the original set. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); + + /* This means we don't wait for input. */ + sngl_tv.tv_sec = 0; + sngl_tv.tv_usec = 0; + + maxfd = -1; + + /* Reset the return value. */ + ready = 0; + + for (f = fds; f < &fds[nfds]; ++f) + if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) + && (f->revents & POLLNVAL) == 0) + { + int n; + + memset (sngl_rset, 0, bytes); + memset (sngl_wset, 0, bytes); + memset (sngl_xset, 0, bytes); + + if (f->events & POLLIN) + FD_SET (f->fd, sngl_rset); + if (f->events & POLLOUT) + FD_SET (f->fd, sngl_wset); + if (f->events & POLLPRI) + FD_SET (f->fd, sngl_xset); + + n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, + &sngl_tv); + if (n != -1) + { + /* This descriptor is ok. */ + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd) + maxfd = f->fd; + if (n > 0) + /* Count it as being available. */ + ++ready; + } + else if (errno == EBADF) + f->revents |= POLLNVAL; + } + /* Try again. */ + continue; + } + + break; + } + + if (ready > 0) + for (f = fds; f < &fds[nfds]; ++f) + { + if (f->fd >= 0) + { + if (FD_ISSET (f->fd, rset)) + f->revents |= POLLIN; + if (FD_ISSET (f->fd, wset)) + f->revents |= POLLOUT; + if (FD_ISSET (f->fd, xset)) + f->revents |= POLLPRI; + } + } + + return ready; +} + +#endif +libc_hidden_proto(poll) +weak_alias(__libc_poll,poll) +libc_hidden_weak(poll) diff --git a/libc/sysdeps/linux/common/posix_fadvise.c b/libc/sysdeps/linux/common/posix_fadvise.c new file mode 100644 index 0000000..a3f9c76 --- /dev/null +++ b/libc/sysdeps/linux/common/posix_fadvise.c @@ -0,0 +1,62 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* need to hide the 64bit prototype or the strong_alias() + * will fail when __NR_fadvise64_64 doesnt exist */ +#define posix_fadvise64 __hideposix_fadvise64 + +#include +#include + +#undef posix_fadvise64 + +#ifdef __NR_fadvise64 +#define __NR_posix_fadvise __NR_fadvise64 +/* get rid of following conditional when + all supported arches are having INTERNAL_SYSCALL defined +*/ +#ifdef INTERNAL_SYSCALL +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ + INTERNAL_SYSCALL_DECL(err); + int ret = (int) (INTERNAL_SYSCALL(posix_fadvise, err, 5, fd, + __LONG_LONG_PAIR (offset >> 31, offset), len, advice)); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} +#else +static __inline__ int syscall_posix_fadvise(int fd, off_t offset1, off_t offset2, off_t len, int advice); +#define __NR_syscall_posix_fadvise __NR_fadvise64 +_syscall5(int, syscall_posix_fadvise, int, fd, off_t, offset1, + off_t, offset2, off_t, len, int, advice) + +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ + int ret = syscall_posix_fadvise(fd, __LONG_LONG_PAIR (offset >> 31, offset), len, advice); + if (ret == -1) + return errno; + return ret; +} + +#endif + +#if defined __UCLIBC_HAS_LFS__ && (!defined __NR_fadvise64_64 || !defined _syscall6) +extern __typeof(posix_fadvise) posix_fadvise64; +strong_alias(posix_fadvise,posix_fadvise64) +#endif + +#else +int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif diff --git a/libc/sysdeps/linux/common/posix_fadvise64.c b/libc/sysdeps/linux/common/posix_fadvise64.c new file mode 100644 index 0000000..6b1325d --- /dev/null +++ b/libc/sysdeps/linux/common/posix_fadvise64.c @@ -0,0 +1,105 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +#ifdef __NR_fadvise64_64 + +/* 64 bit implementation is cake ... or more like pie ... */ +#if __WORDSIZE == 64 + +#define __NR_posix_fadvise64 __NR_fadvise64_64 + +#if defined INTERNAL_SYSCALL && ! defined __TARGET_powerpc__ +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + if (len != (off_t) len) + return EOVERFLOW; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (posix_fadvise64, err, 5, fd, + __LONG_LONG_PAIR ((long) (offset >> 32), + (long) offset), + (off_t) len, advice); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} +#else +static __inline__ int syscall_posix_fadvise(int fd, off_t offset1, off_t offset2, off_t len, int advice); +#define __NR_syscall_posix_fadvise64 __NR_posix_fadvise64 +_syscall4(int, syscall_posix_fadvise64, int, fd, __off64_t, offset, + __off64_t, len, int, advice) +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + int ret = syscall_posix_fadvise64(fd, offset, len, advice); + if (ret == -1) + return errno; + return ret; +} +#endif + +/* 32 bit implementation is kind of a pita */ +#elif __WORDSIZE == 32 + +#if defined INTERNAL_SYSCALL && ! defined __TARGET_powerpc__ +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, + __LONG_LONG_PAIR(offset >> 32, offset & 0xffffffff), + __LONG_LONG_PAIR(len >> 32, len & 0xffffffff), + advice); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} +#elif defined _syscall6 /* workaround until everyone has _syscall6() */ +#define __NR___syscall_fadvise64_64 __NR_fadvise64_64 +static __inline__ _syscall6(int, __syscall_fadvise64_64, int, fd, + unsigned long, high_offset, unsigned long, low_offset, + unsigned long, high_len, unsigned long, low_len, + int, advice) +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + int ret = __syscall_fadvise64_64(fd, + __LONG_LONG_PAIR(offset >> 32, offset & 0xffffffff), + __LONG_LONG_PAIR(len >> 32, len & 0xffffffff), + advice); + if (ret == -1) + return errno; + return ret; +} +#else +#warning neither INTERNAL_SYSCALL nor _syscall6 has been defined for your machine :( +#endif /* INTERNAL_SYSCALL */ + +#else +#error your machine is neither 32 bit or 64 bit ... it must be magical +#endif + +#elif !defined __NR_fadvise64 +/* This is declared as a strong alias in posix_fadvise.c if __NR_fadvise64 + * is defined. + */ +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif /* __NR_fadvise64_64 */ +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c new file mode 100644 index 0000000..a203c0c --- /dev/null +++ b/libc/sysdeps/linux/common/ppoll.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2006. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__ + +libc_hidden_proto(ppoll) + +# define __NR___libc_ppoll __NR_ppoll +static __always_inline +_syscall4(int, __libc_ppoll, struct pollfd *, fds, + nfds_t, nfds, const struct timespec *, timeout, + const __sigset_t *, sigmask) + +int +ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, + const __sigset_t *sigmask) +{ + /* The Linux kernel can in some situations update the timeout value. + We do not want that so use a local variable. */ + struct timespec tval; + if (timeout != NULL) + { + tval = *timeout; + timeout = &tval; + } + + return __libc_ppoll(fds, nfds, timeout, sigmask); +} +libc_hidden_def(ppoll) + +#endif diff --git a/libc/sysdeps/linux/common/prctl.c b/libc/sysdeps/linux/common/prctl.c new file mode 100644 index 0000000..a6764c5 --- /dev/null +++ b/libc/sysdeps/linux/common/prctl.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * prctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +/* psm: including sys/prctl.h would depend on kernel headers */ + +#ifdef __NR_prctl +extern int prctl (int, long, long, long, long); +_syscall5(int, prctl, int, option, long, arg2, long, arg3, long, arg4, long, arg5) +#endif diff --git a/libc/sysdeps/linux/common/pread_write.c b/libc/sysdeps/linux/common/pread_write.c new file mode 100644 index 0000000..eb96c3e --- /dev/null +++ b/libc/sysdeps/linux/common/pread_write.c @@ -0,0 +1,191 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + +#ifdef __NR_pread + +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __syscall_pread(fd, buf, count, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pread(fd, buf, count, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* __NR_pread */ + +#ifdef __NR_pwrite + +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return __syscall_pwrite(fd, buf, count, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pwrite(fd, buf, count, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + +#if ! defined __NR_pread || ! defined __NR_pwrite +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(lseek) + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lseek64) + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64(fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __fake_pread_write(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + /* we won't actually be modifying the buffer, + *just cast it to get rid of warnings */ + return __fake_pread_write(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c new file mode 100644 index 0000000..3a958fc --- /dev/null +++ b/libc/sysdeps/linux/common/pselect.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For NULL. */ +#include +#include + +extern __typeof(pselect) __libc_pselect; + +libc_hidden_proto(sigprocmask) +libc_hidden_proto(select) + + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Additionally set the sigmask + SIGMASK for this call. Returns the number of ready descriptors, or -1 for + errors. */ +int +__libc_pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + struct timeval tval; + int retval; + sigset_t savemask; + + /* Change nanosecond number to microseconds. This might mean losing + precision and therefore the `pselect` should be available. But + for now it is hardly found. */ + if (timeout != NULL) + TIMESPEC_TO_TIMEVAL (&tval, timeout); + + /* The setting and restoring of the signal mask and the select call + should be an atomic operation. This can't be done without kernel + help. */ + if (sigmask != NULL) + sigprocmask (SIG_SETMASK, sigmask, &savemask); + + /* Note the pselect() is a cancellation point. But since we call + select() which itself is a cancellation point we do not have + to do anything here. */ + retval = select (nfds, readfds, writefds, exceptfds, + timeout != NULL ? &tval : NULL); + + if (sigmask != NULL) + sigprocmask (SIG_SETMASK, &savemask, NULL); + + return retval; +} +weak_alias(__libc_pselect,pselect) diff --git a/libc/sysdeps/linux/common/ptrace.c b/libc/sysdeps/linux/common/ptrace.c new file mode 100644 index 0000000..8b8ebf0 --- /dev/null +++ b/libc/sysdeps/linux/common/ptrace.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __NR_ptrace && defined __USE_BSD && defined __USE_MISC +#define __NR___syscall_ptrace __NR_ptrace + +static __inline__ _syscall4(long, __syscall_ptrace, enum __ptrace_request, request, + __kernel_pid_t, pid, void*, addr, void*, data) + +long int +ptrace (enum __ptrace_request request, ...) +{ + long int res, ret; + va_list ap; + pid_t pid; + void *addr, *data; + + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, void *); + va_end (ap); + + if (request > 0 && request < 4) + data = &ret; + + res = __syscall_ptrace(request, pid, addr, data); + if (res >= 0 && request > 0 && request < 4) { + __set_errno(0); + return ret; + } + + return res; +} +#endif diff --git a/libc/sysdeps/linux/common/query_module.c b/libc/sysdeps/linux/common/query_module.c new file mode 100644 index 0000000..0f3d470 --- /dev/null +++ b/libc/sysdeps/linux/common/query_module.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * query_module() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int query_module(const char *name attribute_unused, int which attribute_unused, + void *buf attribute_unused, size_t bufsize attribute_unused, size_t * ret attribute_unused); +#ifdef __NR_query_module +_syscall5(int, query_module, const char *, name, int, which, + void *, buf, size_t, bufsize, size_t *, ret) +#elif defined __UCLIBC_HAS_STUBS__ +int query_module(const char *name attribute_unused, int which attribute_unused, + void *buf attribute_unused, size_t bufsize attribute_unused, size_t * ret attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/quotactl.c b/libc/sysdeps/linux/common/quotactl.c new file mode 100644 index 0000000..edd5092 --- /dev/null +++ b/libc/sysdeps/linux/common/quotactl.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * quotactl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_BSD +#include +_syscall4(int, quotactl, int, cmd, const char *, special, + int, id, caddr_t, addr) +#endif diff --git a/libc/sysdeps/linux/common/read.c b/libc/sysdeps/linux/common/read.c new file mode 100644 index 0000000..965787d --- /dev/null +++ b/libc/sysdeps/linux/common/read.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * read() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(read) __libc_read; +#define __NR___libc_read __NR_read +_syscall3(ssize_t, __libc_read, int, fd, __ptr_t, buf, size_t, count) +libc_hidden_proto(read) +weak_alias(__libc_read,read) +libc_hidden_weak(read) diff --git a/libc/sysdeps/linux/common/readahead.c b/libc/sysdeps/linux/common/readahead.c new file mode 100644 index 0000000..cd40352 --- /dev/null +++ b/libc/sysdeps/linux/common/readahead.c @@ -0,0 +1,58 @@ +/* Provide kernel hint to read ahead. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#include <_lfs_64.h> + +#ifdef __NR_readahead + +# define __NR___readahead __NR_readahead + +# if __WORDSIZE == 64 + +static __inline__ _syscall3(ssize_t, __readahead, int, fd, + off_t, offset, size_t, count) + +ssize_t readahead(int fd, off_t offset, size_t count) +{ + return __readahead(fd, offset, count); +} + +# else + +static __inline__ _syscall4(ssize_t, __readahead, int, fd, + off_t, high_offset, off_t, low_offset, size_t, count) + +ssize_t readahead(int fd, off64_t offset, size_t count) +{ + return __readahead(fd, (off_t) (offset >> 32), (off_t) (offset & 0xffffffff), count); +} + +# endif + +#endif + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/readlink.c b/libc/sysdeps/linux/common/readlink.c new file mode 100644 index 0000000..716bfcc --- /dev/null +++ b/libc/sysdeps/linux/common/readlink.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * readlink() for uClibc + * + * Copyright (C) 2000-2007 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(readlink) +_syscall3(ssize_t, readlink, const char *, path, char *, buf, size_t, bufsiz) +libc_hidden_def(readlink) diff --git a/libc/sysdeps/linux/common/readv.c b/libc/sysdeps/linux/common/readv.c new file mode 100644 index 0000000..86e94d8 --- /dev/null +++ b/libc/sysdeps/linux/common/readv.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * readv() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(readv) __libc_readv; + +#define __NR___libc_readv __NR_readv +_syscall3(ssize_t, __libc_readv, int, filedes, const struct iovec *, vector, + int, count) +weak_alias(__libc_readv,readv) diff --git a/libc/sysdeps/linux/common/reboot.c b/libc/sysdeps/linux/common/reboot.c new file mode 100644 index 0000000..ec271b1 --- /dev/null +++ b/libc/sysdeps/linux/common/reboot.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * _reboot() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#define __NR__reboot __NR_reboot +static __inline__ _syscall3(int, _reboot, int, magic, int, magic2, int, flag) +int reboot(int flag) +{ + return (_reboot((int) 0xfee1dead, 672274793, flag)); +} diff --git a/libc/sysdeps/linux/common/remap_file_pages.c b/libc/sysdeps/linux/common/remap_file_pages.c new file mode 100644 index 0000000..0512b88 --- /dev/null +++ b/libc/sysdeps/linux/common/remap_file_pages.c @@ -0,0 +1,16 @@ +/* + * remap_file_pages() for uClibc + * + * Copyright (C) 2008 Will Newton + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include + +#ifdef __NR_remap_file_pages + +_syscall5(int, remap_file_pages, void *, __start, size_t, __size, + int, __prot, size_t, __pgoff, int, __flags) + +#endif diff --git a/libc/sysdeps/linux/common/rename.c b/libc/sysdeps/linux/common/rename.c new file mode 100644 index 0000000..9d8397a --- /dev/null +++ b/libc/sysdeps/linux/common/rename.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * rename() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define __NR___syscall_rename __NR_rename +static __inline__ _syscall2(int, __syscall_rename, const char *, oldpath, + const char *, newpath) + +int rename(const char * oldpath, const char * newpath) +{ + return __syscall_rename(oldpath, newpath); +} + diff --git a/libc/sysdeps/linux/common/rmdir.c b/libc/sysdeps/linux/common/rmdir.c new file mode 100644 index 0000000..63c5f2e --- /dev/null +++ b/libc/sysdeps/linux/common/rmdir.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * rmdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(rmdir) + +_syscall1(int, rmdir, const char *, pathname) +libc_hidden_def(rmdir) diff --git a/libc/sysdeps/linux/common/sbrk.c b/libc/sysdeps/linux/common/sbrk.c new file mode 100644 index 0000000..734a4ce --- /dev/null +++ b/libc/sysdeps/linux/common/sbrk.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(brk) + +/* Defined in brk.c. */ +extern void *__curbrk attribute_hidden; + +/* Extend the process's data space by INCREMENT. + If INCREMENT is negative, shrink data space by - INCREMENT. + Return start of new space allocated, or -1 for errors. */ +libc_hidden_proto(sbrk) +void * sbrk (intptr_t increment) +{ + void *oldbrk; + + if (__curbrk == NULL) + if (brk (NULL) < 0) /* Initialize the break. */ + return (void *) -1; + + if (increment == 0) + return __curbrk; + + oldbrk = __curbrk; + if (brk (oldbrk + increment) < 0) + return (void *) -1; + + return oldbrk; +} +libc_hidden_def(sbrk) diff --git a/libc/sysdeps/linux/common/sched_get_priority_max.c b/libc/sysdeps/linux/common/sched_get_priority_max.c new file mode 100644 index 0000000..cf5447c --- /dev/null +++ b/libc/sysdeps/linux/common/sched_get_priority_max.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_get_priority_max() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sched_get_priority_max, int, policy) diff --git a/libc/sysdeps/linux/common/sched_get_priority_min.c b/libc/sysdeps/linux/common/sched_get_priority_min.c new file mode 100644 index 0000000..884efed --- /dev/null +++ b/libc/sysdeps/linux/common/sched_get_priority_min.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_get_priority_min() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sched_get_priority_min, int, policy) diff --git a/libc/sysdeps/linux/common/sched_getaffinity.c b/libc/sysdeps/linux/common/sched_getaffinity.c new file mode 100644 index 0000000..5d5e5b2 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_getaffinity.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifdef __USE_GNU + +#include +#include +#include + +#include +#include + +#if defined __NR_sched_getaffinity +#define __NR___syscall_sched_getaffinity __NR_sched_getaffinity +static __inline__ _syscall3(int, __syscall_sched_getaffinity, __kernel_pid_t, pid, + size_t, cpusetsize, cpu_set_t *, cpuset) + +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *cpuset) +{ + int res = (__syscall_sched_getaffinity(pid, MIN(INT_MAX, cpusetsize), + cpuset)); + + if (res != -1) { + /* Clean the rest of the memory the kernel didn't do. */ + memset ((char *) cpuset + res, '\0', cpusetsize - res); + + res = 0; + } + return res; +} +#elif defined __UCLIBC_HAS_STUBS__ +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *cpuset) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/sched_getparam.c b/libc/sysdeps/linux/common/sched_getparam.c new file mode 100644 index 0000000..eb17e25 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_getparam.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_getparam() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_getparam __NR_sched_getparam +static __inline__ _syscall2(int, __syscall_sched_getparam, + __kernel_pid_t, pid, struct sched_param *, p) + +int sched_getparam(pid_t pid, struct sched_param *p) +{ + return (__syscall_sched_getparam(pid, p)); +} diff --git a/libc/sysdeps/linux/common/sched_getscheduler.c b/libc/sysdeps/linux/common/sched_getscheduler.c new file mode 100644 index 0000000..e657abd --- /dev/null +++ b/libc/sysdeps/linux/common/sched_getscheduler.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_getscheduler() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_getscheduler __NR_sched_getscheduler +static __inline__ _syscall1(int, __syscall_sched_getscheduler, __kernel_pid_t, pid) + +int sched_getscheduler(pid_t pid) +{ + return (__syscall_sched_getscheduler(pid)); +} diff --git a/libc/sysdeps/linux/common/sched_rr_get_interval.c b/libc/sysdeps/linux/common/sched_rr_get_interval.c new file mode 100644 index 0000000..31d620f --- /dev/null +++ b/libc/sysdeps/linux/common/sched_rr_get_interval.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_rr_get_interval() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval +static __inline__ _syscall2(int, __syscall_sched_rr_get_interval, + __kernel_pid_t, pid, struct timespec *, tp) + +int sched_rr_get_interval(pid_t pid, struct timespec *tp) +{ + return (__syscall_sched_rr_get_interval(pid, tp)); +} diff --git a/libc/sysdeps/linux/common/sched_setaffinity.c b/libc/sysdeps/linux/common/sched_setaffinity.c new file mode 100644 index 0000000..815fe80 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_setaffinity.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifdef __USE_GNU + +#include +#include +#include + +#ifdef INTERNAL_SYSCALL /* remove this when all archs has this #defined */ + +#include +#include +#include +#include + +#if defined __NR_sched_setaffinity +libc_hidden_proto(getpid) + +#define __NR___syscall_sched_setaffinity __NR_sched_setaffinity +static __inline__ _syscall3(int, __syscall_sched_setaffinity, __kernel_pid_t, pid, + size_t, cpusetsize, cpu_set_t *, cpuset) + +static size_t __kernel_cpumask_size; + +int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset) +{ + size_t cnt; + if (unlikely (__kernel_cpumask_size == 0)) { + INTERNAL_SYSCALL_DECL (err); + int res; + size_t psize = 128; + void *p = alloca (psize); + + while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, getpid (), + psize, p), + INTERNAL_SYSCALL_ERROR_P (res, err) + && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + p = extend_alloca (p, psize, 2 * psize); + + if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) { + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + return -1; + } + + __kernel_cpumask_size = res; + } + + /* We now know the size of the kernel cpumask_t. Make sure the user + does not request to set a bit beyond that. */ + for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') { + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + __set_errno (EINVAL); + return -1; + } + + return INLINE_SYSCALL (sched_setaffinity, 3, pid, cpusetsize, cpuset); +} +#else +#define ___HAVE_NO_sched_setaffinity +#endif +#else +#define ___HAVE_NO_sched_setaffinity +#endif + +#if defined ___HAVE_NO_sched_setaffinity && defined __UCLIBC_HAS_STUBS__ +int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#endif /* __USE_GNU */ diff --git a/libc/sysdeps/linux/common/sched_setparam.c b/libc/sysdeps/linux/common/sched_setparam.c new file mode 100644 index 0000000..0f5f74f --- /dev/null +++ b/libc/sysdeps/linux/common/sched_setparam.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_setparam() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_setparam __NR_sched_setparam +static __inline__ _syscall2(int, __syscall_sched_setparam, + __kernel_pid_t, pid, const struct sched_param *, p) + +int sched_setparam(pid_t pid, const struct sched_param *p) +{ + return (__syscall_sched_setparam(pid, p)); +} diff --git a/libc/sysdeps/linux/common/sched_setscheduler.c b/libc/sysdeps/linux/common/sched_setscheduler.c new file mode 100644 index 0000000..0af498f --- /dev/null +++ b/libc/sysdeps/linux/common/sched_setscheduler.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_setscheduler() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_setscheduler __NR_sched_setscheduler +static __inline__ _syscall3(int, __syscall_sched_setscheduler, + __kernel_pid_t, pid, int, policy, const struct sched_param *, p) + +int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p) +{ + return (__syscall_sched_setscheduler(pid, policy, p)); +} diff --git a/libc/sysdeps/linux/common/sched_yield.c b/libc/sysdeps/linux/common/sched_yield.c new file mode 100644 index 0000000..2d584bd --- /dev/null +++ b/libc/sysdeps/linux/common/sched_yield.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_yield() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall0(int, sched_yield) diff --git a/libc/sysdeps/linux/common/select.c b/libc/sysdeps/linux/common/select.c new file mode 100644 index 0000000..6d42285 --- /dev/null +++ b/libc/sysdeps/linux/common/select.c @@ -0,0 +1,47 @@ +/* vi: set sw=4 ts=4: */ +/* + * select() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(select) __libc_select; + +#if !defined(__NR__newselect) && !defined(__NR_select) && defined __USE_XOPEN2K +# define __NR___libc_pselect6 __NR_pselect6 +_syscall6(int, __libc_pselect6, int, n, fd_set *, readfds, fd_set *, writefds, + fd_set *, exceptfds, const struct timespec *, timeout, + const sigset_t *, sigmask) + +int __libc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + struct timespec _ts, *ts = 0; + if (timeout) { + _ts.tv_sec = timeout->tv_sec; + _ts.tv_nsec = timeout->tv_usec * 1000; + ts = &_ts; + } + return __libc_pselect6(n, readfds, writefds, exceptfds, ts, 0); +} + +#else + +#ifdef __NR__newselect +# define __NR___libc_select __NR__newselect +#else +# define __NR___libc_select __NR_select +#endif +_syscall5(int, __libc_select, int, n, fd_set *, readfds, fd_set *, writefds, + fd_set *, exceptfds, struct timeval *, timeout) + +#endif + +libc_hidden_proto(select) +weak_alias(__libc_select,select) +libc_hidden_weak(select) diff --git a/libc/sysdeps/linux/common/sendfile.c b/libc/sysdeps/linux/common/sendfile.c new file mode 100644 index 0000000..0d2ebaa --- /dev/null +++ b/libc/sysdeps/linux/common/sendfile.c @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * sendfile() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* need to hide the 64bit prototype or the strong_alias() + * will fail when __NR_sendfile64 doesnt exist */ +#define sendfile64 __hidesendfile64 + +#include +#include +#include + +#undef sendfile64 + +#ifdef __NR_sendfile + +_syscall4(ssize_t, sendfile, int, out_fd, int, in_fd, __off_t *, offset, + size_t, count) + +#if ! defined __NR_sendfile64 && defined __UCLIBC_HAS_LFS__ +strong_alias(sendfile,sendfile64) +#endif + +#endif /* __NR_sendfile */ diff --git a/libc/sysdeps/linux/common/sendfile64.c b/libc/sysdeps/linux/common/sendfile64.c new file mode 100644 index 0000000..fc5155f --- /dev/null +++ b/libc/sysdeps/linux/common/sendfile64.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* sendfile64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_sendfile64 +_syscall4(ssize_t,sendfile64, int, out_fd, int, in_fd, __off64_t *, offset, size_t, count) +#endif diff --git a/libc/sysdeps/linux/common/setdomainname.c b/libc/sysdeps/linux/common/setdomainname.c new file mode 100644 index 0000000..6b768b7 --- /dev/null +++ b/libc/sysdeps/linux/common/setdomainname.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * setdomainname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall2(int, setdomainname, const char *, name, size_t, len) +#endif diff --git a/libc/sysdeps/linux/common/setegid.c b/libc/sysdeps/linux/common/setegid.c new file mode 100644 index 0000000..33c627c --- /dev/null +++ b/libc/sysdeps/linux/common/setegid.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#if (defined __NR_setresgid || defined __NR_setresgid32) && defined __USE_GNU +libc_hidden_proto(setresgid) +#endif +libc_hidden_proto(setregid) + +int setegid(gid_t gid) +{ + int result; + + if (gid == (gid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + +#if (defined __NR_setresgid || defined __NR_setresgid32) && defined __USE_GNU + result = setresgid(-1, gid, -1); + if (result == -1 && errno == ENOSYS) + /* Will also set the saved group ID if egid != gid, + * making it impossible to switch back...*/ +#endif + result = setregid(-1, gid); + + return result; +} diff --git a/libc/sysdeps/linux/common/seteuid.c b/libc/sysdeps/linux/common/seteuid.c new file mode 100644 index 0000000..5a6e9a2 --- /dev/null +++ b/libc/sysdeps/linux/common/seteuid.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#if !defined __UCLIBC_LINUX_SPECIFIC__ +#undef __NR_setresuid +#undef __NR_setresuid32 +#endif + +libc_hidden_proto(seteuid) + +#if (defined __NR_setresuid || defined __NR_setresuid32) && defined __USE_GNU +libc_hidden_proto(setresuid) +#endif +libc_hidden_proto(setreuid) + +int seteuid(uid_t uid) +{ + int result; + + if (uid == (uid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + +#if (defined __NR_setresuid || defined __NR_setresuid32) && defined __USE_GNU + result = setresuid(-1, uid, -1); + if (result == -1 && errno == ENOSYS) + /* Will also set the saved user ID if euid != uid, + * making it impossible to switch back...*/ +#endif + result = setreuid(-1, uid); + + return result; +} +libc_hidden_def(seteuid) diff --git a/libc/sysdeps/linux/common/setfsgid.c b/libc/sysdeps/linux/common/setfsgid.c new file mode 100644 index 0000000..78d35dd --- /dev/null +++ b/libc/sysdeps/linux/common/setfsgid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setfsgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setfsgid32)) || __WORDSIZE == 64 +# ifdef __NR_setfsgid32 +# undef __NR_setfsgid +# define __NR_setfsgid __NR_setfsgid32 +# endif + +_syscall1(int, setfsgid, gid_t, gid) + +#else + +# define __NR___syscall_setfsgid __NR_setfsgid +static __inline__ _syscall1(int, __syscall_setfsgid, __kernel_gid_t, gid) + +int setfsgid(gid_t gid) +{ + if (gid != (gid_t) ((__kernel_gid_t) gid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setfsgid(gid)); +} +#endif diff --git a/libc/sysdeps/linux/common/setfsuid.c b/libc/sysdeps/linux/common/setfsuid.c new file mode 100644 index 0000000..a7372bd --- /dev/null +++ b/libc/sysdeps/linux/common/setfsuid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setfsuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setfsuid32)) || __WORDSIZE == 64 +# ifdef __NR_setfsuid32 +# undef __NR_setfsuid +# define __NR_setfsuid __NR_setfsuid32 +# endif + +_syscall1(int, setfsuid, uid_t, uid) + +#else + +# define __NR___syscall_setfsuid __NR_setfsuid +static __inline__ _syscall1(int, __syscall_setfsuid, __kernel_uid_t, uid) + +int setfsuid(uid_t uid) +{ + if (uid != (uid_t) ((__kernel_uid_t) uid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setfsuid(uid)); +} +#endif diff --git a/libc/sysdeps/linux/common/setgid.c b/libc/sysdeps/linux/common/setgid.c new file mode 100644 index 0000000..88341ba --- /dev/null +++ b/libc/sysdeps/linux/common/setgid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setgid32)) || __WORDSIZE == 64 +# ifdef __NR_setgid32 +# undef __NR_setgid +# define __NR_setgid __NR_setgid32 +# endif + +_syscall1(int, setgid, gid_t, gid) + +#else + +# define __NR___syscall_setgid __NR_setgid +static __inline__ _syscall1(int, __syscall_setgid, __kernel_gid_t, gid) + +int setgid(gid_t gid) +{ + if (gid == (gid_t) ~ 0 || gid != (gid_t) ((__kernel_gid_t) gid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setgid(gid)); +} +#endif diff --git a/libc/sysdeps/linux/common/setgroups.c b/libc/sysdeps/linux/common/setgroups.c new file mode 100644 index 0000000..298252d --- /dev/null +++ b/libc/sysdeps/linux/common/setgroups.c @@ -0,0 +1,66 @@ +/* vi: set sw=4 ts=4: */ +/* + * setgroups() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#ifdef __USE_BSD + +libc_hidden_proto(setgroups) + +#if defined(__NR_setgroups32) +# undef __NR_setgroups +# define __NR_setgroups __NR_setgroups32 +_syscall2(int, setgroups, size_t, size, const gid_t *, list) + +#elif __WORDSIZE == 64 +_syscall2(int, setgroups, size_t, size, const gid_t *, list) + +#else + +libc_hidden_proto(sysconf) + +#define __NR___syscall_setgroups __NR_setgroups +static __inline__ _syscall2(int, __syscall_setgroups, + size_t, size, const __kernel_gid_t *, list) + +int setgroups(size_t size, const gid_t *groups) +{ + if (size > (size_t) sysconf(_SC_NGROUPS_MAX)) { +ret_error: + __set_errno(EINVAL); + return -1; + } else { + size_t i; + __kernel_gid_t *kernel_groups = NULL; + + if (size) { + kernel_groups = (__kernel_gid_t *)malloc(sizeof(*kernel_groups) * size); + if (kernel_groups == NULL) + goto ret_error; + } + + for (i = 0; i < size; i++) { + kernel_groups[i] = (groups)[i]; + if (groups[i] != (gid_t) ((__kernel_gid_t) groups[i])) { + goto ret_error; + } + } + + i = __syscall_setgroups(size, kernel_groups); + free(kernel_groups); + return i; + } +} +#endif + +libc_hidden_def(setgroups) +#endif diff --git a/libc/sysdeps/linux/common/sethostname.c b/libc/sysdeps/linux/common/sethostname.c new file mode 100644 index 0000000..1ceb2a0 --- /dev/null +++ b/libc/sysdeps/linux/common/sethostname.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * sethostname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall2(int, sethostname, const char *, name, size_t, len) +#endif diff --git a/libc/sysdeps/linux/common/setitimer.c b/libc/sysdeps/linux/common/setitimer.c new file mode 100644 index 0000000..f57e6ac --- /dev/null +++ b/libc/sysdeps/linux/common/setitimer.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * setitimer() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(setitimer) + +_syscall3(int, setitimer, __itimer_which_t, which, + const struct itimerval *, new, struct itimerval *, old) +libc_hidden_def(setitimer) diff --git a/libc/sysdeps/linux/common/setpgid.c b/libc/sysdeps/linux/common/setpgid.c new file mode 100644 index 0000000..1ec5e62 --- /dev/null +++ b/libc/sysdeps/linux/common/setpgid.c @@ -0,0 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * setpgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_UNIX98 || defined __USE_SVID +#include + +libc_hidden_proto(setpgid) + +#define __NR___syscall_setpgid __NR_setpgid +static __inline__ _syscall2(int, __syscall_setpgid, + __kernel_pid_t, pid, __kernel_pid_t, pgid) + +int setpgid(pid_t pid, pid_t pgid) +{ + return (__syscall_setpgid(pid, pgid)); +} +libc_hidden_def(setpgid) +#endif diff --git a/libc/sysdeps/linux/common/setpgrp.c b/libc/sysdeps/linux/common/setpgrp.c new file mode 100644 index 0000000..38300dc --- /dev/null +++ b/libc/sysdeps/linux/common/setpgrp.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(setpgid) + +int setpgrp(void) +{ + return setpgid(0,0); +} diff --git a/libc/sysdeps/linux/common/setpriority.c b/libc/sysdeps/linux/common/setpriority.c new file mode 100644 index 0000000..9774348 --- /dev/null +++ b/libc/sysdeps/linux/common/setpriority.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * setpriority() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(setpriority) + +_syscall3(int, setpriority, __priority_which_t, which, id_t, who, int, prio) +libc_hidden_def(setpriority) diff --git a/libc/sysdeps/linux/common/setregid.c b/libc/sysdeps/linux/common/setregid.c new file mode 100644 index 0000000..b92b844 --- /dev/null +++ b/libc/sysdeps/linux/common/setregid.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * setregid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(setregid) + +#if (__WORDSIZE == 32 && defined(__NR_setregid32)) || __WORDSIZE == 64 +# ifdef __NR_setregid32 +# undef __NR_setregid +# define __NR_setregid __NR_setregid32 +# endif + +_syscall2(int, setregid, gid_t, rgid, gid_t, egid) + +#else + +# define __NR___syscall_setregid __NR_setregid +static __inline__ _syscall2(int, __syscall_setregid, + __kernel_gid_t, rgid, __kernel_gid_t, egid) + +int setregid(gid_t rgid, gid_t egid) +{ + if (((rgid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((egid + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setregid(rgid, egid)); +} +#endif + +libc_hidden_def(setregid) diff --git a/libc/sysdeps/linux/common/setresgid.c b/libc/sysdeps/linux/common/setresgid.c new file mode 100644 index 0000000..6018f19 --- /dev/null +++ b/libc/sysdeps/linux/common/setresgid.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* + * setresgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_setresgid32) +# undef __NR_setresgid +# define __NR_setresgid __NR_setresgid32 + +libc_hidden_proto(setresgid) +_syscall3(int, setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) +libc_hidden_def(setresgid) + +#elif defined(__NR_setresgid) + +# define __NR___syscall_setresgid __NR_setresgid +static __inline__ _syscall3(int, __syscall_setresgid, + __kernel_gid_t, rgid, __kernel_gid_t, egid, __kernel_gid_t, sgid) + +libc_hidden_proto(setresgid) +int setresgid(gid_t rgid, gid_t egid, gid_t sgid) +{ + if (((rgid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((egid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((sgid + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setresgid(rgid, egid, sgid)); +} +libc_hidden_def(setresgid) + +#endif + +#endif diff --git a/libc/sysdeps/linux/common/setresuid.c b/libc/sysdeps/linux/common/setresuid.c new file mode 100644 index 0000000..ab15be1 --- /dev/null +++ b/libc/sysdeps/linux/common/setresuid.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* + * setresuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +#include + +#if defined(__NR_setresuid32) +# undef __NR_setresuid +# define __NR_setresuid __NR_setresuid32 + +libc_hidden_proto(setresuid) +_syscall3(int, setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) +libc_hidden_def(setresuid) + +#elif defined(__NR_setresuid) + +# define __NR___syscall_setresuid __NR_setresuid +static __inline__ _syscall3(int, __syscall_setresuid, + __kernel_uid_t, rgid, __kernel_uid_t, egid, __kernel_uid_t, sgid) + +libc_hidden_proto(setresuid) +int setresuid(uid_t ruid, uid_t euid, uid_t suid) +{ + if (((ruid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((euid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((suid + 1) > (uid_t) ((__kernel_uid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setresuid(ruid, euid, suid)); +} +libc_hidden_def(setresuid) + +#endif + +#endif diff --git a/libc/sysdeps/linux/common/setreuid.c b/libc/sysdeps/linux/common/setreuid.c new file mode 100644 index 0000000..bf55843 --- /dev/null +++ b/libc/sysdeps/linux/common/setreuid.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * setreuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(setreuid) + +#if (__WORDSIZE == 32 && defined(__NR_setreuid32)) || __WORDSIZE == 64 +# ifdef __NR_setreuid32 +# undef __NR_setreuid +# define __NR_setreuid __NR_setreuid32 +# endif + +_syscall2(int, setreuid, uid_t, ruid, uid_t, euid) + +#else + +# define __NR___syscall_setreuid __NR_setreuid +static __inline__ _syscall2(int, __syscall_setreuid, + __kernel_uid_t, ruid, __kernel_uid_t, euid) + +int setreuid(uid_t ruid, uid_t euid) +{ + if (((ruid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((euid + 1) > (uid_t) ((__kernel_uid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setreuid(ruid, euid)); +} +#endif + +libc_hidden_def(setreuid) diff --git a/libc/sysdeps/linux/common/setrlimit.c b/libc/sysdeps/linux/common/setrlimit.c new file mode 100644 index 0000000..3811cd7 --- /dev/null +++ b/libc/sysdeps/linux/common/setrlimit.c @@ -0,0 +1,70 @@ +/* vi: set sw=4 ts=4: */ +/* + * setrlimit() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define setrlimit64 __hide_setrlimit64 +#include +#include +#include +#undef setrlimit64 + +libc_hidden_proto(setrlimit) + +/* Only wrap setrlimit if the new usetrlimit is not present and setrlimit sucks */ + +#if defined(__NR_usetrlimit) + +/* just call usetrlimit() */ +# define __NR___syscall_usetrlimit __NR_usetrlimit +static __always_inline +_syscall2(int, __syscall_usetrlimit, enum __rlimit_resource, resource, + const struct rlimit *, rlim) +int setrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + return (__syscall_usetrlimit(resource, rlimits)); +} + +#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) + +/* We don't need to wrap setrlimit() */ +_syscall2(int, setrlimit, __rlimit_resource_t, resource, + const struct rlimit *, rlim) + +#else + +/* we have to handle old style setrlimit() */ +# define __NR___syscall_setrlimit __NR_setrlimit +static __always_inline +_syscall2(int, __syscall_setrlimit, int, resource, const struct rlimit *, rlim) + +int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits) +{ + struct rlimit rlimits_small; + + if (rlimits == NULL) { + __set_errno(EINVAL); + return -1; + } + + /* We might have to correct the limits values. Since the old values + * were signed the new values might be too large. */ +# define RMIN(x, y) ((x) < (y) ? (x) : (y)) + rlimits_small.rlim_cur = RMIN((unsigned long int) rlimits->rlim_cur, + RLIM_INFINITY >> 1); + rlimits_small.rlim_max = RMIN((unsigned long int) rlimits->rlim_max, + RLIM_INFINITY >> 1); +#undef RMIN + return (__syscall_setrlimit(resource, &rlimits_small)); +} +#endif + +libc_hidden_def(setrlimit) + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 64 +strong_alias(setrlimit, setrlimit64) +#endif diff --git a/libc/sysdeps/linux/common/setrlimit64.c b/libc/sysdeps/linux/common/setrlimit64.c new file mode 100644 index 0000000..90b8eeb --- /dev/null +++ b/libc/sysdeps/linux/common/setrlimit64.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991,1995,1996,1997,1998,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + +/* the regular setrlimit will work just fine for 64bit users */ + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 32 + +libc_hidden_proto(setrlimit) + +/* Set the soft and hard limits for RESOURCE to *RLIMITS. + Only the super-user can increase hard limits. + Return 0 if successful, -1 if not (and sets errno). */ +int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits) +{ + struct rlimit rlimits32; + + if (rlimits->rlim_cur >= RLIM_INFINITY) + rlimits32.rlim_cur = RLIM_INFINITY; + else + rlimits32.rlim_cur = rlimits->rlim_cur; + if (rlimits->rlim_max >= RLIM_INFINITY) + rlimits32.rlim_max = RLIM_INFINITY; + else + rlimits32.rlim_max = rlimits->rlim_max; + + return setrlimit (resource, &rlimits32); +} +#endif diff --git a/libc/sysdeps/linux/common/setsid.c b/libc/sysdeps/linux/common/setsid.c new file mode 100644 index 0000000..849c02f --- /dev/null +++ b/libc/sysdeps/linux/common/setsid.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * setsid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(setsid) + +_syscall0(pid_t, setsid) +libc_hidden_def(setsid) diff --git a/libc/sysdeps/linux/common/settimeofday.c b/libc/sysdeps/linux/common/settimeofday.c new file mode 100644 index 0000000..c6f2d79 --- /dev/null +++ b/libc/sysdeps/linux/common/settimeofday.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * settimeofday() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_BSD + +libc_hidden_proto(settimeofday) + +_syscall2(int, settimeofday, const struct timeval *, tv, + const struct timezone *, tz) +libc_hidden_def(settimeofday) +#endif diff --git a/libc/sysdeps/linux/common/setuid.c b/libc/sysdeps/linux/common/setuid.c new file mode 100644 index 0000000..7fd8c65 --- /dev/null +++ b/libc/sysdeps/linux/common/setuid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setuid32)) || __WORDSIZE == 64 +# ifdef __NR_setuid32 +# undef __NR_setuid +# define __NR_setuid __NR_setuid32 +# endif + +_syscall1(int, setuid, uid_t, uid) + +#else + +# define __NR___syscall_setuid __NR_setuid +static __inline__ _syscall1(int, __syscall_setuid, __kernel_uid_t, uid) + +int setuid(uid_t uid) +{ + if (uid == (uid_t) ~ 0 || uid != (uid_t) ((__kernel_uid_t) uid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setuid(uid)); +} +#endif diff --git a/libc/sysdeps/linux/common/sigaltstack.c b/libc/sysdeps/linux/common/sigaltstack.c new file mode 100644 index 0000000..964e16f --- /dev/null +++ b/libc/sysdeps/linux/common/sigaltstack.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigaltstack() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_sigaltstack && (defined __USE_BSD || defined __USE_UNIX98) + +_syscall2(int, sigaltstack, const struct sigaltstack *, ss, + struct sigaltstack *, oss) +#endif diff --git a/libc/sysdeps/linux/common/signalfd.c b/libc/sysdeps/linux/common/signalfd.c new file mode 100644 index 0000000..3d76e04 --- /dev/null +++ b/libc/sysdeps/linux/common/signalfd.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * signalfd() for uClibc + * + * Copyright (C) 2008 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if defined __NR_signalfd4 +#define __NR___syscall_signalfd4 __NR_signalfd4 +static __inline__ _syscall4(int, __syscall_signalfd4, int, fd, + const sigset_t *, mask, size_t, sizemask, int, flags) +#elif defined __NR_signalfd +#define __NR___syscall_signalfd __NR_signalfd +static __inline__ _syscall3(int, __syscall_signalfd, int, fd, + const sigset_t *, mask, size_t, sizemask) +#endif + +#if defined __NR_signalfd4 || defined __NR_signalfd \ + || defined __UCLIBC_HAS_STUBS__ +int signalfd (int fd, const sigset_t *mask, int flags) +{ +#if defined __NR___syscall_signalfd4 + return __syscall_signalfd4(fd, mask, _NSIG / 8, flags); +#elif defined __NR___syscall_signalfd + if (flags != 0) { + __set_errno(EINVAL); + return -1; + } + return __syscall_signalfd(fd, mask, _NSIG / 8); +#elif defined __UCLIBC_HAS_STUBS__ + __set_errno(ENOSYS); + return -1; +#endif +} +#endif diff --git a/libc/sysdeps/linux/common/sigpending.c b/libc/sysdeps/linux/common/sigpending.c new file mode 100644 index 0000000..8fa2a51 --- /dev/null +++ b/libc/sysdeps/linux/common/sigpending.c @@ -0,0 +1,27 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigpending() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include +#undef sigpending + +#ifdef __NR_rt_sigpending +# define __NR___rt_sigpending __NR_rt_sigpending +static __inline__ _syscall2(int, __rt_sigpending, sigset_t *, set, size_t, size) + +int sigpending(sigset_t * set) +{ + return __rt_sigpending(set, _NSIG / 8); +} +#else +_syscall1(int, sigpending, sigset_t *, set) +#endif +#endif diff --git a/libc/sysdeps/linux/common/sigprocmask.c b/libc/sysdeps/linux/common/sigprocmask.c new file mode 100644 index 0000000..7da17bc --- /dev/null +++ b/libc/sysdeps/linux/common/sigprocmask.c @@ -0,0 +1,73 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigprocmask() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include + +#undef sigprocmask + +libc_hidden_proto(sigprocmask) + +#ifdef __NR_rt_sigprocmask + +# define __NR___rt_sigprocmask __NR_rt_sigprocmask +static __always_inline +_syscall4(int, __rt_sigprocmask, int, how, const sigset_t *, set, + sigset_t *, oldset, size_t, size) + +int sigprocmask(int how, const sigset_t * set, sigset_t * oldset) +{ + if (set && +# if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) +#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) + (((unsigned int)(how-1)) > 2) +# else +# warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) + && (how != SIG_SETMASK)) +# endif + ) { + __set_errno(EINVAL); + return -1; + } + return __rt_sigprocmask(how, set, oldset, _NSIG / 8); +} + + +#else + +# define __NR___syscall_sigprocmask __NR_sigprocmask +static __always_inline +_syscall3(int, __syscall_sigprocmask, int, how, const sigset_t *, set, + sigset_t *, oldset) + +int sigprocmask(int how, const sigset_t * set, sigset_t * oldset) +{ + if (set && +# if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) +#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) + (((unsigned int)(how-1)) > 2) +# else +# warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) + && (how != SIG_SETMASK)) +# endif + ) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_sigprocmask(how, set, oldset)); +} +#endif +libc_hidden_def(sigprocmask) +#endif diff --git a/libc/sysdeps/linux/common/sigqueue.c b/libc/sysdeps/linux/common/sigqueue.c new file mode 100644 index 0000000..f941d63 --- /dev/null +++ b/libc/sysdeps/linux/common/sigqueue.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include +#if defined __USE_POSIX199309 + +libc_hidden_proto(getpid) +libc_hidden_proto(getuid) +/* Experimentally off - libc_hidden_proto(memset) */ + +#ifdef __NR_rt_sigqueueinfo + +# define __NR___libc_rt_sigqueueinfo __NR_rt_sigqueueinfo +static __inline__ _syscall3(int, __libc_rt_sigqueueinfo, pid_t, pid, int, sig, void*, value) + +/* Return any pending signal or wait for one for the given time. */ +int sigqueue (pid_t pid, int sig, const union sigval val) +{ + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t value. */ + info.si_signo = sig; + info.si_code = SI_QUEUE; + info.si_pid = getpid (); + info.si_uid = getuid (); + info.si_value = val; + + return __libc_rt_sigqueueinfo(pid, sig, __ptrvalue (&info)); +} + +#endif +#endif diff --git a/libc/sysdeps/linux/common/sigsuspend.c b/libc/sysdeps/linux/common/sigsuspend.c new file mode 100644 index 0000000..6161acb --- /dev/null +++ b/libc/sysdeps/linux/common/sigsuspend.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigsuspend() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include + +extern __typeof(sigsuspend) __libc_sigsuspend; + +#ifdef __NR_rt_sigsuspend +# define __NR___rt_sigsuspend __NR_rt_sigsuspend +static __inline__ _syscall2(int, __rt_sigsuspend, const sigset_t *, mask, size_t, size) + +int __libc_sigsuspend(const sigset_t * mask) +{ + return __rt_sigsuspend(mask, _NSIG / 8); +} +#else +# define __NR___syscall_sigsuspend __NR_sigsuspend +static __inline__ _syscall3(int, __syscall_sigsuspend, int, a, unsigned long int, b, + unsigned long int, c) + +int __libc_sigsuspend(const sigset_t * set) +{ + return __syscall_sigsuspend(0, 0, set->__val[0]); +} +#endif +libc_hidden_proto(sigsuspend) +weak_alias(__libc_sigsuspend,sigsuspend) +libc_hidden_weak(sigsuspend) +#endif diff --git a/libc/sysdeps/linux/common/splice.c b/libc/sysdeps/linux/common/splice.c new file mode 100644 index 0000000..f1e0d82 --- /dev/null +++ b/libc/sysdeps/linux/common/splice.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * splice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(splice) + +#ifdef __NR_splice +_syscall6(ssize_t, splice, int, __fdin, __off64_t *, __offin, int, __fdout, + __off64_t *, __offout, size_t, __len, unsigned int, __flags) +#else +ssize_t splice(int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +libc_hidden_def(splice) + diff --git a/libc/sysdeps/linux/common/ssp-local.c b/libc/sysdeps/linux/common/ssp-local.c new file mode 100644 index 0000000..202d956 --- /dev/null +++ b/libc/sysdeps/linux/common/ssp-local.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Peter S. Mazinger ps.m[@]gmx.net + * copied stack_chk_fail_local.c from glibc and adapted for uClibc + */ + +#include + +extern void __stack_chk_fail (void) attribute_noreturn; + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __stack_chk_fail_local (void) attribute_noreturn attribute_hidden; +void __stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} diff --git a/libc/sysdeps/linux/common/ssp.c b/libc/sysdeps/linux/common/ssp.c new file mode 100644 index 0000000..1563700 --- /dev/null +++ b/libc/sysdeps/linux/common/ssp.c @@ -0,0 +1,130 @@ +/* + * Distributed under the terms of the GNU Lesser General Public License + * $Header: $ + * + * This is a modified version of Hiroaki Etoh's stack smashing routines + * implemented for glibc. + * + * The following people have contributed input to this code. + * Ned Ludd - + * Alexander Gabert - + * The PaX Team - + * Peter S. Mazinger - + * Yoann Vandoorselaere - + * Robert Connolly - + * Cory Visi + * Mike Frysinger + */ + +#if defined __SSP__ || defined __SSP_ALL__ +#error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector" +#endif + +#ifdef __PROPOLICE_BLOCK_SEGV__ +# define SSP_SIGTYPE SIGSEGV +#else +# define SSP_SIGTYPE SIGABRT +#endif + +#include +#include +#include +#if defined __UCLIBC_HAS_SYSLOG__ +#include + +libc_hidden_proto(openlog) +libc_hidden_proto(syslog) +libc_hidden_proto(closelog) +#endif + +libc_hidden_proto(sigaction) +libc_hidden_proto(sigfillset) +libc_hidden_proto(sigdelset) +libc_hidden_proto(sigprocmask) +libc_hidden_proto(write) +libc_hidden_proto(kill) +libc_hidden_proto(getpid) +libc_hidden_proto(_exit) + +static void block_signals(void) +{ + struct sigaction sa; + sigset_t mask; + + sigfillset(&mask); + + sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */ + sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */ + + /* Make the default handler associated with the signal handler */ + memset(&sa, 0, sizeof(struct sigaction)); + sigfillset(&sa.sa_mask); /* Block all signals */ + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SSP_SIGTYPE, &sa, NULL); +} + +static void ssp_write(int fd, const char *msg1, const char *msg2, const char *msg3) +{ + write(fd, msg1, strlen(msg1)); + write(fd, msg2, strlen(msg2)); + write(fd, msg3, strlen(msg3)); + write(fd, "()\n", 3); +#if defined __UCLIBC_HAS_SYSLOG__ + openlog("ssp", LOG_CONS | LOG_PID, LOG_USER); + syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3); + closelog(); +#endif +} + +static attribute_noreturn void terminate(void) +{ + (void) kill(getpid(), SSP_SIGTYPE); + _exit(127); +} + +void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))) attribute_noreturn; +void __stack_smash_handler(char func[], int damaged) +{ + static const char message[] = ": stack smashing attack in function "; + + block_signals(); + + ssp_write(STDERR_FILENO, __uclibc_progname, message, func); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} + +void __stack_chk_fail(void) attribute_noreturn; +void __stack_chk_fail(void) +{ + static const char msg1[] = "stack smashing detected: "; + static const char msg3[] = " terminated"; + + block_signals(); + + ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} + +#if 0 +void __chk_fail(void) attribute_noreturn; +void __chk_fail(void) +{ + static const char msg1[] = "buffer overflow detected: "; + static const char msg3[] = " terminated"; + + block_signals(); + + ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} +#endif diff --git a/libc/sysdeps/linux/common/stat.c b/libc/sysdeps/linux/common/stat.c new file mode 100644 index 0000000..160f38a --- /dev/null +++ b/libc/sysdeps/linux/common/stat.c @@ -0,0 +1,46 @@ +/* vi: set sw=4 ts=4: */ +/* + * stat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* need to hide the 64bit prototype or the strong_alias() + * will fail when __NR_stat64 doesnt exist */ +#define stat64 __hidestat64 + +#include +#include +#include +#include "xstatconv.h" + +#undef stat64 + +libc_hidden_proto(stat) + +#define __NR___syscall_stat __NR_stat +#undef stat +static __inline__ _syscall2(int, __syscall_stat, + const char *, file_name, struct kernel_stat *, buf) + +int stat(const char *file_name, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_stat(file_name, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(stat) + +#if ! defined __NR_stat64 && defined __UCLIBC_HAS_LFS__ +extern __typeof(stat) stat64; +libc_hidden_proto(stat64) +strong_alias(stat,stat64) +libc_hidden_def(stat64) +#endif diff --git a/libc/sysdeps/linux/common/stat64.c b/libc/sysdeps/linux/common/stat64.c new file mode 100644 index 0000000..c9ba2bc --- /dev/null +++ b/libc/sysdeps/linux/common/stat64.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * stat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_stat64 +libc_hidden_proto(stat64) + +# define __NR___syscall_stat64 __NR_stat64 +# include +# include "xstatconv.h" + +static __inline__ _syscall2(int, __syscall_stat64, + const char *, file_name, struct kernel_stat64 *, buf) + +int stat64(const char *file_name, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_stat64(file_name, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(stat64) +#endif diff --git a/libc/sysdeps/linux/common/statfs.c b/libc/sysdeps/linux/common/statfs.c new file mode 100644 index 0000000..a1a32c3 --- /dev/null +++ b/libc/sysdeps/linux/common/statfs.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * statfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +extern __typeof(statfs) __libc_statfs; +libc_hidden_proto(__libc_statfs) +#define __NR___libc_statfs __NR_statfs +_syscall2(int, __libc_statfs, const char *, path, struct statfs *, buf) +libc_hidden_def(__libc_statfs) + +#if defined __UCLIBC_LINUX_SPECIFIC__ +libc_hidden_proto(statfs) +weak_alias(__libc_statfs,statfs) +libc_hidden_weak(statfs) +#endif diff --git a/libc/sysdeps/linux/common/stime.c b/libc/sysdeps/linux/common/stime.c new file mode 100644 index 0000000..2b7ea6f --- /dev/null +++ b/libc/sysdeps/linux/common/stime.c @@ -0,0 +1,33 @@ +/* vi: set sw=4 ts=4: */ +/* + * stime() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __USE_SVID +#ifdef __NR_stime +_syscall1(int, stime, const time_t *, t) +#else +libc_hidden_proto(settimeofday) + +int stime(const time_t * when) +{ + struct timeval tv; + + if (when == NULL) { + __set_errno(EINVAL); + return -1; + } + tv.tv_sec = *when; + tv.tv_usec = 0; + return settimeofday(&tv, (struct timezone *) 0); +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/swapoff.c b/libc/sysdeps/linux/common/swapoff.c new file mode 100644 index 0000000..db0b9be --- /dev/null +++ b/libc/sysdeps/linux/common/swapoff.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * swapoff() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_swapoff + +#include +_syscall1(int, swapoff, const char *, path) + +#endif diff --git a/libc/sysdeps/linux/common/swapon.c b/libc/sysdeps/linux/common/swapon.c new file mode 100644 index 0000000..5d6b6e2 --- /dev/null +++ b/libc/sysdeps/linux/common/swapon.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * swapon() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_swapon + +#include +_syscall2(int, swapon, const char *, path, int, swapflags) + +#endif diff --git a/libc/sysdeps/linux/common/symlink.c b/libc/sysdeps/linux/common/symlink.c new file mode 100644 index 0000000..e53e8d4 --- /dev/null +++ b/libc/sysdeps/linux/common/symlink.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * symlink() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K +#include +_syscall2(int, symlink, const char *, oldpath, const char *, newpath) +#endif diff --git a/libc/sysdeps/linux/common/sync.c b/libc/sysdeps/linux/common/sync.c new file mode 100644 index 0000000..e663c58 --- /dev/null +++ b/libc/sysdeps/linux/common/sync.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * sync syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +# if defined __USE_BSD || defined __USE_UNIX98 +#include +#include + +#ifndef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) __syscall_sync (args) +#define __NR___syscall_sync __NR_sync +static __inline__ _syscall0(void, __syscall_sync) +#endif + +void sync(void) +{ + INLINE_SYSCALL(sync, 0); +} +#endif diff --git a/libc/sysdeps/linux/common/sync_file_range.c b/libc/sysdeps/linux/common/sync_file_range.c new file mode 100644 index 0000000..7e2deff --- /dev/null +++ b/libc/sysdeps/linux/common/sync_file_range.c @@ -0,0 +1,33 @@ +/* vi: set sw=4 ts=4: */ +/* + * sync_file_range() for uClibc + * + * Copyright (C) 2008 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_GNU +#include + +#if defined __NR_sync_file_range && defined __UCLIBC_HAS_LFS__ +#define __NR___syscall_sync_file_range __NR_sync_file_range +static __inline__ _syscall6(int, __syscall_sync_file_range, int, fd, + off_t, offset_hi, off_t, offset_lo, + off_t, nbytes_hi, off_t, nbytes_lo, unsigned int, flags) +int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags) +{ + return __syscall_sync_file_range(fd, + __LONG_LONG_PAIR((long)(offset >> 32), (long)(offset & 0xffffffff)), + __LONG_LONG_PAIR((long)(nbytes >> 32), (long)(nbytes & 0xffffffff)), + flags); +} +#elif defined __UCLIBC_HAS_STUBS__ +int sync_file_range(int fd, __off64_t offset, __off64_t nbytes, unsigned int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/sys/acct.h b/libc/sysdeps/linux/common/sys/acct.h new file mode 100644 index 0000000..9ee8564 --- /dev/null +++ b/libc/sysdeps/linux/common/sys/acct.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ACCT_H +#define _SYS_ACCT_H 1 + +#include + +#define __need_time_t +#include +#include + +__BEGIN_DECLS + +#define ACCT_COMM 16 + +/* + comp_t is a 16-bit "floating" point number with a 3-bit base 8 + exponent and a 13-bit fraction. See linux/kernel/acct.c for the + specific encoding system used. +*/ + +typedef u_int16_t comp_t; + +struct acct + { + char ac_flag; /* Accounting flags. */ + u_int16_t ac_uid; /* Accounting user ID. */ + u_int16_t ac_gid; /* Accounting group ID. */ + u_int16_t ac_tty; /* Controlling tty. */ + u_int32_t ac_btime; /* Beginning time. */ + comp_t ac_utime; /* Accounting user time. */ + comp_t ac_stime; /* Accounting system time. */ + comp_t ac_etime; /* Accounting elapsed time. */ + comp_t ac_mem; /* Accounting average memory usage. */ + comp_t ac_io; /* Accounting chars transferred. */ + comp_t ac_rw; /* Accounting blocks read or written. */ + comp_t ac_minflt; /* Accounting minor pagefaults. */ + comp_t ac_majflt; /* Accounting major pagefaults. */ + comp_t ac_swaps; /* Accounting number of swaps. */ + u_int32_t ac_exitcode; /* Accounting process exitcode. */ + char ac_comm[ACCT_COMM+1]; /* Accounting command name. */ + char ac_pad[10]; /* Accounting padding bytes. */ + }; + +enum + { + AFORK = 0x01, /* Has executed fork, but no exec. */ + ASU = 0x02, /* Used super-user privileges. */ + ACORE = 0x08, /* Dumped core. */ + AXSIG = 0x10 /* Killed by a signal. */ + }; + +#define AHZ 100 + + +/* Switch process accounting on and off. */ +extern int acct (__const char *__filename) __THROW; + +__END_DECLS + +#endif /* sys/acct.h */ diff --git a/libc/sysdeps/linux/common/sys/epoll.h b/libc/sysdeps/linux/common/sys/epoll.h new file mode 100644 index 0000000..68f173a --- /dev/null +++ b/libc/sysdeps/linux/common/sys/epoll.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H 1 + +#include +#include + + +enum EPOLL_EVENTS + { + EPOLLIN = 0x001, +#define EPOLLIN EPOLLIN + EPOLLPRI = 0x002, +#define EPOLLPRI EPOLLPRI + EPOLLOUT = 0x004, +#define EPOLLOUT EPOLLOUT + EPOLLRDNORM = 0x040, +#define EPOLLRDNORM EPOLLRDNORM + EPOLLRDBAND = 0x080, +#define EPOLLRDBAND EPOLLRDBAND + EPOLLWRNORM = 0x100, +#define EPOLLWRNORM EPOLLWRNORM + EPOLLWRBAND = 0x200, +#define EPOLLWRBAND EPOLLWRBAND + EPOLLMSG = 0x400, +#define EPOLLMSG EPOLLMSG + EPOLLERR = 0x008, +#define EPOLLERR EPOLLERR + EPOLLHUP = 0x010, +#define EPOLLHUP EPOLLHUP + EPOLLONESHOT = (1 << 30), +#define EPOLLONESHOT EPOLLONESHOT + EPOLLET = (1 << 31) +#define EPOLLET EPOLLET + }; + + +/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ +#define EPOLL_CTL_ADD 1 /* Add a file decriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file decriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file decriptor epoll_event structure. */ + + +typedef union epoll_data +{ + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event +{ + uint32_t events; /* Epoll events */ + epoll_data_t data; /* User data variable */ +}; + + +__BEGIN_DECLS + +/* Creates an epoll instance. Returns an fd for the new instance. + The "size" parameter is a hint specifying the number of file + descriptors to be associated with the new instance. The fd + returned by epoll_create() should be closed with close(). */ +extern int epoll_create (int __size) __THROW; + + +/* Manipulate an epoll instance "epfd". Returns 0 in case of success, + -1 in case of error ( the "errno" variable will contain the + specific error code ) The "op" parameter is one of the EPOLL_CTL_* + constants defined above. The "fd" parameter is the target of the + operation. The "event" parameter describes which events the caller + is interested in and any associated user data. */ +extern int epoll_ctl (int __epfd, int __op, int __fd, + struct epoll_event *__event) __THROW; + + +/* Wait for events on an epoll instance "epfd". Returns the number of + triggered events returned in "events" buffer. Or -1 in case of + error with the "errno" variable set to the specific error code. The + "events" parameter is a buffer that will contain triggered + events. The "maxevents" is the maximum number of events to be + returned ( usually size of "events" ). The "timeout" parameter + specifies the maximum wait time in milliseconds (-1 == infinite). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +__END_DECLS + +#endif /* sys/epoll.h */ diff --git a/libc/sysdeps/linux/common/sys/inotify.h b/libc/sysdeps/linux/common/sys/inotify.h new file mode 100644 index 0000000..0131db9 --- /dev/null +++ b/libc/sysdeps/linux/common/sys/inotify.h @@ -0,0 +1,92 @@ +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_INOTIFY_H +#define _SYS_INOTIFY_H 1 + +#include + + +/* Structure describing an inotify event. */ +struct inotify_event +{ + int wd; /* Watch descriptor. */ + uint32_t mask; /* Watch mask. */ + uint32_t cookie; /* Cookie to synchronize two events. */ + uint32_t len; /* Length (including NULs) of name. */ + char name __flexarr; /* Name. */ +}; + + +/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */ +#define IN_ACCESS 0x00000001 /* File was accessed. */ +#define IN_MODIFY 0x00000002 /* File was modified. */ +#define IN_ATTRIB 0x00000004 /* Metadata changed. */ +#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */ +#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */ +#define IN_OPEN 0x00000020 /* File was opened. */ +#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */ +#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */ +#define IN_CREATE 0x00000100 /* Subfile was created. */ +#define IN_DELETE 0x00000200 /* Subfile was deleted. */ +#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */ +#define IN_MOVE_SELF 0x00000800 /* Self was moved. */ + +/* Events sent by the kernel. */ +#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted. */ +#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed. */ +#define IN_IGNORED 0x00008000 /* File was ignored. */ + +/* Helper events. */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */ + +/* Special flags. */ +#define IN_ONLYDIR 0x01000000 /* Only watch the path if it is a + directory. */ +#define IN_DONT_FOLLOW 0x02000000 /* Do not follow a sym link. */ +#define IN_MASK_ADD 0x20000000 /* Add to the mask of an already + existing watch. */ +#define IN_ISDIR 0x40000000 /* Event occurred against dir. */ +#define IN_ONESHOT 0x80000000 /* Only send event once. */ + +/* All events which a program can wait on. */ +#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \ + | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \ + | IN_MOVED_TO | IN_CREATE | IN_DELETE \ + | IN_DELETE_SELF | IN_MOVE_SELF) + + +__BEGIN_DECLS + +/* Create and initialize inotify instance. */ +extern int inotify_init (void) __THROW; + +/* Add watch of object NAME to inotify instance FD. Notify about + events specified by MASK. */ +extern int inotify_add_watch (int __fd, const char *__name, uint32_t __mask) + __THROW; + +/* Remove the watch specified by WD from the inotify instance FD. */ +extern int inotify_rm_watch (int __fd, uint32_t __wd) __THROW; + +__END_DECLS + +#endif /* sys/inotify.h */ diff --git a/libc/sysdeps/linux/common/sys/prctl.h b/libc/sysdeps/linux/common/sys/prctl.h new file mode 100644 index 0000000..7e9b72d --- /dev/null +++ b/libc/sysdeps/linux/common/sys/prctl.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PRCTL_H +#define _SYS_PRCTL_H 1 + +#include +#include /* The magic values come from here */ + +__BEGIN_DECLS + +/* Control process execution. */ +extern int prctl (int __option, ...) __THROW; + +__END_DECLS + +#endif /* sys/prctl.h */ diff --git a/libc/sysdeps/linux/common/sys/ptrace.h b/libc/sysdeps/linux/common/sys/ptrace.h new file mode 100644 index 0000000..b4aec4f --- /dev/null +++ b/libc/sysdeps/linux/common/sys/ptrace.h @@ -0,0 +1,129 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPXREGS = 18, +#define PT_GETFPXREGS PTRACE_GETFPXREGS + + /* Set all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPXREGS = 19, +#define PT_SETFPXREGS PTRACE_SETFPXREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/common/sys/user.h b/libc/sysdeps/linux/common/sys/user.h new file mode 100644 index 0000000..30e9b57 --- /dev/null +++ b/libc/sysdeps/linux/common/sys/user.h @@ -0,0 +1 @@ +#include diff --git a/libc/sysdeps/linux/common/syscalls.h b/libc/sysdeps/linux/common/syscalls.h new file mode 100644 index 0000000..c4f6a44 --- /dev/null +++ b/libc/sysdeps/linux/common/syscalls.h @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * Common header file for uClibc syscalls + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include + +#undef __OPTIMIZE__ +/* We absolutely do _NOT_ want interfaces silently + * being renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif + +#include diff --git a/libc/sysdeps/linux/common/sysctl.c b/libc/sysdeps/linux/common/sysctl.c new file mode 100644 index 0000000..11d53cd --- /dev/null +++ b/libc/sysdeps/linux/common/sysctl.c @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* + * _sysctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __NR__sysctl && (defined __USE_GNU || defined __USE_BSD) + +/* psm: including sys/sysctl.h would depend on kernel headers */ +extern int sysctl (int *__name, int __nlen, void *__oldval, + size_t *__oldlenp, void *__newval, size_t __newlen) __THROW; + +struct __sysctl_args { + int *name; + int nlen; + void *oldval; + size_t *oldlenp; + void *newval; + size_t newlen; + unsigned long __unused[4]; +}; + +static __always_inline +_syscall1(int, _sysctl, struct __sysctl_args *, args) + +int sysctl(int *name, int nlen, void *oldval, size_t * oldlenp, + void *newval, size_t newlen) +{ + struct __sysctl_args args = { + .name = name, + .nlen = nlen, + .oldval = oldval, + .oldlenp = oldlenp, + .newval = newval, + .newlen = newlen + }; + + return _sysctl(&args); +} +#endif diff --git a/libc/sysdeps/linux/common/sysfs.c b/libc/sysdeps/linux/common/sysfs.c new file mode 100644 index 0000000..02f37d7 --- /dev/null +++ b/libc/sysdeps/linux/common/sysfs.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * sysfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* libc isn't really supposed to export this */ +#if 0 +#include + +#if defined __USE_SVID +_syscall3(int, sysfs, int, option, unsigned int, index, char, addr) +#endif +#endif diff --git a/libc/sysdeps/linux/common/sysinfo.c b/libc/sysdeps/linux/common/sysinfo.c new file mode 100644 index 0000000..fc37aaf --- /dev/null +++ b/libc/sysdeps/linux/common/sysinfo.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sysinfo() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sysinfo, struct sysinfo *, info) diff --git a/libc/sysdeps/linux/common/tee.c b/libc/sysdeps/linux/common/tee.c new file mode 100644 index 0000000..5047767 --- /dev/null +++ b/libc/sysdeps/linux/common/tee.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * tee() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_tee +_syscall4(ssize_t, tee, int, __fdin, int, __fdout, size_t, __len, + unsigned int, __flags) +#endif diff --git a/libc/sysdeps/linux/common/time.c b/libc/sysdeps/linux/common/time.c new file mode 100644 index 0000000..9563b41 --- /dev/null +++ b/libc/sysdeps/linux/common/time.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * time() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(time) */ + +#ifdef __NR_time +_syscall1(time_t, time, time_t *, t) +#else +libc_hidden_proto(gettimeofday) + +time_t time(time_t * t) +{ + time_t result; + struct timeval tv; + + if (gettimeofday(&tv, (struct timezone *) NULL)) { + result = (time_t) - 1; + } else { + result = (time_t) tv.tv_sec; + } + if (t != NULL) { + *t = result; + } + return result; +} +#endif +libc_hidden_def(time) diff --git a/libc/sysdeps/linux/common/times.c b/libc/sysdeps/linux/common/times.c new file mode 100644 index 0000000..a6ea1fa --- /dev/null +++ b/libc/sysdeps/linux/common/times.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * times() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(times) + +_syscall1(clock_t, times, struct tms *, buf) +libc_hidden_def(times) diff --git a/libc/sysdeps/linux/common/truncate.c b/libc/sysdeps/linux/common/truncate.c new file mode 100644 index 0000000..a40ec30 --- /dev/null +++ b/libc/sysdeps/linux/common/truncate.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * truncate() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(truncate) + +_syscall2(int, truncate, const char *, path, __off_t, length) +libc_hidden_def(truncate) diff --git a/libc/sysdeps/linux/common/truncate64.c b/libc/sysdeps/linux/common/truncate64.c new file mode 100644 index 0000000..3ab6165 --- /dev/null +++ b/libc/sysdeps/linux/common/truncate64.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* truncate64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ + +#if defined __NR_truncate64 + +#if __WORDSIZE == 64 + +/* For a 64 bit machine, life is simple... */ +_syscall2(int, truncate64, const char *, path, __off64_t, length) + +#elif __WORDSIZE == 32 + +#ifndef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) __syscall_truncate64 (args) +#define __NR___syscall_truncate64 __NR_truncate64 +#if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) +static __inline__ _syscall4(int, __syscall_truncate64, const char *, path, + uint32_t, pad, unsigned long, high_length, unsigned long, low_length) +#else +static __inline__ _syscall3(int, __syscall_truncate64, const char *, path, + unsigned long, high_length, unsigned long, low_length) +#endif +#endif + + +/* The exported truncate64 function. */ +int truncate64 (const char * path, __off64_t length) +{ + uint32_t low = length & 0xffffffff; + uint32_t high = length >> 32; +#if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) + return INLINE_SYSCALL(truncate64, 4, path, 0, + __LONG_LONG_PAIR (high, low)); +#else + return INLINE_SYSCALL(truncate64, 3, path, + __LONG_LONG_PAIR (high, low)); +#endif +} + +#else /* __WORDSIZE */ +#error Your machine is not 64 bit nor 32 bit, I am dazed and confused. +#endif /* __WORDSIZE */ + +#else /* __NR_truncate64 */ + +libc_hidden_proto(truncate) + +int truncate64 (const char * path, __off64_t length) +{ + __off_t x = (__off_t) length; + + if (x == length) { + return truncate(path, x); + } + + __set_errno((x < 0) ? EINVAL : EFBIG); + + return -1; +} + +#endif /* __NR_truncate64 */ + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/ulimit.c b/libc/sysdeps/linux/common/ulimit.c new file mode 100644 index 0000000..c02c191 --- /dev/null +++ b/libc/sysdeps/linux/common/ulimit.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_ulimit + +extern long int ulimit(int cmd, long arg); +_syscall2(long, ulimit, int, cmd, long, arg) + +#else + +#include +#include +#include +#include + +libc_hidden_proto(sysconf) +libc_hidden_proto(getrlimit) +libc_hidden_proto(setrlimit) + +long int ulimit(int cmd, ...) +{ + va_list va; + struct rlimit limit; + long int result = -1; + va_start (va, cmd); + switch (cmd) { + /* Get limit on file size. */ + case UL_GETFSIZE: + if (getrlimit(RLIMIT_FSIZE, &limit) == 0) + result = limit.rlim_cur / 512; /* bytes to 512 byte blocksize */ + break; + /* Set limit on file size. */ + case UL_SETFSIZE: + result = va_arg (va, long int); + if ((rlim_t) result > RLIM_INFINITY / 512) { + limit.rlim_cur = RLIM_INFINITY; + limit.rlim_max = RLIM_INFINITY; + } else { + limit.rlim_cur = result * 512; + limit.rlim_max = result * 512; + } + result = setrlimit(RLIMIT_FSIZE, &limit); + break; + case __UL_GETOPENMAX: + result = sysconf(_SC_OPEN_MAX); + break; + default: + __set_errno(EINVAL); + } + va_end (va); + return result; +} +#endif diff --git a/libc/sysdeps/linux/common/umask.c b/libc/sysdeps/linux/common/umask.c new file mode 100644 index 0000000..ef9860e --- /dev/null +++ b/libc/sysdeps/linux/common/umask.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * umask() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_umask __NR_umask +static __inline__ _syscall1(__kernel_mode_t, __syscall_umask, __kernel_mode_t, mode) + +mode_t umask(mode_t mode) +{ + return (__syscall_umask(mode)); +} diff --git a/libc/sysdeps/linux/common/umount.c b/libc/sysdeps/linux/common/umount.c new file mode 100644 index 0000000..453ecd2 --- /dev/null +++ b/libc/sysdeps/linux/common/umount.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * umount() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_GNU +#include + +/* arch provides umount() syscall */ +#ifdef __NR_umount + +_syscall1(int, umount, const char *, specialfile) + +/* arch provides umount2() syscall */ +#elif defined __NR_umount2 + +# define __NR___syscall_umount2 __NR_umount2 +static __inline__ _syscall2(int, __syscall_umount2, const char *, special_file, int, flags) + +int umount(const char *special_file) +{ + return (__syscall_umount2(special_file, 0)); +} + +/* arch doesn't provide any umount syscall !? */ +#else + +int umount(const char *special_file) +{ + __set_errno(ENOSYS); + return -1; +} + +#endif +#endif diff --git a/libc/sysdeps/linux/common/umount2.c b/libc/sysdeps/linux/common/umount2.c new file mode 100644 index 0000000..bd44717 --- /dev/null +++ b/libc/sysdeps/linux/common/umount2.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * umount2() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_GNU +#include +#ifdef __NR_umount2 /* Old kernels don't have umount2 */ +_syscall2(int, umount2, const char *, special_file, int, flags) +#else +int umount2(const char *special_file, int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/libc/sysdeps/linux/common/uname.c b/libc/sysdeps/linux/common/uname.c new file mode 100644 index 0000000..1b51687 --- /dev/null +++ b/libc/sysdeps/linux/common/uname.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * uname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(uname) + +_syscall1(int, uname, struct utsname *, buf) +libc_hidden_def(uname) diff --git a/libc/sysdeps/linux/common/unlink.c b/libc/sysdeps/linux/common/unlink.c new file mode 100644 index 0000000..9b1f38b --- /dev/null +++ b/libc/sysdeps/linux/common/unlink.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * unlink() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(unlink) + +_syscall1(int, unlink, const char *, pathname) +libc_hidden_def(unlink) diff --git a/libc/sysdeps/linux/common/uselib.c b/libc/sysdeps/linux/common/uselib.c new file mode 100644 index 0000000..b2b806f --- /dev/null +++ b/libc/sysdeps/linux/common/uselib.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * uselib() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#if 0 +linux specific and we do not use it in uClibc. + +#include +#include +#ifdef __NR_uselib +int uselib (const char *library); +_syscall1(int, uselib, const char *, library) +#endif +#endif diff --git a/libc/sysdeps/linux/common/ustat.c b/libc/sysdeps/linux/common/ustat.c new file mode 100644 index 0000000..09edaa3 --- /dev/null +++ b/libc/sysdeps/linux/common/ustat.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * ustat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_ustat __NR_ustat +static __inline__ _syscall2(int, __syscall_ustat, + unsigned short int, kdev_t, struct ustat *, ubuf) + +int ustat(dev_t dev, struct ustat *ubuf) +{ + /* We must convert the dev_t value to a __kernel_dev_t */ + __kernel_dev_t k_dev; + + k_dev = ((major(dev) & 0xff) << 8) | (minor(dev) & 0xff); + return __syscall_ustat(k_dev, ubuf); +} diff --git a/libc/sysdeps/linux/common/utime.c b/libc/sysdeps/linux/common/utime.c new file mode 100644 index 0000000..fd528bd --- /dev/null +++ b/libc/sysdeps/linux/common/utime.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * utime() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(utime) + +#ifdef __NR_utime +_syscall2(int, utime, const char *, file, const struct utimbuf *, times) +#else +#include +#include + +libc_hidden_proto(utimes) +libc_hidden_proto(gettimeofday) + +int utime(const char *file, const struct utimbuf *times) +{ + struct timeval timevals[2]; + + if (times != NULL) { + timevals[0].tv_usec = 0L; + timevals[1].tv_usec = 0L; + timevals[0].tv_sec = (long int) times->actime; + timevals[1].tv_sec = (long int) times->modtime; + } + return utimes(file, times ? timevals : NULL); +} +#endif +libc_hidden_def(utime) diff --git a/libc/sysdeps/linux/common/utimes.c b/libc/sysdeps/linux/common/utimes.c new file mode 100644 index 0000000..e62faff --- /dev/null +++ b/libc/sysdeps/linux/common/utimes.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * utimes() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(utimes) + +#ifdef __NR_utimes +_syscall2(int, utimes, const char *, file, const struct timeval *, tvp) +#else +#include + +libc_hidden_proto(utime) + +int utimes(const char *file, const struct timeval tvp[2]) +{ + struct utimbuf buf, *times; + + if (tvp) { + times = &buf; + times->actime = tvp[0].tv_sec; + times->modtime = tvp[1].tv_sec; + } else { + times = NULL; + } + return utime(file, times); +} +#endif +link_warning(utimes, "the use of LEGACY `utimes' is discouraged, use `utime'") +libc_hidden_def(utimes) diff --git a/libc/sysdeps/linux/common/vfork.c b/libc/sysdeps/linux/common/vfork.c new file mode 100644 index 0000000..f9634cd --- /dev/null +++ b/libc/sysdeps/linux/common/vfork.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Trivial implementation for arches that lack vfork */ +#include +#include +#include + +#ifdef __ARCH_USE_MMU__ + +#ifdef __NR_fork +libc_hidden_proto(fork) + +extern __typeof(vfork) __vfork attribute_hidden; +pid_t __vfork(void) +{ + return fork(); +} +libc_hidden_proto(vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) +#endif + +#endif diff --git a/libc/sysdeps/linux/common/vhangup.c b/libc/sysdeps/linux/common/vhangup.c new file mode 100644 index 0000000..77910e6 --- /dev/null +++ b/libc/sysdeps/linux/common/vhangup.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * vhangup() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall0(int, vhangup) +#endif diff --git a/libc/sysdeps/linux/common/vmsplice.c b/libc/sysdeps/linux/common/vmsplice.c new file mode 100644 index 0000000..2d32f20 --- /dev/null +++ b/libc/sysdeps/linux/common/vmsplice.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * vmsplice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +libc_hidden_proto(vmsplice) + +#ifdef __NR_vmsplice +_syscall4(ssize_t, vmsplice, int, __fdout, const struct iovec *, __iov, + size_t, __count, unsigned int, __flags) +#else +ssize_t vmsplice(int __fdout, const struct iovec *__iov, size_t __count, + unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +libc_hidden_def(vmsplice) + diff --git a/libc/sysdeps/linux/common/wait.c b/libc/sysdeps/linux/common/wait.c new file mode 100644 index 0000000..39d0e47 --- /dev/null +++ b/libc/sysdeps/linux/common/wait.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(wait4) + +extern __typeof(wait) __libc_wait; + +/* Wait for a child to die. When one does, put its status in *STAT_LOC + * and return its process ID. For errors, return (pid_t) -1. */ +__pid_t __libc_wait (__WAIT_STATUS_DEFN stat_loc) +{ + return wait4 (WAIT_ANY, stat_loc, 0, (struct rusage *) NULL); +} +weak_alias(__libc_wait,wait) diff --git a/libc/sysdeps/linux/common/wait3.c b/libc/sysdeps/linux/common/wait3.c new file mode 100644 index 0000000..8a2d43f --- /dev/null +++ b/libc/sysdeps/linux/common/wait3.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD + +libc_hidden_proto(wait4) + +/* Wait for a child to exit. When one does, put its status in *STAT_LOC and + * return its process ID. For errors return (pid_t) -1. If USAGE is not nil, + * store information about the child's resource usage (as a `struct rusage') + * there. If the WUNTRACED bit is set in OPTIONS, return status for stopped + * children; otherwise don't. */ +pid_t wait3 (__WAIT_STATUS stat_loc, int options, struct rusage * usage) +{ + return wait4 (WAIT_ANY, stat_loc, options, usage); +} +#endif diff --git a/libc/sysdeps/linux/common/wait4.c b/libc/sysdeps/linux/common/wait4.c new file mode 100644 index 0000000..c62a855 --- /dev/null +++ b/libc/sysdeps/linux/common/wait4.c @@ -0,0 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * wait4() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +#include +#include + +libc_hidden_proto(wait4) + +#define __NR___syscall_wait4 __NR_wait4 +static __inline__ _syscall4(int, __syscall_wait4, __kernel_pid_t, pid, + int *, status, int, opts, struct rusage *, rusage) + +pid_t wait4(pid_t pid, int *status, int opts, struct rusage *rusage) +{ + return (__syscall_wait4(pid, status, opts, rusage)); +} +libc_hidden_def(wait4) +#endif diff --git a/libc/sysdeps/linux/common/waitid.c b/libc/sysdeps/linux/common/waitid.c new file mode 100644 index 0000000..ce3d5dc --- /dev/null +++ b/libc/sysdeps/linux/common/waitid.c @@ -0,0 +1,51 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2007 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_SVID || defined __USE_XOPEN +# include +# include +# include +# ifdef __NR_waitid +_syscall4(int, waitid, idtype_t, idtype, id_t, id, siginfo_t*, infop, int, options) +# else +# include +libc_hidden_proto(waitpid) +int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) +{ + switch (idtype) { + case P_PID: + if (id <= 0) + goto invalid; + break; + case P_PGID: + if (id < 0 || id == 1) + goto invalid; + id = -id; + break; + case P_ALL: + id = -1; + break; + default: + invalid: + __set_errno(EINVAL); + return -1; + } + + memset(infop, 0, sizeof *infop); + infop->si_pid = waitpid(id, &infop->si_status, options +# ifdef WEXITED + &~ WEXITED +# endif + ); + if (infop->si_pid < 0) + return infop->si_pid; + return 0; +} +# endif +#endif diff --git a/libc/sysdeps/linux/common/waitpid.c b/libc/sysdeps/linux/common/waitpid.c new file mode 100644 index 0000000..c1766be --- /dev/null +++ b/libc/sysdeps/linux/common/waitpid.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(wait4) + +extern __typeof(waitpid) __libc_waitpid; +__pid_t __libc_waitpid(__pid_t pid, int *wait_stat, int options) +{ + return wait4(pid, wait_stat, options, NULL); +} +libc_hidden_proto(waitpid) +weak_alias(__libc_waitpid,waitpid) +libc_hidden_weak(waitpid) diff --git a/libc/sysdeps/linux/common/write.c b/libc/sysdeps/linux/common/write.c new file mode 100644 index 0000000..f280d90 --- /dev/null +++ b/libc/sysdeps/linux/common/write.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * write() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(write) __libc_write; +#define __NR___libc_write __NR_write +_syscall3(ssize_t, __libc_write, int, fd, const __ptr_t, buf, size_t, count) +libc_hidden_proto(write) +weak_alias(__libc_write,write) +libc_hidden_weak(write) +#if 0 +/* Stupid libgcc.a from gcc 2.95.x uses __write in pure.o + * which is a blatent GNU libc-ism... */ +strong_alias(__libc_write,__write) +#endif diff --git a/libc/sysdeps/linux/common/writev.c b/libc/sysdeps/linux/common/writev.c new file mode 100644 index 0000000..c393bee --- /dev/null +++ b/libc/sysdeps/linux/common/writev.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * writev() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(writev) __libc_writev; + +#define __NR___libc_writev __NR_writev +_syscall3(ssize_t, __libc_writev, int, filedes, const struct iovec *, vector, + int, count) +weak_alias(__libc_writev,writev) diff --git a/libc/sysdeps/linux/common/xattr.c b/libc/sysdeps/linux/common/xattr.c new file mode 100644 index 0000000..8a4e3be --- /dev/null +++ b/libc/sysdeps/linux/common/xattr.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2004 + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* This file provides the following Extended Attribute system calls to uClibc. + * + * setxattr(), lsetxattr(), fsetxattr(), + * getxattr(), lgetxattr(), fgetxattr(), + * listxattr(), llistxattr(), flistxattr(), + * removexattr(), lremovexattr(), fremovexattr() + * + * Dec 2004 - + */ + +/* Taken from the manpage. + * On success, a positive number is returned indicating the size of the + * extended attribute name list. On failure, -1 is returned and errno + * is set appropriately. If extended attributes are not supported by the + * filesystem, or are disabled, errno is set to ENOSYS. + */ + +#include +#include +#include + +/* sets */ +#ifdef __NR_setxattr +_syscall5(int, setxattr, const char *, path, const char *, name, + const void *, value, size_t, size, int, flags) +#else +int setxattr(__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lsetxattr +_syscall5(int, lsetxattr, const char *, path, const char *, name, + const void *, value, size_t, size, int, flags) +#else +int lsetxattr(__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fsetxattr +_syscall5(int, fsetxattr, int, filedes, const char *, name, const void *, + value, size_t, size, int, flags) +#else +int fsetxattr(int __fd, __const char *__name, __const void *__value, + size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* gets */ +#ifdef __NR_getxattr +_syscall4(ssize_t, getxattr, const char *, path, const char *, name, + void *, value, size_t, size) +#else +ssize_t getxattr(__const char *__path, __const char *__name, void *__value, + size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lgetxattr +_syscall4(ssize_t, lgetxattr, const char *, path, const char *, name, + void *, value, size_t, size) +#else +ssize_t lgetxattr(__const char *__path, __const char *__name, + void *__value, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fgetxattr +_syscall4(ssize_t, fgetxattr, int, filedes, const char *, name, void *, + value, size_t, size) +#else +ssize_t fgetxattr(int __fd, __const char *__name, void *__value, + size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* list */ +#ifdef __NR_listxattr +_syscall3(ssize_t, listxattr, const char *, path, char *, list, size_t, + size) +#else +ssize_t listxattr(__const char *__path, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_llistxattr +_syscall3(ssize_t, llistxattr, const char *, path, char *, list, size_t, + size) +#else +ssize_t llistxattr(__const char *__path, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_flistxattr +_syscall3(ssize_t, flistxattr, int, filedes, char *, list, size_t, size) +#else +ssize_t flistxattr(int __fd, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* remove */ +#ifdef __NR_removexattr +_syscall2(int, removexattr, const char *, path, const char *, name) +#else +int removexattr(__const char *__path, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lremovexattr +_syscall2(int, lremovexattr, const char *, path, const char *, name) +#else +int lremovexattr(__const char *__path, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fremovexattr +_syscall2(int, fremovexattr, int, filedes, const char *, name) +#else +int fremovexattr(int __fd, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/xstatconv.c b/libc/sysdeps/linux/common/xstatconv.c new file mode 100644 index 0000000..abcb496 --- /dev/null +++ b/libc/sysdeps/linux/common/xstatconv.c @@ -0,0 +1,83 @@ +/* Convert between the kernel's `struct stat' format, and libc's. + Copyright (C) 1991,1995,1996,1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Modified for uClibc by Erik Andersen + */ + +#include +#include +#include +#include "xstatconv.h" + +/* Experimentally off - libc_hidden_proto(memset) */ + +void attribute_hidden __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) +{ + /* Convert to current kernel version of `struct stat'. */ + memset(buf, 0x00, sizeof(*buf)); + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atime = kbuf->st_atime; + buf->st_mtime = kbuf->st_mtime; + buf->st_ctime = kbuf->st_ctime; +#ifdef STAT_HAVE_NSEC + buf->st_atimensec = kbuf->st_atime_nsec; + buf->st_mtimensec = kbuf->st_mtime_nsec; + buf->st_ctimensec = kbuf->st_ctime_nsec; +#endif +} + +#ifdef __UCLIBC_HAS_LFS__ + +void attribute_hidden __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) +{ + /* Convert to current kernel version of `struct stat64'. */ + memset(buf, 0x00, sizeof(*buf)); + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; +# ifdef _HAVE_STAT64___ST_INO + buf->__st_ino = kbuf->__st_ino; +# endif + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atime = kbuf->st_atime; + buf->st_mtime = kbuf->st_mtime; + buf->st_ctime = kbuf->st_ctime; +# ifdef STAT_HAVE_NSEC + buf->st_atimensec = kbuf->st_atime_nsec; + buf->st_mtimensec = kbuf->st_mtime_nsec; + buf->st_ctimensec = kbuf->st_ctime_nsec; +# endif +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/common/xstatconv.h b/libc/sysdeps/linux/common/xstatconv.h new file mode 100644 index 0000000..57c8bcb --- /dev/null +++ b/libc/sysdeps/linux/common/xstatconv.h @@ -0,0 +1,32 @@ +/* Convert between the kernel's `struct stat' format, and libc's. + Copyright (C) 1991,1995,1996,1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Modified for uClibc by Erik Andersen + */ + +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#include + +extern void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) attribute_hidden; +#if defined __UCLIBC_HAS_LFS__ +extern void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) attribute_hidden; +#endif + diff --git a/libc/sysdeps/linux/cris/Makefile b/libc/sysdeps/linux/cris/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/cris/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/cris/Makefile.arch b/libc/sysdeps/linux/cris/Makefile.arch new file mode 100644 index 0000000..850c83d --- /dev/null +++ b/libc/sysdeps/linux/cris/Makefile.arch @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __init_brk.c brk.c sbrk.c + +SSRC := setjmp.S __longjmp.S clone.S sysdep.S syscall.S +ifeq ($(UNIFIED_SYSCALL),y) +SSRC += __uClibc_syscall.S +endif + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/cris/__init_brk.c b/libc/sysdeps/linux/cris/__init_brk.c new file mode 100644 index 0000000..27b8524 --- /dev/null +++ b/libc/sysdeps/linux/cris/__init_brk.c @@ -0,0 +1,32 @@ +/* From libc-5.3.12 */ + +#include +#include +#include +#include "sysdep.h" + +void * __curbrk attribute_hidden = 0; + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) { + /* Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("clear.d $r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : + : "r9", "r10"); + + if (__curbrk == 0) { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/libc/sysdeps/linux/cris/__longjmp.S b/libc/sysdeps/linux/cris/__longjmp.S new file mode 100644 index 0000000..52a986f --- /dev/null +++ b/libc/sysdeps/linux/cris/__longjmp.S @@ -0,0 +1,62 @@ +/* longjmp for CRIS. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "sysdep.h" +#define _SETJMP_H +#define _ASM +#include + + .syntax no_register_prefix + +/* Saving and restoring CCR is meaningless, so we don't do it. */ +ENTRY (__longjmp) + /* Note that r10 = jmp_buf, r11 = retval. */ +#ifdef __arch_v32 + + /* We don't restore the call-clobbered registers for v32; + their space (corresponding to v10) is now defined as + reserved. */ + movem [r10],r9 + addq 14*4,r10 + cmpq 0,r11 + beq 0f + move.d [r10+],sp + + move.d r11,r9 +0: + move.d [r10+],acr + jump acr + move [r10],srp + +#else + + move [r10+16*4],srp + test.d r11 + beq 0f /* Already a 1 in place. */ + nop + /* Offset for r9, the return value (see setjmp). */ + move.d r11,[r10+6*4] +0: + movem [r10],pc + +#endif +END (__longjmp) + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/cris/bits/byteswap.h b/libc/sysdeps/linux/cris/bits/byteswap.h new file mode 100644 index 0000000..4027456 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/byteswap.h @@ -0,0 +1,83 @@ +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* CRIS specific byte swap operations: 16, 32 and 64-bit */ + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ +({ \ + unsigned short __x = (x); \ + ((unsigned short)( \ + (((unsigned short)(__x) & (unsigned short)0x00ffu) << 8) | \ + (((unsigned short)(__x) & (unsigned short)0xff00u) >> 8) )); \ +}) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_16(x) \ + __extension__ \ + ({ unsigned short __bswap_16_v; \ + if (__builtin_constant_p (x)) \ + __bswap_16_v = __bswap_constant_16 (x); \ + else \ + __asm__ ("swapb %0" : "=r" (__bswap_16_v) : "0" (x)); \ + __bswap_16_v; }) +#else +# define __bswap_16(x) __bswap_constant_16 (x) +#endif + + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ +({ \ + unsigned long __x = (x); \ + ((unsigned long)( \ + (((unsigned long)(__x) & (unsigned long)0x000000fful) << 24) | \ + (((unsigned long)(__x) & (unsigned long)0x0000ff00ul) << 8) | \ + (((unsigned long)(__x) & (unsigned long)0x00ff0000ul) >> 8) | \ + (((unsigned long)(__x) & (unsigned long)0xff000000ul) >> 24) )); \ +}) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_32(x) \ + __extension__ \ + ({ unsigned long __bswap_32_v; \ + if (__builtin_constant_p (x)) \ + __bswap_32_v = __bswap_constant_32 (x); \ + else \ + __asm__ ("swapwb %0" : "=r" (__bswap_32_v) : "0" (x)); \ + __bswap_32_v; }) +#else +# define __bswap_32(x) __bswap_constant_32 (x) +#endif + + +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#else +# define __bswap_64(x) __bswap_constant_64 (x) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/cris/bits/endian.h b/libc/sysdeps/linux/cris/bits/endian.h new file mode 100644 index 0000000..90e290b --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/endian.h @@ -0,0 +1,7 @@ +/* cris is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/cris/bits/fcntl.h b/libc/sysdeps/linux/cris/bits/fcntl.h new file mode 100644 index 0000000..2637a6b --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/cris/bits/kernel_stat.h b/libc/sysdeps/linux/cris/bits/kernel_stat.h new file mode 100644 index 0000000..50202e5 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/kernel_stat.h @@ -0,0 +1,84 @@ +/* Taken from linux/include/asm-cris/stat.h */ + +#ifndef _CRIS_STAT_H +#define _CRIS_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +/* This matches struct kernel_stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long __pad5; + + unsigned long st_mtime; + unsigned long __pad6; + + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + + unsigned long long st_ino; +}; + +#endif diff --git a/libc/sysdeps/linux/cris/bits/kernel_types.h b/libc/sysdeps/linux/cris/bits/kernel_types.h new file mode 100644 index 0000000..f122c7f --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/kernel_types.h @@ -0,0 +1,46 @@ +/* Taken from linux/include/asm-cris/posix_types.h */ + +#ifndef __ARCH_CRIS_POSIX_TYPES_H +#define __ARCH_CRIS_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif + } __kernel_fsid_t; + +/* should this ifdef be here ? */ + +#endif /* __ARCH_CRIS_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/cris/bits/mman.h b/libc/sysdeps/linux/cris/bits/mman.h new file mode 100644 index 0000000..ec9d2a5 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/mman.h @@ -0,0 +1,98 @@ +/* Definitions for POSIX memory map interface. Linux/CRIS version. + Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/cris/bits/setjmp.h b/libc/sysdeps/linux/cris/bits/setjmp.h new file mode 100644 index 0000000..2a29c8c --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/setjmp.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. CRIS version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* + Note that we save and restore CCR to be able to + correctly handle DI/EI. Note also that the "move x,ccr" does NOT affect + the DMA enable bits (E and D). + + jmp_buf[0] - PC + jmp_buf[1] - SP (R14) + jmp_buf[2] - R13 + jmp_buf[3] - R12 + jmp_buf[4] - R11 + jmp_buf[5] - R10 + jmp_buf[6] - R9 + jmp_buf[7] - R8 + jmp_buf[8] - R7 + jmp_buf[9] - R6 + jmp_buf[10] - R5 + jmp_buf[11] - R4 + jmp_buf[12] - R3 + jmp_buf[13] - R2 + jmp_buf[14] - R1 + jmp_buf[15] - R0 + jmp_buf[16] - SRP + jmp_buf[17] - CCR + */ + +#define _JBLEN 18 +#if defined (__USE_MISC) || defined (_ASM) +#define JB_SP 1 +#endif + +#ifndef _ASM +typedef int __jmp_buf[_JBLEN]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/cris/bits/stackinfo.h b/libc/sysdeps/linux/cris/bits/stackinfo.h new file mode 100644 index 0000000..43c9448 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On cris the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/cris/bits/syscalls.h b/libc/sysdeps/linux/cris/bits/syscalls.h new file mode 100644 index 0000000..93e7cf2 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/syscalls.h @@ -0,0 +1,159 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +#error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned long __sys_res; \ + register unsigned long __res __asm__ ("r10"); \ + LOAD_ARGS_c_##nr (args) \ + register unsigned long __callno __asm__ ("r9") \ + = SYS_ify (name); \ + __asm__ __volatile__ (LOAD_ARGS_asm_##nr (args) \ + CHECK_ARGS_asm_##nr \ + "break 13" \ + : "=r" (__res) \ + : ASM_ARGS_##nr (args) \ + : ASM_CLOBBER_##nr); \ + __sys_res = __res; \ + \ + if (__sys_res >= (unsigned long) -4096) \ + { \ + __set_errno (- __sys_res); \ + __sys_res = (unsigned long) -1; \ + } \ + __sys_res; \ + }) + +#define LOAD_ARGS_c_0() +#define LOAD_ARGS_asm_0() +#define ASM_CLOBBER_0 "memory" +#define ASM_ARGS_0() "r" (__callno) +#define CHECK_ARGS_asm_0 + +#define LOAD_ARGS_c_1(r10) \ + LOAD_ARGS_c_0() \ + register unsigned long __r10 __asm__ ("r10") = (unsigned long) (r10); +#define LOAD_ARGS_asm_1(r10) LOAD_ARGS_asm_0 () +#define ASM_CLOBBER_1 ASM_CLOBBER_0 +#define ASM_ARGS_1(r10) ASM_ARGS_0 (), "0" (__r10) +#define CHECK_ARGS_asm_1 \ + ".ifnc %0,$r10\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_2(r10, r11) \ + LOAD_ARGS_c_1(r10) \ + register unsigned long __r11 __asm__ ("r11") = (unsigned long) (r11); +#define LOAD_ARGS_asm_2(r10, r11) LOAD_ARGS_asm_1 (r10) +#define ASM_CLOBBER_2 ASM_CLOBBER_1 +#define ASM_ARGS_2(r10, r11) ASM_ARGS_1 (r10), "r" (__r11) +#define CHECK_ARGS_asm_2 \ + ".ifnc %0-%3,$r10-$r11\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_3(r10, r11, r12) \ + LOAD_ARGS_c_2(r10, r11) \ + register unsigned long __r12 __asm__ ("r12") = (unsigned long) (r12); +#define LOAD_ARGS_asm_3(r10, r11, r12) LOAD_ARGS_asm_2 (r10, r11) +#define ASM_CLOBBER_3 ASM_CLOBBER_2 +#define ASM_ARGS_3(r10, r11, r12) ASM_ARGS_2 (r10, r11), "r" (__r12) +#define CHECK_ARGS_asm_3 \ + ".ifnc %0-%3-%4,$r10-$r11-$r12\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_4(r10, r11, r12, r13) \ + LOAD_ARGS_c_3(r10, r11, r12) \ + register unsigned long __r13 __asm__ ("r13") = (unsigned long) (r13); +#define LOAD_ARGS_asm_4(r10, r11, r12, r13) LOAD_ARGS_asm_3 (r10, r11, r12) +#define ASM_CLOBBER_4 ASM_CLOBBER_3 +#define ASM_ARGS_4(r10, r11, r12, r13) ASM_ARGS_3 (r10, r11, r12), "r" (__r13) +#define CHECK_ARGS_asm_4 \ + ".ifnc %0-%3-%4-%5,$r10-$r11-$r12-$r13\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_c_4(r10, r11, r12, r13) +#define LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_asm_4 (r10, r11, r12, r13) "move %6,$mof\n\t" +#define ASM_CLOBBER_5 ASM_CLOBBER_4 +#define ASM_ARGS_5(r10, r11, r12, r13, mof) \ + ASM_ARGS_4 (r10, r11, r12, r13), "g" (mof) +#define CHECK_ARGS_asm_5 CHECK_ARGS_asm_4 + +#define LOAD_ARGS_c_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_c_5(r10, r11, r12, r13, mof) +#define LOAD_ARGS_asm_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + "move %7,$srp\n\t" +#define ASM_CLOBBER_6 ASM_CLOBBER_5, "srp" +#define ASM_ARGS_6(r10, r11, r12, r13, mof, srp) \ + ASM_ARGS_5 (r10, r11, r12, r13, mof), "g" (srp) +#define CHECK_ARGS_asm_6 CHECK_ARGS_asm_5 + +#endif /* not __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/cris/bits/termios.h b/libc/sysdeps/linux/cris/bits/termios.h new file mode 100644 index 0000000..63ca4ea --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/termios.h @@ -0,0 +1,215 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#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 + +/* c_iflag bits */ +#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 IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# 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 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#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 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#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 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B921600 0010005 +#define B1843200 0010006 +#define B6250000 0010007 +#ifdef __arch_v32 +#define B12500000 0010010 +#define __MAX_BAUD B12500000 +#else +#define __MAX_BAUD B6250000 +#endif +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h b/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h new file mode 100644 index 0000000..bdd3387 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h @@ -0,0 +1,42 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* lovely */ +#define __UCLIBC_ASM_LINE_SEP__ @ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/cris/bits/uClibc_page.h b/libc/sysdeps/linux/cris/bits/uClibc_page.h new file mode 100644 index 0000000..adfc3c9 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/uClibc_page.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 8192 */ +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +#define MMAP2_PAGE_SHIFT PAGE_SHIFT + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/cris/bits/wordsize.h b/libc/sysdeps/linux/cris/bits/wordsize.h new file mode 100644 index 0000000..d6a2fc6 --- /dev/null +++ b/libc/sysdeps/linux/cris/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/cris/brk.c b/libc/sysdeps/linux/cris/brk.c new file mode 100644 index 0000000..ae99e10 --- /dev/null +++ b/libc/sysdeps/linux/cris/brk.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "sysdep.h" + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; + +libc_hidden_proto(brk) +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) { + /* + * Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("move.d %1,$r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : "g" (end_data_seg) + : "r9", "r10"); + + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; + +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/cris/clone.S b/libc/sysdeps/linux/cris/clone.S new file mode 100644 index 0000000..9e284fe --- /dev/null +++ b/libc/sysdeps/linux/cris/clone.S @@ -0,0 +1,96 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "sysdep.h" +#define _ERRNO_H 1 +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .syntax no_register_prefix + + .text +ENTRY (clone) + /* Sanity check arguments: No NULL function pointers. Allow a NULL + stack pointer though; it makes the kernel allocate stack. */ + cmpq 0,r10 + beq 1f + nop + + /* We need to muck with a few registers. */ + subq 8,sp + movem r1,[sp] + + /* Save the function pointer and argument. We can't save them + onto the new stack since it can be NULL. */ + move.d r10,r0 + move.d r13,r1 + + /* Move the other arguments into place for the system call. */ + move.d r11,r10 + move.d r12,r11 + + /* Do the system call. */ + movu.w SYS_ify (clone),r9 + break 13 + cmpq 0,r10 + beq .Lthread_start + nop + + /* Jump to error handler if we get (unsigned) -4096 .. 0xffffffff. */ + cmps.w -4096,r10 + bhs 0f + movem [sp+],r1 + + /* In parent, successful return. (Avoid using "ret" - it's a macro.) */ + Ret + nop + +.Lthread_start: + /* Terminate frame pointers here. */ + moveq 0,r8 + +#ifdef __arch_v32 + /* Is this the right place for an argument? */ + jsr r0 + move.d r1,r10 +#else + /* I've told you once. */ + move.d r1,r10 + jsr r0 +#endif + + SETUP_PIC + PLTCALL (HIDDEN_JUMPTARGET(_exit)) + + /* Die horribly. */ + move.d 6809,r13 + test.d [r13] + + /* Stop the unstoppable. */ +9: + ba 9b + nop + +/* Local error handler. */ +1: + movs.w -EINVAL,r10 + /* Drop through into the ordinary error handler. */ +PSEUDO_END (clone) diff --git a/libc/sysdeps/linux/cris/crt1.S b/libc/sysdeps/linux/cris/crt1.S new file mode 100644 index 0000000..b07e36b --- /dev/null +++ b/libc/sysdeps/linux/cris/crt1.S @@ -0,0 +1,56 @@ +/* Startup code compliant to the ELF CRIS ABI */ + +#include + + .syntax no_register_prefix + +/* The first piece of initialized data. */ + .data + .global __data_start + .align 2 + .type __data_start, @object + .size __data_start, 4 +__data_start: + .dword 0 + + .text + .align 1 + .global _start + .type _start, %function +#if defined(__UCLIBC_CTOR_DTOR__) + .type _init, %function + .type _fini, %function +#else + .weak _init + .weak _fini +#endif + .type main, %function + .type __uClibc_main, %function + +/* + * On the stack we have argc. We can calculate argv/envp + * from that and the succeeding stack location, but fix so + * we get the right calling convention (regs in r10/r11). + * + * Please view linux/fs/binfmt_elf.c for a complete + * understanding of this. + */ + +/* + * Need to call __uClibc_main(main, argc, argv, _init, _fini) + */ + +_start: + move.d main, r10 + move.d [sp+], r11 + move.d sp, r12 + subq 4, sp + move srp, [sp] + subq 4, sp + move.d _fini, r13 + move.d r13, [sp] + move.d _init, r13 + /* Leave control to the libc */ + jsr __uClibc_main + nop + .size _start, .-_start diff --git a/libc/sysdeps/linux/cris/crti.S b/libc/sysdeps/linux/cris/crti.S new file mode 100644 index 0000000..d9e1397 --- /dev/null +++ b/libc/sysdeps/linux/cris/crti.S @@ -0,0 +1,37 @@ +/* glibc's sysdeps/cris/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 1 + .global _init + .type _init, @function +_init: + subq 4,$sp + move.d $r1,[$sp] + move $srp,$r1 + subq 4,$sp + move.d $r0,[$sp] +#ifdef __arch_v32 + lapc _GLOBAL_OFFSET_TABLE_,$r0 +#else + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 +#endif + .align 1 + + .section .fini + .align 1 + .global _fini + .type _fini, @function +_fini: + subq 4,$sp + move.d $r1,[$sp] + move $srp,$r1 + subq 4,$sp + move.d $r0,[$sp] +#ifdef __arch_v32 + lapc _GLOBAL_OFFSET_TABLE_,$r0 +#else + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 +#endif + .align 1 diff --git a/libc/sysdeps/linux/cris/crtn.S b/libc/sysdeps/linux/cris/crtn.S new file mode 100644 index 0000000..951ae54 --- /dev/null +++ b/libc/sysdeps/linux/cris/crtn.S @@ -0,0 +1,23 @@ +/* glibc's sysdeps/cris/elf/initfini.c used for reference [EPILOG] */ + + .section .init + .align 1 + .global _init + .type _init, @function + move.d [$sp+],$r0 + move $r1,$srp + move.d [$sp+],$r1 + Ret + nop + .size _init, .-_init + + .section .fini + .align 1 + .global _fini + .type _fini, @function + move.d [$sp+],$r0 + move $r1,$srp + move.d [$sp+],$r1 + Ret + nop + .size _fini, .-_fini diff --git a/libc/sysdeps/linux/cris/fork.c b/libc/sysdeps/linux/cris/fork.c new file mode 100644 index 0000000..20b5469 --- /dev/null +++ b/libc/sysdeps/linux/cris/fork.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "sysdep.h" + +#define __NR___libc_fork __NR_fork +SYSCALL__ (__libc_fork, 0) + /* R1 is now 0 for the parent and 1 for the child. Decrement it to + make it -1 (all bits set) for the parent, and 0 (no bits set) + for the child. Then AND it with R0, so the parent gets + R0&-1==R0, and the child gets R0&0==0. */ + /* i dunno what the blurb above is useful for. we just return. */ +__asm__("ret\n\tnop"); +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/libc/sysdeps/linux/cris/libc.map b/libc/sysdeps/linux/cris/libc.map new file mode 100644 index 0000000..6710c73 --- /dev/null +++ b/libc/sysdeps/linux/cris/libc.map @@ -0,0 +1,3 @@ +U { + local: __sigjmp_save; +}; diff --git a/libc/sysdeps/linux/cris/sbrk.c b/libc/sysdeps/linux/cris/sbrk.c new file mode 100644 index 0000000..830d01d --- /dev/null +++ b/libc/sysdeps/linux/cris/sbrk.c @@ -0,0 +1,42 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "sysdep.h" + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; + +libc_hidden_proto(sbrk) +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) { + void * tmp = __curbrk + increment; + + /* + * Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("move.d %1,$r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : "g" (tmp) + : "r9", "r10"); + + if (__curbrk == tmp) + return tmp - increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/libc/sysdeps/linux/cris/setjmp.S b/libc/sysdeps/linux/cris/setjmp.S new file mode 100644 index 0000000..e7bb635 --- /dev/null +++ b/libc/sysdeps/linux/cris/setjmp.S @@ -0,0 +1,84 @@ +/* setjmp for CRIS. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#define _SETJMP_H +#define _ASM +#include + + .syntax no_register_prefix + +ENTRY (__sigsetjmp) +.Local__sigsetjmp: + +#ifdef __arch_v32 + + moveq 1,r9 + move.d r10,r12 + addq 14*4,r12 + movem r9,[r10] + lapc 0f,r13 + move.d sp,[r12+] + move.d r13,[r12+] + move srp,[r12+] + +#else + + moveq 1,r9 + movem sp,[r10+1*4] +#ifdef __PIC__ + move.d pc,r9 + addq 0f-.,r9 +#else + move.d 0f,r9 +#endif + move.d r9,[r10] + move srp,[r10+16*4] + +#endif + +/* Saving and restoring CCR is meaningless, so we don't do it. */ + +/* Saving registers would complicate the implementation, but we + can get away with not setting up R0 here since we know that + __sigjmp_save is a local symbol; it doesn't have a PLT (which + would have required GOT in R0 at the time of the jump). */ + PLTJUMP (__sigjmp_save) +0: /* This is where longjmp returns. (Don't use "ret" - it's a macro. */ + Ret + move.d r9,r10 +END (__sigsetjmp) + +/* Binary compatibility entry points. Having these in separate files + is not meaningful and just adds library overhead. */ + +ENTRY (__setjmp) + ba .Local__sigsetjmp + moveq 0,r11 +END (__setjmp) + +ENTRY (_setjmp) + ba .Local__sigsetjmp + moveq 0,r11 +END (_setjmp) + +ENTRY (setjmp) + ba .Local__sigsetjmp + moveq 1,r11 +END (setjmp) diff --git a/libc/sysdeps/linux/cris/sys/procfs.h b/libc/sysdeps/linux/cris/sys/procfs.h new file mode 100644 index 0000000..072029b --- /dev/null +++ b/libc/sysdeps/linux/cris/sys/procfs.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/cris/sys/ucontext.h b/libc/sysdeps/linux/cris/sys/ucontext.h new file mode 100644 index 0000000..5f87545 --- /dev/null +++ b/libc/sysdeps/linux/cris/sys/ucontext.h @@ -0,0 +1,95 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/cris ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 20 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 + R_SP = R14, +#define R_SP R_SP + R_PC = R15, +#define R_PC R_PC +}; + +/* A placeholder; CRIS does not have any fp regs. */ +typedef unsigned long fpregset_t; + +/* A machine context is exactly a sigcontext. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/cris/syscall.S b/libc/sysdeps/linux/cris/syscall.S new file mode 100644 index 0000000..d4b052e --- /dev/null +++ b/libc/sysdeps/linux/cris/syscall.S @@ -0,0 +1,61 @@ +/* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" + + .syntax no_register_prefix + +/* Make syscall (callno, ...) into a system call. */ + +ENTRY (syscall) +#ifdef __arch_v32 + subq 4,sp + move.d r10,r9 + move srp,[sp] + addoq 8,sp,acr + move.d r11,r10 + move [acr],mof + addoq 12,sp,acr + move.d r12,r11 + move [acr],srp + addoq 4,sp,acr + move.d r13,r12 + move.d [acr],r13 + break 13 + cmps.w -4096,r10 + bhs 0f + move [sp+],srp + Ret + nop +#else + push srp + move.d r10,r9 + move.d r11,r10 + move.d r12,r11 + move.d r13,r12 + move.d [sp+4],r13 + move [sp+8],mof + move [sp+12],srp + break 13 + cmps.w -4096,r10 + bhs 0f + pop srp + Ret + nop +#endif +PSEUDO_END (syscall) diff --git a/libc/sysdeps/linux/cris/sysdep.S b/libc/sysdeps/linux/cris/sysdep.S new file mode 100644 index 0000000..416751d --- /dev/null +++ b/libc/sysdeps/linux/cris/sysdep.S @@ -0,0 +1,80 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "sysdep.h" + +/* The syscall stubs jump here when they detect an error, bot for PIC and + non-PIC. */ + + .syntax no_register_prefix + +ENTRY (__syscall_error) + neg.d r10,r10 + +#ifdef __UCLIBC_HAS_THREADS__ + subq 4,sp + move.d r10,[sp] + subq 4,sp + move srp,[sp] + + /* Note that __syscall_error is only visible within this library, + and no-one passes it on as a pointer, so can assume that R0 (GOT + pointer) is correctly set up. */ + PLTCALL (HIDDEN_JUMPTARGET(__errno_location)) + + move [sp+],srp + move.d [sp+],r11 + move.d r11,[r10] + +#else /* not __UCLIBC_HAS_THREADS__ */ +#ifdef __arch_v32 +# ifdef __PIC__ + addo.d C_SYMBOL_NAME(errno:GOT),r0,acr + move.d [acr],r9 + move.d r10,[r9] +# else /* not __PIC__ */ + lapc C_SYMBOL_NAME(errno),acr + move.d r10,[r9] +# endif /* not __PIC__ */ +#else /* not __arch_v32 */ +# ifdef __PIC__ + move.d [r0+C_SYMBOL_NAME(errno:GOT)],r9 + move.d r10,[r9] +# else + move.d r10,[C_SYMBOL_NAME(errno)] +# endif +#endif /* not __arch_v32 */ +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __PIC__ +/* PIC callers are supposed to have R0 on stack, ready for us to restore. + Callers are only allowed from within this DSO, so the GOT in r0 is the + one we want to use. + + (Don't use "ret" - it's a macro). */ + + moveq -1,r10 + Ret + move.d [sp+],r0 +#else + Ret + moveq -1,r10 +#endif + +END (__syscall_error) diff --git a/libc/sysdeps/linux/cris/sysdep.h b/libc/sysdeps/linux/cris/sysdep.h new file mode 100644 index 0000000..593e777 --- /dev/null +++ b/libc/sysdeps/linux/cris/sysdep.h @@ -0,0 +1,149 @@ +/* Assembler macros for CRIS. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYSDEP_H_ +#define _SYSDEP_H_ + +#ifndef C_LABEL + +/* Define a macro we can use to construct the asm name for a C symbol. */ +#ifdef __STDC__ +#define C_LABEL(name) name##: +#else +#define C_LABEL(name) name/**/: +#endif + +#endif /* C_LABEL */ + +#define __STR(x) #x +#define STR(x) __STR(x) + +/* Mark the end of function named SYM. This is used on some platforms + to generate correct debugging information. */ +#ifndef END +#define END(sym) +#endif + +#undef SYS_ify +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifdef __ASSEMBLER__ + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +/* Syntactic details of assembly-code. */ + +/* It is *not* generally true that "ELF uses byte-counts for .align, most + others use log2 of count of bytes", like some neighboring configs say. + See "align" in gas/read.c which is not overridden by + gas/config/obj-elf.c. It takes a log2 argument. *Some* targets + override it to take a byte argument. People should read source instead + of relying on hearsay. */ +#define ALIGNARG(log2) log2 + +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* The non-PIC jump is preferred, since it does not stall, and does not + invoke generation of a PLT. These macros assume that $r0 is set up as + GOT register. */ +#ifdef __arch_v32 +#ifdef __PIC__ +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define SETUP_PIC \ + subq 4,$sp @ \ + move.d $r0,[$sp] @ \ + lapc _GLOBAL_OFFSET_TABLE_,$r0 + +#define TEARDOWN_PIC move.d [$sp+],$r0 +#else +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x) @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x) @ \ + nop + +#define SETUP_PIC +#define TEARDOWN_PIC +#endif + +#else + +#ifdef __PIC__ +#define PLTJUMP(_x) \ + add.d C_SYMBOL_NAME (_x):PLT,$pc + +#define PLTCALL(_x) \ + jsr [$r0+C_SYMBOL_NAME (_x):GOTPLT16] + +#define SETUP_PIC \ + push $r0 @ \ + move.d $pc,$r0 @ \ + sub.d .:GOTOFF,$r0 + +#define TEARDOWN_PIC pop $r0 +#else +#define PLTJUMP(_x) jump C_SYMBOL_NAME (_x) +#define PLTCALL(_x) jsr C_SYMBOL_NAME (_x) +#define SETUP_PIC +#define TEARDOWN_PIC +#endif + +#endif /* __arch_v32 */ + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .text @ \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (name) @ \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME (name), function) @ \ + .align ALIGNARG (2) @ \ + C_LABEL(name) + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE (C_SYMBOL_NAME (name)) + +#define PSEUDO(name, syscall_name, args) \ + ENTRY (name) @ \ + DOARGS_##args @ \ + movu.w SYS_ify (syscall_name),$r9 @ \ + break 13 @ \ + cmps.w -4096,$r10 @ \ + bhs 0f @ \ + nop @ \ + UNDOARGS_return_##args + +#define PSEUDO_END(name) \ +0: @ \ + SETUP_PIC @ \ + PLTJUMP (__syscall_error) @ \ + END (name) + +#endif /* __ASSEMBLER__ */ +#endif /* _SYSDEP_H_ */ diff --git a/libc/sysdeps/linux/e1/Makefile b/libc/sysdeps/linux/e1/Makefile new file mode 100644 index 0000000..c69ccb9 --- /dev/null +++ b/libc/sysdeps/linux/e1/Makefile @@ -0,0 +1,56 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +# If you're looking for vfork(), it is defined in include/unistd.h + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +# why is crt1.c listed in CSRC ? +CSRC := crt1.c syscalls.c longjmp.c setjmp.c vfork.c +OBJS := $(patsubst %.c,%.o, $(CSRC)) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(OBJS): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/e1/bits/endian.h b/libc/sysdeps/linux/e1/bits/endian.h new file mode 100644 index 0000000..0d38c1c --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/endian.h @@ -0,0 +1,7 @@ +/* e1 is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/e1/bits/fcntl.h b/libc/sysdeps/linux/e1/bits/fcntl.h new file mode 100644 index 0000000..87d1939 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/fcntl.h @@ -0,0 +1,234 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/e1/bits/fenv.h b/libc/sysdeps/linux/e1/bits/fenv.h new file mode 100644 index 0000000..beeea3d --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/fenv.h @@ -0,0 +1,88 @@ + +/* Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the SR. */ +enum + { + FE_INEXACT = (1 << 8), +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = (1 << 9), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = (1 << 10), +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = (1 << 11), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = (1 << 12) +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* We support all of the four defined rounding modes. We use + the bit positions in the FPCR Mode Control Byte as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 13 , +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 2 << 13, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 3 << 13 +#define FE_UPWARD FE_UPWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment.*/ +typedef struct +{ + unsigned int round_mode; + unsigned int trap_enabled; + unsigned int accrued_except; + unsigned int actual_except; +} fenv_t; + +#if 0 +/* If the default argument is used we use this value. */ +const fenv FE_DFL_ENV_OBJ = {0, 0x1C00, 0} +#define FE_DFL_ENV (&FE_DFL_ENV_OBJ) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +const fenv_t FE_NOMASK_ENV_OBJ = { 0, 0x1F00, 0 }; +# define FE_NOMASK_ENV (&FE_NOMASK_ENV_OBJ) +#endif + +#endif + +#include diff --git a/libc/sysdeps/linux/e1/bits/fenvinline.h b/libc/sysdeps/linux/e1/bits/fenvinline.h new file mode 100644 index 0000000..2556247 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/fenvinline.h @@ -0,0 +1,298 @@ +/* + Inline floating-point environment handling functions for Hyperstone e1-32X. + Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES + +/********************************************************** + * --- A small description of the E1-16/32X FP unit. --- + * FP exceptions can be enabled and disabled through + * , . + * + * - When an enabled exception takes place a SIGFPE signal + * is sent to the process by the exception handler. User + * can test for the exception that took place through + * . + * feraiseexcept works only for accrued exceptions. + * + * - When a disabld exception takes place it does not generate + * a trap. The user can check if any exception took place after + * an FP instruction by issuing an command. + * User should first clear the G2 register by issuing an + * function. + * The following program is a typical example of how the user + * should check for exceptions that did not generate a SIGFPE + * signal : + * { + * double f; + * int raised; + * feclearexcept (FE_ALL_EXCEPT); + * f = compute (); + * raised = fetestexcept (FE_OVERFLOW | FE_INVALID); + * if (raised & FE_OVERFLOW) { ... } + * if (raised & FE_INVALID) { ... } + * ... + * } + ***********************************************************/ + +/* Get FPU rounding mode */ +#define fegetround() \ +({ \ + unsigned int tmp; \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(tmp) \ + :/*no input*/); \ + tmp &= (3<<13); \ + (tmp); \ +}) + +/* Set FPU rounding mode */ +#define fesetround(round) \ +({ \ + unsigned int tmp = (3 << 13); \ + while(1) { \ + /* Clear SR.FRM field */ \ + __asm__ __volatile__("andn SR, %0" \ + :/*no output*/ \ + :"l"(tmp) ); \ + tmp &= round; \ + \ + if(tmp) { \ + tmp = -1; \ + break; \ + } \ + \ + __asm__ __volatile__("or SR, %0" \ + :/*no input*/ \ + :"l"(round) ); \ + tmp = 0; \ + break; \ + } \ + (tmp); \ +}) + +/* The following functions test for accrued exceptions. + * No trap is generated on an FP exception. + */ +static __inline__ feclearexcept(int __excepts) +{ + unsigned int enabled_excepts, disabled_excepts; + + /* Check that __excepts is correctly set */ + if( __excepts & (~0x1F00) ) + return -1; + + __asm__ __volatile__("mov %0, SR" + :"=l"(enabled_excepts) + :/*no input*/ ); + + enabled_excepts &= 0x1F00; + disabled_excepts = ~enabled_excepts; + disabled_excepts &= 0x1F00; + + enabled_excepts &= __excepts; + disabled_excepts &= __excepts; + + /* Clear accrued exceptions */ + __asm__ __volatile__("andn G2, %0\n\t" + "andn G2, %1\n\t" + :/*no output*/ + :"l"(enabled_excepts), + "l"(disabled_excepts >> 8) ); + return 0; +} + +/* fetestexcepts tests both for actual and accrued + * excepts. You can test for an exception either after + * an FP instruction or within a SIGFPE handler + */ +__inline__ int fetestexcept(int __excepts) +{ + unsigned int G2, G2en, G2dis; + unsigned int enabled_excepts, disabled_excepts; + + /* Check that __excepts is correctly set */ + if( __excepts & (~0x1F00) ) + return -1; + + __asm__ __volatile__("mov %0, SR" + :"=l"(enabled_excepts) + :/*no input*/ ); + + enabled_excepts &= 0x1F00; + disabled_excepts = ~enabled_excepts; + disabled_excepts &= 0x1F00; + + __asm__ __volatile__("mov %0, G2" + :"=l"(G2) + :/*no input*/ ); + + G2en = G2 & 0x1F00; + G2dis = G2 & 0x1F; + G2en &= enabled_excepts; + G2dis &= (disabled_excepts >> 8); + return ( G2en | (G2dis << 8) ); +} + +static __inline__ int feraiseexcept(int __excepts) +{ + __asm__ __volatile__("or G2, %0" + :/*no output*/ + :"l"( __excepts >> 8 ) ); + return 0; +} + +/* The following functions enable/disable individual exceptions. + * If enabling an exception trap is going to occur, in case of error. + */ +#define feenableexcept(__excepts) \ +({ \ + int __retval, __pexcepts; \ + int __tmpexcepts = __excepts; \ + \ + while(1) { \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(__pexcepts) \ + :/*no input*/ ); \ + __pexcepts &= 0x1F00; \ + \ +/* Check if __except values are valid */ \ + if( __tmpexcepts & ~0x1F00 ) { \ + __retval = -1; \ + fprintf(stderr,"Non valid excepts\n");\ + break; \ + } \ + \ + __asm__ __volatile__("or SR, %0" \ + :/*no output*/ \ + :"l"(__tmpexcepts) ); \ + __retval = __pexcepts; \ + break; \ + } \ + (__retval); \ +}) + + +#define fedisableexcept(__excepts) \ +({ \ + int __retval, __pexcepts; \ + int __tmpexcepts = __excepts; \ + \ + while(1) { \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(__pexcepts) \ + :/*no input*/ ); \ + __pexcepts &= 0x1F00; \ + \ +/* Check if __except values are valid */ \ + if( __tmpexcepts & ~0x1F00 ) { \ + __retval = -1; \ + fprintf(stderr,"Non valid excepts\n");\ + break; \ + } \ + \ + __asm__ __volatile__("andn SR, %0" \ + :/*no output*/ \ + :"l"(__tmpexcepts) ); \ + __retval = __pexcepts; \ + break; \ + } \ + (__retval); \ +}) + +static __inline__ int fegetexcept(int excepts) +{ + unsigned int tmp; + __asm__ __volatile__("mov %0, SR" + :"=l"(tmp) + :/*no input*/ ); + tmp &= 0x1F00; + return tmp; +} + +static __inline__ int fegetenv(fenv_t *envp) +{ + __asm__ __volatile__("mov %0, SR\n\t + mov %1, SR\n\t + mov %2, G2\n\t + mov %3, G2\n\t" + :"=l"(envp->round_mode), + "=l"(envp->trap_enabled), + "=l"(envp->accrued_except), + "=l"(envp->actual_except) + :/*no input*/ ); + envp->round_mode &= (3<<13); + envp->trap_enabled &= 0x1F00; + envp->accrued_except &= 0x1F; + envp->accrued_except <<= 8; + envp->actual_except &= 0x1F00; +} + +#define feholdexcept(envp) \ +( \ + fegetenv(envp); \ + fedisableexcept(FE_ALL_EXCEPT); \ + feclearexcept(FE_ALL_EXCEPT); \ + (0); \ +) + +#define fesetenv(envp) \ +({ \ + /* Clear FRM & FTE field of SR */ \ + unsigned long clearSR = ( 127<<8 ); \ + __asm__ __volatile__("andn SR, %0\n\t" \ + "or SR, %1\n\t" \ + "or SR, %2\n\t" \ + :/*no output*/ \ + :"l"(clearSR), \ + "l"(envp->round_mode), \ + "l"(envp->trap_enabled) ); \ + __asm__ __volatile__("andn G2, 0x1F1F\n\t" \ + "or G2, %0\n\t" \ + "or G2, %1\n\t" \ + :/*no output*/ \ + :"l"( envp->accrued_except >> 8),\ + :"l"( envp->actual_except ) ); \ + (0); /* return 0 */ \ +}) + +#define feupdateenv(envp) \ +({ \ + /* Clear FRM & FTE field of SR */ \ + __asm__ __volatile__(/* We dont clear the prev SR*/ \ + "or SR, %1\n\t" \ + "or SR, %2\n\t" \ + :/*no output*/ \ + :"l"(clearSR), \ + "l"(envp->round_mode), \ + "l"(envp->accrued_except) ); \ + __asm__ __volatile__(/* We dont clear the prev SR*/ \ + "or G2, %0\n\t" \ + "or G2, %1\n\t" \ + :/*no output*/ \ + :"l"( envp->accrued_except >> 8),\ + :"l"( envp->actual_except ) ); \ + (0); /* return 0 */ \ +}) + + +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/libc/sysdeps/linux/e1/bits/kernel_stat.h b/libc/sysdeps/linux/e1/bits/kernel_stat.h new file mode 100644 index 0000000..9be9d11 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/kernel_stat.h @@ -0,0 +1,60 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/e1/bits/kernel_types.h b/libc/sysdeps/linux/e1/bits/kernel_types.h new file mode 100644 index 0000000..8017d85 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/kernel_types.h @@ -0,0 +1,46 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_E1_POSIX_TYPES_H +#define __ARCH_E1_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +/* +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; +*/ + +#endif /* __ARCH_E1_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/e1/bits/mman.h b/libc/sysdeps/linux/e1/bits/mman.h new file mode 100644 index 0000000..7f644b9 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/mman.h @@ -0,0 +1,76 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/e1/bits/proto.h b/libc/sysdeps/linux/e1/bits/proto.h new file mode 100644 index 0000000..7aa38ff --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/proto.h @@ -0,0 +1,5 @@ +#ifndef _E1_PROTO_H_ +#define _E1_PROTO_H_ +int kprintf( char *msg, int len); +#define KPRINTF(msg) kprintf(msg, strlen(msg)+1) +#endif diff --git a/libc/sysdeps/linux/e1/bits/setjmp.h b/libc/sysdeps/linux/e1/bits/setjmp.h new file mode 100644 index 0000000..88fa76f --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/setjmp.h @@ -0,0 +1,22 @@ +/* This file is lisenced under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +typedef struct { + unsigned long G3; + unsigned long G4; + unsigned long SavedSP; + unsigned long SavedPC; + unsigned long SavedSR; + unsigned long ReturnValue; +} __jmp_buf[1]; + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/e1/bits/syscalls.h b/libc/sysdeps/linux/e1/bits/syscalls.h new file mode 100644 index 0000000..8852a0f --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/syscalls.h @@ -0,0 +1,17 @@ +/* This file is licensed under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Include the library _syscallx macros */ +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h b/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/e1/bits/unistd.h b/libc/sysdeps/linux/e1/bits/unistd.h new file mode 100644 index 0000000..f492b8b --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/unistd.h @@ -0,0 +1,464 @@ + /* This file is lisenced under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ +#ifndef _BITS_UNISTD_H_ +#define _BITS_UNISTD_H_ + +#include +#include + +#define __E1_COFF_GCC__ + +/* The following macros have been provided by C.Baumhof + * They can be inlined in contrast to the previous ones*/ +#define _syscall0(type, name) \ +type name(void) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + par1 = -1; \ + par2 = __NR_##name; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2) \ + :"memory","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall1(type, name,atype, a) \ +type name(atype a) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3) \ + :"memory","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall2(type, name,atype, a, btype, b) \ +type name(atype a, btype b) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4) \ + :"memory","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall3(type, name,atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4), "l"(par5) \ + :"memory","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6) \ + :"memory","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7) \ + :"memory","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ + return (type)(par1); \ +} + +#define _syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + register int par8 __asm__("L8"); \ + int sys_retval; \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + par7 = (int)f; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7),"l"(par8) \ + :"memory","L8","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall0(type, name) \ +type name(...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + par1 = -1; \ + par2 = __NR_##name; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2)\ + :"memory","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall1(type, name, atype, a) \ +type name(atype a, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3)\ + :"memory","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall2(type, name,atype, a, btype, b) \ +type name(atype a, btype b, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4)\ + :"memory","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall3(type, name,atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4), "l"(par5) \ + :"memory","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6) \ + :"memory","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7) \ + :"memory","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + register int par8 __asm__("L8"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + par7 = (int)f; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7),"l"(par8) \ + :"memory","L8","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#include +/* Taken from */ +#ifndef _LIBC +/* We don't support pthreads for the moment*/ +#define __set_errno(val) ((errno) = (val)) +#endif + +#if 0 +#define _syscall3(type, name,atype, a , btype, b, ctype, c) \ +type name(atype a, btype b, ctype c,) \ +{ \ + __asm__ __volatile__( \ + "movi L9, -1\n\t" \ + "movi L8, %0\n\t" \ + "ldw.d G3, L7, 0\n\t" \ + "ldw.d G3, L6, 4\n\t" \ + "ldw.d G3, L5, 8\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","%L5","L6","L7","L8","L9");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L9\n\t"); \ +} + +#define _syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d) \ +{ \ + __asm__ __volatile__( \ + "movi L11, -1\n\t" \ + "movi L10, %0\n\t" \ + "ldw.d G3, L9, 0\n\t" \ + "ldw.d G3, L8, 4\n\t" \ + "ldw.d G3, L7, 8\n\t" \ + "ldw.d G3, L6, 12\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L6","L7","L8","L9","L10","L11");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L11\n\t"); \ +} + +#define _syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e) \ +{ \ + __asm__ __volatile__( \ + "movi L13, -1\n\t" \ + "movi L12, %0\n\t" \ + "ldw.d G3, L11, 0\n\t" \ + "ldw.d G3, L10, 4\n\t" \ + "ldw.d G3, L9, 8\n\t" \ + "ldw.d G3, L8, 12\n\t" \ + "ldw.d G3, L7, 16\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L7","L8","L9","L10","L11","L12","L13");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L13\n\t"); \ +} + +#define _syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f) \ +{ \ + __asm__ __volatile__( \ + "movi L15, -1\n\t" \ + "movi L14, %0\n\t" \ + "ldw.d G3, L13, 0\n\t" \ + "ldw.d G3, L12, 4\n\t" \ + "ldw.d G3, L11, 8\n\t" \ + "ldw.d G3, L10, 12\n\t" \ + "ldw.d G3, L9, 16\n\t" \ + "ldw.d G3, L8, 20\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L8","L9","L10","L11","L12","L13","L14","L15");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L15\n\t"); \ +} +#endif + +#endif /* !_HYPERSTONE_NOMMU_UNISTD_H_ */ diff --git a/libc/sysdeps/linux/e1/bits/wordsize.h b/libc/sysdeps/linux/e1/bits/wordsize.h new file mode 100644 index 0000000..a56d3ef --- /dev/null +++ b/libc/sysdeps/linux/e1/bits/wordsize.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/e1/crt0.S b/libc/sysdeps/linux/e1/crt0.S new file mode 100644 index 0000000..9d5e98d --- /dev/null +++ b/libc/sysdeps/linux/e1/crt0.S @@ -0,0 +1,17 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +.global __start +__start: + call L1, 0, __uClibc_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/e1/crt1.c b/libc/sysdeps/linux/e1/crt1.c new file mode 100644 index 0000000..dd8ed6a --- /dev/null +++ b/libc/sysdeps/linux/e1/crt1.c @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: */ +/* uClibc/sysdeps/linux/m68k/crt0.S + * Pull stuff off the stack and get uClibc moving. + * + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + * + * Copyright (C) 2000,2001 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +extern void main(int argc,void *argv,void *envp); +/* void (*mainp)(int argc,void *argv,void *envp) = main; */ + +void __uClibc_main(int argc,void *argv,void *envp); + +void _uClibc_start(unsigned int first_arg) +{ + unsigned int argc; + char **argv, **envp; + unsigned long *stack; + + stack = (unsigned long*) first_arg; + argc = *(stack); + argv = (char **)(stack + 1); + envp = (char **)(stack + 1 + argc + 1); + + __uClibc_main(argc, argv, envp); +} + +void __main() { } + diff --git a/libc/sysdeps/linux/e1/longjmp.c b/libc/sysdeps/linux/e1/longjmp.c new file mode 100644 index 0000000..9f04e7b --- /dev/null +++ b/libc/sysdeps/linux/e1/longjmp.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#define __NR_e1newSP 224 +static __inline__ _syscall1(int, e1newSP, unsigned long, SavedSP ) + +unsigned long jmpbuf_ptr; + +void longjmp(jmp_buf state, int value ) +{ + if(!value) + state->__jmpbuf->ReturnValue = 1; + else + state->__jmpbuf->ReturnValue = value; + + jmpbuf_ptr = (unsigned long)state; + e1newSP(state->__jmpbuf->SavedSP); + +#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr) + __asm__ __volatile__("mov L0, %0\n\t" + "mov L1, %1\n\t" + "mov L2, %2\n\t" + "mov G3, %3\n\t" + "mov G4, %4\n\t" + "ret PC, L1\n\t" + :/*no output*/ + :"l"(_state_->__jmpbuf->ReturnValue), + "l"(_state_->__jmpbuf->SavedPC), + "l"(_state_->__jmpbuf->SavedSR), + "l"(_state_->__jmpbuf->G3), + "l"(_state_->__jmpbuf->G4) + :"%G3", "%G4", "%L0", "%L1" ); +#undef _state_ +} + +libc_hidden_proto(sigprocmask) + +void siglongjmp(sigjmp_buf state, int value ) +{ + if( state->__mask_was_saved ) + sigprocmask(SIG_SETMASK, &state->__saved_mask, NULL); + + if(!value) + state->__jmpbuf->ReturnValue = 1; + else + state->__jmpbuf->ReturnValue = value; + + jmpbuf_ptr = (unsigned long)state; + e1newSP(state->__jmpbuf->SavedSP); + + +#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr) + __asm__ __volatile__("mov L0, %0\n\t" + "mov L1, %1\n\t" + "mov L2, %2\n\t" + "mov G3, %3\n\t" + "mov G4, %4\n\t" + "ret PC, L1\n\t" + :/*no output*/ + :"l"(_state_->__jmpbuf->ReturnValue), + "l"(_state_->__jmpbuf->SavedPC), + "l"(_state_->__jmpbuf->SavedSR), + "l"(_state_->__jmpbuf->G3), + "l"(_state_->__jmpbuf->G4) + :"%G3", "%G4", "%L0", "%L1" ); +#undef _state_ +} diff --git a/libc/sysdeps/linux/e1/setjmp.c b/libc/sysdeps/linux/e1/setjmp.c new file mode 100644 index 0000000..bda18b1 --- /dev/null +++ b/libc/sysdeps/linux/e1/setjmp.c @@ -0,0 +1,56 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#include +#include +#include + +libc_hidden_proto(sigprocmask) + +int setjmp( jmp_buf state) +{ + __asm__ __volatile__( "mov %0, G3\n\t" + "mov %1, G4\n\t" + :"=l"(state->__jmpbuf->G3), + "=l"(state->__jmpbuf->G4) + :/*no input*/ + :"%G3", "%G4" ); + + __asm__ __volatile__( "setadr %0\n\t" + "mov %1, L1\n\t" + "mov %2, L2\n\t" + :"=l"(state->__jmpbuf->SavedSP), + "=l"(state->__jmpbuf->SavedPC), + "=l"(state->__jmpbuf->SavedSR) + :/*no input*/); + return 0; +} + +int sigsetjmp( sigjmp_buf state , int savesigs) +{ + + if(savesigs) { + state->__mask_was_saved = 1; + /* how arg in is not significant */ + sigprocmask(SIG_SETMASK, NULL, &state->__saved_mask); + } else + state->__mask_was_saved = 0; + + __asm__ __volatile__( "mov %0, G3\n\t" + "mov %1, G4\n\t" + :"=l"(state->__jmpbuf->G3), + "=l"(state->__jmpbuf->G4) + :/*no input*/ + :"%G3", "%G4" ); + + __asm__ __volatile__( "setadr %0\n\t" + "mov %1, L2\n\t" + "mov %2, L3\n\t" + :"=l"(state->__jmpbuf->SavedSP), + "=l"(state->__jmpbuf->SavedPC), + "=l"(state->__jmpbuf->SavedSR) + :/*no input*/); + return 0; +} diff --git a/libc/sysdeps/linux/e1/sys/procfs.h b/libc/sysdeps/linux/e1/sys/procfs.h new file mode 100644 index 0000000..8416b3b --- /dev/null +++ b/libc/sysdeps/linux/e1/sys/procfs.h @@ -0,0 +1,31 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/e1/sys/reg.h b/libc/sysdeps/linux/e1/sys/reg.h new file mode 100644 index 0000000..a8a7ec1 --- /dev/null +++ b/libc/sysdeps/linux/e1/sys/reg.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +#endif /* _SYS_REG_H */ diff --git a/libc/sysdeps/linux/e1/sys/ucontext.h b/libc/sysdeps/linux/e1/sys/ucontext.h new file mode 100644 index 0000000..3c441dc --- /dev/null +++ b/libc/sysdeps/linux/e1/sys/ucontext.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/m68k ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R_D0 = 0, +#define R_D0 R_D0 + R_D1 = 1, +#define R_D1 R_D1 + R_D2 = 2, +#define R_D2 R_D2 + R_D3 = 3, +#define R_D3 R_D3 + R_D4 = 4, +#define R_D4 R_D4 + R_D5 = 5, +#define R_D5 R_D5 + R_D6 = 6, +#define R_D6 R_D6 + R_D7 = 7, +#define R_D7 R_D7 + R_A0 = 8, +#define R_A0 R_A0 + R_A1 = 9, +#define R_A1 R_A1 + R_A2 = 10, +#define R_A2 R_A2 + R_A3 = 11, +#define R_A3 R_A3 + R_A4 = 12, +#define R_A4 R_A4 + R_A5 = 13, +#define R_A5 R_A5 + R_A6 = 14, +#define R_A6 R_A6 + R_A7 = 15, +#define R_A7 R_A7 + R_SP = 15, +#define R_SP R_SP + R_PC = 16, +#define R_PC R_PC + R_PS = 17 +#define R_PS R_PS +}; + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int f_fpregs[8][3]; + int f_pcr; + int f_psr; + int f_fpiaddr; +} fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + int version; + gregset_t gregs; + fpregset_t fpregs; +} mcontext_t; + +#define MCONTEXT_VERSION 2 + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + long int uc_filler[174]; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/e1/syscalls.c b/libc/sysdeps/linux/e1/syscalls.c new file mode 100644 index 0000000..e58ad5f --- /dev/null +++ b/libc/sysdeps/linux/e1/syscalls.c @@ -0,0 +1,11 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#include + +/* We now need a declaration of the `errno' variable. */ +extern int errno; +# define __set_errno(val) ((errno) = (val)) +_syscall2( int, kprintf, char *, msg, int, len) diff --git a/libc/sysdeps/linux/e1/vfork.c b/libc/sysdeps/linux/e1/vfork.c new file mode 100644 index 0000000..799a112 --- /dev/null +++ b/libc/sysdeps/linux/e1/vfork.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___vfork __NR_vfork +attribute_hidden _syscall0(pid_t, __vfork) +libc_hidden_proto(vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/frv/Makefile b/libc/sysdeps/linux/frv/Makefile new file mode 100644 index 0000000..554fdb0 --- /dev/null +++ b/libc/sysdeps/linux/frv/Makefile @@ -0,0 +1,58 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# ported to FR-V by Alexandre Oliva +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +SCRT_OBJ := $(patsubst %,S%, $(CRT_OBJ)) + +CTOR_TARGETS := crti.o crtn.o + +SSRC := __longjmp.S setjmp.S clone.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC = mmap.c sysdep.c syscall.c brk.c sbrk.c __init_brk.c dl-iterate-phdr.c +CSRC += xstatconv.c stat.c stat64.c fstat.c fstat64.c lstat.c lstat64.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) crtreloc.o + $(CC) $(ASFLAGS) -DL_$* -r -nostdlib $^ -o $*.o + +crtreloc.o: crtreloc.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(SCRT_OBJ): $(CRT_SRC) Scrtreloc.o + $(CC) $(ASFLAGS) $(PIEFLAG) -DL_$* -r -nostdlib $^ -o $*.o + +Scrtreloc.o: crtreloc.c + $(CC) $(CFLAGS) $(PIEFLAG) -c $< -o $@ + +$(CTOR_TARGETS): %.o : %.S + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/frv/__init_brk.c b/libc/sysdeps/linux/frv/__init_brk.c new file mode 100644 index 0000000..7e4c8d1 --- /dev/null +++ b/libc/sysdeps/linux/frv/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk(void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/libc/sysdeps/linux/frv/__longjmp.S b/libc/sysdeps/linux/frv/__longjmp.S new file mode 100644 index 0000000..c3145c8 --- /dev/null +++ b/libc/sysdeps/linux/frv/__longjmp.S @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define _SETJMP_H +#define _ASM +#include + +# setjmp/longjmp for Frv. The jmpbuf looks like this: +# +# Register jmpbuf offset +# R16-R31 0x0-0x03c +# R48-R63 0x40-0x7c +# FR16-FR31 0x80-0xbc +# FR48-FR63 0xc0-0xfc +# LR 0x100 +# SP 0x104 +# FP 0x108 +# +# R8 contains the pointer to jmpbuf + + .text + .global __longjmp + .type __longjmp,@function +__longjmp: + lddi @(gr8,0), gr16 + lddi @(gr8,8), gr18 + lddi @(gr8,16), gr20 + lddi @(gr8,24), gr22 + lddi @(gr8,32), gr24 + lddi @(gr8,40), gr26 + lddi @(gr8,48), gr28 + lddi @(gr8,56), gr30 +#if __FRV_GPR__ != 32 + lddi @(gr8,64), gr48 + lddi @(gr8,72), gr50 + lddi @(gr8,80), gr52 + lddi @(gr8,88), gr54 + lddi @(gr8,96), gr56 + lddi @(gr8,104), gr58 + lddi @(gr8,112), gr60 + lddi @(gr8,120), gr62 +#endif + +#if __FRV_FPR__ != 0 + lddfi @(gr8,128), fr16 + lddfi @(gr8,136), fr18 + lddfi @(gr8,144), fr20 + lddfi @(gr8,152), fr22 + lddfi @(gr8,160), fr24 + lddfi @(gr8,168), fr26 + lddfi @(gr8,176), fr28 + lddfi @(gr8,184), fr30 +#if __FRV_FPR__ != 32 + lddfi @(gr8,192), fr48 + lddfi @(gr8,200), fr50 + lddfi @(gr8,208), fr52 + lddfi @(gr8,216), fr54 + lddfi @(gr8,224), fr56 + lddfi @(gr8,232), fr58 + lddfi @(gr8,240), fr60 + lddfi @(gr8,248), fr62 +#endif +#endif + + ldi @(gr8,256), gr4 + movgs gr4,lr + + ldi @(gr8,260), sp + ldi @(gr8,264), fp + +# Value to return is in r9. If zero, return 1 + cmp gr9, gr0, icc0 + setlos #1, gr8 + ckne icc0, cc4 + cmov gr9, gr8, cc4, 1 + ret +.Lend2: + .size __longjmp,.Lend2-__longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/frv/bits/elf-fdpic.h b/libc/sysdeps/linux/frv/bits/elf-fdpic.h new file mode 100644 index 0000000..b7e87b8 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/elf-fdpic.h @@ -0,0 +1,115 @@ +/* Copyright 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. + The kernel passes a process a memory map, such that for every LOAD + segment there is an elf32_fdpic_loadseg entry. A pointer to an + elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to + an additional such map is passed in GR9 for the interpreter, when + there is one. */ + +#include + +/* This data structure represents a PT_LOAD segment. */ +struct elf32_fdpic_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Half version; + /* Number of segments in this map. */ + Elf32_Half nsegs; + /* The actual memory map. */ + struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { + struct elf32_fdpic_loadmap *map; + void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the + load map. */ +static __always_inline void * +__reloc_pointer (void *p, + const struct elf32_fdpic_loadmap *map) +{ + int c; + +#if 0 + if (map->version != 0) + /* Crash. */ + ((void(*)())0)(); +#endif + + /* No special provision is made for NULL. We don't want NULL + addresses to go through relocation, so they shouldn't be in + .rofixup sections, and, if they're present in dynamic + relocations, they shall be mapped to the NULL address without + undergoing relocations. */ + + for (c = 0; + /* Take advantage of the fact that the loadmap is ordered by + virtual addresses. In general there will only be 2 entries, + so it's not profitable to do a binary search. */ + c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; + c++) + { + /* This should be computed as part of the pointer comparison + above, but we want to use the carry in the comparison, so we + can't convert it to an integer type beforehand. */ + unsigned long offset = p - (void*)map->segs[c].p_vaddr; + /* We only check for one-past-the-end for the last segment, + assumed to be the data segment, because other cases are + ambiguous in the absence of padding between segments, and + rofixup already serves as padding between text and data. + Unfortunately, unless we special-case the last segment, we + fail to relocate the _end symbol. */ + if (offset < map->segs[c].p_memsz + || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) + return (char*)map->segs[c].addr + offset; + } + + /* We might want to crash instead. */ + return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ + (__reloc_pointer ((void*)(ptr), \ + (loadaddr).map)) + +#endif /* _BITS_ELF_FDPIC_H */ diff --git a/libc/sysdeps/linux/frv/bits/endian.h b/libc/sysdeps/linux/frv/bits/endian.h new file mode 100644 index 0000000..0564c59 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/endian.h @@ -0,0 +1,7 @@ +/* frv is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/frv/bits/fcntl.h b/libc/sysdeps/linux/frv/bits/fcntl.h new file mode 100644 index 0000000..49da627 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/fcntl.h @@ -0,0 +1,216 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/frv/bits/kernel_stat.h b/libc/sysdeps/linux/frv/bits/kernel_stat.h new file mode 100644 index 0000000..8b80a26 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/kernel_stat.h @@ -0,0 +1,88 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long __pad2; + unsigned long st_ino; + + unsigned short __pad3; + unsigned short st_mode; + unsigned short __pad4; + unsigned short st_nlink; + + unsigned short __pad5; + unsigned short st_uid; + unsigned short __pad6; + unsigned short st_gid; + + unsigned char __pad7[6]; + unsigned short st_rdev; + + unsigned long __pad8; + unsigned long st_size; + + unsigned long __pad9; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad10; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long __unused1; + unsigned long st_atime; + + unsigned long __unused2; + unsigned long st_mtime; + + unsigned long __unused3; + unsigned long st_ctime; + + unsigned long long __unused4; +}; + +struct kernel_stat64 { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned char __pad2[6]; + unsigned short st_rdev; + + long long st_size; + + unsigned long __pad3; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long __unused1; + unsigned long st_atime; + + unsigned long __unused2; + unsigned long st_mtime; + + unsigned long __unused3; /* will be high 32 bits of ctime someday */ + unsigned long st_ctime; + + unsigned long long __unused4; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/frv/bits/kernel_types.h b/libc/sysdeps/linux/frv/bits/kernel_types.h new file mode 100644 index 0000000..8403fd3 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/kernel_types.h @@ -0,0 +1,43 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/frv/bits/mman.h b/libc/sysdeps/linux/frv/bits/mman.h new file mode 100644 index 0000000..0802005 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/mman.h @@ -0,0 +1,76 @@ +/* Definitions for POSIX memory map interface. Linux/frv version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/frv/bits/setjmp.h b/libc/sysdeps/linux/frv/bits/setjmp.h new file mode 100644 index 0000000..d49ad7b --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/setjmp.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. FRV version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#define __SETJMP_NUM_INT 32 /* number of integer registers to save */ +#define __SETJMP_NUM_DBL 32 /* number of double registers to save */ + +#define __SETJMP_INT(x) (x) +#define __SETJMP_DBL(x) (__SETJMP_NUM_INT+(x)) +#define __SETJMP_LR (__SETJMP_NUM_INT+__SETJMP_NUM_DBL) +#define __SETJMP_SP (__SETJMP_LR+1) +#define __SETJMP_FP (__SETJMP_SP+1) + + +#ifndef _ASM +typedef struct +/* Demand 64-bit alignment such that we can use std/ldd in + setjmp/longjmp. */ +__attribute__((__aligned__(8))) + { + /* Callee-saved registers. */ + unsigned long __ints[__SETJMP_NUM_INT]; /* integer registers */ + unsigned long __dbls[__SETJMP_NUM_DBL]; /* double registers */ + unsigned long __lr; /* linkage register */ + unsigned long __sp; /* stack pointer */ + unsigned long __fp; /* frame pointer */ + } __jmp_buf[1]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__sp) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/frv/bits/stackinfo.h b/libc/sysdeps/linux/frv/bits/stackinfo.h new file mode 100644 index 0000000..03412e0 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On FRV the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/frv/bits/stat.h b/libc/sysdeps/linux/frv/bits/stat.h new file mode 100644 index 0000000..ae5f059 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/stat.h @@ -0,0 +1,154 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_STAT_H +#define _BITS_STAT_H + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 0 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + +struct stat +{ + __dev_t st_dev; /* Device. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad1; + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + + __dev_t st_rdev; /* Device number, if device. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad2; + __off_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad3; +#else + __off64_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad1; +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad4; + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif + + unsigned long int __unused1; + __time_t st_atime; /* Time of last access. */ + + unsigned long int __unused2; + __time_t st_mtime; /* Time of last modification. */ + + unsigned long int __unused3; + __time_t st_ctime; /* Time of last status change. */ + + unsigned long long __unused4; +}; + +#ifdef __USE_LARGEFILE64 +struct stat64 +{ + __dev_t st_dev; /* Device. */ + + __ino64_t st_ino; /* File serial number. */ + + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + + __dev_t st_rdev; /* Device number, if device. */ + + __off64_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad1; + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long int __unused1; + __time_t st_atime; /* Time of last access. */ + + unsigned long int __unused2; + __time_t st_mtime; /* Time of last modification. */ + + unsigned long int __unused3; + __time_t st_ctime; /* Time of last status change. */ + + unsigned long long __unused4; +}; +#endif + + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#endif /* _BITS_STAT_H */ diff --git a/libc/sysdeps/linux/frv/bits/syscalls.h b/libc/sysdeps/linux/frv/bits/syscalls.h new file mode 100644 index 0000000..eea3050 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/syscalls.h @@ -0,0 +1,139 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -4095: see */ +#if defined _LIBC && !defined __set_errno +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + extern int __syscall_error (int); \ + return (type) __syscall_error (__sr2); \ + } \ + return (type) (__sr2); \ +} while (0) +#else +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + __set_errno (-__sr2); \ + __sr2 = -1; \ + } \ + return (type) (__sr2); \ +} while (0) +#endif + +#ifndef __set_errno +# define __set_errno(val) ((*__errno_location ()) = (val)) +#endif + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8"); \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "=r" (__sc0) \ + : "r" (__scnum)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ + "r" (__sc3), "r" (__sc4)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ +register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ + "r" (__sc3), "r" (__sc4), "r" (__sc5)); \ +__syscall_return(type,__sc0); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h b/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/frv/bits/uClibc_page.h b/libc/sysdeps/linux/frv/bits/uClibc_page.h new file mode 100644 index 0000000..51a6e15 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/uClibc_page.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT (14) +#ifndef __ASSEMBLY__ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/frv/bits/wordsize.h b/libc/sysdeps/linux/frv/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/frv/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/frv/brk.c b/libc/sysdeps/linux/frv/brk.c new file mode 100644 index 0000000..c69c97a --- /dev/null +++ b/libc/sysdeps/linux/frv/brk.c @@ -0,0 +1,28 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(brk) +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/frv/clone.S b/libc/sysdeps/linux/frv/clone.S new file mode 100644 index 0000000..1456157 --- /dev/null +++ b/libc/sysdeps/linux/frv/clone.S @@ -0,0 +1,83 @@ +/* Copyright (C) 2003, 2004 Free Software Foudnation, Inc. + This file is part of the GNU C Library. + Contributed by Alexandre Oliva , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#define _ERRNO_H 1 +#include + + .text + .globl clone + .type clone,@function +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ +clone: + /* Sanity check arguments. */ + cmp.p gr8, gr0, icc0 + cmp gr9, gr0, icc1 + mov.p gr8, gr4 + beq icc0, #0, .Lerror + mov.p gr11, gr5 + beq icc1, #0, .Lerror + + mov.p gr10, gr8 + setlos #__NR_clone, gr7 + tra gr0,gr0 + + cmp.p gr8, gr0, icc0 + setlos #-4096, gr6 + cmp.p gr8, gr6, icc1 + beq icc0, #0, .Lthread_start + blslr icc1, #2 + +.Lsys_error: + sethi.p #gotofffuncdeschi(__syscall_error), gr14 + setlo #gotofffuncdesclo(__syscall_error), gr14 + ldd @(gr14, gr15), gr14 + jmpl @(gr14, gr0) + +.Lerror: + setlos.p #-EINVAL, gr8 + bra .Lsys_error + +############################################################################### +# +# come here as the new thread [GR4 is fn, GR5 is arg] +# +############################################################################### +.Lthread_start: + /* Save the PIC register. */ + mov gr15, gr17 + + /* Call the user's function. */ + ldd.p @(gr4, gr0), gr14 + mov gr5, gr8 + calll @(gr14, gr0) + + /* Call _exit, rather simply inlining the syscall, such that + breakpoints work.*/ + + mov.p gr17, gr15 + call HIDDEN_JUMPTARGET(_exit) + + /* Should never get here. */ + jmpl @(gr0, gr0) + .size clone,.-clone diff --git a/libc/sysdeps/linux/frv/crt0.S b/libc/sysdeps/linux/frv/crt0.S new file mode 100644 index 0000000..a1d07bb --- /dev/null +++ b/libc/sysdeps/linux/frv/crt0.S @@ -0,0 +1,125 @@ +/* Copyright (C) 1991, 1992, 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* Based on ../i386/crt0.S and newlib's libgloss/frv/crt0.S */ + +/* + When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + + Also, GR16 holds a pointer to a memory map. */ + +#include + + .text + .global _start + .type _start,%function +#if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__ + .type __uClibc_main,%function +#else + .weak _init + .weak _fini + .type __uClibc_start_main,%function +#endif +_start: + /* Make sure the stack pointer is properly aligned. Save the + original value in gr21 such that we can get to arguments and + such from there. */ + mov.p sp, gr21 + andi sp, #-8, sp + /* At program start-up, gr16 contains a pointer to a memory + map, that we use to relocate addresses. */ + call .Lcall +.Lcall: + movsg lr, gr4 + sethi.p #gprelhi(.Lcall), gr5 + setlo #gprello(.Lcall), gr5 + sub.p gr4, gr5, gr4 + /* gr4 now holds the _gp address. */ + + mov gr16, gr8 + sethi.p #gprelhi(__ROFIXUP_LIST__), gr9 + sethi #gprelhi(__ROFIXUP_END__), gr10 + setlo.p #gprello(__ROFIXUP_LIST__), gr9 + setlo #gprello(__ROFIXUP_END__), gr10 + add.p gr9, gr4, gr9 + add gr10, gr4, gr10 + call __self_reloc + mov.p gr8, gr17 + mov gr8, gr15 + /* gr17 now holds the self-relocated _GLOBAL_OFFSET_TABLE_ + address, because the linker added its unrelocated address as + the last entry in the ROFIXUP list, and __self_reloc returns + the last entry, relocated. */ + + /* Prepare arguments for uClibc main. */ + ld @(gr21, gr0), gr8 + slli gr8, #2, gr10 + add gr21, gr10, gr10 + addi.p gr21, #4, gr9 + addi gr10, #8, gr10 + + /* Set up an invalid (NULL return address, NULL frame pointer) + callers stack frame so anybody unrolling the stack knows where + to stop */ + mov gr0, fp + movgs gr0, lr + +#if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__ + /* Pass .init and .fini arguments to __uClibc_start_main(). */ + sethi.p #gotfuncdeschi(_init), gr11 + sethi #gotfuncdeschi(_fini), gr12 + setlo.p #gotfuncdesclo(_init), gr11 + setlo #gotfuncdesclo(_fini), gr12 + ld.p @(gr11, gr17), gr11 + mov gr17, gr15 + ld.p @(gr12, gr17), gr12 + call __uClibc_start_main +#else + mov.p gr17, gr15 + call __uClibc_main +#endif + + /* Crash if somehow `exit' returns anyways. */ + jmpl @(gr0,gr0) +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/frv/crti.S b/libc/sysdeps/linux/frv/crti.S new file mode 100644 index 0000000..1788524 --- /dev/null +++ b/libc/sysdeps/linux/frv/crti.S @@ -0,0 +1,50 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + .section .init,"x" + .p2align 2 + .globl _init + .type _init, @function +_init: + addi sp,#-16,sp + st.p fp, @(sp,gr0) + mov sp, fp + movsg lr, gr5 + sti gr15, @(fp,4) + sti gr5, @(fp,8) + + .section .fini,"x" + .p2align 2 + .globl _fini + .type _fini, @function +_fini: + addi sp,#-16,sp + st.p fp, @(sp,gr0) + mov sp, fp + movsg lr, gr5 + sti gr15, @(fp,4) + sti gr5, @(fp,8) diff --git a/libc/sysdeps/linux/frv/crtn.S b/libc/sysdeps/linux/frv/crtn.S new file mode 100644 index 0000000..1d58c02 --- /dev/null +++ b/libc/sysdeps/linux/frv/crtn.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + .section .init,"x" + .globl _init + .type _init, @function + ldi @(fp,8), gr5 + ld @(sp,gr0), fp + addi sp,#16,sp + jmpl @(gr5,gr0) + .size _init, .-_init + + .section .fini,"x" + .globl _fini + .type _fini, @function + ldi @(fp,8), gr5 + ld @(sp,gr0), fp + addi sp,#16,sp + jmpl @(gr5,gr0) + .size _fini, .-_fini diff --git a/libc/sysdeps/linux/frv/crtreloc.c b/libc/sysdeps/linux/frv/crtreloc.c new file mode 100644 index 0000000..ba934bc --- /dev/null +++ b/libc/sysdeps/linux/frv/crtreloc.c @@ -0,0 +1,120 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + written by Alexandre Oliva +This file is part of the GNU C Library. + +The GNU C 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. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + +/* This file is to be compiled into crt object files, to enable + executables to easily self-relocate. */ + +/* Compute the runtime address of pointer in the range [p,e), and then + map the pointer pointed by it. */ +static __always_inline void *** +reloc_range_indirect (void ***p, void ***e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + void *ptr = __reloc_pointer (*p, map); + if (ptr) + { + void *pt; + if ((long)ptr & 3) + __builtin_memcpy(&pt, ptr, sizeof(pt)); + else + pt = *(void**)ptr; + pt = __reloc_pointer (pt, map); + if ((long)ptr & 3) + __builtin_memcpy(ptr, &pt, sizeof(pt)); + else + *(void**)ptr = pt; + } + p++; + } + return p; +} + +/* Call __reloc_range_indirect for the given range except for the last + entry, whose contents are only relocated. It's expected to hold + the GOT value. */ +void* attribute_hidden +__self_reloc (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + p = reloc_range_indirect (p, e-1, map); + + if (p >= e) + return (void*)-1; + + return __reloc_pointer (*p, map); +} + +#if 0 +/* These are other functions that might be useful, but that we don't + need. */ + +/* Remap pointers in [p,e). */ +static __always_inline void** +reloc_range (void **p, void **e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + *p = __reloc_pointer (*p, map); + p++; + } + return p; +} + +/* Remap p, adjust e by the same offset, then map the pointers in the + range determined by them. */ +void attribute_hidden +__reloc_range (const struct elf32_fdpic_loadmap *map, + void **p, void **e) +{ + void **old = p; + + p = __reloc_pointer (p, map); + e += p - old; + reloc_range (p, e, map); +} + +/* Remap p, adjust e by the same offset, then map pointers referenced + by the (unadjusted) pointers in the range. Return the relocated + value of the last pointer in the range. */ +void* attribute_hidden +__reloc_range_indirect (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + void ***old = p; + + p = __reloc_pointer (p, map); + e += p - old; + return reloc_range_indirect (p, e, map); +} +#endif diff --git a/libc/sysdeps/linux/frv/dl-iterate-phdr.c b/libc/sysdeps/linux/frv/dl-iterate-phdr.c new file mode 100644 index 0000000..144e4c1 --- /dev/null +++ b/libc/sysdeps/linux/frv/dl-iterate-phdr.c @@ -0,0 +1,42 @@ +/* Copyright 2003 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C 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. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + +extern int weak_function +__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data); + +/* Define it as a pointer, such that we get a pointer to the global + function descriptor, that won't be optimized away by the + linker. */ +static int (*ptr) (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data) = __dl_iterate_phdr; + +int +dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data) +{ + if (ptr) + return ptr (callback, data); + + return 0; +} diff --git a/libc/sysdeps/linux/frv/fstat.c b/libc/sysdeps/linux/frv/fstat.c new file mode 100644 index 0000000..0153ebe --- /dev/null +++ b/libc/sysdeps/linux/frv/fstat.c @@ -0,0 +1,18 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +libc_hidden_proto(fstat) +_syscall2(int, fstat, int, fd, struct stat *, buf) +libc_hidden_def(fstat) diff --git a/libc/sysdeps/linux/frv/fstat64.c b/libc/sysdeps/linux/frv/fstat64.c new file mode 100644 index 0000000..6b356e0 --- /dev/null +++ b/libc/sysdeps/linux/frv/fstat64.c @@ -0,0 +1,20 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(fstat64) +_syscall2(int, fstat64, int, fd, struct stat64 *, buf) +libc_hidden_def(fstat64) +#endif diff --git a/libc/sysdeps/linux/frv/lstat.c b/libc/sysdeps/linux/frv/lstat.c new file mode 100644 index 0000000..f2c7789 --- /dev/null +++ b/libc/sysdeps/linux/frv/lstat.c @@ -0,0 +1,18 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +libc_hidden_proto(lstat) +_syscall2(int, lstat, const char *, file_name, struct stat *, buf) +libc_hidden_def(lstat) diff --git a/libc/sysdeps/linux/frv/lstat64.c b/libc/sysdeps/linux/frv/lstat64.c new file mode 100644 index 0000000..1184a0a --- /dev/null +++ b/libc/sysdeps/linux/frv/lstat64.c @@ -0,0 +1,20 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lstat64) +_syscall2(int, lstat64, const char *, file_name, struct stat64 *, buf) +libc_hidden_def(lstat64) +#endif diff --git a/libc/sysdeps/linux/frv/mmap.c b/libc/sysdeps/linux/frv/mmap.c new file mode 100644 index 0000000..7095bd2 --- /dev/null +++ b/libc/sysdeps/linux/frv/mmap.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Daniel Jacobowitz , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Massivly hacked up for uClibc by Erik Andersen */ + +/* Extracted from ../common/mmap64.c by Alexandre Oliva + + We don't want to use the old mmap interface. */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset) + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno (EINVAL); + return MAP_FAILED; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/frv/sbrk.c b/libc/sysdeps/linux/frv/sbrk.c new file mode 100644 index 0000000..a1ff2a1 --- /dev/null +++ b/libc/sysdeps/linux/frv/sbrk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(sbrk) +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/libc/sysdeps/linux/frv/setjmp.S b/libc/sysdeps/linux/frv/setjmp.S new file mode 100644 index 0000000..66008d1 --- /dev/null +++ b/libc/sysdeps/linux/frv/setjmp.S @@ -0,0 +1,90 @@ + .text + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .global _setjmp + .type _setjmp,@function +_setjmp: + setlos #0, gr9 + bra .Lsigsetjmp_intern + .size _setjmp,.-_setjmp + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type setjmp,@function + .globl setjmp +setjmp: + setlos #1, gr9 + bra .Lsigsetjmp_intern + .size setjmp,.-setjmp + +# setjmp/longjmp for Frv. The jmpbuf looks like this: +# +# Register jmpbuf offset +# R16-R31 0x0-0x03c +# R48-R63 0x40-0x7c +# FR16-FR31 0x80-0xbc +# FR48-FR63 0xc0-0xfc +# LR 0x100 +# SP 0x104 +# FP 0x108 + + .global __sigsetjmp + .type __sigsetjmp,@function +__sigsetjmp: +.Lsigsetjmp_intern: + stdi gr16, @(gr8,0) + stdi gr18, @(gr8,8) + stdi gr20, @(gr8,16) + stdi gr22, @(gr8,24) + stdi gr24, @(gr8,32) + stdi gr26, @(gr8,40) + stdi gr28, @(gr8,48) + stdi gr30, @(gr8,56) +#if __FRV_GPR__ != 32 + stdi gr48, @(gr8,64) + stdi gr50, @(gr8,72) + stdi gr52, @(gr8,80) + stdi gr54, @(gr8,88) + stdi gr56, @(gr8,96) + stdi gr58, @(gr8,104) + stdi gr60, @(gr8,112) + stdi gr62, @(gr8,120) +#endif + +#if __FRV_FPR__ != 0 + stdfi fr16, @(gr8,128) + stdfi fr18, @(gr8,136) + stdfi fr20, @(gr8,144) + stdfi fr22, @(gr8,152) + stdfi fr24, @(gr8,160) + stdfi fr26, @(gr8,168) + stdfi fr28, @(gr8,176) + stdfi fr30, @(gr8,184) +#if __FRV_FPR__ != 32 + stdfi fr48, @(gr8,192) + stdfi fr50, @(gr8,200) + stdfi fr52, @(gr8,208) + stdfi fr54, @(gr8,216) + stdfi fr56, @(gr8,224) + stdfi fr58, @(gr8,232) + stdfi fr60, @(gr8,240) + stdfi fr62, @(gr8,248) +#endif +#endif + + movsg lr, gr4 + sti gr4, @(gr8,256) + sti sp, @(gr8,260) + sti fp, @(gr8,264) + + sethi.p #gotofffuncdeschi(__sigjmp_save), gr4 + setlo #gotofffuncdesclo(__sigjmp_save), gr4 + ldd @(gr15, gr4), gr14 + jmpl @(gr14, gr0) + .size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/frv/stat.c b/libc/sysdeps/linux/frv/stat.c new file mode 100644 index 0000000..ea9592f --- /dev/null +++ b/libc/sysdeps/linux/frv/stat.c @@ -0,0 +1,18 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +libc_hidden_proto(stat) +_syscall2(int, stat, const char *, file_name, struct stat *, buf) +libc_hidden_def(stat) diff --git a/libc/sysdeps/linux/frv/stat64.c b/libc/sysdeps/linux/frv/stat64.c new file mode 100644 index 0000000..daa5ac9 --- /dev/null +++ b/libc/sysdeps/linux/frv/stat64.c @@ -0,0 +1,20 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(stat64) +_syscall2(int, stat64, const char *, file_name, struct stat64 *, buf) +libc_hidden_def(stat64) +#endif diff --git a/libc/sysdeps/linux/frv/sys/procfs.h b/libc/sysdeps/linux/frv/sys/procfs.h new file mode 100644 index 0000000..f075233 --- /dev/null +++ b/libc/sysdeps/linux/frv/sys/procfs.h @@ -0,0 +1,125 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_int_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpmedia_regs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/frv/sys/ptrace.h b/libc/sysdeps/linux/frv/sys/ptrace.h new file mode 100644 index 0000000..6b0eca7 --- /dev/null +++ b/libc/sysdeps/linux/frv/sys/ptrace.h @@ -0,0 +1,139 @@ +/* `ptrace' debugger support interface. FRV-Linux version. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPXREGS = 18, +#define PT_GETFPXREGS PTRACE_GETFPXREGS + + /* Set all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPXREGS = 19, +#define PT_SETFPXREGS PTRACE_SETFPXREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24, +#define PT_SYSCALL PTRACE_SYSCALL + + /* Obtain the load map of the main program or the interpreter of the + ptraced process, depending on whether the addr argument is + (void*)0 or (void*)1, respectively. */ + PTRACE_GETFDPIC = 31 +#define PT_GETFDPIC PTRACE_GETFDPIC +}; + +#define PTRACE_GETFDPIC_EXEC ((void*)0) /* [addr] request the executable loadmap */ +#define PTRACE_GETFDPIC_INTERP ((void*)1) /* [addr] request the interpreter loadmap */ + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/frv/sys/ucontext.h b/libc/sysdeps/linux/frv/sys/ucontext.h new file mode 100644 index 0000000..487c9ee --- /dev/null +++ b/libc/sysdeps/linux/frv/sys/ucontext.h @@ -0,0 +1,451 @@ +/* Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef unsigned long greg_t; + +/* Number of general registers. */ +#define NGREG (10+2+64) + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_PSR = 0, +#define REG_PSR REG_PSR + REG_ISR = 1, +#define REG_ISR REG_ISR + REG_CCR = 2, +#define REG_CCR REG_CCR + REG_CCCR = 3, +#define REG_CCCR REG_CCCR + REG_LR = 4, +#define REG_LR REG_LR + REG_LCR = 5, +#define REG_LCR REG_LCR + REG_PC = 6, +#define REG_PC REG_PC + REG___STATUS = 7, +#define REG___STATUS REG___STATUS + REG_SYSCALLNO = 8, +#define REG_SYSCALLNO REG_SYSCALLNO + REG_ORIG_GR8 = 9, +#define REG_ORIG_GR8 REG_ORIG_GR8 + REG_GNER0 = 10, +#define REG_GNER0 REG_GNER0 + REG_GNER1 = 11, +#define REG_GNER1 REG_GNER1 + REG_GR0 = 12, +#define REG_GR0 REG_GR0 + REG_GR1 = 13, +#define REG_GR1 REG_GR1 + REG_GR2 = 14, +#define REG_GR2 REG_GR2 + REG_GR3 = 15, +#define REG_GR3 REG_GR3 + REG_GR4 = 16, +#define REG_GR4 REG_GR4 + REG_GR5 = 17, +#define REG_GR5 REG_GR5 + REG_GR6 = 18, +#define REG_GR6 REG_GR6 + REG_GR7 = 19, +#define REG_GR7 REG_GR7 + REG_GR8 = 20, +#define REG_GR8 REG_GR8 + REG_GR9 = 21, +#define REG_GR9 REG_GR9 + REG_GR10 = 22, +#define REG_GR10 REG_GR10 + REG_GR11 = 23, +#define REG_GR11 REG_GR11 + REG_GR12 = 24, +#define REG_GR12 REG_GR12 + REG_GR13 = 25, +#define REG_GR13 REG_GR13 + REG_GR14 = 26, +#define REG_GR14 REG_GR14 + REG_GR15 = 27, +#define REG_GR15 REG_GR15 + REG_GR16 = 28, +#define REG_GR16 REG_GR16 + REG_GR17 = 29, +#define REG_GR17 REG_GR17 + REG_GR18 = 30, +#define REG_GR18 REG_GR18 + REG_GR19 = 31, +#define REG_GR19 REG_GR19 + REG_GR20 = 32, +#define REG_GR20 REG_GR20 + REG_GR21 = 33, +#define REG_GR21 REG_GR21 + REG_GR22 = 34, +#define REG_GR22 REG_GR22 + REG_GR23 = 35, +#define REG_GR23 REG_GR23 + REG_GR24 = 36, +#define REG_GR24 REG_GR24 + REG_GR25 = 37, +#define REG_GR25 REG_GR25 + REG_GR26 = 38, +#define REG_GR26 REG_GR26 + REG_GR27 = 39, +#define REG_GR27 REG_GR27 + REG_GR28 = 40, +#define REG_GR28 REG_GR28 + REG_GR29 = 41, +#define REG_GR29 REG_GR29 + REG_GR30 = 42, +#define REG_GR30 REG_GR30 + REG_GR31 = 43, +#define REG_GR31 REG_GR31 + REG_GR32 = 44, +#define REG_GR32 REG_GR32 + REG_GR33 = 45, +#define REG_GR33 REG_GR33 + REG_GR34 = 46, +#define REG_GR34 REG_GR34 + REG_GR35 = 47, +#define REG_GR35 REG_GR35 + REG_GR36 = 48, +#define REG_GR36 REG_GR36 + REG_GR37 = 49, +#define REG_GR37 REG_GR37 + REG_GR38 = 50, +#define REG_GR38 REG_GR38 + REG_GR39 = 51, +#define REG_GR39 REG_GR39 + REG_GR40 = 52, +#define REG_GR40 REG_GR40 + REG_GR41 = 53, +#define REG_GR41 REG_GR41 + REG_GR42 = 54, +#define REG_GR42 REG_GR42 + REG_GR43 = 55, +#define REG_GR43 REG_GR43 + REG_GR44 = 56, +#define REG_GR44 REG_GR44 + REG_GR45 = 57, +#define REG_GR45 REG_GR45 + REG_GR46 = 58, +#define REG_GR46 REG_GR46 + REG_GR47 = 59, +#define REG_GR47 REG_GR47 + REG_GR48 = 60, +#define REG_GR48 REG_GR48 + REG_GR49 = 61, +#define REG_GR49 REG_GR49 + REG_GR50 = 62, +#define REG_GR50 REG_GR50 + REG_GR51 = 63, +#define REG_GR51 REG_GR51 + REG_GR52 = 64, +#define REG_GR52 REG_GR52 + REG_GR53 = 65, +#define REG_GR53 REG_GR53 + REG_GR54 = 66, +#define REG_GR54 REG_GR54 + REG_GR55 = 67, +#define REG_GR55 REG_GR55 + REG_GR56 = 68, +#define REG_GR56 REG_GR56 + REG_GR57 = 69, +#define REG_GR57 REG_GR57 + REG_GR58 = 70, +#define REG_GR58 REG_GR58 + REG_GR59 = 71, +#define REG_GR59 REG_GR59 + REG_GR60 = 72, +#define REG_GR60 REG_GR60 + REG_GR61 = 73, +#define REG_GR61 REG_GR61 + REG_GR62 = 74, +#define REG_GR62 REG_GR62 + REG_GR63 = 75, +#define REG_GR63 REG_GR63 +}; +#endif + +typedef unsigned long freg_t; + +/* Number of FPU registers. */ +#define NFPREG (64+2+2+8+2+1) + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_FR0 = 0, +#define REG_FR0 REG_FR0 + REG_FR1 = 1, +#define REG_FR1 REG_FR1 + REG_FR2 = 2, +#define REG_FR2 REG_FR2 + REG_FR3 = 3, +#define REG_FR3 REG_FR3 + REG_FR4 = 4, +#define REG_FR4 REG_FR4 + REG_FR5 = 5, +#define REG_FR5 REG_FR5 + REG_FR6 = 6, +#define REG_FR6 REG_FR6 + REG_FR7 = 7, +#define REG_FR7 REG_FR7 + REG_FR8 = 8, +#define REG_FR8 REG_FR8 + REG_FR9 = 9, +#define REG_FR9 REG_FR9 + REG_FR10 = 10, +#define REG_FR10 REG_FR10 + REG_FR11 = 11, +#define REG_FR11 REG_FR11 + REG_FR12 = 12, +#define REG_FR12 REG_FR12 + REG_FR13 = 13, +#define REG_FR13 REG_FR13 + REG_FR14 = 14, +#define REG_FR14 REG_FR14 + REG_FR15 = 15, +#define REG_FR15 REG_FR15 + REG_FR16 = 16, +#define REG_FR16 REG_FR16 + REG_FR17 = 17, +#define REG_FR17 REG_FR17 + REG_FR18 = 18, +#define REG_FR18 REG_FR18 + REG_FR19 = 19, +#define REG_FR19 REG_FR19 + REG_FR20 = 20, +#define REG_FR20 REG_FR20 + REG_FR21 = 21, +#define REG_FR21 REG_FR21 + REG_FR22 = 22, +#define REG_FR22 REG_FR22 + REG_FR23 = 23, +#define REG_FR23 REG_FR23 + REG_FR24 = 24, +#define REG_FR24 REG_FR24 + REG_FR25 = 25, +#define REG_FR25 REG_FR25 + REG_FR26 = 26, +#define REG_FR26 REG_FR26 + REG_FR27 = 27, +#define REG_FR27 REG_FR27 + REG_FR28 = 28, +#define REG_FR28 REG_FR28 + REG_FR29 = 29, +#define REG_FR29 REG_FR29 + REG_FR30 = 30, +#define REG_FR30 REG_FR30 + REG_FR31 = 31, +#define REG_FR31 REG_FR31 + REG_FR32 = 32, +#define REG_FR32 REG_FR32 + REG_FR33 = 33, +#define REG_FR33 REG_FR33 + REG_FR34 = 34, +#define REG_FR34 REG_FR34 + REG_FR35 = 35, +#define REG_FR35 REG_FR35 + REG_FR36 = 36, +#define REG_FR36 REG_FR36 + REG_FR37 = 37, +#define REG_FR37 REG_FR37 + REG_FR38 = 38, +#define REG_FR38 REG_FR38 + REG_FR39 = 39, +#define REG_FR39 REG_FR39 + REG_FR40 = 40, +#define REG_FR40 REG_FR40 + REG_FR41 = 41, +#define REG_FR41 REG_FR41 + REG_FR42 = 42, +#define REG_FR42 REG_FR42 + REG_FR43 = 43, +#define REG_FR43 REG_FR43 + REG_FR44 = 44, +#define REG_FR44 REG_FR44 + REG_FR45 = 45, +#define REG_FR45 REG_FR45 + REG_FR46 = 46, +#define REG_FR46 REG_FR46 + REG_FR47 = 47, +#define REG_FR47 REG_FR47 + REG_FR48 = 48, +#define REG_FR48 REG_FR48 + REG_FR49 = 49, +#define REG_FR49 REG_FR49 + REG_FR50 = 50, +#define REG_FR50 REG_FR50 + REG_FR51 = 51, +#define REG_FR51 REG_FR51 + REG_FR52 = 52, +#define REG_FR52 REG_FR52 + REG_FR53 = 53, +#define REG_FR53 REG_FR53 + REG_FR54 = 54, +#define REG_FR54 REG_FR54 + REG_FR55 = 55, +#define REG_FR55 REG_FR55 + REG_FR56 = 56, +#define REG_FR56 REG_FR56 + REG_FR57 = 57, +#define REG_FR57 REG_FR57 + REG_FR58 = 58, +#define REG_FR58 REG_FR58 + REG_FR59 = 59, +#define REG_FR59 REG_FR59 + REG_FR60 = 60, +#define REG_FR60 REG_FR60 + REG_FR61 = 61, +#define REG_FR61 REG_FR61 + REG_FR62 = 62, +#define REG_FR62 REG_FR62 + REG_FR63 = 63, +#define REG_FR63 REG_FR63 + REG_FNER0 = 64, +#define REG_FNER0 REG_FNER0 + REG_FNER1 = 65, +#define REG_FNER1 REG_FNER1 + REG_MSR0 = 66, +#define REG_MSR0 REG_MSR0 + REG_MSR1 = 67, +#define REG_MSR1 REG_MSR1 + REG_ACC0 = 68, +#define REG_ACC0 REG_ACC0 + REG_ACC1 = 69, +#define REG_ACC1 REG_ACC1 + REG_ACC2 = 70, +#define REG_ACC2 REG_ACC2 + REG_ACC3 = 71, +#define REG_ACC3 REG_ACC3 + REG_ACC4 = 72, +#define REG_ACC4 REG_ACC4 + REG_ACC5 = 73, +#define REG_ACC5 REG_ACC5 + REG_ACC6 = 74, +#define REG_ACC6 REG_ACC6 + REG_ACC7 = 75, +#define REG_ACC7 REG_ACC7 + REG_ACCG0123 = 76, +#define REG_ACCG0123 REG_ACCG0123 + REG_ACCG4567 = 77, +#define REG_ACCG4567 REG_ACCG4567 + REG_FSR0 = 78, +#define REG_FSR0 REG_FSR0 +}; +#endif + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + void *extension; + unsigned long sc_oldmask; /* old sigmask */ + } __attribute__((aligned(8))) mcontext_t; + +#ifdef __USE_GNU +struct kernel_user_int_regs +{ + /* integer registers + * - up to gr[31] mirror pt_regs in the kernel + */ + unsigned long psr; /* Processor Status Register */ + unsigned long isr; /* Integer Status Register */ + unsigned long ccr; /* Condition Code Register */ + unsigned long cccr; /* Condition Code for Conditional Insns Register */ + unsigned long lr; /* Link Register */ + unsigned long lcr; /* Loop Count Register */ + unsigned long pc; /* Program Counter Register */ + unsigned long __status; /* exception status */ + unsigned long syscallno; /* syscall number or -1 */ + unsigned long orig_gr8; /* original syscall arg #1 */ + unsigned long gner[2]; + + union { + unsigned long tbr; + unsigned long gr[64]; + }; +}; + +struct kernel_user_fpmedia_regs +{ + /* FP/Media registers */ + unsigned long fr[64]; + unsigned long fner[2]; + unsigned long msr[2]; + unsigned long acc[8]; + unsigned char accg[8]; + unsigned long fsr[1]; +}; + +struct kernel_user_context +{ + struct kernel_user_int_regs i; + struct kernel_user_fpmedia_regs f; + + /* we provide a context extension so that we can save the regs for CPUs that + * implement many more of Fujitsu's lavish register spec + */ + void *extension; + + /* This is not part of the kernel's struct user_context, but + rather of the enclosing struct sigcontext, but we add it + here to parallel mcontext_t, just for completeness. */ + unsigned long sc_oldmask; /* old sigmask */ +} __attribute__((aligned(8))); + +/* This union enables alias-safe casts from mcontext_t* to the union + type, that can then be dereferenced as_aliases. */ +union kmcontext_t +{ + mcontext_t as_regsets; + /* as_aliases is actually missing sc_oldmask, that is present in + mcontext_t. */ + struct kernel_user_context as_aliases; +}; +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/frv/syscall.c b/libc/sysdeps/linux/frv/syscall.c new file mode 100644 index 0000000..7b416e8 --- /dev/null +++ b/libc/sysdeps/linux/frv/syscall.c @@ -0,0 +1,41 @@ +/* syscall for frv/uClibc + * + * Copyright (C) 2004 by Alexandre Oliva + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ + register unsigned long __scnum __asm__ ("gr7") = (sysnum); + register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) (arg1); + register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) (arg2); + register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) (arg3); + register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) (arg4); + register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) (arg5); + register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) (arg6); + __asm__ __volatile__ ("tra gr0,gr0" + : "+r" (__sc0) + : "r" (__scnum), "r" (__sc1), "r" (__sc2), + "r" (__sc3), "r" (__sc4), "r" (__sc5)); + __syscall_return(long,__sc0); +} diff --git a/libc/sysdeps/linux/frv/sysdep.c b/libc/sysdeps/linux/frv/sysdep.c new file mode 100644 index 0000000..7387d11 --- /dev/null +++ b/libc/sysdeps/linux/frv/sysdep.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This routine is jumped to by all the syscall handlers, to stash + an error number into errno. */ +int __syscall_error (int err_no) +{ + __set_errno (-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/frv/vfork.S b/libc/sysdeps/linux/frv/vfork.S new file mode 100644 index 0000000..8935a12 --- /dev/null +++ b/libc/sysdeps/linux/frv/vfork.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2003, 2004 Free Software Foudnation, Inc. + This file is part of the GNU C Library. + Contributed by David Howells , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include +#define _ERRNO_H 1 +#include + + .text + .globl __vfork + .hidden __vfork + .type __vfork,@function +/* int vfork(void) */ +__vfork: + setlos.p #__NR_vfork, gr7 + setlos #-4096, gr4 + tra gr0, gr0 + + cmp gr8, gr4, icc0 + blslr icc0, #2 + + sethi.p #gotofffuncdeschi(__syscall_error), gr14 + setlo #gotofffuncdesclo(__syscall_error), gr14 + ldd @(gr14, gr15), gr14 + jmpl @(gr14, gr0) + + .size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/frv/xstatconv.c b/libc/sysdeps/linux/frv/xstatconv.c new file mode 100644 index 0000000..d7948c0 --- /dev/null +++ b/libc/sysdeps/linux/frv/xstatconv.c @@ -0,0 +1 @@ +/* We don't need any of this. */ diff --git a/libc/sysdeps/linux/h8300/Makefile b/libc/sysdeps/linux/h8300/Makefile new file mode 100644 index 0000000..2ab4ee6 --- /dev/null +++ b/libc/sysdeps/linux/h8300/Makefile @@ -0,0 +1,65 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak +ifeq ($(DOPIC),y) +# is this not provided by gcc ? +ASFLAGS+=-D__PIC__ +endif + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC := ptrace.c brk.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/h8300/__longjmp.S b/libc/sysdeps/linux/h8300/__longjmp.S new file mode 100644 index 0000000..5cffa3e --- /dev/null +++ b/libc/sysdeps/linux/h8300/__longjmp.S @@ -0,0 +1,22 @@ +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global ___longjmp + +___longjmp: + mov.l er1,er1 + bne 1f + sub.l er1,er1 + inc.l #1,er1 +1: + mov.l @er0+,er4 + mov.l @er0+,er5 + mov.l @er0+,er6 + mov.l @er0+,sp + mov.l @er0+,er3 ; return PC + adds #4,sp ; adjust return stack + jmp @er3 diff --git a/libc/sysdeps/linux/h8300/bits/byteswap.h b/libc/sysdeps/linux/h8300/bits/byteswap.h new file mode 100644 index 0000000..dc56467 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/byteswap.h @@ -0,0 +1,67 @@ +/* Macros to swap the order of bytes in integer values. H8/300 version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Swap bytes in 16 bit value. We don't provide an assembler version + because GCC is smart enough to generate optimal assembler output, and + this allows for better cse. */ +#define __bswap_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_32(x) \ + __extension__ \ + ({ unsigned int __v; \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_32 (x); \ + else \ + __asm__ __volatile__ ("mov.l %0,er0\n\t" \ + "mov.b r0l,r1h\n\t" \ + "mov.b r0h,r1l\n\t" \ + "mov.w r1,e1\n\t" \ + "mov.w e0,r0\n\t" \ + "mov.b r0l,r1h\n\t" \ + "mov.b r0h,r1l\n\t" \ + "mov.l er1,%0" \ + : "=d" (__v) \ + : "0" (x): "er0","er1"); \ + __v; }) +#else +# define __bswap_32(x) __bswap_constant_32 (x) +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + __extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __v, __r; \ + __v.__ll = (x); \ + __r.__l[0] = __bswap_32 (__v.__l[1]); \ + __r.__l[1] = __bswap_32 (__v.__l[0]); \ + __r.__ll; }) +#endif diff --git a/libc/sysdeps/linux/h8300/bits/endian.h b/libc/sysdeps/linux/h8300/bits/endian.h new file mode 100644 index 0000000..383918d --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/endian.h @@ -0,0 +1,7 @@ +/* H8/300 is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/h8300/bits/fcntl.h b/libc/sysdeps/linux/h8300/bits/fcntl.h new file mode 100644 index 0000000..87d1939 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/fcntl.h @@ -0,0 +1,234 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/h8300/bits/kernel_stat.h b/libc/sysdeps/linux/h8300/bits/kernel_stat.h new file mode 100644 index 0000000..9468292 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/kernel_stat.h @@ -0,0 +1,61 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned char __pad0[6]; + unsigned short st_dev; + unsigned char __pad1[2]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/h8300/bits/kernel_types.h b/libc/sysdeps/linux/h8300/bits/kernel_types.h new file mode 100644 index 0000000..0570675 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/kernel_types.h @@ -0,0 +1,44 @@ +#ifndef _BITS_KERNEL_TYPES_H +#define _BITS_KERNEL_TYPES_H + +/* Sigh. We need to carefully wrap this one... No guarantees + * that the asm/posix_types.h kernel header is working. Many + * arches have broken headers that introduce tons of gratuitous + * conflicts with uClibc's namespace. See bits/kernel_types.h + * for i386, arm, etc for examples... */ + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _BITS_KERNEL_TYPES_H */ diff --git a/libc/sysdeps/linux/h8300/bits/mman.h b/libc/sysdeps/linux/h8300/bits/mman.h new file mode 100644 index 0000000..7f644b9 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/mman.h @@ -0,0 +1,76 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/h8300/bits/setjmp.h b/libc/sysdeps/linux/h8300/bits/setjmp.h new file mode 100644 index 0000000..15f8d84 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/setjmp.h @@ -0,0 +1,32 @@ + +/* Copyright (C) 2004, Yoshinori Sato */ +/* Define the machine-dependent type `jmp_buf'. H8/300 version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +typedef struct + { + unsigned long __regs[4]; /* save er4 - er7(sp) */ + unsigned long __pc; /* the return address */ + } __jmp_buf[1]; + +#endif /* _ASM */ + +#define JB_REGS 0 +#define JB_PC 16 +#define JB_SIZE 20 + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__regs[3]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h b/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h new file mode 100644 index 0000000..b7e08cf --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/h8300/bits/stackinfo.h b/libc/sysdeps/linux/h8300/bits/stackinfo.h new file mode 100644 index 0000000..89a77d9 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On h8300 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/h8300/bits/syscalls.h b/libc/sysdeps/linux/h8300/bits/syscalls.h new file mode 100644 index 0000000..5867ed6 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/syscalls.h @@ -0,0 +1,151 @@ +/* Unlike the asm/unistd.h kernel header file (which this is partly based on), + * this file must be able to cope with PIC and non-PIC code. For some arches + * there is no difference. For x86 (which has far too few registers) there is + * a difference. Regardless, including asm/unistd.h is hereby officially + * forbidden. Don't do it. It is bad for you. + */ +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + /* avoid using res which is declared to be in register d0; \ + errno might expand to a function call and clobber it. */ \ + int __err = -(res); \ + errno = __err; \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type, name) \ +type name(void) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %1,er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name) \ + : "cc"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall1(type, name, atype, a) \ +type name(atype a) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a) \ + : "cc", "er1"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall2(type, name, atype, a, btype, b) \ +type name(atype a, btype b) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b) \ + : "cc", "er1", "er2"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c) \ + : "cc", "er1", "er2", "er3"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c, dtype d) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %5, er4\n\t" \ + "mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c), \ + "g" ((long)d) \ + : "cc", "er1", "er2", "er3", "er4"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c, dtype d, etype e) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ( \ + "mov.l er5,@-sp\n\t" \ + "mov.l %5, er4\n\t" \ + "mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "mov.l %6, er5\n\t" \ + "trapa #0\n\t" \ + "mov.l @sp+,er5\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c), \ + "g" ((long)d), \ + "m" ((long)e) \ + : "cc", "er1", "er2", "er3", "er4"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + diff --git a/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h b/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h new file mode 100644 index 0000000..b0d032d --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/h8300/bits/wordsize.h b/libc/sysdeps/linux/h8300/bits/wordsize.h new file mode 100644 index 0000000..b47eee9 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bits/wordsize.h @@ -0,0 +1 @@ +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/h8300/brk.c b/libc/sysdeps/linux/h8300/brk.c new file mode 100644 index 0000000..9eab660 --- /dev/null +++ b/libc/sysdeps/linux/h8300/brk.c @@ -0,0 +1,38 @@ +/* brk on H8/300 by ysato */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *newbrk; + + __asm__ ("mov.l %2,er1\n\t" + "mov.l %1,er0\n\t" + "trapa #0\n\t" + "mov.l er0,%0" + : "=r" (newbrk) + : "0" (__NR_brk), "g" (addr) + : "er0","er1"); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/h8300/bsd-_setjmp.S b/libc/sysdeps/linux/h8300/bsd-_setjmp.S new file mode 100644 index 0000000..e315058 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bsd-_setjmp.S @@ -0,0 +1,27 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. H8/300 version. */ + +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global __setjmp + +__setjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + mov.l er0,er1 + sub.l er0,er0 + mov.l er0,@(JB_SIZE:16,er1) + rts diff --git a/libc/sysdeps/linux/h8300/bsd-setjmp.S b/libc/sysdeps/linux/h8300/bsd-setjmp.S new file mode 100644 index 0000000..9c35355 --- /dev/null +++ b/libc/sysdeps/linux/h8300/bsd-setjmp.S @@ -0,0 +1,30 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 1)'. H8/300 version. */ + +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global _setjmp + +_setjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + sub.l er0,er0 +#if !defined(__PIC__) + jmp @___sigjmp_save +#else + mov.l @(___sigjmp_save@GOTOFF,er5),er1 + jmp @er3 +#endif diff --git a/libc/sysdeps/linux/h8300/clone.S b/libc/sysdeps/linux/h8300/clone.S new file mode 100644 index 0000000..554a297 --- /dev/null +++ b/libc/sysdeps/linux/h8300/clone.S @@ -0,0 +1,68 @@ +/* Adapted from glibc */ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + +.text +.globl _clone +_clone: + /* Sanity check arguments. */ + mov.l #-EINVAL,er3 + mov.l er0,er0 /* no NULL function pointers */ + beq __syscall_error + mov.l er1,er1 /* no NULL stack pointers */ + beq __syscall_error + + /* Allocate space and copy the argument onto the new stack. */ + mov.l @(4:16,sp),er3 + mov.l er3,@-er1 + + /* Do the system call */ + mov.l er0,er3 /* er3 = child entry */ + mov.l er1,er0 + mov.l er2,er1 /* er1 = flags */ + mov.l er0,er2 /* er2 = child sp */ + mov.l #__NR_clone,r0 + trapa #0 + mov.l er0,er0 + bmi __syscall_error + beq thread_start + + rts + +__syscall_error: + neg.l er0 + mov.l er0,@-sp +#if !defined(__PIC__) + jsr @__errno_location +#else + mov.l @(__errno_location@GOTOFF,er5),er1 + jsr @er1 +#endif + mov.l @sp,er1 + mov.l er1,@er0 + sub.l er0,er0 + dec.l #1,er0 + + rts + +thread_start: + mov.l @sp+,er0 /* restore args */ + jsr @er3 + mov.l er0,er1 + mov.l #__NR_exit,er0 + trapa #0 diff --git a/libc/sysdeps/linux/h8300/crt0.S b/libc/sysdeps/linux/h8300/crt0.S new file mode 100644 index 0000000..ebdca18 --- /dev/null +++ b/libc/sysdeps/linux/h8300/crt0.S @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + + .global _start + .global __exit + .global atexit + .global main + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +_start: /* put here so that references to _start work with elf-PIC */ + + mov.l @(0,sp),er0 /* argc */ + mov.l @(4,sp),er1 /* argv */ + mov.l @(8,sp),er2 /* envp */ +#if !defined(__PIC__) + jsr @___uClibc_main +#else + mov.l @(___uClibc_main@GOTOFF,er5),er3 + jsr @er3 +#endif + + /* If that didn't kill us, ... */ +__exit: + mov.l er0,er1 + sub.l er0,er0 + inc.l #1,er0 /* __NR_exit */ + trapa #0 + +/* + * this was needed for gcc/g++-builds, atexit was not getting included + * for some stupid reason, this gets us a compiler + */ +empty_func: + rts + .weak atexit + atexit = empty_func + + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/h8300/crti.S b/libc/sysdeps/linux/h8300/crti.S new file mode 100644 index 0000000..270df27 --- /dev/null +++ b/libc/sysdeps/linux/h8300/crti.S @@ -0,0 +1,30 @@ +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + .file "initfini.c" +; #APP + + .section .init +; #NO_APP + .align 1 + .global __init +__init: + mov.l er6,@-er7 + mov.l er7,er6 +; #APP + .align 1 + + .section .fini +; #NO_APP + .align 1 + .global __fini +__fini: + mov.l er6,@-er7 + mov.l er7,er6 +; #APP + .align 1 + + .end diff --git a/libc/sysdeps/linux/h8300/crtn.S b/libc/sysdeps/linux/h8300/crtn.S new file mode 100644 index 0000000..89e3218 --- /dev/null +++ b/libc/sysdeps/linux/h8300/crtn.S @@ -0,0 +1,30 @@ +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + .file "initfini.c" +; #APP + + .section .init +; #NO_APP + .align 1 + .global __init +; #NO_APP + mov.l @er7+,er6 + rts + .size __init, .-__init +; #APP + + .section .fini +; #NO_APP + .align 1 + .global __fini +; #NO_APP + mov.l @er7+,er6 + rts + .size __fini, .-__fini +; #APP + + .end diff --git a/libc/sysdeps/linux/h8300/float.h b/libc/sysdeps/linux/h8300/float.h new file mode 100644 index 0000000..7dbe4e9 --- /dev/null +++ b/libc/sysdeps/linux/h8300/float.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/libc/sysdeps/linux/h8300/ptrace.c b/libc/sysdeps/linux/h8300/ptrace.c new file mode 100644 index 0000000..1dd7d06 --- /dev/null +++ b/libc/sysdeps/linux/h8300/ptrace.c @@ -0,0 +1,36 @@ + +#include +#include +#include + +int +ptrace(int request, int pid, int addr, int data) +{ + int ret; + int res; + + if (request > 0 && request < 4) data = (int)&ret; + + __asm__ __volatile__ ("sub.l er0,er0\n\t" + "mov.b %1,r0l\n\t" + "mov.l %2,er1\n\t" + "mov.l %3,er2\n\t" + "mov.l %4,er3\n\t" + "mov.l %5,er4\n\t" + "trapa #0\n\t" + "mov.l er0,%0" + :"=g" (res) + :"i" (__NR_ptrace), "g" (request), "g" (pid), + "g" (addr), "g" (data) + : "er0", "er1", "er2", "er3", "er4"); + + if (res >= 0) { + if (request > 0 && request < 4) { + __set_errno(0); + return (ret); + } + return (int) res; + } + __set_errno(-res); + return -1; +} diff --git a/libc/sysdeps/linux/h8300/setjmp.S b/libc/sysdeps/linux/h8300/setjmp.S new file mode 100644 index 0000000..5e48767 --- /dev/null +++ b/libc/sysdeps/linux/h8300/setjmp.S @@ -0,0 +1,23 @@ +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global ___sigsetjmp + +___sigsetjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + sub.l er0,er0 + rts diff --git a/libc/sysdeps/linux/h8300/sys/procfs.h b/libc/sysdeps/linux/h8300/sys/procfs.h new file mode 100644 index 0000000..27abf8e --- /dev/null +++ b/libc/sysdeps/linux/h8300/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/h8300/sys/ucontext.h b/libc/sysdeps/linux/h8300/sys/ucontext.h new file mode 100644 index 0000000..ffc9ea0 --- /dev/null +++ b/libc/sysdeps/linux/h8300/sys/ucontext.h @@ -0,0 +1,75 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* H8/300 compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NFPREG 8 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NFPREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + ER0 = 0, +#define ER0 ER0 + ER1 = 1, +#define ER1 ER1 + ER2 = 2, +#define ER2 ER2 + ER3 = 3, +#define ER3 ER3 + ER4 = 4, +#define ER4 ER4 + ER5 = 5, +#define ER5 ER5 + ER6 = 6, +#define ER6 ER6 + ER7 = 7, +#define ER7 ER7 +}; +#endif + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif + diff --git a/libc/sysdeps/linux/h8300/vfork.S b/libc/sysdeps/linux/h8300/vfork.S new file mode 100644 index 0000000..35c04e5 --- /dev/null +++ b/libc/sysdeps/linux/h8300/vfork.S @@ -0,0 +1,41 @@ + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + .align 2 + .globl _errno + .globl ___vfork + .hidden ___vfork + .type ___vfork,@function +___vfork: + mov.l @sp+, er1 + sub.l er0,er0 + mov.b #__NR_vfork,r0l + trapa #0 + mov.l #-4096, er2 + cmp.l er0,er2 + bcs fix_errno + jmp @er1 /* don't return, just jmp directly */ +fix_errno: + neg.l er0 +#if !defined(__PIC__) + mov.l er0,@_errno +#else + mov.l @(_errno@GOTOFF,er5),er2 + mov.l er0,@er2 +#endif + sub.l er0,er0 + dec.l #1,er0 + jmp @er1 /* don't return, just jmp directly */ + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/hppa/Makefile b/libc/sysdeps/linux/hppa/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/hppa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/hppa/Makefile.arch b/libc/sysdeps/linux/hppa/Makefile.arch new file mode 100644 index 0000000..9739e74 --- /dev/null +++ b/libc/sysdeps/linux/hppa/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c brk.c mmap.c syscall.c + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S \ + add_n.s lshift.s rshift.s sub_n.s udiv_qrnnd.s + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/hppa/__longjmp.S b/libc/sysdeps/linux/hppa/__longjmp.S new file mode 100644 index 0000000..750863e --- /dev/null +++ b/libc/sysdeps/linux/hppa/__longjmp.S @@ -0,0 +1,74 @@ +/* longjmp for PA-RISC. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _SETJMP_H +#define _ASM +#include + +/* __longjmp(jmpbuf, val) */ + + .text + .align 4 + .globl __longjmp + .export __longjmp, code + .proc + .callinfo +__longjmp: + /* set return value */ + copy %r25, %r28 + + ldw 0(%r26), %r3 + ldw 8(%r26), %r4 + ldw 12(%r26), %r5 + ldw 16(%r26), %r6 + ldw 20(%r26), %r7 + ldw 24(%r26), %r8 + ldw 28(%r26), %r9 + ldw 32(%r26), %r10 + ldw 36(%r26), %r11 + ldw 40(%r26), %r12 + ldw 44(%r26), %r13 + ldw 48(%r26), %r14 + ldw 52(%r26), %r15 + ldw 56(%r26), %r16 + ldw 60(%r26), %r17 + ldw 64(%r26), %r18 + ldw 68(%r26), %r19 + ldw 72(%r26), %r27 + ldw 76(%r26), %r30 + + ldw 80(%r26), %rp + + ldo 88(%r26),%r20 + fldds,ma 8(%r20), %fr12 + fldds,ma 8(%r20), %fr13 + fldds,ma 8(%r20), %fr14 + fldds,ma 8(%r20), %fr15 + fldds,ma 8(%r20), %fr16 + fldds,ma 8(%r20), %fr17 + fldds,ma 8(%r20), %fr18 + fldds,ma 8(%r20), %fr19 + fldds,ma 8(%r20), %fr20 + fldds 0(%r20), %fr21 + + bv,n %r0(%r2) + .procend + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/hppa/__syscall_error.c b/libc/sysdeps/linux/hppa/__syscall_error.c new file mode 100644 index 0000000..5e109a8 --- /dev/null +++ b/libc/sysdeps/linux/hppa/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/hppa/add_n.s b/libc/sysdeps/linux/hppa/add_n.s new file mode 100644 index 0000000..a396b34 --- /dev/null +++ b/libc/sysdeps/linux/hppa/add_n.s @@ -0,0 +1,58 @@ +;! HP-PA __mpn_add_n -- Add two limb vectors of the same length > 0 and store +;! sum in a third limb vector. + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP 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. + +;! The GNU MP 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 the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s1_ptr gr25 +;! s2_ptr gr24 +;! size gr23 + +;! One might want to unroll this as for other processors, but it turns +;! out that the data cache contention after a store makes such +;! unrolling useless. We can't come under 5 cycles/limb anyway. + + .text + .export __mpn_add_n +__mpn_add_n: + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + + addib,= -1,%r23,L$end ;! check for (SIZE == 1) + add %r21,%r20,%r28 ;! add first limbs ignoring cy + +L$loop: ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + stws,ma %r28,4(%r26) + addib,<> -1,%r23,L$loop + addc %r21,%r20,%r28 + +L$end: stws %r28,0(%r26) + bv 0(%r2) + addc %r0,%r0,%r28 + + .exit + .procend diff --git a/libc/sysdeps/linux/hppa/bits/endian.h b/libc/sysdeps/linux/hppa/bits/endian.h new file mode 100644 index 0000000..585db0c --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/endian.h @@ -0,0 +1,7 @@ +/* hppa1.1 big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/hppa/bits/fcntl.h b/libc/sysdeps/linux/hppa/bits/fcntl.h new file mode 100644 index 0000000..c6aaa3a --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/fcntl.h @@ -0,0 +1,228 @@ +/* O_*, F_*, FD_* bit values for Linux/HPPA. + Copyright (C) 1995,1996,1997,1998,1999,2000,2002,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 +#define O_ACCMODE 00000003 +#define O_APPEND 00000010 +#define O_BLKSEEK 00000100 /* HPUX only */ +#define O_CREAT 00000400 /* not fcntl */ +#define O_TRUNC 00001000 /* not fcntl */ +#define O_EXCL 00002000 /* not fcntl */ +#define O_ASYNC 00020000 +#define O_SYNC 00100000 +#define O_NONBLOCK 00200004 /* HPUX has separate NDELAY & NONBLOCK */ +#define O_NDELAY O_NONBLOCK +#define O_NOCTTY 00400000 /* not fcntl */ + + +#ifdef __USE_GNU +# define O_DIRECT 00040000 /* Direct disk access. */ +# define O_DIRECTORY 00010000 /* Must be a directory. */ +# define O_NOFOLLOW 00000200 /* Do not follow links. */ +# define O_NOATIME 04000000 /* Do not set atime. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 00004000 +#endif + +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC 01000000 /* HPUX only */ +# define O_RSYNC 02000000 /* HPUX only */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking). */ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 8 /* Get record locking info. */ +#define F_SETLK64 9 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 10 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_GETOWN 11 /* Get owner of socket (receiver of SIGIO). */ +# define F_SETOWN 12 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 13 /* Set number of signal to be sent. */ +# define F_GETSIG 14 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 3 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/hppa/bits/fenv.h b/libc/sysdeps/linux/hppa/bits/fenv.h new file mode 100644 index 0000000..c5f8c43 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/fenv.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Huggins-Daines + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +/* Define bits representing the exception. We use the values of the + appropriate enable bits in the FPU status word (which, + coincidentally, are the same as the flag bits, but shifted right by + 27 bits). */ +enum +{ + FE_INVALID = 1<<4, /* V */ +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 1<<3, /* Z */ +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 1<<2, /* O */ +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 1<<1, /* U */ +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 1<<0, /* I */ +#define FE_INEXACT FE_INEXACT +}; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The PA-RISC FPU supports all of the four defined rounding modes. + We use the values of the RM field in the floating point status + register for the appropriate macros. */ +enum + { + FE_TONEAREST = 0 << 9, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 9, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 2 << 9, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 3 << 9, +#define FE_DOWNWARD FE_DOWNWARD + }; + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. This structure + corresponds to the layout of the status and exception words in the + register file. */ +typedef struct +{ + unsigned int __status_word; + unsigned int __exception[7]; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((fenv_t *) -2) +#endif diff --git a/libc/sysdeps/linux/hppa/bits/ipc.h b/libc/sysdeps/linux/hppa/bits/ipc.h new file mode 100644 index 0000000..d80cf06 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/ipc.h @@ -0,0 +1,63 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad2; +#else + __mode_t mode; /* Read/write permission. */ + unsigned short int __pad2; +#endif + unsigned short int __seq; /* Sequence number. */ + unsigned int __pad3; + unsigned long long int __unused1; + unsigned long long int __unused2; + }; diff --git a/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h b/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h new file mode 100644 index 0000000..4ae53fd --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h @@ -0,0 +1,26 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* We have a separate header file here because we do not support + SA_RESTORER on hppa. */ + +/* This is the sigaction struction from the Linux 2.1.20 kernel. */ +/* Blah. This is bogus. We don't ever use it. */ +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned long sa_flags; +}; + +/* This is the sigaction structure from the Linux 2.1.68 kernel. */ + +struct kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; + +extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, + struct kernel_sigaction *__unbounded, size_t) attribute_hidden; + +#endif diff --git a/libc/sysdeps/linux/hppa/bits/kernel_stat.h b/libc/sysdeps/linux/hppa/bits/kernel_stat.h new file mode 100644 index 0000000..e4d784e --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/kernel_stat.h @@ -0,0 +1,72 @@ +/* Ripped from linux/include/asm-parisc/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _PARISC_STAT_H +#define _PARISC_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned int st_dev; /* dev_t is 32 bits on parisc */ + ino_t st_ino; /* 32 bits */ + mode_t st_mode; /* 16 bits */ + nlink_t st_nlink; /* 16 bits */ + unsigned short st_reserved1; /* old st_uid */ + unsigned short st_reserved2; /* old st_gid */ + unsigned int st_rdev; + off_t st_size; + time_t st_atime; + unsigned int st_atime_nsec; + time_t st_mtime; + unsigned int st_mtime_nsec; + time_t st_ctime; + unsigned int st_ctime_nsec; + int st_blksize; + int st_blocks; + unsigned int __unused1; /* ACL stuff */ + unsigned int __unused2; /* network */ + ino_t __unused3; /* network */ + unsigned int __unused4; /* cnodes */ + unsigned short __unused5; /* netsite */ + short st_fstype; + unsigned int st_realdev; + unsigned short st_basemode; + unsigned short st_spareshort; + uid_t st_uid; + gid_t st_gid; + unsigned int st_spare4[3]; +}; + +#define STAT_HAVE_NSEC 1 + +/* This is the struct that 32-bit userspace applications are expecting. + * How 64-bit apps are going to be compiled, I have no idea. But at least + * this way, we don't have a wrapper in the kernel. + */ +struct kernel_stat64 { + unsigned long long st_dev; + unsigned int __pad1; + + unsigned int __st_ino; /* Not actually filled in */ + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long long st_rdev; + unsigned int __pad2; + signed long long st_size; + signed int st_blksize; + + signed long long st_blocks; + signed int st_atime; + unsigned int st_atime_nsec; + signed int st_mtime; + unsigned int st_mtime_nsec; + signed int st_ctime; + unsigned int st_ctime_nsec; + unsigned long long st_ino; +}; + +#endif diff --git a/libc/sysdeps/linux/hppa/bits/kernel_types.h b/libc/sysdeps/linux/hppa/bits/kernel_types.h new file mode 100644 index 0000000..4441f9b --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/kernel_types.h @@ -0,0 +1,61 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_PARISC_POSIX_TYPES_H +#define __ARCH_PARISC_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef int __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +/* Note these change from narrow to wide kernels */ +#ifdef __LP64__ +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +#endif +typedef char * __kernel_caddr_t; + +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef long long __kernel_loff_t; +typedef long long __kernel_off64_t; +typedef unsigned long long __kernel_ino64_t; + +typedef unsigned int __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +/* compatibility stuff */ +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; + +#endif /* __ARCH_PARISC_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/hppa/bits/mman.h b/libc/sysdeps/linux/hppa/bits/mman.h new file mode 100644 index 0000000..54531ec --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/mman.h @@ -0,0 +1,92 @@ +/* Definitions for POSIX memory map interface. Linux/HPPA version. + Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* these are basically taken from the kernel definitions */ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x03 /* Mask for type of mapping */ +#define MAP_FIXED 0x04 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x10 /* don't use a file */ + +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +#define MAP_LOCKED 0x2000 /* pages are locked */ +#define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_GROWSDOWN 0x8000 /* stack-like segment */ +#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x20000 /* do not block on IO */ + +#define MS_SYNC 1 /* synchronous memory sync */ +#define MS_ASYNC 2 /* sync memory asynchronously */ +#define MS_INVALIDATE 4 /* invalidate the caches */ + +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + +/* Advice to "madvise" */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* no further special treatment */ +# define MADV_RANDOM 1 /* expect random page references */ +# define MADV_SEQUENTIAL 2 /* expect sequential page references */ +# define MADV_WILLNEED 3 /* will need these pages */ +# define MADV_DONTNEED 4 /* dont need these pages */ +# define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ +# define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */ +# define MADV_VPS_INHERIT 7 /* Inherit parents page size */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The range 12-64 is reserved for page size specification. */ +#define MADV_4K_PAGES 12 /* Use 4K pages */ +#define MADV_16K_PAGES 14 /* Use 16K pages */ +#define MADV_64K_PAGES 16 /* Use 64K pages */ +#define MADV_256K_PAGES 18 /* Use 256K pages */ +#define MADV_1M_PAGES 20 /* Use 1 Megabyte pages */ +#define MADV_4M_PAGES 22 /* Use 4 Megabyte pages */ +#define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */ +#define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 +#define MAP_VARIABLE 0 + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + + diff --git a/libc/sysdeps/linux/hppa/bits/setjmp.h b/libc/sysdeps/linux/hppa/bits/setjmp.h new file mode 100644 index 0000000..4395b8f --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/setjmp.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. HPPA version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'double' instead, to make writing the assembler + easier, and to ensure proper alignment. Naturally, user code should + not depend on either representation. */ + +#if defined __USE_MISC || defined _ASM +#define JB_SP (76/4) +#endif + +#ifndef _ASM +typedef double __jmp_buf[21]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) > (void *)(((unsigned long *) _jmpbuf)[JB_SP])) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/hppa/bits/sigaction.h b/libc/sysdeps/linux/hppa/bits/sigaction.h new file mode 100644 index 0000000..33f2b23 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/sigaction.h @@ -0,0 +1,75 @@ +/* Definitions for Linux/HPPA sigaction. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Special flags. */ + unsigned long int sa_flags; + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + }; + +/* Bits in `sa_flags'. */ + +#define SA_NOCLDSTOP 0x00000008 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000080 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000010 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESETHAND 0x00000004 /* Reset to SIG_DFL on entry to handler. */ +# define SA_NODEFER 0x00000020 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESTART 0x00000040 /* Restart syscall on signal return. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historic no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/libc/sysdeps/linux/hppa/bits/signum.h b/libc/sysdeps/linux/hppa/bits/signum.h new file mode 100644 index 0000000..bf46006 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/signum.h @@ -0,0 +1,82 @@ +/* Signal number definitions. Linux/HPPA version. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif + + +/* Signals. */ +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGEMT 7 +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGBUS 10 /* BUS error (4.2 BSD). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGSYS 12 /* Bad system call. */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 18 /* Child status has changed (POSIX). */ +#define SIGPWR 19 /* Power failure restart (System V). */ +#define SIGVTALRM 20 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 21 /* Profiling alarm clock (4.2 BSD). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define SIGWINCH 23 /* Window size change (4.3 BSD, Sun). */ +#define SIGSTOP 24 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 25 /* Keyboard stop (POSIX). */ +#define SIGCONT 26 /* Continue (POSIX). */ +#define SIGTTIN 27 /* Background read from tty (POSIX). */ +#define SIGTTOU 28 /* Background write to tty (POSIX). */ +#define SIGURG 29 /* Urgent condition on socket (4.2 BSD). */ +#define SIGLOST 30 /* Operating System Has Lost (HP/UX). */ +#define SIGUNUSED 31 +#define SIGXCPU 33 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 34 /* File size limit exceeded (4.2 BSD). */ +#define SIGSTKFLT 36 /* Stack fault. */ + +#define _NSIG 65 /* Biggest signal number + 1 + (including real-time signals). */ + +#define SIGRTMIN (__libc_current_sigrtmin ()) +#define SIGRTMAX (__libc_current_sigrtmax ()) + +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#define __SIGRTMIN 37 +#define __SIGRTMAX (_NSIG - 1) + +#endif /* included. */ diff --git a/libc/sysdeps/linux/hppa/bits/stackinfo.h b/libc/sysdeps/linux/hppa/bits/stackinfo.h new file mode 100644 index 0000000..318de71 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On PA the stack grows up. */ +#define _STACK_GROWS_UP 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/hppa/bits/syscalls.h b/libc/sysdeps/linux/hppa/bits/syscalls.h new file mode 100644 index 0000000..9035cd5 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/syscalls.h @@ -0,0 +1,155 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) __NR_##syscall_name + +/* Assume all syscalls are done from PIC code just to be + * safe. The worst case scenario is that you lose a register + * and save/restore r19 across the syscall. */ +#define PIC + +/* Definition taken from glibc 2.3.3 + * sysdeps/unix/sysv/linux/hppa/sysdep.h + */ + +#ifdef PIC +/* WARNING: CANNOT BE USED IN A NOP! */ +# define K_STW_ASM_PIC " copy %%r19, %%r4\n" +# define K_LDW_ASM_PIC " copy %%r4, %%r19\n" +# define K_USING_GR4 "%r4", +#else +# define K_STW_ASM_PIC " \n" +# define K_LDW_ASM_PIC " \n" +# define K_USING_GR4 +#endif + +/* GCC has to be warned that a syscall may clobber all the ABI + registers listed as "caller-saves", see page 8, Table 2 + in section 2.2.6 of the PA-RISC RUN-TIME architecture + document. However! r28 is the result and will conflict with + the clobber list so it is left out. Also the input arguments + registers r20 -> r26 will conflict with the list so they + are treated specially. Although r19 is clobbered by the syscall + we cannot say this because it would violate ABI, thus we say + r4 is clobbered and use that register to save/restore r19 + across the syscall. */ + +#define K_CALL_CLOB_REGS "%r1", "%r2", K_USING_GR4 \ + "%r20", "%r29", "%r31" + +#undef K_INLINE_SYSCALL +#define K_INLINE_SYSCALL(name, nr, args...) ({ \ + long __sys_res; \ + { \ + register unsigned long __res __asm__("r28"); \ + K_LOAD_ARGS_##nr(args) \ + /* FIXME: HACK stw/ldw r19 around syscall */ \ + __asm__ __volatile__( \ + K_STW_ASM_PIC \ + " ble 0x100(%%sr2, %%r0)\n" \ + " ldi %1, %%r20\n" \ + K_LDW_ASM_PIC \ + : "=r" (__res) \ + : "i" (SYS_ify(name)) K_ASM_ARGS_##nr \ + : "memory", K_CALL_CLOB_REGS K_CLOB_ARGS_##nr \ + ); \ + __sys_res = (long)__res; \ + } \ + if ( (unsigned long)__sys_res >= (unsigned long)-4095 ){ \ + errno = -__sys_res; \ + __sys_res = -1; \ + } \ + __sys_res; \ +}) + +#define K_LOAD_ARGS_0() +#define K_LOAD_ARGS_1(r26) \ + register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \ + K_LOAD_ARGS_0() +#define K_LOAD_ARGS_2(r26,r25) \ + register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \ + K_LOAD_ARGS_1(r26) +#define K_LOAD_ARGS_3(r26,r25,r24) \ + register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \ + K_LOAD_ARGS_2(r26,r25) +#define K_LOAD_ARGS_4(r26,r25,r24,r23) \ + register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \ + K_LOAD_ARGS_3(r26,r25,r24) +#define K_LOAD_ARGS_5(r26,r25,r24,r23,r22) \ + register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \ + K_LOAD_ARGS_4(r26,r25,r24,r23) +#define K_LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \ + register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \ + K_LOAD_ARGS_5(r26,r25,r24,r23,r22) + +/* Even with zero args we use r20 for the syscall number */ +#define K_ASM_ARGS_0 +#define K_ASM_ARGS_1 K_ASM_ARGS_0, "r" (__r26) +#define K_ASM_ARGS_2 K_ASM_ARGS_1, "r" (__r25) +#define K_ASM_ARGS_3 K_ASM_ARGS_2, "r" (__r24) +#define K_ASM_ARGS_4 K_ASM_ARGS_3, "r" (__r23) +#define K_ASM_ARGS_5 K_ASM_ARGS_4, "r" (__r22) +#define K_ASM_ARGS_6 K_ASM_ARGS_5, "r" (__r21) + +/* The registers not listed as inputs but clobbered */ +#define K_CLOB_ARGS_6 +#define K_CLOB_ARGS_5 K_CLOB_ARGS_6, "%r21" +#define K_CLOB_ARGS_4 K_CLOB_ARGS_5, "%r22" +#define K_CLOB_ARGS_3 K_CLOB_ARGS_4, "%r23" +#define K_CLOB_ARGS_2 K_CLOB_ARGS_3, "%r24" +#define K_CLOB_ARGS_1 K_CLOB_ARGS_2, "%r25" +#define K_CLOB_ARGS_0 K_CLOB_ARGS_1, "%r26" + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 1, arg1); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 2, arg1, arg2); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \ +} + +/* select takes 5 arguments */ +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ +} + +/* mmap & mmap2 take 6 arguments */ +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ + return (type) K_INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h new file mode 100644 index 0000000..2c04f1b --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h @@ -0,0 +1,41 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "iitlbp %r0,(%sr0,%r0)" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* the default ; is a comment on hppa */ +#define __UCLIBC_ASM_LINE_SEP__ ! + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/hppa/bits/wordsize.h b/libc/sysdeps/linux/hppa/bits/wordsize.h new file mode 100644 index 0000000..951e838 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/wordsize.h @@ -0,0 +1,7 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#ifdef __LP64__ +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#endif diff --git a/libc/sysdeps/linux/hppa/brk.c b/libc/sysdeps/linux/hppa/brk.c new file mode 100644 index 0000000..dab2d57 --- /dev/null +++ b/libc/sysdeps/linux/hppa/brk.c @@ -0,0 +1,43 @@ +/* brk system call for Linux/HPPA. + Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int +brk (void *addr) +{ + void *newbrk; + + __curbrk = newbrk = (void *) K_INLINE_SYSCALL (brk, 1, addr); + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/hppa/bsd-_setjmp.S b/libc/sysdeps/linux/hppa/bsd-_setjmp.S new file mode 100644 index 0000000..30e53f5 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bsd-_setjmp.S @@ -0,0 +1,36 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. HPPA version. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .text + .align 4 + .globl _setjmp + .export _setjmp, code + .level 2.0 + .proc + .callinfo + .import __sigsetjmp +_setjmp: + b __sigsetjmp + ldi 0, %r25 + + .procend diff --git a/libc/sysdeps/linux/hppa/bsd-setjmp.S b/libc/sysdeps/linux/hppa/bsd-setjmp.S new file mode 100644 index 0000000..04ddba4 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bsd-setjmp.S @@ -0,0 +1,36 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. HPPA version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .text + .align 4 + .globl setjmp + .export setjmp, code + .level 2.0 + .proc + .callinfo + .import __sigsetjmp +setjmp: + b __sigsetjmp + ldi 1, %r25 + + .procend diff --git a/libc/sysdeps/linux/hppa/clone.S b/libc/sysdeps/linux/hppa/clone.S new file mode 100644 index 0000000..b8e354c --- /dev/null +++ b/libc/sysdeps/linux/hppa/clone.S @@ -0,0 +1,135 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Huggins-Daines , 2000. + Based on the Alpha version by Richard Henderson , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Non-thread code calls __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) + + NPTL Code will call __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + int *parent_tidptr, struct user_desc *newtls, int *child_pidptr) + + The code should not mangle the extra input registers. + Syscall expects: Input to __clone: + 4(r25) - function pointer (r26, arg0) + 0(r25) - argument (r23, arg3) + r26 - clone flags. (r24, arg2) + r25+64 - user stack pointer. (r25, arg1) + r24 - parent tid pointer. (stack - 52) + r23 - struct user_desc newtls pointer. (stack - 56) + r22 - child tid pointer. (stack - 60) + r20 - clone syscall number (constant) + */ + +.text +.global __clone +.type __clone,%function +__clone: + + /* Sanity check arguments. */ + ldi -EINVAL,%ret0 + comib,=,n 0,%arg0,.Lerror /* no NULL function pointers */ + comib,=,n 0,%arg1,.Lerror /* no NULL stack pointers */ + + /* Save the fn ptr and arg on the new stack. */ + stwm %r26,64(%r25) + stw %r23,-60(%r25) + /* Clone arguments are (int flags, void * child_stack) */ + copy %r24,%r26 /* flags are first */ + /* User stack pointer is in the correct register already */ + + /* Load args from stack... */ + ldw -52(%sp), %r24 /* Load parent_tidptr */ + ldw -56(%sp), %r23 /* Load newtls */ + ldw -60(%sp), %r22 /* Load child_tidptr */ + + /* Create frame to get r3 free */ + copy %sp, %r21 + stwm %r3, 64(%sp) + stw %r21, -4(%sp) + + /* Save the PIC register. */ +#ifdef __PIC__ + copy %r19, %r3 /* parent */ +#endif + + /* Do the system call */ + ble 0x100(%sr2,%r0) + ldi __NR_clone,%r20 + + ldi -4096,%r1 + comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ + b,n .LerrorRest + + comib,=,n 0,%ret0,thread_start + + /* Successful return from the parent + No need to restore the PIC register, + since we return immediately. */ + + bv %r0(%rp) + ldwm -64(%sp), %r3 + +.LerrorRest: + /* Restore the PIC register on error */ +#ifdef __PIC__ + copy %r3, %r19 /* parent */ +#endif + + /* Something bad happened -- no child created */ +.Lerror: + + /* Set errno, save ret0 so we return with that value. */ + copy %ret0, %r3 + b __syscall_error + sub %r0,%ret0,%arg0 + copy %r3, %ret0 + /* Return after setting errno, and restoring ret0 */ + bv %r0(%rp) + ldwm -64(%sp), %r3 + +thread_start: + + /* Load up the arguments. */ + ldw -60(%sr0, %sp),%arg0 + ldw -64(%sr0, %sp),%r22 + + /* $$dyncall fixes childs PIC register */ + + /* Call the user's function */ + bl $$dyncall,%r31 + copy %r31,%rp + + bl HIDDEN_JUMPTARGET(_exit),%rp + copy %ret0,%arg0 + + /* Die horribly. */ + iitlbp %r0,(%sr0,%r0) + +.size clone,.-clone + +weak_alias (__clone, clone) diff --git a/libc/sysdeps/linux/hppa/crt1.S b/libc/sysdeps/linux/hppa/crt1.S new file mode 100644 index 0000000..8b42dac --- /dev/null +++ b/libc/sysdeps/linux/hppa/crt1.S @@ -0,0 +1,126 @@ +/* ELF startup code for HPPA. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .import main, code + .import $global$, data + .import __uClibc_main, code +#if defined(__UCLIBC_CTOR_DTOR__) + .import _fini, code + .import _init, code +#else + .weak _fini + .weak _init +#endif + + /* Have the linker create plabel words + so we get PLABEL32 relocs and not 21/14 */ + .section .rodata + .align 4 +.Lpmain: + .word P%main +.Lp__uClibc_main: + .word P%__uClibc_main +.Lp_fini: + .word P%_fini +.Lp_init: + .word P%_init + + .text + .align 4 + .globl _start + .export _start, ENTRY + .type _start,@function +_start: + + .proc + .callinfo + + /* Expand the stack to store the 5th through 7th args */ + ldo 64(%sp), %sp + /* TODO: Follow ABI? Place more things on the stack here... */ + +#ifdef __PIC__ + /* load main (1st argument) */ + addil LR'.Lpmain, %r19 + ldw RR'.Lpmain(%r1), %r26 + ldw 0(%r26),%r26 + /* argc and argv should be in 25 and 24 (2nd and 3rd argument) */ + /* void (*init) (void) (4th argument) */ + addil LR'.Lp_init, %r19 + ldw RR'.Lp_init(%r1), %r23 + ldw 0(%r23), %r23 + /* void (*fini) (void) (5th argument) */ + addil LR'.Lp_fini, %r19 + ldw RR'.Lp_fini(%r1), %r22 + ldw 0(%r22), %r22 +#else + /* load main (1st argument) */ + ldil LR'.Lpmain, %r26 + ldw RR'.Lpmain(%r26), %r26 + /* argc and argv should be in 25 and 24 (2nd and 3rd argument) */ + /* void (*init) (void) (4th argument) */ + ldil LR'.Lp_init, %r23 + ldw RR'.Lp_init(%r23), %r23 + /* void (*fini) (void) (5th argument) */ + ldil LR'.Lp_fini, %r22 + ldw RR'.Lp_fini(%r22), %r22 +#endif + /* Store 5th argument */ + stw %r22, -52(%sp) + /* void (*rtld_fini) (void) (6th argument) */ + stw %r23, -56(%sp) + /* void *stack_end (7th argument) */ + stw %sp, -60(%sp) + + /* load global */ + ldil L%$global$, %dp + ldo R%$global$(%dp), %dp + + bl __uClibc_main,%r2 + nop + /* die horribly if it returned (it shouldn't) */ + iitlbp %r0,(%sr0,%r0) + nop + + .procend + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/hppa/crti.S b/libc/sysdeps/linux/hppa/crti.S new file mode 100644 index 0000000..9a37c71 --- /dev/null +++ b/libc/sysdeps/linux/hppa/crti.S @@ -0,0 +1,24 @@ +/* glibc's sysdeps/hppa/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 4 + .globl _init + .type _init,@function +_init: + stw %rp,-20(%sp) + stwm %r4,64(%sp) + stw %r19,-32(%sp) + copy %r19,%r4 /* delay slot */ + copy %r4,%r19 + + + + .section .fini + .align 4 + .globl _fini + .type _fini,@function +_fini: + stw %rp,-20(%sp) + stwm %r4,64(%sp) + stw %r19,-32(%sp) + copy %r19,%r4 diff --git a/libc/sysdeps/linux/hppa/crtn.S b/libc/sysdeps/linux/hppa/crtn.S new file mode 100644 index 0000000..6602ece --- /dev/null +++ b/libc/sysdeps/linux/hppa/crtn.S @@ -0,0 +1,34 @@ +/* glibc's sysdeps/hppa/elf/initfini.c used for reference [EPILOG] */ + + .text + .align 4 +/* Here is the tail end of _init. We put __gmon_start before this so + that the assembler creates the .PARISC.unwind section for us, ie. + with the right attributes. */ + .section .init + ldw -84(%sp),%rp + copy %r4,%r19 + bv %r0(%rp) +_end_init: + ldwm -64(%sp),%r4 + +/* Our very own unwind info, because the assembler can't handle + functions split into two or more pieces. */ + .section .PARISC.unwind + .extern _init + .word _init, _end_init + .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08 + + + + .section .fini + ldw -84(%sp),%rp + copy %r4,%r19 + bv %r0(%rp) +_end_fini: + ldwm -64(%sp),%r4 + + .section .PARISC.unwind + .extern _fini + .word _fini, _end_fini + .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08 diff --git a/libc/sysdeps/linux/hppa/lshift.s b/libc/sysdeps/linux/hppa/lshift.s new file mode 100644 index 0000000..151b283 --- /dev/null +++ b/libc/sysdeps/linux/hppa/lshift.s @@ -0,0 +1,66 @@ +;! HP-PA __mpn_lshift -- + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP 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. + +;! The GNU MP 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 the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s_ptr gr25 +;! size gr24 +;! cnt gr23 + + .text + .export __mpn_lshift +__mpn_lshift: + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ;! compute carry out limb + ldws,mb -4(%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r22,%r29,%r20 + +L$loop: ldws,mb -4(%r25),%r22 + stws,mb %r20,-4(%r26) + addib,= -1,%r24,L$0003 + vshd %r29,%r22,%r20 + ldws,mb -4(%r25),%r29 + stws,mb %r20,-4(%r26) + addib,<> -1,%r24,L$loop + vshd %r22,%r29,%r20 + +L$0002: stws,mb %r20,-4(%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(%r26) +L$0003: stws,mb %r20,-4(%r26) +L$0004: vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(%r26) + + .exit + .procend diff --git a/libc/sysdeps/linux/hppa/mmap.c b/libc/sysdeps/linux/hppa/mmap.c new file mode 100644 index 0000000..faaaab9 --- /dev/null +++ b/libc/sysdeps/linux/hppa/mmap.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc/x86_64 + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +_syscall6(void *, mmap, void *, start, size_t, length, int, prot, + int, flags, int, fd, off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/hppa/rshift.s b/libc/sysdeps/linux/hppa/rshift.s new file mode 100644 index 0000000..dff189d --- /dev/null +++ b/libc/sysdeps/linux/hppa/rshift.s @@ -0,0 +1,63 @@ +;! HP-PA __mpn_rshift -- + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP 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. + +;! The GNU MP 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 the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s_ptr gr25 +;! size gr24 +;! cnt gr23 + + .text + .export __mpn_rshift +__mpn_rshift: + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$0004 + vshd %r22,%r0,%r28 ;! compute carry out limb + ldws,ma 4(%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r29,%r22,%r20 + +L$loop: ldws,ma 4(%r25),%r22 + stws,ma %r20,4(%r26) + addib,= -1,%r24,L$0003 + vshd %r22,%r29,%r20 + ldws,ma 4(%r25),%r29 + stws,ma %r20,4(%r26) + addib,<> -1,%r24,L$loop + vshd %r29,%r22,%r20 + +L$0002: stws,ma %r20,4(%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(%r26) +L$0003: stws,ma %r20,4(%r26) +L$0004: vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(%r26) + + .exit + .procend diff --git a/libc/sysdeps/linux/hppa/setjmp.S b/libc/sysdeps/linux/hppa/setjmp.S new file mode 100644 index 0000000..fdc4c42 --- /dev/null +++ b/libc/sysdeps/linux/hppa/setjmp.S @@ -0,0 +1,63 @@ +/* setjmp for HPPA. + Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .text + .align 4 + .import __sigjmp_save, code + .globl __sigsetjmp + .export __sigsetjmp, code + .proc + .callinfo +__sigsetjmp: + stw %r3, 0(%r26) + stw %r4, 8(%r26) + stw %r5, 12(%r26) + stw %r6, 16(%r26) + stw %r7, 20(%r26) + stw %r8, 24(%r26) + stw %r9, 28(%r26) + stw %r10, 32(%r26) + stw %r11, 36(%r26) + stw %r12, 40(%r26) + stw %r13, 44(%r26) + stw %r14, 48(%r26) + stw %r15, 52(%r26) + stw %r16, 56(%r26) + stw %r17, 60(%r26) + stw %r18, 64(%r26) + stw %r19, 68(%r26) + stw %r27, 72(%r26) + stw %r30, 76(%r26) + + stw %rp, 80(%r26) + + ldo 88(%r26),%r1 + fstds,ma %fr12, 8(%r1) /* 88 */ + fstds,ma %fr13, 8(%r1) /* 96 */ + fstds,ma %fr14, 8(%r1) /* 104 */ + fstds,ma %fr15, 8(%r1) /* 112 */ + fstds,ma %fr16, 8(%r1) /* 120 */ + fstds,ma %fr17, 8(%r1) /* 128 */ + fstds,ma %fr18, 8(%r1) /* 136 */ + fstds,ma %fr19, 8(%r1) /* 144 */ + fstds,ma %fr20, 8(%r1) /* 152 */ + fstds %fr21, 0(%r1) /* 160 */ + b __sigjmp_save + nop + .procend diff --git a/libc/sysdeps/linux/hppa/sub_n.s b/libc/sysdeps/linux/hppa/sub_n.s new file mode 100644 index 0000000..7764961 --- /dev/null +++ b/libc/sysdeps/linux/hppa/sub_n.s @@ -0,0 +1,59 @@ +;! HP-PA __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and +;! store difference in a third limb vector. + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP 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. + +;! The GNU MP 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 the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s1_ptr gr25 +;! s2_ptr gr24 +;! size gr23 + +;! One might want to unroll this as for other processors, but it turns +;! out that the data cache contention after a store makes such +;! unrolling useless. We can't come under 5 cycles/limb anyway. + + .text + .export __mpn_sub_n +__mpn_sub_n: + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + + addib,= -1,%r23,L$end ;! check for (SIZE == 1) + sub %r21,%r20,%r28 ;! subtract first limbs ignoring cy + +L$loop: ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + stws,ma %r28,4(%r26) + addib,<> -1,%r23,L$loop + subb %r21,%r20,%r28 + +L$end: stws %r28,0(%r26) + addc %r0,%r0,%r28 + bv 0(%r2) + subi 1,%r28,%r28 + + .exit + .procend diff --git a/libc/sysdeps/linux/hppa/sys/procfs.h b/libc/sysdeps/linux/hppa/sys/procfs.h new file mode 100644 index 0000000..2e6d109 --- /dev/null +++ b/libc/sysdeps/linux/hppa/sys/procfs.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/hppa/sys/ucontext.h b/libc/sysdeps/linux/hppa/sys/ucontext.h new file mode 100644 index 0000000..1431143 --- /dev/null +++ b/libc/sysdeps/linux/hppa/sys/ucontext.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 80 +#define NFPREG 32 + +/* Container for all general registers. */ +typedef struct gregset + { + greg_t g_regs[32]; + greg_t sr_regs[8]; + greg_t cr_regs[24]; + greg_t g_pad[16]; + } gregset_t; + +/* Container for all FPU registers. */ +typedef struct fpregset + { + double fp_dregs[32]; + } fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/hppa/syscall.c b/libc/sysdeps/linux/hppa/syscall.c new file mode 100644 index 0000000..cd11e08 --- /dev/null +++ b/libc/sysdeps/linux/hppa/syscall.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1997, 1998, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* HPPA implements syscall() in 'C'; the assembler version would + typically be in syscall.S. Also note that we have INLINE_SYSCALL, + INTERNAL_SYSCALL, and all the generated pure assembly syscall wrappers. + How often the function is used is unknown. */ + +long int +syscall (long int __sysno, ...) +{ + /* FIXME: Keep this matching INLINE_SYSCALL for hppa */ + va_list args; + long int arg0, arg1, arg2, arg3, arg4, arg5; + long int __sys_res; + + /* Load varargs */ + va_start (args, __sysno); + arg0 = va_arg (args, long int); + arg1 = va_arg (args, long int); + arg2 = va_arg (args, long int); + arg3 = va_arg (args, long int); + arg4 = va_arg (args, long int); + arg5 = va_arg (args, long int); + va_end (args); + + { + register unsigned long int __res __asm__("r28"); + K_LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) + __asm__ __volatile__ (K_STW_ASM_PIC + " ble 0x100(%%sr2, %%r0) \n" + " copy %1, %%r20 \n" + K_LDW_ASM_PIC + : "=r" (__res) + : "r" (__sysno) K_ASM_ARGS_6 + : "memory", K_CALL_CLOB_REGS K_CLOB_ARGS_6); + __sys_res = __res; + } + if ((unsigned long int) __sys_res >= (unsigned long int) -4095) + { + __set_errno (-__sys_res); + __sys_res = -1; + } + return __sys_res; +} diff --git a/libc/sysdeps/linux/hppa/udiv_qrnnd.s b/libc/sysdeps/linux/hppa/udiv_qrnnd.s new file mode 100644 index 0000000..8e9c07a --- /dev/null +++ b/libc/sysdeps/linux/hppa/udiv_qrnnd.s @@ -0,0 +1,286 @@ +;! HP-PA __udiv_qrnnd division support, used from longlong.h. +;! This version runs fast on pre-PA7000 CPUs. + +;! Copyright (C) 1993, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP 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. + +;! The GNU MP 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 the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! rem_ptr gr26 +;! n1 gr25 +;! n0 gr24 +;! d gr23 + +;! The code size is a bit excessive. We could merge the last two ds;addc +;! sequences by simply moving the "bb,< Odd" instruction down. The only +;! trouble is the FFFFFFFF code that would need some hacking. + + .text + .export __udiv_qrnnd +__udiv_qrnnd: + .proc + .callinfo frame=0,no_calls + .entry + + comb,< %r23,%r0,L$largedivisor + sub %r0,%r23,%r1 ;! clear cy as side-effect + ds %r0,%r1,%r0 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r28 + ds %r25,%r23,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r23,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r28,%r28,%r28 + +L$largedivisor: + extru %r24,31,1,%r20 ;! r20 = n0 & 1 + bb,< %r23,31,L$odd + extru %r23,30,31,%r22 ;! r22 = d >> 1 + shd %r25,%r24,1,%r24 ;! r24 = new n0 + extru %r25,30,31,%r25 ;! r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r20,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r24,%r24,%r28 + +L$odd: addib,sv,n 1,%r22,L$FF.. ;! r22 = (d / 2 + 1) + shd %r25,%r24,1,%r24 ;! r24 = new n0 + extru %r25,30,31,%r25 ;! r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r28 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r20,%r25 +;! We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25 + add,nuv %r28,%r25,%r25 + addl %r25,%r1,%r25 + addc %r0,%r28,%r28 + sub,<< %r25,%r23,%r0 + addl %r25,%r1,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r0,%r28,%r28 + +;! This is just a special case of the code above. +;! We come here when d == 0xFFFFFFFF +L$FF..: add,uv %r25,%r24,%r24 + sub,<< %r24,%r23,%r0 + ldo 1(%r24),%r24 + stws %r24,0(%r26) + bv 0(%r2) + addc %r0,%r25,%r28 + + .exit + .procend diff --git a/libc/sysdeps/linux/i386/Makefile b/libc/sysdeps/linux/i386/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/i386/Makefile.arch b/libc/sysdeps/linux/i386/Makefile.arch new file mode 100644 index 0000000..3d338a0 --- /dev/null +++ b/libc/sysdeps/linux/i386/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c sigaction.c __syscall_error.c + +SSRC := \ + __longjmp.S vfork.S clone.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + sync_file_range.S syscall.S mmap.S mmap64.S posix_fadvise64.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/i386/__longjmp.S b/libc/sysdeps/linux/i386/__longjmp.S new file mode 100644 index 0000000..e2809c0 --- /dev/null +++ b/libc/sysdeps/linux/i386/__longjmp.S @@ -0,0 +1,42 @@ +/* longjmp for i386. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.global __longjmp +.type __longjmp,%function +__longjmp: + movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */ + movl 8(%esp), %eax /* Second argument is return value. */ + /* Save the return address now. */ + movl (JB_PC*4)(%ecx), %edx + /* Restore registers. */ + movl (JB_BX*4)(%ecx), %ebx + movl (JB_SI*4)(%ecx), %esi + movl (JB_DI*4)(%ecx), %edi + movl (JB_BP*4)(%ecx), %ebp + movl (JB_SP*4)(%ecx), %esp + /* Jump to saved PC. */ + jmp *%edx +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/i386/__syscall_error.c b/libc/sysdeps/linux/i386/__syscall_error.c new file mode 100644 index 0000000..7509d44 --- /dev/null +++ b/libc/sysdeps/linux/i386/__syscall_error.c @@ -0,0 +1,36 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ + +/* This version uses a lot of magic and relies heavily on x86 + * calling convention ... The advantage is that this is the same + * size as the previous __syscall_error() but all the .S functions + * need just one instruction. + * + * Local .S files have to set %eax to the negative errno value + * and then jump to this function. The neglected return to caller + * and return value of -1 is taken care of here so we don't have to + * worry about it in the .S functions. + * + * We have to stash the errno from %eax in a local stack var because + * __set_errno will prob call a function thus clobbering %eax on us. + */ + +#include +#include + +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int edx __asm__ ("%edx"); + __asm__ ("mov %eax, %edx\n\t" + "negl %edx"); + __set_errno (edx); + return -1; +} diff --git a/libc/sysdeps/linux/i386/bits/atomic.h b/libc/sysdeps/linux/i386/bits/atomic.h new file mode 100644 index 0000000..a20f424 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/atomic.h @@ -0,0 +1,369 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if defined __CONFIG_GENERIC_I386__ || defined __CONFIG_I386__ +# warning this file is only good for 486 or better +#endif + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "q" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +/* XXX We do not really need 64-bit compare-and-exchange. At least + not in the moment. Using it would mean causing portability + problems since not many other 32-bit architectures have support for + such an operation. So don't define any code for now. If it is + really going to be used the code below can be used on Intel Pentium + and later, but NOT on i486. */ +#if 1 +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret = *(mem); abort (); ret = (newval); ret = (oldval); }) +#else +# ifdef __PIC__ +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ ("xchgl %2, %%ebx\n\t" \ + LOCK_PREFIX "cmpxchg8b %1\n\t" \ + "xchgl %2, %%ebx" \ + : "=A" (ret), "=m" (*mem) \ + : "DS" (((unsigned long long int) (newval)) \ + & 0xffffffff), \ + "c" (((unsigned long long int) (newval)) >> 32), \ + "m" (*mem), "a" (((unsigned long long int) (oldval)) \ + & 0xffffffff), \ + "d" (((unsigned long long int) (oldval)) >> 32)); \ + ret; }) +# else +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchg8b %1" \ + : "=A" (ret), "=m" (*mem) \ + : "b" (((unsigned long long int) (newval)) \ + & 0xffffffff), \ + "c" (((unsigned long long int) (newval)) >> 32), \ + "m" (*mem), "a" (((unsigned long long int) (oldval)) \ + & 0xffffffff), \ + "d" (((unsigned long long int) (oldval)) >> 32)); \ + ret; }) +# endif +#endif + + +/* Note that we need no lock prefix. */ +#define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ ("xchgb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ ("xchgw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ ("xchgl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else \ + { \ + result = 0; \ + abort (); \ + } \ + result; }) + + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) __result; \ + __typeof (value) __addval = (value); \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddl %0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __tmpval; \ + __result = *__memp; \ + do \ + __tmpval = __result; \ + while ((__result = __arch_compare_and_exchange_val_64_acq \ + (__memp, __result + __addval, __result)) == __tmpval); \ + } \ + __result; }) + + +#define atomic_add(mem, value) \ + (void) ({ if (__builtin_constant_p (value) && (value) == 1) \ + atomic_increment (mem); \ + else if (__builtin_constant_p (value) && (value) == -1) \ + atomic_decrement (mem); \ + else if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else \ + { \ + __typeof (value) __addval = (value); \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval + __addval, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "iq" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_increment(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval + 1, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_increment_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %0; sete %b1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %0; sete %w1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_decrement(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval - 1, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_decrement_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_bit_set(mem, bit) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else \ + abort (); \ + }) + + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "btsb %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "btsw %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_delay() __asm__ ("rep; nop") diff --git a/libc/sysdeps/linux/i386/bits/byteswap.h b/libc/sysdeps/linux/i386/bits/byteswap.h new file mode 100644 index 0000000..33af208 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/byteswap.h @@ -0,0 +1,133 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +# endif +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ + && !defined __pentium4__ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# endif +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +# endif +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/i386/bits/endian.h b/libc/sysdeps/linux/i386/bits/endian.h new file mode 100644 index 0000000..54bd9d1 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/endian.h @@ -0,0 +1,7 @@ +/* i386 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/i386/bits/fcntl.h b/libc/sysdeps/linux/i386/bits/fcntl.h new file mode 100644 index 0000000..0b53b45 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/fcntl.h @@ -0,0 +1,241 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/i386/bits/fenv.h b/libc/sysdeps/linux/i386/bits/fenv.h new file mode 100644 index 0000000..ef3fcb3 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/fenv.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/libc/sysdeps/linux/i386/bits/kernel_stat.h b/libc/sysdeps/linux/i386/bits/kernel_stat.h new file mode 100644 index 0000000..20eb6d2 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/kernel_stat.h @@ -0,0 +1,60 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/i386/bits/kernel_types.h b/libc/sysdeps/linux/i386/bits/kernel_types.h new file mode 100644 index 0000000..6609dd3 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/kernel_types.h @@ -0,0 +1,48 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + +/* a hack for compiling a 32 bit user space with 64 bit + * kernel on x86_64 */ +#if !defined(__ARCH_I386_POSIX_TYPES_H) && !defined(_ASM_X86_64_POSIX_TYPES_H) +#define _ASM_X86_64_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_I386_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/i386/bits/mathdef.h b/libc/sysdeps/linux/i386/bits/mathdef.h new file mode 100644 index 0000000..ec42ed5 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/mathdef.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# if defined __FLT_EVAL_METHOD__ && __FLT_EVAL_METHOD__ == 0 +/* When using -mfpmath=sse, values are computed with the precission of the + used type. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ +# else +/* The ix87 FPUs evaluate all values in the 80 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/i386/bits/mathinline.h b/libc/sysdeps/linux/i386/bits/mathinline.h new file mode 100644 index 0000000..ca7277d --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/mathinline.h @@ -0,0 +1,755 @@ +/* Inline math functions for i387. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 +/* GCC 2.97 and up have builtins that actually can be used. */ +# if !__GNUC_PREREQ (2,97) +/* ISO C99 defines some macros to perform unordered comparisons. The + ix87 FPU supports this with special opcodes and we should use them. + These must not be inline functions since we have to be able to handle + all floating-point types. */ +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# ifdef __i686__ +/* For the PentiumPro and more recent processors we can provide + better code. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setne %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# else +/* This is the dumb, portable code for i386 and above. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; sahf; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) +# endif /* __i686__ */ +# endif /* GCC 2.97 */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +# endif +#endif + + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +#if __GNUC_PREREQ (2, 8) + +#if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__) + +/* A macro to define float, double, and long double versions of various + math functions for the ix87 FPU. FUNC is the function name (which will + be suffixed with f and l for the float and long double version, + respectively). OP is the name of the FPU operation. + We define two sets of macros. The set with the additional NP + doesn't add a prototype declaration. */ + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) \ + __inline_mathop_ (float, __CONCAT(func,f), op) \ + __inline_mathop_ (long double, __CONCAT(func,l), op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) \ + __inline_mathopNP_ (float, __CONCAT(func,f), op) \ + __inline_mathopNP_ (long double, __CONCAT(func,l), op) +#else +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) +#endif + +#define __inline_mathop_(float_type, func, op) \ + __inline_mathop_decl_ (float_type, func, op, "0" (__x)) +#define __inline_mathopNP_(float_type, func, op) \ + __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) + + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) \ + __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) \ + __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) +#else +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) +#endif + +#define __inline_mathop_decl_(float_type, func, op, params...) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathop_declNP_ (float_type, func, op, params) + +#define __inline_mathop_declNP_(float_type, func, op, params...) \ + __MATH_INLINE float_type __NTH (func (float_type __x)) \ + { \ + register float_type __result; \ + __asm__ __volatile__ (op : "=t" (__result) : params); \ + return __result; \ + } + + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, arg, code) \ + __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, arg, code) \ + __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) \ + __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +#else +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, (arg), code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, (arg), code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) +#endif + +#define __inline_mathcode_(float_type, func, arg, code) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathcodeNP_(float_type, func, arg, code) + +#define __inline_mathcodeNP_(float_type, func, arg, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg)) \ + { \ + code; \ + } + + +#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type func (float_type, float_type) __THROW; \ + __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) + +#define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ + { \ + code; \ + } + +#define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ + __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) + +#define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ + float_type arg3)) \ + { \ + code; \ + } +#endif + + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ +/* Miscellaneous functions */ + +__inline_mathcode (__sgn, __x, \ + return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0)) + +/* __FAST_MATH__ is defined by gcc -ffast-math. */ +#ifdef __FAST_MATH__ +__inline_mathcode (__pow2, __x, \ + register long double __value; \ + register long double __exponent; \ + __extension__ long long int __p = (long long int) __x; \ + if (__x == (long double) __p) \ + { \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (1.0), "u" (__x)); \ + return __value; \ + } \ + __asm__ __volatile__ \ + ("fld %%st(0)\n\t" \ + "frndint # int(x)\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x)\n\t" \ + "f2xm1 # 2^(fract(x)) - 1\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __value += 1.0; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__value), "u" (__exponent)); \ + return __value) + +# ifdef __USE_GNU +# define __sincos_code \ + register long double __cosr; \ + register long double __sinr; \ + __asm__ __volatile__ \ + ("fsincos\n\t" \ + "fnstsw %%ax\n\t" \ + "testl $0x400, %%eax\n\t" \ + "jz 1f\n\t" \ + "fldpi\n\t" \ + "fadd %%st(0)\n\t" \ + "fxch %%st(1)\n\t" \ + "2: fprem1\n\t" \ + "fnstsw %%ax\n\t" \ + "testl $0x400, %%eax\n\t" \ + "jnz 2b\n\t" \ + "fstp %%st(1)\n\t" \ + "fsincos\n\t" \ + "1:" \ + : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \ + *__sinx = __sinr; \ + *__cosx = __cosr + +__MATH_INLINE void +__NTH (__sincos (double __x, double *__sinx, double *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosf (float __x, float *__sinx, float *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) +{ + __sincos_code; +} +# endif + + +/* Optimized inline implementation, sometimes with reduced precision + and/or argument range. */ + +# if __GNUC_PREREQ (3, 5) +# define __expm1_code \ + register long double __temp; \ + __temp = __builtin_expm1l (__x); \ + return __temp ? __temp : __x +# else +# define __expm1_code \ + register long double __value; \ + register long double __exponent; \ + register long double __temp; \ + __asm__ __volatile__ \ + ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __asm__ __volatile__ \ + ("fscale # 2^int(x * log2(e))\n\t" \ + : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ + __temp -= 1.0; \ + __temp += __value; \ + return __temp ? __temp : __x +# endif +__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) + +# if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) +# else +# define __exp_code \ + register long double __value; \ + register long double __exponent; \ + __asm__ __volatile__ \ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __value += 1.0; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__value), "u" (__exponent)); \ + return __value +__inline_mathcodeNP (exp, __x, __exp_code) +__inline_mathcodeNP_ (long double, __expl, __x, __exp_code) +# endif + + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (tan, __x, \ + register long double __value; \ + register long double __value2 __attribute__ ((__unused__)); \ + __asm__ __volatile__ \ + ("fptan" \ + : "=t" (__value2), "=u" (__value) : "0" (__x)); \ + return __value) +# endif +#endif /* __FAST_MATH__ */ + + +#if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, + return __builtin_atan2l (__y, __x)) +#else +# define __atan2_code \ + register long double __value; \ + __asm__ __volatile__ \ + ("fpatan" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ + return __value +# ifdef __FAST_MATH__ +__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) +# endif +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) +#endif + + +#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (fmod, __x, __y, \ + register long double __value; \ + __asm__ __volatile__ \ + ("1: fprem\n\t" \ + "fnstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ + return __value) +#endif + + +#ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3,3) +__inline_mathopNP (sqrt, "fsqrt") +__inline_mathopNP_ (long double, __sqrtl, "fsqrt") +# define __libc_sqrtl(n) __sqrtl (n) +# else +# define __libc_sqrtl(n) __builtin_sqrtl (n) +# endif +#endif + +#if __GNUC_PREREQ (2, 8) +__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) +# if defined __USE_MISC || defined __USE_ISOC99 +__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) +__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) +# endif +__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) +#else +__inline_mathop (fabs, "fabs") +__inline_mathop_ (long double, __fabsl, "fabs") +#endif + +#ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3, 4) +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (sin, "fsin") +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (cos, "fcos") + +__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") + +__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) +__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) +# endif + +# if !__GNUC_PREREQ (3, 4) +__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") +# endif +#endif /* __FAST_MATH__ */ + +__inline_mathcode_ (long double, __sgn1l, __x, \ + __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ + { __xld: __x }; \ + __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ + __n.__xi[1] = 0x80000000; \ + __n.__xi[0] = 0; \ + return __n.__xld) + + +#ifdef __FAST_MATH__ +/* The argument range of the inline version of sinhl is slightly reduced. */ +__inline_mathcodeNP (sinh, __x, \ + register long double __exm1 = __expm1l (__fabsl (__x)); \ + return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) + +__inline_mathcodeNP (cosh, __x, \ + register long double __ex = __expl (__x); \ + return 0.5 * (__ex + 1.0 / __ex)) + +__inline_mathcodeNP (tanh, __x, \ + register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ + return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) +#endif + +__inline_mathcodeNP (floor, __x, \ + register long double __value; \ + __volatile unsigned short int __cw; \ + __volatile unsigned short int __cwtmp; \ + __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ + __asm__ __volatile__ ("frndint" : "=t" (__value) : "0" (__x)); \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cw)); \ + return __value) + +__inline_mathcodeNP (ceil, __x, \ + register long double __value; \ + __volatile unsigned short int __cw; \ + __volatile unsigned short int __cwtmp; \ + __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ + __asm__ __volatile__ ("frndint" : "=t" (__value) : "0" (__x)); \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cw)); \ + return __value) + +#ifdef __FAST_MATH__ +# define __ldexp_code \ + register long double __value; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ + return __value + +__MATH_INLINE double +__NTH (ldexp (double __x, int __y)) +{ + __ldexp_code; +} +#endif + + +/* Optimized versions for some non-standardized functions. */ +#if defined __USE_ISOC99 || defined __USE_MISC + +# ifdef __FAST_MATH__ +__inline_mathcodeNP (expm1, __x, __expm1_code) + +/* We cannot rely on M_SQRT being defined. So we do it for ourself + here. */ +# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (log1p, __x, \ + register long double __value; \ + if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ + __value = logl (1.0 + __x); \ + else \ + __asm__ __volatile__ \ + ("fldln2\n\t" \ + "fxch\n\t" \ + "fyl2xp1" \ + : "=t" (__value) : "0" (__x) : "st(1)"); \ + return __value) +# endif + + +/* The argument range of the inline version of asinhl is slightly reduced. */ +__inline_mathcodeNP (asinh, __x, \ + register long double __y = __fabsl (__x); \ + return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ + * __sgn1l (__x))) + +__inline_mathcodeNP (acosh, __x, \ + return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) + +__inline_mathcodeNP (atanh, __x, \ + register long double __y = __fabsl (__x); \ + return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) + +/* The argument range of the inline version of hypotl is slightly reduced. */ +__inline_mathcodeNP2 (hypot, __x, __y, + return __libc_sqrtl (__x * __x + __y * __y)) + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP(logb, __x, \ + register long double __value; \ + register long double __junk; \ + __asm__ __volatile__ \ + ("fxtract\n\t" \ + : "=t" (__junk), "=u" (__value) : "0" (__x)); \ + return __value) +# endif + +# endif +#endif + +#ifdef __USE_ISOC99 +# ifdef __FAST_MATH__ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +__MATH_INLINE float +__NTH (ldexpf (float __x, int __y)) +{ + __ldexp_code; +} + +__MATH_INLINE long double +__NTH (ldexpl (long double __x, int __y)) +{ + __ldexp_code; +} + +__inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z) + +__inline_mathopNP (rint, "frndint") +# endif /* __FAST_MATH__ */ + +# define __lrint_code \ + long int __lrintres; \ + __asm__ __volatile__ \ + ("fistpl %0" \ + : "=m" (__lrintres) : "t" (__x) : "st"); \ + return __lrintres +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrintl (long double __x)) +{ + __lrint_code; +} +# undef __lrint_code + +# define __llrint_code \ + long long int __llrintres; \ + __asm__ __volatile__ \ + ("fistpll %0" \ + : "=m" (__llrintres) : "t" (__x) : "st"); \ + return __llrintres +__MATH_INLINE long long int +__NTH (llrintf (float __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrint (double __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrintl (long double __x)) +{ + __llrint_code; +} +# undef __llrint_code + +#endif + + +#ifdef __USE_MISC + +# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (drem, __x, __y, \ + register double __value; \ + register int __clobbered; \ + __asm__ __volatile__ \ + ("1: fprem1\n\t" \ + "fstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ + return __value) +# endif + + +/* This function is used in the `isfinite' macro. */ +__MATH_INLINE int +__NTH (__finite (double __x)) +{ + return (__extension__ + (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] + | 0x800fffffu) + 1) >> 31)); +} + +/* Miscellaneous functions */ +# ifdef __FAST_MATH__ +__inline_mathcode (__coshm1, __x, \ + register long double __exm1 = __expm1l (__fabsl (__x)); \ + return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1) + +__inline_mathcode (__acosh1p, __x, \ + return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0))) + +# endif /* __FAST_MATH__ */ +#endif /* __USE_MISC */ + +/* Undefine some of the large macros which are not used anymore. */ +#undef __atan2_code +#ifdef __FAST_MATH__ +# undef __expm1_code +# undef __exp_code +# undef __sincos_code +#endif /* __FAST_MATH__ */ + +#endif /* __NO_MATH_INLINES */ + + +/* This code is used internally in the GNU libc. */ +#ifdef __LIBC_INTERNAL_MATH_INLINES +__inline_mathop (__ieee754_sqrt, "fsqrt") +__inline_mathcode2 (__ieee754_atan2, __y, __x, + register long double __value; + __asm__ __volatile__ ("fpatan\n\t" + : "=t" (__value) + : "0" (__x), "u" (__y) : "st(1)"); + return __value;) +#endif + +#endif /* __GNUC__ */ diff --git a/libc/sysdeps/linux/i386/bits/mman.h b/libc/sysdeps/linux/i386/bits/mman.h new file mode 100644 index 0000000..00cb982 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/mman.h @@ -0,0 +1,103 @@ +/* Definitions for POSIX memory map interface. Linux/i386 version. + Copyright (C) 1997, 2000, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/i386/bits/select.h b/libc/sysdeps/linux/i386/bits/select.h new file mode 100644 index 0000000..972bfb6 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/select.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 + +# define __FD_ZERO(fdsp) \ + do { \ + int __d0, __d1; \ + __asm__ __volatile__ ("cld; rep; stosl" \ + : "=c" (__d0), "=D" (__d1) \ + : "a" (0), "0" (sizeof (fd_set) \ + / sizeof (__fd_mask)), \ + "1" (&__FDS_BITS (fdsp)[0]) \ + : "memory"); \ + } while (0) + +# define __FD_SET(fd, fdsp) \ + __asm__ __volatile__ ("btsl %1,%0" \ + : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "r" (((int) (fd)) % __NFDBITS) \ + : "cc","memory") +# define __FD_CLR(fd, fdsp) \ + __asm__ __volatile__ ("btrl %1,%0" \ + : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "r" (((int) (fd)) % __NFDBITS) \ + : "cc","memory") +# define __FD_ISSET(fd, fdsp) \ + (__extension__ \ + ({register char __result; \ + __asm__ __volatile__ ("btl %1,%2 ; setcb %b0" \ + : "=q" (__result) \ + : "r" (((int) (fd)) % __NFDBITS), \ + "m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "cc"); \ + __result; })) + +#else /* ! GNU CC */ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +# define __FD_ZERO(set) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (set); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) +# define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) +# define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) +# define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) + +#endif /* GNU CC */ diff --git a/libc/sysdeps/linux/i386/bits/setjmp.h b/libc/sysdeps/linux/i386/bits/setjmp.h new file mode 100644 index 0000000..107fe58 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/setjmp.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. Intel 386 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#if defined __USE_MISC || defined _ASM +# define JB_BX 0 +# define JB_SI 1 +# define JB_DI 2 +# define JB_BP 3 +# define JB_SP 4 +# define JB_PC 5 +# define JB_SIZE 24 +#endif + +#ifndef _ASM +typedef int __jmp_buf[6]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/i386/bits/sigcontextinfo.h b/libc/sysdeps/linux/i386/bits/sigcontextinfo.h new file mode 100644 index 0000000..b7367ba --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/sigcontextinfo.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) ctx.eip) +#define GET_FRAME(ctx) ((void *) ctx.ebp) +#define GET_STACK(ctx) ((void *) ctx.esp_at_signal) +#define CALL_SIGHANDLER(handler, signo, ctx) \ +do { \ + int __tmp1, __tmp2, __tmp3, __tmp4; \ + __asm__ __volatile__ ("movl\t%%esp, %%edi\n\t" \ + "andl\t$-16, %%esp\n\t" \ + "subl\t%8, %%esp\n\t" \ + "movl\t%%edi, %c8-4(%%esp)\n\t" \ + "movl\t%1, 0(%%esp)\n\t" \ + "leal\t4(%%esp), %%edi\n\t" \ + "cld\n\t" \ + "rep\tmovsl\n\t" \ + "call\t*%0\n\t" \ + "cld\n\t" \ + "movl\t%9, %%ecx\n\t" \ + "subl\t%%edi, %%esi\n\t" \ + "leal\t4(%%esp,%%esi,1), %%edi\n\t" \ + "leal\t4(%%esp), %%esi\n\t" \ + "rep\tmovsl\n\t" \ + "movl\t%c8-4(%%esp), %%esp\n\t" \ + : "=a" (__tmp1), "=d" (__tmp2), "=S" (__tmp3), \ + "=c" (__tmp4) \ + : "0" (handler), "1" (signo), "2" (&ctx), \ + "3" (sizeof (struct sigcontext) / 4), \ + "n" ((sizeof (struct sigcontext) + 19) & ~15), \ + "i" (sizeof (struct sigcontext) / 4) \ + : "cc", "edi"); \ +} while (0) diff --git a/libc/sysdeps/linux/i386/bits/stackinfo.h b/libc/sysdeps/linux/i386/bits/stackinfo.h new file mode 100644 index 0000000..a9a6745 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/i386/bits/syscalls.h b/libc/sysdeps/linux/i386/bits/syscalls.h new file mode 100644 index 0000000..014539c --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/syscalls.h @@ -0,0 +1,211 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h +*/ + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +/* We need some help from the assembler to generate optimal code. We + define some macros here which later will be used. */ + +#if defined __SUPPORT_LD_DEBUG__ && defined __DOMULTI__ +#error LD debugging and DOMULTI are incompatible +#endif + +#ifdef __DOMULTI__ +__asm__ (".L__X'%ebx = 1\n\t" + ".L__X'%ecx = 2\n\t" + ".L__X'%edx = 2\n\t" + ".L__X'%eax = 3\n\t" + ".L__X'%esi = 3\n\t" + ".L__X'%edi = 3\n\t" + ".L__X'%ebp = 3\n\t" + ".L__X'%esp = 3\n\t" + ".ifndef _BITS_SYSCALLS_ASM\n\t" + ".set _BITS_SYSCALLS_ASM,1\n\t" + ".macro bpushl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "pushl %ebx\n\t" + ".else\n\t" + "xchgl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + ".macro bpopl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "popl %ebx\n\t" + ".else\n\t" + "xchgl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + ".macro bmovl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "movl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + ".endif\n\t"); +#else +__asm__ (".L__X'%ebx = 1\n\t" + ".L__X'%ecx = 2\n\t" + ".L__X'%edx = 2\n\t" + ".L__X'%eax = 3\n\t" + ".L__X'%esi = 3\n\t" + ".L__X'%edi = 3\n\t" + ".L__X'%ebp = 3\n\t" + ".L__X'%esp = 3\n\t" + ".macro bpushl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "pushl %ebx\n\t" + ".else\n\t" + "xchgl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + ".macro bpopl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "popl %ebx\n\t" + ".else\n\t" + "xchgl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + ".macro bmovl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" + "movl \\reg, %ebx\n\t" + ".endif\n\t" + ".endif\n\t" + ".endm\n\t"); +#endif + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + #define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned int _resultvar = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_resultvar, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_resultvar, )); \ + _resultvar = 0xffffffff; \ + } \ + (int) _resultvar; }) + +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + __asm__ __volatile__ ( \ + LOADARGS_##nr \ + "movl %1, %%eax\n\t" \ + "int $0x80\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ + (int) resultvar; }) + +#define LOADARGS_0 +#define LOADARGS_1 \ + "bpushl .L__X'%k2, %k2\n\t" \ + "bmovl .L__X'%k2, %k2\n\t" +#define LOADARGS_2 LOADARGS_1 +#define LOADARGS_3 LOADARGS_1 +#define LOADARGS_4 LOADARGS_1 +#define LOADARGS_5 LOADARGS_1 +#define LOADARGS_6 LOADARGS_1 "push %%ebp ; movl %7, %%ebp\n\t" + +#define RESTOREARGS_0 +#define RESTOREARGS_1 \ + "bpopl .L__X'%k2, %k2\n\t" +#define RESTOREARGS_2 RESTOREARGS_1 +#define RESTOREARGS_3 RESTOREARGS_1 +#define RESTOREARGS_4 RESTOREARGS_1 +#define RESTOREARGS_5 RESTOREARGS_1 +#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 + +#define ASMFMT_0() +#define ASMFMT_1(arg1) \ + , "acdSD" (arg1) +#define ASMFMT_2(arg1, arg2) \ + , "adSD" (arg1), "c" (arg2) +#define ASMFMT_3(arg1, arg2, arg3) \ + , "aSD" (arg1), "c" (arg2), "d" (arg3) +#define ASMFMT_4(arg1, arg2, arg3, arg4) \ + , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) +#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h b/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4730d9 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h @@ -0,0 +1,46 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "hlt" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +/* this is only an issue on i386 where linux < 2.3.25, so we just assume it works ... */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#if defined _LIBC +#define internal_function __attribute__ ((regparm (3), stdcall)) +#endif + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/i386/bits/wchar.h b/libc/sysdeps/linux/i386/bits/wchar.h new file mode 100644 index 0000000..442a462 --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/wchar.h @@ -0,0 +1,26 @@ +/* wchar_t type related definitions. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_WCHAR_H +#define _BITS_WCHAR_H 1 + +#define __WCHAR_MIN (-2147483647l - 1l) +#define __WCHAR_MAX (2147483647l) + +#endif /* bits/wchar.h */ diff --git a/libc/sysdeps/linux/i386/bits/wordsize.h b/libc/sysdeps/linux/i386/bits/wordsize.h new file mode 100644 index 0000000..7c3cd9c --- /dev/null +++ b/libc/sysdeps/linux/i386/bits/wordsize.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 + +#ifdef UCLIBC_INTERNAL +#ifndef smallint_type +#define smallint_type char +#endif +#endif diff --git a/libc/sysdeps/linux/i386/brk.c b/libc/sysdeps/linux/i386/brk.c new file mode 100644 index 0000000..eda8ad9 --- /dev/null +++ b/libc/sysdeps/linux/i386/brk.c @@ -0,0 +1,49 @@ +/* brk system call for Linux/i386. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *__unbounded newbrk, *__unbounded scratch; + + __asm__ ("movl %%ebx, %1\n" /* Save %ebx in scratch register. */ + "movl %3, %%ebx\n" /* Put ADDR in %ebx to be syscall arg. */ + "int $0x80 # %2\n" /* Perform the system call. */ + "movl %1, %%ebx\n" /* Restore %ebx from scratch register. */ + : "=a" (newbrk), "=r" (scratch) + : "0" (__NR_brk), "g" (__ptrvalue (addr))); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/i386/bsd-_setjmp.S b/libc/sysdeps/linux/i386/bsd-_setjmp.S new file mode 100644 index 0000000..f3cd6cb --- /dev/null +++ b/libc/sysdeps/linux/i386/bsd-_setjmp.S @@ -0,0 +1,46 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. i386 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#define _ASM +#define _SETJMP_H +#include + +.global _setjmp +.type _setjmp,%function +_setjmp: + xorl %eax, %eax + movl 4 (%esp), %edx + + /* Save registers. */ + movl %ebx, (JB_BX*4)(%edx) + movl %esi, (JB_SI*4)(%edx) + movl %edi, (JB_DI*4)(%edx) + leal 4 (%esp), %ecx /* Save SP as it will be after we return. */ + movl %ecx, (JB_SP*4)(%edx) + movl 0 (%esp), %ecx /* Save PC we are returning to now. */ + movl %ecx, (JB_PC*4)(%edx) + movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer. */ + + movl %eax, JB_SIZE(%edx) /* No signal mask set. */ + ret +.size _setjmp,.-_setjmp diff --git a/libc/sysdeps/linux/i386/bsd-setjmp.S b/libc/sysdeps/linux/i386/bsd-setjmp.S new file mode 100644 index 0000000..df46997 --- /dev/null +++ b/libc/sysdeps/linux/i386/bsd-setjmp.S @@ -0,0 +1,60 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. i386 version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global setjmp +.type setjmp,%function +setjmp: + movl 4 (%esp), %eax + /* Save registers. */ + movl %ebx, (0 *4)(%eax) + movl %esi, (1 *4)(%eax) + movl %edi, (2 *4)(%eax) + /* Save SP as it will be after we return. */ + leal 4 (%esp), %ecx + movl %ecx, (4 *4)(%eax) + /* Save PC we are returning to now. */ + movl 0 (%esp), %ecx + movl %ecx, (5 *4)(%eax) + /* Save caller's frame pointer. */ + movl %ebp, (3 *4)(%eax) + + /* Call __sigjmp_save. */ + pushl $1 + pushl 8(%esp) +#ifdef __PIC__ + /* We cannot use the PLT, because it requires that %ebx be set, but + we can't save and restore our caller's value. Instead, we do an + indirect jump through the GOT, using for the temporary register + %ecx, which is call-clobbered. */ + call here2 +here2: popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.-here2], %ecx + movl __sigjmp_save @GOT (%ecx), %ecx + call *%ecx +#else + call __sigjmp_save +#endif + popl %ecx + popl %edx + ret +.size setjmp,.-setjmp diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S new file mode 100644 index 0000000..14fc25c --- /dev/null +++ b/libc/sysdeps/linux/i386/clone.S @@ -0,0 +1,123 @@ +/* Copyright (C) 1996-2000,02,03,04,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu) + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. + + Hacked up for uClibc by Erik Andersen +*/ + +#define _ERRNO_H 1 +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, struct user_desc *tls, pid_t *ctid); */ + +#define LINKAGE 4 +#define PTR_SIZE 4 +#define PARMS LINKAGE /* no space for saved regs */ +#define FUNC PARMS +#define STACK FUNC+4 +#define FLAGS STACK+PTR_SIZE +#define ARG FLAGS+4 +#define PTID ARG+PTR_SIZE +#define TLS PTID+PTR_SIZE +#define CTID TLS+PTR_SIZE + +.text +.global clone +.type clone,%function +clone: + /* Sanity check arguments. */ + movl $-EINVAL,%eax + + /* no NULL function pointers */ + movl FUNC(%esp),%ecx +#ifdef __PIC__ + jecxz __error +#else + testl %ecx,%ecx + jz __error +#endif + + /* no NULL stack pointers */ + movl STACK(%esp),%ecx +#ifdef __PIC__ + jecxz __error +#else + testl %ecx,%ecx + jz __error +#endif + + /* Insert the argument onto the new stack. Make sure the new + thread is started with an alignment of (mod 16). */ + andl $0xfffffff0, %ecx + subl $28,%ecx + movl ARG(%esp),%eax /* no negative argument counts */ + movl %eax,12(%ecx) + + /* Save the function pointer as the zeroth argument. + It will be popped off in the child in the ebx frobbing below. */ + movl FUNC(%esp),%eax + movl %eax,8(%ecx) + /* Don't leak any information. */ + movl $0,4(%ecx) + movl $0,(%ecx) + + /* Do the system call */ + pushl %ebx + pushl %esi + pushl %edi + movl TLS+12(%esp),%esi + movl PTID+12(%esp),%edx + movl FLAGS+12(%esp),%ebx + movl CTID+12(%esp),%edi + movl $__NR_clone,%eax + int $0x80 + popl %edi + popl %esi + popl %ebx + + test %eax,%eax + jl __error + jz .Lthread_start + ret + +.Lthread_start: + /* Note: %esi is zero. */ + movl %esi,%ebp /* terminate the stack frame */ + call *%ebx +#ifdef __PIC__ + call .Lhere +.Lhere: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.Lhere], %ebx +#endif + movl %eax, %ebx + movl $__NR_exit, %eax + int $0x80 + +/* Need to indirect jump to syscall error + * or we end up with TEXTREL's + */ +__error: + jmp __syscall_error + +.size clone,.-clone diff --git a/libc/sysdeps/linux/i386/crt1.S b/libc/sysdeps/linux/i386/crt1.S new file mode 100644 index 0000000..a133cb9 --- /dev/null +++ b/libc/sysdeps/linux/i386/crt1.S @@ -0,0 +1,140 @@ +/* Startup code compliant to the ELF i386 ABI. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + %edx Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %esp The stack contains the arguments and environment: + 0(%esp) argc + 4(%esp) argv[0] + ... + (4*argc)(%esp) NULL + (4*(argc+1))(%esp) envp[0] + ... + NULL +*/ + +#include + +.text +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type main,%function +.type __uClibc_main,%function +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + + /* Extract the arguments as encoded on the stack and set up + the arguments for `main': argc, argv. envp will be determined + later in __libc_start_main. */ + popl %esi /* Pop the argument count. */ + movl %esp, %ecx /* argv starts just at the current stack top.*/ + + /* Before pushing the arguments align the stack to a 16-byte + (SSE needs 16-byte alignment) boundary to avoid penalties from + misaligned accesses. Thanks to Edward Seidl + for pointing this out. */ + andl $0xfffffff0, %esp + pushl %eax /* Push garbage because we allocate + 28 more bytes. */ + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushl %esp + + pushl %edx /* Push address of the shared library + termination function. */ + +#ifdef __PIC__ + /* Load PIC register. */ + call .L0 +.L0: + pop %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx + + /* Push address of our own entry points to .fini and .init. */ + pushl _fini@GOT(%ebx) + pushl _init@GOT(%ebx) + + pushl %ecx /* Push second argument: argv. */ + pushl %esi /* Push first argument: argc. */ + + pushl main@GOT(%ebx) + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + call __uClibc_main@PLT +#else + /* Push address of our own entry points to .fini and .init. */ + pushl $_fini + pushl $_init + + pushl %ecx /* Push second argument: argv. */ + pushl %esi /* Push first argument: argc. */ + + pushl $main + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + call __uClibc_main +#endif + + hlt /* Crash if somehow `exit' does return. */ +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/i386/crti.S b/libc/sysdeps/linux/i386/crti.S new file mode 100644 index 0000000..7dbaaad --- /dev/null +++ b/libc/sysdeps/linux/i386/crti.S @@ -0,0 +1,31 @@ +.section .init +.global _init +.type _init,%function +_init: + pushl %ebp + movl %esp, %ebp + pushl %ebx + call __get_pc_thunk_bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + + + +.section .fini +.global _fini +.type _fini,%function +_fini: + pushl %ebp + movl %esp, %ebp + pushl %ebx + call __get_pc_thunk_bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + + + +.section .gnu.linkonce.t.__get_pc_thunk_bx,"ax",@progbits +.global __get_pc_thunk_bx +.hidden __get_pc_thunk_bx +.type __get_pc_thunk_bx,%function +__get_pc_thunk_bx: + movl (%esp), %ebx + ret diff --git a/libc/sysdeps/linux/i386/crtn.S b/libc/sysdeps/linux/i386/crtn.S new file mode 100644 index 0000000..1912504 --- /dev/null +++ b/libc/sysdeps/linux/i386/crtn.S @@ -0,0 +1,29 @@ +.file "initfini.c" + +.section .init +.global _init +.type _init,%function + popl %ebx + popl %ebp + ret +.size _init,.-_init + + + +.section .fini +.global _fini +.type _fini,%function + popl %ebx + popl %ebp + ret +.size _fini,.-_fini + + + +.section .gnu.linkonce.t.__get_pc_thunk_bx,"ax",@progbits +.global __get_pc_thunk_bx +.hidden __get_pc_thunk_bx +.type __get_pc_thunk_bx,%function +__get_pc_thunk_bx: + movl (%esp), %ebx + ret diff --git a/libc/sysdeps/linux/i386/fpu_control.h b/libc/sysdeps/linux/i386/fpu_control.h new file mode 100644 index 0000000..c6cb005 --- /dev/null +++ b/libc/sysdeps/linux/i386/fpu_control.h @@ -0,0 +1,104 @@ +/* FPU control word bits. i387 version. + Copyright (C) 1993,1995-1998,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + +/* Here is the dirty part. Set up your 387 through the control word + * (cw) register. + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f which we use. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* libm requires double extended precision. */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x037f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x037f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); + +/* Macros for accessing the hardware control word. + + Note that the use of these macros is no sufficient anymore with + recent hardware. Some floating point operations are executed in + the SSE/SSE2 engines which have their own control and status register. */ +#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/i386/mmap.S b/libc/sysdeps/linux/i386/mmap.S new file mode 100644 index 0000000..fe7a798 --- /dev/null +++ b/libc/sysdeps/linux/i386/mmap.S @@ -0,0 +1,51 @@ +/* Copyright (C) 1995,96,97,98,99,2000,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +.text +.global mmap +.type mmap,%function +mmap: + + /* Save registers. */ + movl %ebx, %edx + + movl $__NR_mmap, %eax /* System call number in %eax. */ + + lea 4(%esp), %ebx /* Address of args is 1st arg. */ + + /* Do the system call trap. */ + int $0x80 + + /* Restore registers. */ + movl %edx, %ebx + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4096, %eax + ja __syscall_error + + /* Successful; return the syscall's value. */ + ret + +.size mmap,.-mmap + +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/i386/mmap64.S b/libc/sysdeps/linux/i386/mmap64.S new file mode 100644 index 0000000..a6b4aa0 --- /dev/null +++ b/libc/sysdeps/linux/i386/mmap64.S @@ -0,0 +1,93 @@ +/* Copyright (C) 1995,96,97,98,99,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#define _ERRNO_H 1 +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 + + +#define LINKAGE 4 +#define PTR_SIZE 4 +#define SVRSP 16 /* saved register space */ +#define PARMS LINKAGE+SVRSP /* space for 4 saved regs */ +#define ADDR PARMS +#define LEN ADDR+PTR_SIZE +#define PROT LEN+4 +#define FLAGS PROT+4 +#define FD FLAGS+4 +#define OFFLO FD+4 +#define OFFHI OFFLO+4 + +.text +.global mmap64 +.type mmap64,%function + +mmap64: + /* Save registers. */ + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + movl OFFLO(%esp), %edx + movl OFFHI(%esp), %ecx + testl $0xfff, %edx + jne L_einval + shrdl $12, %ecx, %edx /* mmap2 takes the offset in pages. */ + shrl $12, %ecx + jne L_einval + movl %edx, %ebp + + movl ADDR(%esp), %ebx + movl LEN(%esp), %ecx + movl PROT(%esp), %edx + movl FLAGS(%esp), %esi + movl FD(%esp), %edi + + movl $__NR_mmap2, %eax /* System call number in %eax. */ + /* Do the system call trap. */ + int $0x80 + + /* Restore registers. */ + popl %edi + popl %esi + popl %ebx + popl %ebp + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4095,%eax + ja __syscall_error + /* Successful; return the syscall's value. */ + ret + + /* This means the offset value is too large. */ +L_einval: + popl %edi + popl %esi + popl %ebx + popl %ebp + movl $-EINVAL, %eax + jmp __syscall_error + +.size mmap64,.-mmap64 + +#endif diff --git a/libc/sysdeps/linux/i386/posix_fadvise64.S b/libc/sysdeps/linux/i386/posix_fadvise64.S new file mode 100644 index 0000000..b99b35e --- /dev/null +++ b/libc/sysdeps/linux/i386/posix_fadvise64.S @@ -0,0 +1,100 @@ +/* Copyright (C) 1995-2000,2002,2003,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +.text +.global __libc_posix_fadvise64 +.type __libc_posix_fadvise64,%function +__libc_posix_fadvise64: +#if defined __NR_fadvise64_64 + /* Save regs */ + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + movl $__NR_fadvise64_64, %eax /* Syscall number in %eax. */ + + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl 40(%esp), %ebp + + /* Do the system call trap. */ + int $0x80 + + /* Restore regs */ + popl %edi + popl %esi + popl %ebx + popl %ebp + + /* Returns 0 on success, else an error code. */ + negl %eax + +#elif defined __NR_fadvise64 + /* Save regs */ + pushl %ebx + pushl %esi + pushl %edi +#if 0 + /* does len overflow long? */ + cmpl $0, 28(%esp) + movl $-EOVERFLOW, %eax + jne overflow +#endif + movl $__NR_fadvise64, %eax /* Syscall number in %eax. */ + + movl 16(%esp), %ebx + movl 20(%esp), %ecx + movl 24(%esp), %edx + movl 28(%esp), %esi + movl 32(%esp), %edi + + /* Do the system call trap. */ + int $0x80 +overflow: + /* Restore regs */ + popl %edi + popl %esi + popl %ebx + + /* Returns 0 on success, else an error code. */ + negl %eax + +#elif defined __UCLIBC_HAS_STUBS__ + movl $-ENOSYS, %eax + jmp __syscall_error +#endif + /* Successful; return the syscall's value. */ + ret + +.size __libc_posix_fadvise64,.-__libc_posix_fadvise64 + +libc_hidden_def(__libc_posix_fadvise64) +#if defined __UCLIBC_HAS_LFS__ && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +weak_alias(__libc_posix_fadvise64,posix_fadvise64) +#endif + diff --git a/libc/sysdeps/linux/i386/setjmp.S b/libc/sysdeps/linux/i386/setjmp.S new file mode 100644 index 0000000..20a6a0b --- /dev/null +++ b/libc/sysdeps/linux/i386/setjmp.S @@ -0,0 +1,58 @@ +/* setjmp for i386, ELF version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + + +.global __sigsetjmp +.type __sigsetjmp,%function + +__sigsetjmp: + movl 4 (%esp), %eax + /* Save registers. */ + movl %ebx, (0 *4)(%eax) + movl %esi, (1 *4)(%eax) + movl %edi, (2 *4)(%eax) + /* Save SP as it will be after we return. */ + leal 4(%esp), %ecx + movl %ecx, (4 *4)(%eax) + /* Save PC we are returning to now. */ + movl 0(%esp), %ecx + movl %ecx, (5 *4)(%eax) + /* Save caller's frame pointer. */ + movl %ebp, (3 *4)(%eax) + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + /* We cannot use the PLT, because it requires that %ebx be set, but + we can't save and restore our caller's value. Instead, we do an + indirect jump through the GOT, using for the temporary register + %ecx, which is call-clobbered. */ + call .Lhere +.Lhere: + popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.- .Lhere ], %ecx + movl __sigjmp_save @GOT (%ecx), %ecx + jmp *%ecx +#else + jmp __sigjmp_save +#endif +.size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/i386/sigaction.c b/libc/sysdeps/linux/i386/sigaction.c new file mode 100644 index 0000000..79eb6fd --- /dev/null +++ b/libc/sysdeps/linux/i386/sigaction.c @@ -0,0 +1,172 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + +#if defined __NR_rt_sigaction +/* Experimentally off - libc_hidden_proto(memcpy) */ + +extern void restore_rt (void) __asm__ ("__restore_rt") attribute_hidden; +extern void restore (void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct kernel_sigaction kact, koact; + +#ifdef SIGCANCEL + if (sig == SIGCANCEL) { + __set_errno (EINVAL); + return -1; + } +#endif + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask)); + kact.sa_flags = act->sa_flags; + + kact.sa_flags = act->sa_flags | SA_RESTORER; + kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) + ? &restore_rt : &restore); + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = __syscall_rt_sigaction(sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (oact->sa_mask)); + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + + +#else +extern void restore (void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + +#ifdef SIGCANCEL + if (sig == SIGCANCEL) { + __set_errno (EINVAL); + return -1; + } +#endif + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags | SA_RESTORER; + kact.sa_restorer = &restore; + } + + __asm__ __volatile__ ("pushl %%ebx\n" + "movl %3, %%ebx\n" + "int $0x80\n" + "popl %%ebx" + : "=a" (result), "=m" (koact) + : "0" (__NR_sigaction), "r" (sig), "m" (kact), + "c" (act ? __ptrvalue (&kact) : 0), + "d" (oact ? __ptrvalue (&koact) : 0)); + + if (result < 0) { + __set_errno(-result); + return -1; + } + + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + +#endif + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + + + + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore and __restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2 (name, syscall) +#define RESTORE2(name, syscall) \ +__asm__ \ + ( \ + ".text\n" \ + "__" #name ":\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80" \ + ); + +#ifdef __NR_rt_sigaction +/* The return code for realtime-signals. */ +RESTORE (restore_rt, __NR_rt_sigreturn) +#endif + +#ifdef __NR_sigreturn +/* For the boring old signals. */ +# undef RESTORE2 +# define RESTORE2(name, syscall) \ +__asm__ \ + ( \ + ".text\n" \ + "__" #name ":\n" \ + " popl %eax\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80" \ + ); + +RESTORE (restore, __NR_sigreturn) +#endif diff --git a/libc/sysdeps/linux/i386/sync_file_range.S b/libc/sysdeps/linux/i386/sync_file_range.S new file mode 100644 index 0000000..6cdaf45 --- /dev/null +++ b/libc/sysdeps/linux/i386/sync_file_range.S @@ -0,0 +1,67 @@ +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +.text +.global sync_file_range +.type sync_file_range,%function +sync_file_range: +#ifdef __NR_sync_file_range + + /* Save regs */ + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + + movl $__NR_sync_file_range, %eax /* Syscall number in %eax. */ + + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl 40(%esp), %ebp + + /* Do the system call trap. */ + int $0x80 + + /* Restore regs */ + popl %ebp + popl %edi + popl %esi + popl %ebx + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4096, %eax + ja __syscall_error +#else + movl $-ENOSYS, %eax + jmp __syscall_error +#endif + /* Successful; return the syscall's value. */ + ret + +.size sync_file_range,.-sync_file_range + +libc_hidden_def(sync_file_range) + diff --git a/libc/sysdeps/linux/i386/sys/debugreg.h b/libc/sysdeps/linux/i386/sys/debugreg.h new file mode 100644 index 0000000..c99c943 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/debugreg.h @@ -0,0 +1,91 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DEBUGREG_H +#define _SYS_DEBUGREG_H 1 + +/* Indicate the register numbers for a number of the specific + debug registers. Registers 0-3 contain the addresses we wish to trap on */ +#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ +#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ + +#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ +#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ + +/* Define a few things for the status register. We can use this to determine + which debugging register was responsible for the trap. The other bits + are either reserved or not of interest to us. */ + +#define DR_TRAP0 (0x1) /* db0 */ +#define DR_TRAP1 (0x2) /* db1 */ +#define DR_TRAP2 (0x4) /* db2 */ +#define DR_TRAP3 (0x8) /* db3 */ + +#define DR_STEP (0x4000) /* single-step */ +#define DR_SWITCH (0x8000) /* task switch */ + +/* Now define a bunch of things for manipulating the control register. + The top two bytes of the control register consist of 4 fields of 4 + bits - each field corresponds to one of the four debug registers, + and indicates what types of access we trap on, and how large the data + field is that we are looking at */ + +#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ +#define DR_CONTROL_SIZE 4 /* 4 control bits per register */ + +#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ +#define DR_RW_WRITE (0x1) +#define DR_RW_READ (0x3) + +#define DR_LEN_1 (0x0) /* Settings for data length to trap on */ +#define DR_LEN_2 (0x4) +#define DR_LEN_4 (0xC) + +/* The low byte to the control register determine which registers are + enabled. There are 4 fields of two bits. One bit is "local", meaning + that the processor will reset the bit after a task switch and the other + is global meaning that we have to explicitly reset the bit. With linux, + you can use either one, since we explicitly zero the register when we enter + kernel mode. */ + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ +#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ + +#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ +#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ + +/* The second byte to the control register has a few special things. + + On the i386, you should set the DR_LOCAL_SLOWDOWN or + DR_GLOBAL_SLOWDOWN bits if you want to know exactly which + instruction triggered the watchpoint. Setting these bits causes + the processor to run more slowly, but leaving them clear makes it + treat watchpoint hits as imprecise exceptions, so you can't + reliably determine which instruction caused the hit. + + The i486 and all later IA-32 processors ignore DR_LOCAL_SLOWDOWN + and DR_GLOBAL_SLOWDOWN. They always report the exception + precisely, except in some rare cases, which the user can't do + anything about. */ + +#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */ +#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ +#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ + +#endif /* sys/debugreg.h */ diff --git a/libc/sysdeps/linux/i386/sys/elf.h b/libc/sysdeps/linux/i386/sys/elf.h new file mode 100644 index 0000000..d959cdc --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* _SYS_ELF_H */ diff --git a/libc/sysdeps/linux/i386/sys/io.h b/libc/sysdeps/linux/i386/sys/io.h new file mode 100644 index 0000000..87b99a9 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/io.h @@ -0,0 +1,183 @@ +/* Copyright (C) 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; +#endif /* __UCLIBC_LINUX_SPECIFIC__ */ + +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outb_p (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outw (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port)); + +} + +static __inline void +outw_p (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outl (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outl_p (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +insb (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insw (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insl (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsb (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsw (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsl (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +#endif /* GNU C */ + +__END_DECLS +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/i386/sys/perm.h b/libc/sysdeps/linux/i386/sys/perm.h new file mode 100644 index 0000000..e389e66 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/perm.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PERM_H + +#define _SYS_PERM_H 1 +#include + +__BEGIN_DECLS + +/* Set port input/output permissions. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + + +/* Change I/O privilege level. */ +extern int iopl (int __level) __THROW; + +__END_DECLS + +#endif /* _SYS_PERM_H */ diff --git a/libc/sysdeps/linux/i386/sys/procfs.h b/libc/sysdeps/linux/i386/sys/procfs.h new file mode 100644 index 0000000..f0be433 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/procfs.h @@ -0,0 +1,131 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs_struct elf_fpregset_t; + +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpxregs_struct elf_fpxregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/i386/sys/reg.h b/libc/sysdeps/linux/i386/sys/reg.h new file mode 100644 index 0000000..39003c4 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/reg.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + * location of the users' stored general purpose registers. */ + +#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 + +#endif /* _SYS_REG_H */ diff --git a/libc/sysdeps/linux/i386/sys/ucontext.h b/libc/sysdeps/linux/i386/sys/ucontext.h new file mode 100644 index 0000000..d6474c7 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/ucontext.h @@ -0,0 +1,129 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 19 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_GS = 0, +# define REG_GS REG_GS + REG_FS, +# define REG_FS REG_FS + REG_ES, +# define REG_ES REG_ES + REG_DS, +# define REG_DS REG_DS + REG_EDI, +# define REG_EDI REG_EDI + REG_ESI, +# define REG_ESI REG_ESI + REG_EBP, +# define REG_EBP REG_EBP + REG_ESP, +# define REG_ESP REG_ESP + REG_EBX, +# define REG_EBX REG_EBX + REG_EDX, +# define REG_EDX REG_EDX + REG_ECX, +# define REG_ECX REG_ECX + REG_EAX, +# define REG_EAX REG_EAX + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_ERR, +# define REG_ERR REG_ERR + REG_EIP, +# define REG_EIP REG_EIP + REG_CS, +# define REG_CS REG_CS + REG_EFL, +# define REG_EFL REG_EFL + REG_UESP, +# define REG_UESP REG_UESP + REG_SS +# define REG_SS REG_SS +}; +#endif + +/* Definitions taken from the kernel headers. */ +struct _libc_fpreg +{ + unsigned short int significand[4]; + unsigned short int exponent; +}; + +struct _libc_fpstate +{ + unsigned long int cw; + unsigned long int sw; + unsigned long int tag; + unsigned long int ipoff; + unsigned long int cssel; + unsigned long int dataoff; + unsigned long int datasel; + struct _libc_fpreg _st[8]; + unsigned long int status; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Due to Linux's history we have to use a pointer here. The SysV/i386 + ABI requires a struct with the values. */ + fpregset_t fpregs; + unsigned long int oldmask; + unsigned long int cr2; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/i386/sys/user.h b/libc/sysdeps/linux/i386/sys/user.h new file mode 100644 index 0000000..c5cfff2 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/user.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +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]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + 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]; +}; + +#include +#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) + +#endif /* _SYS_USER_H */ diff --git a/libc/sysdeps/linux/i386/sys/vm86.h b/libc/sysdeps/linux/i386/sys/vm86.h new file mode 100644 index 0000000..8faeed7 --- /dev/null +++ b/libc/sysdeps/linux/i386/sys/vm86.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_VM86_H + +#define _SYS_VM86_H 1 +#include + +/* Get constants and data types from kernel header file. */ +#include + +__BEGIN_DECLS + +/* Enter virtual 8086 mode. */ +extern int vm86 (struct vm86_struct *__info) __THROW; + +__END_DECLS + +#endif /* _SYS_VM86_H */ diff --git a/libc/sysdeps/linux/i386/syscall.S b/libc/sysdeps/linux/i386/syscall.S new file mode 100644 index 0000000..b9f65fe --- /dev/null +++ b/libc/sysdeps/linux/i386/syscall.S @@ -0,0 +1,50 @@ +/* + * June 27, 2001 Manuel Novoa III + * + * This is a heavily modified version of gcc's output for the _syscall5 macro. + * The idea (originally from dietlibc) is that all syscall functions simply set + * the syscall number as the first argument, then set the syscall arguments as + * the next up-to-five arguments, and then jump here. All the common work is + * done by syscall(), saving a fair amount of generated code when a number of + * syscalls are used. The (potential) cost is some unnecessary pushes, pops, + * and movs but the execution time penalty should be relatively small compared + * to the cost of the syscall itself. + * + * July 24, 2002 + * + * Modified by Erik Andersen to take all function parameters from off the stack + * like a proper function and eliminates the old 255 syscall number limit. So + * now we can just call this as a function as syscall() per the function + * prototype in unistd.h, so to call _exit(42) you can just call. + * syscall(__NR_exit, 42); + * and things will just work. + */ + +.text +.global syscall +.type syscall,%function +syscall: + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + + movl 44(%esp),%ebp /* Load the 6 syscall argument registers */ + movl 40(%esp),%edi + movl 36(%esp),%esi + movl 32(%esp),%edx + movl 28(%esp),%ecx + movl 24(%esp),%ebx + movl 20(%esp),%eax /* Load syscall number into %eax. */ + int $0x80 + + popl %ebx + popl %esi + popl %edi + popl %ebp + + cmpl $-4095,%eax + jae __syscall_error + ret /* Return to caller. */ + +.size syscall,.-syscall diff --git a/libc/sysdeps/linux/i386/vfork.S b/libc/sysdeps/linux/i386/vfork.S new file mode 100644 index 0000000..8005ff1 --- /dev/null +++ b/libc/sysdeps/linux/i386/vfork.S @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function + +__vfork: + popl %ecx + movl $__NR_vfork,%eax + int $0x80 + pushl %ecx + cmpl $-4095,%eax + jae __syscall_error + ret + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/i960/AUTHORS b/libc/sysdeps/linux/i960/AUTHORS new file mode 100644 index 0000000..0d65549 --- /dev/null +++ b/libc/sysdeps/linux/i960/AUTHORS @@ -0,0 +1,4 @@ +The initial support (inspired by what was done in an old i960 port of uC-libc): + +Martin Proulx +http://www.okiok.com diff --git a/libc/sysdeps/linux/i960/Makefile b/libc/sysdeps/linux/i960/Makefile new file mode 100644 index 0000000..d6ae358 --- /dev/null +++ b/libc/sysdeps/linux/i960/Makefile @@ -0,0 +1,55 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := clone.S _mmap.S setjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +OBJS := $(SOBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/i960/README b/libc/sysdeps/linux/i960/README new file mode 100644 index 0000000..7516735 --- /dev/null +++ b/libc/sysdeps/linux/i960/README @@ -0,0 +1,71 @@ +Overview +--------------------------------------------------------------------------- + +This is the README file for the i960 support in uClibc. + +This has been tested with gcc 2.95.3 and i960-intel-coff target. + +There is no support at all to compile with the intel CTOOLS, as this would +have required too many changes to uClibc. So you won't see any support +in the asm files for position independent data or code. + +Quirks needed +--------------------------------------------------------------------------- + +prepended underscore +-------------------- + +As the i960 compiler prepends an underscore to symbols, it is critical that +Rules.mak defines SYMBOL_PREFIX as _, such that -D__UCLIBC_UNDERSCORES__ +is added to CFLAGS to make sure that underscores are applied to symbol +names when needed. + + +__va_copy in va-i960.h +---------------------- + +When compiled with gcc-2.95, the __va_copy macro in va-i960.h seems to be broken +and it has to be modified in order for uClibc to compile correctly. + +Change: + +#define __va_copy(dest, src) (dest) = (src) + +To: + +#define __va_copy(dest, src) dest[0] = src[0]; dest[1] = src[1] + + +gcc integration +--------------------------------------------------------------------------- + +I've preferred modifying the specs file so that the i960-intel-coff compiler +directly compiles with uClibc. + +First, compile and install the standard i960-intel-coff compiler, which is meant +to be used with newlib. + +Then, compile uClibc, installing over the newlib include files and libraries. + +Update the specs file with the included specs.uclinux.gcc-2.95.i960-intel-coff + +This specs file always build relocatable objects, which has the disadvantage +of not letting you know if the link is missing any symbols. + +coff2flt +--------------------------------------------------------------------------- + +In order to run the executables under uClinux, fully relocatable binaries +need to be built using coff2flt. + +We have built a working coff2flt that works with the i960 and the current version +of binfmt_flat with uClinux. + +Contact Martin Proulx for further informations. + + + + + +Check: + _mmap.S: besoin??? diff --git a/libc/sysdeps/linux/i960/bits/endian.h b/libc/sysdeps/linux/i960/bits/endian.h new file mode 100644 index 0000000..e2b1316 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/endian.h @@ -0,0 +1,15 @@ +/* This file should define __BYTE_ORDER as appropriate for the machine + in question. See string/endian.h for how to define it. + + If only the stub bits/endian.h applies to a particular configuration, + bytesex.h is generated by running a program on the host machine. + So if cross-compiling to a machine with a different byte order, + the bits/endian.h file for that machine must exist. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN + + diff --git a/libc/sysdeps/linux/i960/bits/fcntl.h b/libc/sysdeps/linux/i960/bits/fcntl.h new file mode 100644 index 0000000..a8efa57 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/fcntl.h @@ -0,0 +1,234 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/i960/bits/mman.h b/libc/sysdeps/linux/i960/bits/mman.h new file mode 100644 index 0000000..48f46c2 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/mman.h @@ -0,0 +1,94 @@ +/* Definitions for POSIX memory map interface. Linux/i960 version. + Copyright (C) 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/i960/bits/setjmp.h b/libc/sysdeps/linux/i960/bits/setjmp.h new file mode 100644 index 0000000..f90e4ce --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/setjmp.h @@ -0,0 +1,38 @@ +/* Define the machine-dependent type `jmp_buf'. i960 version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* + * assume that every single local and global register + * must be saved. + * + * ___SAVEREGS is the number of quads to save. + * + * Using the structure will guarantee quad-word alignment for the + * jmp_buf type. + */ + +#define ___SAVEREGS 8 + +typedef struct __jmp_buf__ { + long _q0; + long _q1; + long _q2; + long _q3; +} __attribute__ ((aligned (16))) __jmp_buf[___SAVEREGS] ; + +/* I have not yet figured out what this should be for the i960... */ + +#if 0 +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) +#endif + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/i960/bits/syscalls.h b/libc/sysdeps/linux/i960/bits/syscalls.h new file mode 100644 index 0000000..b218513 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/syscalls.h @@ -0,0 +1,15 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Do something very evil for now. Until we create our own syscall + * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ +#warning "fixme -- add arch specific syscall macros.h" +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h b/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h new file mode 100644 index 0000000..cd6bcd9 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/i960/bits/wordsize.h b/libc/sysdeps/linux/i960/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/i960/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/i960/clone.S b/libc/sysdeps/linux/i960/clone.S new file mode 100644 index 0000000..f602fba --- /dev/null +++ b/libc/sysdeps/linux/i960/clone.S @@ -0,0 +1,62 @@ +# +# clone.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). +# + +#include +#include + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .globl clone +clone: + /* set up new stack image in regs r4-r7; argument will be in r3 in child. */ + ldconst 0, r4 /* pfp == 0 */ + addo 16, g1, r5 /* sp == newfp + 16 */ + mov g0, r6 /* rip == fnc */ + mov g2, r7 + stq r4, (g1) + + addo sp, 4, sp + st g10, -4(sp) + mov sp, g10 + ldconst __NR_clone, g13 + calls 0 + + /* Do the system call */ + cmpibg 0, g0, __syscall_error /* if < 0, error */ + be thread_start /* if == 0, we're the child */ + ret /* we're the parent */ + +__syscall_error: + not g0, r3 + callx ___errno_location + st r3, (g0) + ret + +thread_start: + # our new pfp is in g1; here we go + flushreg + mov g1, pfp + flushreg + ret diff --git a/libc/sysdeps/linux/i960/crt0.S b/libc/sysdeps/linux/i960/crt0.S new file mode 100644 index 0000000..b167ad7 --- /dev/null +++ b/libc/sysdeps/linux/i960/crt0.S @@ -0,0 +1,58 @@ +# +# crt0.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +/* + * + * The behavior in this file is tightly coupled with how the linux kernel sets things up + * on the stack before calling us. + * + * Currently fs/binfmt_flat.c (for STACK_GROWS_UP) and arch/i960/kernel/process.c + * build things so that a pointer to argc is left in g13 by start_thread(). + * + * ^ + * | <- sp somewhere around here, after being aligned. + * | + * |envp -> envp[0] + * |argv -> argv[0] + * |argc <- g13 + * + * A complete picture of how things are set up can be seen in the comments of + * create_flat_tables_stack_grows_up in fs/binfmt_flat.c + * + * I believe having to use this register could probably be avoided. + * + */ + + .globl start +start: + mov g13, r3 + ldt (r3), g0 + callx ___uClibc_main + +/* We might want to add some instruction so that it crashes if main returns */ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/i960/mmap.S b/libc/sysdeps/linux/i960/mmap.S new file mode 100644 index 0000000..bc42679 --- /dev/null +++ b/libc/sysdeps/linux/i960/mmap.S @@ -0,0 +1,52 @@ +# +# __mmap.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). +# + +#include + +/* This is a plain system call. The 6 arguments are already set up correctly */ +/* void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) */ + + + .globl _mmap +_mmap: + mov g13, r3 + ldconst __NR_mmap, g13 + calls 0 + mov r3, g13 + + /* We now need to check if the return value is a small negative integer. */ + /* This is somewhat tricky as the return code (normally an address) is an */ + /* unsigned type, or an ordinal in i960 assembler. */ + /* We'll use the fact that, integers from -256 to -1 are ordinals 0xFFFFFF00 to 0xFFFFFFFF. */ + /* So by checking that the return address is in the top range of the ordinals, we'll */ + /* in fact be checking if it's not an encoded negated erro code. */ + + /* The range -256 to -1 should be enough since that in uClinux 2.0.39, there are */ + /* 124 system calls for the i960. */ + + ldconst 0xFFFFFF00, r3 /* This is the integer's -256 representation */ + cmpobl g0, r3, 1f /* Something smaller than this means it's out of the range, and a valid address */ + subi g0, 0, r3 /* If it's an errno, save its negated (now positive) value in _errno. */ + st r3, _errno + subi 1, 0, g0 /* And return -1. */ +1: + ret diff --git a/libc/sysdeps/linux/i960/setjmp.S b/libc/sysdeps/linux/i960/setjmp.S new file mode 100644 index 0000000..2133ef5 --- /dev/null +++ b/libc/sysdeps/linux/i960/setjmp.S @@ -0,0 +1,124 @@ +/******************************************************************************* + * + * Copyright (c) 1993 Intel Corporation + * + * Intel hereby grants you permission to copy, modify, and distribute this + * software and its documentation. Intel grants this permission provided + * that the above copyright notice appears in all copies and that both the + * copyright notice and this permission notice appear in supporting + * documentation. In addition, Intel grants this permission provided that + * you prominently mark as "not part of the original" any modifications + * made to this software or documentation, and that the name of Intel + * Corporation not be used in advertising or publicity pertaining to + * distribution of the software or the documentation without specific, + * written prior permission. + * + * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR + * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY + * OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or + * representations regarding the use of, or the results of the use of, + * the software and documentation in terms of correctness, accuracy, + * reliability, currentness, or otherwise; and you rely on the software, + * documentation and results solely at your own risk. + * + * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, + * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES + * OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM + * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + * + ******************************************************************************/ + +/*************************************************************************** + * + * Modified from the original in order to fit with + * uClibc's setjmp, _setjmp, __sigsetjmp and ___sigjmp_save. + * + * + * int setjmp (jmp_buf __env) is the BSD style setjmp function. + * It simply calls __sigsetjmp(env, 1) + * + * int _setjmp (jmp_buf __env) is the posix style setjmp function. + * It simply calls __sigsetjmp(env, 0) + * This is the one normally used. + * + ***************************************************************************/ + + .text + .align 4 + .globl _setjmp + .globl __setjmp + +_setjmp: + mov 1, g1 /* __sigsetjmp(env, 1) */ + bx __sigsetjmp + +__setjmp: + mov 0, g1 /* __sigsetjmp(env, 0) */ + bx __sigsetjmp + + +/******************************************************************************/ +/* */ +/* setjmp(), longjmp() */ +/* */ +/******************************************************************************/ + .file "setjmp.S" + .text + /* .link_pix */ + + .align 4 + .globl __sigsetjmp +__sigsetjmp: + flushreg + andnot 0xf,pfp,g2 /* get pfp, mask out return status bits */ + st g2, 0x58(g0) /* save fp of caller*/ + /* save globals not killed by the calling convention */ + stq g8, 0x40(g0) /* save g8-g11*/ + st g12, 0x50(g0) /* save g12*/ + st g14, 0x54(g0) /* save g14*/ + /* save previous frame local registers */ + ldq (g2), g4 /* get previous frame pfp, sp, rip, r3 */ + stq g4, (g0) /* save pfp, sp, rip, r3 */ + ldq 0x10(g2), g4 /* get previous frame r4-r7 */ + stq g4, 0x10(g0) /* save r4-r7 */ + ldq 0x20(g2), g4 /* get previous frame r8-r11 */ + stq g4, 0x20(g0) /* save r8-r11 */ + ldq 0x30(g2), g4 /* get previous frame r12-r15 */ + stq g4, 0x30(g0) /* save r12-r15 */ + + bx ___sigjmp_save + + /* + * fake a return to the place that called the corresponding __sigsetjmp + */ + .align 4 + .globl ___longjmp +___longjmp: + call 0f /* ensure there is at least one stack frame */ + +0: + flushreg /* do this before swapping stack */ + ld 0x58(g0), pfp /* get fp of caller of setjmp */ + /* restore local registers + * the following code modifies the frame of the function which originally + * called setjmp. + */ + ldq (g0), g4 /* get pfp, sp, rip, r3 */ + stq g4, (pfp) /* restore pfp, sp, rip, r3 */ + ldq 0x10(g0), g4 /* get r4-r7 */ + stq g4, 0x10(pfp) /* restore r4-r7 */ + ldq 0x20(g0), g4 /* get r8-r11 */ + stq g4, 0x20(pfp) /* restore r8-r11 */ + ldq 0x30(g0), g4 /* get r12-r15 */ + stq g4, 0x30(pfp) /* restore r12-r15 */ + /* restore global registers */ + ldq 0x40(g0), g8 /* get old g8-g11 values */ + ld 0x50(g0), g12 /* get old g12 value */ + ld 0x54(g0), g14 /* get old g14 value */ + + mov g1, g0 /* get return value */ + cmpo g0, 0 /* make sure it is not zero */ + bne 0f + mov 1, g0 /* return 1 by default */ +0: + ret /* return to caller of __sigsetjmp */ diff --git a/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff b/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff new file mode 100644 index 0000000..cefd853 --- /dev/null +++ b/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff @@ -0,0 +1,64 @@ +*asm: +%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB} %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF} %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX} %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-AKB}}}}}}}}}}}} %{mlink-relax:-linkrelax} + +*asm_final: + + +*cpp: +%{mic*:-D__i960 %{mka:-D__i960KA}%{mkb:-D__i960KB} %{mja:-D__i960JA}%{mjd:-D__i960JD}%{mjf:-D__i960JF} %{mrp:-D__i960RP} %{msa:-D__i960SA}%{msb:-D__i960SB} %{mmc:-D__i960MC} %{mca:-D__i960CA}%{mcc:-D__i960CC} %{mcf:-D__i960CF}} %{mka:-D__i960KA__ -D__i960_KA__} %{mkb:-D__i960KB__ -D__i960_KB__} %{msa:-D__i960SA__ -D__i960_SA__} %{msb:-D__i960SB__ -D__i960_SB__} %{mmc:-D__i960MC__ -D__i960_MC__} %{mca:-D__i960CA__ -D__i960_CA__} %{mcc:-D__i960CC__ -D__i960_CC__} %{mcf:-D__i960CF__ -D__i960_CF__} %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca: %{!mcc:%{!mcf:-D__i960_KB -D__i960KB__ %{mic*:-D__i960KB}}}}}}}}} %{mlong-double-64:-D__LONG_DOUBLE_64__} + +*cc1: +%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-mka}}}}}}}}}}}} %{!gs*:%{!gc*:%{mbout:%{g*:-gstabs}} %{mcoff:%{g*:-gcoff}} %{!mbout:%{!mcoff:%{g*:-gstabs}}}}} + +*cc1plus: + + +*endfile: +crtn.o%s + +*link: +%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB} %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF} %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX} %{mbout:-Fbout}%{mcoff:-Fcoff} %{mlink-relax:-relax} -r -d + +*lib: +-lc -lgcc + +*libgcc: + + +*startfile: +%{!shared:%{pg:pgcrt0%O%s}%{!pg:%{p:pcrt0%O%s}%{!p:crt0%O%s}}} crti.o%s + +*switches_need_spaces: + + +*signed_char: +%{!fsigned-char:%{!mic*:-D__CHAR_UNSIGNED__}} + +*predefines: +-Di960 -Di80960 -DI960 -DI80960 -Acpu(i960) -Amachine(i960) -Dunix -Dlinux -Asystem(posix) -D__linux__ -D__uClinux__ -DEMBED + +*cross_compile: +1 + +*version: +2.95.3 + +*multilib: +. !mnumerics !msoft-float !mlong-double-64;float mnumerics !msoft-float !mlong-double-64;soft-float !mnumerics msoft-float !mlong-double-64;ld64 !mnumerics !msoft-float mlong-double-64;float/ld64 mnumerics !msoft-float mlong-double-64;soft-float/ld64 !mnumerics msoft-float mlong-double-64; + +*multilib_defaults: +mnumerics + +*multilib_extra: + + +*multilib_matches: +msb mnumerics;msc mnumerics;mkb mnumerics;mkc mnumerics;mmc mnumerics;mcb mnumerics;mcc mnumerics;mjf mnumerics;msa msoft-float;mka msoft-float;mca msoft-float;mcf msoft-float;mnumerics mnumerics;msoft-float msoft-float;mlong-double-64 mlong-double-64; + +*linker: +collect2 + +*link_command: +%{!fsyntax-only: %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}} %{static:} %{L*} %D %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}} %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} + }}}}}} + diff --git a/libc/sysdeps/linux/i960/sys/procfs.h b/libc/sysdeps/linux/i960/sys/procfs.h new file mode 100644 index 0000000..27abf8e --- /dev/null +++ b/libc/sysdeps/linux/i960/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/i960/sys/ucontext.h b/libc/sysdeps/linux/i960/sys/ucontext.h new file mode 100644 index 0000000..8c55ea4 --- /dev/null +++ b/libc/sysdeps/linux/i960/sys/ucontext.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 32 /* 16 global and 16 local */ + +/* Container for all general registers. */ +/* gregset_t must be an array. The below declared array corresponds to: +typedef struct gregset { + greg_t g_regs[32]; + greg_t g_hi; + greg_t g_lo; + greg_t g_pad[3]; +} gregset_t; */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + /* No floating point registers on most i960 */ + + /* Otherwise, signal the missing implementation */ +#if defined(__i960SB) || defined(__i960KB) +#error Floating point support is not yet implemented for the i960 platform. +#endif +} fpregset_t; + + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/i960/vfork.S b/libc/sysdeps/linux/i960/vfork.S new file mode 100644 index 0000000..1646e1b --- /dev/null +++ b/libc/sysdeps/linux/i960/vfork.S @@ -0,0 +1,33 @@ +/* + * clone.S, part of the i960 support for the uClibc library. + * + * Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). + */ + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + + .globl ___vfork + .hidden ___vfork +___vfork: + mov g13, r3 + ldconst __NR_vfork, g13 + calls 0 + mov r3, g13 + cmpible 0, g0, 1f + subo g0, 0, r3 + st r3, _errno +1: + ret + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/ia64/Makefile b/libc/sysdeps/linux/ia64/Makefile new file mode 100644 index 0000000..b1bf1ef --- /dev/null +++ b/libc/sysdeps/linux/ia64/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +TOPDIR=../../../../ + +top_srcdir=$(TOPDIR) +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/ia64/Makefile.arch b/libc/sysdeps/linux/ia64/Makefile.arch new file mode 100644 index 0000000..2b32124 --- /dev/null +++ b/libc/sysdeps/linux/ia64/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c + +SSRC := \ + __longjmp.S brk.S bsd-setjmp.S bsd-_setjmp.S clone2.S fork.S \ + pipe.S setjmp.S syscall.S vfork.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/ia64/__longjmp.S b/libc/sysdeps/linux/ia64/__longjmp.S new file mode 100644 index 0000000..85fe936 --- /dev/null +++ b/libc/sysdeps/linux/ia64/__longjmp.S @@ -0,0 +1,162 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Note that __sigsetjmp() did NOT flush the register stack. Instead, + we do it here since __longjmp() is usually much less frequently + invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp() + didn't (and wouldn't be able to) save ar.rnat either. This is a problem + because if we're not careful, we could end up loading random NaT bits. + There are two cases: + + (i) ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ar.rnat contains the desired bits---preserve ar.rnat + across loadrs and write to ar.bspstore + + (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp) + The desired ar.rnat is stored in + ia64_rse_rnat_addr(jmpbuf.ar_bsp). Load those + bits into ar.rnat after setting ar.bspstore. */ + +#include "sysdep.h" +#include + +# define pPos p6 /* is rotate count positive? */ +# define pNeg p7 /* is rotate count negative? */ + + + /* __longjmp(__jmp_buf buf, int val) */ + +LEAF(__longjmp) + alloc r8=ar.pfs,2,1,0,0 + mov r27=ar.rsc + add r2=0x98,in0 /* r2 <- &jmpbuf.orig_jmp_buf_addr */ + ;; + ld8 r8=[r2],-16 /* r8 <- orig_jmp_buf_addr */ + mov r10=ar.bsp + and r11=~0x3,r27 /* clear ar.rsc.mode */ + ;; + flushrs /* flush dirty regs to backing store (must be first in insn grp) */ + ld8 r23=[r2],8 /* r23 <- jmpbuf.ar_bsp */ + sub r8=r8,in0 /* r8 <- &orig_jmpbuf - &jmpbuf */ + ;; + ld8 r25=[r2] /* r25 <- jmpbuf.ar_unat */ + extr.u r8=r8,3,6 /* r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f */ + ;; + cmp.lt pNeg,pPos=r8,r0 + mov r2=in0 + ;; +(pPos) mov r16=r8 +(pNeg) add r16=64,r8 +(pPos) sub r17=64,r8 +(pNeg) sub r17=r0,r8 + ;; + mov ar.rsc=r11 /* put RSE in enforced lazy mode */ + shr.u r8=r25,r16 + add r3=8,in0 /* r3 <- &jmpbuf.r1 */ + shl r9=r25,r17 + ;; + or r25=r8,r9 + ;; + mov r26=ar.rnat + mov ar.unat=r25 /* setup ar.unat (NaT bits for r1, r4-r7, and r12) */ + ;; + ld8.fill.nta sp=[r2],16 /* r12 (sp) */ + ld8.fill.nta gp=[r3],16 /* r1 (gp) */ + dep r11=-1,r23,3,6 /* r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) */ + ;; + ld8.nta r16=[r2],16 /* caller's unat */ + ld8.nta r17=[r3],16 /* fpsr */ + ;; + ld8.fill.nta r4=[r2],16 /* r4 */ + ld8.fill.nta r5=[r3],16 /* r5 (gp) */ + cmp.geu p8,p0=r10,r11 /* p8 <- (ar.bsp >= jmpbuf.ar_bsp) */ + ;; + ld8.fill.nta r6=[r2],16 /* r6 */ + ld8.fill.nta r7=[r3],16 /* r7 */ + ;; + mov ar.unat=r16 /* restore caller's unat */ + mov ar.fpsr=r17 /* restore fpsr */ + ;; + ld8.nta r16=[r2],16 /* b0 */ + ld8.nta r17=[r3],16 /* b1 */ + ;; +(p8) ld8 r26=[r11] /* r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp) */ + mov ar.bspstore=r23 /* restore ar.bspstore */ + ;; + ld8.nta r18=[r2],16 /* b2 */ + ld8.nta r19=[r3],16 /* b3 */ + ;; + ld8.nta r20=[r2],16 /* b4 */ + ld8.nta r21=[r3],16 /* b5 */ + ;; + ld8.nta r11=[r2],16 /* ar.pfs */ + ld8.nta r22=[r3],56 /* ar.lc */ + ;; + ld8.nta r24=[r2],32 /* pr */ + mov b0=r16 + ;; + ldf.fill.nta f2=[r2],32 + ldf.fill.nta f3=[r3],32 + mov b1=r17 + ;; + ldf.fill.nta f4=[r2],32 + ldf.fill.nta f5=[r3],32 + mov b2=r18 + ;; + ldf.fill.nta f16=[r2],32 + ldf.fill.nta f17=[r3],32 + mov b3=r19 + ;; + ldf.fill.nta f18=[r2],32 + ldf.fill.nta f19=[r3],32 + mov b4=r20 + ;; + ldf.fill.nta f20=[r2],32 + ldf.fill.nta f21=[r3],32 + mov b5=r21 + ;; + ldf.fill.nta f22=[r2],32 + ldf.fill.nta f23=[r3],32 + mov ar.lc=r22 + ;; + ldf.fill.nta f24=[r2],32 + ldf.fill.nta f25=[r3],32 + cmp.eq p8,p9=0,in1 + ;; + ldf.fill.nta f26=[r2],32 + ldf.fill.nta f27=[r3],32 + mov ar.pfs=r11 + ;; + ldf.fill.nta f28=[r2],32 + ldf.fill.nta f29=[r3],32 + ;; + ldf.fill.nta f30=[r2] + ldf.fill.nta f31=[r3] +(p8) mov r8=1 + + mov ar.rnat=r26 /* restore ar.rnat */ + ;; + mov ar.rsc=r27 /* restore ar.rsc */ +(p9) mov r8=in1 + + invala /* virt. -> phys. regnum mapping may change */ + mov pr=r24,-1 + ret +END(__longjmp) + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/ia64/__syscall_error.c b/libc/sysdeps/linux/ia64/__syscall_error.c new file mode 100644 index 0000000..0727b2b --- /dev/null +++ b/libc/sysdeps/linux/ia64/__syscall_error.c @@ -0,0 +1,19 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__("%r8"); + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/ia64/bits/atomic.h b/libc/sysdeps/linux/ia64/bits/atomic.h new file mode 100644 index 0000000..1020c2f --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/atomic.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ + (!__sync_bool_compare_and_swap ((mem), (int) (long) (oldval), \ + (int) (long) (newval))) + +#define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ + (!__sync_bool_compare_and_swap ((mem), (long) (oldval), \ + (long) (newval))) + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap ((mem), (int) (long) (oldval), \ + (int) (long) (newval)) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap ((mem), (long) (oldval), (long) (newval)) + +/* Atomically store newval and return the old value. */ +#define atomic_exchange_acq(mem, value) \ + __sync_lock_test_and_set (mem, value) + +#define atomic_exchange_rel(mem, value) \ + (__sync_synchronize (), __sync_lock_test_and_set (mem, value)) + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) __result; \ + __result = __sync_fetch_and_add ((mem), (int) (value)); \ + __result; }) + +#define atomic_decrement_if_positive(mem) \ + ({ __typeof (*mem) __oldval, __val; \ + __typeof (mem) __memp = (mem); \ + \ + __val = (*__memp); \ + do \ + { \ + __oldval = __val; \ + if (__builtin_expect (__val <= 0, 0)) \ + break; \ + __val = atomic_compare_and_exchange_val_acq (__memp, __oldval - 1, \ + __oldval); \ + } \ + while (__builtin_expect (__val != __oldval, 0)); \ + __oldval; }) + +#define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*mem) __oldval, __val; \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __mask = ((__typeof (*mem)) 1 << (bit)); \ + \ + __val = (*__memp); \ + do \ + { \ + __oldval = __val; \ + __val = atomic_compare_and_exchange_val_acq (__memp, \ + __oldval | __mask, \ + __oldval); \ + } \ + while (__builtin_expect (__val != __oldval, 0)); \ + __oldval & __mask; }) + +#define atomic_full_barrier() __sync_synchronize () diff --git a/libc/sysdeps/linux/ia64/bits/byteswap.h b/libc/sysdeps/linux/ia64/bits/byteswap.h new file mode 100644 index 0000000..6862aa0 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/byteswap.h @@ -0,0 +1,110 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 48 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned short int) (__x))); \ + __v; })) +#else +/* This is better than nothing. */ +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ __volatile__ ("shl %0 = %1, 32 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned int) (__x))); \ + __v; })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + + +/* Swap bytes in 64 bit value. */ +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ul) >> 56) \ + | (((x) & 0x00ff000000000000ul) >> 40) \ + | (((x) & 0x0000ff0000000000ul) >> 24) \ + | (((x) & 0x000000ff00000000ul) >> 8) \ + | (((x) & 0x00000000ff000000ul) << 8) \ + | (((x) & 0x0000000000ff0000ul) << 24) \ + | (((x) & 0x000000000000ff00ul) << 40) \ + | (((x) & 0x00000000000000fful) << 56)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_64(x) \ + (__extension__ \ + ({ register unsigned long int __v, __x = (x); \ + if (__builtin_constant_p (x)) \ + __v = __bswap_constant_64 (__x); \ + else \ + __asm__ __volatile__ ("mux1 %0 = %1, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned long int) (__x))); \ + __v; })) + +#else +static __inline unsigned long int +__bswap_64 (unsigned long int __bsx) +{ + return __bswap_constant_64 (__bsx); +} +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/ia64/bits/endian.h b/libc/sysdeps/linux/ia64/bits/endian.h new file mode 100644 index 0000000..98a5e23 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/endian.h @@ -0,0 +1,7 @@ +/* Linux/ia64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/ia64/bits/fcntl.h b/libc/sysdeps/linux/ia64/bits/fcntl.h new file mode 100644 index 0000000..2a4b9ca --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/fcntl.h @@ -0,0 +1,235 @@ +/* O_*, F_*, FD_* bit values for Linux/IA64. + Copyright (C) 1999, 2000, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 +# define O_DIRECTORY 0200000 /* must be a directory */ +# define O_NOFOLLOW 0400000 /* don't follow links */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +#ifdef __USE_LARGEFILE64 +/* Not necessary, files are always with 64bit off_t. */ +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 5 /* Get record locking info. */ +#define F_SETLK 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW 7 /* Set record locking info (blocking). */ + +/* Not necessary, we always have 64-bit offsets. */ +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +/* We don't need to support __USE_FILE_OFFSET64. */ +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/ia64/bits/fenv.h b/libc/sysdeps/linux/ia64/bits/fenv.h new file mode 100644 index 0000000..32515f0 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/fenv.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSR... (Tahoe EAS 2.4 5-4)*/ + +enum + { + FE_INEXACT = 1UL << 5, +#define FE_INEXACT FE_INEXACT + + FE_UNDERFLOW = 1UL << 4, +#define FE_UNDERFLOW FE_UNDERFLOW + + FE_OVERFLOW = 1UL << 3, +#define FE_OVERFLOW FE_OVERFLOW + + FE_DIVBYZERO = 1UL << 2, +#define FE_DIVBYZERO FE_DIVBYZERO + + FE_UNNORMAL = 1UL << 1, +#define FE_UNNORMAL FE_UNNORMAL + + FE_INVALID = 1UL << 0, +#define FE_INVALID FE_INVALID + + FE_ALL_EXCEPT = + (FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW | FE_DIVBYZERO | FE_UNNORMAL | FE_INVALID) +#define FE_ALL_EXCEPT FE_ALL_EXCEPT + }; + + +enum + { + FE_TOWARDZERO = 3, +#define FE_TOWARDZERO FE_TOWARDZERO + + FE_UPWARD = 2, +#define FE_UPWARD FE_UPWARD + + FE_DOWNWARD = 1, +#define FE_DOWNWARD FE_DOWNWARD + + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + }; + + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) 0xc009804c0270033fUL) + +#ifdef __USE_GNU +/* Floating-point environment where only FE_UNNORMAL is masked since this + exception is not generally supported by glibc. */ +# define FE_NOMASK_ENV ((__const fenv_t *) 0xc009804c02700302UL) + +/* Floating-point environment with (processor-dependent) non-IEEE + floating point. In this case, turning on flush-to-zero mode for + s0, s2, and s3. */ +# define FE_NONIEEE_ENV ((__const fenv_t *) 0xc009a04d0270037fUL) +#endif diff --git a/libc/sysdeps/linux/ia64/bits/ipc.h b/libc/sysdeps/linux/ia64/bits/ipc.h new file mode 100644 index 0000000..858c332 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/ipc.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#define IPC_INFO 3 /* See ipcs. */ + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + __mode_t mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/libc/sysdeps/linux/ia64/bits/kernel_stat.h b/libc/sysdeps/linux/ia64/bits/kernel_stat.h new file mode 100644 index 0000000..c67c92d --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/kernel_stat.h @@ -0,0 +1,61 @@ +/* Ripped from linux/include/asm-ia64/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _ASM_IA64_STAT_H +#define _ASM_IA64_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co + */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; + +#define STAT_HAVE_NSEC 1 + +struct __old_kernel_stat { + unsigned int st_dev; + unsigned int st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + unsigned int __pad1; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; + unsigned int st_blksize; + int st_blocks; + unsigned int __unused1; + unsigned int __unused2; +}; + +/* ia64 stat64 is same as stat */ +#define kernel_stat64 kernel_stat + +#endif /* _ASM_IA64_STAT_H */ diff --git a/libc/sysdeps/linux/ia64/bits/kernel_types.h b/libc/sysdeps/linux/ia64/bits/kernel_types.h new file mode 100644 index 0000000..c8ef86d --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/kernel_types.h @@ -0,0 +1,56 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_IA64_POSIX_TYPES_H +#define _ASM_IA64_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + * + * Based on . + * + * Modified 1998-2000, 2003 + * David Mosberger-Tang , Hewlett-Packard Co + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; + +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_old_dev_t; + +#endif /* _ASM_IA64_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/ia64/bits/mathdef.h b/libc/sysdeps/linux/ia64/bits/mathdef.h new file mode 100644 index 0000000..3dc2860 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/mathdef.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The IA-64 architecture computes values with the precision of the + used type. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/ia64/bits/mathinline.h b/libc/sysdeps/linux/ia64/bits/mathinline.h new file mode 100644 index 0000000..9bb5f1a --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/mathinline.h @@ -0,0 +1,54 @@ +/* Inline math functions for ia64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +# endif +#endif diff --git a/libc/sysdeps/linux/ia64/bits/mman.h b/libc/sysdeps/linux/ia64/bits/mman.h new file mode 100644 index 0000000..a27a30f --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/mman.h @@ -0,0 +1,104 @@ +/* Definitions for POSIX memory map interface. Linux/ia64 version. + Copyright (C) 1997,1998,2000,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_GROWSUP 0x00200 /* Register stack-like segment */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 0x1 /* Sync memory asynchronously. */ +#define MS_INVALIDATE 0x2 /* Invalidate the caches. */ +#define MS_SYNC 0x4 /* Synchronous memory sync. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/ia64/bits/msq.h b/libc/sysdeps/linux/ia64/bits/msq.h new file mode 100644 index 0000000..cd268ee --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/msq.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +#error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#define MSG_EXCEPT 020000 /* recv any msg except of specified type */ + + +/* Structure of record for one message inside the kernel. + The type `struct __msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + __time_t msg_rtime; /* time of last msgrcv command */ + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + unsigned long int msg_qnum; /* number of messages currently on queue */ + unsigned long int msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/ia64/bits/sem.h b/libc/sysdeps/linux/ia64/bits/sem.h new file mode 100644 index 0000000..449f1ec --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2000 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/ia64/bits/setjmp.h b/libc/sysdeps/linux/ia64/bits/setjmp.h new file mode 100644 index 0000000..7662575 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/setjmp.h @@ -0,0 +1,40 @@ +/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. + Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* User code must not depend on the internal representation of jmp_buf. */ + +#define _JBLEN 70 + +/* the __jmp_buf element type should be __float80 per ABI... */ +typedef long __jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) < (void *)(((long *)_jmpbuf)[0])) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/ia64/bits/shm.h b/libc/sysdeps/linux/ia64/bits/shm.h new file mode 100644 index 0000000..7f38f2d --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/shm.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +/* Segment low boundary address multiple. */ +#define SHMLBA (1024 * 1024) + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/ia64/bits/sigaction.h b/libc/sysdeps/linux/ia64/bits/sigaction.h new file mode 100644 index 0000000..11599d5 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/sigaction.h @@ -0,0 +1,73 @@ +/* Definitions for Linux/ia64 sigaction. + Copyright (C) 1996, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Special flags. */ + unsigned long int sa_flags; + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + }; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000001 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000002 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000004 +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historic no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/libc/sysdeps/linux/ia64/bits/sigcontext.h b/libc/sysdeps/linux/ia64/bits/sigcontext.h new file mode 100644 index 0000000..72c60ec --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/sigcontext.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen , July 2000 + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#include + +struct ia64_fpreg + { + union + { + unsigned long bits[2]; + } u; + } __attribute__ ((aligned (16))); + +struct sigcontext +{ + unsigned long int sc_flags; /* see manifest constants below */ + unsigned long int sc_nat; /* bit i == 1 iff scratch reg gr[i] is a NaT */ + stack_t sc_stack; /* previously active stack */ + + unsigned long int sc_ip; /* instruction pointer */ + unsigned long int sc_cfm; /* current frame marker */ + unsigned long int sc_um; /* user mask bits */ + unsigned long int sc_ar_rsc; /* register stack configuration register */ + unsigned long int sc_ar_bsp; /* backing store pointer */ + unsigned long int sc_ar_rnat; /* RSE NaT collection register */ + unsigned long int sc_ar_ccv; /* compare & exchange compare value register */ + unsigned long int sc_ar_unat; /* ar.unat of interrupted context */ + unsigned long int sc_ar_fpsr; /* floating-point status register */ + unsigned long int sc_ar_pfs; /* previous function state */ + unsigned long int sc_ar_lc; /* loop count register */ + unsigned long int sc_pr; /* predicate registers */ + unsigned long int sc_br[8]; /* branch registers */ + unsigned long int sc_gr[32]; /* general registers (static partition) */ + struct ia64_fpreg sc_fr[128]; /* floating-point registers */ + unsigned long int sc_rbs_base;/* NULL or new base of sighandler's rbs */ + unsigned long int sc_loadrs; /* see description above */ + unsigned long int sc_ar25; /* cmp8xchg16 uses this */ + unsigned long int sc_ar26; /* rsvd for scratch use */ + unsigned long int sc_rsvd[12];/* reserved for future use */ + + /* sc_mask is actually an sigset_t but we don't want to + * include the kernel headers here. */ + unsigned long int sc_mask; /* signal mask to restore after handler returns */ +}; + +/* sc_flag bit definitions. */ +#define IA64_SC_FLAG_ONSTACK_BIT 0 /* is handler running on signal stack? */ +#define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */ +#define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */ + +#define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT) +#define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT) +#define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT) + +#endif /* _BITS_SIGCONTEXT_H */ diff --git a/libc/sysdeps/linux/ia64/bits/siginfo.h b/libc/sysdeps/linux/ia64/bits/siginfo.h new file mode 100644 index 0000000..66310c6 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/siginfo.h @@ -0,0 +1,339 @@ +/* siginfo_t, sigevent and constants. Linux/ia64 version. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + int __pad0; /* Explicit padding. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + int _si_imm; + unsigned int _si_flags; + unsigned long int _si_isr; + } _sigfault; + + /* SIGPOLL. */ + struct + { + long int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + +# ifdef __USE_GNU +# define si_imm _sifields._sigfault._si_imm +# define si_segvflags _sifields._sigfault._si_flags +# define si_isr _sifields._sigfault._si_isr +# endif + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK, /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK + ILL_BADIADDR /* Unimplemented instruction address. */ +# define ILL_BADIADDR ILL_BADIADDR + +# ifdef __USE_GNU + , ILL_BREAK +# define ILL_BREAK ILL_BREAK +# endif +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +# ifdef __USE_GNU + , FPE_DECOVF +# define FPE_DECOVF FPE_DECOVF + , FPE_DECDIV +# define FPE_DECDIV FPE_DECDIV + , FPE_DECERR +# define FPE_DECERR FPE_DECERR + , FPE_INVASC +# define FPE_INVASC FPE_INVASC + , FPE_INVDEC +# define FPE_INVDEC FPE_INVDEC +# endif +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +# ifdef __USE_GNU + , SEGV_PSTKOVF /* Paragraph stack overflow. */ +# define SEGV_PSTKOVF SEGV_PSTKOVF +# endif +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE + +# ifdef __USE_GNU + , TRAP_BRANCH +# define TRAP_BRANCH TRAP_BRANCH + , TRAP_HWBKPT +# define TRAP_HWBKPT TRAP_HWBKPT +# endif +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/libc/sysdeps/linux/ia64/bits/sigstack.h b/libc/sysdeps/linux/ia64/bits/sigstack.h new file mode 100644 index 0000000..c9c9d2f --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/sigstack.h @@ -0,0 +1,63 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + +#ifndef _SIGSTACK_H +#define _SIGSTACK_H 1 + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + __ptr_t ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. + + Yes, this should be 131072 but the constant got defined incorrectly + in the kernel and we have to live with it. Users should in any case + use SIGSTKSZ as the size user-supplied buffers should have. */ +#define MINSIGSTKSZ 131027 + +/* System default stack size. */ +#define SIGSTKSZ 262144 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + __ptr_t ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; + +#endif /* bits/sigstack.h */ diff --git a/libc/sysdeps/linux/ia64/bits/stackinfo.h b/libc/sysdeps/linux/ia64/bits/stackinfo.h new file mode 100644 index 0000000..b7dc5d9 --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/stackinfo.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On IA-64 the stack grows down. The register stack is of no concern + here. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/ia64/bits/stat.h b/libc/sysdeps/linux/ia64/bits/stat.h new file mode 100644 index 0000000..a5a121b --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/stat.h @@ -0,0 +1,140 @@ +/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 1 +#define _STAT_VER _STAT_VER_LINUX + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + +struct stat + { + __dev_t st_dev; /* Device. */ + __ino_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */ + long int __unused[3]; + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 is the same shape as stat. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ + long int __unused[3]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/ia64/bits/syscalls.h b/libc/sysdeps/linux/ia64/bits/syscalls.h new file mode 100644 index 0000000..0c3d6ca --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/syscalls.h @@ -0,0 +1,192 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef IA64_USE_NEW_STUB + +/* taken from asm-ia64/break.h */ +#define __IA64_BREAK_SYSCALL 0x100000 +#define ___IA64_BREAK_SYSCALL "0x100000" + +#define _DO_SYSCALL(name, nr, args...) \ + LOAD_ARGS_##nr (args) \ + register long _r8 __asm__ ("r8"); \ + register long _r10 __asm__ ("r10"); \ + register long _r15 __asm__ ("r15") = SYS_ify(name); \ + long _retval; \ + LOAD_REGS_##nr \ + __asm__ __volatile__ ("break " ___IA64_BREAK_SYSCALL ";;\n\t" \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15) ASM_OUTARGS_##nr \ + : "2" (_r15) ASM_ARGS_##nr \ + : "memory" ASM_CLOBBERS_##nr); \ + _retval = _r8; \ + if (_r10 == -1) { \ + __set_errno (_retval); \ + _retval = -1; \ + } + +#define LOAD_ARGS_0() +#define LOAD_REGS_0 +#define LOAD_ARGS_1(a1) \ + long _arg1 = (long) (a1); \ + LOAD_ARGS_0 () +#define LOAD_REGS_1 \ + register long _out0 __asm__ ("out0") = _arg1; \ + LOAD_REGS_0 +#define LOAD_ARGS_2(a1, a2) \ + long _arg2 = (long) (a2); \ + LOAD_ARGS_1 (a1) +#define LOAD_REGS_2 \ + register long _out1 __asm__ ("out1") = _arg2; \ + LOAD_REGS_1 +#define LOAD_ARGS_3(a1, a2, a3) \ + long _arg3 = (long) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define LOAD_REGS_3 \ + register long _out2 __asm__ ("out2") = _arg3; \ + LOAD_REGS_2 +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + long _arg4 = (long) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define LOAD_REGS_4 \ + register long _out3 __asm__ ("out3") = _arg4; \ + LOAD_REGS_3 +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + long _arg5 = (long) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define LOAD_REGS_5 \ + register long _out4 __asm__ ("out4") = _arg5; \ + LOAD_REGS_4 +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + long _arg6 = (long) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define LOAD_REGS_6 \ + register long _out5 __asm__ ("out5") = _arg6; \ + LOAD_REGS_5 + +#define ASM_OUTARGS_0 +#define ASM_OUTARGS_1 ASM_OUTARGS_0, "=r" (_out0) +#define ASM_OUTARGS_2 ASM_OUTARGS_1, "=r" (_out1) +#define ASM_OUTARGS_3 ASM_OUTARGS_2, "=r" (_out2) +#define ASM_OUTARGS_4 ASM_OUTARGS_3, "=r" (_out3) +#define ASM_OUTARGS_5 ASM_OUTARGS_4, "=r" (_out4) +#define ASM_OUTARGS_6 ASM_OUTARGS_5, "=r" (_out5) + +#ifdef IA64_USE_NEW_STUB +#define ASM_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "4" (_out0) +#define ASM_ARGS_2 ASM_ARGS_1, "5" (_out1) +#define ASM_ARGS_3 ASM_ARGS_2, "6" (_out2) +#define ASM_ARGS_4 ASM_ARGS_3, "7" (_out3) +#define ASM_ARGS_5 ASM_ARGS_4, "8" (_out4) +#define ASM_ARGS_6 ASM_ARGS_5, "9" (_out5) +#else +#define ASM_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "3" (_out0) +#define ASM_ARGS_2 ASM_ARGS_1, "4" (_out1) +#define ASM_ARGS_3 ASM_ARGS_2, "5" (_out2) +#define ASM_ARGS_4 ASM_ARGS_3, "6" (_out3) +#define ASM_ARGS_5 ASM_ARGS_4, "7" (_out4) +#define ASM_ARGS_6 ASM_ARGS_5, "8" (_out5) +#endif + +#define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0" +#define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1" +#define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2" +#define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3" +#define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4" +#define ASM_CLOBBERS_5 ASM_CLOBBERS_6, "out5" +#define ASM_CLOBBERS_6_COMMON , "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r10, r15. */ \ + "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6" + +#ifdef IA64_USE_NEW_STUB +# define ASM_CLOBBERS_6 ASM_CLOBBERS_6_COMMON +#else +# define ASM_CLOBBERS_6 ASM_CLOBBERS_6_COMMON , "b7" +#endif + + + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + _DO_SYSCALL(name, 0); return (type) _retval; \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + _DO_SYSCALL(name, 1, arg1); return (type) _retval; \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2) \ +{ \ + _DO_SYSCALL(name, 2, arg1, arg2); return (type) _retval; \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3) \ +{ \ + _DO_SYSCALL(name, 3, arg1, arg2, arg3); return (type) _retval; \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + _DO_SYSCALL(name, 4, arg1, arg2, arg3, arg4); return (type) _retval; \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + _DO_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); return (type) _retval; \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ + _DO_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); return (type) _retval; \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h b/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h new file mode 100644 index 0000000..953279e --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "break 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/ia64/bits/wordsize.h b/libc/sysdeps/linux/ia64/bits/wordsize.h new file mode 100644 index 0000000..dd698fa --- /dev/null +++ b/libc/sysdeps/linux/ia64/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 64 diff --git a/libc/sysdeps/linux/ia64/brk.S b/libc/sysdeps/linux/ia64/brk.S new file mode 100644 index 0000000..e9974d5 --- /dev/null +++ b/libc/sysdeps/linux/ia64/brk.S @@ -0,0 +1,52 @@ +/* brk system call for Linux/ia64 + Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Stephane Eranian and + Jes Sorensen, , April 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +#include +#include + + .global __curbrk + .hidden __curbrk + .type __curbrk,@object + .size __curbrk,8 + .data + .align 8 +__curbrk: + data8 0 + +weak_alias (__curbrk, ___brk_addr) + +LEAF(brk) + .regstk 1, 0, 0, 0 + DO_CALL(__NR_brk) + cmp.ltu p6, p0 = ret0, in0 + addl r9 = @ltoff(__curbrk), gp + ;; + ld8 r9 = [r9] +(p6) mov ret0 = ENOMEM +(p6) br.cond.spnt.few __syscall_error + ;; + st8 [r9] = ret0 + mov ret0 = 0 + ret +END(brk) +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/ia64/bsd-_setjmp.S b/libc/sysdeps/linux/ia64/bsd-_setjmp.S new file mode 100644 index 0000000..4e6a2da --- /dev/null +++ b/libc/sysdeps/linux/ia64/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/ia64/bsd-setjmp.S b/libc/sysdeps/linux/ia64/bsd-setjmp.S new file mode 100644 index 0000000..1da848d --- /dev/null +++ b/libc/sysdeps/linux/ia64/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/ia64/clone2.S b/libc/sysdeps/linux/ia64/clone2.S new file mode 100644 index 0000000..7f067df --- /dev/null +++ b/libc/sysdeps/linux/ia64/clone2.S @@ -0,0 +1,107 @@ +/* Copyright (C) 2000, 2001, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +#include "sysdep.h" +#include + + +/* int __clone2(int (*fn) (void *arg), void *child_stack_base, */ +/* size_t child_stack_size, int flags, void *arg, */ +/* pid_t *parent_tid, void *tls, pid_t *child_tid) */ + +#define CHILD p8 +#define PARENT p9 + +ENTRY(__clone2) + .prologue + alloc r2=ar.pfs,8,1,6,0 + cmp.eq p6,p0=0,in0 + cmp.eq p7,p0=0,in1 + mov r8=EINVAL + mov out0=in3 /* Flags are first syscall argument. */ + mov out1=in1 /* Stack address. */ +(p6) br.cond.spnt.many __syscall_error /* no NULL function pointers */ +(p7) br.cond.spnt.many __syscall_error /* no NULL stack pointers */ + ;; + mov out2=in2 /* Stack size. */ + mov out3=in5 /* Parent TID Pointer */ + mov out4=in7 /* Child TID Pointer */ + mov out5=in6 /* TLS pointer */ + /* + * clone2() is special: the child cannot execute br.ret right + * after the system call returns, because it starts out + * executing on an empty stack. Because of this, we can't use + * the new (lightweight) syscall convention here. Instead, we + * just fall back on always using "break". + * + * Furthermore, since the child starts with an empty stack, we + * need to avoid unwinding past invalid memory. To that end, + * we'll pretend now that __clone2() is the end of the + * call-chain. This is wrong for the parent, but only until + * it returns from clone2() but it's better than the + * alternative. + */ + mov r15=SYS_ify (clone2) + .save rp, r0 + break __BREAK_SYSCALL + .body + cmp.eq p6,p0=-1,r10 + cmp.eq CHILD,PARENT=0,r8 /* Are we the child? */ +(p6) br.cond.spnt.many __syscall_error + ;; +(CHILD) mov loc0=gp +(PARENT) ret + ;; +#ifdef RESET_PID + tbit.nz p6,p0=in3,16 /* CLONE_THREAD */ + tbit.z p7,p10=in3,8 /* CLONE_VM */ +(p6) br.cond.dptk 1f + ;; + mov r15=SYS_ify (getpid) +(p10) addl r8=-1,r0 +(p7) break __BREAK_SYSCALL + ;; + add r9=PID,r13 + add r10=TID,r13 + ;; + st4 [r9]=r8 + st4 [r10]=r8 + ;; +#endif +1: ld8 out1=[in0],8 /* Retrieve code pointer. */ + mov out0=in4 /* Pass proper argument to fn */ + ;; + ld8 gp=[in0] /* Load function gp. */ + mov b6=out1 + br.call.dptk.many rp=b6 /* Call fn(arg) in the child */ + ;; + mov out0=r8 /* Argument to _exit */ + mov gp=loc0 + .globl HIDDEN_JUMPTARGET(_exit) + br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit) + /* call _exit with result from fn. */ + ret /* Not reached. */ +PSEUDO_END(__clone2) + +/* For now we leave __clone undefined. This is unlikely to be a */ +/* problem, since at least the i386 __clone in glibc always failed */ +/* with a 0 sp (eventhough the kernel explicitly handled it). */ +/* Thus all such calls needed to pass an explicit sp, and as a result, */ +/* would be unlikely to work on ia64. */ diff --git a/libc/sysdeps/linux/ia64/crt1.S b/libc/sysdeps/linux/ia64/crt1.S new file mode 100644 index 0000000..774e84f --- /dev/null +++ b/libc/sysdeps/linux/ia64/crt1.S @@ -0,0 +1,129 @@ +/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __ASSEMBLY__ +#include "sysdep.h" + +#include +#include + +/* + * Arguments for __uClibc_main: + * out0: main + * out1: argc + * out2: argv + * out3: init + * out4: fini + * out5: rtld_fini + * out6: stack_end + */ + +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif + + .align 32 + .global _start + + .proc _start + .type _start,@function +_start: + .prologue + .save rp, r0 + .body + .prologue + { .mlx + alloc r2 = ar.pfs,0,0,7,0 + movl r3 = FPSR_DEFAULT + } + { .mlx + adds out2 = 16, sp /* get address of argc value */ + movl gp = @gprel(0f) + ;; + } +0: { .mmi + ld8 out1 = [out2], 8 /* load argc and move out2 to become argv */ + mov.m r10 = ar.bsp /* fetch rbs base address */ + mov r9 = ip + ;; + } + { .mii + mov ar.fpsr = r3 + sub gp = r9, gp /* back-compute gp value */ + adds out6 = 16, sp /* highest non-environment stack address */ + ;; + } + { + addl r11 = @ltoff(__libc_ia64_register_backing_store_base), gp + addl out0 = @ltoff(@fptr(main)), gp + addl out3 = @ltoff(@fptr(_init)), gp + ;; + } + { .mmi + ld8 r3 = [r11] /* pointer to __libc_ia64_register_backing_store_base */ + ld8 out0 = [out0] /* pointer to `main' function descriptor */ + addl out4 = @ltoff(@fptr(_fini)), gp + ;; + } + { .mmi + ld8 out3 = [out3] /* pointer to `init' function descriptor */ + ld8 out4 = [out4] /* pointer to `fini' function descriptor */ + nop 0 + } + .body + { .mib + st8 [r3] = r10 + mov out5 = ret0 /* dynamic linker destructor */ + br.call.sptk.few rp = __uClibc_main + } + { .mib + break 0 /* break miserably if we ever return */ + } + .endp _start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + + .common __libc_ia64_register_backing_store_base, 8, 8 diff --git a/libc/sysdeps/linux/ia64/crti.S b/libc/sysdeps/linux/ia64/crti.S new file mode 100644 index 0000000..c22bbf1 --- /dev/null +++ b/libc/sysdeps/linux/ia64/crti.S @@ -0,0 +1,36 @@ +/* glibc's sysdeps/ia64/elf/initfini.c used for reference [PROLOG] */ + + .text + .section .init + .global _init# + .proc _init# +_init: + .prologue + .save ar.pfs, r34 + alloc r34 = ar.pfs, 0, 3, 0, 0 + .vframe r32 + mov r32 = r12 + .save rp, r33 + mov r33 = b0 + .body + adds r12 = -16, r12 + ;; + .endp _init# + + + + .section .fini + .global _fini# + .proc _fini# +_fini: + .prologue + .save ar.pfs, r34 + alloc r34 = ar.pfs, 0, 3, 0, 0 + .vframe r32 + mov r32 = r12 + .save rp, r33 + mov r33 = b0 + .body + adds r12 = -16, r12 + ;; + .endp _fini# diff --git a/libc/sysdeps/linux/ia64/crtn.S b/libc/sysdeps/linux/ia64/crtn.S new file mode 100644 index 0000000..5403446 --- /dev/null +++ b/libc/sysdeps/linux/ia64/crtn.S @@ -0,0 +1,33 @@ +/* glibc's sysdeps/ia64/elf/initfini.c used for reference [EPILOG] */ + + .text + .section .init + .proc _init# +_init: + .prologue + .save ar.pfs, r34 + .vframe r32 + .save rp, r33 + .body + .regstk 0,2,0,0 + mov r12 = r32 + mov ar.pfs = r34 + mov b0 = r33 + br.ret.sptk.many b0 + .endp _init# + + + + .section .fini + .proc _fini# +_fini: + .prologue + .save ar.pfs, r34 + .vframe r32 + .save rp, r33 + .body + mov r12 = r32 + mov ar.pfs = r34 + mov b0 = r33 + br.ret.sptk.many b0 + .endp _fini# diff --git a/libc/sysdeps/linux/ia64/fork.S b/libc/sysdeps/linux/ia64/fork.S new file mode 100644 index 0000000..c657453 --- /dev/null +++ b/libc/sysdeps/linux/ia64/fork.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include "sysdep.h" +#define _SIGNAL_H +#include + +/* pid_t fork(void); */ +/* Implemented as a clone system call with parameters SIGCHLD and 0 */ + +ENTRY(__libc_fork) + alloc r2=ar.pfs,0,0,2,0 + mov out0=SIGCHLD /* Return SIGCHLD when child finishes */ + /* no other clone flags; nothing shared */ + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__libc_fork) + +weak_alias (__libc_fork, __fork) +libc_hidden_def (__fork) +weak_alias (__libc_fork, fork) +libc_hidden_weak (fork) diff --git a/libc/sysdeps/linux/ia64/pipe.S b/libc/sysdeps/linux/ia64/pipe.S new file mode 100644 index 0000000..2bfa8a7 --- /dev/null +++ b/libc/sysdeps/linux/ia64/pipe.S @@ -0,0 +1,37 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* __pipe is a special syscall since it returns two values. */ + +#include "sysdep.h" + +ENTRY(pipe) + .regstk 1,0,0,0 + DO_CALL (SYS_ify (pipe)) + cmp.ne p6,p0=-1,r10 + ;; +(p6) st4 [in0]=r8,4 +(p6) mov ret0=0 + ;; +(p6) st4 [in0]=r9 +(p6) ret + br.cond.spnt.few __syscall_error +PSEUDO_END(pipe) + +libc_hidden_def (pipe) diff --git a/libc/sysdeps/linux/ia64/setjmp.S b/libc/sysdeps/linux/ia64/setjmp.S new file mode 100644 index 0000000..cf6c75d --- /dev/null +++ b/libc/sysdeps/linux/ia64/setjmp.S @@ -0,0 +1,189 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 + Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + The layout of the jmp_buf is as follows. This is subject to change + and user-code should never depend on the particular layout of + jmp_buf! + + + offset: description: + ------- ------------ + 0x000 stack pointer (r12) ; unchangeable (see _JMPBUF_UNWINDS) + 0x008 r1 (gp) + 0x010 caller's unat + 0x018 fpsr + 0x020 r4 + 0x028 r5 + 0x030 r6 + 0x038 r7 + 0x040 rp (b0) + 0x048 b1 + 0x050 b2 + 0x058 b3 + 0x060 b4 + 0x068 b5 + 0x070 ar.pfs + 0x078 ar.lc + 0x080 pr + 0x088 ar.bsp ; unchangeable (see __longjmp.S) + 0x090 ar.unat + 0x098 &__jmp_buf ; address of the jmpbuf (needed to locate NaT bits in unat) + 0x0a0 f2 + 0x0b0 f3 + 0x0c0 f4 + 0x0d0 f5 + 0x0e0 f16 + 0x0f0 f17 + 0x100 f18 + 0x110 f19 + 0x120 f20 + 0x130 f21 + 0x130 f22 + 0x140 f23 + 0x150 f24 + 0x160 f25 + 0x170 f26 + 0x180 f27 + 0x190 f28 + 0x1a0 f29 + 0x1b0 f30 + 0x1c0 f31 */ + +#include "sysdep.h" +#include + + /* The following two entry points are the traditional entry points: */ + +LEAF(setjmp) + alloc r8=ar.pfs,2,0,0,0 + mov in1=1 + br.cond.sptk.many _GI___sigsetjmp +END(setjmp) + +LEAF(_setjmp) + alloc r8=ar.pfs,2,0,0,0 + mov in1=0 + br.cond.sptk.many _GI___sigsetjmp +END(_setjmp) +libc_hidden_def (_setjmp) + + /* __sigsetjmp(__jmp_buf buf, int savemask) */ + +ENTRY(__sigsetjmp) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) + alloc loc1=ar.pfs,2,5,2,0 + .save ar.unat, loc2 + mov loc2=ar.unat + ;; + mov r17=ar.fpsr + mov r2=in0 + add r3=8,in0 + ;; +.mem.offset 8,0; st8.spill.nta [r2]=sp,16 /* r12 (sp) */ +.mem.offset 0,0; st8.spill.nta [r3]=gp,16 /* r1 (gp) */ + ;; + st8.nta [r2]=loc2,16 /* save caller's unat */ + st8.nta [r3]=r17,16 /* save fpsr */ + add r8=0xa0,in0 + ;; +.mem.offset 8,0; st8.spill.nta [r2]=r4,16 /* r4 */ +.mem.offset 0,0; st8.spill.nta [r3]=r5,16 /* r5 */ + add r9=0xb0,in0 + ;; + stf.spill.nta [r8]=f2,32 + stf.spill.nta [r9]=f3,32 + mov loc0=rp + .body + ;; + stf.spill.nta [r8]=f4,32 + stf.spill.nta [r9]=f5,32 + mov r17=b1 + ;; + stf.spill.nta [r8]=f16,32 + stf.spill.nta [r9]=f17,32 + mov r18=b2 + ;; + stf.spill.nta [r8]=f18,32 + stf.spill.nta [r9]=f19,32 + mov r19=b3 + ;; + stf.spill.nta [r8]=f20,32 + stf.spill.nta [r9]=f21,32 + mov r20=b4 + ;; + stf.spill.nta [r8]=f22,32 + stf.spill.nta [r9]=f23,32 + mov r21=b5 + ;; + stf.spill.nta [r8]=f24,32 + stf.spill.nta [r9]=f25,32 + mov r22=ar.lc + ;; + stf.spill.nta [r8]=f26,32 + stf.spill.nta [r9]=f27,32 + mov r24=pr + ;; + stf.spill.nta [r8]=f28,32 + stf.spill.nta [r9]=f29,32 + ;; + stf.spill.nta [r8]=f30 + stf.spill.nta [r9]=f31 + +.mem.offset 8,0; st8.spill.nta [r2]=r6,16 /* r6 */ +.mem.offset 0,0; st8.spill.nta [r3]=r7,16 /* r7 */ + ;; + mov r23=ar.bsp + mov r25=ar.unat + mov out0=in0 + + st8.nta [r2]=loc0,16 /* b0 */ + st8.nta [r3]=r17,16 /* b1 */ + mov out1=in1 + ;; + st8.nta [r2]=r18,16 /* b2 */ + st8.nta [r3]=r19,16 /* b3 */ + ;; + st8.nta [r2]=r20,16 /* b4 */ + st8.nta [r3]=r21,16 /* b5 */ + ;; + st8.nta [r2]=loc1,16 /* ar.pfs */ + st8.nta [r3]=r22,16 /* ar.lc */ + ;; + st8.nta [r2]=r24,16 /* pr */ + st8.nta [r3]=r23,16 /* ar.bsp */ + ;; + st8.nta [r2]=r25 /* ar.unat */ + st8.nta [r3]=in0 /* &__jmp_buf */ +#if defined NOT_IN_libc && defined IS_IN_rtld + /* In ld.so we never save the signal mask. */ + ;; +#else + br.call.dpnt.few rp=__sigjmp_save +#endif +.ret0: /* force a new bundle ::q */ + mov.m ar.unat=loc2 /* restore caller's unat */ + mov rp=loc0 + mov ar.pfs=loc1 + mov r8=0 + ret +END(__sigsetjmp) +strong_alias(__sigsetjmp, _GI___sigsetjmp) + +weak_extern(_setjmp) +weak_extern(setjmp) diff --git a/libc/sysdeps/linux/ia64/sys/io.h b/libc/sysdeps/linux/ia64/sys/io.h new file mode 100644 index 0000000..14736ff --- /dev/null +++ b/libc/sysdeps/linux/ia64/sys/io.h @@ -0,0 +1,68 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on); + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level); + +extern unsigned int _inb (unsigned long int __port); +extern unsigned int _inb (unsigned long int __port); +extern unsigned int _inw (unsigned long int __port); +extern unsigned int _inl (unsigned long int __port); +extern void _outb (unsigned char __val, unsigned long int __port); +extern void _outw (unsigned short __val, unsigned long int __port); +extern void _outl (unsigned int __val, unsigned long int __port); + +#define inb _inb +#define inw _inw +#define inl _inl +#define outb _outb +#define outw _outw +#define outl _outl + +/* Access PCI space protected from machine checks. */ +extern int pciconfig_read (unsigned long int __bus, unsigned long int __dfn, + unsigned long int __off, unsigned long int __len, + unsigned char *__buf); + +extern int pciconfig_write (unsigned long int __bus, unsigned long int __dfn, + unsigned long int __off, unsigned long int __len, + unsigned char *__buf); + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/ia64/sys/procfs.h b/libc/sysdeps/linux/ia64/sys/procfs.h new file mode 100644 index 0000000..b5196b9 --- /dev/null +++ b/libc/sysdeps/linux/ia64/sys/procfs.h @@ -0,0 +1,130 @@ +/* Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* We really need just 72 but let's leave some headroom... */ +#define ELF_NGREG 128 +/* f0 and f1 could be omitted, but so what... */ +#define ELF_NFPREG 128 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct ia64_fpreg elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +typedef elf_greg_t greg_t; +typedef elf_gregset_t gregset_t; +typedef elf_fpregset_t fpregset_t; +#define NGREG ELF_NGREG + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/ia64/sys/ptrace.h b/libc/sysdeps/linux/ia64/sys/ptrace.h new file mode 100644 index 0000000..986c4b2 --- /dev/null +++ b/libc/sysdeps/linux/ia64/sys/ptrace.h @@ -0,0 +1,135 @@ +/* `ptrace' debugger support interface. Linux/ia64 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Execute process until next taken branch. */ + PTRACE_SINGLEBLOCK = 12, +#define PT_STEPBLOCK PTRACE_SINGLEBLOCK + + /* Get siginfo for process. */ + PTRACE_GETSIGINFO = 13, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Set new siginfo for process. */ + PTRACE_SETSIGINFO = 14, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all registers (pt_all_user_regs) in one shot */ + PTRACE_GETREGS = 18, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all registers (pt_all_user_regs) in one shot */ + PTRACE_SETREGS = 19, +#define PT_SETREGS PTRACE_SETREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* pt_all_user_regs is used for PTRACE_GETREGS/PTRACE_SETREGS. */ +struct pt_all_user_regs + { + unsigned long nat; + unsigned long cr_iip; + unsigned long cfm; + unsigned long cr_ipsr; + unsigned long pr; + + unsigned long gr[32]; + unsigned long br[8]; + unsigned long ar[128]; + struct ia64_fpreg fr[128]; + }; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/ia64/sys/ucontext.h b/libc/sysdeps/linux/ia64/sys/ucontext.h new file mode 100644 index 0000000..17dc85f --- /dev/null +++ b/libc/sysdeps/linux/ia64/sys/ucontext.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + +/* + * These are here mostly for backwards compatibility with older Unices. + * IA-64 Linux does not distinguish between "struct sigcontext" and + * "ucontext_t" as all the necessary info is inside the former. + */ + +typedef struct sigcontext mcontext_t; + +#if defined __cplusplus && __GNUC_PREREQ (3, 5) +# define _SC_GR0_OFFSET \ + __builtin_offsetof (struct sigcontext, sc_gr[0]) +#elif defined __GNUC__ +# define _SC_GR0_OFFSET \ + (((char *) &((struct sigcontext *) 0)->sc_gr[0]) - (char *) 0) +#else +# define _SC_GR0_OFFSET 0xc8 /* pray that this is correct... */ +#endif + +typedef struct ucontext + { + union + { + mcontext_t _mc; + struct + { + unsigned long _pad[_SC_GR0_OFFSET/8]; + struct ucontext *_link; /* this should overlay sc_gr[0] */ + } + _uc; + } + _u; + } +ucontext_t; + +#define uc_mcontext _u._mc +#define uc_sigmask _u._mc.sc_mask +#define uc_stack _u._mc.sc_stack +#define uc_link _u._uc._link + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/ia64/sys/user.h b/libc/sysdeps/linux/ia64/sys/user.h new file mode 100644 index 0000000..0392187 --- /dev/null +++ b/libc/sysdeps/linux/ia64/sys/user.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include +#include + +/* This definition comes directly from the kernel headers. If + anything changes in them this header has to be changed, too. */ + + +/* The definition in the kernel has the comment "XXX fix me". */ +#define EF_SIZE 3072 + + +struct user +{ + unsigned long int regs[EF_SIZE / 8 + 32]; /* Integer and fp regs. */ + size_t u_tsize; /* Text size (pages). */ + size_t u_dsize; /* Data size (pages). */ + size_t u_ssize; /* Stack size (pages). */ + unsigned long int start_code; /* Text starting address. */ + unsigned long int start_data; /* Data starting address. */ + unsigned long int start_stack; /* Stack starting address. */ + long int signal; /* Signal causing core dump. */ + struct regs *u_ar0; /* Help gdb find registers. */ + unsigned long int magic; /* Identifies a core file. */ + char u_comm[32]; /* User command name. */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/libc/sysdeps/linux/ia64/syscall.S b/libc/sysdeps/linux/ia64/syscall.S new file mode 100644 index 0000000..e4ac834 --- /dev/null +++ b/libc/sysdeps/linux/ia64/syscall.S @@ -0,0 +1,30 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +ENTRY(syscall) + alloc r2=ar.pfs,1,0,8,0 + mov r15=r32 /* syscall number */ + break __BREAK_SYSCALL + ;; + cmp.ne p6,p0=-1,r10 /* r10 = -1 on error */ +(p6) ret + br.cond.spnt.few __syscall_error +PSEUDO_END(syscall) diff --git a/libc/sysdeps/linux/ia64/sysdep.h b/libc/sysdeps/linux/ia64/sysdep.h new file mode 100644 index 0000000..d10020a --- /dev/null +++ b/libc/sysdeps/linux/ia64/sysdep.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_IA64_SYSDEP_H +#define _LINUX_IA64_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Macros to help writing .prologue directives in assembly code. */ +#define ASM_UNW_PRLG_RP 0x8 +#define ASM_UNW_PRLG_PFS 0x4 +#define ASM_UNW_PRLG_PSP 0x2 +#define ASM_UNW_PRLG_PR 0x1 +#define ASM_UNW_PRLG_GRSAVE(ninputs) (32+(ninputs)) + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define CALL_MCOUNT + +#define ENTRY(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global C_SYMBOL_NAME(name); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define LEAF(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global name; \ + C_LABEL(name) + +/* Mark the end of function SYM. */ +#undef END +#define END(sym) .endp C_SYMBOL_NAME(sym) + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +/* Linux uses a negative return value to indicate syscall errors, unlike + most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be negative + even if the call succeeded. E.g., the `lseek' system call might return + a large offset. Therefore we must not anymore test for < 0, but test + for a real error by making sure the value in %d0 is a real error + number. Linus said he will make sure the no syscall returns a value + in -1 .. -4095 as a valid result so we can savely test with -4095. */ + +/* We don't want the label for the error handler to be visible in the symbol + table when we define it here. */ +#define SYSCALL_ERROR_LABEL __syscall_error + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; + +#define DO_CALL_VIA_BREAK(num) \ + mov r15=num; \ + break __BREAK_SYSCALL + +#ifdef IA64_USE_NEW_STUB +# ifdef SHARED +# define DO_CALL(num) \ + .prologue; \ + adds r2 = SYSINFO_OFFSET, r13;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov r15 = num; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# else /* !SHARED */ +# define DO_CALL(num) \ + .prologue; \ + mov r15 = num; \ + movl r2 = _dl_sysinfo;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# endif +#else +# define DO_CALL(num) DO_CALL_VIA_BREAK(num) +#endif + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) mov r10=r8; + + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) .endp C_SYMBOL_NAME(name); + +#undef END +#define END(name) \ + .size C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ; \ + .endp C_SYMBOL_NAME(name) + +#define ret br.ret.sptk.few b0 +#define ret_NOERRNO ret +#define ret_ERRVAL ret + +#endif /* not __ASSEMBLER__ */ + +#endif /* linux/ia64/sysdep.h */ diff --git a/libc/sysdeps/linux/ia64/vfork.S b/libc/sysdeps/linux/ia64/vfork.S new file mode 100644 index 0000000..f233b05 --- /dev/null +++ b/libc/sysdeps/linux/ia64/vfork.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include "sysdep.h" +#define _SIGNAL_H +#include + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL_VIA_BREAK (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/m68k/Makefile b/libc/sysdeps/linux/m68k/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/m68k/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/m68k/Makefile.arch b/libc/sysdeps/linux/m68k/Makefile.arch new file mode 100644 index 0000000..14ce2e3 --- /dev/null +++ b/libc/sysdeps/linux/m68k/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c syscall.c + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/m68k/README.m68k b/libc/sysdeps/linux/m68k/README.m68k new file mode 100644 index 0000000..a6bb17e --- /dev/null +++ b/libc/sysdeps/linux/m68k/README.m68k @@ -0,0 +1,54 @@ + +README for uC-libc on the m68k[nommu] architecture + +James Graves + +For now (2001/1/9) support for the m68k should be considered "alpha" +quality at best. It mostly works OK for some of the stuff I'm working +on, but you can't fully compile other things (like the user +applications for uClinux). Needs lots more testing. + +Only developed/tested with m68k-pic-coff-gcc 2.7.2.3-pic-060999, from +Lineo. + +Configuration: + + Read and edit the Config file, carefully. + + TARGET_ARCH=m68k + CROSS = m68k-pic-coff- + CC = $(CROSS)gcc + STRIPTOOL = $(CROSS)strip + KERNEL_SOURCE=/opt/uClinux/linux + HAS_MMU = false + HAS_FLOATS = false + MALLOC = malloc-simple + INSTALL_DIR = /opt/uClinux/m68k-pic-coff + + The regular malloc library is broken, dunno why. Use + simple-malloc. + +Installation: + Theoretically, you should be able to install right over the + existing uC-libc 0.9.1 files in + /opt/uClinux/m68k-pic-coff/include, but I recommend cleaning + out all the include files there. + + The only file in there that's not from the old uC-libc is + assert.h, but I don't know why that would be the valid copy. + + run: + make install + +Problems: + + I _may_ be able to help if you run into problems. Create a + really, really short program that demonstrates the problem, + and contact me. + +TODO: + Fix vfork(). + + Does crt0.o still need to be a separate file? Can't I just + stick it in libc.a and be done with it? Is that specified in + the GCC link options? diff --git a/libc/sysdeps/linux/m68k/__longjmp.S b/libc/sysdeps/linux/m68k/__longjmp.S new file mode 100644 index 0000000..5db9e43 --- /dev/null +++ b/libc/sysdeps/linux/m68k/__longjmp.S @@ -0,0 +1,26 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include + +.globl __longjmp +.type __longjmp,@function +.align 4 +__longjmp: + moveal %sp@(4), %a0 + movel %sp@(8), %d0 + bne 1f + movel #1, %d0 +1: + moveml %a0@(JB_REGS), %d2-%d7/%a2-%a7 +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %a0@(JB_FPREGS), %fp2-%fp7 +#endif + movel %a0@(JB_PC), %sp@ + rts + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/m68k/__syscall_error.c b/libc/sysdeps/linux/m68k/__syscall_error.c new file mode 100644 index 0000000..a29f6ff --- /dev/null +++ b/libc/sysdeps/linux/m68k/__syscall_error.c @@ -0,0 +1,19 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__("%d0"); + __set_errno(-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/m68k/bits/byteswap.h b/libc/sysdeps/linux/m68k/bits/byteswap.h new file mode 100644 index 0000000..f5ec916 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/byteswap.h @@ -0,0 +1,67 @@ +/* Macros to swap the order of bytes in integer values. m68k version. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. We don't provide an assembler version + because GCC is smart enough to generate optimal assembler output, and + this allows for better cse. */ +#define __bswap_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 && !defined __mcoldfire__ +# define __bswap_32(x) \ + __extension__ \ + ({ unsigned int __bswap_32_v; \ + if (__builtin_constant_p (x)) \ + __bswap_32_v = __bswap_constant_32 (x); \ + else \ + __asm__ __volatile__ ("ror%.w %#8, %0;" \ + "swap %0;" \ + "ror%.w %#8, %0" \ + : "=d" (__bswap_32_v) \ + : "0" ((unsigned int) (x))); \ + __bswap_32_v; }) +#else +# define __bswap_32(x) __bswap_constant_32 (x) +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + __extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __bswap_64_v, __bswap_64_r; \ + __bswap_64_v.__ll = (x); \ + __bswap_64_r.__l[0] = __bswap_32 (__bswap_64_v.__l[1]); \ + __bswap_64_r.__l[1] = __bswap_32 (__bswap_64_v.__l[0]); \ + __bswap_64_r.__ll; }) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/m68k/bits/endian.h b/libc/sysdeps/linux/m68k/bits/endian.h new file mode 100644 index 0000000..bf4ecb6 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/endian.h @@ -0,0 +1,7 @@ +/* m68k is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/m68k/bits/fcntl.h b/libc/sysdeps/linux/m68k/bits/fcntl.h new file mode 100644 index 0000000..37e99f9 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/fcntl.h @@ -0,0 +1,237 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/m68k/bits/fenv.h b/libc/sysdeps/linux/m68k/bits/fenv.h new file mode 100644 index 0000000..7c0bcb6 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/fenv.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSR Accrued Exception Byte. */ +enum + { + FE_INEXACT = 1 << 3, +#define FE_INEXACT FE_INEXACT + FE_DIVBYZERO = 1 << 4, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << 5, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << 6, +#define FE_OVERFLOW FE_OVERFLOW + FE_INVALID = 1 << 7 +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The m68k FPU supports all of the four defined rounding modes. We use + the bit positions in the FPCR Mode Control Byte as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 4, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 2 << 4, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 3 << 4 +#define FE_UPWARD FE_UPWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by `fmovem'. */ +typedef struct + { + unsigned int __control_register; + unsigned int __status_register; + unsigned int __instruction_address; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/libc/sysdeps/linux/m68k/bits/kernel_stat.h b/libc/sysdeps/linux/m68k/bits/kernel_stat.h new file mode 100644 index 0000000..e60362b --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/kernel_stat.h @@ -0,0 +1,62 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned char __pad0[6]; + unsigned short st_dev; + unsigned char __pad1[2]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned char __pad2[6]; + unsigned short st_rdev; + unsigned char __pad3[2]; + long long st_size; + unsigned long st_blksize; + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/m68k/bits/kernel_types.h b/libc/sysdeps/linux/m68k/bits/kernel_types.h new file mode 100644 index 0000000..0a77a8f --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_M68K_POSIX_TYPES_H +#define __ARCH_M68K_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_M68K_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/m68k/bits/mathdef.h b/libc/sysdeps/linux/m68k/bits/mathdef.h new file mode 100644 index 0000000..65cf8d4 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/mathdef.h @@ -0,0 +1,38 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The m68k FPUs evaluate all values in the 96 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/m68k/bits/mathinline.h b/libc/sysdeps/linux/m68k/bits/mathinline.h new file mode 100644 index 0000000..f316600 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/mathinline.h @@ -0,0 +1,445 @@ +/* Definitions of inline math functions implemented by the m68881/2. + Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __GNUC__ + +#ifdef __USE_ISOC99 +/* GCC 3.1 and up have builtins that actually can be used. */ +# if !__GNUC_PREREQ (3,1) +/* ISO C99 defines some macros to perform unordered comparisons. The + m68k FPU supports this with special opcodes and we should use them. + These must not be inline functions since we have to be able to handle + all floating-point types. */ +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# define isgreater(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsogt %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isgreaterequal(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsoge %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isless(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsolt %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define islessequal(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsole %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define islessgreater(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsogl %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isunordered(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsun %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) +# endif /* GCC 3.1 */ +#endif + + +#if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \ + || defined __LIBC_INTERNAL_MATH_INLINES + +#ifdef __LIBC_INTERNAL_MATH_INLINES +/* This is used when defining the functions themselves. Define them with + __ names, and with `static inline' instead of `extern inline' so the + bodies will always be used, never an external function call. */ +# define __m81_u(x) __CONCAT(__,x) +# define __m81_inline static __inline +#else +# define __m81_u(x) x +# ifdef __cplusplus +# define __m81_inline __inline +# else +# define __m81_inline extern __inline +# endif +# define __M81_MATH_INLINES 1 +#endif + +/* Define a const math function. */ +#define __m81_defun(rettype, func, args) \ + __m81_inline rettype __attribute__((__const__)) \ + __m81_u(func) args + +/* Define the three variants of a math function that has a direct + implementation in the m68k fpu. FUNC is the name for C (which will be + suffixed with f and l for the float and long double version, resp). OP + is the name of the fpu operation (without leading f). */ + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop(func, op) \ + __inline_mathop1(double, func, op) \ + __inline_mathop1(float, __CONCAT(func,f), op) \ + __inline_mathop1(long double, __CONCAT(func,l), op) +#else +# define __inline_mathop(func, op) \ + __inline_mathop1(double, func, op) +#endif + +#define __inline_mathop1(float_type,func, op) \ + __m81_defun (float_type, func, (float_type __mathop_x)) \ + { \ + float_type __result; \ + __asm__("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\ + return __result; \ + } + +__inline_mathop(__atan, atan) +__inline_mathop(__cos, cos) +__inline_mathop(__sin, sin) +__inline_mathop(__tan, tan) +__inline_mathop(__tanh, tanh) +__inline_mathop(__fabs, abs) + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__inline_mathop(__rint, int) +__inline_mathop(__expm1, etoxm1) +__inline_mathop(__log1p, lognp1) +#endif + +#ifdef __USE_MISC +__inline_mathop(__significand, getman) +#endif + +#ifdef __USE_ISOC99 +__inline_mathop(__trunc, intrz) +#endif + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +__inline_mathop(atan, atan) +__inline_mathop(cos, cos) +__inline_mathop(sin, sin) +__inline_mathop(tan, tan) +__inline_mathop(tanh, tanh) + +# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__inline_mathop(rint, int) +__inline_mathop(expm1, etoxm1) +__inline_mathop(log1p, lognp1) +# endif + +# ifdef __USE_MISC +__inline_mathop(significand, getman) +# endif + +# ifdef __USE_ISOC99 +__inline_mathop(trunc, intrz) +# endif + +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +/* This macro contains the definition for the rest of the inline + functions, using FLOAT_TYPE as the domain type and S as the suffix + for the function names. */ + +#define __inline_functions(float_type, s) \ +__m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Set rounding towards negative infinity. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \ + /* Convert X to an integer, using -Inf rounding. */ \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + /* Restore the previous rounding mode. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} \ + \ +__m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Set rounding towards positive infinity. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg | 0x30)); \ + /* Convert X to an integer, using +Inf rounding. */ \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + /* Restore the previous rounding mode. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} + +__inline_functions(double,) +#if defined __USE_MISC || defined __USE_ISOC99 +__inline_functions(float,f) +__inline_functions(long double,l) +#endif +#undef __inline_functions + +#ifdef __USE_MISC + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for infinity, \ + so we must extract and examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \ +} \ + \ +__m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for infinity, so we must extract and \ + examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__ ("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr & (3 << 24)) == 0; \ +} \ + \ +__m81_defun (float_type, __CONCAT(__scalbn,s), \ + (float_type __x, int __n)) \ +{ \ + float_type __result; \ + __asm__ ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x)); \ + return __result; \ +} + +__inline_functions(double,) +__inline_functions(float,f) +__inline_functions(long double,l) +# undef __inline_functions + +#endif /* Use misc. */ + +#if defined __USE_MISC || defined __USE_XOPEN + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) \ +{ \ + char __result; \ + __asm__("ftst%.x %1\n" \ + "fsun %0" : "=dm" (__result) : "f" (__value)); \ + return __result; \ +} + +__inline_functions(double,) +# ifdef __USE_MISC +__inline_functions(float,f) +__inline_functions(long double,l) +# endif +# undef __inline_functions + +#endif + +#ifdef __USE_ISOC99 + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for the sign bit, so we must extract \ + and examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__ ("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr >> 27) & 1; \ +} \ + \ + __m81_defun (float_type, __CONCAT(__scalbln,s), \ + (float_type __x, long int __n)) \ +{ \ + return __CONCAT(__scalbn,s) (__x, __n); \ +} \ + \ +__m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Temporarily disable the inexact exception. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg & ~0x200)); \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} \ + \ +__m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \ +{ \ + long int __result; \ + __asm__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \ + return __result; \ +} \ + \ +__m81_inline float_type \ +__m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y, \ + float_type __z) \ +{ \ + return (__x * __y) + __z; \ +} + +__inline_functions (double,) +__inline_functions (float,f) +__inline_functions (long double,l) +# undef __inline_functions + +#endif /* Use ISO C9x */ + +#ifdef __USE_GNU + +# define __inline_functions(float_type, s) \ +__m81_inline void \ +__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \ + float_type *__cosx) \ +{ \ + __asm__ ("fsincos%.x %2,%1:%0" \ + : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \ +} + +__inline_functions (double,) +__inline_functions (float,f) +__inline_functions (long double,l) +# undef __inline_functions + +#endif + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +/* Define inline versions of the user visible functions. */ + +/* Note that there must be no whitespace before the argument passed for + NAME, to make token pasting work correctly with -traditional. */ +# define __inline_forward_c(rettype, name, args1, args2) \ +extern __inline rettype __attribute__((__const__)) \ + name args1 \ +{ \ + return __CONCAT(__,name) args2; \ +} + +# define __inline_forward(rettype, name, args1, args2) \ +extern __inline rettype name args1 \ +{ \ + return __CONCAT(__,name) args2; \ +} + +__inline_forward_c(double,floor, (double __x), (__x)) +__inline_forward_c(double,ceil, (double __x), (__x)) +# ifdef __USE_MISC +# ifndef __USE_ISOC99 /* Conflict with macro of same name. */ +__inline_forward_c(int,isinf, (double __value), (__value)) +# endif +__inline_forward_c(int,finite, (double __value), (__value)) +__inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n)) +# endif +# if defined __USE_MISC || defined __USE_XOPEN +# ifndef __USE_ISOC99 /* Conflict with macro of same name. */ +__inline_forward_c(int,isnan, (double __value), (__value)) +# endif +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n)) +__inline_forward_c(double,nearbyint, (double __value), (__value)) +__inline_forward_c(long int,lrint, (double __value), (__value)) +__inline_forward_c(double,fma, (double __x, double __y, double __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx), + (__x, __sinx, __cosx)) +# endif + +# if defined __USE_MISC || defined __USE_ISOC99 + +__inline_forward_c(float,floorf, (float __x), (__x)) +__inline_forward_c(float,ceilf, (float __x), (__x)) +# ifdef __USE_MISC +__inline_forward_c(int,isinff, (float __value), (__value)) +__inline_forward_c(int,finitef, (float __value), (__value)) +__inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n)) +__inline_forward_c(int,isnanf, (float __value), (__value)) +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n)) +__inline_forward_c(float,nearbyintf, (float __value), (__value)) +__inline_forward_c(long int,lrintf, (float __value), (__value)) +__inline_forward_c(float,fmaf, (float __x, float __y, float __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx), + (__x, __sinx, __cosx)) +# endif + +__inline_forward_c(long double,floorl, (long double __x), (__x)) +__inline_forward_c(long double,ceill, (long double __x), (__x)) +# ifdef __USE_MISC +__inline_forward_c(int,isinfl, (long double __value), (__value)) +__inline_forward_c(int,finitel, (long double __value), (__value)) +__inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n)) +__inline_forward_c(int,isnanl, (long double __value), (__value)) +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(long double,scalblnl, (long double __x, long int __n), + (__x, __n)) +__inline_forward_c(long double,nearbyintl, (long double __value), (__value)) +__inline_forward_c(long int,lrintl, (long double __value), (__value)) +__inline_forward_c(long double,fmal, + (long double __x, long double __y, long double __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincosl, + (long double __x, long double *__sinx, long double *__cosx), + (__x, __sinx, __cosx)) +# endif + +#endif /* Use misc or ISO C99 */ + +#undef __inline_forward +#undef __inline_forward_c + +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +#endif +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/m68k/bits/mman.h b/libc/sysdeps/linux/m68k/bits/mman.h new file mode 100644 index 0000000..fbec1a0 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/mman.h @@ -0,0 +1,102 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/m68k/bits/poll.h b/libc/sysdeps/linux/m68k/bits/poll.h new file mode 100644 index 0000000..f7a7393 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/m68k/bits/setjmp.h b/libc/sysdeps/linux/m68k/bits/setjmp.h new file mode 100644 index 0000000..a6b0ed0 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/setjmp.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2002, David McCullough */ +/* Copyright (C) 1997,1998,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. m68k version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +typedef struct + { + /* There are eight 4-byte data registers, but D0 is not saved. */ + long int __dregs[7]; + + /* There are six 4-byte address registers, plus the FP and SP. */ + int *__aregs[6]; + int *__fp; + int *__sp; + +#if defined __HAVE_68881__ || defined __HAVE_FPU__ + /* There are eight floating point registers which + are saved in IEEE 96-bit extended format. */ + char __fpregs[8 * (96 / 8)]; +#endif + + } __jmp_buf[1]; + +#endif + +#define JB_REGS 0 +#define JB_DREGS 0 +#define JB_AREGS 24 +#define JB_PC 48 +#define JB_FPREGS 52 + +#if defined __HAVE_68881__ || defined __HAVE_FPU__ +# define JB_SIZE 76 +#else +# define JB_SIZE 52 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__aregs[5]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h b/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h new file mode 100644 index 0000000..b7e08cf --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/m68k/bits/stackinfo.h b/libc/sysdeps/linux/m68k/bits/stackinfo.h new file mode 100644 index 0000000..66e5a17 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On m68k the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/m68k/bits/stat.h b/libc/sysdeps/linux/m68k/bits/stat.h new file mode 100644 index 0000000..a0fefbe --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/stat.h @@ -0,0 +1,164 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/m68k/bits/syscalls.h b/libc/sysdeps/linux/m68k/bits/syscalls.h new file mode 100644 index 0000000..d1ade80 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/syscalls.h @@ -0,0 +1,199 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* m68k headers does stupid stuff with __NR_iopl / __NR_vm86: + * #define __NR_iopl not supported + * #define __NR_vm86 not supported + */ +#undef __NR_iopl +#undef __NR_vm86 + +#ifndef __ASSEMBLER__ + +#include + +/* Linux takes system call arguments in registers: + + syscall number %d0 call-clobbered + arg 1 %d1 call-clobbered + arg 2 %d2 call-saved + arg 3 %d3 call-saved + arg 4 %d4 call-saved + arg 5 %d5 call-saved + + The stack layout upon entering the function is: + + 20(%sp) Arg# 5 + 16(%sp) Arg# 4 + 12(%sp) Arg# 3 + 8(%sp) Arg# 2 + 4(%sp) Arg# 1 + (%sp) Return address + + (Of course a function with say 3 arguments does not have entries for + arguments 4 and 5.) + + Separate move's are faster than movem, but need more space. Since + speed is more important, we don't use movem. Since %a0 and %a1 are + scratch registers, we can use them for saving as well. */ + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + /* avoid using res which is declared to be in register d0; \ + errno might expand to a function call and clobber it. */ \ + int __err = -(res); \ + __set_errno(__err); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type, name) \ +type name(void) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name) \ + : "memory", "cc", "%d0"); \ + __syscall_return(type, __res); \ +} + +#define _syscall1(type, name, atype, a) \ +type name(atype a) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "g" ((long)a) \ + : "memory", "cc", "%d0", "%d1"); \ + __syscall_return(type, __res); \ +} + +#define _syscall2(type, name, atype, a, btype, b) \ +type name(atype a, btype b) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %3, %%d2\n\t" \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "a" ((long)a), \ + "g" ((long)b) \ + : "memory", "cc", "%d0", "%d1", "%d2"); \ + __syscall_return(type, __res); \ +} + +#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %4, %%d3\n\t" \ + "movel %3, %%d2\n\t" \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "a" ((long)a), \ + "a" ((long)b), \ + "g" ((long)c) \ + : "memory", "cc", "%d0", "%d1", "%d2", "%d3"); \ + __syscall_return(type, __res); \ +} + +#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c, dtype d) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %5, %%d4\n\t" \ + "movel %4, %%d3\n\t" \ + "movel %3, %%d2\n\t" \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "a" ((long)a), \ + "a" ((long)b), \ + "a" ((long)c), \ + "g" ((long)d) \ + : "memory", "cc", "%d0", "%d1", "%d2", "%d3", \ + "%d4"); \ + __syscall_return(type, __res); \ +} + +#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c, dtype d, etype e) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %6, %%d5\n\t" \ + "movel %5, %%d4\n\t" \ + "movel %4, %%d3\n\t" \ + "movel %3, %%d2\n\t" \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "a" ((long)a), \ + "a" ((long)b), \ + "a" ((long)c), \ + "a" ((long)d), \ + "g" ((long)e) \ + : "memory", "cc", "%d0", "%d1", "%d2", "%d3", \ + "%d4", "%d5"); \ + __syscall_return(type, __res); \ +} + +#define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \ +{ \ + long __res; \ + __asm__ __volatile__ ( \ + "movel %7, %%a0\n\t" \ + "movel %6, %%d5\n\t" \ + "movel %5, %%d4\n\t" \ + "movel %4, %%d3\n\t" \ + "movel %3, %%d2\n\t" \ + "movel %2, %%d1\n\t" \ + "movel %1, %%d0\n\t" \ + "trap #0\n\t" \ + "movel %%d0, %0" \ + : "=g" (__res) \ + : "i" (__NR_##name), \ + "a" ((long)a), \ + "a" ((long)b), \ + "a" ((long)c), \ + "a" ((long)d), \ + "g" ((long)e), \ + "g" ((long)f) \ + : "memory", "cc", "%d0", "%d1", "%d2", "%d3", \ + "%d4", "%d5", "%a0"); \ + __syscall_return(type, __res); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h b/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h new file mode 100644 index 0000000..b5ef48f --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h @@ -0,0 +1,45 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#if defined(__mc68000__) +# define __UCLIBC_ABORT_INSTRUCTION__ ".long 0xffffffff" +#else /* defined(__m68k__) */ +# define __UCLIBC_ABORT_INSTRUCTION__ "illegal" +#endif + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#define __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/m68k/bits/uClibc_page.h b/libc/sysdeps/linux/m68k/bits/uClibc_page.h new file mode 100644 index 0000000..51c6f14 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/uClibc_page.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* +#include +*/ + +/* PAGE_SHIFT determines the page size */ + +/* +#ifndef CONFIG_SUN3 +*/ +#define PAGE_SHIFT (12) +/* +#else +#define PAGE_SHIFT (13) +#endif +*/ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/m68k/bits/wordsize.h b/libc/sysdeps/linux/m68k/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/m68k/brk.c b/libc/sysdeps/linux/m68k/brk.c new file mode 100644 index 0000000..7daf1bd --- /dev/null +++ b/libc/sysdeps/linux/m68k/brk.c @@ -0,0 +1,38 @@ +/* consider this code LGPL - davidm */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(brk) + +/* This must be initialized data because commons can't have aliases. */ +void * __curbrk = 0; + +int brk (void *addr) +{ + void *newbrk; + + __asm__ __volatile__ ("movel %2,%/d1\n\t" + "moveq %1,%/d0\n\t" + "trap #0\n\t" + "movel %/d0,%0" + :"=g" (newbrk) + :"i" (__NR_brk),"g" (addr) : "%d0", "%d1"); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/m68k/bsd-_setjmp.S b/libc/sysdeps/linux/m68k/bsd-_setjmp.S new file mode 100644 index 0000000..0380c3d --- /dev/null +++ b/libc/sysdeps/linux/m68k/bsd-_setjmp.S @@ -0,0 +1,24 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include + +.globl _setjmp; +.type _setjmp,@function +.align 4; + +_setjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + movl %d0, JB_SIZE(%a0) /* No signal mask set. */ + rts + + diff --git a/libc/sysdeps/linux/m68k/bsd-setjmp.S b/libc/sysdeps/linux/m68k/bsd-setjmp.S new file mode 100644 index 0000000..fdd7540 --- /dev/null +++ b/libc/sysdeps/linux/m68k/bsd-setjmp.S @@ -0,0 +1,23 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include "m68k_pic.S" + +.globl setjmp; +.type setjmp,@function +.align 4; + +setjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + JUMP __sigjmp_save,%a0 + diff --git a/libc/sysdeps/linux/m68k/clone.S b/libc/sysdeps/linux/m68k/clone.S new file mode 100644 index 0000000..7eddff1 --- /dev/null +++ b/libc/sysdeps/linux/m68k/clone.S @@ -0,0 +1,69 @@ +/* Adapted from glibc */ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include +#include +#include "m68k_pic.S" + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.align 4 +.type clone,@function +.globl clone; +clone: + /* Sanity check arguments. */ + movel #-EINVAL, %d0 + movel 4(%sp), %d1 /* no NULL function pointers */ + movel %d1, %a0 + tstl %d1 + beq.w __syscall_error_trampoline + movel 8(%sp), %d1 /* no NULL stack pointers */ + movel %d1, %a1 + tstl %d1 + beq.w __syscall_error_trampoline + + /* Allocate space and copy the argument onto the new stack. */ + movel 16(%sp), -(%a1) + + /* Do the system call */ +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* save %d2 and get stack pointer */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* save %d2 and get stack pointer */ +#endif + movel 12(%sp), %d1 /* get flags */ + movel #__NR_clone, %d0 + trap #0 +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* restore %d2 */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* restore %d2 */ +#endif + + tstl %d0 + bmi.w __syscall_error_trampoline + beq.w thread_start + + rts + +thread_start: + /*subl %fp, %fp*/ /* terminate the stack frame */ + jsr (%a0) + movel %d0, -(%sp) + movel #__NR_exit, %d0 + trap #0 + /*jsr exit*/ + +__syscall_error_trampoline: + JUMP __syscall_error,%a0 + diff --git a/libc/sysdeps/linux/m68k/crt1.S b/libc/sysdeps/linux/m68k/crt1.S new file mode 100644 index 0000000..a9cf001 --- /dev/null +++ b/libc/sysdeps/linux/m68k/crt1.S @@ -0,0 +1,152 @@ +/* Startup code compliant to the ELF m68k ABI. + Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "m68k_pic.S" + +#ifndef L_Scrt1 +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/m68k ABI says that when the entry point runs, + most registers' values are unspecified, except for: + + %a1 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %sp The stack contains the arguments and environment: + 0(%sp) argc + 4(%sp) argv[0] + ... + (4*argc)(%sp) NULL + (4*(argc+1))(%sp) envp[0] + ... + NULL + + The uclinux conventions are different. %a1 is not defined on entry + and the stack is laid out as follows: + + 0(%sp) argc + 4(%sp) argv + 8(%sp) envp +*/ + + .text + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .globl _start + .type _start,@function +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + sub.l %fp, %fp + +#if !defined __ARCH_USE_MMU__ && defined __PIC__ + /* Set up the global pointer. The GOT is at the beginning of the + data segment, whose address is in %d5. */ + move.l %d5,%a5 + .equ have_current_got, 1 +#endif + +#ifdef __UCLIBC_FORMAT_SHARED_FLAT__ + CALL __shared_flat_add_library,%a1 +#endif + + /* Extract the arguments as encoded on the stack and set up the + arguments for `main': argc, argv. envp will be determined + later in __libc_start_main. */ + move.l (%sp)+, %d0 /* Pop the argument count. */ +#ifndef __ARCH_USE_MMU__ + move.l (%sp)+, %a0 +#else + move.l %sp, %a0 /* The argument vector starts just at the + current stack top. */ +#endif + + /* Provide the highest stack address to the user code (for stacks + which grow downward). */ + pea (%sp) + +#ifndef __ARCH_USE_MMU__ + clr.l -(%sp) +#else + pea (%a1) /* Push address of the shared library + termination function. */ +#endif + + /* Push the address of our own entry points to `.fini' and + `.init'. */ +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + PEA_TEXT __shared_flat_fini,%a1 + PEA_TEXT __shared_flat_init,%a1 +#else + PEA_TEXT _fini,%a1 + PEA_TEXT _init,%a1 +#endif + + pea (%a0) /* Push second argument: argv. */ + move.l %d0, -(%sp) /* Push first argument: argc. */ + + PEA_TEXT main,%a1 + + /* Call the user's main function, and exit with its value. But + let the libc call main. */ + CALL __uClibc_main,%a1 + + illegal /* Crash if somehow `exit' does return. */ +#else + .text + .globl lib_main + .hidden lib_main + .type lib_main,@function +lib_main: + move.l %d5,%a5 + JUMP __shared_flat_add_library,%a0 + + .hidden _current_shared_library_a5_offset_ +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/m68k/crti.S b/libc/sysdeps/linux/m68k/crti.S new file mode 100644 index 0000000..1b4b643 --- /dev/null +++ b/libc/sysdeps/linux/m68k/crti.S @@ -0,0 +1,17 @@ +#include "m68k_pic.S" + + .section .init + .align 2 + .globl _init + .type _init, @function +_init: + link.w %a6,#0 + INIT_GP + + .section .fini + .align 2 + .globl _fini + .type _fini, @function +_fini: + link.w %a6,#0 + INIT_GP diff --git a/libc/sysdeps/linux/m68k/crtn.S b/libc/sysdeps/linux/m68k/crtn.S new file mode 100644 index 0000000..2a29b87 --- /dev/null +++ b/libc/sysdeps/linux/m68k/crtn.S @@ -0,0 +1,11 @@ +#include "m68k_pic.S" + + .section .init + FINI_GP + unlk %a6 + rts + + .section .fini + FINI_GP + unlk %a6 + rts diff --git a/libc/sysdeps/linux/m68k/float.h b/libc/sysdeps/linux/m68k/float.h new file mode 100644 index 0000000..7dbe4e9 --- /dev/null +++ b/libc/sysdeps/linux/m68k/float.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/libc/sysdeps/linux/m68k/fpu_control.h b/libc/sysdeps/linux/m68k/fpu_control.h new file mode 100644 index 0000000..040e62c --- /dev/null +++ b/libc/sysdeps/linux/m68k/fpu_control.h @@ -0,0 +1,103 @@ +/* 68k FPU control word definitions. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* + * Motorola floating point control register bits. + * + * 31-16 -> reserved (read as 0, ignored on write) + * 15 -> enable trap for BSUN exception + * 14 -> enable trap for SNAN exception + * 13 -> enable trap for OPERR exception + * 12 -> enable trap for OVFL exception + * 11 -> enable trap for UNFL exception + * 10 -> enable trap for DZ exception + * 9 -> enable trap for INEX2 exception + * 8 -> enable trap for INEX1 exception + * 7-6 -> Precision Control + * 5-4 -> Rounding Control + * 3-0 -> zero (read as 0, write as 0) + * + * + * Precision Control: + * 00 - round to extended precision + * 01 - round to single precision + * 10 - round to double precision + * 11 - undefined + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (down)toward minus infinity (RM) + * 11 - rounding (up) toward plus infinity (RP) + * + * The hardware default is 0x0000. I choose 0x5400. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_BSUN 0x8000 +#define _FPU_MASK_SNAN 0x4000 +#define _FPU_MASK_OPERR 0x2000 +#define _FPU_MASK_OVFL 0x1000 +#define _FPU_MASK_UNFL 0x0800 +#define _FPU_MASK_DZ 0x0400 +#define _FPU_MASK_INEX1 0x0200 +#define _FPU_MASK_INEX2 0x0100 + +/* precision control */ +#define _FPU_EXTENDED 0x00 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x80 +#define _FPU_SINGLE 0x40 /* DO NOT USE */ + +/* rounding control */ +#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x10 +#define _FPU_RC_DOWN 0x20 +#define _FPU_RC_UP 0x30 + +#define _FPU_RESERVED 0xFFFF000F /* Reserved bits in fpucr */ + + +/* Now two recommended fpucr */ + +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions. We must make it non-zero so + that __setfpucw works. This bit will be ignored. */ +#define _FPU_IEEE 0x00000001 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("fmove%.l %0, %!" : : "dm" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _M68K_FPU_CONTROL_H */ diff --git a/libc/sysdeps/linux/m68k/m68k_pic.S b/libc/sysdeps/linux/m68k/m68k_pic.S new file mode 100644 index 0000000..d41509e --- /dev/null +++ b/libc/sysdeps/linux/m68k/m68k_pic.S @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines some m68k assembly macros for handling the differences + * between PIC and non-PIC. + */ +#include + + /* When assembling code for shared flat libraries, this is nonzero + * if %a5 points the current library's GOT. */ + .equ have_current_got, 0 + + /* Perform the equivalent of " ", where is + * a text address. is available as a temporary address + * register. */ + .macro DO_TEXT op,target,tmp +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + .ifne have_current_got + move.l \target@GOT(%a5),\tmp + .else + move.l _current_shared_library_a5_offset_(%a5),\tmp + move.l \target@GOT(\tmp),\tmp + .endif + \op (\tmp) +#elif defined __PIC__ + lea \target-.-8,\tmp + \op (%pc,\tmp) +#else + \op \target +#endif + .endm + + /* Do "pea " when is a text address. + * is available as a temporary register. */ + .macro PEA_TEXT target,tmp + DO_TEXT pea,\target,\tmp + .endm + + /* Likewise jsr. */ + .macro CALL target,tmp + DO_TEXT jsr,\target,\tmp + .endm + + /* Likewise jmp. */ + .macro JUMP target,tmp + DO_TEXT jmp,\target,\tmp + .endm + + /* Initialize the global pointer, if functions need to do that. */ + .macro INIT_GP +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + move.l %a5,-(%sp) + move.l _current_shared_library_a5_offset_(%a5),%a5 +#endif + .endm + + /* Undo the effects of INIT_GP. */ + .macro FINI_GP +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + move.l (%sp)+,%a5 +#endif + .endm diff --git a/libc/sysdeps/linux/m68k/setjmp.S b/libc/sysdeps/linux/m68k/setjmp.S new file mode 100644 index 0000000..4adda0a --- /dev/null +++ b/libc/sysdeps/linux/m68k/setjmp.S @@ -0,0 +1,23 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include "m68k_pic.S" + +.globl __sigsetjmp; +.type __sigsetjmp,@function +.align 4; + +__sigsetjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + JUMP __sigjmp_save,%a0 + diff --git a/libc/sysdeps/linux/m68k/sys/procfs.h b/libc/sysdeps/linux/m68k/sys/procfs.h new file mode 100644 index 0000000..27abf8e --- /dev/null +++ b/libc/sysdeps/linux/m68k/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/m68k/sys/reg.h b/libc/sysdeps/linux/m68k/sys/reg.h new file mode 100644 index 0000000..418f832 --- /dev/null +++ b/libc/sysdeps/linux/m68k/sys/reg.h @@ -0,0 +1,89 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +enum +{ + PT_D1 = 0, +#define PT_D1 PT_D1 + PT_D2 = 1, +#define PT_D2 PT_D2 + PT_D3 = 2, +#define PT_D3 PT_D3 + PT_D4 = 3, +#define PT_D4 PT_D4 + PT_D5 = 4, +#define PT_D5 PT_D5 + PT_D6 = 5, +#define PT_D6 PT_D6 + PT_D7 = 6, +#define PT_D7 PT_D7 + PT_A0 = 7, +#define PT_A0 PT_A0 + PT_A1 = 8, +#define PT_A1 PT_A1 + PT_A2 = 9, +#define PT_A2 PT_A2 + PT_A3 = 10, +#define PT_A3 PT_A3 + PT_A4 = 11, +#define PT_A4 PT_A4 + PT_A5 = 12, +#define PT_A5 PT_A5 + PT_A6 = 13, +#define PT_A6 PT_A6 + PT_D0 = 14, +#define PT_D0 PT_D0 + PT_USP = 15, +#define PT_USP PT_USP + PT_ORIG_D0 = 16, +#define PT_ORIG_D0 PT_ORIG_D0 + PT_SR = 17, +#define PT_SR PT_SR + PT_PC = 18, +#define PT_PC PT_PC + PT_FP0 = 21, +#define PT_FP0 PT_FP0 + PT_FP1 = 24, +#define PT_FP1 PT_FP1 + PT_FP2 = 27, +#define PT_FP2 PT_FP2 + PT_FP3 = 30, +#define PT_FP3 PT_FP3 + PT_FP4 = 33, +#define PT_FP4 PT_FP4 + PT_FP5 = 36, +#define PT_FP5 PT_FP5 + PT_FP6 = 39, +#define PT_FP6 PT_FP6 + PT_FP7 = 42, +#define PT_FP7 PT_FP7 + PT_FPCR = 45, +#define PT_FPCR PT_FPCR + PT_FPSR = 46, +#define PT_FPSR PT_FPSR + PT_FPIAR = 47 +#define PT_FPIAR PT_FPIAR +}; + +#endif /* _SYS_REG_H */ diff --git a/libc/sysdeps/linux/m68k/sys/ucontext.h b/libc/sysdeps/linux/m68k/sys/ucontext.h new file mode 100644 index 0000000..3c441dc --- /dev/null +++ b/libc/sysdeps/linux/m68k/sys/ucontext.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/m68k ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R_D0 = 0, +#define R_D0 R_D0 + R_D1 = 1, +#define R_D1 R_D1 + R_D2 = 2, +#define R_D2 R_D2 + R_D3 = 3, +#define R_D3 R_D3 + R_D4 = 4, +#define R_D4 R_D4 + R_D5 = 5, +#define R_D5 R_D5 + R_D6 = 6, +#define R_D6 R_D6 + R_D7 = 7, +#define R_D7 R_D7 + R_A0 = 8, +#define R_A0 R_A0 + R_A1 = 9, +#define R_A1 R_A1 + R_A2 = 10, +#define R_A2 R_A2 + R_A3 = 11, +#define R_A3 R_A3 + R_A4 = 12, +#define R_A4 R_A4 + R_A5 = 13, +#define R_A5 R_A5 + R_A6 = 14, +#define R_A6 R_A6 + R_A7 = 15, +#define R_A7 R_A7 + R_SP = 15, +#define R_SP R_SP + R_PC = 16, +#define R_PC R_PC + R_PS = 17 +#define R_PS R_PS +}; + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int f_fpregs[8][3]; + int f_pcr; + int f_psr; + int f_fpiaddr; +} fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + int version; + gregset_t gregs; + fpregset_t fpregs; +} mcontext_t; + +#define MCONTEXT_VERSION 2 + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + long int uc_filler[174]; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/m68k/sys/user.h b/libc/sysdeps/linux/m68k/sys/user.h new file mode 100644 index 0000000..8114a2b --- /dev/null +++ b/libc/sysdeps/linux/m68k/sys/user.h @@ -0,0 +1,90 @@ +#ifndef _M68K_USER_H +#define _M68K_USER_H +/* + This file was taken verbatim from linux-2.6.26.5. + The linux kernel is Copyright (C) Linus Torvalds et al. + and is licensed under the GNU General Public License, version 2. +*/ +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a meaningful + backtrace. We need to write the data from (esp) to + current->start_stack, so we round each of these off in order to be able + to write an integer number of pages. + The minimum core file size is 3 pages, or 12288 bytes. +*/ + +struct user_m68kfp_struct { + unsigned long fpregs[8*3]; /* fp0-fp7 registers */ + unsigned long fpcntl[3]; /* fp control regs */ +}; + +/* This is the old layout of "struct pt_regs" as of Linux 1.x, and + is still the layout used by user (the new pt_regs doesn't have + all registers). */ +struct user_regs_struct { + long d1,d2,d3,d4,d5,d6,d7; + long a0,a1,a2,a3,a4,a5,a6; + long d0; + long usp; + long orig_d0; + short stkadj; + short sr; + long pc; + short fmtvec; + short __fill; +}; + + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ +struct user{ +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + struct user_regs_struct regs; /* Where the registers are actually stored */ +/* ptrace does not yet supply these. Someday.... */ + int u_fpvalid; /* True if math co-processor being used. */ + /* for this mess. Not yet used. */ + struct user_m68kfp_struct m68kfp; /* Math Co-processor registers. */ +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + unsigned long u_ar0; /* Used by gdb to help find the values for */ + /* the registers. */ + struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ +}; +#define NBPG 4096 +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif diff --git a/libc/sysdeps/linux/m68k/syscall.c b/libc/sysdeps/linux/m68k/syscall.c new file mode 100644 index 0000000..5b13ea6 --- /dev/null +++ b/libc/sysdeps/linux/m68k/syscall.c @@ -0,0 +1,47 @@ +/* syscall for m68k/uClibc + * + * Copyright (C) 2005-2006 by Christian Magnusson + * Copyright (C) 2005-2006 Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f); +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ + long __res; + __asm__ __volatile__ ( + "movel %7, %%a0\n\t" + "movel %6, %%d5\n\t" + "movel %5, %%d4\n\t" + "movel %4, %%d3\n\t" + "movel %3, %%d2\n\t" + "movel %2, %%d1\n\t" + "movel %1, %%d0\n\t" + "trap #0\n\t" + "movel %%d0, %0" + : "=g" (__res) + : "g" (sysnum), + "g" ((long)a), "g" ((long)b), "g" ((long)c), + "g" ((long)d), "g" ((long)e), "g" ((long)f) + : "memory", "cc", "%d0", "%d1", "%d2", "%d3", + "%d4", "%d5", "%a0"); + __syscall_return(long,__res); +} diff --git a/libc/sysdeps/linux/m68k/vfork.S b/libc/sysdeps/linux/m68k/vfork.S new file mode 100644 index 0000000..56d57f7 --- /dev/null +++ b/libc/sysdeps/linux/m68k/vfork.S @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +#define IMM # + + .text + .align 2 + .globl errno + .globl __vfork + .hidden __vfork + .type __vfork,@function + +__vfork: + movl %sp@+, %a1 /* save the return address for later */ + movl IMM __NR_vfork,%d0 + trap #0 + movl IMM -4097, %d1 + cmpl %d0, %d1 + bcs fix_errno + jmp %a1@ /* don't return, just jmp directly */ +fix_errno: + negl %d0 +#ifndef __PIC__ /* needs handling as the other archs */ + movl errno, %a0 +#else + movl errno@GOT(%a5), %a0 +#endif + movl %d0, %a0@ + movl IMM -1, %d0 + jmp %a1@ /* don't return, just jmp directly */ + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/microblaze/Makefile b/libc/sysdeps/linux/microblaze/Makefile new file mode 100644 index 0000000..a7a832b --- /dev/null +++ b/libc/sysdeps/linux/microblaze/Makefile @@ -0,0 +1,67 @@ +# Makefile for uClibc +# +# Copyright (C) 2001,2002 NEC Corporation +# Copyright (C) 2001,2002 Miles Bader +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +CFLAGS += -I.. +ASFLAGS += -I.. -D__ASSEMBLER -DASM_GLOBAL_DIRECTIVE=.globl + +TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine) + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := setjmp.S __longjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC := mmap.c syscall.c clone.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/microblaze/__longjmp.S b/libc/sysdeps/linux/microblaze/__longjmp.S new file mode 100644 index 0000000..2752f0b --- /dev/null +++ b/libc/sysdeps/linux/microblaze/__longjmp.S @@ -0,0 +1,45 @@ +/* + * libc/sysdeps/linux/microblaze/longjmp.S -- `longjmp' for microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(__longjmp): + /* load registers from memory to r5 (arg0) */ + lwi r1, r5, 0 + lwi r15, r5, 4 + lwi r18, r5, 8 + lwi r19, r5, 12 + lwi r20, r5, 16 + lwi r21, r5, 20 + lwi r22, r5, 24 + lwi r23, r5, 28 + lwi r24, r5, 32 + lwi r25, r5, 36 + lwi r26, r5, 40 + lwi r27, r5, 44 + lwi r28, r5, 48 + lwi r29, r5, 52 + lwi r30, r5, 56 + + addi r3, r0, 1 /* return val */ + rtsd r15, 8 /* normal return */ + nop + +C_END(__longjmp) +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/microblaze/bits/byteswap.h b/libc/sysdeps/linux/microblaze/bits/byteswap.h new file mode 100644 index 0000000..9b6a5d7 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/byteswap.h @@ -0,0 +1,41 @@ +/* + * libc/sysdeps/linux/microblaze/bits/byteswap.h -- Macros to swap the order + * of bytes in integer values + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997,1998,2001 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +# define __bswap_16(x) __bswap_constant_16 (x) + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +# define __bswap_32(x) __bswap_constant_32 (x) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + (__extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __bswap_64_v, __bswap_64_r; \ + __bswap_64_v.__ll = (x); \ + __bswap_64_r.__l[0] = __bswap_32 (__bswap_64_v.__l[1]); \ + __bswap_64_r.__l[1] = __bswap_32 (__bswap_64_v.__l[0]); \ + __bswap_64_r.__ll; })) +#endif diff --git a/libc/sysdeps/linux/microblaze/bits/endian.h b/libc/sysdeps/linux/microblaze/bits/endian.h new file mode 100644 index 0000000..8a4f6ef --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/endian.h @@ -0,0 +1,20 @@ +/* + * libc/sysdeps/linux/microblaze/bits/endian.h -- Define processor endianess + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/libc/sysdeps/linux/microblaze/bits/fcntl.h b/libc/sysdeps/linux/microblaze/bits/fcntl.h new file mode 100644 index 0000000..87d1939 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/fcntl.h @@ -0,0 +1,234 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/microblaze/bits/kernel_stat.h b/libc/sysdeps/linux/microblaze/bits/kernel_stat.h new file mode 100644 index 0000000..248345e --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/kernel_stat.h @@ -0,0 +1,66 @@ +/* Stat structure for linux/microblaze*/ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat +{ + __kernel_dev_t st_dev; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + __kernel_off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 +{ + __kernel_dev_t st_dev; + unsigned long __unused0; + unsigned long __unused1; + + __kernel_ino64_t st_ino; + + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + + __kernel_dev_t st_rdev; + unsigned long __unused2; + unsigned long __unused3; + + __kernel_loff_t st_size; + unsigned long st_blksize; + + unsigned long __unused4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long st_atime; + unsigned long __unused5; + + unsigned long st_mtime; + unsigned long __unused6; + + unsigned long st_ctime; + unsigned long __unused7; /* high 32 bits of ctime someday */ +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/microblaze/bits/kernel_types.h b/libc/sysdeps/linux/microblaze/bits/kernel_types.h new file mode 100644 index 0000000..1ca2dae --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/kernel_types.h @@ -0,0 +1,55 @@ +/* + * sysdeps/linux/microblaze/bits/kernel_types.h -- Kernel versions of standard types + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#ifndef __MICROBLAZE_POSIX_TYPES_H__ +#define __MICROBLAZE_POSIX_TYPES_H__ + +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __MICROBLAZE_POSIX_TYPES_H__ */ diff --git a/libc/sysdeps/linux/microblaze/bits/mman.h b/libc/sysdeps/linux/microblaze/bits/mman.h new file mode 100644 index 0000000..d051c8f --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/mman.h @@ -0,0 +1,99 @@ +/* Definitions for POSIX memory map interface. Linux/microblaze version. + Copyright (C) 1997, 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* These are the bits used by 4.4 BSD and its derivatives. On systems + (such as GNU) where these facilities are not system services but can be + emulated in the C library, these are the definitions we emulate. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + + +/* Flags for `mlockall' (can be OR'd together). */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/microblaze/bits/poll.h b/libc/sysdeps/linux/microblaze/bits/poll.h new file mode 100644 index 0000000..f7a7393 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/microblaze/bits/select.h b/libc/sysdeps/linux/microblaze/bits/select.h new file mode 100644 index 0000000..7c787b3 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/select.h @@ -0,0 +1,58 @@ +/* + * include/bits/select.h -- fd_set operations + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997, 1998 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + +#ifdef __GNUC__ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) + +#define __FD_SET(fd, s) \ + do { \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + *__addr |= (1 << __fd); \ + } while (0) + +#define __FD_CLR(fd, s) \ + do { \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + *__addr &= ~(1 << __fd); \ + } while (0) + +#define __FD_ISSET(fd, s) \ + ({ \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + int res; \ + res = (*__addr & (1 << fd)) ? 1 : 0; \ + }) + +#else /* !__GNUC__ */ + +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) + +#endif /* __GNUC__ */ diff --git a/libc/sysdeps/linux/microblaze/bits/setjmp.h b/libc/sysdeps/linux/microblaze/bits/setjmp.h new file mode 100644 index 0000000..d966efd --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/setjmp.h @@ -0,0 +1,43 @@ +/* + * libc/sysdeps/linux/microblaze/bits/setjmp.h -- microblaze version of `jmp_buf' type + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Stack pointer. */ + void *__sp; + + /* Link pointer. */ + void *__lp; + + /* Callee-saved registers r18-r30. */ + int __regs[13]; + } __jmp_buf[1]; +#endif + +#define JB_SIZE (4 * 15) + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/microblaze/bits/syscalls.h b/libc/sysdeps/linux/microblaze/bits/syscalls.h new file mode 100644 index 0000000..b218513 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/syscalls.h @@ -0,0 +1,15 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Do something very evil for now. Until we create our own syscall + * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ +#warning "fixme -- add arch specific syscall macros.h" +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h b/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/microblaze/bits/wordsize.h b/libc/sysdeps/linux/microblaze/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/microblaze/clinkage.h b/libc/sysdeps/linux/microblaze/clinkage.h new file mode 100644 index 0000000..a9beffc --- /dev/null +++ b/libc/sysdeps/linux/microblaze/clinkage.h @@ -0,0 +1,15 @@ +/* + * libc/sysdeps/linux/microblaze/clinkage.h -- Macros for C symbols in assembler + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include diff --git a/libc/sysdeps/linux/microblaze/clone.c b/libc/sysdeps/linux/microblaze/clone.c new file mode 100644 index 0000000..a47ee8c --- /dev/null +++ b/libc/sysdeps/linux/microblaze/clone.c @@ -0,0 +1,52 @@ +/* + * libc/sysdeps/linux/microblaze/clone.c -- `clone' syscall for linux/microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#include +#include + +int +clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg) +{ + register unsigned long rval __asm__ (SYSCALL_RET) = -EINVAL; + + if (fn && child_stack) + { + register unsigned long syscall __asm__ (SYSCALL_NUM); + register unsigned long arg0 __asm__ (SYSCALL_ARG0); + register unsigned long arg1 __asm__ (SYSCALL_ARG1); + + /* Clone this thread. */ + arg0 = flags; + arg1 = (unsigned long)child_stack; + syscall = __NR_clone; + __asm__ __volatile__ ("bralid r17, trap;nop;" + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0), "r" (arg1) + : SYSCALL_CLOBBERS); + + if (rval == 0) + /* In child thread, call FN and exit. */ + { + arg0 = (*fn) (arg); + syscall = __NR_exit; + __asm__ __volatile__ ("bralid r17, trap;nop;" + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0) + : SYSCALL_CLOBBERS); + } + } + + __syscall_return (int, rval); +} diff --git a/libc/sysdeps/linux/microblaze/crt0.S b/libc/sysdeps/linux/microblaze/crt0.S new file mode 100644 index 0000000..591c3a2 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/crt0.S @@ -0,0 +1,56 @@ +/* + * libc/sysdeps/linux/microblaze/crt0.S -- Initial program entry point for linux/microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +/* Upon entry, the stack contains the following data: + argc, argv[0], ..., argv[argc-1], 0, envp[0], ..., 0 +*/ + + .text +C_ENTRY(_start): + lw r5, r0, r1 /* Arg 0: argc */ + + addi r6, r1, 4 /* Arg 1: argv */ + + /* Arg 2: envp */ + addi r3, r5, 1 /* skip argc elements to get envp start */ + /* ...plus the NULL at the end of argv */ + add r3, r3, r3 /* Make word offset */ + add r3, r3, r3 + add r7, r6, r3 /* add to argv to get offset */ + + /* Load SDAs */ + la r2, r0, C_SYMBOL_NAME(_SDA_BASE_) + la r13, r0, C_SYMBOL_NAME(_SDA2_BASE_) + + /* tail-call uclibc's startup routine */ + brid C_SYMBOL_NAME(__uClibc_main) + nop + + +/* Stick in a dummy reference to `main', so that if an application + is linking when the `main' function is in a static library (.a) + we can be sure that `main' actually gets linked in. */ +L_dummy_main_reference: + .long C_SYMBOL_NAME(main) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/microblaze/mmap.c b/libc/sysdeps/linux/microblaze/mmap.c new file mode 100644 index 0000000..9cb43b4 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/mmap.c @@ -0,0 +1,17 @@ +/* Use new style mmap for microblaze */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/microblaze/setjmp.S b/libc/sysdeps/linux/microblaze/setjmp.S new file mode 100644 index 0000000..7068d4b --- /dev/null +++ b/libc/sysdeps/linux/microblaze/setjmp.S @@ -0,0 +1,53 @@ +/* + * libc/sysdeps/linux/microblaze/setjmp.S -- `setjmp' for microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(setjmp): + addi r6, r0, 1 /* Save the signal mask. */ + braid C_SYMBOL_NAME(__sigsetjmp) + nop + + .globl C_SYMBOL_NAME(_setjmp) +C_SYMBOL_NAME(_setjmp): + add r6, r0, r0 /* Don't save the signal mask. */ + + .globl C_SYMBOL_NAME(__sigsetjmp) +C_SYMBOL_NAME(__sigsetjmp): + /* Save registers relative to r5 (arg0)*/ + swi r1, r5, 0 /* stack pointer */ + swi r15, r5, 4 /* link register */ + swi r18, r5, 8 /* assembler temp */ + swi r19, r5, 12 /* now call-preserved regs */ + swi r20, r5, 16 + swi r21, r5, 20 + swi r22, r5, 24 + swi r23, r5, 28 + swi r24, r5, 32 + swi r25, r5, 36 + swi r26, r5, 40 + swi r27, r5, 44 + swi r28, r5, 48 + swi r29, r5, 52 + swi r30, r5, 56 + + /* Make a tail call to __sigjmp_save; it takes the same args. */ + braid C_SYMBOL_NAME(__sigjmp_save) + nop +C_END(setjmp) diff --git a/libc/sysdeps/linux/microblaze/sys/ptrace.h b/libc/sysdeps/linux/microblaze/sys/ptrace.h new file mode 100644 index 0000000..b7a9adf --- /dev/null +++ b/libc/sysdeps/linux/microblaze/sys/ptrace.h @@ -0,0 +1,94 @@ +/* `ptrace' debugger support interface. Linux/microblaze version. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 0x10, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 0x11, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/microblaze/sys/ucontext.h b/libc/sysdeps/linux/microblaze/sys/ucontext.h new file mode 100644 index 0000000..07f0933 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/sys/ucontext.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/microblaze/syscall.c b/libc/sysdeps/linux/microblaze/syscall.c new file mode 100644 index 0000000..0e07e45 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/syscall.c @@ -0,0 +1,51 @@ +/* + * libc/sysdeps/linux/microblaze/syscall.c -- generic syscall function for linux/microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include + +typedef unsigned long arg_t; + +/* Invoke `system call' NUM, passing it the remaining arguments. + This is completely system-dependent, and not often useful. */ +long +syscall (long num, arg_t a1, arg_t a2, arg_t a3, arg_t a4, arg_t a5, arg_t a6) +{ + /* We don't know how many arguments are valid, so A5 and A6 are fetched + off the stack even for (the majority of) system calls with fewer + arguments; hopefully this won't cause any problems. A1-A4 are in + registers, so they're OK. */ + register arg_t a __asm__ (SYSCALL_ARG0) = a1; + register arg_t b __asm__ (SYSCALL_ARG1) = a2; + register arg_t c __asm__ (SYSCALL_ARG2) = a3; + register arg_t d __asm__ (SYSCALL_ARG3) = a4; + register arg_t e __asm__ (SYSCALL_ARG4) = a5; + register arg_t f __asm__ (SYSCALL_ARG5) = a6; + register unsigned long syscall __asm__ (SYSCALL_NUM) = num; + register unsigned long ret __asm__ (SYSCALL_RET); + unsigned long ret_sav; + + *((unsigned long *)0xFFFF4004) = (unsigned int)('+'); + __asm__ ("brlid r17, 08x; nop;" + : "=r" (ret) + : "r" (syscall), "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f) + : SYSCALL_CLOBBERS); + + ret_sav=ret; + *((unsigned long *)0xFFFF4004) = (unsigned int)('-'); + + + + __syscall_return (long, ret); +} diff --git a/libc/sysdeps/linux/microblaze/vfork.S b/libc/sysdeps/linux/microblaze/vfork.S new file mode 100644 index 0000000..4245830 --- /dev/null +++ b/libc/sysdeps/linux/microblaze/vfork.S @@ -0,0 +1,44 @@ +/* + * libc/sysdeps/linux/microblaze/vfork.S -- `vfork' syscall for linux/microblaze + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 2003 John Williams + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#define _ERRNO_H 1 +#include +#define _SYSCALL_H +#include + +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.global C_SYMBOL_NAME(errno) + +C_ENTRY (__vfork): + addi r12, r0, SYS_vfork + bralid r17, 0x08; + nop + addi r4, r3, 125 /* minimum err value */ + blti r4, 1f /* is r3 < -125? */ + rtsd r15, 8 /* normal return */ + nop +1: sub r3, r3, r0 /* r3 = -r3 */ + swi r3, r0, C_SYMBOL_NAME(errno); + rtsd r15, 8 /* error return */ + nop +C_END(__vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/mips/Makefile b/libc/sysdeps/linux/mips/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/mips/Makefile.arch b/libc/sysdeps/linux/mips/Makefile.arch new file mode 100644 index 0000000..da5ca1e --- /dev/null +++ b/libc/sysdeps/linux/mips/Makefile.arch @@ -0,0 +1,18 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := \ + __longjmp.c brk.c setjmp_aux.c mmap.c __syscall_error.c \ + cacheflush.c pread_write.c sysmips.c _test_and_set.c sigaction.c \ + readahead.c posix_fadvise.c posix_fadvise64.c + +SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S syscall.S pipe.S + +ARCH_HEADERS := sgidefs.h +# regdef.h + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/mips/__longjmp.c b/libc/sysdeps/linux/mips/__longjmp.c new file mode 100644 index 0000000..9dc09f2 --- /dev/null +++ b/libc/sysdeps/linux/mips/__longjmp.c @@ -0,0 +1,128 @@ +/* Copyright (C) 1992, 1995, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#ifndef __GNUC__ + #error This file uses GNU C extensions; you must compile with GCC. +#endif + +extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; +libc_hidden_proto(__longjmp) + +void __longjmp (__jmp_buf env, int val_arg) +{ + /* gcc 1.39.19 miscompiled the longjmp routine (as it did setjmp before + the hack around it); force it to use $a1 for the longjmp value. + Without this it saves $a1 in a register which gets clobbered + along the way. */ + register int val __asm__ ("a1"); + + /* Pull back the floating point callee-saved registers. */ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[0])); + __asm__ __volatile__ ("l.d $f25, %0" : : "m" (env[0].__fpregs[1])); + __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[2])); + __asm__ __volatile__ ("l.d $f27, %0" : : "m" (env[0].__fpregs[3])); + __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4])); + __asm__ __volatile__ ("l.d $f29, %0" : : "m" (env[0].__fpregs[5])); + __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[6])); + __asm__ __volatile__ ("l.d $f31, %0" : : "m" (env[0].__fpregs[7])); +#else /* O32 || N32 */ + __asm__ __volatile__ ("l.d $f20, %0" : : "m" (env[0].__fpregs[0])); + __asm__ __volatile__ ("l.d $f22, %0" : : "m" (env[0].__fpregs[1])); + __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[2])); + __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[3])); + __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4])); + __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[5])); +#endif /* O32 || N32 */ + + /* Get and reconstruct the floating point csr. */ + __asm__ __volatile__ ("lw $2, %0" : : "m" (env[0].__fpc_csr)); + __asm__ __volatile__ ("ctc1 $2, $31"); +#endif + + /* Get the GP. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("ld $gp, %0" : : "m" (env[0].__gp)); +#else /* O32 || N32 */ + __asm__ __volatile__ ("lw $gp, %0" : : "m" (env[0].__gp)); +#endif /* O32 || N32 */ + + /* Get the callee-saved registers. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("lw $16, %0" : : "m" (env[0].__regs[0])); + __asm__ __volatile__ ("lw $17, %0" : : "m" (env[0].__regs[1])); + __asm__ __volatile__ ("lw $18, %0" : : "m" (env[0].__regs[2])); + __asm__ __volatile__ ("lw $19, %0" : : "m" (env[0].__regs[3])); + __asm__ __volatile__ ("lw $20, %0" : : "m" (env[0].__regs[4])); + __asm__ __volatile__ ("lw $21, %0" : : "m" (env[0].__regs[5])); + __asm__ __volatile__ ("lw $22, %0" : : "m" (env[0].__regs[6])); + __asm__ __volatile__ ("lw $23, %0" : : "m" (env[0].__regs[7])); +#else /* N32 || N64 */ + __asm__ __volatile__ ("ld $16, %0" : : "m" (env[0].__regs[0])); + __asm__ __volatile__ ("ld $17, %0" : : "m" (env[0].__regs[1])); + __asm__ __volatile__ ("ld $18, %0" : : "m" (env[0].__regs[2])); + __asm__ __volatile__ ("ld $19, %0" : : "m" (env[0].__regs[3])); + __asm__ __volatile__ ("ld $20, %0" : : "m" (env[0].__regs[4])); + __asm__ __volatile__ ("ld $21, %0" : : "m" (env[0].__regs[5])); + __asm__ __volatile__ ("ld $22, %0" : : "m" (env[0].__regs[6])); + __asm__ __volatile__ ("ld $23, %0" : : "m" (env[0].__regs[7])); +#endif /* N32 || N64 */ + + /* Get the PC. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("lw $25, %0" : : "m" (env[0].__pc)); +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + __asm__ __volatile__ ("lw $31, %0" : : "m" (env[0].__pc)); +#else /* N64 */ + __asm__ __volatile__ ("ld $31, %0" : : "m" (env[0].__pc)); +#endif /* N64 */ + + /* Restore the stack pointer and the FP. They have to be restored + last and in a single asm as gcc, depending on options used, may + use either of them to access env. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("ld $29, %0\n\t" + "ld $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp)); +#else /* O32 || N32 */ + __asm__ __volatile__ ("lw $29, %0\n\t" + "lw $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp)); +#endif /* O32 || N32 */ + + /* Give setjmp 1 if given a 0, or what they gave us if non-zero. */ + if (val == 0) + __asm__ __volatile__ ("li $2, 1"); + else + __asm__ __volatile__ ("move $2, %0" : : "r" (val)); + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("jr $25"); +#else /* N32 || N64 */ + __asm__ __volatile__ ("jr $31"); +#endif /* N32 || N64 */ + + /* Avoid `volatile function does return' warnings. */ + for (;;); +} +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/mips/__syscall_error.c b/libc/sysdeps/linux/mips/__syscall_error.c new file mode 100644 index 0000000..5e109a8 --- /dev/null +++ b/libc/sysdeps/linux/mips/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/mips/_test_and_set.c b/libc/sysdeps/linux/mips/_test_and_set.c new file mode 100644 index 0000000..9fd48f7 --- /dev/null +++ b/libc/sysdeps/linux/mips/_test_and_set.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the real-function versions of all inline functions + defined in sys/tas.h */ + +#include + +#define _EXTERN_INLINE +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif + +#include "sys/tas.h" diff --git a/libc/sysdeps/linux/mips/bits/atomic.h b/libc/sysdeps/linux/mips/bits/atomic.h new file mode 100644 index 0000000..4f73cc2 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/atomic.h @@ -0,0 +1,303 @@ +/* Low-level functions for atomic operations. Mips version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MIPS_BITS_ATOMIC_H +#define _MIPS_BITS_ATOMIC_H 1 + +#include +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#if _MIPS_SIM == _ABIO32 +#define MIPS_PUSH_MIPS2 ".set mips2\n\t" +#else +#define MIPS_PUSH_MIPS2 +#endif + +/* See the comments in about the use of the sync instruction. */ +#ifndef MIPS_SYNC +# define MIPS_SYNC sync +#endif + +#define MIPS_SYNC_STR_2(X) #X +#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X) +#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC) + +/* Compare and exchange. For all of the "xxx" routines, we expect a + "__prev" and a "__cmp" variable to be provided by the enclosing scope, + in which values are returned. */ + +#define __arch_compare_and_exchange_xxx_8_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) + +#define __arch_compare_and_exchange_xxx_16_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) + +#define __arch_compare_and_exchange_xxx_32_int(mem, newval, oldval, rel, acq) \ + __asm__ __volatile__ ( \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%4\n\t" \ + "move %1,$0\n\t" \ + "bne %0,%2,2f\n\t" \ + "move %1,%3\n\t" \ + "sc %1,%4\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (oldval), "r" (newval), "m" (*mem) \ + : "memory") + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) +#else +#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "lld %0,%4\n\t" \ + "move %1,$0\n\t" \ + "bne %0,%2,2f\n\t" \ + "move %1,%3\n\t" \ + "scd %1,%4\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (oldval), "r" (newval), "m" (*mem) \ + : "memory") +#endif + +/* For all "bool" routines, we return FALSE if exchange succesful. */ + +#define __arch_compare_and_exchange_bool_8_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_16_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_32_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_64_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \ + !__cmp; }) + +/* For all "val" routines, return the old value whether exchange + successful or not. */ + +#define __arch_compare_and_exchange_val_8_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_16_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_32_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_64_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +/* Compare and exchange with "acquire" semantics, ie barrier after. */ + +#define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, "", MIPS_SYNC_STR) + +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, "", MIPS_SYNC_STR) + +/* Compare and exchange with "release" semantics, ie barrier before. */ + +#define atomic_compare_and_exchange_bool_rel(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, MIPS_SYNC_STR, "") + +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, MIPS_SYNC_STR, "") + + + +/* Atomic exchange (without compare). */ + +#define __arch_exchange_xxx_8_int(mem, newval, rel, acq) \ + (abort (), 0) + +#define __arch_exchange_xxx_16_int(mem, newval, rel, acq) \ + (abort (), 0) + +#define __arch_exchange_xxx_32_int(mem, newval, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%3\n\t" \ + "move %1,%2\n\t" \ + "sc %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (newval), "m" (*mem) \ + : "memory"); \ + __prev; }) + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \ + (abort (), 0) +#else +#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\n" \ + "lld %0,%3\n\t" \ + "move %1,%2\n\t" \ + "scd %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (newval), "m" (*mem) \ + : "memory"); \ + __prev; }) +#endif + +#define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, "", MIPS_SYNC_STR) + +#define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, MIPS_SYNC_STR, "") + + +/* Atomically add value and return the previous (unincremented) value. */ + +#define __arch_exchange_and_add_8_int(mem, newval, rel, acq) \ + (abort (), (__typeof(*mem)) 0) + +#define __arch_exchange_and_add_16_int(mem, newval, rel, acq) \ + (abort (), (__typeof(*mem)) 0) + +#define __arch_exchange_and_add_32_int(mem, value, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%3\n\t" \ + "addu %1,%0,%2\n\t" \ + "sc %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (value), "m" (*mem) \ + : "memory"); \ + __prev; }) + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \ + (abort (), (__typeof(*mem)) 0) +#else +#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ( \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "lld %0,%3\n\t" \ + "daddu %1,%0,%2\n\t" \ + "scd %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (value), "m" (*mem) \ + : "memory"); \ + __prev; }) +#endif + +/* ??? Barrier semantics for atomic_exchange_and_add appear to be + undefined. Use full barrier for now, as that's safe. */ +#define atomic_exchange_and_add(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + MIPS_SYNC_STR, MIPS_SYNC_STR) + +/* TODO: More atomic operations could be implemented efficiently; only the + basic requirements are done. */ + +#define atomic_full_barrier() \ + __asm__ __volatile__ (".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + MIPS_SYNC_STR "\n\t" \ + ".set pop" : : : "memory") + +#endif /* bits/atomic.h */ diff --git a/libc/sysdeps/linux/mips/bits/dirent.h b/libc/sysdeps/linux/mips/bits/dirent.h new file mode 100644 index 0000000..014e011 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/dirent.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DIRENT_H +# error "Never use directly; include instead." +#endif +#include +#include + +struct dirent + { +#if defined(__USE_FILE_OFFSET64) && defined(__NR_getdents64) + __ino64_t d_ino; + __off64_t d_off; +#else + __ino_t d_ino; + __off_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +struct dirent64 + { +#ifdef __NR_getdents64 + __ino64_t d_ino; + __off64_t d_off; +#else + /* dirent64 is the same as dirent. */ + __ino_t d_ino; + __off_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE diff --git a/libc/sysdeps/linux/mips/bits/dlfcn.h b/libc/sysdeps/linux/mips/bits/dlfcn.h new file mode 100644 index 0000000..1f054f9 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/dlfcn.h @@ -0,0 +1,66 @@ +/* System dependent definitions for run-time dynamic loading. + Copyright (C) 1996, 1997, 1999, 2000, 2001, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +# error "Never use directly; include instead." +#endif + +/* The MODE argument to `dlopen' contains one of the following: */ +#define RTLD_LAZY 0x0001 /* Lazy function call binding. */ +#define RTLD_NOW 0x0002 /* Immediate function call binding. */ +#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +#define RTLD_NOLOAD 0x00008 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00010 /* Use deep binding. */ + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +#define RTLD_GLOBAL 0x0004 + +/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. + The implementation does this by default and so we can define the + value to zero. */ +#define RTLD_LOCAL 0 + +/* Do not delete object when closed. */ +#define RTLD_NODELETE 0x01000 + +#if 0 /*def __USE_GNU*/ +/* To support profiling of shared objects it is a good idea to call + the function found using `dlsym' using the following macro since + these calls do not use the PLT. But this would mean the dynamic + loader has no chance to find out when the function is called. The + macro applies the necessary magic so that profiling is possible. + Rewrite + foo = (*fctp) (arg1, arg2); + into + foo = DL_CALL_FCT (fctp, (arg1, arg2)); +*/ +# define DL_CALL_FCT(fctp, args) \ + (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args) + +__BEGIN_DECLS + +/* This function calls the profiling functions. */ +extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW; + +__END_DECLS + +#endif diff --git a/libc/sysdeps/linux/mips/bits/endian.h b/libc/sysdeps/linux/mips/bits/endian.h new file mode 100644 index 0000000..0a3d2fa --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/endian.h @@ -0,0 +1,16 @@ +/* The MIPS architecture has selectable endianness. + Linux/MIPS exists in two both little and big endian flavours and we + want to be able to share the installed headerfiles between both, + so we define __BYTE_ORDER based on GCC's predefines. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __MIPSEB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# ifdef __MIPSEL__ +# define __BYTE_ORDER __LITTLE_ENDIAN +# endif +#endif diff --git a/libc/sysdeps/linux/mips/bits/fcntl.h b/libc/sysdeps/linux/mips/bits/fcntl.h new file mode 100644 index 0000000..8967869 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/fcntl.h @@ -0,0 +1,261 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_APPEND 0x0008 +#define O_SYNC 0x0010 +#define O_NONBLOCK 0x0080 +#define O_NDELAY O_NONBLOCK +#define O_CREAT 0x0100 /* not fcntl */ +#define O_TRUNC 0x0200 /* not fcntl */ +#define O_EXCL 0x0400 /* not fcntl */ +#define O_NOCTTY 0x0800 /* not fcntl */ +#define O_FSYNC O_SYNC +#define O_ASYNC 0x1000 + +#ifdef __USE_GNU +# define O_NOFOLLOW 0x20000 /* Do not follow links. */ +# define O_DIRECT 0x8000 /* Direct disk access hint. */ +# define O_DIRECTORY 0x10000 /* Must be a directory. */ +# define O_NOATIME 0x40000 /* Do not set atime. */ +#endif + +/* For now Linux has no synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0x2000 /* Allow large file opens. */ +# endif +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 14 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif + +#if __WORDSIZE == 64 +# define F_GETLK64 14 /* Get record locking info. */ +# define F_SETLK64 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK64 33 /* Get record locking info. */ +# define F_SETLK64 34 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 35 /* Set record locking info (blocking). */ +#endif + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 24 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 23 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#if _MIPS_SIM != _ABI64 + /* The 64-bit flock structure, used by the n64 ABI, and for 64-bit + fcntls in o32 and n32, never has this field. */ + long int l_sysid; +#endif +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ +#if ! defined __USE_FILE_OFFSET64 && _MIPS_SIM != _ABI64 + /* The 64-bit flock structure, used by the n64 ABI, and for 64-bit + flock in o32 and n32, never has this field. */ + long int pad[4]; +#endif + }; +typedef struct flock flock_t; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/mips/bits/fenv.h b/libc/sysdeps/linux/mips/bits/fenv.h new file mode 100644 index 0000000..24e0694 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/fenv.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INEXACT = 0x04, +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = 0x08, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 0x10, +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = 0x20, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = 0x40, +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The MIPS FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0x0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 0x2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 0x3 +#define FE_DOWNWARD FE_DOWNWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned int __fp_control_register; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/libc/sysdeps/linux/mips/bits/ioctl-types.h b/libc/sysdeps/linux/mips/bits/ioctl-types.h new file mode 100644 index 0000000..a8dcf24 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/ioctl-types.h @@ -0,0 +1,76 @@ +/* Structure types for pre-termios terminal ioctls. Linux/MIPS version. + Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Get definition of constants for use with `ioctl'. */ +#include + +struct winsize + { + unsigned short int ws_row; + unsigned short int ws_col; + unsigned short int ws_xpixel; + unsigned short int ws_ypixel; + }; + +#define NCC 8 +struct termio + { + unsigned short int c_iflag; /* input mode flags */ + unsigned short int c_oflag; /* output mode flags */ + unsigned short int c_cflag; /* control mode flags */ + unsigned short int c_lflag; /* local mode flags */ + char c_line; /* line discipline */ + /* Yes, this is really NCCS. */ + unsigned char c_cc[32 /* NCCS */]; /* control characters */ + }; + +/* modem lines */ +#define TIOCM_LE 0x001 /* line enable */ +#define TIOCM_DTR 0x002 /* data terminal ready */ +#define TIOCM_RTS 0x004 /* request to send */ +#define TIOCM_ST 0x010 /* secondary transmit */ +#define TIOCM_SR 0x020 /* secondary receive */ +#define TIOCM_CTS 0x040 /* clear to send */ +#define TIOCM_CAR 0x100 /* carrier detect */ +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RNG 0x200 /* ring */ +#define TIOCM_RI TIOCM_RNG +#define TIOCM_DSR 0x400 /* data set ready */ + +/* line disciplines */ +#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 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/libc/sysdeps/linux/mips/bits/ipc.h b/libc/sysdeps/linux/mips/bits/ipc.h new file mode 100644 index 0000000..1f629ce --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/ipc.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned int uid; /* Owner's user ID. */ + unsigned int gid; /* Owner's group ID. */ + unsigned int cuid; /* Creator's user ID. */ + unsigned int cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; +}; diff --git a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h new file mode 100644 index 0000000..5c84548 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h @@ -0,0 +1,48 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This is the sigaction structure from the Linux 2.1.24 kernel. */ + +#include + +#define HAVE_SA_RESTORER + +struct old_kernel_sigaction { + unsigned int sa_flags; + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned int __pad0[3]; /* reserved, keep size constant */ + + /* Abi says here follows reserved int[2] */ + void (*sa_restorer)(void); +#if (_MIPS_SZPTR < 64) + /* + * For 32 bit code we have to pad struct sigaction to get + * constant size for the ABI + */ + int pad1[1]; /* reserved */ +#endif +}; + + +#define _KERNEL_NSIG 128 +#define _KERNEL_NSIG_BPW _MIPS_SZLONG +#define _KERNEL_NSIG_WORDS (_KERNEL_NSIG / _KERNEL_NSIG_BPW) + +typedef struct { + unsigned long sig[_KERNEL_NSIG_WORDS]; +} kernel_sigset_t; + +/* This is the sigaction structure from the Linux 2.1.68 kernel. */ +struct kernel_sigaction { + unsigned int sa_flags; + __sighandler_t k_sa_handler; + kernel_sigset_t sa_mask; + void (*sa_restorer)(void); + int s_resv[1]; /* reserved */ +}; + +extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, + struct kernel_sigaction *__unbounded, size_t) attribute_hidden; + +#endif diff --git a/libc/sysdeps/linux/mips/bits/kernel_stat.h b/libc/sysdeps/linux/mips/bits/kernel_stat.h new file mode 100644 index 0000000..3161562 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/kernel_stat.h @@ -0,0 +1,112 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI64 +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct kernel_stat { + __kernel_dev_t st_dev; + unsigned int st_pad1[3]; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + unsigned int st_pad2[3]; + __kernel_off_t st_size; + unsigned int st_atime; + unsigned int st_atime_nsec; + unsigned int st_mtime; + unsigned int st_mtime_nsec; + unsigned int st_ctime; + unsigned int st_ctime_nsec; + unsigned int st_blksize; + unsigned int reserved3; + unsigned long st_blocks; +}; +#define kernel_stat64 kernel_stat +#elif _MIPS_SIM == _MIPS_SIM_NABI32 +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct kernel_stat { + unsigned int st_dev; + unsigned int st_pad1[3]; + unsigned long long st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + unsigned int st_rdev; + unsigned int st_pad2[3]; + unsigned long long st_size; + unsigned int st_atime; + unsigned int st_atime_nsec; + unsigned int st_mtime; + unsigned int st_mtime_nsec; + unsigned int st_ctime; + unsigned int st_ctime_nsec; + unsigned int st_blksize; + unsigned int reserved3; + unsigned long long st_blocks; +}; +#define kernel_stat64 kernel_stat +#else /* O32 */ +struct kernel_stat { + __kernel_dev_t st_dev; + long st_pad1[3]; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + long st_pad2[2]; + __kernel_off_t st_size; + long st_pad3; + time_t st_atime; + long st_atime_nsec; + time_t st_mtime; + long st_mtime_nsec; + time_t st_ctime; + long st_ctime_nsec; + long st_blksize; + long st_blocks; + long st_pad4[14]; +}; + +struct kernel_stat64 { + unsigned long st_dev; + unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ + unsigned long long st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + unsigned long st_rdev; + unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + long long st_size; + 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; + unsigned long st_blksize; + unsigned long st_pad2; + long long st_blocks; +}; +#endif /* O32 */ + +#define STAT_HAVE_NSEC 1 + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/mips/bits/kernel_types.h b/libc/sysdeps/linux/mips/bits/kernel_types.h new file mode 100644 index 0000000..9fc3b96 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/kernel_types.h @@ -0,0 +1,79 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef long int __kernel_ipc_pid_t; +typedef int __kernel_uid_t; +typedef int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef int __kernel_uid32_t; +typedef int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#else +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; + +/* Linux 2.4.20 include/asm-mips/posix_types.h has this: +but apparently that is an error?!?!? +*/ +#if 0 +typedef int __kernel_nlink_t; +#else +/* So use this instead */ +typedef unsigned long __kernel_nlink_t; +#endif + +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef long int __kernel_ipc_pid_t; +typedef int __kernel_uid_t; +typedef int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef int __kernel_uid32_t; +typedef int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + + +typedef struct { + long val[2]; +} __kernel_fsid_t; + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/mips/bits/mathdef.h b/libc/sysdeps/linux/mips/bits/mathdef.h new file mode 100644 index 0000000..b741f65 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/mathdef.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#include + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Normally, there is no long double type and the `float' and `double' + expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ && _MIPS_SIM == _ABIO32 +/* Signal that we do not really have a `long double'. This disables the + declaration of all the `long double' function variants. */ +# error defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ and _MIPS_SIM == _ABIO32 +#endif diff --git a/libc/sysdeps/linux/mips/bits/mman.h b/libc/sysdeps/linux/mips/bits/mman.h new file mode 100644 index 0000000..47d3393 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/mman.h @@ -0,0 +1,106 @@ +/* Definitions for POSIX memory map interface. Linux/MIPS version. + Copyright (C) 1997, 2000, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x0800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_NORESERVE 0x0400 /* don't check for reservations */ +# define MAP_ANONYMOUS 0x0800 /* don't use a file */ +# define MAP_GROWSDOWN 0x1000 /* stack-like segment */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* mark it as an executable */ +# define MAP_LOCKED 0x8000 /* pages are locked */ +# define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +# define MAP_NONBLOCK 0x20000 /* do not block on IO */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/mips/bits/msq.h b/libc/sysdeps/linux/mips/bits/msq.h new file mode 100644 index 0000000..2b0d38e --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/msq.h @@ -0,0 +1,93 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused1; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused2; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused3; +#endif + __time_t msg_ctime; /* time of last change */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused3; +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/mips/bits/poll.h b/libc/sysdeps/linux/mips/bits/poll.h new file mode 100644 index 0000000..eee4ea2 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x400 +# define POLLREMOVE 0x1000 +# define POLLRDHUP 0x2000 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/mips/bits/resource.h b/libc/sysdeps/linux/mips/bits/resource.h new file mode 100644 index 0000000..1c8b99a --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/resource.h @@ -0,0 +1,233 @@ +/* Bit values & structures for resource limits. Linux/MIPS version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 7, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 5, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 6, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 8, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 9, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#if _MIPS_SIM == _ABI64 +/* The N64 syscall uses this value. */ +# define RLIM_INFINITY 0xffffffffffffffffUL +# ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffUL +# endif +#else +/* The O32 and N32 syscalls use 0x7fffffff. */ +# ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +# else +# define RLIM_INFINITY 0x7fffffffffffffffULL +# endif +# ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffULL +# endif +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/libc/sysdeps/linux/mips/bits/sem.h b/libc/sysdeps/linux/mips/bits/sem.h new file mode 100644 index 0000000..6282de9 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/sem.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/mips/bits/setjmp.h b/libc/sysdeps/linux/mips/bits/setjmp.h new file mode 100644 index 0000000..08e74fe --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/setjmp.h @@ -0,0 +1,72 @@ +/* Define the machine-dependent type `jmp_buf'. MIPS version. + Copyright (C) 1992,93,95,97,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +typedef struct + { + /* Program counter. */ + void * __pc; + + /* Stack pointer. */ + void * __sp; + + /* Callee-saved registers s0 through s7. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + int __regs[8]; +#else + long long __regs[8]; +#endif + + /* The frame pointer. */ + void * __fp; + + /* The global pointer. */ + void * __gp; + + /* Floating point status register. */ + int __fpc_csr; + + /* Callee-saved floating point registers. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + double __fpregs[8]; +#else /* N32 || O32 */ + double __fpregs[6]; +#endif /* N32 || O32 */ + } __jmp_buf[1]; + +#ifdef __USE_MISC +/* Offset to the program counter in `jmp_buf'. */ +# define JB_PC 0 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/mips/bits/shm.h b/libc/sysdeps/linux/mips/bits/shm.h new file mode 100644 index 0000000..b308334 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/shm.h @@ -0,0 +1,94 @@ +/* Copyright (C) 1995,1996,1997,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +/* Segment low boundary address multiple. */ +#define SHMLBA 0x40000 + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/mips/bits/sigaction.h b/libc/sysdeps/linux/mips/bits/sigaction.h new file mode 100644 index 0000000..d04e25f --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/sigaction.h @@ -0,0 +1,89 @@ +/* The proper definitions for Linux/MIPS's sigaction. + Copyright (C) 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Special flags. */ + unsigned int sa_flags; + + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + + /* The ABI says here are two unused ints following. */ + /* Restore handler. */ + void (*sa_restorer) (void); + +#if _MIPS_SZPTR < 64 + int sa_resv[1]; +#endif + }; + +/* Bits in `sa_flags'. */ +/* Please note that some Linux kernels versions use different values for these + flags which is a bug in those kernel versions. */ +#define SA_NOCLDSTOP 0x00000001 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00010000 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000008 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal when + its handler is being executed. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_NOP 0 /* 0 is unused to catch errors */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 3 /* Set the set of blocked signals. */ +#ifdef __USE_MISC +# define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility: + set only the low 32 bit of the sigset. */ +#endif diff --git a/libc/sysdeps/linux/mips/bits/sigcontext.h b/libc/sysdeps/linux/mips/bits/sigcontext.h new file mode 100644 index 0000000..99faeed --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/sigcontext.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1996, 1997, 1998, 2003, 2004, 2006 Free Software + Foundation, Inc. This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +#if _MIPS_SIM == _ABIO32 + +/* Certain unused fields were replaced with new ones in 2.6.12-rc4. + The changes were as follows: + + sc_cause -> sc_hi1 + sc_badvaddr -> sc_lo1 + sc_sigset[0] -> sc_hi2 + sc_sigset[1] -> sc_lo2 + sc_sigset[2] -> sc_hi3 + sc_sigset[3] -> sc_lo3 + + sc_regmask, sc_ownedfp and sc_fpc_eir are not used. */ +struct sigcontext { + unsigned int sc_regmask; + unsigned int sc_status; + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_ownedfp; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; + unsigned int sc_used_math; + unsigned int sc_dsp; + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long sc_hi1; + unsigned long sc_lo1; + unsigned long sc_hi2; + unsigned long sc_lo2; + unsigned long sc_hi3; + unsigned long sc_lo3; +}; + +#else + +/* This structure changed in 2.6.12-rc4 when DSP support was added. */ +struct sigcontext { + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned long long sc_mdhi; + unsigned long long sc_hi1; + unsigned long long sc_hi2; + unsigned long long sc_hi3; + unsigned long long sc_mdlo; + unsigned long long sc_lo1; + unsigned long long sc_lo2; + unsigned long long sc_lo3; + unsigned long long sc_pc; + unsigned int sc_fpc_csr; + unsigned int sc_used_math; + unsigned int sc_dsp; + unsigned int sc_reserved; +}; + +#endif /* _MIPS_SIM != _ABIO32 */ +#endif diff --git a/libc/sysdeps/linux/mips/bits/sigcontextinfo.h b/libc/sysdeps/linux/mips/bits/sigcontextinfo.h new file mode 100644 index 0000000..f453c8d --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/sigcontextinfo.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include + +#if _MIPS_SIM == _ABIO32 + +#define SIGCONTEXT unsigned long _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) ctx->sc_pc) +#define GET_FRAME(ctx) ((void *) ctx->sc_regs[30]) +#define GET_STACK(ctx) ((void *) ctx->sc_regs[29]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + +#else + +#define SIGCONTEXT unsigned long _code, ucontext_t * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) ctx->uc_mcontext.pc) +#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.gregs[30]) +#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.gregs[29]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + +#endif diff --git a/libc/sysdeps/linux/mips/bits/siginfo.h b/libc/sysdeps/linux/mips/bits/siginfo.h new file mode 100644 index 0000000..ba3e1f6 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/siginfo.h @@ -0,0 +1,311 @@ +/* siginfo_t, sigevent and constants. Linux/MIPS version. + Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Signal code. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int __pad0[__SI_MAX_SIZE / sizeof (int) - __SI_PAD_SIZE - 3]; + /* Explicit padding. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + + /* POSIX.1b timers. */ + struct + { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by real time mesq state change. */ +# define SI_TIMER SI_TIMER + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_HEAD_SIZE (sizeof(long) + 2*sizeof(int)) +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE - __SIGEV_HEAD_SIZE) / sizeof (int)) + +/* Forward declaration of the `pthread_attr_t' type. */ +struct __pthread_attr_s; + +/* XXX This one might need to change!!! */ +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/libc/sysdeps/linux/mips/bits/signum.h b/libc/sysdeps/linux/mips/bits/signum.h new file mode 100644 index 0000000..a9b6848 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/signum.h @@ -0,0 +1,79 @@ +/* Signal number definitions. Linux version. + Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif + + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGABRT SIGIOT /* Abort (ANSI). */ +#define SIGEMT 7 +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGBUS 10 /* BUS error (4.2 BSD). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGSYS 12 +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define SIGCHLD 18 /* Child status has changed (POSIX). */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGPWR 19 /* Power failure restart (System V). */ +#define SIGWINCH 20 /* Window size change (4.3 BSD, Sun). */ +#define SIGURG 21 /* Urgent condition on socket (4.2 BSD). */ +#define SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGSTOP 23 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 24 /* Keyboard stop (POSIX). */ +#define SIGCONT 25 /* Continue (POSIX). */ +#define SIGTTIN 26 /* Background read from tty (POSIX). */ +#define SIGTTOU 27 /* Background write to tty (POSIX). */ +#define SIGVTALRM 28 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */ +#define SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */ + + +#define _NSIG 128 /* Biggest signal number + 1 + (including real-time signals). */ + +#define SIGRTMIN (__libc_current_sigrtmin ()) +#define SIGRTMAX (__libc_current_sigrtmax ()) + +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#define __SIGRTMIN 32 +#define __SIGRTMAX (_NSIG - 1) + +#endif /* included. */ diff --git a/libc/sysdeps/linux/mips/bits/sigstack.h b/libc/sysdeps/linux/mips/bits/sigstack.h new file mode 100644 index 0000000..d2c8552 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 2048 + +/* System default stack size. */ +#define SIGSTKSZ 8192 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + size_t ss_size; + int ss_flags; + } stack_t; diff --git a/libc/sysdeps/linux/mips/bits/socket.h b/libc/sysdeps/linux/mips/bits/socket.h new file mode 100644 index 0000000..0860b4d --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/socket.h @@ -0,0 +1,334 @@ +/* System-specific socket constants and types. Linux/MIPS version. + Copyright (C) 1991, 92, 1994-1999, 2000, 2001, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_DGRAM = 1, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_STREAM = 2, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_PACKET = 10 /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#if ULONG_MAX > 0xffffffff +# define __ss_aligntype __uint64_t +#else +# define __ss_aligntype __uint32_t +#endif +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000 /* Sender will send more. */ +#define MSG_MORE MSG_MORE + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#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)) + +extern struct cmsghdr * __NTH (__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg)) __THROW; +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +#endif /* bits/socket.h */ diff --git a/libc/sysdeps/linux/mips/bits/stackinfo.h b/libc/sysdeps/linux/mips/bits/stackinfo.h new file mode 100644 index 0000000..86e3d62 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On MIPS the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/mips/bits/stat.h b/libc/sysdeps/linux/mips/bits/stat.h new file mode 100644 index 0000000..e35d649 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/stat.h @@ -0,0 +1,203 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#include + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +#if _MIPS_SIM == _ABIO32 +/* Structure describing file characteristics. */ +struct stat + { + __dev_t st_dev; + long int st_pad1[2]; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + long int st_pad2[1]; + __off_t st_size; /* Size of file, in bytes. */ + /* SVR4 added this extra long to allow for expansion of off_t. */ + long int st_pad3; +#else + long int st_pad2[2]; + __off64_t st_size; /* Size of file, in bytes. */ +#endif + /* + * Actually this should be timestruc_t st_atime, st_mtime and + * st_ctime but we don't have it under Linux. + */ + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ +#else + long int st_pad4; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ +#endif + long int st_pad5[14]; + }; +#else /* N32 || N64 */ +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct stat { + unsigned int st_dev; + int st_pad1[3]; + __ino_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + int st_pad2[3]; + __off_t st_size; /* Size of file, in bytes. */ + /* + * Actually this should be timestruc_t st_atime, st_mtime and + * st_ctime but we don't have it under Linux. + */ + int st_atime; + int st_atimensec; + int st_mtime; + int st_mtimensec; + int st_ctime; + int st_ctimensec; + int st_blksize; /* Optimal block size for I/O. */ + int st_pad3; + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ + int st_pad4[14]; +}; +#endif /* N32 || N64 */ + +#ifdef __USE_LARGEFILE64 +#if _MIPS_SIM == _ABIO32 +struct stat64 + { + __dev_t st_dev; + long int st_pad1[2]; + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + long int st_pad2[2]; + __off64_t st_size; /* Size of file, in bytes. */ + /* + * Actually this should be timestruc_t st_atime, st_mtime and + * st_ctime but we don't have it under Linux. + */ + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + long int st_pad3; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ + long int st_pad4[14]; + }; +#else /* N32 || N64 */ +/* stat64 of N32/N64 is just an alias of stat syscall. */ +struct stat64 { + unsigned int st_dev; + int st_pad1[3]; + __ino_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + int st_pad2[3]; + __off_t st_size; /* Size of file, in bytes. */ + /* + * Actually this should be timestruc_t st_atime, st_mtime and + * st_ctime but we don't have it under Linux. + */ + int st_atime; + int st_atimensec; + int st_mtime; + int st_mtimensec; + int st_ctime; + int st_ctimensec; + int st_blksize; /* Optimal block size for I/O. */ + int st_pad3; + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ + int st_pad4[14]; +}; +#endif /* N32 || N64 */ +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/mips/bits/statfs.h b/libc/sysdeps/linux/mips/bits/statfs.h new file mode 100644 index 0000000..2f9bd54 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/statfs.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t*/ + +struct statfs + { + long int f_type; +#define f_fstyp f_type + long int f_bsize; + long int f_frsize; /* Fragment size - unsupported */ +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_files; + __fsblkcnt_t f_ffree; + __fsblkcnt_t f_bavail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; + __fsblkcnt64_t f_bavail; +#endif + + /* Linux specials */ + __fsid_t f_fsid; + long int f_namelen; + long int f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + long int f_type; +#define f_fstyp f_type + long int f_bsize; + long int f_frsize; /* Fragment size - unsupported */ + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; + __fsblkcnt64_t f_bavail; + + /* Linux specials */ + __fsid_t f_fsid; + long int f_namelen; + long int f_spare[6]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATFS_F_NAMELEN diff --git a/libc/sysdeps/linux/mips/bits/syscalls.h b/libc/sysdeps/linux/mips/bits/syscalls.h new file mode 100644 index 0000000..fa8b876 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/syscalls.h @@ -0,0 +1,393 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + +#undef _syscall7 +#define _syscall7(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6,type7,arg7) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6,type7 arg7) \ +{ \ +return (type) (INLINE_SYSCALL(name, 7, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); \ +} + +/* + * Import from: + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h + */ + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ INTERNAL_SYSCALL_DECL(err); \ + long result_var = INTERNAL_SYSCALL (name, err, nr, args); \ + if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ + result_var = -1L; \ + } \ + result_var; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) long err + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err)) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ + "i" (SYS_ify (name)), err, args) + +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (= number, , "r" (__v0), err, args) + +#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABI64 +# define ARG_TYPE long +#else +# define ARG_TYPE long long +#endif + +#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#if _MIPS_SIM == _ABIO32 +#include +/* We need to use a frame pointer for the functions in which we + adjust $sp around the syscall, or debug information and unwind + information will be $sp relative and thus wrong during the syscall. As + of GCC 3.4.3, this is sufficient. */ +#define FORCE_FRAME_POINTER alloca (4) + +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + "sw\t%8, 24($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" + +#else /* N32 || N64 */ + +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \ + register ARG_TYPE __a5 __asm__("$9") = (ARG_TYPE) arg6; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), \ + "r" (__a5) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" + +#endif + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/mips/bits/termios.h b/libc/sysdeps/linux/mips/bits/termios.h new file mode 100644 index 0000000..546faa0 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/termios.h @@ -0,0 +1,217 @@ +/* termios type and macro definitions. Linux/MIPS version. + Copyright (C) 1993, 94, 95, 96, 97, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + }; + +/* c_cc characters */ +#define VINTR 0 /* Interrupt character [ISIG]. */ +#define VQUIT 1 /* Quit character [ISIG]. */ +#define VERASE 2 /* Erase character [ICANON]. */ +#define VKILL 3 /* Kill-line character [ICANON]. */ +#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ +#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ +#define VEOL2 6 /* Second EOL character [ICANON]. */ +#define VSWTC 7 +#define VSWTCH VSWTC +#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */ +#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */ +#define VSUSP 10 /* Suspend character [ISIG]. */ + /* VDSUSP is not supported on Linux. */ +/* #define VDSUSP 11 / * Delayed suspend character [ISIG]. */ +#define VREPRINT 12 /* Reprint-line character [ICANON]. */ +#define VDISCARD 13 /* Discard character [IEXTEN]. */ +#define VWERASE 14 /* Word-erase character [ICANON]. */ +#define VLNEXT 15 /* Literal-next character [IEXTEN]. */ +#define VEOF 16 /* End-of-file character [ICANON]. */ +#define VEOL 17 /* End-of-line character [ICANON]. */ + +/* c_iflag bits */ +#define IGNBRK 0000001 /* Ignore break condition. */ +#define BRKINT 0000002 /* Signal interrupt on break. */ +#define IGNPAR 0000004 /* Ignore characters with parity errors. */ +#define PARMRK 0000010 /* Mark parity and framing errors. */ +#define INPCK 0000020 /* Enable input parity check. */ +#define ISTRIP 0000040 /* Strip 8th bit off characters. */ +#define INLCR 0000100 /* Map NL to CR on input. */ +#define IGNCR 0000200 /* Ignore CR. */ +#define ICRNL 0000400 /* Map CR to NL on input. */ +#define IUCLC 0001000 /* Map upper case to lower case on input. */ +#define IXON 0002000 /* Enable start/stop output control. */ +#define IXANY 0004000 /* Any character will restart after stop. */ +#define IXOFF 0010000 /* Enable start/stop input control. */ +#define IMAXBEL 0020000 /* Ring bell when input queue is full. */ + +/* c_oflag bits */ +#define OPOST 0000001 /* Perform output processing. */ +#define OLCUC 0000002 /* Map lower case to upper case on output. */ +#define ONLCR 0000004 /* Map NL to CR-NL on output. */ +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# 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 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#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 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 /* Number of bits per byte (mask). */ +#define CS5 0000000 /* 5 bits per byte. */ +#define CS6 0000020 /* 6 bits per byte. */ +#define CS7 0000040 /* 7 bits per byte. */ +#define CS8 0000060 /* 8 bits per byte. */ +#define CSTOPB 0000100 /* Two stop bits instead of one. */ +#define CREAD 0000200 /* Enable receiver. */ +#define PARENB 0000400 /* Parity enable. */ +#define PARODD 0001000 /* Odd parity instead of even. */ +#define HUPCL 0002000 /* Hang up on last close. */ +#define CLOCAL 0004000 /* Ignore modem status lines. */ +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#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 __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 /* Enable signals. */ +#define ICANON 0000002 /* Do erase and kill processing. */ +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 /* Enable echo. */ +#define ECHOE 0000020 /* Visual erase for ERASE. */ +#define ECHOK 0000040 /* Echo NL after KILL. */ +#define ECHONL 0000100 /* Echo NL even if ECHO is off. */ +#define NOFLSH 0000200 /* Disable flush after interrupt. */ +#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */ +#ifdef __USE_MISC +# define ECHOCTL 0001000 /* Echo control characters as ^X. */ +# define ECHOPRT 0002000 /* Hardcopy visual erase. */ +# define ECHOKE 0004000 /* Visual erase for KILL. */ +# define FLUSHO 0020000 +# define PENDIN 0040000 /* Retype pending input (state). */ +#endif +#define TOSTOP 0100000 /* Send SIGTTOU for background output. */ +#define ITOSTOP TOSTOP + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 /* Suspend output. */ +#define TCOON 1 /* Restart suspended output. */ +#define TCIOFF 2 /* Send a STOP character. */ +#define TCION 3 /* Send a START character. */ + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 /* Discard data received but not yet read. */ +#define TCOFLUSH 1 /* Discard data written but not yet sent. */ +#define TCIOFLUSH 2 /* Discard all pending data. */ + +/* tcsetattr uses these */ +#define TCSANOW 0x540e /* Same as TCSETS; change immediately. */ +#define TCSADRAIN 0x540f /* Same as TCSETSW; change when pending output is written. */ +#define TCSAFLUSH 0x5410 /* Same as TCSETSF; flush pending input before changing. */ + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h b/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h new file mode 100644 index 0000000..42a7c45 --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "break 255" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#undef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/mips/bits/uClibc_page.h b/libc/sysdeps/linux/mips/bits/uClibc_page.h new file mode 100644 index 0000000..915918c --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/uClibc_page.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SIZE of mips is sortof wierd, and depends on how the kernel + * happens to have been configured. It might use 4KB, 16K or 64K + * pages. To avoid using the current kernel configuration settings, + * uClibc will simply use 4KB on mips and call it good. */ +#if 0 +#define PAGE_SHIFT 16 +#define PAGE_SHIFT 14 +#endif +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/mips/bits/wordsize.h b/libc/sysdeps/linux/mips/bits/wordsize.h new file mode 100644 index 0000000..666c7ad --- /dev/null +++ b/libc/sysdeps/linux/mips/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE _MIPS_SZPTR diff --git a/libc/sysdeps/linux/mips/brk.c b/libc/sysdeps/linux/mips/brk.c new file mode 100644 index 0000000..36620b2 --- /dev/null +++ b/libc/sysdeps/linux/mips/brk.c @@ -0,0 +1,52 @@ +/* brk system call for Linux/MIPS. + Copyright (C) 2000, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *newbrk; + + { + register long int res __asm__ ("$2"); + + __asm__ ("move\t$4,%2\n\t" + "li\t%0,%1\n\t" + "syscall" /* Perform the system call. */ + : "=r" (res) + : "I" (__NR_brk), "r" (addr) + : "$4", "$7", __SYSCALL_CLOBBERS); + newbrk = (void *) res; + } + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/mips/bsd-_setjmp.S b/libc/sysdeps/linux/mips/bsd-_setjmp.S new file mode 100644 index 0000000..6853dea --- /dev/null +++ b/libc/sysdeps/linux/mips/bsd-_setjmp.S @@ -0,0 +1,56 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. MIPS version. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif + +.text +.global _setjmp +.align 2; +.ent _setjmp,0; +.type _setjmp,@function + +_setjmp: +#ifdef __PIC__ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) + .set noreorder + .cpload t9 + .set reorder + la t9, __sigsetjmp +#else + .cpsetup t9, v0, _setjmp + PTR_LA t9, __sigsetjmp + .cpreturn +#endif +#endif + move a1,zero /* Pass a second argument of zero. */ +#ifdef __PIC__ + jr t9 +#else + j __sigsetjmp +#endif + .end _setjmp; diff --git a/libc/sysdeps/linux/mips/bsd-setjmp.S b/libc/sysdeps/linux/mips/bsd-setjmp.S new file mode 100644 index 0000000..1f57a97 --- /dev/null +++ b/libc/sysdeps/linux/mips/bsd-setjmp.S @@ -0,0 +1,56 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. MIPS version. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif + +.text +.global setjmp +.align 2; +.ent setjmp,0; +.type setjmp,@function + +setjmp: + .set noreorder +#ifdef __PIC__ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .cpload t9 + .set reorder + la t9, __sigsetjmp +#else /* N32 */ + .cpsetup t9, v0, setjmp + PTR_LA t9, __sigsetjmp + .cprestore +#endif /* N32 */ +#endif + li a1, 1 /* Pass a second argument of one. */ +#ifdef __PIC__ + jr t9 +#else + j __sigsetjmp +#endif + .end setjmp diff --git a/libc/sysdeps/linux/mips/cacheflush.c b/libc/sysdeps/linux/mips/cacheflush.c new file mode 100644 index 0000000..235414d --- /dev/null +++ b/libc/sysdeps/linux/mips/cacheflush.c @@ -0,0 +1,30 @@ +/* _flush_cache system call for Linux/MIPS. + Copyright (C) 2003 Christophe Massiot + + The uClibc 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. + + The uClibc 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 the uClibc Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __NR_cacheflush +_syscall3(int, cacheflush, void *, addr, const int, nbytes, const int, op) +strong_alias(cacheflush, _flush_cache) +#endif + +#ifdef __NR_cachectl +_syscall3(int, cachectl, void *, addr, const int, nbytes, const int, op) +#endif diff --git a/libc/sysdeps/linux/mips/clone.S b/libc/sysdeps/linux/mips/clone.S new file mode 100644 index 0000000..716cd99 --- /dev/null +++ b/libc/sysdeps/linux/mips/clone.S @@ -0,0 +1,127 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include +#define _ERRNO_H 1 +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ + + .text +.globl clone ; + .align 2; + .type clone,@function; + .ent clone, 0; + +clone: + .frame sp, 4*SZREG, sp +#ifdef __PIC__ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .set noreorder + .cpload $25 + .set reorder + subu sp,32 + .cprestore 16 +#else /* N32 */ + PTR_SUBU sp,32 /* fn, arg, gp, pad */ + .cpsetup $25, 16, clone +#endif /* N32 */ +#else + subu sp,32 +#endif + + + /* Sanity check arguments. */ + li v0,EINVAL + beqz a0,error /* No NULL function pointers. */ + beqz a1,error /* No NULL stack pointers. */ + +#if _MIPS_SIM != _MIPS_SIM_ABI32 + and a1,~(16-1) /* force alignment */ +#endif + PTR_SUBU a1,32 /* Reserve argument save space. */ + PTR_S a0,0(a1) /* Save function pointer. */ + PTR_S a3,PTRSIZE(a1) /* Save argument pointer. */ + + + /* Do the system call */ + move a0,a2 + li v0,__NR_clone + syscall + + bnez a3,error + beqz v0,__thread_start + + /* Successful return from the parent */ +#if _MIPS_SIM != _MIPS_SIM_ABI32 + .cpreturn +#endif + PTR_ADDU sp,32 + j $31 ; nop + + /* Something bad happened -- no child created */ +error: +#if _MIPS_SIM != _MIPS_SIM_ABI32 + .cpreturn +#endif + PTR_ADDU sp,32 + + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + +#ifdef __PIC__ + PTR_LA t9,__syscall_error + jr t9 +#else + j __syscall_error +#endif + .end clone + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + +.globl __thread_start; + .align 2; + .ent __thread_start, 0; + +__thread_start: +#if _MIPS_SIM == _MIPS_SIM_ABI32 + /* cp is already loaded. */ + .cprestore 16 +#endif + /* The stackframe has been created on entry of clone(). */ + /* Restore the arg for user's function. */ + PTR_L t9,0(sp) /* Function pointer. */ + PTR_L a0,PTRSIZE(sp) /* Argument pointer. */ + + /* Call the user's function. */ + jal t9 + + /* Call _exit rather than doing it inline for breakpoint purposes. */ + move a0,v0 + jal HIDDEN_JUMPTARGET(_exit) + .end __thread_start diff --git a/libc/sysdeps/linux/mips/crt1.S b/libc/sysdeps/linux/mips/crt1.S new file mode 100644 index 0000000..2e38cf0 --- /dev/null +++ b/libc/sysdeps/linux/mips/crt1.S @@ -0,0 +1,148 @@ +/* Startup code compliant to the ELF Mips ABI. + Copyright (C) 1995, 1997, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#include +#include + + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + v0 ($2) Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp ($29) The stack contains the arguments and environment: + 0(%esp) argc + 4(%esp) argv[0] + ... + (4*argc)(%esp) NULL + (4*(argc+1))(%esp) envp[0] + ... + NULL + ra ($31) The return address register is set to zero so that programs + that search backword through stack frames recognize the last + stack frame. +*/ + + +/* We need to call: + __uClibc_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) +*/ + +.text + .globl __start + .type __start,@function + .type _init,@function + .type _fini,@function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,@function + .type __uClibc_main,@function + +__start: +#ifdef __PIC__ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .set noreorder + move $0, $31 /* Save old ra. */ + bal 10f /* Find addr of cpload. */ + nop +10: + .cpload $31 + move $31, $0 + .set reorder +#else + move $0, $31; /* Save old ra. */ + .set noreorder + bal 10f /* Find addr of .cpsetup. */ + nop +10: + .set reorder + .cpsetup $31, $25, 10b + move $31, $0 +#endif +#else + la $28, _gp /* Setup GP correctly if we're non-PIC. */ + move $31, $0 +#endif + + + PTR_LA $4, main /* main */ + PTR_L $5, 0($29) /* argc */ + PTR_ADDIU $6, $29, PTRSIZE /* argv */ + + /* Allocate space on the stack for seven arguments and + * make sure the stack is aligned to double words (8 bytes) */ + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + and $29, -2 * 4 + subu $29, 32 + la $7, _init /* init */ + la $8, _fini + sw $8, 16($29) /* fini */ + sw $2, 20($29) /* rtld_fini */ + sw $29, 24($29) /* stack_end */ +#else + and $29, -2 * PTRSIZE + PTR_LA $7, _init /* init */ + PTR_LA $8, _fini /* fini */ + move $9, $2 /* rtld_fini */ + move $10, $29 /* stack_end */ +#endif + jal __uClibc_main +hlt: + /* Crash if somehow `__uClibc_main' returns anyway. */ + b hlt +.size __start,.-__start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + + diff --git a/libc/sysdeps/linux/mips/crti.S b/libc/sysdeps/linux/mips/crti.S new file mode 100644 index 0000000..9311a73 --- /dev/null +++ b/libc/sysdeps/linux/mips/crti.S @@ -0,0 +1,158 @@ +#include "sgidefs.h" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .file 1 "initfini.c" + .section .mdebug.abi32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 16, extra= 8 + .mask 0x90000000,-4 + .fmask 0x00000000,0 + .set noreorder + .cpload $25 + .set reorder + subu $sp,$sp,32 + .cprestore 16 + sw $31,28($sp) + sw $28,24($sp) +#APP + + .align 2 + .end _init + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 16, extra= 8 + .mask 0x90000000,-4 + .fmask 0x00000000,0 + .set noreorder + .cpload $25 + .set reorder + subu $sp,$sp,32 + .cprestore 16 + sw $31,28($sp) + sw $28,24($sp) +#APP + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + .file 1 "initfini.c" + .section .mdebug.abiN32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .align 3 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + addiu $sp,$sp,-16 + sd $28,0($sp) + lui $28,%hi(%neg(%gp_rel(_init))) + addu $28,$28,$25 + addiu $28,$28,%lo(%neg(%gp_rel(_init))) + sd $31,8($sp) +#APP + + .align 3 + .end _init + + .section .fini +#NO_APP + .align 2 + .align 3 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + addiu $sp,$sp,-16 + sd $28,0($sp) + lui $28,%hi(%neg(%gp_rel(_fini))) + addu $28,$28,$25 + addiu $28,$28,%lo(%neg(%gp_rel(_fini))) + sd $31,8($sp) +#APP + .align 3 + .end _fini + + .ident "GCC: (GNU) 3.4.3" +#else /* N64 */ + .file 1 "initfini.c" + .section .mdebug.abi64 + .previous + .abicalls +#APP + + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 0, extra= 16 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + dsubu $sp,$sp,32 + sd $31,24($sp) + sd $28,16($sp) + .set noat + lui $1,%hi(%neg(%gp_rel(_init))) + addiu $1,$1,%lo(%neg(%gp_rel(_init))) + daddu $gp,$1,$25 + .set at +#APP + + .align 2 + .end _init + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 0, extra= 16 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + dsubu $sp,$sp,32 + sd $31,24($sp) + sd $28,16($sp) + .set noat + lui $1,%hi(%neg(%gp_rel(_fini))) + addiu $1,$1,%lo(%neg(%gp_rel(_fini))) + daddu $gp,$1,$25 + .set at +#APP + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" +#endif /* N64 */ diff --git a/libc/sysdeps/linux/mips/crtn.S b/libc/sysdeps/linux/mips/crtn.S new file mode 100644 index 0000000..cedd593 --- /dev/null +++ b/libc/sysdeps/linux/mips/crtn.S @@ -0,0 +1,145 @@ +#include "sgidefs.h" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .file 1 "initfini.c" + .section .mdebug.abi32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +#NO_APP + lw $31,28($sp) + #nop + .set noreorder + .set nomacro + j $31 + addu $sp,$sp,32 + .set macro + .set reorder + + .end _init +#APP + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +#NO_APP + lw $31,28($sp) + #nop + .set noreorder + .set nomacro + j $31 + addu $sp,$sp,32 + .set macro + .set reorder + + .end _fini +#APP + + .ident "GCC: (GNU) 3.3.2" +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + .file 1 "initfini.c" + .section .mdebug.abiN32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .align 3 + .globl _init + .ent _init + .type _init, @function +#NO_APP + ld $31,8($sp) + ld $28,0($sp) + .set noreorder + .set nomacro + j $31 + addiu $sp,$sp,16 + .set macro + .set reorder + + .end _init +#APP + + .section .fini +#NO_APP + .align 2 + .align 3 + .globl _fini + .ent _fini + .type _fini, @function +#NO_APP + ld $31,8($sp) + ld $28,0($sp) + .set noreorder + .set nomacro + j $31 + addiu $sp,$sp,16 + .set macro + .set reorder + + .end _fini +#APP + + .ident "GCC: (GNU) 3.4.3" +#else /* N64 */ + .file 1 "initfini.c" + .section .mdebug.abi64 + .previous + .abicalls +#APP + + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +#NO_APP + ld $31,24($sp) + ld $28,16($sp) + #nop + .set noreorder + .set nomacro + j $31 + daddu $sp,$sp,32 + .set macro + .set reorder + + .end _init +#APP + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +#NO_APP + ld $31,24($sp) + ld $28,16($sp) + #nop + .set noreorder + .set nomacro + j $31 + daddu $sp,$sp,32 + .set macro + .set reorder + + .end _fini +#APP + + .ident "GCC: (GNU) 3.3.2" +#endif /* N64 */ diff --git a/libc/sysdeps/linux/mips/fpu_control.h b/libc/sysdeps/linux/mips/fpu_control.h new file mode 100644 index 0000000..c58b235 --- /dev/null +++ b/libc/sysdeps/linux/mips/fpu_control.h @@ -0,0 +1,100 @@ +/* FPU control word bits. Mips version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe and Ralf Baechle. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/mips/mmap.c b/libc/sysdeps/linux/mips/mmap.c new file mode 100644 index 0000000..039d5ed --- /dev/null +++ b/libc/sysdeps/linux/mips/mmap.c @@ -0,0 +1,27 @@ +/* Use new style mmap for mips */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +#if 0 +/* For now, leave mmap using mmap1 since mmap2 seems + * to have issues (i.e. it doesn't work 100% properly). + */ +#ifdef __NR_mmap2 +# undef __NR_mmap +# define __NR_mmap __NR_mmap2 +#endif +#endif + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/mips/pipe.S b/libc/sysdeps/linux/mips/pipe.S new file mode 100644 index 0000000..8b30236 --- /dev/null +++ b/libc/sysdeps/linux/mips/pipe.S @@ -0,0 +1,45 @@ +/* pipe system call for Linux/MIPS */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */ + +#include +#include +#include +#include + + .globl pipe + .ent pipe, 0 + .type pipe,@function +pipe: +#ifdef __PIC__ + SETUP_GP +#endif + li v0,__NR_pipe + syscall + bnez a3, 1f + sw v0, 0(a0) + sw v1, 4(a0) + li v0, 0 + j ra +1: + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + +#ifdef __PIC__ + SETUP_GP64(v0, pipe) + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + j __syscall_error +#endif +1: + .end pipe + .size pipe,.-pipe +libc_hidden_def(pipe) diff --git a/libc/sysdeps/linux/mips/posix_fadvise.c b/libc/sysdeps/linux/mips/posix_fadvise.c new file mode 100644 index 0000000..8546d96 --- /dev/null +++ b/libc/sysdeps/linux/mips/posix_fadvise.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for MIPS uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL(err); +# if _MIPS_SIM == _ABIO32 + int ret = INTERNAL_SYSCALL(fadvise64, err, 7, fd, 0, + __LONG_LONG_PAIR ((long) (offset >> 31), (long) offset), + __LONG_LONG_PAIR ((long) (len >> 31), (long) len), + advice); +# else /* N32 || N64 */ + int ret = INTERNAL_SYSCALL(fadvise64, err, 4, fd, offset, len, advice); +# endif + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} diff --git a/libc/sysdeps/linux/mips/posix_fadvise64.c b/libc/sysdeps/linux/mips/posix_fadvise64.c new file mode 100644 index 0000000..d9b89d1 --- /dev/null +++ b/libc/sysdeps/linux/mips/posix_fadvise64.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for MIPS uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL(err); +# if _MIPS_SIM == _MIPS_SIM_ABI32 + int ret = INTERNAL_SYSCALL(fadvise64, err, 7, fd, 0, + __LONG_LONG_PAIR ((long) (offset >> 32), (long) offset), + __LONG_LONG_PAIR ((long) (len >> 32), (long) len), + advice); +# else /* N32 || N64 */ + int ret = INTERNAL_SYSCALL(fadvise64, err, 4, fd, offset, len, advice); +# endif + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/mips/pread_write.c b/libc/sysdeps/linux/mips/pread_write.c new file mode 100644 index 0000000..b1cce02 --- /dev/null +++ b/libc/sysdeps/linux/mips/pread_write.c @@ -0,0 +1,115 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include +#include + +#ifdef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pread +# error "__NR_pread and __NR_pread64 both defined???" +# endif +# define __NR_pread __NR_pread64 +#endif + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + + +#ifdef __NR_pread + +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR___libc_pread __NR_pread +_syscall4(ssize_t, __libc_pread, int, fd, void *, buf, size_t, count, off_t, offset) +weak_alias (__libc_pread, pread) +# ifdef __UCLIBC_HAS_LFS__ +# define __NR___libc_pread64 __NR_pread +_syscall4(ssize_t, __libc_pread64, int, fd, void *, buf, size_t, count, off64_t, offset) +weak_alias (__libc_pread64, pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +# else /* O32 || N32 */ +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,0,__LONG_LONG_PAIR(offset>>31,offset))); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +# endif /* O32 || N32 */ + +#endif /* __NR_pread */ + +/**********************************************************************/ + +#ifdef __NR_pwrite64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pwrite +# error "__NR_pwrite and __NR_pwrite64 both defined???" +# endif +# define __NR_pwrite __NR_pwrite64 +#endif + +#ifdef __NR_pwrite + +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR___libc_pwrite __NR_pwrite +_syscall4(ssize_t, __libc_pwrite, int, fd, const void *, buf, size_t, count, off_t, offset) +weak_alias (__libc_pwrite, pwrite) +# ifdef __UCLIBC_HAS_LFS__ +# define __NR___libc_pwrite64 __NR_pwrite +_syscall4(ssize_t, __libc_pwrite64, int, fd, const void *, buf, size_t, count, off64_t, offset) +weak_alias (__libc_pwrite64, pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +# else /* O32 || N32 */ +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd,buf,count,0,__LONG_LONG_PAIR(offset>>31,offset))); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +# endif /* O32 || N32 */ +#endif /* __NR_pwrite */ diff --git a/libc/sysdeps/linux/mips/readahead.c b/libc/sysdeps/linux/mips/readahead.c new file mode 100644 index 0000000..9157c27 --- /dev/null +++ b/libc/sysdeps/linux/mips/readahead.c @@ -0,0 +1,41 @@ +/* Provide kernel hint to read ahead. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +#include <_lfs_64.h> +# ifdef __NR_readahead + +ssize_t readahead(int fd, off64_t offset, size_t count) +{ +# if _MIPS_SIM == _ABIO32 + return INLINE_SYSCALL (readahead, 5, fd, 0, + __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) offset), + count); +# else /* N32 || N64 */ + return INLINE_SYSCALL (readahead, 3, fd, offset, count); +# endif +} + +# endif +#endif diff --git a/libc/sysdeps/linux/mips/setjmp.S b/libc/sysdeps/linux/mips/setjmp.S new file mode 100644 index 0000000..226f755 --- /dev/null +++ b/libc/sysdeps/linux/mips/setjmp.S @@ -0,0 +1,61 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* The function __sigsetjmp_aux saves all the registers, but it can't + reliably access the stack or frame pointers, so we pass them in as + extra arguments. */ +#ifdef __PIC__ + .option pic2 +#endif + + +.text +.global __sigsetjmp +.align 2; +.ent __sigsetjmp,0; +.type __sigsetjmp,@function + +__sigsetjmp: +#ifdef __PIC__ + .set noreorder +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .cpload t9 +#else + .cpsetup t9, v0, __sigsetjmp +#endif + .set reorder +#endif + move a2, sp +#ifdef fp + move a3, fp +#else + move a3, $fp +#endif +#ifdef __PIC__ + PTR_LA t9, __sigsetjmp_aux +#if _MIPS_SIM != _MIPS_SIM_ABI32 + .cpreturn +#endif + jr t9 +#else + j __sigsetjmp_aux +#endif + .end __sigsetjmp diff --git a/libc/sysdeps/linux/mips/setjmp_aux.c b/libc/sysdeps/linux/mips/setjmp_aux.c new file mode 100644 index 0000000..751b32d --- /dev/null +++ b/libc/sysdeps/linux/mips/setjmp_aux.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* This function is only called via the assembly language routine + __sigsetjmp, which arranges to pass in the stack pointer and the frame + pointer. We do things this way because it's difficult to reliably + access them in C. */ + +extern int __sigjmp_save (sigjmp_buf, int); + +int +#if _MIPS_SIM == _MIPS_SIM_ABI64 +__sigsetjmp_aux (jmp_buf env, int savemask, long sp, long fp) +#else /* O32 || N32 */ +__sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp) +#endif /* O32 || N32 */ +{ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + /* Store the floating point callee-saved registers... */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0])); + __asm__ __volatile__ ("s.d $f25, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1])); + __asm__ __volatile__ ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2])); + __asm__ __volatile__ ("s.d $f27, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3])); + __asm__ __volatile__ ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4])); + __asm__ __volatile__ ("s.d $f29, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5])); + __asm__ __volatile__ ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[6])); + __asm__ __volatile__ ("s.d $f31, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[7])); +#else /* O32 || N32 */ + __asm__ __volatile__ ("s.d $f20, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0])); + __asm__ __volatile__ ("s.d $f22, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1])); + __asm__ __volatile__ ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2])); + __asm__ __volatile__ ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3])); + __asm__ __volatile__ ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4])); + __asm__ __volatile__ ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5])); +#endif /* O32 || N32 */ +#endif + + /* .. and the PC; */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("sd $31, %0" : : "m" (env[0].__jmpbuf[0].__pc)); +#else + __asm__ __volatile__ ("sw $31, %0" : : "m" (env[0].__jmpbuf[0].__pc)); +#endif + + /* .. and the stack pointer; */ + env[0].__jmpbuf[0].__sp = (void *) sp; + + /* .. and the FP; it'll be in s8. */ + env[0].__jmpbuf[0].__fp = (void *) fp; + + /* .. and the GP; */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("sd $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp)); +#else + __asm__ __volatile__ ("sw $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp)); +#endif + + /* .. and the callee-saved registers; */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) + __asm__ __volatile__ ("sw $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0])); + __asm__ __volatile__ ("sw $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1])); + __asm__ __volatile__ ("sw $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2])); + __asm__ __volatile__ ("sw $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3])); + __asm__ __volatile__ ("sw $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4])); + __asm__ __volatile__ ("sw $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5])); + __asm__ __volatile__ ("sw $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6])); + __asm__ __volatile__ ("sw $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7])); +#else /* N32 || N64 */ + __asm__ __volatile__ ("sd $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0])); + __asm__ __volatile__ ("sd $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1])); + __asm__ __volatile__ ("sd $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2])); + __asm__ __volatile__ ("sd $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3])); + __asm__ __volatile__ ("sd $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4])); + __asm__ __volatile__ ("sd $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5])); + __asm__ __volatile__ ("sd $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6])); + __asm__ __volatile__ ("sd $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7])); +#endif /* N32 || N64 */ + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + /* .. and finally get and reconstruct the floating point csr. */ + __asm__ ("cfc1 %0, $31" : "=r" (env[0].__jmpbuf[0].__fpc_csr)); +#endif + + /* Save the signal mask if requested. */ + return __sigjmp_save (env, savemask); +} diff --git a/libc/sysdeps/linux/mips/sgidefs.h b/libc/sysdeps/linux/mips/sgidefs.h new file mode 100644 index 0000000..74509fd --- /dev/null +++ b/libc/sysdeps/linux/mips/sgidefs.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1996, 1997, 1998, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SGIDEFS_H +#define _SGIDEFS_H 1 + +/* + * A crude hack to stop + */ +#undef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * And remove any damage it might have already done + */ +#undef _MIPS_ISA_MIPS1 +#undef _MIPS_ISA_MIPS2 +#undef _MIPS_ISA_MIPS3 +#undef _MIPS_ISA_MIPS4 +#undef _MIPS_ISA_MIPS5 +#undef _MIPS_ISA_MIPS32 +#undef _MIPS_ISA_MIPS64 + +#undef _MIPS_SIM_ABI32 +#undef _MIPS_SIM_NABI32 +#undef _MIPS_SIM_ABI64 + +/* + * Definitions for the ISA level + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 + +/* + * Subprogram calling convention + */ +#ifndef _ABIO32 +# define _ABIO32 1 +#endif +#define _MIPS_SIM_ABI32 _ABIO32 + +#ifndef _ABIN32 +# define _ABIN32 2 +#endif +#define _MIPS_SIM_NABI32 _ABIN32 + +#ifndef _ABI64 +# define _ABI64 3 +#endif +#define _MIPS_SIM_ABI64 _ABI64 + +#endif /* sgidefs.h */ diff --git a/libc/sysdeps/linux/mips/sigaction.c b/libc/sysdeps/linux/mips/sigaction.c new file mode 100644 index 0000000..39d38b8 --- /dev/null +++ b/libc/sysdeps/linux/mips/sigaction.c @@ -0,0 +1,158 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + +#ifdef __NR_rt_sigaction + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +#if _MIPS_SIM != _ABIO32 + +# ifdef __NR_rt_sigreturn +static void restore_rt (void) __asm__ ("__restore_rt"); +# endif +# ifdef __NR_sigreturn +static void restore (void) __asm__ ("__restore"); +# endif +#endif + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask)); + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER +# if _MIPS_SIM == _ABIO32 + kact.sa_restorer = act->sa_restorer; +# else + kact.sa_restorer = &restore_rt; +# endif +# endif + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = __syscall_rt_sigaction(sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (oact->sa_mask)); + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; +} + + +#else +extern void restore (void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER +# if _MIPS_SIM == _ABIO32 + kact.sa_restorer = act->sa_restorer; +# else + kact.sa_restorer = &restore_rt; +# endif +# endif + } + + result = __syscall_sigaction(sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL); + + if (result < 0) { + __set_errno(-result); + return -1; + } + + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; +} + +#endif + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2 (name, syscall) +#define RESTORE2(name, syscall) \ +__asm__ ( \ + ".align 4\n" \ + "__" #name ":\n" \ + " li $2, " #syscall "\n" \ + " syscall\n" \ + ); + +/* The return code for realtime-signals. */ +#if _MIPS_SIM != _ABIO32 +# ifdef __NR_rt_sigreturn +RESTORE (restore_rt, __NR_rt_sigreturn) +# endif +# ifdef __NR_sigreturn +RESTORE (restore, __NR_sigreturn) +# endif +#endif diff --git a/libc/sysdeps/linux/mips/sys/asm.h b/libc/sysdeps/linux/mips/sys/asm.h new file mode 100644 index 0000000..76f6af3 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/asm.h @@ -0,0 +1,473 @@ +/* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ASM_H +#define _SYS_ASM_H + +#include + +#ifndef CAT +# ifdef __STDC__ +# define __CAT(str1,str2) str1##str2 +# else +# define __CAT(str1,str2) str1/**/str2 +# endif +# define CAT(str1,str2) __CAT(str1,str2) +#endif + +/* + * Macros to handle different pointer/register sizes for 32/64-bit code + * + * 64 bit address space isn't used yet, so we may use the R3000 32 bit + * defines for now. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define PTR .word +# define PTRSIZE 4 +# define PTRLOG 2 +#elif (_MIPS_SIM == _MIPS_SIM_ABI64) +# define PTR .dword +# define PTRSIZE 8 +# define PTRLOG 3 +#endif + +/* + * PIC specific declarations + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +# ifdef __PIC__ +# define CPRESTORE(register) \ + .cprestore register +# define CPLOAD(register) \ + .cpload register +# else +# define CPRESTORE(register) +# define CPLOAD(register) +# endif + +# define CPADD(register) \ + .cpadd register + +/* + * Set gp when at 1st instruction + */ +# define SETUP_GP \ + .set noreorder; \ + .cpload $25; \ + .set reorder +/* Set gp when not at 1st instruction */ +# define SETUP_GPX(r) \ + .set noreorder; \ + move r, $31; /* Save old ra. */ \ + bal 10f; /* Find addr of cpload. */ \ + nop; \ +10: \ + .cpload $31; \ + move $31, r; \ + .set reorder +# define SETUP_GPX_L(r, l) \ + .set noreorder; \ + move r, $31; /* Save old ra. */ \ + bal l; /* Find addr of cpload. */ \ + nop; \ +l: \ + .cpload $31; \ + move $31, r; \ + .set reorder +# define SAVE_GP(x) \ + .cprestore x /* Save gp trigger t9/jalr conversion. */ +# define SETUP_GP64(a, b) +# define SETUP_GPX64(a, b) +# define SETUP_GPX64_L(cp_reg, ra_save, l) +# define RESTORE_GP64 +# define USE_ALT_CP(a) +#else /* (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) */ +/* + * For callee-saved gp calling convention: + */ +# define SETUP_GP +# define SETUP_GPX(r) +# define SETUP_GPX_L(r, l) +# define SAVE_GP(x) + +# define SETUP_GP64(gpoffset, proc) \ + .cpsetup $25, gpoffset, proc +# define SETUP_GPX64(cp_reg, ra_save) \ + move ra_save, $31; /* Save old ra. */ \ + .set noreorder; \ + bal 10f; /* Find addr of .cpsetup. */ \ + nop; \ +10: \ + .set reorder; \ + .cpsetup $31, cp_reg, 10b; \ + move $31, ra_save +# define SETUP_GPX64_L(cp_reg, ra_save, l) \ + move ra_save, $31; /* Save old ra. */ \ + .set noreorder; \ + bal l; /* Find addr of .cpsetup. */ \ + nop; \ +l: \ + .set reorder; \ + .cpsetup $31, cp_reg, l; \ + move $31, ra_save +# define RESTORE_GP64 \ + .cpreturn +/* Use alternate register for context pointer. */ +# define USE_ALT_CP(reg) \ + .cplocal reg +#endif /* _MIPS_SIM != _MIPS_SIM_ABI32 */ + +/* + * Stack Frame Definitions + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +# define NARGSAVE 4 /* Space for 4 argument registers must be allocated. */ +#endif +#if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +# define NARGSAVE 0 /* No caller responsibilities. */ +#endif + + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol,@function; \ + .ent symbol,0; \ +symbol: .frame sp,0,ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol,@function; \ + .ent symbol,0; \ +symbol: .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#ifndef END +# define END(function) \ + .end function; \ + .size function,.-function +#endif + +/* + * EXPORT - export definition of symbol + */ +#define EXPORT(symbol) \ + .globl symbol; \ +symbol: + +/* + * ABS - export absolute symbol + */ +#define ABS(symbol,value) \ + .globl symbol; \ +symbol = value + +#define PANIC(msg) \ + .set push; \ + .set reorder; \ + la a0,8f; \ + jal panic; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) + +/* + * Print formated string + */ +#define PRINT(string) \ + .set push; \ + .set reorder; \ + la a0,8f; \ + jal printk; \ + .set pop; \ + TEXT(string) + +#define TEXT(msg) \ + .data; \ +8: .asciiz msg; \ + .previous; + +/* + * Build text tables + */ +#define TTABLE(string) \ + .text; \ + .word 1f; \ + .previous; \ + .data; \ +1: .asciz string; \ + .previous + +/* + * MIPS IV pref instruction. + * Use with .set noreorder only! + * + * MIPS IV implementations are free to treat this as a nop. The R5000 + * is one of them. So we should have an option not to use this instruction. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define PREF(hint,addr) \ + pref hint,addr +# define PREFX(hint,addr) \ + prefx hint,addr +#else +# define PREF +# define PREFX +#endif + +/* + * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. + */ +#if _MIPS_ISA == _MIPS_ISA_MIPS1 +# define MOVN(rd,rs,rt) \ + .set push; \ + .set reorder; \ + beqz rt,9f; \ + move rd,rs; \ + .set pop; \ +9: +# define MOVZ(rd,rs,rt) \ + .set push; \ + .set reorder; \ + bnez rt,9f; \ + move rd,rt; \ + .set pop; \ +9: +#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) +# define MOVN(rd,rs,rt) \ + .set push; \ + .set noreorder; \ + bnezl rt,9f; \ + move rd,rs; \ + .set pop; \ +9: +# define MOVZ(rd,rs,rt) \ + .set push; \ + .set noreorder; \ + beqzl rt,9f; \ + movz rd,rs; \ + .set pop; \ +9: +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define MOVN(rd,rs,rt) \ + movn rd,rs,rt +# define MOVZ(rd,rs,rt) \ + movz rd,rs,rt +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */ + +/* + * Stack alignment + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define ALSZ 15 +# define ALMASK ~15 +#else +# define ALSZ 7 +# define ALMASK ~7 +#endif + +/* + * Size of a register + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define SZREG 8 +#else +# define SZREG 4 +#endif + +/* + * Use the following macros in assemblercode to load/store registers, + * pointers etc. + */ +#if (SZREG == 4) +# define REG_S sw +# define REG_L lw +#else +# define REG_S sd +# define REG_L ld +#endif + +/* + * How to add/sub/load/store/shift C int variables. + */ +#if (_MIPS_SZINT == 32) +# define INT_ADD add +# define INT_ADDI addi +# define INT_ADDU addu +# define INT_ADDIU addiu +# define INT_SUB add +# define INT_SUBI subi +# define INT_SUBU subu +# define INT_SUBIU subu +# define INT_L lw +# define INT_S sw +#endif + +#if (_MIPS_SZINT == 64) +# define INT_ADD dadd +# define INT_ADDI daddi +# define INT_ADDU daddu +# define INT_ADDIU daddiu +# define INT_SUB dadd +# define INT_SUBI dsubi +# define INT_SUBU dsubu +# define INT_SUBIU dsubu +# define INT_L ld +# define INT_S sd +#endif + +/* + * How to add/sub/load/store/shift C long variables. + */ +#if (_MIPS_SZLONG == 32) +# define LONG_ADD add +# define LONG_ADDI addi +# define LONG_ADDU addu +# define LONG_ADDIU addiu +# define LONG_SUB add +# define LONG_SUBI subi +# define LONG_SUBU subu +# define LONG_SUBIU subu +# define LONG_L lw +# define LONG_S sw +# define LONG_SLL sll +# define LONG_SLLV sllv +# define LONG_SRL srl +# define LONG_SRLV srlv +# define LONG_SRA sra +# define LONG_SRAV srav +#endif + +#if (_MIPS_SZLONG == 64) +# define LONG_ADD dadd +# define LONG_ADDI daddi +# define LONG_ADDU daddu +# define LONG_ADDIU daddiu +# define LONG_SUB dadd +# define LONG_SUBI dsubi +# define LONG_SUBU dsubu +# define LONG_SUBIU dsubu +# define LONG_L ld +# define LONG_S sd +# define LONG_SLL dsll +# define LONG_SLLV dsllv +# define LONG_SRL dsrl +# define LONG_SRLV dsrlv +# define LONG_SRA dsra +# define LONG_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift pointers. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32) +# define PTR_ADD add +# define PTR_ADDI addi +# define PTR_ADDU addu +# define PTR_ADDIU addiu +# define PTR_SUB add +# define PTR_SUBI subi +# define PTR_SUBU subu +# define PTR_SUBIU subu +# define PTR_L lw +# define PTR_LA la +# define PTR_S sw +# define PTR_SLL sll +# define PTR_SLLV sllv +# define PTR_SRL srl +# define PTR_SRLV srlv +# define PTR_SRA sra +# define PTR_SRAV srav + +# define PTR_SCALESHIFT 2 +#endif + +#if _MIPS_SIM == _MIPS_SIM_NABI32 +# define PTR_ADD add +# define PTR_ADDI addi +# define PTR_ADDU add /* no u */ +# define PTR_ADDIU addi /* no u */ +# define PTR_SUB add +# define PTR_SUBI subi +# define PTR_SUBU sub /* no u */ +# define PTR_SUBIU sub /* no u */ +# define PTR_L lw +# define PTR_LA la +# define PTR_S sw +# define PTR_SLL sll +# define PTR_SLLV sllv +# define PTR_SRL srl +# define PTR_SRLV srlv +# define PTR_SRA sra +# define PTR_SRAV srav + +# define PTR_SCALESHIFT 2 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 64 /* o64??? */) \ + || _MIPS_SIM == _MIPS_SIM_ABI64 +# define PTR_ADD dadd +# define PTR_ADDI daddi +# define PTR_ADDU daddu +# define PTR_ADDIU daddiu +# define PTR_SUB dadd +# define PTR_SUBI dsubi +# define PTR_SUBU dsubu +# define PTR_SUBIU dsubu +# define PTR_L ld +# define PTR_LA dla +# define PTR_S sd +# define PTR_SLL dsll +# define PTR_SLLV dsllv +# define PTR_SRL dsrl +# define PTR_SRLV dsrlv +# define PTR_SRA dsra +# define PTR_SRAV dsrav + +# define PTR_SCALESHIFT 3 +#endif + +/* + * Some cp0 registers were extended to 64bit for MIPS III. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) +# define MFC0 mfc0 +# define MTC0 mtc0 +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define MFC0 dmfc0 +# define MTC0 dmtc0 +#endif + +#endif /* sys/asm.h */ diff --git a/libc/sysdeps/linux/mips/sys/cachectl.h b/libc/sysdeps/linux/mips/sys/cachectl.h new file mode 100644 index 0000000..a93e1fb --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/cachectl.h @@ -0,0 +1,42 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_CACHECTL_H +#define _SYS_CACHECTL_H 1 + +#include + +/* + * Get the kernel definition for the op bits. + */ +#include + +__BEGIN_DECLS + +#ifdef __USE_MISC +extern int cachectl (void *addr, __const int nbytes, __const int op) __THROW; +#endif +extern int __cachectl (void *addr, __const int nbytes, __const int op) __THROW; +#ifdef __USE_MISC +extern int cacheflush (void *addr, __const int nbytes, __const int op) __THROW; +#endif +extern int _flush_cache (char *addr, __const int nbytes, __const int op) __THROW; + +__END_DECLS + +#endif /* sys/cachectl.h */ diff --git a/libc/sysdeps/linux/mips/sys/fpregdef.h b/libc/sysdeps/linux/mips/sys/fpregdef.h new file mode 100644 index 0000000..3781152 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/fpregdef.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FPREGDEF_H +#define _SYS_FPREGDEF_H + +/* + * These definitions only cover the R3000-ish 16/32 register model. + * But we're trying to be R3000 friendly anyway ... + */ +#define fv0 $f0 /* return value */ +#define fv0f $f1 +#define fv1 $f2 +#define fv1f $f3 +#define fa0 $f12 /* argument registers */ +#define fa0f $f13 +#define fa1 $f14 +#define fa1f $f15 +#define ft0 $f4 /* caller saved */ +#define ft0f $f5 +#define ft1 $f6 +#define ft1f $f7 +#define ft2 $f8 +#define ft2f $f9 +#define ft3 $f10 +#define ft3f $f11 +#define ft4 $f16 +#define ft4f $f17 +#define ft5 $f18 +#define ft5f $f19 +#define fs0 $f20 /* callee saved */ +#define fs0f $f21 +#define fs1 $f22 +#define fs1f $f23 +#define fs2 $f24 +#define fs2f $f25 +#define fs3 $f26 +#define fs3f $f27 +#define fs4 $f28 +#define fs4f $f29 +#define fs5 $f30 +#define fs5f $f31 + +#define fcr31 $31 /* FPU status register */ + +#endif /* sys/fpregdef.h */ diff --git a/libc/sysdeps/linux/mips/sys/procfs.h b/libc/sysdeps/linux/mips/sys/procfs.h new file mode 100644 index 0000000..a21652e --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/procfs.h @@ -0,0 +1,112 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include + +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/mips/sys/regdef.h b/libc/sysdeps/linux/mips/sys/regdef.h new file mode 100644 index 0000000..9d2c4c1 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/regdef.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REGDEF_H +#define _SYS_REGDEF_H + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#if _MIPS_SIM != _MIPS_SIM_ABI32 +#define a4 $8 +#define a5 $9 +#define a6 $10 +#define a7 $11 +#define t0 $12 +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define ta0 a4 +#define ta1 a5 +#define ta2 a6 +#define ta3 a7 +#else /* if _MIPS_SIM == _MIPS_SIM_ABI32 */ +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define ta0 t4 +#define ta1 t5 +#define ta2 t6 +#define ta3 t7 +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* _SYS_REGDEF_H */ diff --git a/libc/sysdeps/linux/mips/sys/sysmips.h b/libc/sysdeps/linux/mips/sys/sysmips.h new file mode 100644 index 0000000..6a63dc2 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/sysmips.h @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSMIPS_H +#define _SYS_SYSMIPS_H 1 + +#include + +/* + * Commands for the sysmips(2) call + * + * sysmips(2) is deprecated - though some existing software uses it. + * We only support the following commands. Sysmips exists for compatibility + * purposes only so new software should avoid it. + */ +#define SETNAME 1 /* set hostname */ +#define FLUSH_CACHE 3 /* writeback and invalidate caches */ +#define MIPS_FIXADE 7 /* control address error fixing */ +#define MIPS_RDNVRAM 10 /* read NVRAM */ +#define MIPS_ATOMIC_SET 2001 /* atomically set variable */ + +__BEGIN_DECLS + +extern int sysmips (__const int cmd, __const long arg1, + __const int arg2, __const int arg3) __THROW; + +__END_DECLS + +#endif /* sys/sysmips.h */ diff --git a/libc/sysdeps/linux/mips/sys/tas.h b/libc/sysdeps/linux/mips/sys/tas.h new file mode 100644 index 0000000..1183b86 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/tas.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TAS_H +#define _SYS_TAS_H 1 + +#include +#include + +__BEGIN_DECLS + +extern int _test_and_set (int *p, int v) __THROW; + +#ifdef __USE_EXTERN_INLINES + +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif + +_EXTERN_INLINE int +__NTH (_test_and_set (int *p, int v)) +{ + int r, t; + + __asm__ __volatile__ + ("/* Inline test and set */\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif + "ll %0,%3\n\t" + "move %1,%4\n\t" + "beq %0,%4,2f\n\t" + "sc %1,%2\n\t" + ".set pop\n\t" + "beqz %1,1b\n" + "2:\n\t" + "/* End test and set */" + : "=&r" (r), "=&r" (t), "=m" (*p) + : "m" (*p), "r" (v) + : "memory"); + + return r; +} + +#endif /* __USE_EXTERN_INLINES */ + +__END_DECLS + +#endif /* sys/tas.h */ diff --git a/libc/sysdeps/linux/mips/sys/ucontext.h b/libc/sysdeps/linux/mips/sys/ucontext.h new file mode 100644 index 0000000..ac496f3 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/ucontext.h @@ -0,0 +1,117 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2004, 2006 Free Software + Foundation, Inc. This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +/* Type for general register. Even in o32 we assume 64-bit registers, + like the kernel. */ +__extension__ typedef unsigned long long int greg_t; + +/* Number of general registers. */ +#define NGREG 32 +#define NFPREG 32 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + union { + double fp_dregs[NFPREG]; + struct { + float _fp_fregs; + unsigned int _fp_pad; + } fp_fregs[NFPREG]; + } fp_r; +} fpregset_t; + + +/* Context to describe whole processor state. */ +#if _MIPS_SIM == _ABIO32 +/* Earlier versions of glibc for mips had an entirely different + definition of mcontext_t, that didn't even resemble the + corresponding kernel data structure. Since all legitimate uses of + ucontext_t in glibc mustn't have accessed anything beyond + uc_mcontext and, even then, taking a pointer to it, casting it to + sigcontext_t, and accessing it as such, which is what it has always + been, this can still be rectified. Fortunately, makecontext, + [gs]etcontext et all have never been implemented. */ +typedef struct + { + unsigned int regmask; + unsigned int status; + greg_t pc; + gregset_t gregs; + fpregset_t fpregs; + unsigned int fp_owned; + unsigned int fpc_csr; + unsigned int fpc_eir; + unsigned int used_math; + unsigned int dsp; + greg_t mdhi; + greg_t mdlo; + unsigned long hi1; + unsigned long lo1; + unsigned long hi2; + unsigned long lo2; + unsigned long hi3; + unsigned long lo3; + } mcontext_t; +#else +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + greg_t mdhi; + greg_t hi1; + greg_t hi2; + greg_t hi3; + greg_t mdlo; + greg_t lo1; + greg_t lo2; + greg_t lo3; + greg_t pc; + unsigned int fpc_csr; + unsigned int used_math; + unsigned int dsp; + unsigned int reserved; + } mcontext_t; +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/mips/sys/user.h b/libc/sysdeps/linux/mips/sys/user.h new file mode 100644 index 0000000..5d88094 --- /dev/null +++ b/libc/sysdeps/linux/mips/sys/user.h @@ -0,0 +1,217 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +/* #include */ +/* Instead of including the kernel header, that will vary depending on + whether the 32- or the 64-bit kernel is installed, we paste its + contents here. Note that the fact that the file is inline here, + instead of included separately, doesn't change in any way the + licensing status of a program that includes user.h. Since this is + for gdb alone, and gdb is GPLed, no surprises here. */ +#if _MIPS_SIM == _ABIO32 +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 by Ralf Baechle + */ +#ifndef __ASM_MIPS_REG_H +#define __ASM_MIPS_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0 6 +#define EF_REG1 7 +#define EF_REG2 8 +#define EF_REG3 9 +#define EF_REG4 10 +#define EF_REG5 11 +#define EF_REG6 12 +#define EF_REG7 13 +#define EF_REG8 14 +#define EF_REG9 15 +#define EF_REG10 16 +#define EF_REG11 17 +#define EF_REG12 18 +#define EF_REG13 19 +#define EF_REG14 20 +#define EF_REG15 21 +#define EF_REG16 22 +#define EF_REG17 23 +#define EF_REG18 24 +#define EF_REG19 25 +#define EF_REG20 26 +#define EF_REG21 27 +#define EF_REG22 28 +#define EF_REG23 29 +#define EF_REG24 30 +#define EF_REG25 31 +/* + * k0/k1 unsaved + */ +#define EF_REG28 34 +#define EF_REG29 35 +#define EF_REG30 36 +#define EF_REG31 37 + +/* + * Saved special registers + */ +#define EF_LO 38 +#define EF_HI 39 + +#define EF_CP0_EPC 40 +#define EF_CP0_BADVADDR 41 +#define EF_CP0_STATUS 42 +#define EF_CP0_CAUSE 43 + +#define EF_SIZE 180 /* size in bytes */ + +#endif /* __ASM_MIPS_REG_H */ + +#else /* _MIPS_SIM != _ABIO32 */ + +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 Ralf Baechle + * Copyright (C) 1995, 1999 Silicon Graphics + */ +#ifndef _ASM_REG_H +#define _ASM_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0 0 +#define EF_REG1 1 +#define EF_REG2 2 +#define EF_REG3 3 +#define EF_REG4 4 +#define EF_REG5 5 +#define EF_REG6 6 +#define EF_REG7 7 +#define EF_REG8 8 +#define EF_REG9 9 +#define EF_REG10 10 +#define EF_REG11 11 +#define EF_REG12 12 +#define EF_REG13 13 +#define EF_REG14 14 +#define EF_REG15 15 +#define EF_REG16 16 +#define EF_REG17 17 +#define EF_REG18 18 +#define EF_REG19 19 +#define EF_REG20 20 +#define EF_REG21 21 +#define EF_REG22 22 +#define EF_REG23 23 +#define EF_REG24 24 +#define EF_REG25 25 +/* + * k0/k1 unsaved + */ +#define EF_REG28 28 +#define EF_REG29 29 +#define EF_REG30 30 +#define EF_REG31 31 + +/* + * Saved special registers + */ +#define EF_LO 32 +#define EF_HI 33 + +#define EF_CP0_EPC 34 +#define EF_CP0_BADVADDR 35 +#define EF_CP0_STATUS 36 +#define EF_CP0_CAUSE 37 + +#define EF_SIZE 304 /* size in bytes */ + +#endif /* _ASM_REG_H */ + +#endif /* _MIPS_SIM != _ABIO32 */ + +#if _MIPS_SIM == _ABIO32 + +struct user +{ + unsigned long regs[EF_SIZE/4+64]; /* integer and fp regs */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + void* u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#else + +struct user { + __extension__ unsigned long regs[EF_SIZE/8+64]; /* integer and fp regs */ + __extension__ unsigned long u_tsize; /* text size (pages) */ + __extension__ unsigned long u_dsize; /* data size (pages) */ + __extension__ unsigned long u_ssize; /* stack size (pages) */ + __extension__ unsigned long long start_code; /* text starting address */ + __extension__ unsigned long long start_data; /* data starting address */ + __extension__ unsigned long long start_stack; /* stack starting address */ + __extension__ long long signal; /* signal causing core dump */ + __extension__ unsigned long long u_ar0; /* help gdb find registers */ + __extension__ unsigned long long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif + +#include +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _SYS_USER_H */ diff --git a/libc/sysdeps/linux/mips/syscall.S b/libc/sysdeps/linux/mips/syscall.S new file mode 100644 index 0000000..acb9101 --- /dev/null +++ b/libc/sysdeps/linux/mips/syscall.S @@ -0,0 +1,80 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif +.text +.align 2 +.globl syscall +.type syscall,@function +.ent syscall +syscall: +#ifdef __PIC__ + SETUP_GP +#endif + move v0, a0 /* Load system call number from first arg. */ + move a0, a1 /* Move the next three args up a register. */ + move a1, a2 + move a2, a3 + /* Load the remaining possible args (up to 7) from the stack. */ +#ifdef __mips64 + move a3, a4 + move a4, a5 + move a5, a6 + move a6, a7 + daddiu sp,sp,-16 + sd v0,0*8(sp) + ld v0,0*8(sp) /* for system call restarts */ +#else + lw a3,4*4(sp) + lw t0,5*4(sp) + lw t1,6*4(sp) + lw t2,7*4(sp) + addiu sp,sp,-32 + sw t0,4*4(sp) + sw t1,5*4(sp) + sw t2,6*4(sp) + sw v0,7*4(sp) + lw v0,7*4(sp) /* for system call restarts */ +#endif + syscall /* Do the system call. */ +#ifdef __mips64 + daddiu sp,sp,16 +#else + addiu sp,sp,32 +#endif + bnez a3, 1f + j ra /* Return to caller. */ +1: + move a0,v0 /* Pass return val to C function. */ + +#ifdef __PIC__ + SETUP_GP64(v0, syscall) + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + j __syscall_error +#endif +.end syscall +.size syscall,.-syscall diff --git a/libc/sysdeps/linux/mips/sysmips.c b/libc/sysdeps/linux/mips/sysmips.c new file mode 100644 index 0000000..1384782 --- /dev/null +++ b/libc/sysdeps/linux/mips/sysmips.c @@ -0,0 +1,7 @@ +#include +#include +#include + +#ifdef __NR_sysmips +_syscall4(int, sysmips, const int, cmd, const long, arg1, const int, arg2, const int, arg3) +#endif diff --git a/libc/sysdeps/linux/nios/Makefile b/libc/sysdeps/linux/nios/Makefile new file mode 100644 index 0000000..3970f62 --- /dev/null +++ b/libc/sysdeps/linux/nios/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/nios/Makefile.arch b/libc/sysdeps/linux/nios/Makefile.arch new file mode 100644 index 0000000..9bcd0be --- /dev/null +++ b/libc/sysdeps/linux/nios/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c crtbegin.c crtend.c + +SSRC := \ + __longjmp.S bsd-_setjmp.S bsd-setjmp.S setjmp.S \ + clone.S vfork.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/nios/NM_Macros.S b/libc/sysdeps/linux/nios/NM_Macros.S new file mode 100644 index 0000000..da61365 --- /dev/null +++ b/libc/sysdeps/linux/nios/NM_Macros.S @@ -0,0 +1,473 @@ + +;------------------------------ +; Macros I: Faux Instructions +; +; The following "faux instructions" are +; implemented here as macros: +; +; MOVIP register,constant MOVI with optional PFX & MOVHI, or BGEN +; ADDIP register,constant PFX and ADDI with optional PFX +; SUBIP register,constant PFX and SUBI with optional PFX +; CMPIP register,constant PFX and CMPI with optional PFX +; +; MOVI16 register,constant PFX and MOVI +; MOVI32 register,constant PFX, MOVI, PFX, and MOVHI +; MOVIA register,constant PFX and MOVHI on Nios32, and PFX and MOVI +; +; ANDIP register,constant PFX and ANDI +; ANDNIP register,constant PFX and ANDN +; ORIP register,constant PFX and ORI +; XORIP register,constant PFX and XORI +; +; _BSR address MOVIP address to %g7, and CALL +; _BR address MOVIP address to %g7, and JMP +; +; BEQ address SKPS cc_nz and BR, has delay slot +; BNE address SKPS cc_z and BR, has delay slot +; BLE address SKPS cc_gt and BR, has delay slot +; BLT address SKPS cc_ge and BR, has delay slot +; RESTRET RESTORE and JMP %i7 +; +;------------------------------- +; Macros II: Printing +; +; These macros are guaranteed *not* +; to have branch delay slot after them. +; +; NM_PrintChar char +; NM_Print "string" +; NM_PrintLn "string" Follows it with a carriage return +; NM_PrintRegister reg For debugging, prints register name & value +; +;------------------------------- +; Macros III: Inline Debugging +; +; These macros print various information +; using large sections of expanded inline code. +; They each use either few or no registers. +; Thus, they may be safely used in interrupt handlers. +; +; NM_D_TxChar char print char to UART, affects no registers +; NM_D_TxRegister char,char,register prints the two characters, and the hex register value + +; -------------------------------------- + + + .macro _pfx_op OP,reg,val,pForce=0 + .if (\pForce) || ((\val) > (31)) || ((\val) < (0)) + PFX %hi(\val) + .endif + \OP \reg,%lo(\val) + .endm + + .macro _bgen reg,val,bit + .if ((\val)==(1<<\bit)) + BGEN \reg,\bit + .equ _bgenBit,1 + .endif + .endm + + ;------------------------ + ; MOVIP %reg,32-bit-value + .macro MOVIP reg,val + ; Methodically test every BGEN possibility... + .equ _bgenBit,0 +.if 1 + _bgen \reg,\val,0 + _bgen \reg,\val,1 + _bgen \reg,\val,2 + _bgen \reg,\val,3 + _bgen \reg,\val,4 + _bgen \reg,\val,5 + _bgen \reg,\val,6 + _bgen \reg,\val,7 + _bgen \reg,\val,8 + _bgen \reg,\val,9 + _bgen \reg,\val,10 + _bgen \reg,\val,11 + _bgen \reg,\val,12 + _bgen \reg,\val,13 + _bgen \reg,\val,14 + _bgen \reg,\val,15 + _bgen \reg,\val,16 + _bgen \reg,\val,17 + _bgen \reg,\val,18 + _bgen \reg,\val,19 + _bgen \reg,\val,20 + _bgen \reg,\val,21 + _bgen \reg,\val,22 + _bgen \reg,\val,23 + _bgen \reg,\val,24 + _bgen \reg,\val,25 + _bgen \reg,\val,26 + _bgen \reg,\val,27 + _bgen \reg,\val,28 + _bgen \reg,\val,29 + _bgen \reg,\val,30 + _bgen \reg,\val,31 + + ; If no bgen fit... +.endif + .if !_bgenBit + .if ((\val) & 0xFFE0) + PFX %hi(\val) + .endif + MOVI \reg,%lo(\val) + .if __nios32__ + .if ((\val) & 0xffff0000) + .if ((\val) & 0xFFE00000) + PFX %xhi(\val) + .endif + MOVHI \reg,%xlo(\val) + .endif + .endif + .endif + + .endm + + ; ADDIP %reg,16-bit-value + .macro ADDIP reg,val + _pfx_op ADDI,\reg,\val + .endm + + ; SUBIP %reg,16-bit-value + .macro SUBIP reg,val + _pfx_op SUBI,\reg,\val + .endm + + ; CMPIP %reg,16-bit-value + .macro CMPIP reg,val + _pfx_op CMPI,\reg,\val + .endm + + ; ANDIP %reg,16-bit-value + .macro ANDIP reg,val + PFX %hi(\val) + AND \reg,%lo(\val) + .endm + + ; ANDNIP %reg,16-bit-value + .macro ANDNIP reg,val + PFX %hi(\val) + ANDN \reg,%lo(\val) + .endm + + ; ORIP %reg,16-bit-value + .macro ORIP reg,val + PFX %hi(\val) + OR \reg,%lo(\val) + .endm + + ; XORIP %reg,16-bit-value + .macro XORIP reg,val + PFX %hi(\val) + XOR \reg,%lo(\val) + .endm + + ; BEQ addr + .macro BEQ addr + IFS cc_eq + BR \addr + .endm + + ; BNE addr + .macro BNE addr + IFS cc_ne + BR \addr + .endm + + ; BLE addr + .macro BLE addr + SKPS cc_gt + BR \addr + .endm + + ; BLT addr + .macro BLT addr + SKPS cc_ge + BR \addr + .endm + + .macro digitToChar reg + ANDIP \reg,0x000f + CMPI \reg,10 + SKPS cc_lt + ADDI \reg,'A'-'0'-10 + PFX %hi('0') + ADDI \reg,%lo('0') + .endm + +; PUSHRET == dec sp, and stash return addr + .macro PUSHRET + SUBI %sp,2 + ST [%sp],%o7 + .endm +; POPRET == pop and jump + .macro POPRET + LD %o7,[%sp] + JMP %o7 + ADDI %sp,2 ; branch delay slot + .endm + +; RESTRET = restore & return + .macro RESTRET + JMP %i7 + RESTORE + .endm + + ;-------------------- + ; MOVI16 %reg,Address + ; + .macro MOVI16 reg,val + PFX %hi(\val) + MOVI \reg,%lo(\val) + .endm + + ;-------------------- + ; MOVI32 %reg,Address + ; + .macro MOVI32 reg,val + PFX %hi(\val) + MOVI \reg,%lo(\val) + PFX %xhi(\val) + MOVHI \reg,%xlo(\val) + .endm + + ;-------------------- + ; MOVIA %reg,Address + ; + .macro MOVIA reg,val + .if __nios32__ + MOVI32 \reg,\val + .else + MOVI16 \reg,\val + .endif + .endm + + ;-------------------- + ; _BR + + .macro _BR target,viaRegister=%g7 + MOVIA \viaRegister,\target@h + JMP \viaRegister + .endm + + ;-------------------- + ; _BSR + + .macro _BSR target,viaRegister=%g7 + MOVIA \viaRegister,\target@h + CALL \viaRegister + .endm + + ;--------------------- + ; NM_Print "Your String Here" + ; + .macro NM_Print string + + BR pastStringData\@ + NOP + +stringData\@: + .asciz "\string" + .align 1 ; aligns by 2^n +pastStringData\@: + MOVIA %o0,stringData\@ + _BSR NR_TxString + NOP + .endm + + .macro NM_PrintLn string + NM_Print "\string" + _BSR NR_TxCR + NOP + .endm + + .macro NM_PrintRegister reg ; affects %g0 & %g1 & %g7, but thrashes the CWP a bit + SAVE %sp,-16 + NM_Print "\reg = " + RESTORE + MOV %g0,\reg + SAVE %sp,-16 + MOV %o0,%g0 + _BSR NR_TxHex + NOP + _BSR NR_TxCR + NOP + RESTORE + .endm + + .macro NM_PrintChar char + MOVIP %o0,\char + _BSR NR_TxChar + NOP + .endm + + .macro NM_Print2Chars char1,char2 + MOVIP %o0,(\char2<<8)+\char1 + _BSR NR_TxChar + NOP + _BSR NR_TxChar + LSRI %o0,8 + .endm + + + +; --------------------------- +; Completely inline UART sends +; Send the char, or %g7 if not there. +; Trashes %g5 and %g6 and %g7... + + .macro NM_TxChar char=0 +;NM_D_Delay 1000 + MOVIA %g6,NA_UARTBase +txCharLoop\@: + PFX 2 +.if \char + LD %g7,[%g6] + SKP1 %g7,6 +.else + LD %g5,[%g6] + SKP1 %g5,6 +.endif + BR txCharLoop\@ + NOP +.if \char + MOVIP %g7,\char +.endif + PFX 1 + ST [%g6],%g7 +;NM_D_Delay 4 + .endm + + .macro NM_TxCR + NM_TxChar 13 + NM_TxChar 10 + .endm + + .macro NM_TxHexDigit,reg,shift + MOV %g7,\reg + LSRI %g7,\shift + ANDIP %g7,0x000f + CMPI %g7,10 + SKPS cc_lt + ADDIP %g7,'A'-'0'-10 + ADDIP %g7,'0' + NM_TxChar + .endm + + .macro NM_TxHex + + .if __nios32__ + NM_TxHexDigit %g0,28 + NM_TxHexDigit %g0,24 + NM_TxHexDigit %g0,20 + NM_TxHexDigit %g0,16 + .endif + + NM_TxHexDigit %g0,12 + NM_TxHexDigit %g0,8 + NM_TxHexDigit %g0,4 + NM_TxHexDigit %g0,0 + .endm + + + + + + + + + + +; ---------------------- +; The following macros are +; rather mighty. They expand +; to large inline code for +; printing various things to +; the serial port. They are +; useful for debugging +; trap handlers, where you +; can't just go and call +; NR_TxChar and such, because, +; well, the CWP might be +; off limits! +; +; They do, however, presume +; that the stack is in good +; working order. + + +.macro NM_D_PushGRegisters + SUBIP %sp,16+69 ; oddball number so if we accidentally see it, it looks funny. + STS [%sp,16+0],%g0 + STS [%sp,16+1],%g1 + STS [%sp,16+2],%g2 + STS [%sp,16+3],%g3 + STS [%sp,16+4],%g4 + STS [%sp,16+5],%g5 + STS [%sp,16+6],%g6 + STS [%sp,16+7],%g7 + .endm + +.macro NM_D_PopGRegisters + LDS %g0,[%sp,16+0] + LDS %g1,[%sp,16+1] + LDS %g2,[%sp,16+2] + LDS %g3,[%sp,16+3] + LDS %g4,[%sp,16+4] + LDS %g5,[%sp,16+5] + LDS %g6,[%sp,16+6] + LDS %g7,[%sp,16+7] + ADDIP %sp,16+69 ; must match the push + .endm + + +.macro NM_D_TxChar c + SUBI %sp,16+8 ; 32 or 16 bit, that's enough space + STS [%sp,16+0],%g6 + STS [%sp,16+0],%g7 + NM_TxChar \c + LDS %g6,[%sp,16+0] + LDS %g7,[%sp,16+1] + ADDI %sp,16+8 + .endm + +.macro NM_D_TxChar3 c1,c2,c3 + NM_D_TxChar '<' + NM_D_TxChar \c1 + NM_D_TxChar \c2 + NM_D_TxChar \c3 + NM_D_TxChar '>' +.endm + +.macro NM_D_TxRegister r,n,reg + NM_D_PushGRegisters + NM_TxChar '(' + NM_TxChar \r + NM_TxChar \n + NM_TxChar ':' + MOV %g0,\reg + NM_TxHex + NM_TxChar ')' + NM_D_PopGRegisters +.endm + +.macro NM_D_TxReg r,n,reg + NM_D_TxRegister \r,\n,\reg +.endm + +; Do a delay loop, affects no registers. + +.macro NM_D_Delay d + SUBI %sp,16+4 + STS [%sp,16+0],%g0 + MOVIP %g0,\d +NM_D_DelayLoop\@: + IFRnz %g0 + BR NM_D_DelayLoop\@ + SUBI %g0,1 + LDS %g0,[%sp,16+0] + ADDI %sp,16+4 +.endm + diff --git a/libc/sysdeps/linux/nios/NR_Math1.S b/libc/sysdeps/linux/nios/NR_Math1.S new file mode 100644 index 0000000..5d5169b --- /dev/null +++ b/libc/sysdeps/linux/nios/NR_Math1.S @@ -0,0 +1,63 @@ + + + .include "NM_Macros.S" + + .file "okmul.c" +gcc2_compiled.: + .text + .p2align 1 + .globl __mulsi3 + .type __mulsi3,@function +__mulsi3: + + ;SKP0 %o0,31 + ;NEG %o1 + ;ABS %o0 + + .MACRO ZSTEP bit + SKP0 %o0,\bit + ADD %g0,%o1 + LSLI %o1,1 + .ENDM + + MOVI %g0,0 + ZSTEP 0 + ZSTEP 1 + ZSTEP 2 + ZSTEP 3 + ZSTEP 4 + ZSTEP 5 + ZSTEP 6 + ZSTEP 7 + ZSTEP 8 + ZSTEP 9 + ZSTEP 10 + ZSTEP 11 + ZSTEP 12 + ZSTEP 13 + ZSTEP 14 + ZSTEP 15 + ZSTEP 16 + ZSTEP 17 + ZSTEP 18 + ZSTEP 19 + ZSTEP 20 + ZSTEP 21 + ZSTEP 22 + ZSTEP 23 + ZSTEP 24 + ZSTEP 25 + ZSTEP 26 + ZSTEP 27 + ZSTEP 28 + ZSTEP 29 + ZSTEP 30 + ZSTEP 31 + ; No bit 31: we already set %o0 to positive + + JMP %o7 + MOV %o0,%g0 + +.Lfe1: + .size __mulsi3,.Lfe1-__mulsi3 + diff --git a/libc/sysdeps/linux/nios/__longjmp.S b/libc/sysdeps/linux/nios/__longjmp.S new file mode 100644 index 0000000..d7d1cdd --- /dev/null +++ b/libc/sysdeps/linux/nios/__longjmp.S @@ -0,0 +1,103 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + + +;---------------------------------------- +; Name: __longjmp +; Description: Restore the current context +; as saved by a previous nr_setjmp +; Input: %o0: jmp_buf (ptr to) array to restore context from +; %o1: integer to return +; Output: %o0 = 0 the first time we're called, or +; whatever longjmp returns later +; Side Effects: uses %g0, %g1 & %g2 +; CWP Depth: 0 +; + + .align 2 + .global __longjmp +__longjmp: + ; + ; The way we'll do this is by executing + ; RESTORE instructions until the old + ; return address matches. Then we'll + ; jump to where setjmp was called from. + ; + ; Since we're moving the window pointer + ; all over the place, we'll naturally + ; only use the %g registers. + ; + + mov %g0,%o0 ; %g0 -> jmp_buf + mov %g1,%o1 ; %g1 = return value + pfx jmpbuf_callersret + ld %g2,[%g0] ; %g2 = old return address +__longjmp_loop: + cmp %g2,%i7 ; Are we there yet? + skps cc_ne + br __longjmp_done + nop ; (delay slot) + + br __longjmp_loop + restore ; (delay slot) + ; + ; One might put in a watchdog counter here, to + ; prevent a runaway stack crawl... but what would that + ; accomplish? What error can we throw? To whom? + ; + +__longjmp_done: + pfx jmpbuf_l0 ; Restore local register l0 + ld %l0,[%g0] + pfx jmpbuf_l1 ; Restore local register l1 + ld %l1,[%g0] + pfx jmpbuf_l2 ; Restore local register l2 + ld %l2,[%g0] + pfx jmpbuf_l3 ; Restore local register l3 + ld %l3,[%g0] + pfx jmpbuf_l4 ; Restore local register l4 + ld %l4,[%g0] + pfx jmpbuf_l5 ; Restore local register l5 + ld %l5,[%g0] + pfx jmpbuf_l6 ; Restore local register l6 + ld %l6,[%g0] + pfx jmpbuf_l7 ; Restore local register l7 + ld %l7,[%g0] + pfx jmpbuf_i0 ; Restore input register i0 + ld %i0,[%g0] + pfx jmpbuf_i1 ; Restore input register i1 + ld %i1,[%g0] + pfx jmpbuf_i2 ; Restore input register i2 + ld %i2,[%g0] + pfx jmpbuf_i3 ; Restore input register i3 + ld %i3,[%g0] + pfx jmpbuf_i4 ; Restore input register i4 + ld %i4,[%g0] + pfx jmpbuf_i5 ; Restore input register i5 + ld %i5,[%g0] + pfx jmpbuf_jmpret + ld %o7,[%g0] ; set fake return address + jmp %o7 ; and kinda return there. + mov %o0,%g1 ; (delay slot) return value + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/nios/bits/endian.h b/libc/sysdeps/linux/nios/bits/endian.h new file mode 100644 index 0000000..34ea91f --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/endian.h @@ -0,0 +1,8 @@ +/* nios is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/*mle */ +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/nios/bits/fcntl.h b/libc/sysdeps/linux/nios/bits/fcntl.h new file mode 100644 index 0000000..9fc29cd --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/fcntl.h @@ -0,0 +1,237 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/nios/bits/kernel_types.h b/libc/sysdeps/linux/nios/bits/kernel_types.h new file mode 100644 index 0000000..e66f42d --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/kernel_types.h @@ -0,0 +1,43 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_NIOS_POSIX_TYPES_H +#define __ARCH_NIOS_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_NIOS2_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/nios/bits/mathdef.h b/libc/sysdeps/linux/nios/bits/mathdef.h new file mode 100644 index 0000000..22722e3 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/mathdef.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/nios/bits/mman.h b/libc/sysdeps/linux/nios/bits/mman.h new file mode 100644 index 0000000..7f644b9 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/mman.h @@ -0,0 +1,76 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/nios/bits/setjmp.h b/libc/sysdeps/linux/nios/bits/setjmp.h new file mode 100644 index 0000000..807ebea --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/setjmp.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. Nios version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +#include + +typedef struct + { + /* There are eight 4-byte local registers saved. */ + long int __lregs[8]; + + /* There are six 4-byte input registers saved. */ + long int __iregs[6]; + + /* The SP, return address to caller (also for longjmp) + and return address of caller are saved. */ + int *__sp; + int *__jmpret; + int *__callersret; + + } __jmp_buf[1]; + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__sp) + +#else /* _ASM */ + +#define jmpbuf_l0 0x00 +#define jmpbuf_l1 0x01 +#define jmpbuf_l2 0x02 +#define jmpbuf_l3 0x03 +#define jmpbuf_l4 0x04 +#define jmpbuf_l5 0x05 +#define jmpbuf_l6 0x06 +#define jmpbuf_l7 0x07 + +#define jmpbuf_i0 0x08 +#define jmpbuf_i1 0x09 +#define jmpbuf_i2 0x0a +#define jmpbuf_i3 0x0b +#define jmpbuf_i4 0x0c +#define jmpbuf_i5 0x0d + +#define jmpbuf_sp 0x0e +#define jmpbuf_jmpret 0x0f +#define jmpbuf_callersret 0x10 + +#endif /* _ASM */ + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/nios/bits/sigcontextinfo.h b/libc/sysdeps/linux/nios/bits/sigcontextinfo.h new file mode 100644 index 0000000..caf1cf4 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) ((ctx)->regs.pc)) + +/* now way for nios to do GET_FRAME(ctx), it is not saved in ctx */ +#define GET_STACK(ctx) ((void *) (ctx)->regs.u_regs[14]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/nios/bits/stackinfo.h b/libc/sysdeps/linux/nios/bits/stackinfo.h new file mode 100644 index 0000000..e7fbf56 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On nios II the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/nios/bits/stat.h b/libc/sysdeps/linux/nios/bits/stat.h new file mode 100644 index 0000000..213dbe2 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/stat.h @@ -0,0 +1,134 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif + __time_t st_atime; /* Time of last access. */ + unsigned long int __unused1; + __time_t st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + __time_t st_ctime; /* Time of last status change. */ + unsigned long int __unused3; +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ + __time_t st_atime; /* Time of last access. */ + unsigned long int __unused1; + __time_t st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + __time_t st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/nios/bits/syscalls.h b/libc/sysdeps/linux/nios/bits/syscalls.h new file mode 100644 index 0000000..c2b6b97 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/syscalls.h @@ -0,0 +1,13 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include +/* Do something very evil for now. Until we include our out syscall + * macros, short circuit bits/syscall.h and use asm/unistd.h instead */ +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h b/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/nios/bits/wordsize.h b/libc/sysdeps/linux/nios/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/nios/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/nios/brk.c b/libc/sysdeps/linux/nios/brk.c new file mode 100644 index 0000000..ea2e457 --- /dev/null +++ b/libc/sysdeps/linux/nios/brk.c @@ -0,0 +1,45 @@ +/* brk system call for Linux/Nios2. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *newbrk; + register int g1 __asm__("%g1") = __NR_brk; + register void *o0 __asm__("%o0") = addr; + + __asm__ __volatile__ ("trap 63\n\t" : "=r"(newbrk) : "0"(o0), "r"(g1)); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/nios/bsd-_setjmp.S b/libc/sysdeps/linux/nios/bsd-_setjmp.S new file mode 100644 index 0000000..f2f0f23 --- /dev/null +++ b/libc/sysdeps/linux/nios/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp in setjmp.S */ \ No newline at end of file diff --git a/libc/sysdeps/linux/nios/bsd-setjmp.S b/libc/sysdeps/linux/nios/bsd-setjmp.S new file mode 100644 index 0000000..36f2bab --- /dev/null +++ b/libc/sysdeps/linux/nios/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp in setjmp.S */ \ No newline at end of file diff --git a/libc/sysdeps/linux/nios/clone.S b/libc/sysdeps/linux/nios/clone.S new file mode 100644 index 0000000..39eb540 --- /dev/null +++ b/libc/sysdeps/linux/nios/clone.S @@ -0,0 +1,88 @@ +/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include "NM_Macros.S" + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + .align 2 + .globl clone + .type clone,@function + +clone: + save %sp,-16 + + MOVIP %l0, -EINVAL + /* sanity check arguments */ + skprnz %i0 /* no NULL function pointers */ + br CLONE_ERROR_LABEL + mov %o0, %i2 + + skprnz %i1 /* no NULL stack pointers */ + br CLONE_ERROR_LABEL + mov %o1, %i1 + + /* Do the system call */ + MOVIP %g1, __NR_clone + trap 63 + + /* if ret >=0? */ + cmpi %o0, 0 + skps cc_pl + br CLONE_ERROR_LABEL + mov %l0, %o0 + + /* Start thread */ + skprz %o1 + br __thread_start + nop + mov %i0, %o0 + ret + restore + +CLONE_ERROR_LABEL: + neg %l0 + MOVIA %g1, __errno_location@h + call %g1 + nop + st [%o0], %l0 /* store errno */ + + xor %i0, %i0 + dec %i0 /* retval=-1 */ + ret + restore + + .size clone, .-clone + + .type __thread_start,@function + +__thread_start: + call %i0 + mov %o0, %i3 + MOVIA %g1, _exit@h + call %g1 + nop + + .size __thread_start, .-__thread_start diff --git a/libc/sysdeps/linux/nios/crt1.S b/libc/sysdeps/linux/nios/crt1.S new file mode 100644 index 0000000..e80a821 --- /dev/null +++ b/libc/sysdeps/linux/nios/crt1.S @@ -0,0 +1,59 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include "NM_Macros.S" +#define __ASSEMBLY__ +#include /* for REGWIN_SZ */ + + .global _start + .type __start,@function + .weak _init + .weak _fini + .type main,@function + .type __uClibc_main,@function + .type __h_errno_location, @function + .type _stdio_init, @function + .type _stdio_term, @function + + .text + +_start: + nop + nop + + MOVIA %o0, main@h + lds %o1,[%sp, (REGWIN_SZ / 4) + 0] /* main's argc */ + lds %o2,[%sp, (REGWIN_SZ / 4) + 1] /* main's argv */ + + MOVIA %o3, _init@h + MOVIA %o4, _fini@h + mov %o5, %i0 /* rtld_fini */ + mov %o6, %sp /* stack_end */ + MOVIA %o7, __uClibc_main@h + + call %o7 + nop + + + /* If that didn't kill us, ... */ +__exit: + MOVIP %g1, __NR_exit + trap 63 diff --git a/libc/sysdeps/linux/nios/crtbegin.c b/libc/sysdeps/linux/nios/crtbegin.c new file mode 100644 index 0000000..ac3f23f --- /dev/null +++ b/libc/sysdeps/linux/nios/crtbegin.c @@ -0,0 +1,37 @@ +#include +#include +/* +static void (*__CTOR_LIST__[1]) __P((void)) + __attribute__((__unused__)) + __attribute__((section(".ctors"))) = { (void *)0 }; + +static void (*__DTOR_LIST__[1]) __P((void)) + __attribute__((section(".dtors"))) = { (void *)-1 }; +*/ +extern void (*__DTOR_LIST__[]) __P((void)); +static void __do_global_dtors_aux __P((void)); + +static void +__do_global_dtors_aux() +{ + void (**p)(void) = __DTOR_LIST__ + 1; + + while (*p) + (**p++)(); +} + +static void dummy_fini(void) __attribute__((section(".trash"))); + +void +dummy_fini(void) +{ + static void (* volatile call__dtors)(void) = __do_global_dtors_aux; + /* + * Call global destructors. + */ + /* prevent function pointer constant propagation */ + __asm__ __volatile__ (".section .fini"); + (*call__dtors)(); + __asm__ __volatile__ (".section .trash"); + +} diff --git a/libc/sysdeps/linux/nios/crtend.c b/libc/sysdeps/linux/nios/crtend.c new file mode 100644 index 0000000..775eb0f --- /dev/null +++ b/libc/sysdeps/linux/nios/crtend.c @@ -0,0 +1,44 @@ +#include +#include +#include +/* +static void (*__CTOR_END__[1]) __P((void)) + __attribute__((section(".ctors"))) = { (void *)-1 }; + +static void (*__DTOR_END__[1]) __P((void)) + __attribute__((__unused__)) + __attribute__((section(".dtors"))) = { (void *)0 }; +*/ +extern void (*__CTOR_END__[]) __P((void)); +static void __do_global_ctors_aux __P((void)); + +static void +__do_global_ctors_aux() +{ + void (**p)(void) = __CTOR_END__ - 1; + + while (*p) + (**p--)(); +} + +static void dummy_init(void) __attribute__((section(".trash"))); + +void +dummy_init(void) +{ + static smallint initialized; + static void (*volatile call__ctors)(void) = __do_global_ctors_aux; + /* + * Call global constructors. + * Arrange to call global destructors at exit. + */ + /* prevent function pointer constant propagation */ + __asm__ __volatile__ (".section .init"); + + if (!initialized) { + initialized = 1; + (*call__ctors)(); + } + __asm__ __volatile__ (".section .trash"); + +} \ No newline at end of file diff --git a/libc/sysdeps/linux/nios/fpu_control.h b/libc/sysdeps/linux/nios/fpu_control.h new file mode 100644 index 0000000..9c31745 --- /dev/null +++ b/libc/sysdeps/linux/nios/fpu_control.h @@ -0,0 +1,99 @@ +/* FPU control word bits. Nios2 version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/nios/setjmp.S b/libc/sysdeps/linux/nios/setjmp.S new file mode 100644 index 0000000..c285146 --- /dev/null +++ b/libc/sysdeps/linux/nios/setjmp.S @@ -0,0 +1,102 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include +#include "NM_Macros.S" + +;---------------------------------------- +; Name: __sigsetjmp +; Description: Save the current context so +; a nr_longjmp works later. +; Input: %o0: jmp_buf: (ptr to) array to store context in +; Output: %o0 = 0 the first time we're called, or +; whatever longjmp returns later +; Side Effects: Uses %g0 +; CWP Depth: 0 +; + + .align 2 + .global _setjmp + +_setjmp: + br __sigsetjmp + movi %o1,0 ; (Delay slot) Set signal mask to zero + + .align 2 + .global setjmp + +setjmp: + MOVIP %o1,1 ; Set signal mask to 1 to save mask + + .align 2 + .global __sigsetjmp + +__sigsetjmp: + pfx jmpbuf_callersret ; present return address + st [%o0],%i7 + pfx jmpbuf_jmpret ; where the longjmp will later execute from + st [%o0],%o7 + pfx jmpbuf_sp ; Save stack pointer + st [%o0],%o6 + pfx jmpbuf_l0 ; Save local register l0 + st [%o0],%l0 + pfx jmpbuf_l1 ; Save local register l1 + st [%o0],%l1 + pfx jmpbuf_l2 ; Save local register l2 + st [%o0],%l2 + pfx jmpbuf_l3 ; Save local register l3 + st [%o0],%l3 + pfx jmpbuf_l4 ; Save local register l4 + st [%o0],%l4 + pfx jmpbuf_l5 ; Save local register l5 + st [%o0],%l5 + pfx jmpbuf_l6 ; Save local register l6 + st [%o0],%l6 + pfx jmpbuf_l7 ; Save local register l7 + st [%o0],%l7 + pfx jmpbuf_i0 ; Save input register i0 + st [%o0],%i0 + pfx jmpbuf_i1 ; Save input register i1 + st [%o0],%i1 + pfx jmpbuf_i2 ; Save input register i2 + st [%o0],%i2 + pfx jmpbuf_i3 ; Save input register i3 + st [%o0],%i3 + pfx jmpbuf_i4 ; Save input register i4 + st [%o0],%i4 + pfx jmpbuf_i5 ; Save input register i5 + st [%o0],%i5 + pfx %hi(__sigjmp_save@h) ; Load up %g0 with address + movi %g0,%lo(__sigjmp_save@h) + pfx %xhi(__sigjmp_save@h) + movhi %g0,%xlo(__sigjmp_save@h) + jmp %g0 + nop ; (delay slot) + + + + + + + + + + diff --git a/libc/sysdeps/linux/nios/sys/procfs.h b/libc/sysdeps/linux/nios/sys/procfs.h new file mode 100644 index 0000000..8cbaa41 --- /dev/null +++ b/libc/sysdeps/linux/nios/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/nios/sys/ucontext.h b/libc/sysdeps/linux/nios/sys/ucontext.h new file mode 100644 index 0000000..1805b4e --- /dev/null +++ b/libc/sysdeps/linux/nios/sys/ucontext.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_SPARE (2) +#define REG_WVALID (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) +#define REG_GLOBALS (19) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#define NGREG 20 +typedef int greg_t; + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). NIOS_MAXWINDOW is the + * maximum number of outstanding register windows defined in the NIOS + * architecture (*not* implementation). + */ +#define NIOS_MAXREGWINDOW 31 /* max windows in NIOS arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[NIOS_MAXREGWINDOW]; + struct rwindow wbuf[NIOS_MAXREGWINDOW]; + } gwindows_t; + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/nios/vfork.S b/libc/sysdeps/linux/nios/vfork.S new file mode 100644 index 0000000..f8a6d03 --- /dev/null +++ b/libc/sysdeps/linux/nios/vfork.S @@ -0,0 +1,54 @@ +/* + * libc/sysdeps/linux/nios/vfork.S -- `vfork' syscall for linux/nios + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#include + +#include +#include +#include "NM_Macros.S" + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + + .text + .align 2 + .globl __vfork + .hidden __vfork + .type __vfork,@function +__vfork: + MOVIP %g1, __NR_vfork + trap 63 + + bgen %g1, 12 + not %g1 /* (unsigned long) -4096 */ + cmp %o0, %g1 + skps cc_hi + jmp %o7 + nop + +fix_errno: + neg %o0 + save %sp, -16 + MOVIA %g1, __errno_location@h + call %g1 + nop + st [%o0], %i0 /* store errno */ + + xor %i0, %i0 + subi %i0, 1 /* retval=-1 */ + ret + restore + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/nios2/Makefile b/libc/sysdeps/linux/nios2/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/nios2/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/nios2/Makefile.arch b/libc/sysdeps/linux/nios2/Makefile.arch new file mode 100644 index 0000000..fadde95 --- /dev/null +++ b/libc/sysdeps/linux/nios2/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c syscall.c + +SSRC := \ + __longjmp.S bsd-_setjmp.S bsd-setjmp.S setjmp.S \ + vfork.S clone.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/nios2/__longjmp.S b/libc/sysdeps/linux/nios2/__longjmp.S new file mode 100644 index 0000000..4b6508e --- /dev/null +++ b/libc/sysdeps/linux/nios2/__longjmp.S @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/nios2/__longjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.globl __longjmp +.type __longjmp,@function +.balign 4 + +__longjmp: + /* return value is in r5*/ + mov r2, r5 + + /* jmp_buf in r4, restore regs. */ + ldw r16, (JB_REGS+ 0)(r4) + ldw r17, (JB_REGS+ 4)(r4) + ldw r18, (JB_REGS+ 8)(r4) + ldw r19, (JB_REGS+12)(r4) + ldw r20, (JB_REGS+16)(r4) + ldw r21, (JB_REGS+20)(r4) + ldw r22, (JB_REGS+24)(r4) + ldw r23, (JB_REGS+28)(r4) + + ldw ra, JB_PC(r4) + ldw fp, JB_FP(r4) + ldw gp, JB_GP(r4) + ldw sp, JB_SP(r4) + +#if defined(__HAVE_FPU__) + RESTORE_FPU r4 JB_FPREGS +#endif + + /* return to saved RA */ + ret + +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/nios2/bits/endian.h b/libc/sysdeps/linux/nios2/bits/endian.h new file mode 100644 index 0000000..54bd9d1 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/endian.h @@ -0,0 +1,7 @@ +/* i386 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/nios2/bits/fcntl.h b/libc/sysdeps/linux/nios2/bits/fcntl.h new file mode 100644 index 0000000..7e32a04 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/fcntl.h @@ -0,0 +1,237 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/nios2/bits/kernel_stat.h b/libc/sysdeps/linux/nios2/bits/kernel_stat.h new file mode 100644 index 0000000..9be9d11 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/kernel_stat.h @@ -0,0 +1,60 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/nios2/bits/kernel_types.h b/libc/sysdeps/linux/nios2/bits/kernel_types.h new file mode 100644 index 0000000..3fcd1af --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_NIOS2_POSIX_TYPES_H +#define __ARCH_NIOS2_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_NIOS2_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/nios2/bits/mathdef.h b/libc/sysdeps/linux/nios2/bits/mathdef.h new file mode 100644 index 0000000..22722e3 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/mathdef.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/nios2/bits/mman.h b/libc/sysdeps/linux/nios2/bits/mman.h new file mode 100644 index 0000000..2fa35e6 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/mman.h @@ -0,0 +1,85 @@ +/* Definitions for POSIX memory map interface. Linux/m68k version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/nios2/bits/setjmp.h b/libc/sysdeps/linux/nios2/bits/setjmp.h new file mode 100644 index 0000000..fcff031 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/setjmp.h @@ -0,0 +1,72 @@ +/* Define the machine-dependent type `jmp_buf'. Nios2 version. + Copyright (C) 1992,93,95,97,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct +{ + /* Callee-saved registers r16 through r23. */ + unsigned long __regs[8]; + + /* Program counter. */ + unsigned long __pc; + + /* Stack pointer. */ + unsigned long __sp; + + /* The frame pointer. */ + unsigned long __fp; + + /* The global pointer. */ + unsigned long __gp; + + /* floating point regs, if any */ +#if defined __HAVE_FPU__ + unsigned long __fpregs[64]; +#endif +} __jmp_buf[1]; + +#endif + +#define JB_REGS 0 +#define JB_PC 32 +#define JB_SP 36 +#define JB_FP 40 +#define JB_GP 44 +#define JB_FPREGS 48 + +#if defined __HAVE_FPU__ +# define JB_SIZE 304 +#else +# define JB_SIZE 48 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void*)(jmpbuf)->__sp) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h b/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h new file mode 100644 index 0000000..d6383b9 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) (ctx)->regs.ea) +#define GET_FRAME(ctx) ((void *) (ctx)->regs.sp) +#define GET_STACK(ctx) ((void *) (ctx)->regs.fp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/nios2/bits/stackinfo.h b/libc/sysdeps/linux/nios2/bits/stackinfo.h new file mode 100644 index 0000000..e7fbf56 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On nios II the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/nios2/bits/stat.h b/libc/sysdeps/linux/nios2/bits/stat.h new file mode 100644 index 0000000..f446a91 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/stat.h @@ -0,0 +1,134 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif + __time_t st_atime; /* Time of last access. */ + unsigned long int __unused1; + __time_t st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + __time_t st_ctime; /* Time of last status change. */ + unsigned long int __unused3; +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ + __time_t st_atime; /* Time of last access. */ + unsigned long int __unused1; + __time_t st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + __time_t st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/nios2/bits/syscalls.h b/libc/sysdeps/linux/nios2/bits/syscalls.h new file mode 100644 index 0000000..ec53707 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/syscalls.h @@ -0,0 +1,295 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include +#include + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + \ + /* avoid using res which is declared to be in \ + register r2; errno might expand to a function \ + call and clobber it. */ \ + \ + int __err = -(res); \ + errno = __err; \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall1(type,name,atype,a) \ +type name(atype a) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall2(type,name,atype,a,btype,b) \ +type name(atype a,btype b) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + " mov r5, %4\n\t" /* (long) b */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + , "r" ((long) b) /* %4 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + , "r5" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a,btype b,ctype c) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + " mov r5, %4\n\t" /* (long) b */ \ + " mov r6, %5\n\t" /* (long) c */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + , "r" ((long) b) /* %4 */ \ + , "r" ((long) c) /* %5 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + , "r5" /* Clobbered */ \ + , "r6" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ +type name (atype a, btype b, ctype c, dtype d) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + " mov r5, %4\n\t" /* (long) b */ \ + " mov r6, %5\n\t" /* (long) c */ \ + " mov r7, %6\n\t" /* (long) d */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + , "r" ((long) b) /* %4 */ \ + , "r" ((long) c) /* %5 */ \ + , "r" ((long) d) /* %6 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + , "r5" /* Clobbered */ \ + , "r6" /* Clobbered */ \ + , "r7" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \ +type name (atype a,btype b,ctype c,dtype d,etype e) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + " mov r5, %4\n\t" /* (long) b */ \ + " mov r6, %5\n\t" /* (long) c */ \ + " mov r7, %6\n\t" /* (long) c */ \ + " mov r8, %7\n\t" /* (long) e */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + , "r" ((long) b) /* %4 */ \ + , "r" ((long) c) /* %5 */ \ + , "r" ((long) d) /* %6 */ \ + , "r" ((long) e) /* %7 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + , "r5" /* Clobbered */ \ + , "r6" /* Clobbered */ \ + , "r7" /* Clobbered */ \ + , "r8" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \ +type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \ +{ \ + long __res; \ + \ + __asm__ __volatile__ ( \ + \ + " \n\t" \ + \ + " movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + " movi r3, %1\n\t" /* __NR_##name */ \ + " mov r4, %3\n\t" /* (long) a */ \ + " mov r5, %4\n\t" /* (long) b */ \ + " mov r6, %5\n\t" /* (long) c */ \ + " mov r7, %6\n\t" /* (long) c */ \ + " mov r8, %7\n\t" /* (long) e */ \ + " mov r9, %8\n\t" /* (long) f */ \ + \ + " trap\n\t" \ + " mov %0, r2\n\t" /* syscall rtn */ \ + \ + " \n\t" \ + \ + : "=r" (__res) /* %0 */ \ + \ + : "i" (__NR_##name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + , "r" ((long) a) /* %3 */ \ + , "r" ((long) b) /* %4 */ \ + , "r" ((long) c) /* %5 */ \ + , "r" ((long) d) /* %6 */ \ + , "r" ((long) e) /* %7 */ \ + , "r" ((long) f) /* %8 */ \ + \ + : "r2" /* Clobbered */ \ + , "r3" /* Clobbered */ \ + , "r4" /* Clobbered */ \ + , "r5" /* Clobbered */ \ + , "r6" /* Clobbered */ \ + , "r7" /* Clobbered */ \ + , "r8" /* Clobbered */ \ + , "r9" /* Clobbered */ \ + ); \ + \ +__syscall_return(type,__res); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h b/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/nios2/bits/uClibc_page.h b/libc/sysdeps/linux/nios2/bits/uClibc_page.h new file mode 100644 index 0000000..311dd40 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/uClibc_page.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Erik Andersen + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT (12) +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/nios2/bits/wordsize.h b/libc/sysdeps/linux/nios2/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/nios2/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/nios2/brk.c b/libc/sysdeps/linux/nios2/brk.c new file mode 100644 index 0000000..0420798 --- /dev/null +++ b/libc/sysdeps/linux/nios2/brk.c @@ -0,0 +1,46 @@ +/* brk system call for Linux/Nios2. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *newbrk; + register int r2 __asm__("r2") = TRAP_ID_SYSCALL; + register int r3 __asm__("r3") = __NR_brk; + register void *r4 __asm__("r4") = addr; + + __asm__ __volatile__ ("trap\n\t" : "=r"(newbrk) : "0"(r2), "r"(r3), "r"(r4)); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/nios2/bsd-_setjmp.S b/libc/sysdeps/linux/nios2/bsd-_setjmp.S new file mode 100644 index 0000000..ed4061c --- /dev/null +++ b/libc/sysdeps/linux/nios2/bsd-_setjmp.S @@ -0,0 +1,45 @@ +/* + * libc/sysdeps/linux/nios2/bsd-_setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#define _ASM +#define _SETJMP_H +#include + + .globl _setjmp + .type _setjmp,@function + .balign 4 + +_setjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + stw r0, JB_SIZE(r4) /* signal mask is not saved */ + mov r2, zero + ret + + + diff --git a/libc/sysdeps/linux/nios2/bsd-setjmp.S b/libc/sysdeps/linux/nios2/bsd-setjmp.S new file mode 100644 index 0000000..ac99bfe --- /dev/null +++ b/libc/sysdeps/linux/nios2/bsd-setjmp.S @@ -0,0 +1,52 @@ +/* + * libc/sysdeps/linux/nios2/bsd-setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + + +#define _ASM +#define _SETJMP_H +#include + + .globl setjmp + .type setjmp,@function + .balign 4 + +setjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + + movui r5, 1 +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __sigjmp_save +#else + movhi r8, %hi(__sigjmp_save) + ori r8, r8, %lo(__sigjmp_save) + jmp r8 +#endif + + diff --git a/libc/sysdeps/linux/nios2/clone.S b/libc/sysdeps/linux/nios2/clone.S new file mode 100644 index 0000000..4afcb7d --- /dev/null +++ b/libc/sysdeps/linux/nios2/clone.S @@ -0,0 +1,70 @@ +/* + * libc/sysdeps/linux/nios2/clone.S -- `clone' syscall for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#define _ERRNO_H +#include +#include + +#ifdef __NR_clone +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.global clone +.type clone,%function +.align 4 +clone: + addi sp,sp,-8 + mov r8,r4 + stw ra,4(sp) + stw r16,0(sp) + + mov r4,r6 + movi r2,-EINVAL + + /* sanity check */ + beq r8,zero,CLONE_ERROR_LABEL + beq r5,zero,CLONE_ERROR_LABEL + + /* system call */ + movi r2,TRAP_ID_SYSCALL + movi r3,__NR_clone + trap + + /* child call the function */ + mov r4,r7 + bne r2,zero,CLONE_ERROR_LABEL + callr r8 + + /* exit if it returns */ + mov r4,r2 + movi r3,__NR_exit + trap + +CLONE_ERROR_LABEL: + movi r3,-4096 + sub r16,zero,r2 + bgeu r3,r2,CLONE_OK + + /* store errno */ + call __errno_location + stw r16,0(r2) + movi r2,-1 + +CLONE_OK: + ldw ra,4(sp) + ldw r16,0(sp) + addi sp,sp,8 + ret + +.size clone,.-clone + +#endif diff --git a/libc/sysdeps/linux/nios2/clone.c b/libc/sysdeps/linux/nios2/clone.c new file mode 100644 index 0000000..eec9f42 --- /dev/null +++ b/libc/sysdeps/linux/nios2/clone.c @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/nios2/clone.c -- `clone' syscall for linux/nios2 + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * + * Copyright (C) 2004,05 Microtronix Datacom Ltd + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * Written by Miles Bader + * Nios2 port by Wentao Xu + */ + +#include +#include +#include + +int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + register unsigned long rval __asm__ ("r2") = -EINVAL; + + if (fn && child_stack) { + register unsigned long syscall __asm__ ("r3"); + register unsigned long arg0 __asm__ ("r4"); + register unsigned long arg1 __asm__ ("r5"); + + /* Clone this thread. */ + rval = TRAP_ID_SYSCALL; + syscall = __NR_clone; + arg0 = flags; + arg1 = (unsigned long)child_stack; + __asm__ __volatile__ ("trap " + : "=r" (rval), "=r" (syscall) + : "0" (rval),"1" (syscall), "r" (arg0), "r" (arg1) + ); + + if (rval == 0) { + /* In child thread, call fn and exit. */ + arg0 = (*fn) (arg); + syscall = __NR_exit; + __asm__ __volatile__ ("trap " + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0)); + } + } + + __syscall_return (int, rval); +} diff --git a/libc/sysdeps/linux/nios2/crt1.S b/libc/sysdeps/linux/nios2/crt1.S new file mode 100644 index 0000000..0ba8d59 --- /dev/null +++ b/libc/sysdeps/linux/nios2/crt1.S @@ -0,0 +1,73 @@ +/* + * libc/sysdeps/linux/nios2/crt0.S -- entry point for linux/nios2 + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * Updated by Thomas Chou for crt1.S + * + */ + +#include +#include + + .global _start + .type _start,@function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,@function + .type __uClibc_main,@function + .type __h_errno_location, @function + .type _stdio_init, @function + .type _stdio_term, @function + .text + .balign 4 +_start: + nop + br 0f +0: + /* load gp */ + movhi gp, %hiadj(_gp) + addi gp, gp, %lo(_gp) + + /* load main, argc, argv from stack */ + movhi r4, %hi(main) + ori r4, r4, %lo(main) /* main */ + ldw r5, 0(sp) /* argc */ + ldw r6, 4(sp) /* argv */ + + /* load the 4th arg */ + movhi r7, %hi(_init) + ori r7, r7, %lo(_init) + + /* Allocate space on the stack for 6-7th arg, reuse 5th space */ + addi sp,sp,-8 + /* push 5-7th args on stack */ + movhi r8, %hi(_fini) + ori r8, r8, %lo(_fini) + stw r8, 0(sp) + + stw r2, 4(sp) /* rtld_fini */ + stw sp, 8(sp) /* stack_end */ + + /* call uClibc_main, shouldn't return */ +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __uClibc_main +#else + call __uClibc_main +#endif + + /* crash in the event of return */ +__exit: + movui r2, TRAP_ID_SYSCALL + movui r3, __NR_exit + trap diff --git a/libc/sysdeps/linux/nios2/crti.S b/libc/sysdeps/linux/nios2/crti.S new file mode 100644 index 0000000..26c55c9 --- /dev/null +++ b/libc/sysdeps/linux/nios2/crti.S @@ -0,0 +1,22 @@ + + .section .init + .balign 4 + .global _init + .type _init, @function +_init: + addi sp, sp, -8 + stw ra, 0(sp) + stw fp, 4(sp) + + .balign 4 + + + .section .fini + .balign 4 + .global _fini + .type _fini, @function +_fini: + addi sp, sp, -8 + stw ra, 0(sp) + stw fp, 4(sp) + .balign 4 diff --git a/libc/sysdeps/linux/nios2/crtn.S b/libc/sysdeps/linux/nios2/crtn.S new file mode 100644 index 0000000..de00fd1 --- /dev/null +++ b/libc/sysdeps/linux/nios2/crtn.S @@ -0,0 +1,14 @@ + + .section .init + + ldw ra, 0(sp) + ldw fp, 4(sp) + addi sp, sp, 8 + ret + + .section .fini + + ldw ra, 0(sp) + ldw fp, 4(sp) + addi sp, sp, 8 + ret diff --git a/libc/sysdeps/linux/nios2/fpu_control.h b/libc/sysdeps/linux/nios2/fpu_control.h new file mode 100644 index 0000000..9c31745 --- /dev/null +++ b/libc/sysdeps/linux/nios2/fpu_control.h @@ -0,0 +1,99 @@ +/* FPU control word bits. Nios2 version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/nios2/setjmp.S b/libc/sysdeps/linux/nios2/setjmp.S new file mode 100644 index 0000000..8acd220 --- /dev/null +++ b/libc/sysdeps/linux/nios2/setjmp.S @@ -0,0 +1,51 @@ +/* + * libc/sysdeps/linux/nios2/setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.globl __sigsetjmp +.type __sigsetjmp,@function +.balign 4 + +__sigsetjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __sigjmp_save +#else + movhi r8, %hi(__sigjmp_save) + ori r8, r8, %lo(__sigjmp_save) + jmp r8 +#endif + +.size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/nios2/sys/procfs.h b/libc/sysdeps/linux/nios2/sys/procfs.h new file mode 100644 index 0000000..8cbaa41 --- /dev/null +++ b/libc/sysdeps/linux/nios2/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/nios2/sys/ucontext.h b/libc/sysdeps/linux/nios2/sys/ucontext.h new file mode 100644 index 0000000..1805b4e --- /dev/null +++ b/libc/sysdeps/linux/nios2/sys/ucontext.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_SPARE (2) +#define REG_WVALID (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) +#define REG_GLOBALS (19) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#define NGREG 20 +typedef int greg_t; + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). NIOS_MAXWINDOW is the + * maximum number of outstanding register windows defined in the NIOS + * architecture (*not* implementation). + */ +#define NIOS_MAXREGWINDOW 31 /* max windows in NIOS arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[NIOS_MAXREGWINDOW]; + struct rwindow wbuf[NIOS_MAXREGWINDOW]; + } gwindows_t; + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/nios2/syscall.c b/libc/sysdeps/linux/nios2/syscall.c new file mode 100644 index 0000000..c3eb002 --- /dev/null +++ b/libc/sysdeps/linux/nios2/syscall.c @@ -0,0 +1,47 @@ +/* + * libc/sysdeps/linux/nios2/syscall.c -- generic syscall function for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ + register long _r2 __asm__("r2")=(long)TRAP_ID_SYSCALL; + register long _r3 __asm__("r3")=(long)sysnum; + + register long _r4 __asm__("r4")=(long)(a); + register long _r5 __asm__("r5")=(long)(b); + register long _r6 __asm__("r6")=(long)(c); + register long _r7 __asm__("r7")=(long)(d); + register long _r8 __asm__("r8")=(long)(e); + register long _r9 __asm__("r9")=(long)(f); + __asm__ __volatile__( + "trap " + : "=r"(_r2), "=r"(_r3) + : "0"(_r2), "1"(_r3), + "r"(_r4), "r"(_r5), "r"(_r6), "r"(_r7), "r"(_r8), "r"(_r9) + : "memory"); + + __syscall_return (long, _r2); +} + diff --git a/libc/sysdeps/linux/nios2/vfork.S b/libc/sysdeps/linux/nios2/vfork.S new file mode 100644 index 0000000..5d275ff --- /dev/null +++ b/libc/sysdeps/linux/nios2/vfork.S @@ -0,0 +1,56 @@ +/* + * libc/sysdeps/linux/nios2/vfork.S -- `vfork' syscall for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#include + +#define _ERRNO_H +#include +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 +__vfork: + movui r2, TRAP_ID_SYSCALL + movui r3, __NR_vfork + trap + movi r8, -4096 + bltu r8, r2, fix_errno + ret +fix_errno: + sub r8, r0, r2 + + addi sp, sp, -8 + stw ra, 4(sp) + stw r8, 0(sp) +#ifndef __PIC__ + call __errno_location +#else + +#endif + ldw ra, 4(sp) + ldw r8, 0(sp) + stw r8, 0(r2) + + addi r2, r0, -1 + addi sp, sp, 8 + ret + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/powerpc/Makefile b/libc/sysdeps/linux/powerpc/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/powerpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/powerpc/Makefile.arch b/libc/sysdeps/linux/powerpc/Makefile.arch new file mode 100644 index 0000000..85c2cd3 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/Makefile.arch @@ -0,0 +1,18 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c pread_write.c ioctl.c + +SSRC := \ + __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S \ + clone.S __uClibc_syscall.S syscall.S vfork.S + +ifeq ($(CONFIG_E500),y) +ARCH_HEADERS := fenv.h +endif + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/powerpc/README.bits b/libc/sysdeps/linux/powerpc/README.bits new file mode 100644 index 0000000..c0542e5 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/README.bits @@ -0,0 +1,14 @@ + +include/bits is mostly the same as glibc-2.2.4. The glibc-2.2.4 +versions can be accessed with the tag glibc224. + +Major differences: + + - termios.h is from the Linux kernel, not glibc, because glibc has + a very strange legacy conversion layer, which we ignore. + + - syscall.h is deleted; instead, sysnum.h is autogenerated in uClibc + + - syscalls.h is added. + + diff --git a/libc/sysdeps/linux/powerpc/__longjmp.S b/libc/sysdeps/linux/powerpc/__longjmp.S new file mode 100644 index 0000000..765a873 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/__longjmp.S @@ -0,0 +1,94 @@ +/* longjmp for PowerPC and PowerPC e500. + Copyright (C) 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + e500 contributed by Aldy Hernandez . + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ASM +#define _SETJMP_H +#include + + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#define FP(x...) x +#else +#define FP(x...) +#endif + +#if defined __CONFIG_E500__ +#define LFD(reg) evldd r##reg +#define STFD(reg) evstdd r##reg +#else +#define LFD(reg) lfd fp##reg +#define STFD(reg) stfd fp##reg +#endif /* __CONFIG_E500__ */ + +.globl __longjmp; +.type __longjmp, @function; +.align 2; + +__longjmp: + lwz r1,(JB_GPR1*4)(r3) + lwz r2,(JB_GPR2*4)(r3) + lwz r0,(JB_LR*4)(r3) + lwz r14,((JB_GPRS+0)*4)(r3) +FP( LFD (14),((JB_FPRS+0*2)*4)(r3)) + lwz r15,((JB_GPRS+1)*4)(r3) +FP( LFD (15),((JB_FPRS+1*2)*4)(r3)) + lwz r16,((JB_GPRS+2)*4)(r3) +FP( LFD (16),((JB_FPRS+2*2)*4)(r3)) + lwz r17,((JB_GPRS+3)*4)(r3) +FP( LFD (17),((JB_FPRS+3*2)*4)(r3)) + lwz r18,((JB_GPRS+4)*4)(r3) +FP( LFD (18),((JB_FPRS+4*2)*4)(r3)) + lwz r19,((JB_GPRS+5)*4)(r3) +FP( LFD (19),((JB_FPRS+5*2)*4)(r3)) + lwz r20,((JB_GPRS+6)*4)(r3) +FP( LFD (20),((JB_FPRS+6*2)*4)(r3)) + mtlr r0 + lwz r21,((JB_GPRS+7)*4)(r3) +FP( LFD (21),((JB_FPRS+7*2)*4)(r3)) + lwz r22,((JB_GPRS+8)*4)(r3) +FP( LFD (22),((JB_FPRS+8*2)*4)(r3)) + lwz r0,(JB_CR*4)(r3) + lwz r23,((JB_GPRS+9)*4)(r3) +FP( LFD (23),((JB_FPRS+9*2)*4)(r3)) + lwz r24,((JB_GPRS+10)*4)(r3) +FP( LFD (24),((JB_FPRS+10*2)*4)(r3)) + lwz r25,((JB_GPRS+11)*4)(r3) +FP( LFD (25),((JB_FPRS+11*2)*4)(r3)) + mtcrf 0xFF,r0 + lwz r26,((JB_GPRS+12)*4)(r3) +FP( LFD (26),((JB_FPRS+12*2)*4)(r3)) + lwz r27,((JB_GPRS+13)*4)(r3) +FP( LFD (27),((JB_FPRS+13*2)*4)(r3)) + lwz r28,((JB_GPRS+14)*4)(r3) +FP( LFD (28),((JB_FPRS+14*2)*4)(r3)) + lwz r29,((JB_GPRS+15)*4)(r3) +FP( LFD (29),((JB_FPRS+15*2)*4)(r3)) + lwz r30,((JB_GPRS+16)*4)(r3) +FP( LFD (30),((JB_FPRS+16*2)*4)(r3)) + lwz r31,((JB_GPRS+17)*4)(r3) +FP( LFD (31),((JB_FPRS+17*2)*4)(r3)) + mr r3,r4 + blr +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/powerpc/__syscall_error.c b/libc/sysdeps/linux/powerpc/__syscall_error.c new file mode 100644 index 0000000..5e109a8 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/powerpc/__uClibc_syscall.S b/libc/sysdeps/linux/powerpc/__uClibc_syscall.S new file mode 100644 index 0000000..5a14c94 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/__uClibc_syscall.S @@ -0,0 +1,12 @@ + .text + .align 2 + .globl __uClibc_syscall + .type __uClibc_syscall,@function +__uClibc_syscall: +.Lsize: + sc + bnslr + + b __syscall_error + + .size __uClibc_syscall,.Lsize-__uClibc_syscall diff --git a/libc/sysdeps/linux/powerpc/bits/atomic.h b/libc/sysdeps/linux/powerpc/bits/atomic.h new file mode 100644 index 0000000..d8a4ed3 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/atomic.h @@ -0,0 +1,607 @@ +/* Atomic operations. PowerPC Common version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if __WORDSIZE == 64 +/* Atomic operations. PowerPC64 version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The 32-bit exchange_bool is different on powerpc64 because the subf + does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + (a load word and zero (high 32) form) load. + In powerpc64 register values are 64-bit by default, including oldval. + The value in old val unknown sign extension, lwarx loads the 32-bit + value as unsigned. So we explicitly clear the high 32 bits in oldval. */ +# define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ +({ \ + unsigned int __tmp, __tmp2; \ + __asm__ __volatile__ (" clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ + " bne 2f\n" \ + " stwcx. %4,0,%2\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp), "=r" (__tmp2) \ + : "b" (mem), "1" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ +({ \ + unsigned int __tmp, __tmp2; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + " clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ + " bne 2f\n" \ + " stwcx. %4,0,%2\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp), "=r" (__tmp2) \ + : "b" (mem), "1" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +/* + * Only powerpc64 processors support Load doubleword and reserve index (ldarx) + * and Store doubleword conditional indexed (stdcx) instructions. So here + * we define the 64-bit forms. + */ +# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ +({ \ + unsigned long __tmp; \ + __asm__ __volatile__ ( \ + "1: ldarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ +({ \ + unsigned long __tmp; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ ( \ + "1: ldarx %0,0,%1\n" \ + " cmpd %0,%2\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%1\n" \ + " cmpd %0,%2\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +# define __arch_atomic_exchange_64_acq(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%2\n" \ + " stdcx. %3,0,%2\n" \ + " bne- 1b\n" \ + " " __ARCH_ACQ_INSTR \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_exchange_64_rel(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%2\n" \ + " stdcx. %3,0,%2\n" \ + " bne- 1b" \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_exchange_and_add_64(mem, value) \ + ({ \ + __typeof (*mem) __val, __tmp; \ + __asm__ __volatile__ ("1: ldarx %0,0,%3\n" \ + " add %1,%0,%4\n" \ + " stdcx. %1,0,%3\n" \ + " bne- 1b" \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_increment_val_64(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: ldarx %0,0,%2\n" \ + " addi %0,%0,1\n" \ + " stdcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_decrement_val_64(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: ldarx %0,0,%2\n" \ + " subi %0,%0,1\n" \ + " stdcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_decrement_if_positive_64(mem) \ + ({ int __val, __tmp; \ + __asm__ __volatile__ ("1: ldarx %0,0,%3\n" \ + " cmpdi 0,%0,0\n" \ + " addi %1,%0,-1\n" \ + " ble 2f\n" \ + " stdcx. %1,0,%3\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +/* + * All powerpc64 processors support the new "light weight" sync (lwsync). + */ +# define atomic_read_barrier() __asm__ ("lwsync" ::: "memory") +/* + * "light weight" sync can also be used for the release barrier. + */ +# ifndef UP +# define __ARCH_REL_INSTR "lwsync" +# endif + +#else +/* Atomic operations. PowerPC32 version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * The 32-bit exchange_bool is different on powerpc64 because the subf + * does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + * (a load word and zero (high 32) form). So powerpc64 has a slightly + * different version in sysdeps/powerpc/powerpc64/bits/atomic.h. + */ +# define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ +({ \ + unsigned int __tmp; \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ +({ \ + unsigned int __tmp; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +/* Powerpc32 processors don't implement the 64-bit (doubleword) forms of + load and reserve (ldarx) and store conditional (stdcx.) instructions. + So for powerpc32 we stub out the 64-bit forms. */ +# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ + (abort (), 0) + +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +# define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ + (abort (), 0) + +# define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +# define __arch_atomic_exchange_64_acq(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_exchange_64_rel(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_exchange_and_add_64(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_increment_val_64(mem) \ + ({ abort (); (*mem)++; }) + +# define __arch_atomic_decrement_val_64(mem) \ + ({ abort (); (*mem)--; }) + +# define __arch_atomic_decrement_if_positive_64(mem) \ + ({ abort (); (*mem)--; }) + +/* + * Older powerpc32 processors don't support the new "light weight" + * sync (lwsync). So the only safe option is to use normal sync + * for all powerpc32 applications. + */ +# define atomic_read_barrier() __asm__ ("sync" ::: "memory") + +#endif + +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +/* + * Powerpc does not have byte and halfword forms of load and reserve and + * store conditional. So for powerpc we stub out the 8- and 16-bit forms. + */ +#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \ + (abort (), 0) + +#ifdef UP +# define __ARCH_ACQ_INSTR "" +# define __ARCH_REL_INSTR "" +#else +# define __ARCH_ACQ_INSTR "isync" +# ifndef __ARCH_REL_INSTR +# define __ARCH_REL_INSTR "sync" +# endif +#endif + +#define atomic_full_barrier() __asm__ ("sync" ::: "memory") +#define atomic_write_barrier() __asm__ ("eieio" ::: "memory") + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%1\n" \ + " cmpw %0,%2\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%1\n" \ + " cmpw %0,%2\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_atomic_exchange_32_acq(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%2\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b\n" \ + " " __ARCH_ACQ_INSTR \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_exchange_32_rel(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%2\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b" \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_exchange_and_add_32(mem, value) \ + ({ \ + __typeof (*mem) __val, __tmp; \ + __asm__ __volatile__ ("1: lwarx %0,0,%3\n" \ + " add %1,%0,%4\n" \ + " stwcx. %1,0,%3\n" \ + " bne- 1b" \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_increment_val_32(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: lwarx %0,0,%2\n" \ + " addi %0,%0,1\n" \ + " stwcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_decrement_val_32(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: lwarx %0,0,%2\n" \ + " subi %0,%0,1\n" \ + " stwcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_decrement_if_positive_32(mem) \ + ({ int __val, __tmp; \ + __asm__ __volatile__ ("1: lwarx %0,0,%3\n" \ + " cmpwi 0,%0,0\n" \ + " addi %1,%0,-1\n" \ + " ble 2f\n" \ + " stwcx. %1,0,%3\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_acq(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_32_acq (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_64_acq (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_rel(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_32_rel (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_64_rel (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_and_add(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_and_add_32 (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_and_add_64 (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_increment_val(mem) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*(mem)) == 4) \ + __result = __arch_atomic_increment_val_32 (mem); \ + else if (sizeof (*(mem)) == 8) \ + __result = __arch_atomic_increment_val_64 (mem); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_increment(mem) ({ atomic_increment_val (mem); (void) 0; }) + +#define atomic_decrement_val(mem) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*(mem)) == 4) \ + __result = __arch_atomic_decrement_val_32 (mem); \ + else if (sizeof (*(mem)) == 8) \ + __result = __arch_atomic_decrement_val_64 (mem); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_decrement(mem) ({ atomic_decrement_val (mem); (void) 0; }) + + +/* Decrement *MEM if it is > 0, and return the old value. */ +#define atomic_decrement_if_positive(mem) \ + ({ __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_decrement_if_positive_32 (mem); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_decrement_if_positive_64 (mem); \ + else \ + abort (); \ + __result; \ + }) diff --git a/libc/sysdeps/linux/powerpc/bits/endian.h b/libc/sysdeps/linux/powerpc/bits/endian.h new file mode 100644 index 0000000..2a07934 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/endian.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* PowerPC can be little or big endian. Hopefully gcc will know... */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN +# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN +# error Both BIG_ENDIAN and LITTLE_ENDIAN defined! +# endif +# define __BYTE_ORDER __BIG_ENDIAN +#else +# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN +# define __BYTE_ORDER __LITTLE_ENDIAN +# else +# warning Cannot determine current byte order, assuming big-endian. +# define __BYTE_ORDER __BIG_ENDIAN +# endif +#endif diff --git a/libc/sysdeps/linux/powerpc/bits/fcntl.h b/libc/sysdeps/linux/powerpc/bits/fcntl.h new file mode 100644 index 0000000..f26a25e --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/fcntl.h @@ -0,0 +1,241 @@ +/* O_*, F_*, FD_* bit values for Linux/PowerPC. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 0400000 /* Direct disk access. */ +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0200000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/powerpc/bits/fenv.h b/libc/sysdeps/linux/powerpc/bits/fenv.h new file mode 100644 index 0000000..b674965 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/fenv.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1997, 1998, 1999, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + +#ifdef __CONFIG_E500__ + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the SPEFSCR... */ +enum + { + FE_INEXACT = 1 << (63 - 42), +#define FE_INEXACT FE_INEXACT + FE_INVALID = 1 << (63 - 43), +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 1 << (63 - 44), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << (63 - 45), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << (63 - 46) +#define FE_OVERFLOW FE_OVERFLOW + }; + +#else /* PowerPC 6xx floating-point. */ + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSCR... */ +enum + { + FE_INEXACT = 1 << (31 - 6), +#define FE_INEXACT FE_INEXACT + FE_DIVBYZERO = 1 << (31 - 5), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << (31 - 4), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << (31 - 3), +#define FE_OVERFLOW FE_OVERFLOW + + /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID + actually corresponds to bits 7 through 12 and 21 through 23 + in the FPSCR, but we can't use that because the current draft + says that it must be a power of 2. Instead we use bit 2 which + is the summary bit for all the FE_INVALID exceptions, which + kind of makes sense. */ + FE_INVALID = 1 << (31 - 2), +#define FE_INVALID FE_INVALID + +#ifdef __USE_GNU + /* Breakdown of the FE_INVALID bits. Setting FE_INVALID on an + input to a routine is equivalent to setting all of these bits; + FE_INVALID will be set on output from a routine iff one of + these bits is set. Note, though, that you can't disable or + enable these exceptions individually. */ + + /* Operation with SNaN. */ + FE_INVALID_SNAN = 1 << (31 - 7), +# define FE_INVALID_SNAN FE_INVALID_SNAN + + /* Inf - Inf */ + FE_INVALID_ISI = 1 << (31 - 8), +# define FE_INVALID_ISI FE_INVALID_ISI + + /* Inf / Inf */ + FE_INVALID_IDI = 1 << (31 - 9), +# define FE_INVALID_IDI FE_INVALID_IDI + + /* 0 / 0 */ + FE_INVALID_ZDZ = 1 << (31 - 10), +# define FE_INVALID_ZDZ FE_INVALID_ZDZ + + /* Inf * 0 */ + FE_INVALID_IMZ = 1 << (31 - 11), +# define FE_INVALID_IMZ FE_INVALID_IMZ + + /* Comparison with NaN or SNaN. */ + FE_INVALID_COMPARE = 1 << (31 - 12), +# define FE_INVALID_COMPARE FE_INVALID_COMPARE + + /* Invalid operation flag for software (not set by hardware). */ + /* Note that some chips don't have this implemented, presumably + because no-one expected anyone to write software for them %-). */ + FE_INVALID_SOFTWARE = 1 << (31 - 21), +# define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE + + /* Square root of negative number (including -Inf). */ + /* Note that some chips don't have this implemented. */ + FE_INVALID_SQRT = 1 << (31 - 22), +# define FE_INVALID_SQRT FE_INVALID_SQRT + + /* Conversion-to-integer of a NaN or a number too large or too small. */ + FE_INVALID_INTEGER_CONVERSION = 1 << (31 - 23) +# define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION + +# define FE_ALL_INVALID \ + (FE_INVALID_SNAN | FE_INVALID_ISI | FE_INVALID_IDI | FE_INVALID_ZDZ \ + | FE_INVALID_IMZ | FE_INVALID_COMPARE | FE_INVALID_SOFTWARE \ + | FE_INVALID_SQRT | FE_INVALID_INTEGER_CONVERSION) +#endif /* __USE_GNU */ + }; + +#endif /* __CONFIG_E500__ */ + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* PowerPC chips support all of the four defined rounding modes. We + use the bit pattern in the FPSCR as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 3 +#define FE_DOWNWARD FE_DOWNWARD + }; + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. We leave it as 'double' + for efficiency reasons (rather than writing it to a 32-bit integer). */ +typedef double fenv_t; + +/* If the default argument is used we use this value. */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#ifdef __USE_GNU +/* Floating-point environment where all exceptions are enabled. Note that + this is not sufficient to give you SIGFPE. */ +extern const fenv_t __fe_enabled_env; +# define FE_ENABLED_ENV (&__fe_enabled_env) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. */ +extern const fenv_t __fe_nonieee_env; +# define FE_NONIEEE_ENV (&__fe_nonieee_env) + +/* Floating-point environment with all exceptions enabled. Note that + just evaluating this value will set the processor into 'FPU + exceptions imprecise recoverable' mode, which may cause a significant + performance penalty (but have no other visible effect). */ +extern const fenv_t *__fe_nomask_env (void); +# define FE_NOMASK_ENV (__fe_nomask_env ()) +#endif /* __USE_GNU */ diff --git a/libc/sysdeps/linux/powerpc/bits/fenvinline.h b/libc/sysdeps/linux/powerpc/bits/fenvinline.h new file mode 100644 index 0000000..8146479 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/fenvinline.h @@ -0,0 +1,64 @@ +/* Inline floating-point environment handling functions for powerpc. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES + +/* Inline definition for fegetround. */ +# define fegetround() \ + (__extension__ ({ int __fegetround_result; \ + __asm__ __volatile__ \ + ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; })) + +/* The weird 'i#*X' constraints on the following suppress a gcc + warning when __excepts is not a constant. Otherwise, they mean the + same as just plain 'i'. */ + +/* Inline definition for feraiseexcept. */ +# define feraiseexcept(__excepts) \ + ((__builtin_constant_p (__excepts) \ + && ((__excepts) & ((__excepts)-1)) == 0 \ + && (__excepts) != FE_INVALID) \ + ? ((__excepts) != 0 \ + ? (__extension__ ({ __asm__ __volatile__ \ + ("mtfsb1 %s0" \ + : : "i#*X"(__builtin_ffs (__excepts))); \ + 0; })) \ + : 0) \ + : (feraiseexcept) (__excepts)) + +/* Inline definition for feclearexcept. */ +# define feclearexcept(__excepts) \ + ((__builtin_constant_p (__excepts) \ + && ((__excepts) & ((__excepts)-1)) == 0 \ + && (__excepts) != FE_INVALID) \ + ? ((__excepts) != 0 \ + ? (__extension__ ({ __asm__ __volatile__ \ + ("mtfsb0 %s0" \ + : : "i#*X"(__builtin_ffs (__excepts))); \ + 0; })) \ + : 0) \ + : (feclearexcept) (__excepts)) + +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/libc/sysdeps/linux/powerpc/bits/ioctl-types.h b/libc/sysdeps/linux/powerpc/bits/ioctl-types.h new file mode 100644 index 0000000..87b8265 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/ioctl-types.h @@ -0,0 +1,5 @@ +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +#include diff --git a/libc/sysdeps/linux/powerpc/bits/ipc.h b/libc/sysdeps/linux/powerpc/bits/ipc.h new file mode 100644 index 0000000..4f45aca --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/ipc.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + __mode_t mode; /* Read/write permission. */ +#if 0 + unsigned long __seq; /* Sequence number. */ + unsigned int __pad2; + unsigned long long int __unused1; + unsigned long long int __unused2; +#else + __uint32_t __seq; /* Sequence number. */ + __uint32_t __pad1; + __uint64_t __unused1; + __uint64_t __unused2; +#endif + }; diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h new file mode 100644 index 0000000..bfa6722 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h @@ -0,0 +1,59 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +#if __WORDSIZE == 64 +#define kernel_stat kernel_stat64 +#else +struct kernel_stat { + __kernel_dev_t st_dev; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + __kernel_off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; +#endif + +struct kernel_stat64 { + unsigned long long st_dev; /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + long long st_size; /* Size of file, in bytes. */ + long st_blksize; /* Optimal block size for I/O. */ + long long st_blocks; /* Number 512-byte blocks allocated. */ + long st_atime; /* Time of last access. */ + unsigned long int __unused1; + long st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + long st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_types.h b/libc/sysdeps/linux/powerpc/bits/kernel_types.h new file mode 100644 index 0000000..3f3b933 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/kernel_types.h @@ -0,0 +1,72 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#if ! defined _PPC_POSIX_TYPES_H && ! defined _PPC64_POSIX_TYPES_H && \ + ! defined _ASM_POWERPC_POSIX_TYPES_H +#define _PPC_POSIX_TYPES_H +#define _PPC64_POSIX_TYPES_H +#define _ASM_POWERPC_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_nlink_t; +typedef unsigned int __kernel_mode_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +#else +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* ! defined _PPC_POSIX_TYPES_H && ! defined _PPC64_POSIX_TYPES_H */ + diff --git a/libc/sysdeps/linux/powerpc/bits/mathdef.h b/libc/sysdeps/linux/powerpc/bits/mathdef.h new file mode 100644 index 0000000..81a46dd --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/mathdef.h @@ -0,0 +1,75 @@ +/* Copyright (C) 1997,1998,1999,2000,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! + + FIXME! This file does not deal with the -fshort-double option of + gcc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# ifdef __GNUC__ +# if __STDC__ == 1 + +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +# else + +/* For `gcc -traditional', `float' expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +# endif +# else + +/* Wild guess at types for float_t and double_t. */ +typedef double float_t; +typedef double double_t; + +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifdef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +#include +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# if __WORDSIZE == 32 +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# endif /* __WORDSIZE == 32 */ +#endif /* __UCLIBC_HAS_LONG_DOUBLE_MATH__ */ diff --git a/libc/sysdeps/linux/powerpc/bits/mathinline.h b/libc/sysdeps/linux/powerpc/bits/mathinline.h new file mode 100644 index 0000000..d1b05f3 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/mathinline.h @@ -0,0 +1,185 @@ +/* Inline math functions for powerpc. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif /* __cplusplus */ + +#if defined __GNUC__ && !defined _SOFT_FLOAT + +#ifdef __USE_ISOC99 +# if !__GNUC_PREREQ (2,97) +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + unsigned __r; \ + __asm__("fcmpu 7,%1,%2 ; mfcr %0" : "=r" (__r) : "f" (__x), "f"(__y) \ + : "cr7"); \ + __r; })) + +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered + +# define isgreater(x, y) (__unordered_cmp (x, y) >> 2 & 1) +# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & 6) != 0) +# define isless(x, y) (__unordered_cmp (x, y) >> 3 & 1) +# define islessequal(x, y) ((__unordered_cmp (x, y) & 0xA) != 0) +# define islessgreater(x, y) ((__unordered_cmp (x, y) & 0xC) != 0) +# define isunordered(x, y) (__unordered_cmp (x, y) & 1) + +# endif /* __GNUC_PREREQ (2,97) */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[0] < 0; +} +# endif +#endif /* __USE_ISOC99 */ + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +#ifdef __USE_ISOC99 + +# ifndef __powerpc64__ +__MATH_INLINE long int lrint (double __x) __THROW; +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + union { + double __d; + int __ll[2]; + } __u; + __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); + return __u.__ll[1]; +} + +__MATH_INLINE long int lrintf (float __x) __THROW; +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + union { + double __d; + int __ll[2]; + } __u; + __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); + return __u.__ll[1]; +} +# endif + +__MATH_INLINE double fdim (double __x, double __y) __THROW; +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +__MATH_INLINE float fdimf (float __x, float __y) __THROW; +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +#endif /* __USE_ISOC99 */ +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +/* This code is used internally in the GNU libc. */ +#if 0 /*def __LIBC_INTERNAL_MATH_INLINES*/ + +#include +#include +#include + +# if __WORDSIZE == 64 || defined _ARCH_PWR4 +# define __CPU_HAS_FSQRT 1 +# else +# define __CPU_HAS_FSQRT ((GLRO(dl_hwcap) & PPC_FEATURE_64) != 0) +# endif + +extern double __slow_ieee754_sqrt (double); +__MATH_INLINE double +__NTH (__ieee754_sqrt (double __x)) +{ + double __z; + + /* If the CPU is 64-bit we can use the optional FP instructions. */ + if (__CPU_HAS_FSQRT) + { + /* Volatile is required to prevent the compiler from moving the + fsqrt instruction above the branch. */ + __asm__ __volatile__ ( + " fsqrt %0,%1\n" + : "=f" (__z) + : "f" (__x)); + } + else + __z = __slow_ieee754_sqrt(__x); + + return __z; +} + +extern float __slow_ieee754_sqrtf (float); +__MATH_INLINE float +__NTH (__ieee754_sqrtf (float __x)) +{ + float __z; + + /* If the CPU is 64-bit we can use the optional FP instructions. */ + if (__CPU_HAS_FSQRT) + { + /* Volatile is required to prevent the compiler from moving the + fsqrts instruction above the branch. */ + __asm__ __volatile__ ( + " fsqrts %0,%1\n" + : "=f" (__z) + : "f" (__x)); + } + else + __z = __slow_ieee754_sqrtf(__x); + + return __z; +} +#endif /* __LIBC_INTERNAL_MATH_INLINES */ +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/libc/sysdeps/linux/powerpc/bits/mman.h b/libc/sysdeps/linux/powerpc/bits/mman.h new file mode 100644 index 0000000..e03ab7f --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/mman.h @@ -0,0 +1,104 @@ +/* Definitions for POSIX memory map interface. Linux/PowerPC version. + Copyright (C) 1997, 2000, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; iclude instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x001 /* Share changes. */ +#define MAP_PRIVATE 0x002 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x00f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x010 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x000 +# define MAP_ANONYMOUS 0x020 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x00080 /* Lock the mapping. */ +# define MAP_NORESERVE 0x00040 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/powerpc/bits/msq.h b/libc/sysdeps/linux/powerpc/bits/msq.h new file mode 100644 index 0000000..f198844 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/msq.h @@ -0,0 +1,83 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned int __unused3; +#endif + __time_t msg_ctime; /* time of last change */ + unsigned long __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h b/libc/sysdeps/linux/powerpc/bits/sem.h new file mode 100644 index 0000000..92a7a90 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/sem.h @@ -0,0 +1,92 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t sem_otime; /* last semop() time */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long __unused3; + unsigned long __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/powerpc/bits/setjmp.h b/libc/sysdeps/linux/powerpc/bits/setjmp.h new file mode 100644 index 0000000..dad90c7 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/setjmp.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. PowerPC version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'long int' instead, to make writing the + assembler easier. Naturally, user code should not depend on + either representation. */ + +#include + +#if defined __USE_MISC || defined _ASM +# define JB_GPR1 0 /* Also known as the stack pointer */ +# define JB_GPR2 1 +# define JB_LR 2 /* The address we will return to */ +# if __WORDSIZE == 64 +# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_CR 21 /* Condition code registers with the VRSAVE at */ + /* offset 172 (low half of the double word. */ +# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_SIZE (64 * 8) /* As per PPC64-VMX ABI. */ +# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */ + /* 168 (high half of the double word). */ +# define JB_VRS 40 /* VRs 20 through 31 are saved, 12*4 words total. */ +# else +# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total. */ +# define JB_CR 21 /* Condition code registers. */ +# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_SIZE ((64 + (12 * 4)) * 4) +# define JB_VRSAVE 62 +# define JB_VRS 64 +# endif +#endif + + +/* The current powerpc 32-bit Altivec ABI specifies for SVR4 ABI and EABI + the vrsave must be at byte 248 & v20 at byte 256. So we must pad this + correctly on 32 bit. It also insists that vecregs are only gauranteed + 4 byte alignment so we need to use vperm in the setjmp/longjmp routines. + We have to version the code because members like int __mask_was_saved + in the jmp_buf will move as jmp_buf is now larger than 248 bytes. We + cannot keep the altivec jmp_buf backward compatible with the jmp_buf. */ +#ifndef _ASM +# if __WORDSIZE == 64 +typedef long int __jmp_buf[64] __attribute__ ((__aligned__ (16))); +# else +/* The alignment is not essential, i.e.the buffer can be copied to a 4 byte + aligned buffer as per the ABI it is just added for performance reasons. */ +typedef long int __jmp_buf[64 + (12 * 4)] __attribute__ ((__aligned__ (16))); +# endif +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_GPR1]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/powerpc/bits/shm.h b/libc/sysdeps/linux/powerpc/bits/shm.h new file mode 100644 index 0000000..62560c0 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/shm.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned int __unused3; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ +#if __WORDSIZE == 32 + unsigned int __unused4; +#endif + size_t shm_segsz; /* size of segment in bytes */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long __unused5; + unsigned long __unused6; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h b/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h new file mode 100644 index 0000000..138a15c --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *)((ctx)->regs->nip)) +#define GET_FRAME(ctx) (*(void **)((ctx)->regs->gpr[1])) +#define GET_STACK(ctx) ((void *)((ctx)->regs->gpr[1])) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/powerpc/bits/stackinfo.h b/libc/sysdeps/linux/powerpc/bits/stackinfo.h new file mode 100644 index 0000000..839758a --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On PPC the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/powerpc/bits/stat.h b/libc/sysdeps/linux/powerpc/bits/stat.h new file mode 100644 index 0000000..f4a8de1 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/stat.h @@ -0,0 +1,267 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#include + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#if __WORDSIZE == 32 +# define _STAT_VER _STAT_VER_LINUX +#else +# define _STAT_VER _STAT_VER_KERNEL +#endif + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +#if __WORDSIZE == 32 + +struct stat + { + __dev_t st_dev; /* Device. */ +# ifndef __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +# else + __ino64_t st_ino; /* File serial number. */ +# endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +# ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +# else + __off64_t st_size; /* Size of file, in bytes. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +# else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +# endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + + +# ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; +# endif /* __USE_LARGEFILE64 */ + +#else /* __WORDSIZE == 32 */ + +struct stat + { + __dev_t st_dev; /* Device. */ +# ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +# else + __ino64_t st_ino; /* File serial number. */ +# endif + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int __pad2; + __dev_t st_rdev; /* Device number, if device. */ +# ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +# else + __off64_t st_size; /* Size of file, in bytes. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +# else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +# endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + unsigned long int __unused6; + }; + +# ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int __pad2; + __dev_t st_rdev; /* Device number, if device. */ + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + unsigned long int __unused6; + }; +# endif /* __USE_LARGEFILE64 */ +#endif + + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/powerpc/bits/syscalls.h b/libc/sysdeps/linux/powerpc/bits/syscalls.h new file mode 100644 index 0000000..d233cc7 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/syscalls.h @@ -0,0 +1,322 @@ +/* Copyright (C) 1992,1997-2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#ifndef __ASSEMBLER__ + +# include + +# ifdef SHARED +# define INLINE_VSYSCALL(name, nr, args...) \ + ({ \ + __label__ out; \ + __label__ iserr; \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + goto out; \ + if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \ + goto iserr; \ + } \ + \ + sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + iserr: \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + out: \ + sc_ret; \ + }) +# else +# define INLINE_VSYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, ##args) +# endif + +# ifdef SHARED +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + ({ \ + __label__ out; \ + long int v_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \ + || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \ + goto out; \ + } \ + v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \ + out: \ + v_ret; \ + }) +# else +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL (name, err, nr, ##args) +# endif + +# define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \ + ({ \ + long int sc_ret = ENOSYS; \ + \ + if (__vdso_##name != NULL) \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + else \ + err = 1 << 28; \ + sc_ret; \ + }) + +/* List of system calls which are supported as vsyscalls. */ +# define HAVE_CLOCK_GETRES_VSYSCALL 1 +# define HAVE_CLOCK_GETTIME_VSYSCALL 1 + +/* Define a macro which expands inline into the wrapper code for a VDSO + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ +# define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \ + ({ \ + register void *r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr (funcptr, args); \ + __asm__ __volatile__ \ + ("mtctr %0\n\t" \ + "bctrl\n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "lr", "memory"); \ + err = (long int) r0; \ + (int) r3; \ + }) + +# undef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + sc_ret; \ + }) + +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ + +# undef INTERNAL_SYSCALL_DECL +# define INTERNAL_SYSCALL_DECL(err) long int err + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register long int r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "memory"); \ + err = r0; \ + (int) r3; \ + }) +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((void) (val), __builtin_expect ((err) & (1 << 28), 0)) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +# define LOADARGS_0(name, dummy) \ + r0 = name +# define LOADARGS_1(name, __arg1) \ + long int arg1 = (long int) (__arg1); \ + LOADARGS_0(name, 0); \ + extern void __illegally_sized_syscall_arg1 (void); \ + if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \ + __illegally_sized_syscall_arg1 (); \ + r3 = arg1 +# define LOADARGS_2(name, __arg1, __arg2) \ + long int arg2 = (long int) (__arg2); \ + LOADARGS_1(name, __arg1); \ + extern void __illegally_sized_syscall_arg2 (void); \ + if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \ + __illegally_sized_syscall_arg2 (); \ + r4 = arg2 +# define LOADARGS_3(name, __arg1, __arg2, __arg3) \ + long int arg3 = (long int) (__arg3); \ + LOADARGS_2(name, __arg1, __arg2); \ + extern void __illegally_sized_syscall_arg3 (void); \ + if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \ + __illegally_sized_syscall_arg3 (); \ + r5 = arg3 +# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ + long int arg4 = (long int) (__arg4); \ + LOADARGS_3(name, __arg1, __arg2, __arg3); \ + extern void __illegally_sized_syscall_arg4 (void); \ + if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \ + __illegally_sized_syscall_arg4 (); \ + r6 = arg4 +# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ + long int arg5 = (long int) (__arg5); \ + LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ + extern void __illegally_sized_syscall_arg5 (void); \ + if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \ + __illegally_sized_syscall_arg5 (); \ + r7 = arg5 +# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + long int arg6 = (long int) (__arg6); \ + LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ + extern void __illegally_sized_syscall_arg6 (void); \ + if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \ + __illegally_sized_syscall_arg6 (); \ + r8 = arg6 + +# define ASM_INPUT_0 "0" (r0) +# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) +# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4) +# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5) +# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6) +# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) +# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) + + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void){ \ + return (type) INLINE_SYSCALL(name, 0); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1){ \ + return (type) INLINE_SYSCALL(name, 1, arg1); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2){ \ + return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3){ \ + return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \ + return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \ + return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \ + return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#endif /* __ASSEMBLER__ */ + + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor reg,tmpreg,reg +# define PTR_MANGLE2(reg, tmpreg) \ + xor reg,tmpreg,reg +# define PTR_MANGLE3(destreg, reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor destreg,tmpreg,reg +# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg) +# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg) +# define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg) +# else +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif + +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/powerpc/bits/sysdep.h b/libc/sysdeps/linux/powerpc/bits/sysdep.h new file mode 100644 index 0000000..c42efba --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/sysdep.h @@ -0,0 +1,301 @@ +/* Copyright (C) 1992,1997-2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_POWERPC_SYSDEP_H +#define _LINUX_POWERPC_SYSDEP_H 1 + +#include +#include + +/* Some systen calls got renamed over time, but retained the same semantics. + Handle them here so they can be catched by both C and assembler stubs in + glibc. */ + +#ifdef __NR_pread64 +# ifdef __NR_pread +# error "__NR_pread and __NR_pread64 both defined???" +# endif +# define __NR_pread __NR_pread64 +#endif + +#ifdef __NR_pwrite64 +# ifdef __NR_pwrite +# error "__NR_pwrite and __NR_pwrite64 both defined???" +# endif +# define __NR_pwrite __NR_pwrite64 +#endif + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +#ifndef __ASSEMBLER__ + +# include + +# ifdef SHARED +# define INLINE_VSYSCALL(name, nr, args...) \ + ({ \ + __label__ out; \ + __label__ iserr; \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + goto out; \ + if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \ + goto iserr; \ + } \ + \ + sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + iserr: \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + out: \ + sc_ret; \ + }) +# else +# define INLINE_VSYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, ##args) +# endif + +# ifdef SHARED +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + ({ \ + __label__ out; \ + long int v_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \ + || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \ + goto out; \ + } \ + v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \ + out: \ + v_ret; \ + }) +# else +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL (name, err, nr, ##args) +# endif + +# define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \ + ({ \ + long int sc_ret = ENOSYS; \ + \ + if (__vdso_##name != NULL) \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + else \ + err = 1 << 28; \ + sc_ret; \ + }) + +/* List of system calls which are supported as vsyscalls. */ +# define HAVE_CLOCK_GETRES_VSYSCALL 1 +# define HAVE_CLOCK_GETTIME_VSYSCALL 1 + +/* Define a macro which expands inline into the wrapper code for a VDSO + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ +# define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \ + ({ \ + register void *r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr (funcptr, args); \ + __asm__ __volatile__ \ + ("mtctr %0\n\t" \ + "bctrl\n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "lr", "memory"); \ + err = (long int) r0; \ + (int) r3; \ + }) + +# undef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + sc_ret; \ + }) + +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ + +# undef INTERNAL_SYSCALL_DECL +# define INTERNAL_SYSCALL_DECL(err) long int err + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register long int r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "memory"); \ + err = r0; \ + (int) r3; \ + }) +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((void) (val), __builtin_expect ((err) & (1 << 28), 0)) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +# define LOADARGS_0(name, dummy) \ + r0 = name +# define LOADARGS_1(name, __arg1) \ + long int arg1 = (long int) (__arg1); \ + LOADARGS_0(name, 0); \ + extern void __illegally_sized_syscall_arg1 (void); \ + if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \ + __illegally_sized_syscall_arg1 (); \ + r3 = arg1 +# define LOADARGS_2(name, __arg1, __arg2) \ + long int arg2 = (long int) (__arg2); \ + LOADARGS_1(name, __arg1); \ + extern void __illegally_sized_syscall_arg2 (void); \ + if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \ + __illegally_sized_syscall_arg2 (); \ + r4 = arg2 +# define LOADARGS_3(name, __arg1, __arg2, __arg3) \ + long int arg3 = (long int) (__arg3); \ + LOADARGS_2(name, __arg1, __arg2); \ + extern void __illegally_sized_syscall_arg3 (void); \ + if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \ + __illegally_sized_syscall_arg3 (); \ + r5 = arg3 +# define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ + long int arg4 = (long int) (__arg4); \ + LOADARGS_3(name, __arg1, __arg2, __arg3); \ + extern void __illegally_sized_syscall_arg4 (void); \ + if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \ + __illegally_sized_syscall_arg4 (); \ + r6 = arg4 +# define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ + long int arg5 = (long int) (__arg5); \ + LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ + extern void __illegally_sized_syscall_arg5 (void); \ + if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \ + __illegally_sized_syscall_arg5 (); \ + r7 = arg5 +# define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + long int arg6 = (long int) (__arg6); \ + LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ + extern void __illegally_sized_syscall_arg6 (void); \ + if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \ + __illegally_sized_syscall_arg6 (); \ + r8 = arg6 + +# define ASM_INPUT_0 "0" (r0) +# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) +# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4) +# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5) +# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6) +# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) +# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) + +#endif /* __ASSEMBLER__ */ + + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor reg,tmpreg,reg +# define PTR_MANGLE2(reg, tmpreg) \ + xor reg,tmpreg,reg +# define PTR_MANGLE3(destreg, reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor destreg,tmpreg,reg +# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg) +# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg) +# define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg) +# else +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif + +#endif /* linux/powerpc/powerpc32/sysdep.h */ diff --git a/libc/sysdeps/linux/powerpc/bits/termios.h b/libc/sysdeps/linux/powerpc/bits/termios.h new file mode 100644 index 0000000..7aac02d --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/termios.h @@ -0,0 +1,319 @@ +/* Copyright (C) 1997,1999,2001,2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +/* + * termios type and macro definitions. Be careful about adding stuff + * to this file since it's used in GNU libc and there are strict rules + * concerning namespace pollution. + */ + +#define NCCS 32 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VMIN 5 +#define VEOL 6 +#define VTIME 7 +#define VEOL2 8 +#define VSWTC 9 + +#define VWERASE 10 +#define VREPRINT 11 +#define VSUSP 12 +#define VSTART 13 +#define VSTOP 14 +#define VLNEXT 15 +#define VDISCARD 16 + +/* c_iflag bits */ +#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 IXON 0001000 +#define IXOFF 0002000 +#define IXANY 0004000 +#define IUCLC 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 00001400 +# define NL0 00000000 +# define NL1 00000400 +# define NL2 00001000 +# define NL3 00001400 +# define TABDLY 00006000 +# define TAB0 00000000 +# define TAB1 00002000 +# define TAB2 00004000 +# define TAB3 00006000 +# define CRDLY 00030000 +# define CR0 00000000 +# define CR1 00010000 +# define CR2 00020000 +# define CR3 00030000 +# define FFDLY 00040000 +# define FF0 00000000 +# define FF1 00040000 +# define BSDLY 00100000 +# define BS0 00000000 +# define BS1 00100000 +#endif +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +#ifdef __USE_MISC +# define XTABS 00006000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0000377 +#endif +#define B0 0000000 /* hang up */ +#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 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +# define CBAUDEX 0000020 +#endif +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 +#define __MAX_BAUD B4000000 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#ifdef __USE_MISC +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00004000 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#ifdef __USE_MISC +# define ECHOCTL 0x00000040 +# define ECHOPRT 0x00000020 +# define ECHOKE 0x00000001 +# define FLUSHO 0x00800000 +# define PENDIN 0x20000000 +#endif +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + +/* Used for packet mode */ +#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 + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 10 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* c_cc characters */ +#define _VINTR 0 +#define _VQUIT 1 +#define _VERASE 2 +#define _VKILL 3 +#define _VEOF 4 +#define _VMIN 5 +#define _VEOL 6 +#define _VTIME 7 +#define _VEOL2 8 +#define _VSWTC 9 + +/* modem lines */ +#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 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* line disciplines */ +#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 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h b/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h new file mode 100644 index 0000000..a3f11df --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h @@ -0,0 +1,42 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ ".long 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +/* this is only an issue on i386 where linux < 2.3.35, so we just assume it works ... */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/powerpc/bits/wordsize.h b/libc/sysdeps/linux/powerpc/bits/wordsize.h new file mode 100644 index 0000000..dc19246 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __powerpc64__ +# define __WORDSIZE 64 +# define __WORDSIZE_COMPAT32 1 +#else +# define __WORDSIZE 32 +#endif + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ && !defined __LONG_DOUBLE_MATH_OPTIONAL + +/* Signal the glibc ABI didn't used to have a `long double'. + The changes all the `long double' function variants to be redirects + to the double functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# endif +#endif diff --git a/libc/sysdeps/linux/powerpc/brk.S b/libc/sysdeps/linux/powerpc/brk.S new file mode 100644 index 0000000..5fe8d40 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/brk.S @@ -0,0 +1,80 @@ +/* brk system call for Linux/ppc. + Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ERRNO_H 1 +#include +#include + +#ifdef __NR_brk + +#ifdef __PIC__ +.section .bss + .align 4 + .globl __curbrk + .hidden __curbrk +__curbrk: .skip 4 + .type __curbrk,@object + .size __curbrk,4 +#else +.comm __curbrk, 4,4 +#endif + + .text + .globl brk + .type brk,@function + .align 2 + +brk: + stwu r1,-16(r1) + stw r3,8(r1) + li 0, __NR_brk; + sc + lwz r6,8(r1) +#ifdef __PIC__ + mflr r4 +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr r5 + addis r5,r5,_GLOBAL_OFFSET_TABLE_-1b@ha + addi r5,r5,_GLOBAL_OFFSET_TABLE_-1b@l +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r5 +# endif + lwz r5,__curbrk@got(r5) + mtlr r4 + stw r3,0(r5) +#else + lis r4,__curbrk@ha + stw r3,__curbrk@l(r4) +#endif + cmplw r6,r3 + addi r1,r1,16 + li r3,0 + blelr+ + li r3,ENOMEM + + b __syscall_error + + .size brk,.-brk + +libc_hidden_def(brk) +#endif diff --git a/libc/sysdeps/linux/powerpc/bsd-_setjmp.S b/libc/sysdeps/linux/powerpc/bsd-_setjmp.S new file mode 100644 index 0000000..585878a --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bsd-_setjmp.S @@ -0,0 +1,35 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. PowerPC version. + Copyright (C) 1994, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include "ppc_asm.h" + +.globl _setjmp; +.type _setjmp, @function; +.align 2; + +_setjmp: + li r4,0 /* Set second argument to 0. */ + + b __sigsetjmp@local + +.size _setjmp,.-_setjmp diff --git a/libc/sysdeps/linux/powerpc/bsd-setjmp.S b/libc/sysdeps/linux/powerpc/bsd-setjmp.S new file mode 100644 index 0000000..f95d082 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/bsd-setjmp.S @@ -0,0 +1,38 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. PowerPC version. + Copyright (C) 1994, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include "ppc_asm.h" + +.globl __setjmp; +.type __setjmp, @function; +.align 2; + +__setjmp: + li r4,1 /* Set second argument to 1. */ + + b __sigsetjmp@local + +.size __setjmp,.-__setjmp + +.globl setjmp; +.set setjmp,__setjmp diff --git a/libc/sysdeps/linux/powerpc/clone.S b/libc/sysdeps/linux/powerpc/clone.S new file mode 100644 index 0000000..15d03f6 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/clone.S @@ -0,0 +1,98 @@ +/* Wrapper around clone system call. + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ERRNO_H 1 +#include +#include + +/* This is the only really unusual system call in PPC linux, but not + because of any weirdness in the system call itself; because of + all the freaky stuff we have to do to make the call useful. */ + +/* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4], + int flags [r5], void *arg [r6]); */ + +#ifdef __NR_clone + .globl clone + .type clone,@function + .align 2 + +clone: + /* Check for child_stack == NULL || fn == NULL. */ + cmpwi cr0,r4,0 + cmpwi cr1,r3,0 + cror cr0*4+eq,cr1*4+eq,cr0*4+eq + beq- cr0,.Lbadargs + + /* Set up stack frame for parent. */ + stwu r1,-32(r1) + stmw r29,16(r1) + + /* Set up stack frame for child. */ + clrrwi r4,r4,4 + li r0,0 + stwu r0,-16(r4) + + /* Save fn, args, stack across syscall. */ + mr r29,r3 /* Function in r29. */ + mr r30,r4 /* Stack pointer in r30. */ + mr r31,r6 /* Argument in r31. */ + + /* 'flags' argument is first parameter to clone syscall. (The other + argument is the stack pointer, already in r4.) */ + mr r3,r5 + + /* Do the call. */ + li 0, __NR_clone + sc + + /* Check for child process. */ + cmpwi cr1,r3,0 + crandc cr1*4+eq,cr1*4+eq,cr0*4+so + bne- cr1,.Lparent /* The '-' is to minimise the race. */ + + /* On at least mklinux DR3a5, clone() doesn't actually change + the stack pointer. I'm pretty sure this is a bug, because + it adds a race condition if a signal is sent to a thread + just after it is created (in the previous three instructions). */ + mr r1,r30 + /* Call procedure. */ + mtctr r29 + mr r3,r31 + bctrl + /* Call _exit with result from procedure. */ + b HIDDEN_JUMPTARGET(_exit) + +.Lparent: + /* Parent. Restore registers & return. */ + lmw r29,16(r1) + addi r1,r1,32 + bnslr+ + + b __syscall_error + +.Lbadargs: + li r3,EINVAL + + b __syscall_error + + .size clone,.-clone +#endif diff --git a/libc/sysdeps/linux/powerpc/crt1.S b/libc/sysdeps/linux/powerpc/crt1.S new file mode 100644 index 0000000..4f1494a --- /dev/null +++ b/libc/sysdeps/linux/powerpc/crt1.S @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2003 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +/* Integer registers. */ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r13 13 +#define r31 31 + +.text + .globl _start + .type _start,%function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,%function + .type __uClibc_main,%function + +_start: + mr r9,r1 /* Save the stack pointer and pass it to __uClibc_main */ + clrrwi r1,r1,4 /* Align stack ptr to 16 bytes */ +#ifdef __PIC__ +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr r31 + addis r31,r31,_GLOBAL_OFFSET_TABLE_-1b@ha + addi r31,r31,_GLOBAL_OFFSET_TABLE_-1b@l +# else + bl _GLOBAL_OFFSET_TABLE_-4@local + mflr r31 +# endif +#endif + /* Set up the small data pointer in r13. */ +#ifdef __PIC__ + lwz r13,_SDA_BASE_@got(r31) +#else + lis r13,_SDA_BASE_@ha + addi r13,r13,_SDA_BASE_@l +#endif + /* Set up an initial stack frame, and clear the LR. */ + li r0,0 + stwu r1,-16(r1) + mtlr r0 + stw r0,0(r1) + /* find argc from the stack pointer */ + lwz r4,0(r9) + /* find argv one word offset from the stack pointer */ + addi r5,r9,4 + mr r8,r3 /* Pass _dl_fini from ldso or NULL if statically linked */ + /* Note: PPC depends on the kernel to zero r3 before */ + /* handing over to user space, otherwise static apps */ + /* will SEGV during exit() */ + + /* Ok, now run uClibc's main() -- shouldn't return */ +#ifdef __PIC__ + lwz r6,_init@got(r31) + lwz r7,_fini@got(r31) + lwz r3,main@got(r31) + b __uClibc_main@plt +#else + lis r6,_init@ha # load top 16 bits + addi r6,r6,_init@l # load bottom 16 bits + lis r7,_fini@ha # load top 16 bits + addi r7,r7,_fini@l # load bottom 16 bits + lis r3,main@ha # load top 16 bits + addi r3,r3,main@l # load bottom 16 bits + b __uClibc_main +#endif + +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/powerpc/crti.S b/libc/sysdeps/linux/powerpc/crti.S new file mode 100644 index 0000000..09589ba --- /dev/null +++ b/libc/sysdeps/linux/powerpc/crti.S @@ -0,0 +1,24 @@ + .file "initfini.c" + + .section .init + .align 2 + .globl _init + .type _init, @function +_init: + stwu 1,-32(1) + mflr 0 + stw 0,36(1) + + .align 2 + + + .section .fini + .align 2 + .globl _fini + .type _fini, @function +_fini: + stwu 1,-32(1) + mflr 0 + stw 0,36(1) + + .align 2 diff --git a/libc/sysdeps/linux/powerpc/crtn.S b/libc/sysdeps/linux/powerpc/crtn.S new file mode 100644 index 0000000..ba6d0e0 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/crtn.S @@ -0,0 +1,23 @@ + .file "initfini.c" + + .section .init + .align 2 + .globl _init + .type _init, @function + + lwz 0,36(1) + addi 1,1,32 + mtlr 0 + blr + .size _init, .-_init + + .section .fini + .align 2 + .globl _fini + .type _fini, @function + + lwz 0,36(1) + addi 1,1,32 + mtlr 0 + blr + .size _fini, .-_fini diff --git a/libc/sysdeps/linux/powerpc/fenv.h b/libc/sysdeps/linux/powerpc/fenv.h new file mode 100644 index 0000000..8a06f02 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/fenv.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 7.6: Floating-point environment + */ + +#ifndef _FENV_H +#define _FENV_H 1 + +#include + +/* Get the architecture dependend definitions. The following definitions + are expected to be done: + + fenv_t type for object representing an entire floating-point + environment + + FE_DFL_ENV macro of type pointer to fenv_t to be used as the argument + to functions taking an argument of type fenv_t; in this + case the default environment will be used + + fexcept_t type for object representing the floating-point exception + flags including status associated with the flags + + The following macros are defined iff the implementation supports this + kind of exception. + FE_INEXACT inexact result + FE_DIVBYZERO division by zero + FE_UNDERFLOW result not representable due to underflow + FE_OVERFLOW result not representable due to overflow + FE_INVALID invalid operation + + FE_ALL_EXCEPT bitwise OR of all supported exceptions + + The next macros are defined iff the appropriate rounding mode is + supported by the implementation. + FE_TONEAREST round to nearest + FE_UPWARD round toward +Inf + FE_DOWNWARD round toward -Inf + FE_TOWARDZERO round toward 0 +*/ +#include + +__BEGIN_DECLS + +/* Floating-point exception handling. */ + +/* Clear the supported exceptions represented by EXCEPTS. */ +extern int feclearexcept (int __excepts) __THROW; + +/* Store implementation-defined representation of the exception flags + indicated by EXCEPTS in the object pointed to by FLAGP. */ +extern int fegetexceptflag (fexcept_t *__flagp, int __excepts) __THROW; + +/* Raise the supported exceptions represented by EXCEPTS. */ +extern int feraiseexcept (int __excepts) __THROW; + +/* Set complete status for exceptions indicated by EXCEPTS according to + the representation in the object pointed to by FLAGP. */ +extern int fesetexceptflag (__const fexcept_t *__flagp, int __excepts) __THROW; + +/* Determine which of subset of the exceptions specified by EXCEPTS are + currently set. */ +extern int fetestexcept (int __excepts) __THROW; + + +/* Rounding control. */ + +/* Get current rounding direction. */ +extern int fegetround (void) __THROW; + +/* Establish the rounding direction represented by ROUND. */ +extern int fesetround (int __rounding_direction) __THROW; + + +/* Floating-point environment. */ + +/* Store the current floating-point environment in the object pointed + to by ENVP. */ +extern int fegetenv (fenv_t *__envp) __THROW; + +/* Save the current environment in the object pointed to by ENVP, clear + exception flags and install a non-stop mode (if available) for all + exceptions. */ +extern int feholdexcept (fenv_t *__envp) __THROW; + +/* Establish the floating-point environment represented by the object + pointed to by ENVP. */ +extern int fesetenv (__const fenv_t *__envp) __THROW; + +/* Save current exceptions in temporary storage, install environment + represented by object pointed to by ENVP and raise exceptions + according to saved exceptions. */ +extern int feupdateenv (__const fenv_t *__envp) __THROW; + + +/* Include optimization. */ +#ifdef __OPTIMIZE__ +# include +#endif + +#ifdef __USE_GNU + +/* Enable individual exceptions. Will not enable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully set, otherwise returns -1. */ +extern int feenableexcept (int __excepts) __THROW; + +/* Disable individual exceptions. Will not disable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully disabled, otherwise returns -1. */ +extern int fedisableexcept (int __excepts) __THROW; + +/* Return enabled exceptions. */ +extern int fegetexcept (void) __THROW; +#endif + +__END_DECLS + +#endif /* fenv.h */ diff --git a/libc/sysdeps/linux/powerpc/fpu_control.h b/libc/sysdeps/linux/powerpc/fpu_control.h new file mode 100644 index 0000000..442da47 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/fpu_control.h @@ -0,0 +1,94 @@ +/* FPU control word definitions. PowerPC and PowerPC e500 versions. + Copyright (C) 1996, 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + e500 parts contributed by Aldy Hernandez . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#include + +/* rounding control */ +#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x03 +#define _FPU_RC_UP 0x02 +#define _FPU_RC_ZERO 0x01 + +#define _FPU_MASK_NI 0x04 /* non-ieee mode */ + +/* masking of interrupts */ +#define _FPU_MASK_ZM 0x10 /* zero divide */ +#define _FPU_MASK_OM 0x40 /* overflow */ +#define _FPU_MASK_UM 0x20 /* underflow */ +#define _FPU_MASK_XM 0x08 /* inexact */ +#define _FPU_MASK_IM 0x80 /* invalid operation */ + + +/* The fdlibm code requires no interrupts for exceptions. */ +#define _FPU_DEFAULT 0x00000000 /* Default value. */ + + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + + +#ifdef __CONFIG_E500__ +#define _FPU_RESERVED 0xff3fff7f /* These bits are reserved are not changed. */ +/* IEEE: same as above, but (some) exceptions; + we leave the 'inexact' exception off. + */ +#define _FPU_IEEE 0x000003c0 + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(__cw) ({ \ + unsigned int env; \ + __asm__ __volatile__ ("mfspefscr %0" : "=r" (env)); \ + (__cw) = env; }) +#define _FPU_SETCW(__cw) ({ \ + unsigned int env = __cw; \ + __asm__ __volatile__ ("mtspefscr %0" : : "r" (env)); }) +#else +#define _FPU_RESERVED 0xffffff00 /* These bits are reserved are not changed. */ +/* IEEE: same as above, but (some) exceptions; + we leave the 'inexact' exception off. + */ +#define _FPU_IEEE 0x000000f0 + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(__cw) ( { \ + union { double d; fpu_control_t cw[2]; } \ + tmp __attribute__ ((__aligned__(8))); \ + __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \ + (__cw)=tmp.cw[1]; \ + tmp.cw[1]; } ) +#define _FPU_SETCW(__cw) { \ + union { double d; fpu_control_t cw[2]; } \ + tmp __attribute__ ((__aligned__(8))); \ + tmp.cw[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \ + tmp.cw[1] = __cw; \ + __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \ +} + +#endif /* __CONFIG_E500__ */ + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/libc/sysdeps/linux/powerpc/ioctl.c b/libc/sysdeps/linux/powerpc/ioctl.c new file mode 100644 index 0000000..e123627 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/ioctl.c @@ -0,0 +1,74 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(ioctl) + +libc_hidden_proto(tcsetattr) +libc_hidden_proto(tcgetattr) + +/* The user-visible size of struct termios has changed. Catch ioctl calls + using the new-style struct termios, and translate them to old-style. */ + +#define __NR___syscall_ioctl __NR_ioctl +static __always_inline +_syscall3(int, __syscall_ioctl, int, fd, unsigned long int, request, void *, arg) + + +int ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + int result; + + va_start (ap, request); + arg = va_arg (ap, void *); + + switch (request) + { + case TCGETS: + result = tcgetattr (fd, (struct termios *) arg); + break; + + case TCSETS: + result = tcsetattr (fd, TCSANOW, (struct termios *) arg); + break; + + case TCSETSW: + result = tcsetattr (fd, TCSADRAIN, (struct termios *) arg); + break; + + case TCSETSF: + result = tcsetattr (fd, TCSAFLUSH, (struct termios *) arg); + break; + + default: + result = __syscall_ioctl (fd, request, arg); + break; + } + + va_end (ap); + + return result; +} +libc_hidden_def(ioctl) diff --git a/libc/sysdeps/linux/powerpc/ppc_asm.h b/libc/sysdeps/linux/powerpc/ppc_asm.h new file mode 100644 index 0000000..e51d88f --- /dev/null +++ b/libc/sysdeps/linux/powerpc/ppc_asm.h @@ -0,0 +1,137 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +/* Symbolic names for the registers. The only portable way to write asm + code is to use number but this produces really unreadable code. + Therefore these symbolic names. */ + +/* Integer registers. */ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +/* Floating-point registers. */ +#define fp0 0 +#define fp1 1 +#define fp2 2 +#define fp3 3 +#define fp4 4 +#define fp5 5 +#define fp6 6 +#define fp7 7 +#define fp8 8 +#define fp9 9 +#define fp10 10 +#define fp11 11 +#define fp12 12 +#define fp13 13 +#define fp14 14 +#define fp15 15 +#define fp16 16 +#define fp17 17 +#define fp18 18 +#define fp19 19 +#define fp20 20 +#define fp21 21 +#define fp22 22 +#define fp23 23 +#define fp24 24 +#define fp25 25 +#define fp26 26 +#define fp27 27 +#define fp28 28 +#define fp29 29 +#define fp30 30 +#define fp31 31 + +/* Condition code registers. */ +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +/* Vector registers. */ +#define v0 0 +#define v1 1 +#define v2 2 +#define v3 3 +#define v4 4 +#define v5 5 +#define v6 6 +#define v7 7 +#define v8 8 +#define v9 9 +#define v10 10 +#define v11 11 +#define v12 12 +#define v13 13 +#define v14 14 +#define v15 15 +#define v16 16 +#define v17 17 +#define v18 18 +#define v19 19 +#define v20 20 +#define v21 21 +#define v22 22 +#define v23 23 +#define v24 24 +#define v25 25 +#define v26 26 +#define v27 27 +#define v28 28 +#define v29 29 +#define v30 30 +#define v31 31 + +#endif /* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/powerpc/pread_write.c b/libc/sysdeps/linux/powerpc/pread_write.c new file mode 100644 index 0000000..b3175ec --- /dev/null +++ b/libc/sysdeps/linux/powerpc/pread_write.c @@ -0,0 +1,183 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include + +#ifndef __UCLIBC_HAS_LFS__ +# define off64_t off_t +#endif + +#ifdef __NR_pread +extern __typeof(pread) __libc_pread; +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, + void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset))); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset))); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pread */ + + +#ifdef __NR_pwrite +extern __typeof(pwrite) __libc_pwrite; +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, + const void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset))); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pwrite64) __libc_pwrite64; +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset))); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + + + +#if ! defined __NR_pread || ! defined __NR_pwrite +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(lseek) + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek (fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lseek64) + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64 (fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, buf, count, offset, 0)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, buf, count, offset, 0)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, (void*)buf, count, offset, 1)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, (void*)buf, count, offset, 1)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/libc/sysdeps/linux/powerpc/setjmp.S b/libc/sysdeps/linux/powerpc/setjmp.S new file mode 100644 index 0000000..04b06d6 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/setjmp.S @@ -0,0 +1,92 @@ +/* setjmp for PowerPC and PowerPC e500. + Copyright (C) 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + e500 contributed by Aldy Hernandez . + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ASM +#define _SETJMP_H +#include + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#define FP(x...) x +#else +#define FP(x...) +#endif + +#if defined __CONFIG_E500__ +#define LFD(reg) evldd r##reg +#define STFD(reg) evstdd r##reg +#else +#define LFD(reg) lfd fp##reg +#define STFD(reg) stfd fp##reg +#endif /* __CONFIG_E500__ */ + +.globl __sigsetjmp; +.type __sigsetjmp, @function; +.align 2; + +__sigsetjmp: + stw r1,(JB_GPR1*4)(3) + mflr r0 + stw r2,(JB_GPR2*4)(3) + stw r14,((JB_GPRS+0)*4)(3) +FP( STFD (14),((JB_FPRS+0*2)*4)(3)) + stw r0,(JB_LR*4)(3) + stw r15,((JB_GPRS+1)*4)(3) +FP( STFD (15),((JB_FPRS+1*2)*4)(3)) + mfcr r0 + stw r16,((JB_GPRS+2)*4)(3) +FP( STFD (16),((JB_FPRS+2*2)*4)(3)) + stw r0,(JB_CR*4)(3) + stw r17,((JB_GPRS+3)*4)(3) +FP( STFD (17),((JB_FPRS+3*2)*4)(3)) + stw r18,((JB_GPRS+4)*4)(3) +FP( STFD (18),((JB_FPRS+4*2)*4)(3)) + stw r19,((JB_GPRS+5)*4)(3) +FP( STFD (19),((JB_FPRS+5*2)*4)(3)) + stw r20,((JB_GPRS+6)*4)(3) +FP( STFD (20),((JB_FPRS+6*2)*4)(3)) + stw r21,((JB_GPRS+7)*4)(3) +FP( STFD (21),((JB_FPRS+7*2)*4)(3)) + stw r22,((JB_GPRS+8)*4)(3) +FP( STFD (22),((JB_FPRS+8*2)*4)(3)) + stw r23,((JB_GPRS+9)*4)(3) +FP( STFD (23),((JB_FPRS+9*2)*4)(3)) + stw r24,((JB_GPRS+10)*4)(3) +FP( STFD (24),((JB_FPRS+10*2)*4)(3)) + stw r25,((JB_GPRS+11)*4)(3) +FP( STFD (25),((JB_FPRS+11*2)*4)(3)) + stw r26,((JB_GPRS+12)*4)(3) +FP( STFD (26),((JB_FPRS+12*2)*4)(3)) + stw r27,((JB_GPRS+13)*4)(3) +FP( STFD (27),((JB_FPRS+13*2)*4)(3)) + stw r28,((JB_GPRS+14)*4)(3) +FP( STFD (28),((JB_FPRS+14*2)*4)(3)) + stw r29,((JB_GPRS+15)*4)(3) +FP( STFD (29),((JB_FPRS+15*2)*4)(3)) + stw r30,((JB_GPRS+16)*4)(3) +FP( STFD (30),((JB_FPRS+16*2)*4)(3)) + stw r31,((JB_GPRS+17)*4)(3) +FP( STFD (31),((JB_FPRS+17*2)*4)(3)) + + b __sigjmp_save@local + +.size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/powerpc/sys/procfs.h b/libc/sysdeps/linux/powerpc/sys/procfs.h new file mode 100644 index 0000000..1184636 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/sys/procfs.h @@ -0,0 +1,140 @@ +/* Copyright (C) 1996, 1997, 1999, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* These definitions are normally provided by ucontext.h via + asm/sigcontext.h, asm/ptrace.h, and asm/elf.h. Otherwise we define + them here. */ +#ifndef __PPC64_ELF_H +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ +#if __WORDSIZE == 32 +# define ELF_NVRREG 33 /* includes vscr */ +#else +# define ELF_NVRREG 34 /* includes vscr */ +#endif + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Altivec registers */ +typedef struct { + unsigned int u[4]; +} __attribute__ ((aligned (16))) elf_vrreg_t; +typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; +#endif + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + __uid_t pr_uid; + __gid_t pr_gid; + __pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/powerpc/sys/ptrace.h b/libc/sysdeps/linux/powerpc/sys/ptrace.h new file mode 100644 index 0000000..91a8730 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/sys/ptrace.h @@ -0,0 +1,99 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/powerpc/sys/ucontext.h b/libc/sysdeps/linux/powerpc/sys/ucontext.h new file mode 100644 index 0000000..737512a --- /dev/null +++ b/libc/sysdeps/linux/powerpc/sys/ucontext.h @@ -0,0 +1,177 @@ +/* Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +#if __WORDSIZE == 32 + +/* Number of general registers. */ +# define NGREG 48 + +/* Container for all general registers. */ +typedef unsigned long gregset_t[NGREG]; + +/* Container for floating-point registers and status */ +typedef struct _libc_fpstate +{ + double fpregs[32]; + double fpscr; + unsigned int _pad[2]; +} fpregset_t; + +/* Container for Altivec/VMX registers and status. + Needs to be aligned on a 16-byte boundary. */ +typedef struct _libc_vrstate +{ + unsigned int vrregs[32][4]; + unsigned int vrsave; + unsigned int _pad[2]; + unsigned int vscr; +} vrregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + gregset_t gregs; + fpregset_t fpregs; + vrregset_t vrregs __attribute__((__aligned__(16))); +} mcontext_t; + +#else + +/* For 64-bit kernels with Altivec support, a machine context is exactly + * a sigcontext. For older kernel (without Altivec) the sigcontext matches + * the mcontext upto but not including the v_regs field. For kernels that + * don't AT_HWCAP or return AT_HWCAP without PPC_FEATURE_HAS_ALTIVEC the + * v_regs field may not exit and should not be referenced. The v_regd field + * can be refernced safely only after verifying that PPC_FEATURE_HAS_ALTIVEC + * is set in AT_HWCAP. */ + +/* Number of general registers. */ +# define NGREG 48 /* includes r0-r31, nip, msr, lr, etc. */ +# define NFPREG 33 /* includes fp0-fp31 &fpscr. */ +# define NVRREG 34 /* includes v0-v31, vscr, & vrsave in split vectors */ + +typedef unsigned long gregset_t[NGREG]; +typedef double fpregset_t[NFPREG]; + +/* Container for Altivec/VMX Vector Status and Control Register. Only 32-bits + but can only be copied to/from a 128-bit vector register. So we allocated + a whole quadword speedup save/restore. */ +typedef struct _libc_vscr +{ + unsigned int __pad[3]; + unsigned int vscr_word; +} vscr_t; + +/* Container for Altivec/VMX registers and status. + Must to be aligned on a 16-byte boundary. */ +typedef struct _libc_vrstate +{ + unsigned int vrregs[32][4]; + vscr_t vscr; + unsigned int vrsave; + unsigned int __pad[3]; +} vrregset_t __attribute__((__aligned__(16))); + +typedef struct { + unsigned long __unused[4]; + int signal; + int __pad0; + unsigned long handler; + unsigned long oldmask; + struct pt_regs *regs; + gregset_t gp_regs; + fpregset_t fp_regs; +/* + * To maintain compatibility with current implementations the sigcontext is + * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) + * followed by an unstructured (vmx_reserve) field of 69 doublewords. This + * allows the array of vector registers to be quadword aligned independent of + * the alignment of the containing sigcontext or ucontext. It is the + * responsibility of the code setting the sigcontext to set this pointer to + * either NULL (if this processor does not support the VMX feature) or the + * address of the first quadword within the allocated (vmx_reserve) area. + * + * The pointer (v_regs) of vector type (elf_vrreg_t) is essentually + * an array of 34 quadword entries. The entries with + * indexes 0-31 contain the corresponding vector registers. The entry with + * index 32 contains the vscr as the last word (offset 12) within the + * quadword. This allows the vscr to be stored as either a quadword (since + * it must be copied via a vector register to/from storage) or as a word. + * The entry with index 33 contains the vrsave as the first word (offset 0) + * within the quadword. + */ + vrregset_t *v_regs; + long vmx_reserve[NVRREG+NVRREG+1]; +} mcontext_t; + +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; +#if __WORDSIZE == 32 + /* + * These fields are set up this way to maximize source and + * binary compatibility with code written for the old + * ucontext_t definition, which didn't include space for the + * registers. + * + * Different versions of the kernel have stored the registers on + * signal delivery at different offsets from the ucontext struct. + * Programs should thus use the uc_mcontext.uc_regs pointer to + * find where the registers are actually stored. The registers + * will be stored within the ucontext_t struct but not necessarily + * at a fixed address. As a side-effect, this lets us achieve + * 16-byte alignment for the register storage space if the + * Altivec registers are to be saved, without requiring 16-byte + * alignment on the whole ucontext_t. + * + * The uc_mcontext.regs field is included for source compatibility + * with programs written against the older ucontext_t definition, + * and its name should therefore not change. The uc_pad field + * is for binary compatibility with programs compiled against the + * old ucontext_t; it ensures that uc_mcontext.regs and uc_sigmask + * are at the same offset as previously. + */ + int uc_pad[7]; + union uc_regs_ptr { + struct pt_regs *regs; + mcontext_t *uc_regs; + } uc_mcontext; + sigset_t uc_sigmask; + char uc_reg_space[sizeof(mcontext_t) + 12]; /* last for extensibility */ +#else /* 64-bit */ + sigset_t uc_sigmask; + mcontext_t uc_mcontext; /* last for extensibility */ +#endif + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/powerpc/sys/user.h b/libc/sysdeps/linux/powerpc/sys/user.h new file mode 100644 index 0000000..e8a8aaa --- /dev/null +++ b/libc/sysdeps/linux/powerpc/sys/user.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H + +#define _SYS_USER_H 1 +#include + +#include + +struct user { + struct pt_regs regs; /* entire machine state */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif /* sys/user.h */ diff --git a/libc/sysdeps/linux/powerpc/syscall.S b/libc/sysdeps/linux/powerpc/syscall.S new file mode 100644 index 0000000..b853984 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/syscall.S @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1992, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text + .globl syscall + .type syscall,@function + .align 2 + +syscall: + mr 0,3 + mr 3,4 + mr 4,5 + mr 5,6 + mr 6,7 + mr 7,8 + sc + bnslr; + + b __syscall_error + + .size syscall,.-syscall diff --git a/libc/sysdeps/linux/powerpc/vfork.S b/libc/sysdeps/linux/powerpc/vfork.S new file mode 100644 index 0000000..600c980 --- /dev/null +++ b/libc/sysdeps/linux/powerpc/vfork.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,@function +.type __syscall_error,@function + +__vfork: + li 0, __NR_vfork + sc + bnslr+ + b __syscall_error + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/sh/Makefile b/libc/sysdeps/linux/sh/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/sh/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/sh/Makefile.arch b/libc/sysdeps/linux/sh/Makefile.arch new file mode 100644 index 0000000..77ad570 --- /dev/null +++ b/libc/sysdeps/linux/sh/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2001 by Hewlett-Packard Australia +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := \ + mmap.c pipe.c __init_brk.c brk.c sbrk.c syscall.c pread_write.c + +SSRC := setjmp.S __longjmp.S vfork.S clone.S ___fpscr_values.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/sh/___fpscr_values.S b/libc/sysdeps/linux/sh/___fpscr_values.S new file mode 100644 index 0000000..de8f0b4 --- /dev/null +++ b/libc/sysdeps/linux/sh/___fpscr_values.S @@ -0,0 +1,34 @@ +/* Startup code for SH & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + Copyright (C) 2002 Stefan Allius + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +.data +#if defined(__CONFIG_SH4__) +.global ___fpscr_values +.type ___fpscr_values,@object +.size ___fpscr_values,8 +___fpscr_values: + .long 0 + .long 0x80000 + +.weak __fpscr_values + __fpscr_values = ___fpscr_values +#endif diff --git a/libc/sysdeps/linux/sh/__init_brk.c b/libc/sysdeps/linux/sh/__init_brk.c new file mode 100644 index 0000000..8a41eb3 --- /dev/null +++ b/libc/sysdeps/linux/sh/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/libc/sysdeps/linux/sh/__longjmp.S b/libc/sysdeps/linux/sh/__longjmp.S new file mode 100644 index 0000000..eb56991 --- /dev/null +++ b/libc/sysdeps/linux/sh/__longjmp.S @@ -0,0 +1,65 @@ +/* longjmp for SH. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define _SETJMP_H +#define _ASM +#include +#include + +/* __longjmp(jmpbuf, val) */ + +.text +.align 4 +.type __longjmp,@function +.globl __longjmp; +__longjmp: + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + lds.l @r4+, pr + ldc.l @r4+, gbr + lds.l @r4+, fpscr + fmov.s @r4+, fr12 + fmov.s @r4+, fr13 + mov r5, r0 /* get the return value in place */ + tst r0, r0 + bf.s 1f + fmov.s @r4+, fr14 + mov #1,r0 /* can't let setjmp() return zero! */ +1: + rts + fmov.s @r4+, fr15 +#else + mov r5, r0 /* get the return value in place */ + tst r0, r0 + bf.s 1f + lds.l @r4+, pr + mov #1,r0 /* can't let setjmp() return zero! */ +1: + rts + ldc.l @r4+, gbr +#endif +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/sh/bits/atomic.h b/libc/sysdeps/linux/sh/bits/atomic.h new file mode 100644 index 0000000..6bb7255 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/atomic.h @@ -0,0 +1,419 @@ +/* Atomic operations used inside libc. Linux/SH version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +/* SH kernel has implemented a gUSA ("g" User Space Atomicity) support + for the user space atomicity. The atomicity macros use this scheme. + + Reference: + Niibe Yutaka, "gUSA: Simple and Efficient User Space Atomicity + Emulation with Little Kernel Modification", Linux Conference 2002, + Japan. http://lc.linux.or.jp/lc2002/papers/niibe0919h.pdf (in + Japanese). + + B.N. Bershad, D. Redell, and J. Ellis, "Fast Mutual Exclusion for + Uniprocessors", Proceedings of the Fifth Architectural Support for + Programming Languages and Operating Systems (ASPLOS), pp. 223-233, + October 1992. http://www.cs.washington.edu/homes/bershad/Papers/Rcs.ps + + SuperH ABI: + r15: -(size of atomic instruction sequence) < 0 + r0: end point + r1: saved stack pointer +*/ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*(mem)) __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.b @%1,%0\n\ + cmp/eq %0,%3\n\ + bf 1f\n\ + mov.b %2,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "t", "memory"); \ + __result; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __typeof (*(mem)) __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.w @%1,%0\n\ + cmp/eq %0,%3\n\ + bf 1f\n\ + mov.w %2,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "t", "memory"); \ + __result; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __typeof (*(mem)) __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,%0\n\ + cmp/eq %0,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "t", "memory"); \ + __result; }) + +/* XXX We do not really need 64-bit compare-and-exchange. At least + not in the moment. Using it would mean causing portability + problems since not many other 32-bit architectures have support for + such an operation. So don't define any code for now. */ + +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*(mem)) __result, __tmp, __value = (value); \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,%0\n\ + add %0,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,%0\n\ + add %0,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,%0\n\ + add %0,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "memory"); \ + else \ + { \ + __typeof (mem) memp = (mem); \ + do \ + __result = *memp; \ + while (__arch_compare_and_exchange_val_64_acq \ + (memp, __result + __value, __result) == __result); \ + (void) __value; \ + } \ + __result; }) + +#define atomic_add(mem, value) \ + (void) ({ __typeof (*(mem)) __tmp, __value = (value); \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%1,r2\n\ + add r2,%0\n\ + mov.b %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__tmp) : "r" (mem), "0" (__value) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%1,r2\n\ + add r2,%0\n\ + mov.w %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__tmp) : "r" (mem), "0" (__value) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,r2\n\ + add r2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__tmp) : "r" (mem), "0" (__value) \ + : "r0", "r1", "r2", "memory"); \ + else \ + { \ + __typeof (*(mem)) oldval; \ + __typeof (mem) memp = (mem); \ + do \ + oldval = *memp; \ + while (__arch_compare_and_exchange_val_64_acq \ + (memp, oldval + __value, oldval) == oldval); \ + (void) __value; \ + } \ + }) + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + __typeof (*(mem)) __tmp, __value = (value); \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,r2\n\ + add r2,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,r2\n\ + add r2,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,r2\n\ + add r2,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else \ + abort (); \ + __result; }) + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + __typeof (*(mem)) __tmp, __value = (value); \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,r2\n\ + add r2,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,r2\n\ + add r2,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,r2\n\ + add r2,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (__tmp) : "r" (mem), "1" (__value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else \ + abort (); \ + __result; }) + +#define atomic_increment_and_test(mem) atomic_add_zero((mem), 1) +#define atomic_decrement_and_test(mem) atomic_add_zero((mem), -1) + +#define atomic_bit_set(mem, bit) \ + (void) ({ unsigned int __mask = 1 << (bit); \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%0,r2\n\ + or %1,r2\n\ + mov.b r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%0,r2\n\ + or %1,r2\n\ + mov.w r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%0,r2\n\ + or %1,r2\n\ + mov.l r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else \ + abort (); \ + }) + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned int __mask = 1 << (bit); \ + unsigned int __result = __mask; \ + if (sizeof (*(mem)) == 1) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.b @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 2) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.w @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*(mem)) == 4) \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else \ + abort (); \ + __result; }) diff --git a/libc/sysdeps/linux/sh/bits/endian.h b/libc/sysdeps/linux/sh/bits/endian.h new file mode 100644 index 0000000..1fef1ff --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/endian.h @@ -0,0 +1,13 @@ +/* SH is bi-endian but with a big-endian FPU. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +#define __BYTE_ORDER __LITTLE_ENDIAN +#define __FLOAT_WORD_ORDER __LITTLE_ENDIAN +#else +#define __BYTE_ORDER __BIG_ENDIAN +#define __FLOAT_WORD_ORDER __BIG_ENDIAN +#endif diff --git a/libc/sysdeps/linux/sh/bits/fcntl.h b/libc/sysdeps/linux/sh/bits/fcntl.h new file mode 100644 index 0000000..93c41d2 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/fcntl.h @@ -0,0 +1,241 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/sh/bits/fenv.h b/libc/sysdeps/linux/sh/bits/fenv.h new file mode 100644 index 0000000..cbbad92 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/fenv.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INEXACT = 0x04, +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = 0x08, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 0x10, +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = 0x20, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = 0x40, +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The SH FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0x0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 0x2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 0x3 +#define FE_DOWNWARD FE_DOWNWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned int __fpscr; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1) diff --git a/libc/sysdeps/linux/sh/bits/huge_val.h b/libc/sysdeps/linux/sh/bits/huge_val.h new file mode 100644 index 0000000..732b065 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/huge_val.h @@ -0,0 +1,56 @@ +/* `HUGE_VAL' constants for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + SH version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/libc/sysdeps/linux/sh/bits/kernel_stat.h b/libc/sysdeps/linux/sh/bits/kernel_stat.h new file mode 100644 index 0000000..2e88dad --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/kernel_stat.h @@ -0,0 +1,89 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +#include + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad0b[6]; + unsigned short st_dev; +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) + unsigned short st_dev; + unsigned char __pad0b[6]; +#else +#error Must know endian to build stat64 structure! +#endif + unsigned char __pad0[4]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad3b[6]; + unsigned short st_rdev; +#else /* Must be little */ + unsigned short st_rdev; + unsigned char __pad3b[6]; +#endif + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long __pad4; /* Future possible st_blocks hi bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ +#else /* Must be little */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* Future possible st_blocks hi bits */ +#endif + + unsigned long st_atime; + unsigned long __pad5; + + unsigned long st_mtime; + unsigned long __pad6; + + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/sh/bits/kernel_types.h b/libc/sysdeps/linux/sh/bits/kernel_types.h new file mode 100644 index 0000000..7d55cf5 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_SH_POSIX_TYPES_H +#define __ASM_SH_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_SH_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/sh/bits/mathdef.h b/libc/sysdeps/linux/sh/bits/mathdef.h new file mode 100644 index 0000000..c419fcd --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/mathdef.h @@ -0,0 +1,63 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! + + FIXME! This file does not deal with the -fshort-double option of + gcc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# ifdef __GNUC__ +# if __STDC__ == 1 + +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +# else + +/* For `gcc -traditional', `float' expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +# endif +# else + +/* Wild guess at types for float_t and double_t. */ +typedef double float_t; +typedef double double_t; + +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 0x80000001 +# define FP_ILOGBNAN 0x7fffffff + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/sh/bits/mman.h b/libc/sysdeps/linux/sh/bits/mman.h new file mode 100644 index 0000000..7a6b572 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/mman.h @@ -0,0 +1,103 @@ +/* Definitions for POSIX memory map interface. Linux/SH version. + Copyright (C) 1997,1999,2000,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x8000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/sh/bits/setjmp.h b/libc/sysdeps/linux/sh/bits/setjmp.h new file mode 100644 index 0000000..6458dfe --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/setjmp.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1999, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. SH version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Callee-saved registers r8 through r15. */ + int __regs[8]; + + /* Program counter. */ + void * __pc; + + /* The global pointer. */ + void * __gbr; + + /* Floating point status register. */ + int __fpscr; + + /* Callee-saved floating point registers fr12 through fr15. */ + int __fpregs[4]; + } __jmp_buf[1]; +#endif + +#if defined __USE_MISC || defined _ASM +# define JB_SIZE (4 * 15) +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__regs[7]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/sh/bits/shm.h b/libc/sysdeps/linux/sh/bits/shm.h new file mode 100644 index 0000000..ccf4b89 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/shm.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +/* + * XXX: This is misleading, SH-4 and SH-3 7705 in 32kb mode have dcache + * aliases to contend with in the 4k page case. This is not an issue for + * the other parts. Leave this bumped up for sanity until this can be + * accurately defined by the L1D shape through the auxiliary vector. + */ +#define SHMLBA (__getpagesize() << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/sh/bits/sigcontextinfo.h b/libc/sysdeps/linux/sh/bits/sigcontextinfo.h new file mode 100644 index 0000000..3e1f3e9 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _a2, int _a3, int _a4, struct sigcontext + +#define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, +#define GET_PC(ctx) ((void *) ctx.sc_pc) +#define GET_FRAME(ctx) ((void *) ctx.sc_regs[14]) +#define GET_STACK(ctx) ((void *) ctx.sc_regs[15]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/sh/bits/stackinfo.h b/libc/sysdeps/linux/sh/bits/stackinfo.h new file mode 100644 index 0000000..e65338f --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On SH the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/sh/bits/syscalls.h b/libc/sysdeps/linux/sh/bits/syscalls.h new file mode 100644 index 0000000..bcd73eb --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/syscalls.h @@ -0,0 +1,291 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* The Linux kernel uses different trap numbers on sh-2. */ +#ifdef __CONFIG_SH2__ +# define __SH_SYSCALL_TRAP_BASE 0x20 +#else +# define __SH_SYSCALL_TRAP_BASE 0x10 +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -125: see */ +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + /* Avoid using "res" which is declared to be in register r0; \ + errno might expand to a function call and clobber it. */ \ + int __err = -(res); \ + __set_errno(__err); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define _syscall0(type,name) \ +type name(void) \ +{ \ +register long __sc0 __asm__ ("r3") = __NR_##name; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE), "0" (__sc0) \ + : "memory" ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +register long __sc0 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 1), "0" (__sc0), "r" (__sc4) \ + : "memory"); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +register long __sc0 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +register long __sc5 __asm__ ("r5") = (long) arg2; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 2), "0" (__sc0), "r" (__sc4), \ + "r" (__sc5) \ + : "memory"); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +register long __sc0 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +register long __sc5 __asm__ ("r5") = (long) arg2; \ +register long __sc6 __asm__ ("r6") = (long) arg3; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 3), "0" (__sc0), "r" (__sc4), \ + "r" (__sc5), "r" (__sc6) \ + : "memory"); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +register long __sc0 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +register long __sc5 __asm__ ("r5") = (long) arg2; \ +register long __sc6 __asm__ ("r6") = (long) arg3; \ +register long __sc7 __asm__ ("r7") = (long) arg4; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 4), "0" (__sc0), "r" (__sc4), \ + "r" (__sc5), "r" (__sc6), \ + "r" (__sc7) \ + : "memory" ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ +register long __sc3 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +register long __sc5 __asm__ ("r5") = (long) arg2; \ +register long __sc6 __asm__ ("r6") = (long) arg3; \ +register long __sc7 __asm__ ("r7") = (long) arg4; \ +register long __sc0 __asm__ ("r0") = (long) arg5; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 5), "0" (__sc0), "r" (__sc4), \ + "r" (__sc5), "r" (__sc6), "r" (__sc7), "r" (__sc3) \ + : "memory" ); \ +__syscall_return(type,__sc0); \ +} + +#ifndef __SH_SYSCALL6_TRAPA +#define __SH_SYSCALL6_TRAPA __SH_SYSCALL_TRAP_BASE + 6 +#endif + +/* Add in _syscall6 which is not in the kernel header */ +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ +register long __sc3 __asm__ ("r3") = __NR_##name; \ +register long __sc4 __asm__ ("r4") = (long) arg1; \ +register long __sc5 __asm__ ("r5") = (long) arg2; \ +register long __sc6 __asm__ ("r6") = (long) arg3; \ +register long __sc7 __asm__ ("r7") = (long) arg4; \ +register long __sc0 __asm__ ("r0") = (long) arg5; \ +register long __sc1 __asm__ ("r1") = (long) arg6; \ +__asm__ __volatile__ ("trapa %1" \ + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL6_TRAPA), "0" (__sc0), "r" (__sc4), \ + "r" (__sc5), "r" (__sc6), "r" (__sc7), "r" (__sc3), "r" (__sc1) \ + : "memory" ); \ +__syscall_return(type,__sc0); \ +} + +#define SYSCALL_INST_STR(x) "trapa #"__stringify(__SH_SYSCALL_TRAP_BASE + x)"\n\t" +#define SYSCALL_INST_STR0 SYSCALL_INST_STR(0) +#define SYSCALL_INST_STR1 SYSCALL_INST_STR(1) +#define SYSCALL_INST_STR2 SYSCALL_INST_STR(2) +#define SYSCALL_INST_STR3 SYSCALL_INST_STR(3) +#define SYSCALL_INST_STR4 SYSCALL_INST_STR(4) +#define SYSCALL_INST_STR5 SYSCALL_INST_STR(5) +#define SYSCALL_INST_STR6 SYSCALL_INST_STR(6) + +# ifdef NEED_SYSCALL_INST_PAD +# define SYSCALL_INST_PAD "\ + or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +# define SYSCALL_INST_PAD +# endif + +#define ASMFMT_0 +#define ASMFMT_1 \ + , "r" (r4) +#define ASMFMT_2 \ + , "r" (r4), "r" (r5) +#define ASMFMT_3 \ + , "r" (r4), "r" (r5), "r" (r6) +#define ASMFMT_4 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7) +#define ASMFMT_5 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0) +#define ASMFMT_6 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1) +#define ASMFMT_7 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1), "r" (r2) + +#define SUBSTITUTE_ARGS_0() +#define SUBSTITUTE_ARGS_1(arg1) \ + long int _arg1 = (long int) (arg1); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1) +#define SUBSTITUTE_ARGS_2(arg1, arg2) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2) +#define SUBSTITUTE_ARGS_3(arg1, arg2, arg3) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3) +#define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4) +#define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5) +#define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ + register long int r4 __asm__ ("%r4") = (long int)(_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5); \ + register long int r1 __asm__ ("%r1") = (long int) (_arg6) +#define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ + long int _arg7 = (long int) (arg7); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5); \ + register long int r1 __asm__ ("%r1") = (long int) (_arg6); \ + register long int r2 __asm__ ("%r2") = (long int) (_arg7) + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned int __resultvar = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (__resultvar, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (__resultvar, )); \ + __resultvar = 0xffffffff; \ + } \ + (int) __resultvar; }) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + ({ \ + unsigned long int resultvar; \ + register long int r3 __asm__ ("%r3") = SYS_ify (name); \ + SUBSTITUTE_ARGS_##nr(args); \ + \ + __asm__ volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \ + : "=z" (resultvar) \ + : "r" (r3) ASMFMT_##nr \ + : "memory"); \ + \ + (int) resultvar; }) + +/* The _NCS variant allows non-constant syscall numbers. */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + unsigned long int resultvar; \ + register long int r3 __asm__ ("%r3") = (name); \ + SUBSTITUTE_ARGS_##nr(args); \ + \ + __asm__ volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \ + : "=z" (resultvar) \ + : "r" (r3) ASMFMT_##nr \ + : "memory"); \ + \ + (int) resultvar; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h b/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h new file mode 100644 index 0000000..55e3480 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h @@ -0,0 +1,45 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#if defined(__CONFIG_SH2__) +# define __UCLIBC_ABORT_INSTRUCTION__ "trapa #32" +#else +# define __UCLIBC_ABORT_INSTRUCTION__ "trapa #0xff" +#endif + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/sh/bits/wordsize.h b/libc/sysdeps/linux/sh/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/sh/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/sh/brk.c b/libc/sysdeps/linux/sh/brk.c new file mode 100644 index 0000000..c69c97a --- /dev/null +++ b/libc/sysdeps/linux/sh/brk.c @@ -0,0 +1,28 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(brk) +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/sh/clone.S b/libc/sysdeps/linux/sh/clone.S new file mode 100644 index 0000000..9446803 --- /dev/null +++ b/libc/sysdeps/linux/sh/clone.S @@ -0,0 +1,125 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#define _ERRNO_H +#include +#include + + +#ifdef __HAVE_SHARED__ +#define PLTJMP(_x) _x@PLT +#else +#define PLTJMP(_x) _x +#endif + + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + +.text +.align 4 +.type clone,@function +.globl clone; +clone: + /* sanity check arguments. */ + tst r4, r4 + bt 0f + tst r5, r5 + bf/s 1f + mov #+__NR_clone, r3 +0: + bra __syscall_error + mov #-EINVAL, r4 + +1: + /* insert the args onto the new stack */ + mov.l r7, @-r5 + /* save the function pointer as the 0th element */ + mov.l r4, @-r5 + + /* do the system call */ + mov r6, r4 + trapa #(__SH_SYSCALL_TRAP_BASE + 2) + mov r0, r1 +#ifdef __CONFIG_SH2__ +/* 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! */ + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 +#else + mov #-12, r2 + shad r2, r1 +#endif + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bf/s 2f + tst r0, r0 + bra __syscall_error + mov r0, r4 + +2: + bt 3f + rts + nop +3: + /* thread starts */ + mov.l @r15, r1 + jsr @r1 + mov.l @(4,r15), r4 + + /* we are done, passing the return value through r0 */ + mov.l .L1, r1 +#ifdef __HAVE_SHARED__ + mov.l r12, @-r15 + sts.l pr, @-r15 + mov r0, r4 + mova .LG, r0 /* .LG from syscall_error.S */ + mov.l .LG, r12 + add r0, r12 + mova .L1, r0 + add r0, r1 + jsr @r1 + nop + lds.l @r15+, pr + rts + mov.l @r15+, r12 +#else + jmp @r1 + mov r0, r4 +#endif + .align 2 +.L1: + .long PLTJMP( HIDDEN_JUMPTARGET(_exit)) +.size clone,.-clone; + +#include "syscall_error.S" diff --git a/libc/sysdeps/linux/sh/crt1.S b/libc/sysdeps/linux/sh/crt1.S new file mode 100644 index 0000000..1c3c544 --- /dev/null +++ b/libc/sysdeps/linux/sh/crt1.S @@ -0,0 +1,97 @@ +/* Startup code for SH & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + Copyright (C) 2002 Stefan Allius + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* This is the canonical entry point, usually the first thing in the text + segment. + + At this entry point, most registers' values are unspecified, except: + + r4 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ + +#include + + .text + .globl _start + .type _start,%function + .type main,%function +_start: + /* Clear the frame pointer since this is the outermost frame. */ + mov #0, r14 + + /* Pop argc off the stack and save a pointer to argv */ + mov.l @r15+,r5 + mov r15, r6 + + /* Push the stack_end, rtld_fini and fini func onto the stack */ + mov.l r6,@-r15 + mov.l r4,@-r15 + mov.l L_fini,r0 + mov.l r0,@-r15 + + /* Set up the main/init funcs that go in registers */ + mov.l L_main,r4 + mov.l L_init,r7 + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + + /* Let the libc call main and exit with its return code. */ + mov.l L_uClibc_main,r1 + jsr @r1 + nop + /* We should not get here. */ + mov.l L_abort,r1 + jmp @r1 + nop + + .size _start,.-_start + .align 2 + +L_main: + .long main +L_init: + .long _init +L_fini: + .long _fini +L_uClibc_main: + .long __uClibc_main +L_abort: + .long abort + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/sh/crti.S b/libc/sysdeps/linux/sh/crti.S new file mode 100644 index 0000000..7fba266 --- /dev/null +++ b/libc/sysdeps/linux/sh/crti.S @@ -0,0 +1,32 @@ + .file "crti.S" + .text + + .section .init + .hidden _init + .align 1 + .global _init + .type _init, @function +_init: + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + bra 1f + nop + .align 2 +1: + + .section .fini + .hidden _fini + .align 1 + .global _fini + .type _fini, @function +_fini: + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + bra 1f + nop + .align 2 +1: diff --git a/libc/sysdeps/linux/sh/crtn.S b/libc/sysdeps/linux/sh/crtn.S new file mode 100644 index 0000000..437f8eb --- /dev/null +++ b/libc/sysdeps/linux/sh/crtn.S @@ -0,0 +1,36 @@ + .file "crtn.S" + .text + + .section .init + .hidden _init + .align 1 + .global _init + .type _init, @function + mov r14,r15 + lds.l @r15+,pr + mov.l @r15+,r14 + rts + mov.l @r15+,r12 +.L8: + .align 2 +.L6: +.L7: + .size _init, .-_init + + .section .fini + .hidden _fini + .align 1 + .global _fini + .type _fini, @function + mov r14,r15 + lds.l @r15+,pr + mov.l @r15+,r14 + rts + mov.l @r15+,r12 +.L13: + .align 2 +.L11: +.L12: + .size _fini, .-_fini + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/sh/fpu_control.h b/libc/sysdeps/linux/sh/fpu_control.h new file mode 100644 index 0000000..db3cc45 --- /dev/null +++ b/libc/sysdeps/linux/sh/fpu_control.h @@ -0,0 +1,60 @@ +/* FPU control word definitions. SH version. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#warning This file is only correct for sh4 + +/* masking of interrupts */ +#define _FPU_MASK_VM 0x0800 /* Invalid operation */ +#define _FPU_MASK_ZM 0x0400 /* Division by zero */ +#define _FPU_MASK_OM 0x0200 /* Overflow */ +#define _FPU_MASK_UM 0x0100 /* Underflow */ +#define _FPU_MASK_IM 0x0080 /* Inexact operation */ + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 + +#define _FPU_RESERVED 0xffc00000 /* These bits are reserved. */ + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ +#define _FPU_DEFAULT 0x00080000 /* Default value. */ +#define _FPU_IEEE 0x00080f80 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("sts fpscr,%0" : "=r" (cw)) + +#if defined __GNUC__ +#define _FPU_SETCW(cw) __set_fpscr ((cw)) +#else +#define _FPU_SETCW(cw) __asm__ ("lds %0,fpscr" : : "r" (cw)) +#endif + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/libc/sysdeps/linux/sh/mmap.c b/libc/sysdeps/linux/sh/mmap.c new file mode 100644 index 0000000..56566ea --- /dev/null +++ b/libc/sysdeps/linux/sh/mmap.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2001 Hewlett-Packard + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Derived in part from the Linux-8086 C library, the GNU C Library, and several + other sundry sources. Files within this library are copyright by their + respective copyright holders. +*/ + +#include +#include +#include + +libc_hidden_proto(mmap) + +#ifdef HIOS +# define __SH_SYSCALL6_TRAPA 0x2E +#endif + +#include + +_syscall6(__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/sh/pipe.c b/libc/sysdeps/linux/sh/pipe.c new file mode 100644 index 0000000..432a5bc --- /dev/null +++ b/libc/sysdeps/linux/sh/pipe.c @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * pipe syscall for uClibc sh + * + * Copyright (C) 2001 Lineo, + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(pipe) + +int pipe(int *fd) +{ + long __res, __res2; + __asm__ __volatile__ ( + "mov %2, r3;" + "mov %3, r4;" + "trapa %4;" + "mov r1, %1;" + : "=z" (__res), + "=r" ((long) __res2) + : "r" ((long) __NR_pipe), + "r" ((long) fd), + "i" (__SH_SYSCALL_TRAP_BASE + 3) + : "cc", "memory", "r1", "r3", "r4"); + if ((unsigned long)(__res) >= (unsigned long)(-125)) { + int __err = -(__res); + errno = __err; + return(-1); + } + fd[0] = __res; + fd[1] = __res2; + return(0); +} +libc_hidden_def(pipe) diff --git a/libc/sysdeps/linux/sh/pread_write.c b/libc/sysdeps/linux/sh/pread_write.c new file mode 100644 index 0000000..e03aaee --- /dev/null +++ b/libc/sysdeps/linux/sh/pread_write.c @@ -0,0 +1,83 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +#ifdef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pread +# error "__NR_pread and __NR_pread64 both defined???" +# endif +# define __NR_pread __NR_pread64 +#endif + +#ifdef __NR_pread +extern __typeof(pread) __libc_pread; +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset))); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pread */ + +/**********************************************************************/ + +#ifdef __NR_pwrite64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pwrite +# error "__NR_pwrite and __NR_pwrite64 both defined???" +# endif +# define __NR_pwrite __NR_pwrite64 +#endif + +#ifdef __NR_pwrite +extern __typeof(pwrite) __libc_pwrite; +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset))); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pwrite64) __libc_pwrite64; +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ diff --git a/libc/sysdeps/linux/sh/sbrk.c b/libc/sysdeps/linux/sh/sbrk.c new file mode 100644 index 0000000..a1ff2a1 --- /dev/null +++ b/libc/sysdeps/linux/sh/sbrk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(sbrk) +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/libc/sysdeps/linux/sh/setjmp.S b/libc/sysdeps/linux/sh/setjmp.S new file mode 100644 index 0000000..3296c2b --- /dev/null +++ b/libc/sysdeps/linux/sh/setjmp.S @@ -0,0 +1,102 @@ +/* setjmp for SH3. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _SETJMP_H +#define _ASM +#include + + .text + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type _setjmp,@function + .globl _setjmp; +_setjmp: + bra __sigsetjmp_intern + mov #0, r1 + .size _setjmp,.-_setjmp; + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type setjmp,@function + .globl setjmp; +setjmp: + bra __sigsetjmp_intern + mov #1, r1 + .size setjmp,.-setjmp; + + .align 4 + .type __sigsetjmp,@function + .globl __sigsetjmp; +__sigsetjmp: + mov r0, r1 + nop /* align this guy */ +__sigsetjmp_intern: + /* Save registers */ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + add #(JB_SIZE), r4 + fmov.s fr15, @-r4 + fmov.s fr14, @-r4 + fmov.s fr13, @-r4 + fmov.s fr12, @-r4 + sts.l fpscr, @-r4 +#else + add #(JB_SIZE-(5*4)), r4 /* this code doesn't do FP yet */ +#endif + stc.l gbr, @-r4 + sts.l pr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + +#ifdef __HAVE_SHARED__ + mov.l .LG, r2 + mova .LG, r0 + add r0, r2 + /* Make a tail call to __sigjmp_save; it takes the same args. */ + mov.l .L1, r0 + mov.l @(r0,r2),r0 + jmp @r0 + mov r1, r0 + .align 2 +.LG: .long _GLOBAL_OFFSET_TABLE_ +.L1: .long __sigjmp_save@GOT +#else + /* Make a tail call to __sigjmp_save; it takes the same args. */ + mov.l .L1, r0 + braf r0 + mov r1, r0 +.jmp_loc: + .align 2 +.L1: .long __sigjmp_save - .jmp_loc +#endif + + .size __sigsetjmp,.-__sigsetjmp; diff --git a/libc/sysdeps/linux/sh/sys/io.h b/libc/sysdeps/linux/sh/sys/io.h new file mode 100644 index 0000000..6fdc44f --- /dev/null +++ b/libc/sysdeps/linux/sh/sys/io.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1996, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/sh/sys/procfs.h b/libc/sysdeps/linux/sh/sys/procfs.h new file mode 100644 index 0000000..aad21e5 --- /dev/null +++ b/libc/sysdeps/linux/sh/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * ELF register definitions... + */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fpu_struct elf_fpregset_t; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/sh/sys/ucontext.h b/libc/sysdeps/linux/sh/sys/ucontext.h new file mode 100644 index 0000000..0996bf2 --- /dev/null +++ b/libc/sysdeps/linux/sh/sys/ucontext.h @@ -0,0 +1,121 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Where is System V/SH ABI? */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef int greg_t; + +/* Number of general registers. */ +#define NFPREG 16 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NFPREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 +}; +#endif + +typedef int freg_t; + +/* Number of FPU registers. */ +#define NFPREG 16 + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + unsigned int oldmask; + + /* CPU registers */ + gregset_t gregs; + unsigned int pc; + unsigned int pr; + unsigned int sr; + unsigned int gbr; + unsigned int mach; + unsigned int macl; + +#ifdef __CONFIG_SH4__ + /* FPU registers */ + fpregset_t fpregs; + fpregset_t xfpregs; + unsigned int fpscr; + unsigned int fpul; + unsigned int ownedfp; +#endif + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/sh/sys/user.h b/libc/sysdeps/linux/sh/sys/user.h new file mode 100644 index 0000000..b1adc13 --- /dev/null +++ b/libc/sysdeps/linux/sh/sys/user.h @@ -0,0 +1,78 @@ +/* Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include +#include + +/* + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd). The file contents are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ + +struct user_fpu_struct { + unsigned long fp_regs[16]; + unsigned long xfp_regs[16]; + unsigned long fpscr; + unsigned long fpul; +}; + +struct user { + struct pt_regs regs; /* entire machine state */ + struct user_fpu_struct fpu; /* Math Co-processor registers */ + int u_fpvalid; /* True if math co-processor being used */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + struct user_fpu_struct* u_fpstate; /* Math Co-processor pointer */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG getpagesize() +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/libc/sysdeps/linux/sh/syscall.c b/libc/sysdeps/linux/sh/syscall.c new file mode 100644 index 0000000..ba187c9 --- /dev/null +++ b/libc/sysdeps/linux/sh/syscall.c @@ -0,0 +1,27 @@ + + +#include +#include +#include +#include + +long syscall(long sysnum, + long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +register long __sc3 __asm__ ("r3") = sysnum; +register long __sc4 __asm__ ("r4") = (long) arg1; +register long __sc5 __asm__ ("r5") = (long) arg2; +register long __sc6 __asm__ ("r6") = (long) arg3; +register long __sc7 __asm__ ("r7") = (long) arg4; +register long __sc0 __asm__ ("r0") = (long) arg5; +register long __sc1 __asm__ ("r1") = (long) arg6; +__asm__ __volatile__ ( + "trapa %1" + : "=z" (__sc0) \ + : "i" (__SH_SYSCALL_TRAP_BASE + 6), + "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ + "r" (__sc3), "r" (__sc1) \ + : "memory" ); +__syscall_return(long,__sc0); +} diff --git a/libc/sysdeps/linux/sh/syscall_error.S b/libc/sysdeps/linux/sh/syscall_error.S new file mode 100644 index 0000000..1764ebf --- /dev/null +++ b/libc/sysdeps/linux/sh/syscall_error.S @@ -0,0 +1,37 @@ + .align 4 +__syscall_error: + /* Call errno_location, store '-r4' in errno and return -1 */ + mov.l r12, @-r15 + sts.l pr, @-r15 +#ifdef __HAVE_SHARED__ + mova .LG, r0 + mov.l .LG, r12 + add r0, r12 + mov.l 1f, r0 + mov.l @(r0,r12),r0 + jsr @r0 + neg r4, r12 +#else + mov.l 1f, r0 + bsrf r0 + neg r4, r12 +.jmp_loc: +#endif + mov.l r12, @r0 + lds.l @r15+, pr + mov.l @r15+,r12 + + /* And just kick back a -1. */ + rts + mov #-1, r0 + + .align 4 + +#ifdef __HAVE_SHARED__ +1: .long __errno_location@GOT +.LG: .long _GLOBAL_OFFSET_TABLE_ +#else +1: .long __errno_location - .jmp_loc +#endif + + diff --git a/libc/sysdeps/linux/sh/vfork.S b/libc/sysdeps/linux/sh/vfork.S new file mode 100644 index 0000000..060a36b --- /dev/null +++ b/libc/sysdeps/linux/sh/vfork.S @@ -0,0 +1,114 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Derived in part from the Linux-8086 C library, the GNU C Library, and several + other sundry sources. Files within this library are copyright by their + respective copyright holders. +*/ + +#include +#include +#define _ERRNO_H +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.text +.globl __vfork +.hidden __vfork +.type __vfork,@function +.align 4 + +__vfork: + mov.w .L2, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 +#ifdef __CONFIG_SH2__ +/* 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! */ + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 +#else + mov #-12, r2 + shad r2, r1 +#endif + + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bf 2f + mov.w .L1, r1 + cmp/eq r1, r0 + bf/s __syscall_error + mov r0, r4 + + /* If we don't have vfork, use fork. */ + mov.w .L3, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 +#ifdef __CONFIG_SH2__ +/* 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! */ + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 +#else + mov #-12, r2 + shad r2, r1 +#endif + + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bt/s __syscall_error + mov r0, r4 +2: + rts + nop + + .align 2 +.L1: + .word -ENOSYS +.L2: + .word __NR_vfork +.L3: + .word __NR_fork + +.size __vfork, .-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) + +#include "syscall_error.S" diff --git a/libc/sysdeps/linux/sh64/Makefile b/libc/sysdeps/linux/sh64/Makefile new file mode 100644 index 0000000..ecbf142 --- /dev/null +++ b/libc/sysdeps/linux/sh64/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2001 SuperH (UK) Ltd. +# Copyright (C) 2003 Paul Mundt +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak diff --git a/libc/sysdeps/linux/sh64/Makefile.arch b/libc/sysdeps/linux/sh64/Makefile.arch new file mode 100644 index 0000000..d49540e --- /dev/null +++ b/libc/sysdeps/linux/sh64/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2008 Paul Mundt +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __init_brk.c brk.c sbrk.c syscall.c + +SSRC := setjmp.S __longjmp.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/sh64/__init_brk.c b/libc/sysdeps/linux/sh64/__init_brk.c new file mode 100644 index 0000000..8a41eb3 --- /dev/null +++ b/libc/sysdeps/linux/sh64/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/libc/sysdeps/linux/sh64/__longjmp.S b/libc/sysdeps/linux/sh64/__longjmp.S new file mode 100644 index 0000000..ca7925f --- /dev/null +++ b/libc/sysdeps/linux/sh64/__longjmp.S @@ -0,0 +1,141 @@ +/* __longjmp for SH-5. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define _SETJMP_H +#define _ASM +#include + + +#define INTEGER(reg,offset) ld.q r2, offset*8, reg +#define DOUBLE(reg,offset) fld.d r2, offset*8, reg + + + .file "__longjmp.S" + + .section .text64,"xa" + .align 2 + + .global __longjmp + .type __longjmp,@function + +__longjmp: + /* + * extern void __longjmp(jmp_buf env, int val); + * + * r2 == env + * r3 == val + * r4 == temporary + */ + + /* callee-save registers R10-R16 */ + INTEGER(r10, __SETJMP_INT(0)) + INTEGER(r11, __SETJMP_INT(1)) + INTEGER(r12, __SETJMP_INT(2)) + INTEGER(r13, __SETJMP_INT(3)) + INTEGER(r14, __SETJMP_INT(4)) + INTEGER(r15, __SETJMP_INT(5)) + INTEGER(r16, __SETJMP_INT(6)) + + /* callee-save registers R28-R35 */ + INTEGER(r28, __SETJMP_INT(7)) + INTEGER(r29, __SETJMP_INT(8)) + INTEGER(r30, __SETJMP_INT(9)) + INTEGER(r31, __SETJMP_INT(10)) + INTEGER(r32, __SETJMP_INT(11)) + INTEGER(r33, __SETJMP_INT(12)) + INTEGER(r34, __SETJMP_INT(13)) + INTEGER(r35, __SETJMP_INT(14)) + + /* callee-save registers R44-R59 */ + INTEGER(r44, __SETJMP_INT(15)) + INTEGER(r45, __SETJMP_INT(16)) + INTEGER(r46, __SETJMP_INT(17)) + INTEGER(r47, __SETJMP_INT(18)) + INTEGER(r48, __SETJMP_INT(19)) + INTEGER(r49, __SETJMP_INT(20)) + INTEGER(r50, __SETJMP_INT(21)) + INTEGER(r51, __SETJMP_INT(22)) + INTEGER(r52, __SETJMP_INT(23)) + INTEGER(r53, __SETJMP_INT(24)) + INTEGER(r54, __SETJMP_INT(25)) + INTEGER(r55, __SETJMP_INT(26)) + INTEGER(r56, __SETJMP_INT(27)) + INTEGER(r57, __SETJMP_INT(28)) + INTEGER(r58, __SETJMP_INT(29)) + INTEGER(r59, __SETJMP_INT(30)) + + #if __SETJMP_NUM_INT != 31 + #error __SETJMP_NUM_INT does agree with expected value + #endif + +#if __SETJMP_NUM_DBL > 0 + /* callee-save registers FR12-FR15 */ + DOUBLE(d12, __SETJMP_DBL(0)) + DOUBLE(d14, __SETJMP_DBL(1)) + + /* callee-save registers FR36-FR63 */ + DOUBLE(d36, __SETJMP_DBL(2)) + DOUBLE(d38, __SETJMP_DBL(3)) + DOUBLE(d40, __SETJMP_DBL(4)) + DOUBLE(d42, __SETJMP_DBL(5)) + DOUBLE(d44, __SETJMP_DBL(6)) + DOUBLE(d46, __SETJMP_DBL(7)) + DOUBLE(d48, __SETJMP_DBL(8)) + DOUBLE(d50, __SETJMP_DBL(9)) + DOUBLE(d52, __SETJMP_DBL(10)) + DOUBLE(d54, __SETJMP_DBL(11)) + DOUBLE(d56, __SETJMP_DBL(12)) + DOUBLE(d58, __SETJMP_DBL(13)) + DOUBLE(d60, __SETJMP_DBL(14)) + DOUBLE(d62, __SETJMP_DBL(15)) + + #if __SETJMP_NUM_DBL != 16 + #error __SETJMP_NUM_DBL does agree with expected value + #endif + +#endif /* __SETJMP_NUM_DBL > 0 */ + + /* callee-save registers TR5-TR7 */ + INTEGER(r4, __SETJMP_TRG(0)) + ptabs r4, tr5 + INTEGER(r4, __SETJMP_TRG(1)) + ptabs r4, tr6 + INTEGER(r4, __SETJMP_TRG(2)) + ptabs r4, tr7 + + #if __SETJMP_NUM_TRG != 3 + #error __SETJMP_NUM_TRG does agree with expected value + #endif + + /* restore Linkage Register (LR) for __longjmp return */ + INTEGER(r18, __SETJMP_LR) + ptabs/l r18, tr0 + + /* + * must ensure __longjmp() never returns 0. + * if 'val' == 0, then return 1. + */ + cmpeq r3, r63, r2 /* r2 = (r3==0) ? 1 : 0; */ + add.l r3, r2, r2 /* return value */ + + /* return to caller */ + blink tr0, r63 + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/sh64/bits/endian.h b/libc/sysdeps/linux/sh64/bits/endian.h new file mode 100644 index 0000000..ae7e3bb --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/endian.h @@ -0,0 +1,20 @@ +/* + * libc/sysdeps/linux/sh64/bits/endian.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# define __BYTE_ORDER __BIG_ENDIAN +#endif + diff --git a/libc/sysdeps/linux/sh64/bits/fcntl.h b/libc/sysdeps/linux/sh64/bits/fcntl.h new file mode 100644 index 0000000..49da627 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/fcntl.h @@ -0,0 +1,216 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/sh64/bits/kernel_stat.h b/libc/sysdeps/linux/sh64/bits/kernel_stat.h new file mode 100644 index 0000000..cde7bc8 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/kernel_stat.h @@ -0,0 +1,67 @@ +/* Stat structure for Linux/sh64 */ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long __pad5; + + unsigned long st_mtime; + unsigned long __pad6; + + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/sh64/bits/kernel_types.h b/libc/sysdeps/linux/sh64/bits/kernel_types.h new file mode 100644 index 0000000..671cc83 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/kernel_types.h @@ -0,0 +1,56 @@ +/* + * sysdeps/linux/sh64/bits/kernel_types.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +/* + * Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_SH64_POSIX_TYPES_H +#define __ASM_SH64_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef long unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_SH64_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/sh64/bits/mman.h b/libc/sysdeps/linux/sh64/bits/mman.h new file mode 100644 index 0000000..afa889d --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/mman.h @@ -0,0 +1,97 @@ +/* Cloned for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ + +/* Definitions for POSIX memory map interface. Linux/SH version. + Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/sh64/bits/setjmp.h b/libc/sysdeps/linux/sh64/bits/setjmp.h new file mode 100644 index 0000000..ad1ec9d --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/setjmp.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. SH-5 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#define __SETJMP_NUM_INT 31 /* number of integer registers to save */ +#define __SETJMP_NUM_DBL 0 /* 16 */ /* number of double registers to save */ +#define __SETJMP_NUM_TRG 3 /* number of traget registers to save */ + +#define __SETJMP_INT(x) (x) +#define __SETJMP_DBL(x) (__SETJMP_NUM_INT+(x)) +#define __SETJMP_TRG(x) (__SETJMP_NUM_INT+__SETJMP_NUM_DBL+(x)) +#define __SETJMP_LR (__SETJMP_NUM_INT+__SETJMP_NUM_DBL+__SETJMP_NUM_TRG) + + +#ifndef _ASM +typedef struct + { + /* Callee-saved registers. */ + unsigned long long __ints[__SETJMP_NUM_INT]; /* integer registers */ +#if __SETJMP_NUM_DBL > 0 + unsigned long long __dbls[__SETJMP_NUM_DBL]; /* double registers */ +#endif + unsigned long long __trgs[__SETJMP_NUM_TRG]; /* traget registers */ + unsigned long long __lr; /* linkage register */ + } __jmp_buf[1]; +#endif + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/sh64/bits/shm.h b/libc/sysdeps/linux/sh64/bits/shm.h new file mode 100644 index 0000000..3a2e715 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize() << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/sh64/bits/stackinfo.h b/libc/sysdeps/linux/sh64/bits/stackinfo.h new file mode 100644 index 0000000..e65338f --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On SH the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/sh64/bits/syscalls.h b/libc/sysdeps/linux/sh64/bits/syscalls.h new file mode 100644 index 0000000..84877d0 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/syscalls.h @@ -0,0 +1,126 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -125: see */ +#define __syscall_return(type, res) \ +do { \ + /* Note: when returning from kernel the return value is in r9 \ + ** This prevents conflicts between return value and arg1 \ + ** when dispatching signal handler, in other words makes \ + ** life easier in the system call epilogue (see entry.S) \ + */ \ + register unsigned long __sr2 __asm__ ("r2") = res; \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + errno = -(res); \ + __sr2 = -1; \ + } \ + return (type) (__sr2); \ +} while (0) + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x10 << 16) | __NR_##name); \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x11 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x12 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x14 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\ +__syscall_return(type,__sc0); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x15 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x16 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ +register unsigned long __sc7 __asm__ ("r7") = (unsigned long) arg6; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6), "r" (__sc7)); \ +__syscall_return(type,__sc0); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h b/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h new file mode 100644 index 0000000..1e8aa59 --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "movi 0x10, r9; shori 0xff, r9; trapa r9" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/sh64/bits/wordsize.h b/libc/sysdeps/linux/sh64/bits/wordsize.h new file mode 100644 index 0000000..7c2723b --- /dev/null +++ b/libc/sysdeps/linux/sh64/bits/wordsize.h @@ -0,0 +1,12 @@ +/* + * libc/sysdeps/linux/sh64/bits/wordsize.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#define __WORDSIZE 32 + diff --git a/libc/sysdeps/linux/sh64/brk.c b/libc/sysdeps/linux/sh64/brk.c new file mode 100644 index 0000000..c69c97a --- /dev/null +++ b/libc/sysdeps/linux/sh64/brk.c @@ -0,0 +1,28 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(brk) +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/sh64/crt1.S b/libc/sysdeps/linux/sh64/crt1.S new file mode 100644 index 0000000..1822e2d --- /dev/null +++ b/libc/sysdeps/linux/sh64/crt1.S @@ -0,0 +1,83 @@ +/* Startup code for SH5 & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. + + At this entry point, most registers' values are unspecified, except: + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ + + .file "crt1.S" + + .globl _start + .type _start,%function + .type main,%function + + .section .text64,"xa" + .align 2 /* 2^2 = 4 */ + +_start: + /* __uClibc_main (main, argc, argv, init, fini) */ + movi __main, r18 + or r2, r63, r18 + + /* Pop argc off the stack and save a pointer to argv */ + ld.l r15, 0, r3 /* argc */ + addi r15, 4, r4 /* argv */ + + movi _init, r5 + movi _fini, r6 + + /* call main() */ + movi __uClibc_main, r17 + ptabs/l r17, tr0 + blink tr0, r18 + + /* should never get here....*/ + movi abort, r17 + ptabs/l r17, tr0 + blink tr0, r63 /* call abort() => (r63) do not come back ... */ + +/* + * The following is a stub to stop the GNU toolchain + * from calling its C-RTL initialization routines. + */ +__main: + movi main, r18 + ptabs/l r18, tr0 + blink tr0, r63 + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/sh64/crti.S b/libc/sysdeps/linux/sh64/crti.S new file mode 100644 index 0000000..597be36 --- /dev/null +++ b/libc/sysdeps/linux/sh64/crti.S @@ -0,0 +1,42 @@ + .file "initfini.c" + .section .text..SHmedia32,"ax" + .little + + .section .init + .hidden _init + .align 2 + .global _init + .type _init, @function +_init: + addi.l r15, -16, r15 + st.l r15, 4, r12 + movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 + shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 + .LPCS0: ptrel/u r12, tr0 + st.l r15, 8, r14 + st.l r15, 12, r18 + add.l r15, r63, r14 + gettr tr0, r12 + + .align 2 + + + .section .fini + .hidden _fini + .align 2 + .global _fini + .type _fini, @function +_fini: + addi.l r15, -16, r15 + st.l r15, 4, r12 + movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS1-.)) >> 16) & 65535), r12 + shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS1-.)) & 65535), r12 + .LPCS1: ptrel/u r12, tr0 + st.l r15, 8, r14 + st.l r15, 12, r18 + add.l r15, r63, r14 + gettr tr0, r12 + .align 2 + + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/sh64/crtn.S b/libc/sysdeps/linux/sh64/crtn.S new file mode 100644 index 0000000..eb6479a --- /dev/null +++ b/libc/sysdeps/linux/sh64/crtn.S @@ -0,0 +1,33 @@ + .file "initfini.c" + .section .text..SHmedia32,"ax" + .little + + .section .init + .hidden _init + .align 2 + .global _init + .type _init, @function + add.l r14, r63, r15 + ld.l r15, 12, r18 + ld.l r15, 4, r12 + ld.l r15, 8, r14 + ptabs r18, tr0 + addi.l r15, 16, r15 + blink tr0, r63 + .size _init, .-_init + + .section .fini + .hidden _fini + .align 2 + .global _fini + .type _fini, @function + add.l r14, r63, r15 + ld.l r15, 12, r18 + ld.l r15, 4, r12 + ld.l r15, 8, r14 + ptabs r18, tr0 + addi.l r15, 16, r15 + blink tr0, r63 + .size _fini, .-_fini + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/sh64/sbrk.c b/libc/sysdeps/linux/sh64/sbrk.c new file mode 100644 index 0000000..a1ff2a1 --- /dev/null +++ b/libc/sysdeps/linux/sh64/sbrk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +libc_hidden_proto(sbrk) +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/libc/sysdeps/linux/sh64/setjmp.S b/libc/sysdeps/linux/sh64/setjmp.S new file mode 100644 index 0000000..11d76d3 --- /dev/null +++ b/libc/sysdeps/linux/sh64/setjmp.S @@ -0,0 +1,140 @@ +/* setjmp for SH-5. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define _SETJMP_H +#define _ASM +#include + + +#define INTEGER(reg,offset) st.q r2, offset*8, reg +#define DOUBLE(reg,offset) fst.d r2, offset*8, reg + + + .file "setjmp.S" + + .section .text64,"xa" + .align 2 + + .global __sigsetjmp + .type __sigsetjmp,@function + +__sigsetjmp: + /* + * extern int __sigsetjmp(jmp_buf env, int savemask); + * + * r2 == env + * r3 == savemask + * r4 == temporary + */ + + /* callee-save registers R10-R16 */ + INTEGER(r10, __SETJMP_INT(0)) + INTEGER(r11, __SETJMP_INT(1)) + INTEGER(r12, __SETJMP_INT(2)) + INTEGER(r13, __SETJMP_INT(3)) + INTEGER(r14, __SETJMP_INT(4)) + INTEGER(r15, __SETJMP_INT(5)) + INTEGER(r16, __SETJMP_INT(6)) + + /* callee-save registers R28-R35 */ + INTEGER(r28, __SETJMP_INT(7)) + INTEGER(r29, __SETJMP_INT(8)) + INTEGER(r30, __SETJMP_INT(9)) + INTEGER(r31, __SETJMP_INT(10)) + INTEGER(r32, __SETJMP_INT(11)) + INTEGER(r33, __SETJMP_INT(12)) + INTEGER(r34, __SETJMP_INT(13)) + INTEGER(r35, __SETJMP_INT(14)) + + /* callee-save registers R44-R59 */ + INTEGER(r44, __SETJMP_INT(15)) + INTEGER(r45, __SETJMP_INT(16)) + INTEGER(r46, __SETJMP_INT(17)) + INTEGER(r47, __SETJMP_INT(18)) + INTEGER(r48, __SETJMP_INT(19)) + INTEGER(r49, __SETJMP_INT(20)) + INTEGER(r50, __SETJMP_INT(21)) + INTEGER(r51, __SETJMP_INT(22)) + INTEGER(r52, __SETJMP_INT(23)) + INTEGER(r53, __SETJMP_INT(24)) + INTEGER(r54, __SETJMP_INT(25)) + INTEGER(r55, __SETJMP_INT(26)) + INTEGER(r56, __SETJMP_INT(27)) + INTEGER(r57, __SETJMP_INT(28)) + INTEGER(r58, __SETJMP_INT(29)) + INTEGER(r59, __SETJMP_INT(30)) + + #if __SETJMP_NUM_INT != 31 + #error __SETJMP_NUM_INT does agree with expected value + #endif + +#if __SETJMP_NUM_DBL > 0 + /* callee-save registers FR12-FR15 */ + DOUBLE(d12, __SETJMP_DBL(0)) + DOUBLE(d14, __SETJMP_DBL(1)) + + /* callee-save registers FR36-FR63 */ + DOUBLE(d36, __SETJMP_DBL(2)) + DOUBLE(d38, __SETJMP_DBL(3)) + DOUBLE(d40, __SETJMP_DBL(4)) + DOUBLE(d42, __SETJMP_DBL(5)) + DOUBLE(d44, __SETJMP_DBL(6)) + DOUBLE(d46, __SETJMP_DBL(7)) + DOUBLE(d48, __SETJMP_DBL(8)) + DOUBLE(d50, __SETJMP_DBL(9)) + DOUBLE(d52, __SETJMP_DBL(10)) + DOUBLE(d54, __SETJMP_DBL(11)) + DOUBLE(d56, __SETJMP_DBL(12)) + DOUBLE(d58, __SETJMP_DBL(13)) + DOUBLE(d60, __SETJMP_DBL(14)) + DOUBLE(d62, __SETJMP_DBL(15)) + + #if __SETJMP_NUM_DBL != 16 + #error __SETJMP_NUM_DBL does agree with expected value + #endif + +#endif /* __SETJMP_NUM_DBL > 0 */ + + /* callee-save registers TR5-TR7 */ + gettr tr5, r4 + INTEGER(r4, __SETJMP_TRG(0)) + gettr tr6, r4 + INTEGER(r4, __SETJMP_TRG(1)) + gettr tr7, r4 + INTEGER(r4, __SETJMP_TRG(2)) + + #if __SETJMP_NUM_TRG != 3 + #error __SETJMP_NUM_TRG does agree with expected value + #endif + + /* save Linkage Register (LR) for longjmp return */ + INTEGER(r18, __SETJMP_LR) + + /* + * return a value of zero if call is __sigsetjmp(). + * This is so that caller of setjmp() knows + * we have retruned via setjmp, and not via longjmp. + * R0 is the result register. + */ + + ptabs/l r18, tr0 /* return to caller */ + movi 0, r2 /* return value */ + blink tr0, r63 + diff --git a/libc/sysdeps/linux/sh64/sys/procfs.h b/libc/sysdeps/linux/sh64/sys/procfs.h new file mode 100644 index 0000000..aad21e5 --- /dev/null +++ b/libc/sysdeps/linux/sh64/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * ELF register definitions... + */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fpu_struct elf_fpregset_t; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/sh64/sys/ucontext.h b/libc/sysdeps/linux/sh64/sys/ucontext.h new file mode 100644 index 0000000..7440784 --- /dev/null +++ b/libc/sysdeps/linux/sh64/sys/ucontext.h @@ -0,0 +1,205 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Where is System V/SH ABI? */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef long long greg_t; + +/* Number of general registers. */ +#define NGREG 64 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 + R16 = 16, +#define R16 R16 + R17 = 17, +#define R17 R17 + R18 = 18, +#define R18 R18 + R19 = 19, +#define R19 R19 + R20 = 20, +#define R20 R20 + R21 = 21, +#define R21 R21 + R22 = 22, +#define R22 R22 + R23 = 23, +#define R23 R23 + R24 = 24, +#define R24 R24 + R25 = 25, +#define R25 R25 + R26 = 26, +#define R26 R26 + R27 = 27, +#define R27 R27 + R28 = 28, +#define R28 R28 + R29 = 29, +#define R29 R29 + R30 = 30, +#define R30 R30 + R31 = 31, +#define R31 R31 + R32 = 32, +#define R32 R32 + R33 = 33, +#define R33 R33 + R34 = 34, +#define R34 R34 + R35 = 35, +#define R35 R35 + R36 = 36, +#define R36 R36 + R37 = 37, +#define R37 R37 + R38 = 38, +#define R38 R38 + R39 = 39, +#define R39 R39 + R40 = 40, +#define R40 R40 + R41 = 41, +#define R41 R41 + R42 = 42, +#define R42 R42 + R43 = 43, +#define R43 R43 + R44 = 44, +#define R44 R44 + R45 = 45, +#define R45 R45 + R46 = 46, +#define R46 R46 + R47 = 47, +#define R47 R47 + R48 = 48, +#define R48 R48 + R49 = 49, +#define R49 R49 + R50 = 50, +#define R50 R50 + R51 = 51, +#define R51 R51 + R52 = 52, +#define R52 R52 + R53 = 53, +#define R53 R53 + R54 = 54, +#define R54 R54 + R55 = 55, +#define R55 R55 + R56 = 56, +#define R56 R56 + R57 = 57, +#define R57 R57 + R58 = 58, +#define R58 R58 + R59 = 59, +#define R59 R59 + R60 = 60, +#define R60 R60 + R61 = 61, +#define R61 R61 + R62 = 62, +#define R62 R62 + R63 = 63, +#define R63 R63 +}; +#endif + +typedef int freg_t; + +/* Number of FPU registers. */ +#define NFPREG 32 + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + unsigned long long sc_tregs[8]; + unsigned long long sc_pc; + unsigned long long sc_sr; + unsigned long long sc_fpscr; + + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/sh64/syscall.c b/libc/sysdeps/linux/sh64/syscall.c new file mode 100644 index 0000000..a6c55eb --- /dev/null +++ b/libc/sysdeps/linux/sh64/syscall.c @@ -0,0 +1,24 @@ + + +#include +#include +#include +#include + +long syscall(long sysnum, + long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +register long __sc0 __asm__ ("r9") = ((0x16 << 16) | sysnum); +register long __sc2 __asm__ ("r2") = (long) arg1; +register long __sc3 __asm__ ("r3") = (long) arg2; +register long __sc4 __asm__ ("r4") = (long) arg3; +register long __sc5 __asm__ ("r5") = (long) arg4; +register long __sc6 __asm__ ("r6") = (long) arg5; +register long __sc7 __asm__ ("r7") = (long) arg6; +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6), "r" (__sc7)); +__syscall_return(long,__sc0); +} diff --git a/libc/sysdeps/linux/sparc/Makefile b/libc/sysdeps/linux/sparc/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/sparc/Makefile.arch b/libc/sysdeps/linux/sparc/Makefile.arch new file mode 100644 index 0000000..4562eab --- /dev/null +++ b/libc/sysdeps/linux/sparc/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c qp_ops.c + +SSRC := \ + __longjmp.S fork.S vfork.S clone.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + syscall.S urem.S udiv.S umul.S sdiv.S rem.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/sparc/__longjmp.S b/libc/sysdeps/linux/sparc/__longjmp.S new file mode 100644 index 0000000..c7d4f07 --- /dev/null +++ b/libc/sysdeps/linux/sparc/__longjmp.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1991, 93, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define _ASM 1 +#define _SETJMP_H +#include +#define ENV(base,reg) [%base + (reg * 4)] +#define ST_FLUSH_WINDOWS 3 +#define RW_FP [%fp + 0x48] + +.global __longjmp +.type __longjmp,%function +.align 4 +__longjmp: + .register %g2, #scratch + .register %g3, #scratch + /* Store our arguments in global registers so we can still + * use them while unwinding frames and their register windows. */ + + ld ENV(o0,JB_FP), %g3 /* Cache target FP in register %g3. */ + mov %o0, %g1 /* ENV in %g1 */ + orcc %o1, %g0, %g2 /* VAL in %g2 */ + be,a 0f /* Branch if zero; else skip delay slot. */ + mov 1, %g2 /* Delay slot only hit if zero: VAL = 1. */ +0: + xor %fp, %g3, %o0 + add %fp, 512, %o1 + andncc %o0, 4095, %o0 + bne .Lthread + cmp %o1, %g3 + bl .Lthread + + /* Now we will loop, unwinding the register windows up the stack + * until the restored %fp value matches the target value in %g3. */ + +.Lloop: + cmp %fp, %g3 /* Have we reached the target frame? */ + bl,a .Lloop /* Loop while current fp is below target. */ + restore /* Unwind register window in delay slot. */ + be,a .Lfound /* Better have hit it exactly. */ + ld ENV(g1,JB_SP), %o0 /* Delay slot: extract target SP. */ + +.Lthread: + /* + * Do a "flush register windows trap". The trap handler in the + * kernel writes all the register windows to their stack slots, and + * marks them all as invalid (needing to be sucked up from the + * stack when used). This ensures that all information needed to + * unwind to these callers is in memory, not in the register + * windows. + */ + ta ST_FLUSH_WINDOWS + ld ENV(g1,JB_PC), %o7 /* Set return PC. */ + ld ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */ + sub %fp, 64, %sp /* Allocate a register frame. */ + st %g3, RW_FP /* Set saved FP on restore below. */ + retl + restore %g2, 0, %o0 /* Restore values from above register frame. */ + +.Lfound: + /* We have unwound register windows so %fp matches the target. */ + mov %o0, %sp /* OK, install new SP. */ + +.Lsp_ok: + ld ENV(g1,JB_PC), %o0 /* Extract target return PC. */ + jmp %o0 + 8 /* Return there. */ + mov %g2, %o0 /* Delay slot: set return value. */ + +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/sparc/__syscall_error.c b/libc/sysdeps/linux/sparc/__syscall_error.c new file mode 100644 index 0000000..5e109a8 --- /dev/null +++ b/libc/sysdeps/linux/sparc/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/sparc/_math_inc.h b/libc/sysdeps/linux/sparc/_math_inc.h new file mode 100644 index 0000000..1bf84f0 --- /dev/null +++ b/libc/sysdeps/linux/sparc/_math_inc.h @@ -0,0 +1,32 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +#define __ASSEMBLY__ +#ifndef __sparc_v9__ +#include +#endif + +/* Is alignment really needed? */ + +#if __WORDSIZE == 32 +# define ENTRY_ALIGN 4 +#else +# define ENTRY_ALIGN 2 +#endif + +#define ENTRY(sym) \ + .global sym; \ + .align ENTRY_ALIGN; \ + .type sym,%function; \ + sym: + +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/libc/sysdeps/linux/sparc/bits/endian.h b/libc/sysdeps/linux/sparc/bits/endian.h new file mode 100644 index 0000000..8acfdf5 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/endian.h @@ -0,0 +1,12 @@ +/* Sparc is big-endian, but v9 supports endian conversion on loads/stores + and GCC supports such a mode. Be prepared. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# define __BYTE_ORDER __BIG_ENDIAN +#endif diff --git a/libc/sysdeps/linux/sparc/bits/fcntl.h b/libc/sysdeps/linux/sparc/bits/fcntl.h new file mode 100644 index 0000000..5739459 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/fcntl.h @@ -0,0 +1,260 @@ +/* O_*, F_*, FD_* bit values for Linux/SPARC. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_ACCMODE 0x0003 +#define O_APPEND 0x0008 +#define O_ASYNC 0x0040 +#define O_CREAT 0x0200 /* not fcntl */ +#define O_TRUNC 0x0400 /* not fcntl */ +#define O_EXCL 0x0800 /* not fcntl */ +#define O_SYNC 0x2000 +#define O_NONBLOCK 0x4000 +#define O_NDELAY (0x0004 | O_NONBLOCK) +#define O_NOCTTY 0x8000 /* not fcntl */ + +#ifdef __USE_GNU +# define O_DIRECTORY 0x10000 /* must be a directory */ +# define O_NOFOLLOW 0x20000 /* don't follow links */ +# define O_DIRECT 0x100000 /* direct disk access hint */ +# define O_NOATIME 0x200000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 0x400000 /* Set close_on_exit. */ +# endif +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0x40000 +# endif +#endif + +/* For now Linux has no synchronisity options for data and read + operations. We define the symbols here but let them do the same as + O_SYNC since this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_GETOWN 5 /* Get owner of socket (receiver of SIGIO). */ +# define F_SETOWN 6 /* Set owner of socket (receiver of SIGIO). */ +#endif +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 7 /* Get record locking info. */ +# define F_SETLK 8 /* Set record locking info (non-blocking). */ +# define F_SETLKW 9 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +#if __WORDSIZE == 64 +# define F_GETLK64 7 /* Get record locking info. */ +# define F_SETLK64 8 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 9 /* Set record locking info (blocking). */ +#else +# define F_GETLK64 12 /* Get record locking info. */ +# define F_SETLK64 13 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 14 /* Set record locking info (blocking). */ +#endif + +/* for F_[GET|SET]FD */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 3 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + short int __unused; + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + short int __unused; + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/sparc/bits/fenv.h b/libc/sysdeps/linux/sparc/bits/fenv.h new file mode 100644 index 0000000..d2ef97e --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/fenv.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + + +/* Define bits representing the exception. We use the bit positions + of the appropriate accrued exception bits from the FSR. */ +enum + { + FE_INVALID = (1 << 9), +#define FE_INVALID FE_INVALID + FE_OVERFLOW = (1 << 8), +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = (1 << 7), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_DIVBYZERO = (1 << 6), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INEXACT = (1 << 5) +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The Sparc FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = (0U << 30), +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = (1U << 30), +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = (2U << 30), +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = (3U << 30) +#define FE_DOWNWARD FE_DOWNWARD + }; + +#define __FE_ROUND_MASK (3U << 30) + + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif + +/* For internal use only: access the fp state register. */ +#if __WORDSIZE == 64 +# define __fenv_stfsr(X) __asm__ ("stx %%fsr,%0" : "=m" (X)) +# define __fenv_ldfsr(X) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (X)) +#else +# define __fenv_stfsr(X) __asm__ ("st %%fsr,%0" : "=m" (X)) +# define __fenv_ldfsr(X) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (X)) +#endif diff --git a/libc/sysdeps/linux/sparc/bits/ioctls.h b/libc/sysdeps/linux/sparc/bits/ioctls.h new file mode 100644 index 0000000..e86c503 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/ioctls.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('T', 8, char[36]) +#define TCSETS _IOW ('T', 9, char[36]) +#define TCSETSW _IOW ('T', 10, char[36]) +#define TCSETSF _IOW ('T', 11, char[36]) + +#include diff --git a/libc/sysdeps/linux/sparc/bits/ipc.h b/libc/sysdeps/linux/sparc/bits/ipc.h new file mode 100644 index 0000000..988dc12 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/ipc.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad2; +#else + __mode_t mode; /* Read/write permission. */ + unsigned short int __pad1; +#endif + unsigned short int __seq; /* Sequence number. */ + unsigned long long int __unused1; + unsigned long long int __unused2; + }; diff --git a/libc/sysdeps/linux/sparc/bits/kernel_stat.h b/libc/sysdeps/linux/sparc/bits/kernel_stat.h new file mode 100644 index 0000000..ab85be2 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/kernel_stat.h @@ -0,0 +1,60 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +#if __WORDSIZE == 64 +#define kernel_stat kernel_stat64 +#else +struct kernel_stat { + unsigned short st_dev; + unsigned long st_ino; + unsigned short st_mode; + short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + long st_size; + long st_atime; + unsigned long __unused1; + long st_mtime; + unsigned long __unused2; + long st_ctime; + unsigned long __unused3; + long st_blksize; + long st_blocks; + unsigned long __unused4[2]; +}; + +#endif + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned long long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long long st_rdev; + unsigned char __pad3[8]; + long long st_size; + unsigned int st_blksize; + unsigned char __pad4[8]; + unsigned int st_blocks; + unsigned int st_atime; + unsigned int st_atime_nsec; + unsigned int st_mtime; + unsigned int st_mtime_nsec; + unsigned int st_ctime; + unsigned int st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/sparc/bits/kernel_types.h b/libc/sysdeps/linux/sparc/bits/kernel_types.h new file mode 100644 index 0000000..1b24524 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/kernel_types.h @@ -0,0 +1,76 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#if ! defined __ARCH_SPARC_POSIX_TYPES_H && ! defined __ARCH_SPARC64_POSIX_TYPES_H +#define __ARCH_SPARC_POSIX_TYPES_H +#define __ARCH_SPARC64_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef unsigned int __kernel_nlink_t; +typedef int __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; +typedef int __kernel_suseconds_t; +typedef long long __kernel_loff_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef short __kernel_nlink_t; +typedef long __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* ! defined __ARCH_SPARC_POSIX_TYPES_H && ! defined __ARCH_SPARC64_POSIX_TYPES_H */ + diff --git a/libc/sysdeps/linux/sparc/bits/mathdef.h b/libc/sysdeps/linux/sparc/bits/mathdef.h new file mode 100644 index 0000000..b1a0d91 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/mathdef.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#include + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# ifdef __GNUC__ +# if __STDC__ == 1 + +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ +typedef float float_t; +typedef double double_t; + +# else + +/* For `gcc -traditional', `float' expressions are evaluated as `double'. */ +typedef double float_t; +typedef double double_t; + +# endif +# else + +/* Wild guess at types for float_t and double_t. */ +typedef double float_t; +typedef double double_t; + +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifdef __UCLIBC_HAS_LONG_DOUBLE_MATH__ + +# if __WORDSIZE == 32 +/* Signal that in 32bit ABI we do not really have a `long double'. + The disables the declaration of all the `long double' function + variants. */ +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# endif + +#endif diff --git a/libc/sysdeps/linux/sparc/bits/mathinline.h b/libc/sysdeps/linux/sparc/bits/mathinline.h new file mode 100644 index 0000000..66ca047 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/mathinline.h @@ -0,0 +1,292 @@ +/* Inline math functions for SPARC. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#include + +#ifdef __GNUC__ + +#if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0) +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered + +# if __WORDSIZE == 32 + +# ifdef __UCLIBC_HAS_LONG_DOUBLE_MATH__ + +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else \ + { \ + long double __x = (x); long double __y = (y); \ + extern int _Q_cmp (const long double a, const long double b); \ + __r = _Q_cmp (__x, __y) << 10; \ + } \ + __r; })) + +# else + +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + __r; })) + +# endif + +# define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10)) +# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0) +# define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10)) +# define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0) +# define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0) +# define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10)) + +# else /* sparc64 */ + +# define __unordered_v9cmp(x, y, op, qop) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ + : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ + } \ + else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ + : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ + } \ + else \ + { \ + long double __x = (x); long double __y = (y); \ + extern int _Qp_cmp (const long double *a, const long double *b); \ + __r = qop; \ + } \ + __r; })) + +# define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2) +# define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0) +# define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1) +# define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0) +# define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0) +# define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3) + +# endif /* sparc64 */ + +#endif /* __USE_ISOC99 */ + +#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__ + +# ifdef __cplusplus +# define __MATH_INLINE __inline +# else +# define __MATH_INLINE extern __inline +# endif /* __cplusplus */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) + +# ifdef __USE_ISOC99 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} + +# if __WORDSIZE == 32 + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[0] < 0; +} + +# ifdef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[4]; } __u = { __l: __x }; + return __u.__i[0] < 0; +} +# else +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + return __signbit ((double)__x); +} +# endif + +# else /* sparc64 */ + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; long int __i; } __u = { __d: __x }; + return __u.__i < 0; +} + +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x }; + return __u.__i[0] < 0; +} + +# endif /* sparc64 */ + +# endif /* __USE_ISOC99 */ + +# if !defined __NO_MATH_INLINES && !__GNUC_PREREQ (3, 2) + +__MATH_INLINE double +__NTH (sqrt (double __x)) +{ + register double __r; + __asm__ ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +__MATH_INLINE float +__NTH (sqrtf (float __x)) +{ + register float __r; + __asm__ ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +# if __WORDSIZE == 64 +__MATH_INLINE long double +__NTH (sqrtl (long double __x)) +{ + long double __r; + extern void _Qp_sqrt (long double *, __const__ long double *); + _Qp_sqrt (&__r, &__x); + return __r; +} +# elif defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +__MATH_INLINE long double +sqrtl (long double __x) __THROW +{ + extern long double _Q_sqrt (__const__ long double); + return _Q_sqrt (__x); +} +# endif /* sparc64 */ + +# endif /* !__NO_MATH_INLINES && !GCC 3.2+ */ + +/* This code is used internally in the GNU libc. */ +# ifdef __LIBC_INTERNAL_MATH_INLINES +__MATH_INLINE double +__ieee754_sqrt (double __x) +{ + register double __r; + __asm__ ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +__MATH_INLINE float +__ieee754_sqrtf (float __x) +{ + register float __r; + __asm__ ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +# if __WORDSIZE == 64 +__MATH_INLINE long double +__ieee754_sqrtl (long double __x) +{ + long double __r; + extern void _Qp_sqrt (long double *, __const__ long double *); + _Qp_sqrt(&__r, &__x); + return __r; +} +# elif defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +__MATH_INLINE long double +__ieee754_sqrtl (long double __x) +{ + extern long double _Q_sqrt (__const__ long double); + return _Q_sqrt (__x); +} +# endif /* sparc64 */ +# endif /* __LIBC_INTERNAL_MATH_INLINES */ +# endif /* gcc 2.8+ */ + +# ifdef __USE_ISOC99 + +# ifndef __NO_MATH_INLINES + +__MATH_INLINE double __NTH (fdim (double __x, double __y)); +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +__MATH_INLINE float __NTH (fdimf (float __x, float __y)); +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +# endif /* !__NO_MATH_INLINES */ +# endif /* __USE_ISOC99 */ +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ +#endif /* __GNUC__ */ diff --git a/libc/sysdeps/linux/sparc/bits/mman.h b/libc/sysdeps/linux/sparc/bits/mman.h new file mode 100644 index 0000000..be2b7eb --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/mman.h @@ -0,0 +1,106 @@ +/* Definitions for POSIX memory map interface. Linux/SPARC version. + Copyright (C) 1997,1999,2000,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0200 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +# define MAP_POPULATE 0x8000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_FREE 5 /* Content can be freed (Solaris). */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/sparc/bits/msq.h b/libc/sysdeps/linux/sparc/bits/msq.h new file mode 100644 index 0000000..1268dc8 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/msq.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned int __pad3; +#endif + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/sparc/bits/poll.h b/libc/sysdeps/linux/sparc/bits/poll.h new file mode 100644 index 0000000..53b94bc --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x200 +# define POLLREMOVE 0x400 +# define POLLRDHUP 0x800 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/sparc/bits/resource.h b/libc/sysdeps/linux/sparc/bits/resource.h new file mode 100644 index 0000000..3f2c600 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/resource.h @@ -0,0 +1,241 @@ +/* Bit values & structures for resource limits. Linux/SPARC version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 6, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 9, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 7, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 8, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#if __WORDSIZE == 64 + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +#else + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +#else +# define RLIM_INFINITY 0x7fffffffffffffffLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffLL +#endif + +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/libc/sysdeps/linux/sparc/bits/sem.h b/libc/sysdeps/linux/sparc/bits/sem.h new file mode 100644 index 0000000..2880765 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/sem.h @@ -0,0 +1,92 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t sem_otime; /* last semop() time */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/sparc/bits/setjmp.h b/libc/sysdeps/linux/sparc/bits/setjmp.h new file mode 100644 index 0000000..ac5a4b2 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/setjmp.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1997,1999,2000,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +#if 0 /*__WORDSIZE == 64*/ + +#ifndef _ASM +typedef struct __sparc64_jmp_buf + { + struct __sparc64_jmp_buf *uc_link; + unsigned long uc_flags; + unsigned long uc_sigmask; + struct __sparc64_jmp_buf_mcontext + { + unsigned long mc_gregs[19]; + unsigned long mc_fp; + unsigned long mc_i7; + struct __sparc64_jmp_buf_fpu + { + union + { + unsigned int sregs[32]; + unsigned long dregs[32]; + long double qregs[16]; + } mcfpu_fpregs; + unsigned long mcfpu_fprs; + unsigned long mcfpu_gsr; + void *mcfpu_fq; + unsigned char mcfpu_qcnt; + unsigned char mcfpu_qentsz; + unsigned char mcfpu_enab; + } mc_fpregs; + } uc_mcontext; + } __jmp_buf[1]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((unsigned long int) (address) < (jmpbuf)->uc_mcontext.mc_fp) + +#else + +#if defined __USE_MISC || defined _ASM +# define JB_SP 0 +# define JB_FP 1 +# define JB_PC 2 +#endif + +#ifndef _ASM +typedef int __jmp_buf[3]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((int) (address) < (jmpbuf)[JB_SP]) + +#endif + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/sparc/bits/shm.h b/libc/sysdeps/linux/sparc/bits/shm.h new file mode 100644 index 0000000..03decb1 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/shm.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned int __pad3; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ + size_t shm_segsz; /* size of segment in bytes */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/sparc/bits/sigaction.h b/libc/sysdeps/linux/sparc/bits/sigaction.h new file mode 100644 index 0000000..ee41967 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/sigaction.h @@ -0,0 +1,76 @@ +/* The proper definitions for Linux/SPARC sigaction. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction + { + /* Signal handler. */ +#ifdef __USE_POSIX199309 + union + { + /* Used if SA_SIGINFO is not set. */ + __sighandler_t sa_handler; + /* Used if SA_SIGINFO is set. */ + void (*sa_sigaction) (int, siginfo_t *, void *); + } + __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + + /* Additional set of signals to be blocked. */ + __sigset_t sa_mask; + + /* Special flags. */ + unsigned long sa_flags; + + /* Not used by Linux/Sparc yet. */ + void (*sa_restorer) (void); + }; + + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000008 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000100 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000200 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x00000002 /* Restart syscall on signal return. */ +# define SA_INTERRUPT 0x00000010 /* Historical no-op. */ +# define SA_NOMASK 0x00000020 /* Don't automatically block the signal when + its handler is being executed. */ +# define SA_ONESHOT 0x00000004 /* Reset to SIG_DFL on entry to handler. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NODEFER SA_NOMASK +# define SA_RESETHAND SA_ONESHOT +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 4 /* Set the set of blocked signals. */ diff --git a/libc/sysdeps/linux/sparc/bits/sigcontext.h b/libc/sysdeps/linux/sparc/bits/sigcontext.h new file mode 100644 index 0000000..42eca54 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/sigcontext.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 32 + +/* It is quite hard to choose what to put here, because + Linux/sparc32 had at least 3 totally incompatible + signal stack layouts. + This one is for the "new" style signals, which are + now delivered unless SA_SIGINFO is requested. */ + +struct sigcontext + { + struct + { + unsigned int psr; + unsigned int pc; + unsigned int npc; + unsigned int y; + unsigned int u_regs[16]; /* globals and ins */ + } si_regs; + int si_mask; + }; + +#else /* sparc64 */ + +typedef struct + { + unsigned int si_float_regs [64]; + unsigned long si_fsr; + unsigned long si_gsr; + unsigned long si_fprs; + } __siginfo_fpu_t; + +struct sigcontext + { + char sigc_info[128]; + struct + { + unsigned long u_regs[16]; /* globals and ins */ + unsigned long tstate; + unsigned long tpc; + unsigned long tnpc; + unsigned int y; + unsigned int fprs; + } sigc_regs; + __siginfo_fpu_t * sigc_fpu_save; + struct + { + void * ss_sp; + int ss_flags; + unsigned long ss_size; + } sigc_stack; + unsigned long sigc_mask; +}; + +#endif /* sparc64 */ diff --git a/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h b/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h new file mode 100644 index 0000000..2c2770d --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(__ctx) ((void *) ((__ctx)->si_regs.pc)) +#define ADVANCE_STACK_FRAME(__next) \ + ((void *) (((unsigned *)(__next))+14)) + +#define GET_STACK(__ctx) ((void *) (__ctx)->si_regs.u_regs[14]) +#define GET_FRAME(__ctx) ADVANCE_STACK_FRAME (GET_STACK(__ctx)) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/sparc/bits/siginfo.h b/libc/sysdeps/linux/sparc/bits/siginfo.h new file mode 100644 index 0000000..7ff1971 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/siginfo.h @@ -0,0 +1,318 @@ +/* siginfo_t, sigevent and constants. Linux/SPARC version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + int si_trapno; + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_trapno _sifields._sigfault.si_trapno +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +/* `si_code' values for SIGEMT signal. */ +enum +{ + EMT_TAGOVF = 1 /* Tag overflow. */ +# define EMT_TAGOVF EMT_TAGOVF +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# if __WORDSIZE == 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/libc/sysdeps/linux/sparc/bits/signum.h b/libc/sysdeps/linux/sparc/bits/signum.h new file mode 100644 index 0000000..6b58ec2 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/signum.h @@ -0,0 +1,84 @@ +/* Signal number definitions. Linux/SPARC version. + Copyright (C) 1996, 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif + +/* + * Linux/SPARC has different signal numbers that Linux/i386: I'm trying + * to make it OSF/1 binary compatible, at least for normal binaries. + */ +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 + +/* SunOS values which deviate from the Linux/i386 ones */ +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGPOLL SIGIO /* SysV name for SIGIO */ +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGLOST 29 +#define SIGPWR SIGLOST +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define _NSIG 65 /* Biggest signal number + 1 + (including real-time signals). */ + +#define SIGRTMIN (__libc_current_sigrtmin ()) +#define SIGRTMAX (__libc_current_sigrtmax ()) + +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#define __SIGRTMIN 32 +#define __SIGRTMAX (_NSIG - 1) + +#endif /* included. */ diff --git a/libc/sysdeps/linux/sparc/bits/sigstack.h b/libc/sysdeps/linux/sparc/bits/sigstack.h new file mode 100644 index 0000000..df46539 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/libc/sysdeps/linux/sparc/bits/stackinfo.h b/libc/sysdeps/linux/sparc/bits/stackinfo.h new file mode 100644 index 0000000..fd34e2d --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On sparc the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/sparc/bits/stat.h b/libc/sysdeps/linux/sparc/bits/stat.h new file mode 100644 index 0000000..8dcfacd --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/stat.h @@ -0,0 +1,165 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 + unsigned short int __pad1; +#endif + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/sparc/bits/statvfs.h b/libc/sysdeps/linux/sparc/bits/statvfs.h new file mode 100644 index 0000000..3dafceb --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/statvfs.h @@ -0,0 +1,106 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +#if __WORDSIZE == 32 +#define _STATVFSBUF_F_UNUSED +#endif + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync which the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/libc/sysdeps/linux/sparc/bits/syscalls.h b/libc/sysdeps/linux/sparc/bits/syscalls.h new file mode 100644 index 0000000..fdaa4de --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/syscalls.h @@ -0,0 +1,155 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef __SYSCALL_STRING +#if __WORDSIZE == 32 +# define __SYSCALL_STRING \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" +# define __SYSCALL_RES_CHECK (__res < -255 || __res >= 0) +#elif __WORDSIZE == 64 +# define __SYSCALL_STRING \ + "t 0x6d\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "movcc %%xcc, %%o0, %0\n\t" +# define __SYSCALL_RES_CHECK (__res >= 0) +#else +# error unknown __WORDSIZE +#endif + +#define __SYSCALL_RETURN(type) \ + if (__SYSCALL_RES_CHECK) \ + return (type) __res; \ + __set_errno (-__res); \ + return (type) -1; + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res)\ + : "r" (__g1) \ + : "o0", "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +register long __o2 __asm__ ("o2") = (long)(arg3); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +register long __o2 __asm__ ("o2") = (long)(arg3); \ +register long __o3 __asm__ ("o3") = (long)(arg4); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +register long __o2 __asm__ ("o2") = (long)(arg3); \ +register long __o3 __asm__ ("o3") = (long)(arg4); \ +register long __o4 __asm__ ("o4") = (long)(arg5); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \ +{ \ +long __res; \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register long __o0 __asm__ ("o0") = (long)(arg1); \ +register long __o1 __asm__ ("o1") = (long)(arg2); \ +register long __o2 __asm__ ("o2") = (long)(arg3); \ +register long __o3 __asm__ ("o3") = (long)(arg4); \ +register long __o4 __asm__ ("o4") = (long)(arg5); \ +register long __o5 __asm__ ("o5") = (long)(arg6); \ +__asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__o5), "r" (__g1) \ + : "cc"); \ +__SYSCALL_RETURN(type) \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/sparc/bits/termios.h b/libc/sysdeps/linux/sparc/bits/termios.h new file mode 100644 index 0000000..cea1322 --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/termios.h @@ -0,0 +1,233 @@ +/* termios type and macro definitions. Linux/SPARC version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 17 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VEOL 5 +#define VEOL2 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */ +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 + +/* User apps assume vmin/vtime is shared with eof/eol */ +#define VMIN VEOF +#define VTIME VEOL + +/* c_iflag bits */ +#define IGNBRK 0x00000001 +#define BRKINT 0x00000002 +#define IGNPAR 0x00000004 +#define PARMRK 0x00000008 +#define INPCK 0x00000010 +#define ISTRIP 0x00000020 +#define INLCR 0x00000040 +#define IGNCR 0x00000080 +#define ICRNL 0x00000100 +#define IUCLC 0x00000200 +#define IXON 0x00000400 +#define IXANY 0x00000800 +#define IXOFF 0x00001000 +#define IMAXBEL 0x00002000 +#define IUTF8 0x00004000 + +/* c_oflag bits */ +#define OPOST 0x00000001 +#define OLCUC 0x00000002 +#define ONLCR 0x00000004 +#define OCRNL 0x00000008 +#define ONOCR 0x00000010 +#define ONLRET 0x00000020 +#define OFILL 0x00000040 +#define OFDEL 0x00000080 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0x00000100 +# define NL0 0x00000000 +# define NL1 0x00000100 +# define CRDLY 0x00000600 +# define CR0 0x00000000 +# define CR1 0x00000200 +# define CR2 0x00000400 +# define CR3 0x00000600 +# define TABDLY 0x00001800 +# define TAB0 0x00000000 +# define TAB1 0x00000800 +# define TAB2 0x00001000 +# define TAB3 0x00001800 +# define BSDLY 0x00002000 +# define BS0 0x00000000 +# define BS1 0x00002000 +#define FFDLY 0x00008000 +#define FF0 0x00000000 +#define FF1 0x00008000 +#endif +#define VTDLY 0x00004000 +#define VT0 0x00000000 +#define VT1 0x00004000 +#define PAGEOUT 0x00010000 /* SUNOS specific */ +#define WRAP 0x00020000 /* SUNOS specific */ + +#ifdef __USE_MISC +# define XTABS 0x00001800 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0x0000100f +#endif +#define B0 0x00000000 /* hang up */ +#define B50 0x00000001 +#define B75 0x00000002 +#define B110 0x00000003 +#define B134 0x00000004 +#define B150 0x00000005 +#define B200 0x00000006 +#define B300 0x00000007 +#define B600 0x00000008 +#define B1200 0x00000009 +#define B1800 0x0000000a +#define B2400 0x0000000b +#define B4800 0x0000000c +#define B9600 0x0000000d +#define B19200 0x0000000e +#define B38400 0x0000000f +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0x00000030 +#define CS5 0x00000000 +#define CS6 0x00000010 +#define CS7 0x00000020 +#define CS8 0x00000030 +#define CSTOPB 0x00000040 +#define CREAD 0x00000080 +#define PARENB 0x00000100 +#define PARODD 0x00000200 +#define HUPCL 0x00000400 +#define CLOCAL 0x00000800 +#ifdef __USE_MISC +# define CBAUDEX 0x00001000 +#endif +#define B57600 0x00001001 +#define B115200 0x00001002 +#define B230400 0x00001003 +#define B460800 0x00001004 +#define B76800 0x00001005 +#define B153600 0x00001006 +#define B307200 0x00001007 +#define B614400 0x00001008 +#define B921600 0x00001009 +#define B500000 0x0000100a +#define B576000 0x0000100b +#define B1000000 0x0000100c +#define B1152000 0x0000100d +#define B1500000 0x0000100e +#define B2000000 0x0000100f +#define __MAX_BAUD B2000000 + +#ifdef __USE_MISC +# define CIBAUD 0x100f0000 /* input baud rate (not used) */ +# define CMSPAR 0x40000000 /* mark or space (stick) parity */ +# define CRTSCTS 0x80000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000001 +#define ICANON 0x00000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00000004 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000010 +#define ECHOK 0x00000020 +#define ECHONL 0x00000040 +#define NOFLSH 0x00000080 +#define TOSTOP 0x00000100 +#ifdef __USE_MISC +# define ECHOCTL 0x00000200 +# define ECHOPRT 0x00000400 +# define ECHOKE 0x00000800 +# define DEFECHO 0x00001000 /* SUNOS thing, what is it? */ +# define FLUSHO 0x00002000 +# define PENDIN 0x00004000 +#endif +#define IEXTEN 0x00008000 + +/* modem lines */ +#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 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 diff --git a/libc/sysdeps/linux/sparc/bits/typesizes.h b/libc/sysdeps/linux/sparc/bits/typesizes.h new file mode 100644 index 0000000..b0dd1bd --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/SPARC version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S32_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h b/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h new file mode 100644 index 0000000..41d3e7c --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "unimp 0xf00" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/sparc/bits/wordsize.h b/libc/sysdeps/linux/sparc/bits/wordsize.h new file mode 100644 index 0000000..c8e5bfd --- /dev/null +++ b/libc/sysdeps/linux/sparc/bits/wordsize.h @@ -0,0 +1,20 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __arch64__ || defined __sparcv9 +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#endif + +#if 0 /* uClibc: done in mathdefs.h: defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ && !defined __LONG_DOUBLE_MATH_OPTIONAL*/ + +# if __WORDSIZE == 32 +/* Signal that in 32bit ABI we didn't used to have a `long double'. + The changes all the `long double' function variants to be redirects + to the double functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# endif +# endif +#endif diff --git a/libc/sysdeps/linux/sparc/brk.c b/libc/sysdeps/linux/sparc/brk.c new file mode 100644 index 0000000..53f2c9c --- /dev/null +++ b/libc/sysdeps/linux/sparc/brk.c @@ -0,0 +1,50 @@ +/* brk system call for Linux/i386. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *newbrk; + + { + register void *o0 __asm__("%o0") = addr; + register int g1 __asm__("%g1") = 17 ; + __asm__ ("t 0x10" : "=r"(o0) : "r"(g1), "0"(o0) : "cc"); + newbrk = o0; + } + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/sparc/bsd-_setjmp.S b/libc/sysdeps/linux/sparc/bsd-_setjmp.S new file mode 100644 index 0000000..4e6a2da --- /dev/null +++ b/libc/sysdeps/linux/sparc/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/sparc/bsd-setjmp.S b/libc/sysdeps/linux/sparc/bsd-setjmp.S new file mode 100644 index 0000000..1da848d --- /dev/null +++ b/libc/sysdeps/linux/sparc/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/sparc/clone.S b/libc/sysdeps/linux/sparc/clone.S new file mode 100644 index 0000000..0e41ee0 --- /dev/null +++ b/libc/sysdeps/linux/sparc/clone.S @@ -0,0 +1,66 @@ +/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.global clone +.type clone,%function +.align 4 + +clone: + save %sp,-96,%sp + + /* sanity check arguments */ + tst %i0 + be __error + orcc %i1,%g0,%o1 + be __error + mov %i2,%o0 + + /* Do the system call */ + set __NR_clone,%g1 + ta 0x10 + bcs __error + tst %o1 + bne __thread_start + nop + ret + restore %o0,%g0,%o0 + +__error: + jmp __syscall_error + +.size clone,.-clone + +.type __thread_start,%function + +__thread_start: + call %i0 + mov %i3,%o0 + call HIDDEN_JUMPTARGET(_exit),0 + nop + +.size __thread_start,.-__thread_start diff --git a/libc/sysdeps/linux/sparc/crt1.S b/libc/sysdeps/linux/sparc/crt1.S new file mode 100644 index 0000000..f33a714 --- /dev/null +++ b/libc/sysdeps/linux/sparc/crt1.S @@ -0,0 +1,134 @@ +/* Startup code for elf{32,64}-sparc + Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1997. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Originally based on glibc's sysdeps/sparc/sparc{32,64}/elf/start.S */ + +#include +#include + +/* macro out the 32 / 64 bit differences */ +#if __WORDSIZE == 32 +# define STACK_BIAS 0 +# define ELE_SIZE 4 +# define LD ld +#else +# define STACK_BIAS 2047 /* see glibc/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h */ +# define ELE_SIZE 8 +# define LD ldx +#endif + +.text +.align 4 +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type __uClibc_main,%function +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +.global main +.type main,%function + +#ifdef __PIC__ +.LLGETPC0: + retl + add %o7, %l7, %l7 +#endif + +_start: +#ifdef __PIC__ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call .LLGETPC0 + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 +#endif + + /* Terminate the stack frame, and reserve space for functions to + * drop their arguments. */ + mov %g0, %fp + sub %sp, 6*ELE_SIZE, %sp + + /* Extract the arguments and environment as encoded on the stack. The + * argument info starts after one register window (16 words) past the SP. */ + LD [%sp+STACK_BIAS+22*ELE_SIZE], %o1 /* %o1 = argc */ + add %sp, STACK_BIAS+23*ELE_SIZE, %o2 /* %o2 = argv */ + + /* Load the addresses of the user entry points. */ + sethi %hi(main), %o0 + sethi %hi(_init), %o3 + sethi %hi(_fini), %o4 + or %o0, %lo(main), %o0 + or %o3, %lo(_init), %o3 + or %o4, %lo(_fini), %o4 +#ifdef __PIC__ + /* Need a little more magic when building PIC to get addr of main */ + LD [%l7 + %o0], %o0 + LD [%l7 + %o3], %o3 + LD [%l7 + %o4], %o4 +#endif + + /* When starting a binary via the dynamic linker, %g1 contains the + * address of the shared library termination function, which will be + * registered with atexit(). If we are statically linked, this will + * be NULL. */ + mov %g1, %o5 + + /* Let libc do the rest of the initialization, and call main. */ + call __uClibc_main + nop + + /* Die very horribly if exit returns. */ +#if __WORDSIZE == 32 + unimp +#else + illtrap 0 +#endif + +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/sparc/crti.S b/libc/sysdeps/linux/sparc/crti.S new file mode 100644 index 0000000..6dfc6c6 --- /dev/null +++ b/libc/sysdeps/linux/sparc/crti.S @@ -0,0 +1,23 @@ + .file "initfini.c" + + .section .init + .align 4 + .global _init + .type _init, %function + .proc 020 +_init: + !#PROLOGUE# 0 + save %sp, -104, %sp + + .align 4 + + + .section .fini + .align 4 + .global _fini + .type _fini, %function + .proc 020 +_fini: + !#PROLOGUE# 0 + save %sp, -104, %sp + .align 4 diff --git a/libc/sysdeps/linux/sparc/crtn.S b/libc/sysdeps/linux/sparc/crtn.S new file mode 100644 index 0000000..24b4bf4 --- /dev/null +++ b/libc/sysdeps/linux/sparc/crtn.S @@ -0,0 +1,19 @@ + .file "initfini.c" + + .section .init + .align 4 + .global _init + .type _init, %function + .proc 020 + ret + restore + .size _init, .-_init + + .section .fini + .align 4 + .global _fini + .type _fini, %function + .proc 020 + ret + restore + .size _fini, .-_fini diff --git a/libc/sysdeps/linux/sparc/fork.S b/libc/sysdeps/linux/sparc/fork.S new file mode 100644 index 0000000..00157cf --- /dev/null +++ b/libc/sysdeps/linux/sparc/fork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Code taken from glibc2.2.2/sysdeps/unix/sysv/linux/sparc/vfork.S */ + +#include +#include + +.text +.global __libc_fork +.type __libc_fork,%function +.align 4 + +__libc_fork: + mov __NR_fork, %g1 + ta 0x10 + bcc,a 9000f + nop + save %sp,-96,%sp + call __errno_location + nop + st %i0,[%o0] + jmpl %i7+8,%g0 + restore %g0,-1,%o0 + +9000: + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 + +.size __libc_fork,.-__libc_fork +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/libc/sysdeps/linux/sparc/fpu_control.h b/libc/sysdeps/linux/sparc/fpu_control.h new file mode 100644 index 0000000..41ab0a9 --- /dev/null +++ b/libc/sysdeps/linux/sparc/fpu_control.h @@ -0,0 +1,75 @@ +/* FPU control word bits. SPARC version. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + + +#include +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x08000000 +#define _FPU_MASK_OM 0x04000000 +#define _FPU_MASK_UM 0x02000000 +#define _FPU_MASK_ZM 0x01000000 +#define _FPU_MASK_PM 0x00800000 + +/* precision control */ +#define _FPU_EXTENDED 0x00000000 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x20000000 +#define _FPU_80BIT 0x30000000 +#define _FPU_SINGLE 0x10000000 /* DO NOT USE */ + +/* rounding control / Sparc */ +#define _FPU_RC_DOWN 0xc0000000 +#define _FPU_RC_UP 0x80000000 +#define _FPU_RC_ZERO 0x40000000 +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ + +#define _FPU_RESERVED 0x30300000 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux and IEEE default: + - extended precision + - rounding to nearest + - no exceptions */ +#define _FPU_DEFAULT 0x0 +#define _FPU_IEEE 0x0 + +/* Type of the control word. */ +typedef unsigned long int fpu_control_t; + +#if __WORDSIZE == 64 +# define _FPU_GETCW(cw) __asm__ ("stx %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("ldx %0,%%fsr" : : "m" (*&cw)) +#else +# define _FPU_GETCW(cw) __asm__ ("st %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("ld %0,%%fsr" : : "m" (*&cw)) +#endif + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/sparc/qp_ops.c b/libc/sysdeps/linux/sparc/qp_ops.c new file mode 100644 index 0000000..5336a29 --- /dev/null +++ b/libc/sysdeps/linux/sparc/qp_ops.c @@ -0,0 +1,46 @@ +/* XXX add ops from glibc sysdeps/sparc/sparc64/soft-fp */ + +#define fakedef(name) \ + void name(void) \ + { \ + printf("Unimplemented %s called, exiting\n", #name); \ + exit(-1); \ + } + +#ifdef __sparc_v9__ +fakedef(_Qp_fne) +fakedef(_Qp_feq) +fakedef(_Qp_div) +fakedef(_Qp_flt) +fakedef(_Qp_mul) +fakedef(_Qp_fge) +fakedef(_Qp_qtoux) +fakedef(_Qp_uxtoq) +fakedef(_Qp_sub) +fakedef(_Qp_dtoq) +fakedef(_Qp_qtod) +fakedef(_Qp_qtos) +fakedef(_Qp_stoq) +fakedef(_Qp_itoq) +fakedef(_Qp_add) +#else +fakedef(_Q_fne) +fakedef(_Q_feq) +fakedef(_Q_div) +fakedef(_Q_flt) +fakedef(_Q_mul) +fakedef(_Q_fge) +fakedef(_Q_qtoux) +fakedef(_Q_uxtoq) +fakedef(_Q_qtou) +fakedef(_Q_utoq) +fakedef(_Q_sub) +fakedef(_Q_dtoq) +fakedef(_Q_qtod) +fakedef(_Q_qtos) +fakedef(_Q_stoq) +fakedef(_Q_itoq) +fakedef(_Q_add) +#endif + +#undef fakedef diff --git a/libc/sysdeps/linux/sparc/rem.S b/libc/sysdeps/linux/sparc/rem.S new file mode 100644 index 0000000..595e8ea --- /dev/null +++ b/libc/sysdeps/linux/sparc/rem.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/rem.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/rem.S" +#else +# include "sparcv7/rem.S" +#endif diff --git a/libc/sysdeps/linux/sparc/sdiv.S b/libc/sysdeps/linux/sparc/sdiv.S new file mode 100644 index 0000000..7e9a9c9 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sdiv.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/sdiv.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/sdiv.S" +#else +# include "sparcv7/sdiv.S" +#endif diff --git a/libc/sysdeps/linux/sparc/setjmp.S b/libc/sysdeps/linux/sparc/setjmp.S new file mode 100644 index 0000000..796abc7 --- /dev/null +++ b/libc/sysdeps/linux/sparc/setjmp.S @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 93, 94, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define _ASM 1 +#define _SETJMP_H +#include +#define ST_FLUSH_WINDOWS 3 + +.global _setjmp +.type _setjmp,%function +.align 4 +_setjmp: + b 1f + set 0, %o1 +.size _setjmp,.-_setjmp + + + + + +.global setjmp +.type setjmp,%function +.align 4 +setjmp: + set 1, %o1 +.size setjmp,.-setjmp + + + + + +.global __sigsetjmp +.type __sigsetjmp,%function +.align 4 +__sigsetjmp: +1: + /* Save our PC, SP and FP. Save the signal mask if requested with + a tail-call for simplicity; it always returns zero. */ + ta ST_FLUSH_WINDOWS + + st %o7, [%o0 + (JB_PC * 4)] + st %sp, [%o0 + (JB_SP * 4)] + st %fp, [%o0 + (JB_FP * 4)] + + mov %o7, %g1 + call __sigjmp_save + mov %g1, %o7 +.size __sigsetjmp,.-__sigsetjmp + + + +.weak _setjmp +.weak setjmp diff --git a/libc/sysdeps/linux/sparc/sparcv7/rem.S b/libc/sysdeps/linux/sparc/sparcv7/rem.S new file mode 100644 index 0000000..ce06e63 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv7/rem.S @@ -0,0 +1,360 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .rem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.rem) + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + mov %o0, %g3 ! sign of remainder matches %o0 + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +LOC(got_result): + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o3, %o3 +1: + retl + mov %o3, %o0 + +END(.rem) diff --git a/libc/sysdeps/linux/sparc/sparcv7/sdiv.S b/libc/sysdeps/linux/sparc/sparcv7/sdiv.S new file mode 100644 index 0000000..d6f2bc7 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv7/sdiv.S @@ -0,0 +1,360 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .div name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.div) + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + xor %o1, %o0, %g3 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +LOC(got_result): + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o2, %o2 +1: + retl + mov %o2, %o0 + +END(.div) diff --git a/libc/sysdeps/linux/sparc/sparcv7/udiv.S b/libc/sysdeps/linux/sparc/sparcv7/udiv.S new file mode 100644 index 0000000..56c64ad --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv7/udiv.S @@ -0,0 +1,343 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .udiv name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.udiv) + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +LOC(got_result): + + retl + mov %o2, %o0 + +END(.udiv) diff --git a/libc/sysdeps/linux/sparc/sparcv7/umul.S b/libc/sysdeps/linux/sparc/sparcv7/umul.S new file mode 100644 index 0000000..50b3157 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv7/umul.S @@ -0,0 +1,153 @@ +/* + * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the + * upper 32 bits of the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. Short + * multiplies require 25 instruction cycles, and long ones require + * 45 instruction cycles. + * + * On return, overflow has occurred (%o1 is not zero) if and only if + * the Z condition code is clear, allowing, e.g., the following: + * + * call .umul + * nop + * bnz overflow (or tnz) + */ + +ENTRY(.umul) + or %o0, %o1, %o4 + mov %o0, %y ! multiplier -> Y + andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args + be LOC(mul_shortway) ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product; clear N & V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + /* + * Normally, with the shift-and-add approach, if both numbers are + * positive you get the correct result. With 32-bit two's-complement + * numbers, -x is represented as + * + * x 32 + * ( 2 - ------ ) mod 2 * 2 + * 32 + * 2 + * + * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, + * we can treat this as if the radix point were just to the left + * of the sign bit (multiply by 2^32), and get + * + * -x = (2 - x) mod 2 + * + * Then, ignoring the `mod 2's for convenience: + * + * x * y = xy + * -x * y = 2y - xy + * x * -y = 2x - xy + * -x * -y = 4 - 2x - 2y + xy + * + * For signed multiplies, we subtract (x << 32) from the partial + * product to fix this problem for negative multipliers (see mul.s). + * Because of the way the shift into the partial product is calculated + * (N xor V), this term is automatically removed for the multiplicand, + * so we don't have to adjust. + * + * But for unsigned multiplies, the high order bit wasn't a sign bit, + * and the correction is wrong. So for unsigned multiplies where the + * high order bit is one, we end up with xy - (y << 32). To fix it + * we add y << 32. + */ +#if 0 + tst %o1 + bl,a 1f ! if %o1 < 0 (high order bit = 1), + add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) +1: rd %y, %o0 ! get lower half of product + retl + addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 +#else + /* Faster code from tege@sics.se. */ + sra %o1, 31, %o2 ! make mask from sign bit + and %o0, %o2, %o2 ! %o2 = 0 or %o0, depending on sign of %o1 + rd %y, %o0 ! get lower half of product + retl + addcc %o4, %o2, %o1 ! add compensation and put upper half in place +#endif + +LOC(mul_shortway): + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above), + * and overflow is impossible (the answer is at most 24 bits long). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the result; %y has + * the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * -----result----- + * + * The 12 bits of %o4 left of the `result' area are all zero; + * in fact, all top 20 bits of %o4 are zero. + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20 + or %o5, %o0, %o0 + retl + addcc %g0, %g0, %o1 ! %o1 = zero, and set Z + +END(.umul) diff --git a/libc/sysdeps/linux/sparc/sparcv7/urem.S b/libc/sysdeps/linux/sparc/sparcv7/urem.S new file mode 100644 index 0000000..ecf3467 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv7/urem.S @@ -0,0 +1,343 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .urem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.urem) + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +LOC(got_result): + + retl + mov %o3, %o0 + +END(.urem) diff --git a/libc/sysdeps/linux/sparc/sparcv8/rem.S b/libc/sysdeps/linux/sparc/sparcv8/rem.S new file mode 100644 index 0000000..c4faebe --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv8/rem.S @@ -0,0 +1,19 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.rem) + + sra %o0, 31, %o2 + wr %o2, 0, %y + nop + nop + nop + sdivcc %o0, %o1, %o2 + bvs,a 1f + xnor %o2, %g0, %o2 +1: smul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.rem) diff --git a/libc/sysdeps/linux/sparc/sparcv8/sdiv.S b/libc/sysdeps/linux/sparc/sparcv8/sdiv.S new file mode 100644 index 0000000..4ac901a --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv8/sdiv.S @@ -0,0 +1,18 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.div) + + sra %o0, 31, %o2 + wr %o2, 0, %y + nop + nop + nop + sdivcc %o0, %o1, %o0 + bvs,a 1f + xnor %o0, %g0, %o0 +1: retl + nop + +END(.div) diff --git a/libc/sysdeps/linux/sparc/sparcv8/udiv.S b/libc/sysdeps/linux/sparc/sparcv8/udiv.S new file mode 100644 index 0000000..d5d93bb --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv8/udiv.S @@ -0,0 +1,13 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.udiv) + + wr %g0, 0, %y + nop + nop + retl + udiv %o0, %o1, %o0 + +END(.udiv) diff --git a/libc/sysdeps/linux/sparc/sparcv8/umul.S b/libc/sysdeps/linux/sparc/sparcv8/umul.S new file mode 100644 index 0000000..47b98e9 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv8/umul.S @@ -0,0 +1,11 @@ +/* + * Sparc v8 has multiply. + */ + +ENTRY(.umul) + + umul %o0, %o1, %o0 + retl + rd %y, %o1 + +END(.umul) diff --git a/libc/sysdeps/linux/sparc/sparcv8/urem.S b/libc/sysdeps/linux/sparc/sparcv8/urem.S new file mode 100644 index 0000000..0e96246 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv8/urem.S @@ -0,0 +1,16 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.urem) + + wr %g0, 0, %y + nop + nop + nop + udiv %o0, %o1, %o2 + umul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.urem) diff --git a/libc/sysdeps/linux/sparc/sparcv9/rem.S b/libc/sysdeps/linux/sparc/sparcv9/rem.S new file mode 100644 index 0000000..1474e32 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv9/rem.S @@ -0,0 +1,20 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and sdivcc only 36, + * we use sdivcc eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.rem) + + sra %o0, 31, %o2 + wr %o2, 0, %y + sdivcc %o0, %o1, %o2 + xnor %o2, %g0, %o3 + movvs %icc, %o3, %o2 + smul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.rem) diff --git a/libc/sysdeps/linux/sparc/sparcv9/sdiv.S b/libc/sysdeps/linux/sparc/sparcv9/sdiv.S new file mode 100644 index 0000000..45535bb --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv9/sdiv.S @@ -0,0 +1,18 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and sdivcc only 36, + * we use sdivcc eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.div) + + sra %o0, 31, %o2 + wr %o2, 0, %y + sdivcc %o0, %o1, %o0 + xnor %o0, %g0, %o2 + retl + movvs %icc, %o2, %o0 + +END(.div) diff --git a/libc/sysdeps/linux/sparc/sparcv9/udiv.S b/libc/sysdeps/linux/sparc/sparcv9/udiv.S new file mode 100644 index 0000000..303f29b --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv9/udiv.S @@ -0,0 +1,15 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and udiv only 37, + * we use udiv eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.udiv) + + wr %g0, 0, %y + retl + udiv %o0, %o1, %o0 + +END(.udiv) diff --git a/libc/sysdeps/linux/sparc/sparcv9/umul.S b/libc/sysdeps/linux/sparc/sparcv9/umul.S new file mode 100644 index 0000000..e65e4b9 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv9/umul.S @@ -0,0 +1,15 @@ +/* + * Sparc v9 has multiply. + */ + + .text + .align 32 +ENTRY(.umul) + + srl %o0, 0, %o0 + srl %o1, 0, %o1 + mulx %o0, %o1, %o0 + retl + srlx %o0, 32, %o1 + +END(.umul) diff --git a/libc/sysdeps/linux/sparc/sparcv9/urem.S b/libc/sysdeps/linux/sparc/sparcv9/urem.S new file mode 100644 index 0000000..9354269 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sparcv9/urem.S @@ -0,0 +1,17 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and udiv only 37, + * we use udiv eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.urem) + + wr %g0, 0, %y + udiv %o0, %o1, %o2 + umul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.urem) diff --git a/libc/sysdeps/linux/sparc/sys/procfs.h b/libc/sysdeps/linux/sparc/sys/procfs.h new file mode 100644 index 0000000..2827b1e --- /dev/null +++ b/libc/sysdeps/linux/sparc/sys/procfs.h @@ -0,0 +1,211 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#if __WORDSIZE == 64 + +#define ELF_NGREG 36 + +typedef struct + { + unsigned long pr_regs[32]; + unsigned long pr_fsr; + unsigned long pr_gsr; + unsigned long pr_fprs; + } elf_fpregset_t; + +#else /* sparc32 */ + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +#endif /* sparc32 */ + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ +#if __WORDSIZE == 64 + unsigned int pr_uid; + unsigned int pr_gid; +#else + unsigned short int pr_uid; + unsigned short int pr_gid; +#endif + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +#if __WORDSIZE == 64 + +/* Provide 32-bit variants so that BFD can read 32-bit + core files. */ +#define ELF_NGREG32 38 +typedef struct + { + union + { + unsigned int pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned int __unused; + unsigned int pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t32; + +typedef unsigned int elf_greg_t32; +typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG32]; + +struct elf_prstatus32 + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned int pr_sigpend; /* Set of pending signals. */ + unsigned int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct + { + int tv_sec, tv_usec; + } pr_utime, /* User time. */ + pr_stime, /* System time. */ + pr_cutime, /* Cumulative user time. */ + pr_cstime; /* Cumulative system time. */ + elf_gregset_t32 pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + +struct elf_prpsinfo32 + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +typedef elf_gregset_t32 prgregset32_t; +typedef elf_fpregset_t32 prfpregset32_t; + +typedef struct elf_prstatus32 prstatus32_t; +typedef struct elf_prpsinfo32 prpsinfo32_t; + +#endif /* sparc64 */ + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/sparc/sys/ptrace.h b/libc/sysdeps/linux/sparc/sys/ptrace.h new file mode 100644 index 0000000..d573f0e --- /dev/null +++ b/libc/sysdeps/linux/sparc/sys/ptrace.h @@ -0,0 +1,183 @@ +/* `ptrace' debugger support interface. Linux/SPARC version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +#include + +/* Linux/SPARC kernels up to 2.3.18 do not care much + about what namespace polution, so use a kludge now. */ +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#undef PTRACE_READDATA +#undef PTRACE_WRITEDATA +#undef PTRACE_READTEXT +#undef PTRACE_WRITETEXT +#undef PTRACE_SUNDETACH + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 11, +#define PT_DETACH PTRACE_DETACH + + /* This define is needed for older programs which were + trying to work around sparc-linux ptrace nastiness. */ +#define PTRACE_SUNDETACH PTRACE_DETACH + +#if __WORDSIZE == 32 + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + +#endif + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Write several bytes at a time. */ + PTRACE_WRITEDATA = 17, +#define PTRACE_WRITEDATA PTRACE_WRITEDATA + + /* Read several bytes at a time. */ + PTRACE_READTEXT = 18, +#define PTRACE_READTEXT PTRACE_READTEXT +#define PTRACE_READDATA PTRACE_READTEXT + + /* Write several bytes at a time. */ + PTRACE_WRITETEXT = 19, +#define PTRACE_WRITETEXT PTRACE_WRITETEXT + +#if __WORDSIZE == 64 + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 22, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 23, +#define PT_SETREGS PTRACE_SETREGS + +#endif + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PTRACE_SYSCALL PTRACE_SYSCALL + +#if __WORDSIZE == 64 + + , + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 25, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 26 +#define PT_SETFPREGS PTRACE_SETFPREGS + +#endif +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/sparc/sys/ucontext.h b/libc/sysdeps/linux/sparc/sys/ucontext.h new file mode 100644 index 0000000..b1102b0 --- /dev/null +++ b/libc/sysdeps/linux/sparc/sys/ucontext.h @@ -0,0 +1,270 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +#if __WORDSIZE == 64 + +#define MC_TSTATE 0 +#define MC_PC 1 +#define MC_NPC 2 +#define MC_Y 3 +#define MC_G1 4 +#define MC_G2 5 +#define MC_G3 6 +#define MC_G4 7 +#define MC_G5 8 +#define MC_G6 9 +#define MC_G7 10 +#define MC_O0 11 +#define MC_O1 12 +#define MC_O2 13 +#define MC_O3 14 +#define MC_O4 15 +#define MC_O5 16 +#define MC_O6 17 +#define MC_O7 18 +#define MC_NGREG 19 + +typedef unsigned long mc_greg_t; +typedef mc_greg_t mc_gregset_t[MC_NGREG]; + +#define MC_MAXFPQ 16 +struct mc_fq { + unsigned long *mcfq_addr; + unsigned int mcfq_insn; +}; + +struct mc_fpu { + union { + unsigned int sregs[32]; + unsigned long dregs[32]; + long double qregs[16]; + } mcfpu_fregs; + unsigned long mcfpu_fsr; + unsigned long mcfpu_fprs; + unsigned long mcfpu_gsr; + struct mc_fq *mcfpu_fq; + unsigned char mcfpu_qcnt; + unsigned char mcfpu_qentsz; + unsigned char mcfpu_enab; +}; +typedef struct mc_fpu mc_fpu_t; + +typedef struct { + mc_gregset_t mc_gregs; + mc_greg_t mc_fp; + mc_greg_t mc_i7; + mc_fpu_t mc_fpregs; +} mcontext_t; + +typedef struct ucontext { + struct ucontext *uc_link; + unsigned long uc_flags; + unsigned long __uc_sigmask; + mcontext_t uc_mcontext; + stack_t uc_stack; + __sigset_t uc_sigmask; +} ucontext_t; + +#endif /* __WORDISIZE == 64 */ + +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_nPC (2) +#define REG_Y (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#if __WORDSIZE == 64 + +#define REG_ASI (19) +#define REG_FPRS (20) + +#define NGREG 21 +typedef long greg_t; + +#else /* __WORDSIZE == 32 */ + +#define NGREG 19 +typedef int greg_t; + +#endif /* __WORDSIZE == 32 */ + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). SPARC_MAXWINDOW is the + * maximum number of outstanding regiters window defined in the SPARC + * architecture (*not* implementation). + */ +#define SPARC_MAXREGWINDOW 31 /* max windows in SPARC arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[SPARC_MAXREGWINDOW]; + struct rwindow wbuf[SPARC_MAXREGWINDOW]; + } gwindows_t; + +/* + * Floating point definitions. + */ + +#define MAXFPQ 16 /* max # of fpu queue entries currently supported */ + +/* + * struct fq defines the minimal format of a floating point instruction queue + * entry. The size of entries in the floating point queue are implementation + * dependent. The union FQu is guarenteed to be the first field in any ABI + * conformant system implementation. Any additional fields provided by an + * implementation should not be used applications designed to be ABI conformant. */ + +struct fpq + { + unsigned long *fpq_addr; /* address */ + unsigned long fpq_instr; /* instruction */ + }; + +struct fq + { + union /* FPU inst/addr queue */ + { + double whole; + struct fpq fpq; + } FQu; + }; + +#define FPU_REGS_TYPE unsigned +#define FPU_DREGS_TYPE unsigned long long +#define V7_FPU_FSR_TYPE unsigned +#define V9_FPU_FSR_TYPE unsigned long long +#define V9_FPU_FPRS_TYPE unsigned + +#if __WORDSIZE == 64 + +typedef struct fpu + { + union { /* FPU floating point regs */ + unsigned fpu_regs[32]; /* 32 singles */ + double fpu_dregs[16]; /* 32 doubles */ + long double fpu_qregs[16]; /* 16 quads */ + } fpu_fr; + struct fq *fpu_q; /* ptr to array of FQ entries */ + unsigned long fpu_fsr; /* FPU status register */ + unsigned char fpu_qcnt; /* # of entries in saved FQ */ + unsigned char fpu_q_entrysize; /* # of bytes per FQ entry */ + unsigned char fpu_en; /* flag signifying fpu in use */ + } fpregset_t; + +#else /* __WORDSIZE == 32 */ + +typedef struct fpu + { + union { /* FPU floating point regs */ + unsigned long long fpu_regs[32]; /* 32 singles */ + double fpu_dregs[16]; /* 16 doubles */ + } fpu_fr; + struct fq *fpu_q; /* ptr to array of FQ entries */ + unsigned fpu_fsr; /* FPU status register */ + unsigned char fpu_qcnt; /* # of entries in saved FQ */ + unsigned char fpu_q_entrysize; /* # of bytes per FQ entry */ + unsigned char fpu_en; /* flag signifying fpu in use */ + } fpregset_t; + +/* + * The following structure is for associating extra register state with + * the ucontext structure and is kept within the uc_mcontext filler area. + * + * If (xrs_id == XRS_ID) then the xrs_ptr field is a valid pointer to + * extra register state. The exact format of the extra register state + * pointed to by xrs_ptr is platform-dependent. + * + * Note: a platform may or may not manage extra register state. + */ +typedef struct + { + unsigned int xrs_id; /* indicates xrs_ptr validity */ + void * xrs_ptr; /* ptr to extra reg state */ + } xrs_t; + +#define XRS_ID 0x78727300 /* the string "xrs" */ + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + fpregset_t fpregs; /* floating point register set */ + xrs_t xrs; /* POSSIBLE extra register state association */ + long filler[19]; + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* __WORDSIZE == 32 */ +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/sparc/sys/user.h b/libc/sysdeps/linux/sparc/sys/user.h new file mode 100644 index 0000000..2aad01b --- /dev/null +++ b/libc/sysdeps/linux/sparc/sys/user.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +struct sunos_regs +{ + unsigned int psr, pc, npc, y; + unsigned int regs[15]; +}; + +struct sunos_fpqueue +{ + unsigned int *addr; + unsigned int inst; +}; + +struct sunos_fp +{ + union + { + unsigned int regs[32]; + double reg_dbls[16]; + } fregs; + unsigned int fsr; + unsigned int flags; + unsigned int extra; + unsigned int fpq_count; + struct sunos_fpqueue fpq[16]; +}; + +struct sunos_fpu +{ + struct sunos_fp fpstatus; +}; + +/* The SunOS core file header layout. */ +struct user { + unsigned int magic; + unsigned int len; + struct sunos_regs regs; + struct + { + unsigned char a_dynamic :1; + unsigned char a_toolversion :7; + unsigned char a_machtype; + unsigned short a_info; + unsigned int a_text; + unsigned int a_data; + unsigned int a_bss; + unsigned int a_syms; + unsigned int a_entry; + unsigned int a_trsize; + unsigned int a_drsize; + } uexec; + int signal; + size_t u_tsize; + size_t u_dsize; + size_t u_ssize; + char u_comm[17]; + struct sunos_fpu fpu; + unsigned int sigcode; +}; + +#define NBPG 0x2000 +#define UPAGES 1 +#define SUNOS_CORE_MAGIC 0x080456 + +#endif diff --git a/libc/sysdeps/linux/sparc/syscall.S b/libc/sysdeps/linux/sparc/syscall.S new file mode 100644 index 0000000..86055ec --- /dev/null +++ b/libc/sysdeps/linux/sparc/syscall.S @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1992, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +.text +.global syscall +.type syscall,%function +#if __WORDSIZE == 32 +.align 4 +#else +.align 2 +#endif + +syscall: + mov %o0, %g1 + mov %o1, %o0 + mov %o2, %o1 + mov %o3, %o2 + mov %o4, %o3 + mov %o5, %o4 + +#if __WORDSIZE == 32 + ta 0x10 + bcs __syscall_error +#else + ta 0x6d + bcs,pn %xcc,__syscall_error +#endif + + nop + retl + nop +.size syscall,.-syscall diff --git a/libc/sysdeps/linux/sparc/udiv.S b/libc/sysdeps/linux/sparc/udiv.S new file mode 100644 index 0000000..a1355a7 --- /dev/null +++ b/libc/sysdeps/linux/sparc/udiv.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/udiv.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/udiv.S" +#else +# include "sparcv7/udiv.S" +#endif diff --git a/libc/sysdeps/linux/sparc/umul.S b/libc/sysdeps/linux/sparc/umul.S new file mode 100644 index 0000000..e860597 --- /dev/null +++ b/libc/sysdeps/linux/sparc/umul.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/umul.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/umul.S" +#else +# include "sparcv7/umul.S" +#endif diff --git a/libc/sysdeps/linux/sparc/urem.S b/libc/sysdeps/linux/sparc/urem.S new file mode 100644 index 0000000..baf6c43 --- /dev/null +++ b/libc/sysdeps/linux/sparc/urem.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/urem.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/urem.S" +#else +# include "sparcv7/urem.S" +#endif diff --git a/libc/sysdeps/linux/sparc/vfork.S b/libc/sysdeps/linux/sparc/vfork.S new file mode 100644 index 0000000..35ca037 --- /dev/null +++ b/libc/sysdeps/linux/sparc/vfork.S @@ -0,0 +1,55 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Code taken from glibc2.2.2/sysdeps/unix/sysv/linux/sparc/vfork.S */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 + +__vfork: + mov __NR_vfork, %g1 + ta 0x10 + bcc,a 9000f + nop + save %sp,-96,%sp + call __errno_location + nop + st %i0,[%o0] + jmpl %i7+8,%g0 + restore %g0,-1,%o0 + +9000: + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/v850/Makefile b/libc/sysdeps/linux/v850/Makefile new file mode 100644 index 0000000..60dc97c --- /dev/null +++ b/libc/sysdeps/linux/v850/Makefile @@ -0,0 +1,64 @@ +# Makefile for uClibc +# +# Copyright (C) 2001,2002 NEC Corporation +# Copyright (C) 2001,2002 Miles Bader +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +CFLAGS += -I.. +ASFLAGS += -I.. -D__ASSEMBLER -DASM_GLOBAL_DIRECTIVE=.globl + +TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine) + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := setjmp.S __longjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC := mmap.c syscall.c clone.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/libc/sysdeps/linux/v850/__longjmp.S b/libc/sysdeps/linux/v850/__longjmp.S new file mode 100644 index 0000000..fa29e0f --- /dev/null +++ b/libc/sysdeps/linux/v850/__longjmp.S @@ -0,0 +1,41 @@ +/* + * libc/sysdeps/linux/v850/longjmp.S -- `longjmp' for v850 + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(__longjmp): + /* Save registers */ + mov r6, ep + sld.w 0[ep], sp + sld.w 4[ep], lp + sld.w 8[ep], r2 + sld.w 12[ep], r20 + sld.w 16[ep], r21 + sld.w 20[ep], r22 + sld.w 24[ep], r23 + sld.w 28[ep], r24 + sld.w 32[ep], r25 + sld.w 36[ep], r26 + sld.w 40[ep], r27 + sld.w 44[ep], r28 + sld.w 48[ep], r29 + mov 1, r10 /* return val */ + jmp [lp] +C_END(__longjmp) +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/v850/bits/byteswap.h b/libc/sysdeps/linux/v850/bits/byteswap.h new file mode 100644 index 0000000..44fbee4 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/byteswap.h @@ -0,0 +1,63 @@ +/* + * libc/sysdeps/linux/v850/bits/byteswap.h -- Macros to swap the order + * of bytes in integer values + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997,1998,2001 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned long int __bswap_16_v; \ + if (__builtin_constant_p (x)) \ + __bswap_16_v = __bswap_constant_16 (x); \ + else \ + __asm__ ("bsh %1, %0" : "=r" (__bswap_16_v) : "r" (x)); \ + __bswap_16_v; })) +#else +# define __bswap_16(x) __bswap_constant_16 (x) +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned long int __bswap_32_v; \ + if (__builtin_constant_p (x)) \ + __bswap_32_v = __bswap_constant_32 (x); \ + else \ + __asm__ ("bsw %1, %0" : "=r" (__bswap_32_v) : "r" (x)); \ + __bswap_32_v; })) +#else +# define __bswap_32(x) __bswap_constant_32 (x) +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + (__extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __bswap_64_v, __bswap_64_r; \ + __bswap_64_v.__ll = (x); \ + __bswap_64_r.__l[0] = __bswap_32 (__bswap_64_v.__l[1]); \ + __bswap_64_r.__l[1] = __bswap_32 (__bswap_64_v.__l[0]); \ + __bswap_64_r.__ll; })) +#endif diff --git a/libc/sysdeps/linux/v850/bits/endian.h b/libc/sysdeps/linux/v850/bits/endian.h new file mode 100644 index 0000000..ae78da3 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/endian.h @@ -0,0 +1,18 @@ +/* + * libc/sysdeps/linux/v850/bits/endian.h -- Define processor endianess + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/v850/bits/fcntl.h b/libc/sysdeps/linux/v850/bits/fcntl.h new file mode 100644 index 0000000..87d1939 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/fcntl.h @@ -0,0 +1,234 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_STREAMING 04000000/* streaming access */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/v850/bits/kernel_stat.h b/libc/sysdeps/linux/v850/bits/kernel_stat.h new file mode 100644 index 0000000..02343ed --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/kernel_stat.h @@ -0,0 +1,66 @@ +/* Stat structure for linux/v850 */ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat +{ + __kernel_dev_t st_dev; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + __kernel_off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 +{ + __kernel_dev_t st_dev; + unsigned long __unused0; + unsigned long __unused1; + + __kernel_ino64_t st_ino; + + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + + __kernel_dev_t st_rdev; + unsigned long __unused2; + unsigned long __unused3; + + __kernel_loff_t st_size; + unsigned long st_blksize; + + unsigned long __unused4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long st_atime; + unsigned long __unused5; + + unsigned long st_mtime; + unsigned long __unused6; + + unsigned long st_ctime; + unsigned long __unused7; /* high 32 bits of ctime someday */ +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/v850/bits/kernel_types.h b/libc/sysdeps/linux/v850/bits/kernel_types.h new file mode 100644 index 0000000..3e851ab --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/kernel_types.h @@ -0,0 +1,53 @@ +/* + * sysdeps/linux/v850/bits/kernel_types.h -- Kernel versions of standard types + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef __V850_POSIX_TYPES_H__ +#define __V850_POSIX_TYPES_H__ + +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __V850_POSIX_TYPES_H__ */ diff --git a/libc/sysdeps/linux/v850/bits/mman.h b/libc/sysdeps/linux/v850/bits/mman.h new file mode 100644 index 0000000..4393d03 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/mman.h @@ -0,0 +1,99 @@ +/* Definitions for POSIX memory map interface. Linux/v850 version. + Copyright (C) 1997, 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* These are the bits used by 4.4 BSD and its derivatives. On systems + (such as GNU) where these facilities are not system services but can be + emulated in the C library, these are the definitions we emulate. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + + +/* Flags for `mlockall' (can be OR'd together). */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif diff --git a/libc/sysdeps/linux/v850/bits/poll.h b/libc/sysdeps/linux/v850/bits/poll.h new file mode 100644 index 0000000..f7a7393 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/libc/sysdeps/linux/v850/bits/select.h b/libc/sysdeps/linux/v850/bits/select.h new file mode 100644 index 0000000..b6bb054 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/select.h @@ -0,0 +1,64 @@ +/* + * include/bits/select.h -- fd_set operations + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997, 1998 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + +#ifdef __GNUC__ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) + +#define __FD_SET(fd, s) \ + do { \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + __asm__ __volatile__ ("set1 %0, [%1]" \ + : /*nothing*/ \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3)));\ + } while (0) + +#define __FD_CLR(fd, s) \ + do { \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + __asm__ __volatile__ ("clr1 %0, [%1]" \ + : /*nothing*/ \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3)));\ + } while (0) + +#define __FD_ISSET(fd, s) \ + ({ \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + int res; \ + __asm__ ("tst1 %1, [%2]; setf nz, %0" \ + : "=r" (res) \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3))); \ + res; \ + }) + +#else /* !__GNUC__ */ + +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) + +#endif /* __GNUC__ */ diff --git a/libc/sysdeps/linux/v850/bits/setjmp.h b/libc/sysdeps/linux/v850/bits/setjmp.h new file mode 100644 index 0000000..c943737 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/setjmp.h @@ -0,0 +1,42 @@ +/* + * libc/sysdeps/linux/v850/bits/setjmp.h -- v850 version of `jmp_buf' type + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Stack pointer. */ + void *__sp; + + /* Link pointer. */ + void *__lp; + + /* Callee-saved registers r2 and r20-r29. */ + int __regs[11]; + } __jmp_buf[1]; +#endif + +#define JB_SIZE (4 * 13) + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/v850/bits/sigcontextinfo.h b/libc/sysdeps/linux/v850/bits/sigcontextinfo.h new file mode 100644 index 0000000..de450ff --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/sigcontextinfo.h @@ -0,0 +1,17 @@ +/* + * sysdeps/v850/sigcontextinfo.h -- v850-specific pthread signal definitions + * + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS diff --git a/libc/sysdeps/linux/v850/bits/stackinfo.h b/libc/sysdeps/linux/v850/bits/stackinfo.h new file mode 100644 index 0000000..3ed732a --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/stackinfo.h @@ -0,0 +1,23 @@ +/* + * bits/stackinfo.h -- v850-specific pthread definitions + * + * Copyright (C) 2003 NEC Electronics Corporation + * Copyright (C) 2003 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On v80 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/v850/bits/syscalls.h b/libc/sysdeps/linux/v850/bits/syscalls.h new file mode 100644 index 0000000..b218513 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/syscalls.h @@ -0,0 +1,15 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Do something very evil for now. Until we create our own syscall + * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ +#warning "fixme -- add arch specific syscall macros.h" +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h b/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h new file mode 100644 index 0000000..f4adaf5 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h @@ -0,0 +1,39 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/v850/bits/wordsize.h b/libc/sysdeps/linux/v850/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/v850/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/v850/clinkage.h b/libc/sysdeps/linux/v850/clinkage.h new file mode 100644 index 0000000..e85d39f --- /dev/null +++ b/libc/sysdeps/linux/v850/clinkage.h @@ -0,0 +1,14 @@ +/* + * libc/sysdeps/linux/v850/clinkage.h -- Macros for C symbols in assembler + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include diff --git a/libc/sysdeps/linux/v850/clone.c b/libc/sysdeps/linux/v850/clone.c new file mode 100644 index 0000000..d2e2208 --- /dev/null +++ b/libc/sysdeps/linux/v850/clone.c @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/v850/clone.c -- `clone' syscall for linux/v850 + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include + +int +clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg) +{ + register unsigned long rval __asm__ (SYSCALL_RET) = -EINVAL; + + if (fn && child_stack) + { + register unsigned long syscall __asm__ (SYSCALL_NUM); + register unsigned long arg0 __asm__ (SYSCALL_ARG0); + register unsigned long arg1 __asm__ (SYSCALL_ARG1); + + /* Clone this thread. */ + arg0 = flags; + arg1 = (unsigned long)child_stack; + syscall = __NR_clone; + __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0), "r" (arg1) + : SYSCALL_SHORT_CLOBBERS); + + if (rval == 0) + /* In child thread, call FN and exit. */ + { + arg0 = (*fn) (arg); + syscall = __NR_exit; + __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0) + : SYSCALL_SHORT_CLOBBERS); + } + } + + __syscall_return (int, rval); +} diff --git a/libc/sysdeps/linux/v850/crt0.S b/libc/sysdeps/linux/v850/crt0.S new file mode 100644 index 0000000..01e9f83 --- /dev/null +++ b/libc/sysdeps/linux/v850/crt0.S @@ -0,0 +1,57 @@ +/* + * libc/sysdeps/linux/v850/crt0.S -- Initial program entry point for linux/v850 + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +/* Upon entry, the stack contains the following data: + argc, argv[0], ..., argv[argc-1], 0, envp[0], ..., 0 +*/ + + .text +C_ENTRY(start): + ld.w 0[sp], r6 /* Arg 0: argc */ + + addi 4, sp, r7 /* Arg 1: argv */ + + mov r7, r8 /* Arg 2: envp */ + mov r6, r10 /* skip argc elements to get envp start */ + add 1, r10 /* ...plus the NULL at the end of argv */ + shl 2, r10 /* Convert to byte-count to skip */ + add r10, r8 + + /* Load CTBP register */ + mov hilo(C_SYMBOL_NAME(_ctbp)), r19 + ldsr r19, ctbp + + /* Load GP */ + mov hilo(C_SYMBOL_NAME(_gp)), gp + + /* tail-call uclibc's startup routine */ + addi -24, sp, sp /* Stack space reserved for args */ + jr C_SYMBOL_NAME(__uClibc_main) + + +/* Stick in a dummy reference to `main', so that if an application + is linking when the `main' function is in a static library (.a) + we can be sure that `main' actually gets linked in. */ +L_dummy_main_reference: + .long C_SYMBOL_NAME(main) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/libc/sysdeps/linux/v850/crti.S b/libc/sysdeps/linux/v850/crti.S new file mode 100644 index 0000000..c1e5293 --- /dev/null +++ b/libc/sysdeps/linux/v850/crti.S @@ -0,0 +1,27 @@ + .file "initfini.c" +#APP + + .section .init +#NO_APP + .align 1 + .global __init + .type __init, @function +__init: + jarl __save_r31, r10 +#APP + + .align 1 + + + .section .fini +#NO_APP + .align 1 + .global __fini + .type __fini, @function +__fini: + jarl __save_r31, r10 +#APP + .align 1 + + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/v850/crtn.S b/libc/sysdeps/linux/v850/crtn.S new file mode 100644 index 0000000..aecb557 --- /dev/null +++ b/libc/sysdeps/linux/v850/crtn.S @@ -0,0 +1,24 @@ + .file "initfini.c" +#APP + + .section .init +#NO_APP + .align 1 + .global __init + .type __init, @function +#NO_APP + jr __return_r31 + .size __init, .-__init +#APP + + .section .fini +#NO_APP + .align 1 + .global __fini + .type __fini, @function +#NO_APP + jr __return_r31 + .size __fini, .-__fini +#APP + + .ident "GCC: (GNU) 3.3.2" diff --git a/libc/sysdeps/linux/v850/mmap.c b/libc/sysdeps/linux/v850/mmap.c new file mode 100644 index 0000000..ca5eddd --- /dev/null +++ b/libc/sysdeps/linux/v850/mmap.c @@ -0,0 +1,17 @@ +/* Use new style mmap for v850 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/v850/setjmp.S b/libc/sysdeps/linux/v850/setjmp.S new file mode 100644 index 0000000..87a5e38 --- /dev/null +++ b/libc/sysdeps/linux/v850/setjmp.S @@ -0,0 +1,48 @@ +/* + * libc/sysdeps/linux/v850/setjmp.S -- `setjmp' for v850 + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(setjmp): + mov 1, r7 /* Save the signal mask. */ + br C_SYMBOL_NAME(__sigsetjmp) + + .globl C_SYMBOL_NAME(_setjmp) +C_SYMBOL_NAME(_setjmp): + mov 0, r7 /* Don't save the signal mask. */ + + .globl C_SYMBOL_NAME(__sigsetjmp) +C_SYMBOL_NAME(__sigsetjmp): + /* Save registers */ + mov r6, ep + sst.w sp, 0[ep] + sst.w lp, 4[ep] + sst.w r2, 8[ep] + sst.w r20, 12[ep] + sst.w r21, 16[ep] + sst.w r22, 20[ep] + sst.w r23, 24[ep] + sst.w r24, 28[ep] + sst.w r25, 32[ep] + sst.w r26, 36[ep] + sst.w r27, 40[ep] + sst.w r28, 44[ep] + sst.w r29, 48[ep] + /* Make a tail call to __sigjmp_save; it takes the same args. */ + jr C_SYMBOL_NAME(__sigjmp_save) +C_END(setjmp) diff --git a/libc/sysdeps/linux/v850/sys/procfs.h b/libc/sysdeps/linux/v850/sys/procfs.h new file mode 100644 index 0000000..67acb3c --- /dev/null +++ b/libc/sysdeps/linux/v850/sys/procfs.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include + + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* This is exactly the same as `struct pt_regs' in the kernel. */ +struct elf_gregset +{ + /* General purpose registers. */ + elf_greg_t gpr[32]; + + elf_greg_t pc; /* program counter */ + elf_greg_t psw; /* program status word */ + + /* Registers used by `callt' instruction: */ + elf_greg_t ctpc; /* saved program counter */ + elf_greg_t ctpsw; /* saved psw */ + elf_greg_t ctbp; /* base pointer for callt table */ + + char kernel_mode; /* 1 if in `kernel mode', 0 if user mode */ +}; + +#define ELF_NGREG (sizeof (struct elf_gregset) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef void elf_fpregset_t; + + +struct elf_siginfo +{ + int si_signo; /* signal number */ + int si_code; /* extra code */ + int si_errno; /* errno */ +}; + + +/* + * Definitions to generate Intel SVR4-like core files. + * These mostly have the same names as the SVR4 types with "elf_" + * tacked on the front to prevent clashes with linux definitions, + * and the typedef forms have been avoided. This is mostly like + * the SVR4 structure, but more Linuxy, with things that Linux does + * not support and which gdb doesn't really use excluded. + * Fields present but not used are marked with "XXX". + */ +struct elf_prstatus +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned long pr_sigpend; /* Set of pending signals */ + unsigned long pr_sighold; /* Set of held signals */ + __kernel_pid_t pr_pid; + __kernel_pid_t pr_ppid; + __kernel_pid_t pr_pgrp; + __kernel_pid_t pr_sid; + struct timeval pr_utime; /* User time */ + struct timeval pr_stime; /* System time */ + struct timeval pr_cutime; /* Cumulative user time */ + struct timeval pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned long pr_flag; /* flags */ + __kernel_uid_t pr_uid; + __kernel_gid_t pr_gid; + __kernel_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __kernel_pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/v850/sys/ptrace.h b/libc/sysdeps/linux/v850/sys/ptrace.h new file mode 100644 index 0000000..48690ee --- /dev/null +++ b/libc/sysdeps/linux/v850/sys/ptrace.h @@ -0,0 +1,98 @@ +/* `ptrace' debugger support interface. Linux/v850 version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/v850/sys/ucontext.h b/libc/sysdeps/linux/v850/sys/ucontext.h new file mode 100644 index 0000000..07f0933 --- /dev/null +++ b/libc/sysdeps/linux/v850/sys/ucontext.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/v850/syscall.c b/libc/sysdeps/linux/v850/syscall.c new file mode 100644 index 0000000..dbcc87c --- /dev/null +++ b/libc/sysdeps/linux/v850/syscall.c @@ -0,0 +1,43 @@ +/* + * libc/sysdeps/linux/v850/syscall.c -- generic syscall function for linux/v850 + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include + +typedef unsigned long arg_t; + +/* Invoke `system call' NUM, passing it the remaining arguments. + This is completely system-dependent, and not often useful. */ +long +syscall (long num, arg_t a1, arg_t a2, arg_t a3, arg_t a4, arg_t a5, arg_t a6) +{ + /* We don't know how many arguments are valid, so A5 and A6 are fetched + off the stack even for (the majority of) system calls with fewer + arguments; hopefully this won't cause any problems. A1-A4 are in + registers, so they're OK. */ + register arg_t a __asm__ (SYSCALL_ARG0) = a1; + register arg_t b __asm__ (SYSCALL_ARG1) = a2; + register arg_t c __asm__ (SYSCALL_ARG2) = a3; + register arg_t d __asm__ (SYSCALL_ARG3) = a4; + register arg_t e __asm__ (SYSCALL_ARG4) = a5; + register arg_t f __asm__ (SYSCALL_ARG5) = a6; + register unsigned long syscall __asm__ (SYSCALL_NUM) = num; + register unsigned long ret __asm__ (SYSCALL_RET); + + __asm__ ("trap " SYSCALL_LONG_TRAP + : "=r" (ret) + : "r" (syscall), "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f) + : SYSCALL_CLOBBERS); + + __syscall_return (long, ret); +} diff --git a/libc/sysdeps/linux/v850/vfork.S b/libc/sysdeps/linux/v850/vfork.S new file mode 100644 index 0000000..2533853 --- /dev/null +++ b/libc/sysdeps/linux/v850/vfork.S @@ -0,0 +1,42 @@ +/* + * libc/sysdeps/linux/v850/vfork.S -- `vfork' syscall for linux/v850 + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#define _ERRNO_H 1 +#include +#define _SYSCALL_H +#include + +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.global C_SYMBOL_NAME(errno) + +C_ENTRY (__vfork): + addi SYS_vfork, r0, r12 + trap 0 + addi -125, r0, r11 /* minimum err value */ + cmp r11, r10 + bh 1f + jmp [lp] /* normal return */ +1: mov hilo(C_SYMBOL_NAME(errno)), r11 + subr r0, r10 + st.w r10, 0[r11] + jmp [lp] /* error return */ +C_END(__vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/vax/Makefile b/libc/sysdeps/linux/vax/Makefile new file mode 100644 index 0000000..b1bf1ef --- /dev/null +++ b/libc/sysdeps/linux/vax/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +TOPDIR=../../../../ + +top_srcdir=$(TOPDIR) +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/vax/Makefile.arch b/libc/sysdeps/linux/vax/Makefile.arch new file mode 100644 index 0000000..ea8672c --- /dev/null +++ b/libc/sysdeps/linux/vax/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# Copyright (C) 2005-2006 Jan-Benedict Glaw +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c mmap.c +SSRC := __longjmp.S setjmp.S _setjmp.S clone.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/vax/__longjmp.S b/libc/sysdeps/linux/vax/__longjmp.S new file mode 100644 index 0000000..61b37a3 --- /dev/null +++ b/libc/sysdeps/linux/vax/__longjmp.S @@ -0,0 +1,47 @@ +#include + +/* + * longjmp.S atp sept 2001 + * Jan-Benedict Glaw 2006 + * + * Restore regs and info and jmp back to a previous setjmp + */ + +.globl __longjmp +.align 4 +__longjmp: + .word 0x0040 /* This matches setjmp and PLT */ + movl 0x4(%ap), %r0 /* Our scratch reg */ +/* movl $0, %r0 */ +/* movl (%r0), %r0 */ + /* We are going to modify our stack frame */ + /* to the same as that of the setjmp we called earlier */ + movl (%r0), (%fp) /* cond handler */ + movl 0x4(%r0), 0x4(%fp) /* psw */ + movl 0x8(%r0), 0x8(%fp) /* ap */ + movl 0xc(%r0), 0xc(%fp) /* fp */ + movl 0x10(%r0), 0x10(%fp) /* pc */ + + /* Restore the regs */ + movl 0x14(%r0), %r1 + movl 0x18(%r0), %r2 + movl 0x1c(%r0), %r3 + movl 0x20(%r0), %r4 + movl 0x24(%r0), %r5 + movl 0x28(%r0), %r6 + movl 0x2c(%r0), %r7 + movl 0x30(%r0), %r8 + movl 0x34(%r0), %r9 + movl 0x38(%r0), %r10 + movl 0x3c(%r0), %r11 + + /* Check val and set to 1 if set to zero */ + movl 0x8(%ap), %r0 + tstl %r0 + bneq exit_ok + movl $0x1, %r0 +exit_ok: + ret +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) + diff --git a/libc/sysdeps/linux/vax/_setjmp.S b/libc/sysdeps/linux/vax/_setjmp.S new file mode 100644 index 0000000..680ddd7 --- /dev/null +++ b/libc/sysdeps/linux/vax/_setjmp.S @@ -0,0 +1,53 @@ +.globl _setjmp +.align 4 +_setjmp: + .word 0x0040 + + /* push an empty word onto the stack */ + pushl $0 + + /* now copy handler, psw, ap, fp and pc on the stack up one word */ + movl 4(%sp), (%sp) /* copy handler */ + movl 8(%sp), 4(%sp) /* psw */ + movl 12(%sp), 8(%sp) /* ap */ + movl 16(%sp), 12(%sp) /* fp */ + movl 20(%sp), 16(%sp) /* pc */ + movl 24(%sp), 20(%sp) /* r6 from register mask */ + + movl $2, 24(%sp) /* set the number of arguments to 2 */ + movl 32(%sp), 28(%sp) /* copy the jmp_buf */ + movl $1, 32(%sp) /* put the 1 on the stack */ + + addl3 $24, %sp, %ap + movl %sp, %fp + + moval __sigsetjmp, %r0 + addl2 $2, %r0 + pushl %r0 + rsb + +.globl setjmp +.align 4 +setjmp: + .word 0x0040 + pushl $0 + + /* now copy handler, psw, ap, fp and pc on the stack up one word */ + movl 4(%sp), (%sp) + movl 8(%sp), 4(%sp) + movl 12(%sp), 8(%sp) + movl 16(%sp), 12(%sp) + movl 20(%sp), 16(%sp) + movl 24(%sp), 20(%sp) /* r6 from register mask */ + + movl $2, 24(%sp) /* set the number of arguments to 2 */ + movl 32(%sp), 28(%sp) /* copy the jmp_buf */ + movl $0, 32(%sp) /* put the 0 on the stack */ + + addl3 $24, %sp, %ap + movl %sp, %fp + + moval __sigsetjmp, %r0 + addl2 $2, %r0 + pushl %r0 + rsb diff --git a/libc/sysdeps/linux/vax/bits/byteswap.h b/libc/sysdeps/linux/vax/bits/byteswap.h new file mode 100644 index 0000000..6b51156 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/byteswap.h @@ -0,0 +1,64 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Swap bytes in 16 bit value. */ +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __bsx = (x); \ + ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); })) +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); +} +#endif + +/* Swap bytes in 32 bit value. */ +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned int __bsx = (x); \ + ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \ + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); +} +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_64(x) \ + (__extension__ \ + ({ union { unsigned long long int __ll; \ + unsigned long int __l[2]; } __v, __r; \ + __v.__ll = (x); \ + __r.__l[0] = __bswap_32 (__v.__l[1]); \ + __r.__l[1] = __bswap_32 (__v.__l[0]); \ + __r.__ll; })) +#endif diff --git a/libc/sysdeps/linux/vax/bits/endian.h b/libc/sysdeps/linux/vax/bits/endian.h new file mode 100644 index 0000000..9f0c4e2 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/endian.h @@ -0,0 +1,9 @@ +/* VAX is little endian */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN + +/*#define __FLOAT_WORD_ORDER __BIG_ENDIAN*/ diff --git a/libc/sysdeps/linux/vax/bits/fcntl.h b/libc/sysdeps/linux/vax/bits/fcntl.h new file mode 100644 index 0000000..971245d --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/fcntl.h @@ -0,0 +1,214 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +#endif + +/* XXX missing */ +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 5 /* Get record locking info. */ +#define F_SETLK 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW 7 /* Set record locking info (blocking). */ + +/* XXX missing */ +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ + +#ifdef __USE_BSD +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/vax/bits/ipc.h b/libc/sysdeps/linux/vax/bits/ipc.h new file mode 100644 index 0000000..c4e3735 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/ipc.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#define IPC_INFO 3 /* See ipcs. */ + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned short int uid; /* Owner's user ID. */ + unsigned short int gid; /* Owner's group ID. */ + unsigned short int cuid; /* Creator's user ID. */ + unsigned short int cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + }; diff --git a/libc/sysdeps/linux/vax/bits/kernel_stat.h b/libc/sysdeps/linux/vax/bits/kernel_stat.h new file mode 100644 index 0000000..2b5cb28 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/kernel_stat.h @@ -0,0 +1,60 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO 1 + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_atime; + unsigned long __pad5; + unsigned long st_mtime; + unsigned long __pad6; + unsigned long st_ctime; + unsigned long __pad7; /* will be high 32 bits of ctime someday */ + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/libc/sysdeps/linux/vax/bits/kernel_types.h b/libc/sysdeps/linux/vax/bits/kernel_types.h new file mode 100644 index 0000000..aef74b5 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/kernel_types.h @@ -0,0 +1,45 @@ +#ifndef _VAX_POSIX_TYPES_H +#define _VAX_POSIX_TYPES_H +/* + * Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _VAX_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/vax/bits/machine-gmon.h b/libc/sysdeps/linux/vax/bits/machine-gmon.h new file mode 100644 index 0000000..841518f --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/machine-gmon.h @@ -0,0 +1,41 @@ +/* i386-specific implementation of profiling support. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* We need a special version of the `mcount' function since for ix86 it + must not clobber any register. This has several reasons: + - there is a bug in gcc as of version 2.7.2.2 which prohibits the + use of profiling together with nested functions + - the ELF `fixup' function uses GCC's regparm feature + - some (future) systems might want to pass parameters in registers. */ + +/* We must not pollute the global namespace. */ +#define mcount_internal __mcount_internal + +extern void mcount_internal (u_long frompc, u_long selfpc); + +#define _MCOUNT_DECL(frompc, selfpc) \ +void __attribute__ (( regparm (2) )) mcount_internal (u_long frompc, u_long selfpc) + + +/* Define MCOUNT as empty since we have the implementation in another + file. */ +#define MCOUNT diff --git a/libc/sysdeps/linux/vax/bits/mman.h b/libc/sysdeps/linux/vax/bits/mman.h new file mode 100644 index 0000000..e29dfcc --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/mman.h @@ -0,0 +1,94 @@ +/* Definitions for POSIX memory map interface. Linux/i386 version. + Copyright (C) 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 /* Mapping address may change. */ +# define MREMAP_FIXED 2 /* Fifth argument sets new address. */ +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/vax/bits/sem.h b/libc/sysdeps/linux/vax/bits/sem.h new file mode 100644 index 0000000..c5c04ba --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/vax/bits/setjmp.h b/libc/sysdeps/linux/vax/bits/setjmp.h new file mode 100644 index 0000000..68a1b32 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/setjmp.h @@ -0,0 +1,37 @@ +/* Define the machine-dependent type `jmp_buf'. Vax version. */ + +#ifndef _SETJMP_H +# error "Never include directly; use instead." +#endif + +/* we want to save enough that we can use this to fool RET, + * So we basically save all of the CALLS stack frame. Plus regs. */ +#ifndef _ASM +typedef int __jmp_buf[16]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf[4])) +/* + jmp_buf layout. jmp_buf[0] + void *__cond; The condition handler + void *__psw; mask and PSW bits + void *__ap; argument pointer + void *__fp; frame pointer + void *__pc; program counter + no need to save r0 + void *__r1; regs, r0->r11. + void *__r2; regs, r0->r11. + void *__r3; regs, r0->r11. + void *__r4; regs, r0->r11. + void *__r5; regs, r0->r11. + void *__r6; regs, r0->r11. + void *__r7; regs, r0->r11. + void *__r8; regs, r0->r11. + void *__r9; regs, r0->r11. + void *__rA; regs, r0->r11. + void *__rB; regs, r0->r11. +*/ + diff --git a/libc/sysdeps/linux/vax/bits/shm.h b/libc/sysdeps/linux/vax/bits/shm.h new file mode 100644 index 0000000..191709f --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/shm.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + int shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __ipc_pid_t shm_cpid; /* pid of creator */ + __ipc_pid_t shm_lpid; /* pid of last shmop */ + unsigned short int shm_nattch; /* number of current attaches */ + unsigned short int __shm_npages; /* size of segment (pages) */ + unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__attaches; /* descriptors for attaches */ + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ + +struct shminfo + { + int shmmax; + int shmmin; + int shmmni; + int shmseg; + int shmall; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/vax/bits/sigcontext.h b/libc/sysdeps/linux/vax/bits/sigcontext.h new file mode 100644 index 0000000..97cbf4b --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/sigcontext.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. */ +# define sigcontext_struct sigcontext + +# include +#endif diff --git a/libc/sysdeps/linux/vax/bits/stackinfo.h b/libc/sysdeps/linux/vax/bits/stackinfo.h new file mode 100644 index 0000000..4bdad49 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/stackinfo.h @@ -0,0 +1,7 @@ +#ifndef _VAX_BITS_STACKINFO_H +#define _VAX_BITS_STACKINFO_H + +/* On VAXen, the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* _VAX_BITS_STACKINFO_H */ diff --git a/libc/sysdeps/linux/vax/bits/statfs.h b/libc/sysdeps/linux/vax/bits/statfs.h new file mode 100644 index 0000000..31ae564 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/statfs.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t*/ + +struct statfs + { + int f_type; + int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + int f_namelen; + int f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + int f_type; + int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + int f_namelen; + int f_spare[6]; + }; +#endif diff --git a/libc/sysdeps/linux/vax/bits/syscalls.h b/libc/sysdeps/linux/vax/bits/syscalls.h new file mode 100644 index 0000000..101aacb --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/syscalls.h @@ -0,0 +1,258 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall_return +#define _syscall_return(type) \ + do { \ + if ((unsigned long) (_sc_ret) >= (unsigned long) (-125)) { \ + __set_errno(-_sc_ret); \ + _sc_ret = -1; \ + } \ + \ + return (type) (_sc_ret); \ + } while (0) + +#define _syscall_clobbers \ + "r1", "r2", "r3", "r4", \ + "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11" + +#ifdef _syscall0 +# undef _syscall0 +#endif +#define _syscall0(type, name) \ +type name (void) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl $0x0 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $4, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall1 +# undef _syscall1 +#endif +#define _syscall1(type, name, type1, arg1) \ +type name (type1 arg1) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %2 \n" \ + " pushl $0x1 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $8, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall2 +# undef _syscall2 +#endif +#define _syscall2(type, name, type1, arg1, type2, arg2) \ +type name (type1 arg1, \ + type2 arg2) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x2 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $12, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall3 +# undef _syscall3 +#endif +#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x3 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $16, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall4 +# undef _syscall4 +#endif +#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x4 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $20, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall5 +# undef _syscall5 +#endif +#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4, \ + type5 arg5) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %6 \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x5 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $24, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4), \ + "m" (arg5) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall6 +# undef _syscall6 +#endif +#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4, \ + type5 arg5, \ + type6 arg6) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %7 \n" \ + " pushl %6 \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x6 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $28, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4), \ + "m" (arg5), \ + "m" (arg6) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h b/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h new file mode 100644 index 0000000..eda49b8 --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "halt" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#undef __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/vax/bits/wordsize.h b/libc/sysdeps/linux/vax/bits/wordsize.h new file mode 100644 index 0000000..62dad0c --- /dev/null +++ b/libc/sysdeps/linux/vax/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/vax/brk.c b/libc/sysdeps/linux/vax/brk.c new file mode 100644 index 0000000..47fd3e5 --- /dev/null +++ b/libc/sysdeps/linux/vax/brk.c @@ -0,0 +1,54 @@ +/* brk system call for Linux/VAX. + Copyright (C) 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = NULL; + +libc_hidden_proto(brk) +int +brk (void *addr) +{ + register unsigned long int result __asm__ ("%%r0"); + + __asm__ ( + " pushl %%ap \n" /* Start frame */ + " pushl %2 \n" /* New top address we wish to get */ + " pushl $1 \n" /* One argument */ + " movl %%sp, %%ap \n" /* Finish frame */ + " chmk %1 \n" /* Perform the system call */ + " addl2 $8, %%sp \n" /* Remove pushed arg */ + " movl (%%sp)+, %%ap \n" /* Get back %AP */ + : "=r" (result) + : "0" (__NR_brk), + "g" (addr)); + + if ((void *) result < addr) { + __set_errno (ENOMEM); + return -1; + } else + __curbrk = (void *) result; + + return 0; +} +libc_hidden_def(brk) + diff --git a/libc/sysdeps/linux/vax/clone.S b/libc/sysdeps/linux/vax/clone.S new file mode 100644 index 0000000..086adc6 --- /dev/null +++ b/libc/sysdeps/linux/vax/clone.S @@ -0,0 +1,85 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include + +#warning "This file contains a hardcoded constant for SYS_clone" + +.section .rodata + .align 2 +.LC0: .long 120 /* SYS_clone */ +.align 4 +.text +.type clone,@function +.globl clone; +clone: + .word 0x0040 + /* subl2 $8, %sp */ + movl 4(%ap), %r1 + movl 8(%ap), %r0 + mcoml $21, %r6 + + /* Sanity check args. */ + tstl %r1 + jeql CLONE_ERROR_LABEL + tstl %r0 + jeql CLONE_ERROR_LABEL + + /* Need to setup the child stack the same as the parent. */ + subl2 $24, %r0 + movl 16(%ap), 20(%r0) + movl %r1, 16(%r0) + movl %r0, %r1 + addl2 $16, %r1 + movl %r1, 12(%r0) + + /* Do the system call. */ + pushl %ap + pushl %r0 + pushl 12(%ap) + pushl $0x2 + movl %sp, %ap + chmk .LC0 /* %r0 .LC0 -4(%fp) -8(%fp) */ + addl2 $12, %sp + movl (%sp)+, %ap + movl %r0, %r6 + jneq CLONE_ERROR_LABEL + + movl $0, %fp + pushl 4(%ap) + movl (%r1), %r0 + calls $1, (%r0) + pushl %r0 + calls $1, HIDDEN_JUMPTARGET(_exit) + +CLONE_ERROR_LABEL: + cmpl %r6, $-126 /* -ENOKEY?!?! Fuck, this must be wrong! FIXME */ + jlequ CLONE_RETURN_LABEL + calls $0, __errno_location + mnegl %r6, (%r0) + mcoml $0, %r6 + movl %r6, %r0 + ret + +CLONE_RETURN_LABEL: + ret + +.size clone,.-clone + diff --git a/libc/sysdeps/linux/vax/crt1.S b/libc/sysdeps/linux/vax/crt1.S new file mode 100644 index 0000000..7096098 --- /dev/null +++ b/libc/sysdeps/linux/vax/crt1.S @@ -0,0 +1,73 @@ +/* + * crt0 for VAX + */ + +/* + * Program stack looks like: + * sp-> argc argument counter (integer) + * argv[0] program name (pointer) + * argv[1...N] program args (pointers) + * argv[argc-1] end of args (integer) + * NULL + * env[0...N] environment variables (pointers) + * NULL + */ + +#include + +.text +.align 4 + +.global __start +__start: +.global _start +_start: + /* Kernel uses a_interp + 2, so __start isn't exactly CALLSed, */ + /* but we need to have two bytes here, so we use NOPs. This */ + /* won't hurt, though R0 would be invalid to push, but at */ + /* lease this looks like a real function. */ + .word 0x0101 + + movl $0, %fp /* FP = 0, since this is the */ + /* top-most stack frame */ + movl %sp, %r0 /* R0 = %sp */ + movl (%sp)+, %r4 /* R4 = argc */ + movl %sp, %r3 /* R3 = argv = &argv[0] */ + +#if (defined L_crt1 || defined L_gcrt1) && defined __UCLIBC_CTOR_DTOR__ + pushl %r0 /* stack_end */ + pushl $0 /* rtld_fini. This is probably needed for the */ + /* case where a dynamic linker is involved. So */ + /* this is an open FIXME that needs to be */ + /* addressed at some time... */ + pushl $_fini + pushl $_init + pushl %r3 /* Argument pointer */ + pushl %r4 /* And the argument count */ + pushl $main /* main() */ + + /* We need to call __uClibc_main which should not return. + * __uClibc_main (int (*main) (int, char **, char **), + * int argc, + * char **argv, + * void (*init) (void), + * void (*fini) (void), + * void (*rtld_fini) (void), + * void *stack_end); + */ + calls $7, __uClibc_main +#else /* FIXME: THIS IS BROKEN!!! */ + /* start to load the arguments from the stack */ + /* arguments are on ap stack */ + pushl %r2 + pushl %r3 + pushl %r4 + + calls $3, __uClibc_main +#endif + + /* The above __uClibc_start_main() shouldn't ever return. If it */ + /* does, we just crash. */ + halt +.align 2 + diff --git a/libc/sysdeps/linux/vax/crti.S b/libc/sysdeps/linux/vax/crti.S new file mode 100644 index 0000000..0056478 --- /dev/null +++ b/libc/sysdeps/linux/vax/crti.S @@ -0,0 +1,21 @@ + .file "initfini.c" + .version "01.01" +gcc2_compiled.: +__gnu_compiled_c: + .section .init + .align 1 +.globl _init + .type _init,@function +_init: + .word 0x0000 + + .align 1 + + .section .fini + .align 1 +.globl _fini + .type _fini,@function +_fini: + .word 0x0000 + .align 1 + .ident "GCC: (GNU) 2.95.2 19991024 (release) (Linux/VAX CVS)" diff --git a/libc/sysdeps/linux/vax/crtn.S b/libc/sysdeps/linux/vax/crtn.S new file mode 100644 index 0000000..6ca5c4f --- /dev/null +++ b/libc/sysdeps/linux/vax/crtn.S @@ -0,0 +1,21 @@ + .file "initfini.c" + .version "01.01" +gcc2_compiled.: +__gnu_compiled_c: + + .section .init + .align 1 +.globl _init + .type _init,@function + ret +.Lfe2: + .size _init,.Lfe2-_init + + .section .fini + .align 1 +.globl _fini + .type _fini,@function + ret +.Lfe3: + .size _fini,.Lfe3-_fini + .ident "GCC: (GNU) 2.95.2 19991024 (release) (Linux/VAX CVS)" diff --git a/libc/sysdeps/linux/vax/mmap.c b/libc/sysdeps/linux/vax/mmap.c new file mode 100644 index 0000000..28e4077 --- /dev/null +++ b/libc/sysdeps/linux/vax/mmap.c @@ -0,0 +1,11 @@ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) +_syscall6 (void *, mmap, void *, start, size_t, length, int, prot, int, flags, + int, fd, off_t, offset) +libc_hidden_def(mmap) + diff --git a/libc/sysdeps/linux/vax/setjmp.S b/libc/sysdeps/linux/vax/setjmp.S new file mode 100644 index 0000000..bdbde4b --- /dev/null +++ b/libc/sysdeps/linux/vax/setjmp.S @@ -0,0 +1,39 @@ + +/* + * setjmp.S atp. Sept. 2001 + * Jan-Benedict Glaw 2006 + * + * Save regs and info needed for a longjmp + */ + +.globl __sigsetjmp +.align 4 +__sigsetjmp: + .word 0x0000 /* We look after reg saving here - this */ + /* must match longjmp. */ + movl 0x4(%ap), %r0 /* Our scratch reg */ + /* kenn would probably use movq here. :-) */ + movl %r1, 0x14(%r0) /* save regs */ + movl %r2, 0x18(%r0) + movl %r3, 0x1c(%r0) + movl %r4, 0x20(%r0) + movl %r5, 0x24(%r0) + movl %r6, 0x28(%r0) + movl %r7, 0x2c(%r0) + movl %r8, 0x30(%r0) + movl %r9, 0x34(%r0) + movl %r10, 0x38(%r0) + movl %r11, 0x3c(%r0) + /* Now save our call frame */ + movl (%fp), (%r0) /* Condition handler (for VMS emulation) */ + movl 0x4(%fp), 0x4(%r0) /* psw */ + movl 0x8(%fp), 0x8(%r0) /* ap */ + movl 0xc(%fp), 0xc(%r0) /* fp */ + movl 0x10(%fp), 0x10(%r0) /* pc */ + /* Call the sigjmp save routine */ + pushl 8(%ap) + pushl %r0 + calls $2, __sigjmp_save + /* Done */ + ret + diff --git a/libc/sysdeps/linux/vax/sys/procfs.h b/libc/sysdeps/linux/vax/sys/procfs.h new file mode 100644 index 0000000..9c23350 --- /dev/null +++ b/libc/sysdeps/linux/vax/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_regs_struct elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/vax/sys/ucontext.h b/libc/sysdeps/linux/vax/sys/ucontext.h new file mode 100644 index 0000000..f57b91e --- /dev/null +++ b/libc/sysdeps/linux/vax/sys/ucontext.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 37 +#define NFPREG 33 + +/* Container for all general registers. */ +/* gregset_t must be an array. The below declared array corresponds to: +typedef struct gregset { + greg_t g_regs[32]; + greg_t g_hi; + greg_t g_lo; + greg_t g_pad[3]; +} gregset_t; */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + union { + double fp_dregs[32]; + struct { + float _fp_fregs; + unsigned int _fp_pad; + } fp_fregs[32]; + } fp_r; + unsigned int fp_csr; + unsigned int fp_pad; +} fpregset_t; + + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/x86_64/Makefile b/libc/sysdeps/linux/x86_64/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/x86_64/Makefile.arch b/libc/sysdeps/linux/x86_64/Makefile.arch new file mode 100644 index 0000000..b6ad71c --- /dev/null +++ b/libc/sysdeps/linux/x86_64/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c sigaction.c __syscall_error.c mmap.c + +SSRC := \ + __longjmp.S vfork.S setjmp.S syscall.S bsd-setjmp.S bsd-_setjmp.S clone.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/x86_64/__longjmp.S b/libc/sysdeps/linux/x86_64/__longjmp.S new file mode 100644 index 0000000..db2928b --- /dev/null +++ b/libc/sysdeps/linux/x86_64/__longjmp.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. + void __longjmp (__jmp_buf env, int val). */ +.global __longjmp +.type __longjmp,%function +__longjmp: + /* Restore registers. */ + movq (JB_RBX*8)(%rdi),%rbx + movq (JB_RBP*8)(%rdi),%rbp + movq (JB_R12*8)(%rdi),%r12 + movq (JB_R13*8)(%rdi),%r13 + movq (JB_R14*8)(%rdi),%r14 + movq (JB_R15*8)(%rdi),%r15 + /* Set return value for setjmp. */ + test %esi,%esi + mov $01,%eax + cmove %eax,%esi + mov %esi, %eax + movq (JB_PC*8)(%rdi),%rdx + movq (JB_RSP*8)(%rdi),%rsp + jmpq *%rdx +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/x86_64/__syscall_error.c b/libc/sysdeps/linux/x86_64/__syscall_error.c new file mode 100644 index 0000000..448f509 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/__syscall_error.c @@ -0,0 +1,21 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__ ("%rcx"); + __asm__ ("mov %rax, %rcx\n\t" + "neg %rcx"); + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/x86_64/bits/atomic.h b/libc/sysdeps/linux/x86_64/bits/atomic.h new file mode 100644 index 0000000..04870cb --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/atomic.h @@ -0,0 +1,324 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "q" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgq %q2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" ((long) (newval)), "m" (*mem), \ + "0" ((long) (oldval))); \ + ret; }) + + +/* Note that we need no lock prefix. */ +#define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ ("xchgb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ ("xchgw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ ("xchgl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else \ + __asm__ __volatile__ ("xchgq %q0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" ((long) (newvalue)), "m" (*mem)); \ + result; }) + + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "xaddq %q0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" ((long) (value)), "m" (*mem)); \ + result; }) + + +#define atomic_add(mem, value) \ + (void) ({ if (__builtin_constant_p (value) && (value) == 1) \ + atomic_increment (mem); \ + else if (__builtin_constant_p (value) && (value) == 1) \ + atomic_decrement (mem); \ + else if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q1, %0" \ + : "=m" (*mem) \ + : "ir" ((long) (value)), "m" (*mem)); \ + }) + + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" ((long) (value)), "m" (*mem)); \ + __result; }) + + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" ((long) (value)), "m" (*mem)); \ + __result; }) + + +#define atomic_increment(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "incq %q0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + }) + + +#define atomic_increment_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "incq %q0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + __result; }) + + +#define atomic_decrement(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "decq %q0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + }) + + +#define atomic_decrement_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "decq %q0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + __result; }) + + +#define atomic_bit_set(mem, bit) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (__builtin_constant_p (bit) && (bit) < 32) \ + __asm__ __volatile__ (LOCK_PREFIX "orq %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "i" (1L << (bit))); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "orq %q2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "r" (1UL << (bit))); \ + }) + + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "btsb %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "btsw %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "btsq %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + __result; }) + + +#define atomic_delay() __asm__ ("rep; nop") diff --git a/libc/sysdeps/linux/x86_64/bits/byteswap.h b/libc/sysdeps/linux/x86_64/bits/byteswap.h new file mode 100644 index 0000000..e1c861c --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/byteswap.h @@ -0,0 +1,133 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +#include + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +#else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +#endif + + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__ \ + || defined __pentiumpro__ || defined __pentium4__ \ + || defined __k8__ || defined __athlon__ \ + || defined __k6__) +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# endif +#else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# if __WORDSIZE == 64 +# define __bswap_64(x) \ + (__extension__ \ + ({ register unsigned long __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_64 (__x); \ + else \ + __asm__ ("bswap %q0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# else +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +# endif +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/x86_64/bits/endian.h b/libc/sysdeps/linux/x86_64/bits/endian.h new file mode 100644 index 0000000..2f59ead --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/endian.h @@ -0,0 +1,7 @@ +/* x86_64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/libc/sysdeps/linux/x86_64/bits/environments.h b/libc/sysdeps/linux/x86_64/bits/environments.h new file mode 100644 index 0000000..a51a564 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/environments.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never include this file directly. Use instead" +#endif + +#include + +/* This header should define the following symbols under the described + situations. A value `1' means that the model is always supported, + `-1' means it is never supported. Undefined means it cannot be + statically decided. + + _POSIX_V6_ILP32_OFF32 32bit int, long, pointers, and off_t type + _POSIX_V6_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type + + _POSIX_V6_LP64_OFF32 64bit long and pointers and 32bit off_t type + _POSIX_V6_LPBIG_OFFBIG 64bit long and pointers and large off_t type + + The macros _XBS5_ILP32_OFF32, _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and + _XBS5_LPBIG_OFFBIG were used in previous versions of the Unix standard + and are available only for compatibility. +*/ + +#if __WORDSIZE == 64 + +/* Environments with 32-bit wide pointers are optionally provided. + Therefore following macros aren't defined: + # undef _POSIX_V6_ILP32_OFF32 + # undef _POSIX_V6_ILP32_OFFBIG + # undef _XBS5_ILP32_OFF32 + # undef _XBS5_ILP32_OFFBIG + and users need to check at runtime. */ + +/* We also have no use (for now) for an environment with bigger pointers + and offsets. */ +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* By default we have 64-bit wide `long int', pointers and `off_t'. */ +# define _POSIX_V6_LP64_OFF64 1 +# define _XBS5_LP64_OFF64 1 + +#else /* __WORDSIZE == 32 */ + +/* By default we have 32-bit wide `int', `long int', pointers and `off_t' + and all platforms support LFS. */ +# define _POSIX_V6_ILP32_OFF32 1 +# define _POSIX_V6_ILP32_OFFBIG 1 +# define _XBS5_ILP32_OFF32 1 +# define _XBS5_ILP32_OFFBIG 1 + +/* We optionally provide an environment with the above size but an 64-bit + side `off_t'. Therefore we don't define _XBS5_ILP32_OFFBIG. */ + +/* Environments with 64-bit wide pointers can be provided, + so these macros aren't defined: + # undef _POSIX_V6_LP64_OFF64 + # undef _POSIX_V6_LPBIG_OFFBIG + # undef _XBS5_LP64_OFF64 + # undef _XBS5_LPBIG_OFFBIG + and sysconf tests for it at runtime. */ + +#endif /* __WORDSIZE == 32 */ + +#define __ILP32_OFF32_CFLAGS "-m32" +#define __ILP32_OFFBIG_CFLAGS "-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" +#define __ILP32_OFF32_LDFLAGS "-m32" +#define __ILP32_OFFBIG_LDFLAGS "-m32" +#define __LP64_OFF64_CFLAGS "-m64" +#define __LP64_OFF64_LDFLAGS "-m64" diff --git a/libc/sysdeps/linux/x86_64/bits/fcntl.h b/libc/sysdeps/linux/x86_64/bits/fcntl.h new file mode 100644 index 0000000..42c790a --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/fcntl.h @@ -0,0 +1,255 @@ +/* O_*, F_*, FD_* bit values for Linux/x86-64. + Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# if 0 +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +# endif +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0100000 +# endif +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#if __WORDSIZE == 64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +/* Not necessary, we always have 64-bit offsets. */ +# define F_GETLK64 5 /* Get record locking info. */ +# define F_SETLK64 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 7 /* Set record locking info (blocking). */ +#else +# ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +# else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +# endif +# define F_GETLK64 12 /* Get record locking info. */ +# define F_SETLK64 13 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 14 /* Set record locking info (blocking). */ +#endif + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/x86_64/bits/fenv.h b/libc/sysdeps/linux/x86_64/bits/fenv.h new file mode 100644 index 0000000..11859f0 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/fenv.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by the `fstenv' + instruction and has additional fields for the contents of the MXCSR + register as written by the `stmxcsr' instruction. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +#if __WORDSIZE == 64 + unsigned int __mxcsr; +#endif + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/libc/sysdeps/linux/x86_64/bits/kernel_stat.h b/libc/sysdeps/linux/x86_64/bits/kernel_stat.h new file mode 100644 index 0000000..7dca5ff --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/kernel_stat.h @@ -0,0 +1,54 @@ +/* Ripped from linux/include/asm-x86_64/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _ASM_X86_64_STAT_H +#define _ASM_X86_64_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +#define STAT_HAVE_NSEC 1 + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + unsigned long st_rdev; + long st_size; + long st_blksize; + long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + long __unused[3]; +}; + +/* For 32bit emulation */ +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned int st_size; + unsigned int st_atime; + unsigned int st_mtime; + unsigned int st_ctime; +}; + +/* x86-64 stat64 is same as stat */ +#define kernel_stat64 kernel_stat + +#endif diff --git a/libc/sysdeps/linux/x86_64/bits/kernel_types.h b/libc/sysdeps/linux/x86_64/bits/kernel_types.h new file mode 100644 index 0000000..73f6ffb --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_X86_64_POSIX_TYPES_H +#define _ASM_X86_64_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _ASM_X86_64_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/x86_64/bits/mathdef.h b/libc/sysdeps/linux/x86_64/bits/mathdef.h new file mode 100644 index 0000000..7b16189 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/mathdef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# include + +# if __WORDSIZE == 64 || (defined __FLT_EVAL_METHOD__ && __FLT_EVAL_METHOD__ == 0) +/* The x86-64 architecture computes values with the precission of the + used type. Similarly for -m32 -mfpmath=sse. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated + as `double'. */ +# else +/* The ix87 FPUs evaluate all values in the 80 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +#endif /* ISO C99 */ diff --git a/libc/sysdeps/linux/x86_64/bits/mathinline.h b/libc/sysdeps/linux/x86_64/bits/mathinline.h new file mode 100644 index 0000000..39d11b6 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/mathinline.h @@ -0,0 +1,53 @@ +/* Inline math functions for x86-64. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +#endif diff --git a/libc/sysdeps/linux/x86_64/bits/mman.h b/libc/sysdeps/linux/x86_64/bits/mman.h new file mode 100644 index 0000000..535c9ed --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/mman.h @@ -0,0 +1,104 @@ +/* Definitions for POSIX memory map interface. Linux/x86_64 version. + Copyright (C) 2001, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/x86_64/bits/msq.h b/libc/sysdeps/linux/x86_64/bits/msq.h new file mode 100644 index 0000000..422218a --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/msq.h @@ -0,0 +1,83 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned long int __unused1; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned long int __unused2; +#endif + __time_t msg_ctime; /* time of last change */ +#if __WORDSIZE == 32 + unsigned long int __unused3; +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/x86_64/bits/sem.h b/libc/sysdeps/linux/x86_64/bits/sem.h new file mode 100644 index 0000000..9b1d993 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# 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; +}; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/x86_64/bits/setjmp.h b/libc/sysdeps/linux/x86_64/bits/setjmp.h new file mode 100644 index 0000000..515d769 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/setjmp.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. x86-64 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +#if __WORDSIZE == 64 + +/* We only need to save callee-saved registers plus stackpointer and + program counter. */ +# if defined __USE_MISC || defined _ASM +# define JB_RBX 0 +# define JB_RBP 1 +# define JB_R12 2 +# define JB_R13 3 +# define JB_R14 4 +# define JB_R15 5 +# define JB_RSP 6 +# define JB_PC 7 +# define JB_SIZE (8*8) +# endif + +#else + +# if defined __USE_MISC || defined _ASM +# define JB_BX 0 +# define JB_SI 1 +# define JB_DI 2 +# define JB_BP 3 +# define JB_SP 4 +# define JB_PC 5 +# define JB_SIZE 24 +# endif + +#endif + +#ifndef _ASM + +# if __WORDSIZE == 64 +typedef long int __jmp_buf[8]; +# else +typedef int __jmp_buf[6]; +# endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +# if __WORDSIZE == 64 +# define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_RSP]) +# else +# define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) +# endif +#endif + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/x86_64/bits/shm.h b/libc/sysdeps/linux/x86_64/bits/shm.h new file mode 100644 index 0000000..3d8c05d --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/shm.h @@ -0,0 +1,110 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned long int __unused1; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned long int __unused2; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ +#if __WORDSIZE == 32 + unsigned long int __unused3; +#endif + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/x86_64/bits/sigcontext.h b/libc/sysdeps/linux/x86_64/bits/sigcontext.h new file mode 100644 index 0000000..c0d5fe7 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/sigcontext.h @@ -0,0 +1,159 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +struct _fpreg +{ + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _fpxreg +{ + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg +{ + __uint32_t element[4]; +}; + + + +#if __WORDSIZE == 32 + +struct _fpstate +{ + /* Regular FPU environment. */ + __uint32_t cw; + __uint32_t sw; + __uint32_t tag; + __uint32_t ipoff; + __uint32_t cssel; + __uint32_t dataoff; + __uint32_t datasel; + struct _fpreg _st[8]; + unsigned short status; + unsigned short magic; + + /* FXSR FPU environment. */ + __uint32_t _fxsr_env[6]; + __uint32_t mxcsr; + __uint32_t reserved; + struct _fpxreg _fxsr_st[8]; + struct _xmmreg _xmm[8]; + __uint32_t padding[56]; +}; + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. Some packages have come to rely on + sigcontext_struct being defined on 32-bit x86, so define this for + their benefit. */ +# define sigcontext_struct sigcontext +#endif + +struct sigcontext +{ + unsigned short gs, __gsh; + unsigned short fs, __fsh; + unsigned short es, __esh; + unsigned short ds, __dsh; + unsigned long edi; + unsigned long esi; + unsigned long ebp; + unsigned long esp; + unsigned long ebx; + unsigned long edx; + unsigned long ecx; + unsigned long eax; + unsigned long trapno; + unsigned long err; + unsigned long eip; + unsigned short cs, __csh; + unsigned long eflags; + unsigned long esp_at_signal; + unsigned short ss, __ssh; + struct _fpstate * fpstate; + unsigned long oldmask; + unsigned long cr2; +}; + +#else /* __WORDSIZE == 64 */ + +struct _fpstate +{ + /* FPU environment matching the 64-bit FXSAVE layout. */ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _fpxreg _st[8]; + struct _xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +struct sigcontext +{ + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long rdi; + unsigned long rsi; + unsigned long rbp; + unsigned long rbx; + unsigned long rdx; + unsigned long rax; + unsigned long rcx; + unsigned long rsp; + unsigned long rip; + unsigned long eflags; + unsigned short cs; + unsigned short gs; + unsigned short fs; + unsigned short __pad0; + unsigned long err; + unsigned long trapno; + unsigned long oldmask; + unsigned long cr2; + struct _fpstate * fpstate; + unsigned long __reserved1 [8]; +}; + +#endif /* __WORDSIZE == 64 */ + +#endif /* _BITS_SIGCONTEXT_H */ diff --git a/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h b/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h new file mode 100644 index 0000000..11493c5 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT siginfo_t *_si, struct ucontext * +#define SIGCONTEXT_EXTRA_ARGS _si, +#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RIP]) +#define GET_FRAME(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RBP]) +#define GET_STACK(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RSP]) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/linux/x86_64/bits/stackinfo.h b/libc/sysdeps/linux/x86_64/bits/stackinfo.h new file mode 100644 index 0000000..60668d1 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86_64 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/x86_64/bits/stat.h b/libc/sysdeps/linux/x86_64/bits/stat.h new file mode 100644 index 0000000..3a9c774 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/stat.h @@ -0,0 +1,203 @@ +/* Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 + +#if __WORDSIZE == 32 +# define _STAT_VER_SVR4 2 +# define _STAT_VER_LINUX 3 + +/* i386 versions of the `xmknod' interface. */ +# define _MKNOD_VER_LINUX 1 +# define _MKNOD_VER_SVR4 2 +# define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ +#else +# define _STAT_VER_LINUX 1 + +/* x86-64 versions of the `xmknod' interface. */ +# define _MKNOD_VER_LINUX 0 +#endif + +#define _STAT_VER _STAT_VER_LINUX + +struct stat + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; +#endif +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif +#if __WORDSIZE == 32 + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ +#else + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ +#endif + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ +#if __WORDSIZE == 64 + int pad0; +#endif + __dev_t st_rdev; /* Device number, if device. */ +#if __WORDSIZE == 32 + unsigned short int __pad2; +#endif +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#if __WORDSIZE == 64 + long int __unused[3]; +#else +# ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +# else + __ino64_t st_ino; /* File serial number. */ +# endif +#endif + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 has the same shape as stat for x86-64. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ +#else + unsigned int __pad1; + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ +#endif + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ +#if __WORDSIZE == 64 + int pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#else + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#if __WORDSIZE == 64 + long int __unused[3]; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/x86_64/bits/syscalls.h b/libc/sysdeps/linux/x86_64/bits/syscalls.h new file mode 100644 index 0000000..80f4259 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/syscalls.h @@ -0,0 +1,213 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc-2.2.5/sysdeps/unix/sysv/linux/x86_64/sysdep.h +*/ + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef _syscall6 +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +return (type) (INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6)); \ +} + +/* The Linux/x86-64 kernel expects the system call parameters in + registers according to the following table: + + syscall number rax + arg 1 rdi + arg 2 rsi + arg 3 rdx + arg 4 r10 + arg 5 r8 + arg 6 r9 + + The Linux kernel uses and destroys internally these registers: + return address from + syscall rcx + additionally clobered: r12-r15,rbx,rbp + eflags from syscall r11 + + Normal function call, including calls to the system call stub + functions in the libc, get the first six parameters passed in + registers and the seventh parameter and later on the stack. The + register use is as follows: + + system call number in the DO_CALL macro + arg 1 rdi + arg 2 rsi + arg 3 rdx + arg 4 rcx + arg 5 r8 + arg 6 r9 + + We have to take care that the stack is aligned to 16 bytes. When + called the stack is not aligned since the return address has just + been pushed. + + + Syscalls of more than 6 arguments are not supported. */ + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + movq $SYS_ify (syscall_name), %rax; \ + syscall; + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 movq %rcx, %r10; +#define DOARGS_5 DOARGS_4 +#define DOARGS_6 DOARGS_5 + +/* Define a macro which expands inline into the wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned long _resultvar = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_resultvar, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_resultvar, )); \ + _resultvar = (unsigned long) -1; \ + } \ + (long) _resultvar; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + unsigned long resultvar; \ + LOAD_ARGS_##nr (args) \ + LOAD_REGS_##nr \ + __asm__ __volatile__ ( \ + "syscall\n\t" \ + : "=a" (resultvar) \ + : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ + (long) resultvar; }) +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned long) (val) >= -4095L) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#define LOAD_ARGS_0() +#define LOAD_REGS_0 +#define ASM_ARGS_0 + +#define LOAD_ARGS_1(a1) \ + long int __arg1 = (long) (a1); \ + LOAD_ARGS_0 () +#define LOAD_REGS_1 \ + register long int _a1 __asm__ ("rdi") = __arg1; \ + LOAD_REGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) + +#define LOAD_ARGS_2(a1, a2) \ + long int __arg2 = (long) (a2); \ + LOAD_ARGS_1 (a1) +#define LOAD_REGS_2 \ + register long int _a2 __asm__ ("rsi") = __arg2; \ + LOAD_REGS_1 +#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) + +#define LOAD_ARGS_3(a1, a2, a3) \ + long int __arg3 = (long) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define LOAD_REGS_3 \ + register long int _a3 __asm__ ("rdx") = __arg3; \ + LOAD_REGS_2 +#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) + +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + long int __arg4 = (long) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define LOAD_REGS_4 \ + register long int _a4 __asm__ ("r10") = __arg4; \ + LOAD_REGS_3 +#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) + +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + long int __arg5 = (long) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define LOAD_REGS_5 \ + register long int _a5 __asm__ ("r8") = __arg5; \ + LOAD_REGS_4 +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5) + +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + long int __arg6 = (long) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define LOAD_REGS_6 \ + register long int _a6 __asm__ ("r9") = __arg6; \ + LOAD_REGS_5 +#define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h b/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h new file mode 100644 index 0000000..e3e2c83 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h @@ -0,0 +1,38 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "hlt" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/x86_64/bits/wordsize.h b/libc/sysdeps/linux/x86_64/bits/wordsize.h new file mode 100644 index 0000000..0cce4ea --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bits/wordsize.h @@ -0,0 +1,8 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __x86_64__ +# define __WORDSIZE 64 +/*# define __WORDSIZE_COMPAT32 1*/ +#else +# define __WORDSIZE 32 +#endif diff --git a/libc/sysdeps/linux/x86_64/brk.c b/libc/sysdeps/linux/x86_64/brk.c new file mode 100644 index 0000000..eddfd98 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/brk.c @@ -0,0 +1,46 @@ +/* brk system call for Linux/x86_64. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int brk (void *addr) +{ + void *__unbounded newbrk; + + __asm__ ("syscall\n" + : "=a" (newbrk) + : "0" (__NR_brk), "D" (__ptrvalue (addr)) + : "r11","rcx","memory"); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/x86_64/bsd-_setjmp.S b/libc/sysdeps/linux/x86_64/bsd-_setjmp.S new file mode 100644 index 0000000..81a4352 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bsd-_setjmp.S @@ -0,0 +1,29 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. i386 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global _setjmp +.type _setjmp,%function +_setjmp: + xorq %rsi, %rsi + jmp __sigsetjmp@PLT +.size _setjmp,.-_setjmp diff --git a/libc/sysdeps/linux/x86_64/bsd-setjmp.S b/libc/sysdeps/linux/x86_64/bsd-setjmp.S new file mode 100644 index 0000000..a906a61 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/bsd-setjmp.S @@ -0,0 +1,29 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. i386 version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global setjmp +.type setjmp,%function +setjmp: + movq $1, %rsi + jmp __sigsetjmp@PLT +.size setjmp,.-setjmp diff --git a/libc/sysdeps/linux/x86_64/clone.S b/libc/sysdeps/linux/x86_64/clone.S new file mode 100644 index 0000000..dc5eeb0 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/clone.S @@ -0,0 +1,114 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* The userland implementation is: + int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg), + the kernel entry is: + int clone (long flags, void *child_stack). + + The parameters are passed in register and on the stack from userland: + rdi: fn + rsi: child_stack + rdx: flags + rcx: arg + r8d: TID field in parent + r9d: thread pointer +%esp+8: TID field in child + + The kernel expects: + rax: system call number + rdi: flags + rsi: child_stack + rdx: TID field in parent + r10: TID field in child + r8: thread pointer */ + + +.text +.global clone +.type clone,%function +clone: + /* Sanity check arguments. */ + movq $-EINVAL,%rax + testq %rdi,%rdi /* no NULL function pointers */ + jz __syscall_error + testq %rsi,%rsi /* no NULL stack pointers */ + jz __syscall_error + + /* Insert the argument onto the new stack. */ + subq $16,%rsi + movq %rcx,8(%rsi) + + /* Save the function pointer. It will be popped off in the + child in the ebx frobbing below. */ + movq %rdi,0(%rsi) + + /* Do the system call. */ + movq %rdx, %rdi + movq %r8, %rdx + movq %r9, %r8 + movq 8(%rsp), %r10 + movl $__NR_clone,%eax + + syscall + + testq %rax,%rax + jl __syscall_error + jz .Lthread_start + +.Lpseudo_end: + ret + +.Lthread_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + +#ifdef RESET_PID + testq $CLONE_THREAD, %rdi + jne 1f + testq $CLONE_VM, %rdi + movl $-1, %eax + jne 2f + movl $__NR_getpid, %eax + syscall +2: movl %eax, %fs:PID + movl %eax, %fs:TID +1: +#endif + + /* Set up arguments for the function call. */ + popq %rax /* Function to call. */ + popq %rdi /* Argument. */ + call *%rax + /* Call exit with return value from function call. */ + movq %rax, %rdi + call HIDDEN_JUMPTARGET(_exit) + +.size clone,.-clone diff --git a/libc/sysdeps/linux/x86_64/crt1.S b/libc/sysdeps/linux/x86_64/crt1.S new file mode 100644 index 0000000..f6c1eb1 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/crt1.S @@ -0,0 +1,140 @@ +/* Startup code compliant to the ELF x86-64 ABI. + Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2001. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Originally based on glibc's sysdeps/x86_64/elf/start.S */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + %rdx Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %rsp The stack contains the arguments and environment: + 0(%rsp) argc + 8(%rsp) argv[0] + ... + (8*argc)(%rsp) NULL + (8*(argc+1))(%rsp) envp[0] + ... + NULL +*/ + +#include + +.text +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type __uClibc_main,%function +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +.type main,%function + +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + + /* Extract the arguments as encoded on the stack and set up + the arguments for __libc_start_main (int (*main) (int, char **, char **), + int argc, char *argv, + void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end). + The arguments are passed via registers and on the stack: + main: %rdi + argc: %rsi + argv: %rdx + init: %rcx + fini: %r8 + rtld_fini: %r9 + stack_end: stack. */ + + movq %rdx, %r9 /* Address of the shared library termination function. */ + popq %rsi /* Pop the argument count. */ + movq %rsp, %rdx /* argv starts just at the current stack top. */ + + /* Align the stack to a 16 byte boundary to follow the ABI. */ + andq $~15, %rsp + + pushq %rax /* Push garbage because we push 8 more bytes. */ + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushq %rsp + +#if defined(L_Scrt1) + /* Give address for main() */ + movq main@GOTPCREL(%rip), %rdi + + /* setup init/fini address */ + movq _init@GOTPCREL(%rip), %rcx + movq _fini@GOTPCREL(%rip), %r8 + + /* start the fun */ + call __uClibc_main@PLT +#else + /* Give address for main() */ + movq $main, %rdi + + /* setup init/fini address */ + movq $_init, %rcx + movq $_fini, %r8 + + /* start the fun */ + call __uClibc_main +#endif + + hlt /* Crash if somehow `exit' does return. */ +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/x86_64/crti.S b/libc/sysdeps/linux/x86_64/crti.S new file mode 100644 index 0000000..11491db --- /dev/null +++ b/libc/sysdeps/linux/x86_64/crti.S @@ -0,0 +1,16 @@ +/* glibc's sysdeps/x86_64/elf/initfini.c used for reference [PROLOG] */ + + + +.section .init +.global _init +.type _init, %function +_init: + subq $8, %rsp + + +.section .fini +.global _fini +.type _fini, %function +_fini: + subq $8, %rsp diff --git a/libc/sysdeps/linux/x86_64/crtn.S b/libc/sysdeps/linux/x86_64/crtn.S new file mode 100644 index 0000000..5b110d9 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/crtn.S @@ -0,0 +1,18 @@ +/* glibc's sysdeps/x86_64/elf/initfini.c used for reference [EPILOG] */ + +.file "initfini.c" + +.section .init +.global _init +.type _init, %function + addq $8, %rsp + ret +.size _init,.-_init + + +.section .fini +.global _fini +.type _fini, %function + addq $8, %rsp + ret +.size _fini, .-_fini diff --git a/libc/sysdeps/linux/x86_64/fpu_control.h b/libc/sysdeps/linux/x86_64/fpu_control.h new file mode 100644 index 0000000..6e9b3b3 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/fpu_control.h @@ -0,0 +1,103 @@ +/* FPU control word bits. x86-64 version. + Copyright (C) 1993,1995,1996,1997,1998,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + +/* Note that this file sets on x86-64 only the x87 FPU, it does not + touch the SSE unit. */ + +/* Here is the dirty part. Set up your 387 through the control word + * (cw) register. + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f which we use. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* libm requires double extended precision. */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x037f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x037f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/x86_64/mmap.c b/libc/sysdeps/linux/x86_64/mmap.c new file mode 100644 index 0000000..faaaab9 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/mmap.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc/x86_64 + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(mmap) + +_syscall6(void *, mmap, void *, start, size_t, length, int, prot, + int, flags, int, fd, off_t, offset) +libc_hidden_def(mmap) diff --git a/libc/sysdeps/linux/x86_64/setjmp.S b/libc/sysdeps/linux/x86_64/setjmp.S new file mode 100644 index 0000000..eb4b973 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/setjmp.S @@ -0,0 +1,45 @@ +/* setjmp for x86-64. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global __sigsetjmp +.type __sigsetjmp,%function +__sigsetjmp: + /* Save registers. */ + movq %rbx, (JB_RBX*8)(%rdi) + movq %rbp, (JB_RBP*8)(%rdi) + movq %r12, (JB_R12*8)(%rdi) + movq %r13, (JB_R13*8)(%rdi) + movq %r14, (JB_R14*8)(%rdi) + movq %r15, (JB_R15*8)(%rdi) + leaq 8(%rsp), %rdx /* Save SP as it will be after we return. */ + movq %rdx, (JB_RSP*8)(%rdi) + movq (%rsp), %rax /* Save PC we are returning to now. */ + movq %rax, (JB_PC*8)(%rdi) + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + jmp __sigjmp_save@PLT +#else + jmp __sigjmp_save +#endif +.size __sigsetjmp,.-__sigsetjmp diff --git a/libc/sysdeps/linux/x86_64/sigaction.c b/libc/sysdeps/linux/x86_64/sigaction.c new file mode 100644 index 0000000..aa5c0d4 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sigaction.c @@ -0,0 +1,150 @@ +/* POSIX.1 `sigaction' call for Linux/x86-64. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#include +#include +#include + +#include + +/* The difference here is that the sigaction structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include + +/* We do not globally define the SA_RESTORER flag so do it here. */ +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + +#ifdef __NR_rt_sigaction +/* Using the hidden attribute here does not change the code but it + helps to avoid warnings. */ +extern void restore_rt (void) __asm__ ("__restore_rt") attribute_hidden; +extern void restore (void) __asm__ ("__restore") attribute_hidden; + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + kact.sa_flags = act->sa_flags | SA_RESTORER; + + kact.sa_restorer = &restore_rt; + } + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + result = INLINE_SYSCALL (rt_sigaction, 4, + sig, act ? __ptrvalue (&kact) : NULL, + oact ? __ptrvalue (&koact) : NULL, _NSIG / 8); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} +#else + +extern void restore (void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + +#ifdef SIGCANCEL + if (sig == SIGCANCEL) { + __set_errno (EINVAL); + return -1; + } +#endif + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags | SA_RESTORER; + kact.sa_restorer = &restore; + } + + __asm__ __volatile__ ("syscall\n" + : "=a" (result) + : "0" (__NR_sigaction), "mr" (sig), + "c" (act ? __ptrvalue (&kact) : 0), + "d" (oact ? __ptrvalue (&koact) : 0)); + + if (result < 0) { + __set_errno(-result); + return -1; + } + + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} +#endif + +#ifndef LIBC_SIGACTION +libc_hidden_proto(sigaction) +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2 (name, syscall) +# define RESTORE2(name, syscall) \ +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " movq $" #syscall ", %rax\n" \ + " syscall\n" \ + ); +#ifdef __NR_rt_sigaction +/* The return code for realtime-signals. */ +RESTORE (restore_rt, __NR_rt_sigreturn) +#endif +#ifdef __NR_sigreturn +RESTORE (restore, __NR_sigreturn) +#endif diff --git a/libc/sysdeps/linux/x86_64/sys/debugreg.h b/libc/sysdeps/linux/x86_64/sys/debugreg.h new file mode 100644 index 0000000..8abbf75 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/debugreg.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DEBUGREG_H +#define _SYS_DEBUGREG_H 1 +#include + +/* Indicate the register numbers for a number of the specific + debug registers. Registers 0-3 contain the addresses we wish to trap on */ +#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ +#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ + +#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ +#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ + +/* Define a few things for the status register. We can use this to determine + which debugging register was responsible for the trap. The other bits + are either reserved or not of interest to us. */ + +#define DR_TRAP0 (0x1) /* db0 */ +#define DR_TRAP1 (0x2) /* db1 */ +#define DR_TRAP2 (0x4) /* db2 */ +#define DR_TRAP3 (0x8) /* db3 */ + +#define DR_STEP (0x4000) /* single-step */ +#define DR_SWITCH (0x8000) /* task switch */ + +/* Now define a bunch of things for manipulating the control register. + The top two bytes of the control register consist of 4 fields of 4 + bits - each field corresponds to one of the four debug registers, + and indicates what types of access we trap on, and how large the data + field is that we are looking at */ + +#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ +#define DR_CONTROL_SIZE 4 /* 4 control bits per register */ + +#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ +#define DR_RW_WRITE (0x1) +#define DR_RW_READ (0x3) + +#define DR_LEN_1 (0x0) /* Settings for data length to trap on */ +#define DR_LEN_2 (0x4) +#define DR_LEN_4 (0xC) +#define DR_LEN_8 (0x8) + +/* The low byte to the control register determine which registers are + enabled. There are 4 fields of two bits. One bit is "local", meaning + that the processor will reset the bit after a task switch and the other + is global meaning that we have to explicitly reset the bit. With linux, + you can use either one, since we explicitly zero the register when we enter + kernel mode. */ + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ +#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ + +#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ +#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ + +/* The second byte to the control register has a few special + things. */ + + + +#if __WORDSIZE == 64 +# define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */ +#else +# define DR_CONTROL_RESERVED (0x00FC00U) /* Reserved */ +#endif +#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ +#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ + +#endif /* sys/debugreg.h */ diff --git a/libc/sysdeps/linux/x86_64/sys/epoll.h b/libc/sysdeps/linux/x86_64/sys/epoll.h new file mode 100644 index 0000000..02672d3 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/epoll.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H 1 + +#include +#include + + +enum EPOLL_EVENTS + { + EPOLLIN = 0x001, +#define EPOLLIN EPOLLIN + EPOLLPRI = 0x002, +#define EPOLLPRI EPOLLPRI + EPOLLOUT = 0x004, +#define EPOLLOUT EPOLLOUT + EPOLLRDNORM = 0x040, +#define EPOLLRDNORM EPOLLRDNORM + EPOLLRDBAND = 0x080, +#define EPOLLRDBAND EPOLLRDBAND + EPOLLWRNORM = 0x100, +#define EPOLLWRNORM EPOLLWRNORM + EPOLLWRBAND = 0x200, +#define EPOLLWRBAND EPOLLWRBAND + EPOLLMSG = 0x400, +#define EPOLLMSG EPOLLMSG + EPOLLERR = 0x008, +#define EPOLLERR EPOLLERR + EPOLLHUP = 0x010, +#define EPOLLHUP EPOLLHUP + EPOLLONESHOT = (1 << 30), +#define EPOLLONESHOT EPOLLONESHOT + EPOLLET = (1 << 31) +#define EPOLLET EPOLLET + }; + + +/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ +#define EPOLL_CTL_ADD 1 /* Add a file decriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file decriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file decriptor epoll_event structure. */ + + +typedef union epoll_data +{ + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event +{ + uint32_t events; /* Epoll events */ + epoll_data_t data; /* User data variable */ +} __attribute__ ((__packed__)); + + +__BEGIN_DECLS + +/* Creates an epoll instance. Returns an fd for the new instance. + The "size" parameter is a hint specifying the number of file + descriptors to be associated with the new instance. The fd + returned by epoll_create() should be closed with close(). */ +extern int epoll_create (int __size) __THROW; + + +/* Manipulate an epoll instance "epfd". Returns 0 in case of success, + -1 in case of error ( the "errno" variable will contain the + specific error code ) The "op" parameter is one of the EPOLL_CTL_* + constants defined above. The "fd" parameter is the target of the + operation. The "event" parameter describes which events the caller + is interested in and any associated user data. */ +extern int epoll_ctl (int __epfd, int __op, int __fd, + struct epoll_event *__event) __THROW; + + +/* Wait for events on an epoll instance "epfd". Returns the number of + triggered events returned in "events" buffer. Or -1 in case of + error with the "errno" variable set to the specific error code. The + "events" parameter is a buffer that will contain triggered + events. The "maxevents" is the maximum number of events to be + returned ( usually size of "events" ). The "timeout" parameter + specifies the maximum wait time in milliseconds (-1 == infinite). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +__END_DECLS + +#endif /* sys/epoll.h */ diff --git a/libc/sysdeps/linux/x86_64/sys/io.h b/libc/sysdeps/linux/x86_64/sys/io.h new file mode 100644 index 0000000..802a0df --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/io.h @@ -0,0 +1,181 @@ +/* Copyright (C) 1996, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; + +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outb_p (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outw (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port)); + +} + +static __inline void +outw_p (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outl (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outl_p (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +insb (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insw (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insl (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsb (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsw (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsl (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +#endif /* GNU C */ + +__END_DECLS +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/linux/x86_64/sys/perm.h b/libc/sysdeps/linux/x86_64/sys/perm.h new file mode 100644 index 0000000..382fa92 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/perm.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1996, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PERM_H + +#define _SYS_PERM_H 1 +#include + +__BEGIN_DECLS + +/* Set port input/output permissions. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + + +/* Change I/O privilege level. */ +extern int iopl (int __level) __THROW; + +__END_DECLS + +#endif /* _SYS_PERM_H */ diff --git a/libc/sysdeps/linux/x86_64/sys/procfs.h b/libc/sysdeps/linux/x86_64/sys/procfs.h new file mode 100644 index 0000000..5995b71 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/procfs.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#if __WORDSIZE == 32 +/* Register set for the floating-point registers. */ +typedef struct user_fpregs_struct elf_fpregset_t; + +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpxregs_struct elf_fpxregset_t; +#else +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpregs_struct elf_fpregset_t; +#endif + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ +#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; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/x86_64/sys/reg.h b/libc/sysdeps/linux/x86_64/sys/reg.h new file mode 100644 index 0000000..865e345 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/reg.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +#include + +#if __WORDSIZE == 64 +/* Index into an array of 8 byte longs returned from ptrace for + location of the users' stored general purpose registers. */ + +# define R15 0 +# define R14 1 +# define R13 2 +# define R12 3 +# define RBP 4 +# define RBX 5 +# define R11 6 +# define R10 7 +# define R9 8 +# define R8 9 +# define RAX 10 +# define RCX 11 +# define RDX 12 +# define RSI 13 +# define RDI 14 +# define ORIG_RAX 15 +# define RIP 16 +# define CS 17 +# define EFLAGS 18 +# define RSP 19 +# define SS 20 +# define FS_BASE 21 +# define GS_BASE 22 +# define DS 23 +# define ES 24 +# define FS 25 +# define GS 26 +#else + +/* Index into an array of 4 byte integers returned from ptrace for + * location of the users' stored general purpose registers. */ + +# 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 +#endif + +#endif diff --git a/libc/sysdeps/linux/x86_64/sys/ucontext.h b/libc/sysdeps/linux/x86_64/sys/ucontext.h new file mode 100644 index 0000000..b59cd29 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/ucontext.h @@ -0,0 +1,248 @@ +/* Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +#if __WORDSIZE == 64 + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 23 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register in the `gregset_t' array. */ +enum +{ + REG_R8 = 0, +# define REG_R8 REG_R8 + REG_R9, +# define REG_R9 REG_R9 + REG_R10, +# define REG_R10 REG_R10 + REG_R11, +# define REG_R11 REG_R11 + REG_R12, +# define REG_R12 REG_R12 + REG_R13, +# define REG_R13 REG_R13 + REG_R14, +# define REG_R14 REG_R14 + REG_R15, +# define REG_R15 REG_R15 + REG_RDI, +# define REG_RDI REG_RDI + REG_RSI, +# define REG_RSI REG_RSI + REG_RBP, +# define REG_RBP REG_RBP + REG_RBX, +# define REG_RBX REG_RBX + REG_RDX, +# define REG_RDX REG_RDX + REG_RAX, +# define REG_RAX REG_RAX + REG_RCX, +# define REG_RCX REG_RCX + REG_RSP, +# define REG_RSP REG_RSP + REG_RIP, +# define REG_RIP REG_RIP + REG_EFL, +# define REG_EFL REG_EFL + REG_CSGSFS, /* Actually short cs, gs, fs, __pad0. */ +# define REG_CSGSFS REG_CSGSFS + REG_ERR, +# define REG_ERR REG_ERR + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_OLDMASK, +# define REG_OLDMASK REG_OLDMASK + REG_CR2 +# define REG_CR2 REG_CR2 +}; +#endif + +struct _libc_fpxreg +{ + unsigned short int significand[4]; + unsigned short int exponent; + unsigned short int padding[3]; +}; + +struct _libc_xmmreg +{ + __uint32_t element[4]; +}; + +struct _libc_fpstate +{ + /* 64-bit FXSAVE format. */ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Note that fpregs is a pointer. */ + fpregset_t fpregs; + unsigned long __reserved1 [8]; +} mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#else /* __WORDSIZE == 32 */ + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 19 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_GS = 0, +# define REG_GS REG_GS + REG_FS, +# define REG_FS REG_FS + REG_ES, +# define REG_ES REG_ES + REG_DS, +# define REG_DS REG_DS + REG_EDI, +# define REG_EDI REG_EDI + REG_ESI, +# define REG_ESI REG_ESI + REG_EBP, +# define REG_EBP REG_EBP + REG_ESP, +# define REG_ESP REG_ESP + REG_EBX, +# define REG_EBX REG_EBX + REG_EDX, +# define REG_EDX REG_EDX + REG_ECX, +# define REG_ECX REG_ECX + REG_EAX, +# define REG_EAX REG_EAX + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_ERR, +# define REG_ERR REG_ERR + REG_EIP, +# define REG_EIP REG_EIP + REG_CS, +# define REG_CS REG_CS + REG_EFL, +# define REG_EFL REG_EFL + REG_UESP, +# define REG_UESP REG_UESP + REG_SS +# define REG_SS REG_SS +}; +#endif + +/* Definitions taken from the kernel headers. */ +struct _libc_fpreg +{ + unsigned short int significand[4]; + unsigned short int exponent; +}; + +struct _libc_fpstate +{ + unsigned long int cw; + unsigned long int sw; + unsigned long int tag; + unsigned long int ipoff; + unsigned long int cssel; + unsigned long int dataoff; + unsigned long int datasel; + struct _libc_fpreg _st[8]; + unsigned long int status; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Due to Linux's history we have to use a pointer here. The SysV/i386 + ABI requires a struct with the values. */ + fpregset_t fpregs; + unsigned long int oldmask; + unsigned long int cr2; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#endif /* __WORDSIZE == 32 */ + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/x86_64/sys/user.h b/libc/sysdeps/linux/x86_64/sys/user.h new file mode 100644 index 0000000..5ff68e5 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/sys/user.h @@ -0,0 +1,176 @@ +/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +#include + +#if __WORDSIZE == 64 + +struct user_fpregs_struct +{ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + __uint32_t st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + __uint32_t xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + __uint32_t padding[24]; +}; + +struct user_regs_struct +{ + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long rbp; + unsigned long rbx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long orig_rax; + unsigned long rip; + unsigned long cs; + unsigned long eflags; + unsigned long rsp; + unsigned long ss; + unsigned long fs_base; + unsigned long gs_base; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; +}; + +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]; + unsigned long int u_debugreg [8]; +}; + +#else +/* These are the 32-bit x86 structures. */ +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]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + 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]; +}; +#endif /* __WORDSIZE */ + +#include +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#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) + +#endif /* _SYS_USER_H */ diff --git a/libc/sysdeps/linux/x86_64/syscall.S b/libc/sysdeps/linux/x86_64/syscall.S new file mode 100644 index 0000000..ee223e3 --- /dev/null +++ b/libc/sysdeps/linux/x86_64/syscall.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Please consult the file sysdeps/unix/sysv/linux/x86-64/sysdep.h for + more information about the value -4095 used below. */ + +/* Usage: long syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6) + We need to do some arg shifting, the syscall_number will be in + rax. */ + +.text +.globl syscall +.type syscall,%function +syscall: + movq %rdi, %rax /* Syscall number -> rax. */ + movq %rsi, %rdi /* shift arg1 - arg5. */ + movq %rdx, %rsi + movq %rcx, %rdx + movq %r8, %r10 + movq %r9, %r8 + movq 8(%rsp),%r9 /* arg6 is on the stack. */ + syscall /* Do the system call. */ + cmpq $-4095, %rax /* Check %rax for error. */ + jae __syscall_error /* Branch forward if it failed. */ + ret /* Return to caller. */ + +.size syscall,.-syscall diff --git a/libc/sysdeps/linux/x86_64/vfork.S b/libc/sysdeps/linux/x86_64/vfork.S new file mode 100644 index 0000000..2dadbbf --- /dev/null +++ b/libc/sysdeps/linux/x86_64/vfork.S @@ -0,0 +1,58 @@ +/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function + +__vfork: + + /* Pop the return PC value into RDI. We need a register that + is preserved by the syscall and that we're allowed to destroy. */ + popq %rdi + + /* Stuff the syscall number in RAX and enter into the kernel. */ + movl $__NR_vfork, %eax + syscall + + /* Push back the return PC. */ + pushq %rdi + + cmpl $-4095, %eax + jae __syscall_error /* Branch forward if it failed. */ + + /* Normal return. */ + ret + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/libc/sysdeps/linux/xtensa/Makefile b/libc/sysdeps/linux/xtensa/Makefile new file mode 100644 index 0000000..633c91f --- /dev/null +++ b/libc/sysdeps/linux/xtensa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch new file mode 100644 index 0000000..f548864 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2007, 2008 Tensilica Inc. +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c fork.c posix_fadvise.c posix_fadvise64.c pread_write.c \ + sigaction.c __syscall_error.c + +SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \ + sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/libc/sysdeps/linux/xtensa/__longjmp.S b/libc/sysdeps/linux/xtensa/__longjmp.S new file mode 100644 index 0000000..5d5dd2f --- /dev/null +++ b/libc/sysdeps/linux/xtensa/__longjmp.S @@ -0,0 +1,126 @@ +/* longjmp for Xtensa Processors. + + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This implementation relies heavily on the Xtensa register window + mechanism. Setjmp flushes all the windows except its own to the + stack and then copies registers from the save areas on the stack + into the jmp_buf structure, along with the return address of the call + to setjmp. Longjmp invalidates all the windows except its own, and + then sets things up so that it will return to the right place, + using a window underflow to automatically restore the registers. + + Note that it would probably be sufficient to only copy the + registers from setjmp's caller into jmp_buf. However, we also copy + the save area located at the stack pointer of setjmp's caller. + This save area will typically remain intact until the longjmp call. + The one exception is when there is an intervening alloca in + setjmp's caller. This is certainly an unusual situation and is + likely to cause problems in any case (the storage allocated on the + stack cannot be safely accessed following the longjmp). As bad as + it is, on most systems this situation would not necessarily lead to + a catastrophic failure. If we did not preserve the extra save area + on Xtensa, however, it would. When setjmp's caller returns after a + longjmp, there will be a window underflow; an invalid return + address or stack pointer in the save area will almost certainly + lead to a crash. Keeping a copy of the extra save area in the + jmp_buf avoids this with only a small additional cost. If setjmp + and longjmp are ever time-critical, this could be removed. */ + + +#include "sysdep.h" + + +ENTRY (__longjmp) + + /* Invalidate all but the current window. Reading and writing + special registers WINDOWBASE and WINDOWSTART are + privileged operations, so user processes must call the + slower __window_spill() to do the job. */ + + movi a4, __window_spill + callx4 a4 + + /* Return to the return address of the setjmp, using the + window size bits from the setjmp call so that the caller + will be able to find the return value that we put in a2. */ + + l32i a0, a2, 64 + + /* Copy the first 4 saved registers from jmp_buf into the save area + at the current sp so that the values will be restored to registers + when longjmp returns. */ + + addi a7, a1, -16 + l32i a4, a2, 0 + l32i a5, a2, 4 + s32i a4, a7, 0 + s32i a5, a7, 4 + l32i a4, a2, 8 + l32i a5, a2, 12 + s32i a4, a7, 8 + s32i a5, a7, 12 + + /* Copy the remaining 0-8 saved registers. */ + extui a7, a0, 30, 2 + blti a7, 2, .Lendlj + l32i a8, a2, 52 + slli a4, a7, 4 + sub a6, a8, a4 + addi a5, a2, 16 + addi a8, a8, -16 /* a8 = end of register overflow area */ +.Lljloop: + l32i a7, a5, 0 + l32i a4, a5, 4 + s32i a7, a6, 0 + s32i a4, a6, 4 + l32i a7, a5, 8 + l32i a4, a5, 12 + s32i a7, a6, 8 + s32i a4, a6, 12 + addi a5, a5, 16 + addi a6, a6, 16 + blt a6, a8, .Lljloop +.Lendlj: + + /* The 4 words saved from the register save area at the target's + sp are copied back to the target procedure's save area. The + only point of this is to prevent a catastrophic failure in + case the contents were moved by an alloca after calling + setjmp. This is a bit paranoid but it doesn't cost much. */ + + l32i a7, a2, 4 /* load the target stack pointer */ + addi a7, a7, -16 /* find the destination save area */ + l32i a4, a2, 48 + l32i a5, a2, 52 + s32i a4, a7, 0 + s32i a5, a7, 4 + l32i a4, a2, 56 + l32i a5, a2, 60 + s32i a4, a7, 8 + s32i a5, a7, 12 + + /* Return v ? v : 1. */ + movi a2, 1 + movnez a2, a3, a3 + + retw +END (__longjmp) + +libc_hidden_def (__longjmp) diff --git a/libc/sysdeps/linux/xtensa/__syscall_error.c b/libc/sysdeps/linux/xtensa/__syscall_error.c new file mode 100644 index 0000000..2b642e8 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/libc/sysdeps/linux/xtensa/bits/endian.h b/libc/sysdeps/linux/xtensa/bits/endian.h new file mode 100644 index 0000000..38b3af3 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/endian.h @@ -0,0 +1,10 @@ +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/* Xtensa can be either big or little endian. */ +#ifdef __XTENSA_EB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif diff --git a/libc/sysdeps/linux/xtensa/bits/fcntl.h b/libc/sysdeps/linux/xtensa/bits/fcntl.h new file mode 100644 index 0000000..23de96c --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#ifdef __USE_GNU +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#ifdef __USE_GNU + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/libc/sysdeps/linux/xtensa/bits/ipc.h b/libc/sysdeps/linux/xtensa/bits/ipc.h new file mode 100644 index 0000000..481bdcc --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/ipc.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1995-1999, 2000, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned int __seq; /* Sequence number. */ + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_stat.h b/libc/sysdeps/linux/xtensa/bits/kernel_stat.h new file mode 100644 index 0000000..26da928 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/kernel_stat.h @@ -0,0 +1,57 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#define STAT_HAVE_NSEC 1 + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; /* Device */ + unsigned long long st_ino; /* File serial number */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + long long st_size; /* Size of file, in bytes. */ + unsigned long st_blksize; /* Optimal block size for I/O. */ + unsigned long __unused2; + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long st_atime; /* Time of last access. */ + unsigned long st_atime_nsec; + unsigned long st_mtime; /* Time of last modification. */ + unsigned long st_mtime_nsec; + unsigned long st_ctime; /* Time of last status change. */ + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/kernel_types.h b/libc/sysdeps/linux/xtensa/bits/kernel_types.h new file mode 100644 index 0000000..44f1075 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/kernel_types.h @@ -0,0 +1,48 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _XTENSA_POSIX_TYPES_H +#define _XTENSA_POSIX_TYPES_H + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +/* Beginning in 2.6 kernels, which is the first version that includes the + Xtensa port, __kernel_dev_t is defined in "linux/types.h" and is no longer + architecture-specific. It is defined here in uClibc for consistency with + other uClibc ports and for lack of a better place. */ +typedef unsigned int __kernel_dev_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* _XTENSA_POSIX_TYPES_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/mathdef.h b/libc/sysdeps/linux/xtensa/bits/mathdef.h new file mode 100644 index 0000000..99a4a31 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/mathdef.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2000, 2001, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Xtensa has `float' and `double' operations. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# undef __UCLIBC_HAS_LONG_DOUBLE_MATH__ +#endif diff --git a/libc/sysdeps/linux/xtensa/bits/mman.h b/libc/sysdeps/linux/xtensa/bits/mman.h new file mode 100644 index 0000000..d3beae6 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/mman.h @@ -0,0 +1,104 @@ +/* Definitions for POSIX memory map interface. Linux/Xtensa version. + Copyright (C) 1997, 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0400 /* Don't check for reservations. */ +# define MAP_POPULATE 0x10000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x20000 /* Do not block on IO. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/libc/sysdeps/linux/xtensa/bits/msq.h b/libc/sysdeps/linux/xtensa/bits/msq.h new file mode 100644 index 0000000..2eca21e --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/msq.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1995-1997, 2000, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if defined (__XTENSA_EB__) + unsigned long int __unused1; + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused2; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused3; + __time_t msg_ctime; /* time of last change */ +#elif defined (__XTENSA_EL__) + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused1; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused2; + __time_t msg_ctime; /* time of last change */ + unsigned long int __unused3; +#else +# error endian order not defined +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/libc/sysdeps/linux/xtensa/bits/setjmp.h b/libc/sysdeps/linux/xtensa/bits/setjmp.h new file mode 100644 index 0000000..1bc4896 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/setjmp.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Define the machine-dependent type `jmp_buf'. Xtensa version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The jmp_buf structure for Xtensa holds the following (where "proc" + is the procedure that calls setjmp): 4-12 registers from the window + of proc, the 4 words from the save area at proc's $sp (in case a + subsequent alloca in proc moves $sp), and the return address within + proc. Everything else is saved on the stack in the normal save areas. */ + +#ifndef _ASM +typedef int __jmp_buf[17]; +#endif + +#define JB_SP 1 +#define JB_PC 16 + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ + +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/libc/sysdeps/linux/xtensa/bits/shm.h b/libc/sysdeps/linux/xtensa/bits/shm.h new file mode 100644 index 0000000..de41d0d --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/shm.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ +#if defined (__XTENSA_EL__) + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; +#elif defined (__XTENSA_EB__) + unsigned long int __unused1; + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused2; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused3; + __time_t shm_ctime; /* time of last change by shmctl() */ +#else +# error endian order not defined +#endif + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h b/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h new file mode 100644 index 0000000..8f3301c --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Also see register-dump.h, where we spill live registers to the + stack so that we can trace the stack backward. */ + +#define SIGCONTEXT unsigned long _info, ucontext_t * +#define SIGCONTEXT_EXTRA_ARGS _info, + +/* ANDing with 0x3fffffff clears the window-size bits. + Assumes TASK_SIZE = 0x40000000. */ + +#define GET_PC(ctx) ((void *) (ctx->uc_mcontext.sc_pc & 0x3fffffff)) +#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.sc_a[1]) +#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.sc_a[1]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + diff --git a/libc/sysdeps/linux/xtensa/bits/stackinfo.h b/libc/sysdeps/linux/xtensa/bits/stackinfo.h new file mode 100644 index 0000000..50ddf25 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Xtensa the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/libc/sysdeps/linux/xtensa/bits/stat.h b/libc/sysdeps/linux/xtensa/bits/stat.h new file mode 100644 index 0000000..c6debc8 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/stat.h @@ -0,0 +1,153 @@ +/* Copyright (C) 1992, 1995-2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 1 +#define _STAT_VER _STAT_VER_LINUX + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + unsigned long __pad2; + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + unsigned long __pad2; + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#if 0 /*def __USE_MISC*/ + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long __unused4; + unsigned long __unused5; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ diff --git a/libc/sysdeps/linux/xtensa/bits/syscalls.h b/libc/sysdeps/linux/xtensa/bits/syscalls.h new file mode 100644 index 0000000..a59a805 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/syscalls.h @@ -0,0 +1,140 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc .../sysdeps/unix/sysv/linux/xtensa/sysdep.h +*/ + +#define SYS_ify(syscall_name) __NR_##syscall_name + +#ifdef __ASSEMBLER__ + +/* The register layout upon entering the function is: + + return addr stack ptr arg0, arg1, arg2, arg3, arg4, arg5 + ----------- --------- ---------------------------------- + a0 a1 a2, a3, a4, a5, a6, a7 + + (Of course a function with say 3 arguments does not have entries for + arguments 4, 5, and 6.) + + Linux takes system-call arguments in registers. The ABI and Xtensa + software conventions require the system-call number in a2. We move any + argument that was in a2 to a7, and a7 to a8 if we have all 6 arguments. + Note that for improved efficiency, we do NOT shift all parameters down + one register to maintain the original order. + + syscall number arg0, arg1, arg2, arg3, arg4, arg5 + -------------- ---------------------------------- + a2 a6, a3, a4, a5, a8, a9 + + Upon return, a2 and a3 are clobbered; all other registers are preserved. */ + +#undef DO_CALL +#define DO_CALL(syscall_name, nargs) \ + DO_ARGS_##nargs \ + movi a2, SYS_ify (syscall_name); \ + syscall + +#define DO_ARGS_0 +#define DO_ARGS_1 mov a6, a2; +#define DO_ARGS_2 mov a6, a2; +#define DO_ARGS_3 mov a6, a2; +#define DO_ARGS_4 mov a6, a2; +#define DO_ARGS_5 mov a8, a6; mov a6, a2; +#define DO_ARGS_6 mov a9, a7; mov a8, a6; mov a6, a2; + +#else /* not __ASSEMBLER__ */ + +#include + +#define STR(s) #s +#define LD_ARG(n,ar) register int _a##n __asm__ (STR(a##n)) = (int) (ar) + +#define LD_ARGS_0() +#define LD_ARGS_1(a0) LD_ARG(6,a0) +#define LD_ARGS_2(a0,a1) LD_ARGS_1(a0); LD_ARG(3,a1) +#define LD_ARGS_3(a0,a1,a2) LD_ARGS_2(a0,a1); LD_ARG(4,a2) +#define LD_ARGS_4(a0,a1,a2,a3) LD_ARGS_3(a0,a1,a2); LD_ARG(5,a3) +#define LD_ARGS_5(a0,a1,a2,a3,a4) LD_ARGS_4(a0,a1,a2,a3); LD_ARG(8,a4) +#define LD_ARGS_6(a0,a1,a2,a3,a4,a5) LD_ARGS_5(a0,a1,a2,a3,a4); LD_ARG(9,a5) + +#define ASM_ARGS_0 "r"(_a2) +#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a6) +#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a3) +#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a4) +#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a5) +#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a8) +#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a9) + +/* Define a macro which expands into the inline wrapper code for a system + call. */ + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ unsigned long resultvar = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ + resultvar = (unsigned long) -1; \ + } \ + (long) resultvar; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ LD_ARG(2, name); \ + LD_ARGS_##nr(args); \ + __asm__ __volatile__ ("syscall\n" \ + : "=a" (_a2) \ + : ASM_ARGS_##nr \ + : "memory"); \ + (long) _a2; }) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned long) (val) >= -4095L) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#define _syscall0(args...) SYSCALL_FUNC (0, args) +#define _syscall1(args...) SYSCALL_FUNC (1, args) +#define _syscall2(args...) SYSCALL_FUNC (2, args) +#define _syscall3(args...) SYSCALL_FUNC (3, args) +#define _syscall4(args...) SYSCALL_FUNC (4, args) +#define _syscall5(args...) SYSCALL_FUNC (5, args) +#define _syscall6(args...) SYSCALL_FUNC (6, args) + +#define C_DECL_ARGS_0() void +#define C_DECL_ARGS_1(t, v) t v +#define C_DECL_ARGS_2(t, v, args...) t v, C_DECL_ARGS_1(args) +#define C_DECL_ARGS_3(t, v, args...) t v, C_DECL_ARGS_2(args) +#define C_DECL_ARGS_4(t, v, args...) t v, C_DECL_ARGS_3(args) +#define C_DECL_ARGS_5(t, v, args...) t v, C_DECL_ARGS_4(args) +#define C_DECL_ARGS_6(t, v, args...) t v, C_DECL_ARGS_5(args) + +#define C_ARGS_0() +#define C_ARGS_1(t, v) v +#define C_ARGS_2(t, v, args...) v, C_ARGS_1 (args) +#define C_ARGS_3(t, v, args...) v, C_ARGS_2 (args) +#define C_ARGS_4(t, v, args...) v, C_ARGS_3 (args) +#define C_ARGS_5(t, v, args...) v, C_ARGS_4 (args) +#define C_ARGS_6(t, v, args...) v, C_ARGS_5 (args) + +#define SYSCALL_FUNC(nargs, type, name, args...) \ +type name (C_DECL_ARGS_##nargs (args)) { \ + return (type) INLINE_SYSCALL (name, nargs, C_ARGS_##nargs (args)); \ +} + +#endif /* not __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h new file mode 100644 index 0000000..d6a99b4 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h @@ -0,0 +1,41 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "ill" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_page.h b/libc/sysdeps/linux/xtensa/bits/uClibc_page.h new file mode 100644 index 0000000..74a9f60 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/uClibc_page.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Erik Andersen + * + * 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. + * + * The GNU C 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 the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +#include + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/wordsize.h b/libc/sysdeps/linux/xtensa/bits/wordsize.h new file mode 100644 index 0000000..ba643b6 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h new file mode 100644 index 0000000..34cf28c --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h @@ -0,0 +1,53 @@ +/* Xtensa configuration settings. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef XTENSA_CONFIG_H +#define XTENSA_CONFIG_H + +/* The macros defined here match those with the same names in the Xtensa + compile-time HAL (Hardware Abstraction Layer). Please refer to the + Xtensa System Software Reference Manual for documentation of these + macros. */ + +/* The following macros reflect the default expectations for Xtensa + processor configurations that can run glibc. If you want to try + building glibc for an Xtensa configuration that is missing these + options, you will at least need to change the values of these + macros. */ + +#undef XCHAL_HAVE_NSA +#define XCHAL_HAVE_NSA 1 + +#undef XCHAL_HAVE_LOOPS +#define XCHAL_HAVE_LOOPS 1 + +/* Assume the maximum number of AR registers. This currently only affects + the __window_spill function, and it is always safe to flush extra. */ + +#undef XCHAL_NUM_AREGS +#define XCHAL_NUM_AREGS 64 + +/* Set a default page size. This is currently needed when bootstrapping + the runtime linker. See comments in dl-machine.h where this is used. */ + +#undef XCHAL_MMU_MIN_PTE_PAGE_SIZE +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 + +#endif /* !XTENSA_CONFIG_H */ diff --git a/libc/sysdeps/linux/xtensa/brk.c b/libc/sysdeps/linux/xtensa/brk.c new file mode 100644 index 0000000..51f610b --- /dev/null +++ b/libc/sysdeps/linux/xtensa/brk.c @@ -0,0 +1,43 @@ +/* brk system call for Linux/Xtensa. + Copyright (C) 1996, 1997, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +libc_hidden_proto(brk) +int +brk (void *addr) +{ + void *newbrk; + + __curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr); + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/libc/sysdeps/linux/xtensa/bsd-_setjmp.S b/libc/sysdeps/linux/xtensa/bsd-_setjmp.S new file mode 100644 index 0000000..4e6a2da --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/xtensa/bsd-setjmp.S b/libc/sysdeps/linux/xtensa/bsd-setjmp.S new file mode 100644 index 0000000..1da848d --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S new file mode 100644 index 0000000..31921ea --- /dev/null +++ b/libc/sysdeps/linux/xtensa/clone.S @@ -0,0 +1,103 @@ +/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after it's all over. */ + +#include "sysdep.h" +#include +#define _ERRNO_H 1 +#include + +/* int clone (a2 = int (*fn)(void *arg), + a3 = void *child_stack, + a4 = int flags, + a5 = void *arg, + a6 = pid_t *ptid, + a7 = struct user_desc *tls, + 16(sp) = pid_t *ctid) */ + + .text +ENTRY (__clone) + + /* Sanity check arguments. */ + beqz a2, .Leinval /* no NULL function pointers */ + beqz a3, .Leinval /* no NULL stack pointers */ + + /* a2 and a3 are candidates for destruction by system-call return + parameters. We don't need the stack pointer after the system + call. We trust that the kernel will preserve a7, a9, and a6. */ + + mov a9, a5 /* save function argument */ + mov a5, a7 + mov a7, a2 /* save function pointer */ + mov a8, a6 /* use a8 as a temp */ + mov a6, a4 + mov a4, a8 + l32i a8, a1, 16 /* child_tid */ + movi a2, SYS_ify (clone) + + /* syscall (a2 = NR_clone, + a6 = clone_flags, + a3 = usp, + a4 = parent_tid, + a5 = child_tls, + a8 = child_tid) */ + syscall + bltz a2, SYSCALL_ERROR_LABEL + beqz a2, .Lthread_start + + /* Fall through for parent. */ +.Lpseudo_end: + retw + +.Leinval: + movi a2, -EINVAL + j SYSCALL_ERROR_LABEL + +.Lthread_start: + /* Start child thread. */ + movi a0, 0 /* terminate the stack frame */ + +#ifdef RESET_PID + /* Check and see if we need to reset the PID. */ + bbsi.l a6, 16, 1f /* CLONE_THREAD = 0x00010000 */ + movi a2, -1 + bbsi.l a6, 8, 2f /* CLONE_VM = 0x00000100 */ + movi a2, SYS_ify (getpid) + syscall +2: rur a3, THREADPTR + movi a4, PID_OFFSET + add a4, a4, a3 + s32i a2, a4, 0 + movi a4, TID_OFFSET + add a4, a4, a3 + s32i a2, a3, 0 +1: +#endif /* RESET_PID */ + + mov a6, a9 /* load up the 'arg' parameter */ + callx4 a7 /* call the user's function */ + + /* Call _exit. Note that any return parameter from the user's + function in a6 is seen as inputs to _exit. */ + movi a2, JUMPTARGET(_exit) + callx4 a2 + +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S new file mode 100644 index 0000000..63fbadc --- /dev/null +++ b/libc/sysdeps/linux/xtensa/crt1.S @@ -0,0 +1,119 @@ +/* Startup code compliant to the ELF Xtensa ABI. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include + +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + +/* This is the canonical entry point, usually the first thing in the text + segment. When the entry point runs, most register values are unspecified, + except for: + + a2 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + a1 The stack (i.e., a1+16) contains the arguments and environment: + a1+0 argc + a1+4 argv[0] + ... + a1+(4*argc) NULL + a1+(4*(argc+1)) envp[0] + ... + NULL + + Setup parameters accordingly (for a call4). See function prototype + from sysdeps/generic/libc-start.c + + a6 = *main + a7 = argc + a8 = ubp_av + a9 = *init + a10 = *fini + a11 = *rtld_fini + [sp+0] = stack_end + */ + + .text + .align 4 + .literal_position + .global _start + .type _start, @function +_start: + /* Clear a0 to obviously mark the outermost frame. */ + movi a0, 0 + + /* Load up the user's main function. */ + movi a6, main + + /* Extract the arguments as encoded on the stack and set up + the arguments for `main': argc, argv. envp will be determined + later in __uClibc_main. */ + l32i a7, a1, 0 /* Load the argument count. */ + addi a8, a1, 4 /* Compute the argv pointer. */ + + /* Push address of our own entry points to .fini and .init. */ + movi a9, _init + movi a10, _fini + + /* Setup the shared library termination function. */ + mov a11, a2 + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). Note that we destroy the stack version + of argc here. */ + s32i a1, a1, 0 + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + movi a4, __uClibc_main + callx4 a4 + + /* Crash if somehow `exit' does return. */ + ill + + /* Define a symbol for the first piece of initialized data. */ + .data + .align 4 + .global __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S new file mode 100644 index 0000000..a01c02c --- /dev/null +++ b/libc/sysdeps/linux/xtensa/crti.S @@ -0,0 +1,16 @@ +/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 4 + .global _init + .type _init, @function +_init: + entry sp, 48 + + + .section .fini + .align 4 + .global _fini + .type _fini, @function +_fini: + entry sp, 48 diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S new file mode 100644 index 0000000..ab1a489 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/crtn.S @@ -0,0 +1,8 @@ +/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [EPILOG] */ + + .section .init + retw + + + .section .fini + retw diff --git a/libc/sysdeps/linux/xtensa/fork.c b/libc/sysdeps/linux/xtensa/fork.c new file mode 100644 index 0000000..b06d934 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/fork.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork() for Xtensa uClibc + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#define _SIGNAL_H +#include + +/* Xtensa doesn't provide a 'fork' system call, so we use 'clone'. */ + +extern __typeof(fork) __libc_fork; + +libc_hidden_proto (fork) +pid_t __libc_fork (void) +{ + return (pid_t) INLINE_SYSCALL (clone, 2, SIGCHLD, 0); +} +weak_alias (__libc_fork, fork) +libc_hidden_weak (fork) diff --git a/libc/sysdeps/linux/xtensa/mmap.S b/libc/sysdeps/linux/xtensa/mmap.S new file mode 100644 index 0000000..c991e7d --- /dev/null +++ b/libc/sysdeps/linux/xtensa/mmap.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" +#include + +#define PAGE_SHIFT 12 + +/* __ptr_t __mmap (a2 = __ptr_t addr, + a3 = size_t len, + a4 = int prot, + a5 = int flags, + a6 = int fd, + a7 = off_t offset) */ + +ENTRY (__mmap) + + /* We only support mmap2 in the kernel, so shift offset by + page - size. */ + mov a8, a6 + mov a6, a2 + movi a2, SYS_ify (mmap2) + srli a9, a7, PAGE_SHIFT + + /* syscall (a2 = NR_mmap2, + a6 = arg0, + a3 = arg1, + a4 = arg2, + a5 = arg3, + a8 = arg4, + a9 = arg5) */ + + syscall + bltz a2, SYSCALL_ERROR_LABEL + +.Lpseudo_end: + retw + +PSEUDO_END (__mmap) + +weak_alias (__mmap, mmap) +libc_hidden_weak (mmap) diff --git a/libc/sysdeps/linux/xtensa/posix_fadvise.c b/libc/sysdeps/linux/xtensa/posix_fadvise.c new file mode 100644 index 0000000..0fe13a1 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/posix_fadvise.c @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for Xtensa uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +int posix_fadvise (int fd, off_t offset, off_t len, int advice) +{ +#ifdef __NR_fadvise64_64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice, + __LONG_LONG_PAIR ((long) (offset >> 31), + (long) offset), + __LONG_LONG_PAIR ((long) (len >> 31), + (long) len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +#else + return ENOSYS; +#endif +} diff --git a/libc/sysdeps/linux/xtensa/posix_fadvise64.c b/libc/sysdeps/linux/xtensa/posix_fadvise64.c new file mode 100644 index 0000000..1fdeeba --- /dev/null +++ b/libc/sysdeps/linux/xtensa/posix_fadvise64.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for Xtensa uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +int posix_fadvise64 (int fd, __off64_t offset, __off64_t len, int advice) +{ +#ifdef __NR_fadvise64_64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice, + __LONG_LONG_PAIR ((long) (offset >> 32), + (long) offset), + __LONG_LONG_PAIR ((long) (len >> 32), + (long) len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +#else + return ENOSYS; +#endif +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/libc/sysdeps/linux/xtensa/pread_write.c b/libc/sysdeps/linux/xtensa/pread_write.c new file mode 100644 index 0000000..f44d977 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/pread_write.c @@ -0,0 +1,193 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + +#ifdef __NR_pread + +# define __NR___syscall_pread __NR_pread +/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */ +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* __NR_pread */ + +#ifdef __NR_pwrite + +# define __NR___syscall_pwrite __NR_pwrite +/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */ +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + +#if ! defined __NR_pread || ! defined __NR_pwrite +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(lseek) + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lseek64) + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64(fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __fake_pread_write(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + /* we won't actually be modifying the buffer, + *just cast it to get rid of warnings */ + return __fake_pread_write(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S new file mode 100644 index 0000000..cd74caf --- /dev/null +++ b/libc/sysdeps/linux/xtensa/setjmp.S @@ -0,0 +1,131 @@ +/* setjmp for Xtensa Processors. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This implementation relies heavily on the Xtensa register window + mechanism. Setjmp flushes all the windows except its own to the + stack and then copies registers from the save areas on the stack + into the jmp_buf structure, along with the return address of the call + to setjmp. Longjmp invalidates all the windows except its own, and + then sets things up so that it will return to the right place, + using a window underflow to automatically restore the registers. + + Note that it would probably be sufficient to only copy the + registers from setjmp's caller into jmp_buf. However, we also copy + the save area located at the stack pointer of setjmp's caller. + This save area will typically remain intact until the longjmp call. + The one exception is when there is an intervening alloca in + setjmp's caller. This is certainly an unusual situation and is + likely to cause problems in any case (the storage allocated on the + stack cannot be safely accessed following the longjmp). As bad as + it is, on most systems this situation would not necessarily lead to + a catastrophic failure. If we did not preserve the extra save area + on Xtensa, however, it would. When setjmp's caller returns after a + longjmp, there will be a window underflow; an invalid return + address or stack pointer in the save area will almost certainly + lead to a crash. Keeping a copy of the extra save area in the + jmp_buf avoids this with only a small additional cost. If setjmp + and longjmp are ever time-critical, this could be removed. */ + +#include "sysdep.h" + +/* int setjmp (a2 = jmp_buf env) */ + +ENTRY (_setjmp) + movi a3, 0 + j 1f +END (_setjmp) +libc_hidden_def (_setjmp) + +ENTRY (setjmp) + movi a3, 1 + j 1f +END (setjmp) + +/* int __sigsetjmp (a2 = jmp_buf env, + a3 = int savemask) */ + +ENTRY (__sigsetjmp) +1: + /* Flush registers. */ + movi a4, __window_spill + callx4 a4 + + /* Preserve the second argument (savemask) in a15. The selection + of a15 is arbitrary, except it's otherwise unused. There is no + risk of triggering a window overflow since we just returned + from __window_spill(). */ + mov a15, a3 + + /* Copy the register save area at (sp - 16). */ + addi a5, a1, -16 + l32i a3, a5, 0 + l32i a4, a5, 4 + s32i a3, a2, 0 + s32i a4, a2, 4 + l32i a3, a5, 8 + l32i a4, a5, 12 + s32i a3, a2, 8 + s32i a4, a2, 12 + + /* Copy 0-8 words from the register overflow area. */ + extui a3, a0, 30, 2 + blti a3, 2, .Lendsj + l32i a7, a1, 4 + slli a4, a3, 4 + sub a5, a7, a4 + addi a6, a2, 16 + addi a7, a7, -16 /* a7 = end of register overflow area */ +.Lsjloop: + l32i a3, a5, 0 + l32i a4, a5, 4 + s32i a3, a6, 0 + s32i a4, a6, 4 + l32i a3, a5, 8 + l32i a4, a5, 12 + s32i a3, a6, 8 + s32i a4, a6, 12 + addi a5, a5, 16 + addi a6, a6, 16 + blt a5, a7, .Lsjloop +.Lendsj: + + /* Copy the register save area at sp. */ + l32i a3, a1, 0 + l32i a4, a1, 4 + s32i a3, a2, 48 + s32i a4, a2, 52 + l32i a3, a1, 8 + l32i a4, a1, 12 + s32i a3, a2, 56 + s32i a4, a2, 60 + + /* Save the return address, including the window size bits. */ + s32i a0, a2, 64 + + /* a2 still addresses jmp_buf. a15 contains savemask. */ + mov a6, a2 + mov a7, a15 + movi a3, __sigjmp_save + callx4 a3 + mov a2, a6 + retw +END(__sigsetjmp) + +weak_extern(_setjmp) +weak_extern(setjmp) diff --git a/libc/sysdeps/linux/xtensa/sigaction.c b/libc/sysdeps/linux/xtensa/sigaction.c new file mode 100644 index 0000000..790a8f2 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sigaction.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigaction() for Xtensa uClibc + * + * Copyright (C) 2007, 2008 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern void __default_sa_restorer (void); + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +int __libc_sigaction (int signum, const struct sigaction *act, + struct sigaction *oldact) +{ + struct kernel_sigaction kact, koldact; + int result; + + if (act) { + kact.k_sa_handler = act->sa_handler; + memcpy(&kact.sa_mask, &act->sa_mask, sizeof (kact.sa_mask)); + kact.sa_flags = act->sa_flags; + + if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; + } else { + kact.sa_restorer = __default_sa_restorer; + kact.sa_flags |= SA_RESTORER; + } + } + + result = __syscall_rt_sigaction(signum, act ? __ptrvalue (&kact) : NULL, + oldact ? __ptrvalue (&koldact) : NULL, + _NSIG / 8); + + if (oldact && result >= 0) { + oldact->sa_handler = koldact.k_sa_handler; + memcpy(&oldact->sa_mask, &koldact.sa_mask, sizeof(oldact->sa_mask)); + oldact->sa_flags = koldact.sa_flags; + oldact->sa_restorer = koldact.sa_restorer; + } + + return result; +} + +#ifndef LIBC_SIGACTION +libc_hidden_proto (sigaction) +weak_alias (__libc_sigaction, sigaction) +libc_hidden_weak (sigaction) +#endif diff --git a/libc/sysdeps/linux/xtensa/sigrestorer.S b/libc/sysdeps/linux/xtensa/sigrestorer.S new file mode 100644 index 0000000..474a893 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sigrestorer.S @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if __NR_rt_sigreturn > 255 +# error value of __NR_rt_sigreturn is too big! +#endif + + .text + .align 4 + .global __default_sa_restorer + .type __default_sa_restorer, @function +__default_sa_restorer: + movi a2, __NR_rt_sigreturn + syscall diff --git a/libc/sysdeps/linux/xtensa/sys/procfs.h b/libc/sysdeps/linux/xtensa/sys/procfs.h new file mode 100644 index 0000000..f6f8752 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sys/procfs.h @@ -0,0 +1,121 @@ +/* Copyright (C) 1996, 1997, 1999, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG 128 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +#define ELF_NFPREG 18 +typedef unsigned long elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/xtensa/sys/ptrace.h b/libc/sysdeps/linux/xtensa/sys/ptrace.h new file mode 100644 index 0000000..7aad929 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sys/ptrace.h @@ -0,0 +1,156 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +/* Kludge away careless namespace pollution from the kernel. */ + +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#undef PTRACE_GETFPREGSIZE + + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get size required for the buffer holding the floating point registers. + This is not supported on all machines. */ + PTRACE_GETFPREGSIZE = 18, +#define PT_GETFPREGSIZE PTRACE_GETFPREGSIZE + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Options set using PTRACE_SETOPTIONS. */ +enum __ptrace_setoptions { + PTRACE_O_TRACESYSGOOD = 0x00000001, + PTRACE_O_TRACEFORK = 0x00000002, + PTRACE_O_TRACEVFORK = 0x00000004, + PTRACE_O_TRACECLONE = 0x00000008, + PTRACE_O_TRACEEXEC = 0x00000010, + PTRACE_O_TRACEVFORKDONE = 0x00000020, + PTRACE_O_TRACEEXIT = 0x00000040, + PTRACE_O_MASK = 0x0000007f +}; + +/* Wait extended result codes for the above trace options. */ +enum __ptrace_eventcodes { + PTRACE_EVENT_FORK = 1, + PTRACE_EVENT_VFORK = 2, + PTRACE_EVENT_CLONE = 3, + PTRACE_EVENT_EXEC = 4, + PTRACE_EVENT_VFORK_DONE = 5, + PTRACE_EVENT_EXIT = 6 +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/libc/sysdeps/linux/xtensa/sys/ucontext.h b/libc/sysdeps/linux/xtensa/sys/ucontext.h new file mode 100644 index 0000000..4c37201 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sys/ucontext.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2001, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +/* Revise this structure when we add support for coprocessors. */ + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int dummy; +} fpregset_t; + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/libc/sysdeps/linux/xtensa/syscall.S b/libc/sysdeps/linux/xtensa/syscall.S new file mode 100644 index 0000000..955e889 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/syscall.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" + +/* The register layout upon entering the function is: + + arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5 + --------- -------------- ---------------------------------- + function a2 a3, a4, a5, a6, a7, (sp) + syscall a2 a6, a3, a4, a5, a8, a9 + */ + +ENTRY (syscall) + l32i a9, a1, 16 /* load extra argument from stack */ + mov a8, a7 + mov a7, a3 /* preserve a3 in a7 */ + mov a3, a4 + mov a4, a5 + mov a5, a6 + mov a6, a7 + syscall + movi a4, -4095 + bgeu a2, a4, SYSCALL_ERROR_LABEL +.Lpseudo_end: + retw +PSEUDO_END (syscall) diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h new file mode 100644 index 0000000..5708a81 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/sysdep.h @@ -0,0 +1,160 @@ +/* Assembler macros for Xtensa processors. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifdef __ASSEMBLER__ + +#define ALIGNARG(log2) 1 << log2 +#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg +#define ASM_SIZE_DIRECTIVE(name) .size name, . - name + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \ + .align ALIGNARG(2); \ + LITERAL_POSITION; \ + C_LABEL(name) \ + entry sp, FRAMESIZE; \ + CALL_MCOUNT + +#undef END +#define END(name) ASM_SIZE_DIRECTIVE(name) + +/* Define a macro for this directive so it can be removed in a few places. */ +#define LITERAL_POSITION .literal_position + +#undef JUMPTARGET +#ifdef PIC +/* The "@PLT" suffix is currently a no-op for non-shared linking, but + it doesn't hurt to use it conditionally for PIC code in case that + changes someday. */ +#define JUMPTARGET(name) name##@PLT +#else +#define JUMPTARGET(name) name +#endif + +#define FRAMESIZE 16 +#define CALL_MCOUNT /* Do nothing. */ + + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in a2 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can safely + test with -4095. */ + +/* We don't want the label for the error handler to be global when we define + it here. */ +#define SYSCALL_ERROR_LABEL 0f + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + movi a4, -4095; \ + bgeu a2, a4, SYSCALL_ERROR_LABEL; \ + .Lpseudo_end: + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args) + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#undef ret_NOERRNO +#define ret_NOERRNO retw + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + neg a2, a2 + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL retw + +#if RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +0: movi a4, rtld_errno; \ + neg a2, a2; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; + +#elif defined _LIBC_REENTRANT + +# if USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ +0: rur a4, THREADPTR; \ + movi a3, SYSCALL_ERROR_ERRNO@TPOFF; \ + neg a2, a2; \ + add a4, a4, a3; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +# else /* !USE___THREAD */ +# define SYSCALL_ERROR_HANDLER \ +0: neg a2, a2; \ + mov a6, a2; \ + movi a4, __errno_location@PLT; \ + callx4 a4; \ + s32i a2, a6, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +# endif /* !USE___THREAD */ +#else /* !_LIBC_REENTRANT */ +#define SYSCALL_ERROR_HANDLER \ +0: movi a4, errno; \ + neg a2, a2; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +#endif /* _LIBC_REENTRANT */ + +#endif /* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/xtensa/vfork.S b/libc/sysdeps/linux/xtensa/vfork.S new file mode 100644 index 0000000..6e490fe --- /dev/null +++ b/libc/sysdeps/linux/xtensa/vfork.S @@ -0,0 +1,170 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" +#include +#define _SIGNAL_H +#include + + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. + + Note that it is important that we don't create a new stack frame for the + caller. */ + + +/* The following are defined in linux/sched.h, which unfortunately + is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to + wake it up on mm_release */ + +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + + +/* pid_t vfork(void); + Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY (__vfork) + + movi a6, .Ljumptable + extui a2, a0, 30, 2 /* call-size: call4/8/12 = 1/2/3 */ + addx4 a4, a2, a6 /* find return address in jumptable */ + l32i a4, a4, 0 + add a4, a4, a6 + + slli a2, a2, 30 + xor a3, a0, a2 /* remove call-size from return addr */ + extui a5, a4, 30, 2 /* get high bits of jump target */ + slli a5, a5, 30 + or a3, a3, a5 /* stuff them into the return address */ + xor a4, a4, a5 /* clear high bits of jump target */ + or a0, a4, a2 /* create temporary return address */ + retw /* "return" to .L4, .L8, or .L12 */ + + .align 4 +.Ljumptable: + .word 0 + .word .L4 - .Ljumptable + .word .L8 - .Ljumptable + .word .L12 - .Ljumptable + + /* a7: return address */ +.L4: mov a12, a2 + mov a13, a3 + + SAVE_PID + + /* Use syscall 'clone'. Set new stack pointer to the same address. */ + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + movi a5, -4096 + + mov a6, a2 + mov a2, a12 + mov a3, a13 + + bgeu a6, a5, 1f + jx a7 +1: call4 .Lerr /* returns to original caller */ + + + /* a11: return address */ +.L8: mov a12, a2 + mov a13, a3 + mov a14, a6 + + SAVE_PID + + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + movi a9, -4096 + + mov a10, a2 + mov a2, a12 + mov a3, a13 + mov a6, a14 + + bgeu a10, a9, 1f + jx a11 +1: call8 .Lerr /* returns to original caller */ + + + /* a15: return address */ +.L12: mov a12, a2 + mov a13, a3 + mov a14, a6 + + SAVE_PID + + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + mov a3, a13 + movi a13, -4096 + + mov a6, a14 + mov a14, a2 + + mov a2, a12 + + bgeu a14, a13, 1f + jx a15 +1: call12 .Lerr /* returns to original caller */ + + + .align 4 +.Lerr: entry a1, 16 + + /* Restore the return address. */ + extui a4, a0, 30, 2 /* get the call-size bits */ + slli a4, a4, 30 + slli a3, a3, 2 /* clear high bits of target address */ + srli a3, a3, 2 + or a0, a3, a4 /* combine them */ + + PSEUDO_END (__vfork) +.Lpseudo_end: + retw + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libc/sysdeps/linux/xtensa/windowspill.S b/libc/sysdeps/linux/xtensa/windowspill.S new file mode 100644 index 0000000..1487f07 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/windowspill.S @@ -0,0 +1,96 @@ +/* Function to force register windows to the stack. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include + + .text + .align 4 + .literal_position + .global __window_spill + .type __window_spill, @function +__window_spill: + entry a1, 48 + bbci.l a0, 31, .L4 /* branch if called with call4 */ + bbsi.l a0, 30, .L12 /* branch if called with call12 */ + + /* Called with call8: touch register NUM_REGS-12 (4/20/52) */ +.L8: +#if XCHAL_NUM_AREGS > 16 + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-24 (x/8/40) */ + +#if XCHAL_NUM_AREGS == 32 + mov a8, a0 + retw +#else + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-36 (x/x/28) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-48 (x/x/16) */ + mov a12, a0 + _entry a1, 16 /* touch NUM_REGS-60 (x/x/4) */ +#endif +#endif + mov a4, a0 + retw + + /* Called with call4: touch register NUM_REGS-8 (8/24/56) */ +.L4: +#if XCHAL_NUM_AREGS == 16 + mov a8, a0 +#else + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-20 (x/12/44) */ + mov a12, a0 +#if XCHAL_NUM_AREGS > 32 + _entry a1, 48 /* touch NUM_REGS-32 (x/x/32) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-44 (x/x/20) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-56 (x/x/8) */ + mov a8, a0 +#endif +#endif + retw + + /* Called with call12: touch register NUM_REGS-16 (x/16/48) */ +.L12: +#if XCHAL_NUM_AREGS > 16 + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-28 (x/4/36) */ +#if XCHAL_NUM_AREGS == 32 + mov a4, a0 +#else + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-40 (x/x/24) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-52 (x/x/12) */ + mov a12, a0 +#endif +#endif + retw diff --git a/libc/termios/.indent.pro b/libc/termios/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/termios/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/termios/Makefile b/libc/termios/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/termios/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/termios/Makefile.in b/libc/termios/Makefile.in new file mode 100644 index 0000000..c77ee60 --- /dev/null +++ b/libc/termios/Makefile.in @@ -0,0 +1,19 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +TERMIOS_DIR := $(top_srcdir)libc/termios +TERMIOS_OUT := $(top_builddir)libc/termios + +TERMIOS_SRC := $(wildcard $(TERMIOS_DIR)/*.c) +TERMIOS_OBJ := $(patsubst $(TERMIOS_DIR)/%.c,$(TERMIOS_OUT)/%.o,$(TERMIOS_SRC)) + +libc-y += $(TERMIOS_OBJ) + +objclean-y += termios_clean + +termios_clean: + $(do_rm) $(addprefix $(TERMIOS_OUT)/*., o os) diff --git a/libc/termios/cfmakeraw.c b/libc/termios/cfmakeraw.c new file mode 100644 index 0000000..aae7678 --- /dev/null +++ b/libc/termios/cfmakeraw.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_BSD +/* Set *T to indicate raw mode. */ +void cfmakeraw (struct termios *t) +{ + t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + t->c_oflag &= ~OPOST; + t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + t->c_cflag &= ~(CSIZE|PARENB); + t->c_cflag |= CS8; + t->c_cc[VMIN] = 1; /* read returns when one char is available. */ + t->c_cc[VTIME] = 0; +} +#endif diff --git a/libc/termios/cfsetspeed.c b/libc/termios/cfsetspeed.c new file mode 100644 index 0000000..5d5eb8c --- /dev/null +++ b/libc/termios/cfsetspeed.c @@ -0,0 +1,179 @@ +/* Copyright (C) 1992,93,96,97,98,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_BSD + +libc_hidden_proto(cfsetispeed) +libc_hidden_proto(cfsetospeed) + +struct speed_struct +{ + speed_t value; + speed_t internal; +}; + +static const struct speed_struct speeds[] = + { +#ifdef B0 + { 0, B0 }, +#endif +#ifdef B50 + { 50, B50 }, +#endif +#ifdef B75 + { 75, B75 }, +#endif +#ifdef B110 + { 110, B110 }, +#endif +#ifdef B134 + { 134, B134 }, +#endif +#ifdef B150 + { 150, B150 }, +#endif +#ifdef B200 + { 200, B200 }, +#endif +#ifdef B300 + { 300, B300 }, +#endif +#ifdef B600 + { 600, B600 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1800 + { 1800, B1800 }, +#endif +#ifdef B2400 + { 2400, B2400 }, +#endif +#ifdef B4800 + { 4800, B4800 }, +#endif +#ifdef B9600 + { 9600, B9600 }, +#endif +#ifdef B19200 + { 19200, B19200 }, +#endif +#ifdef B38400 + { 38400, B38400 }, +#endif +#ifdef B57600 + { 57600, B57600 }, +#endif +#ifdef B76800 + { 76800, B76800 }, +#endif +#ifdef B115200 + { 115200, B115200 }, +#endif +#ifdef B153600 + { 153600, B153600 }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif +#ifdef B307200 + { 307200, B307200 }, +#endif +#ifdef B460800 + { 460800, B460800 }, +#endif +#ifdef B500000 + { 500000, B500000 }, +#endif +#ifdef B576000 + { 576000, B576000 }, +#endif +#ifdef B614400 + { 614400, B614400 }, +#endif +#ifdef B921600 + { 921600, B921600 }, +#endif +#ifdef B1000000 + { 1000000, B1000000 }, +#endif +#ifdef B1152000 + { 1152000, B1152000 }, +#endif +#ifdef B1500000 + { 1500000, B1500000 }, +#endif +#ifdef B1843200 + { 1843200, B1843200 }, +#endif +#ifdef B2000000 + { 2000000, B2000000 }, +#endif +#ifdef B2500000 + { 2500000, B2500000 }, +#endif +#ifdef B3000000 + { 3000000, B3000000 }, +#endif +#ifdef B3500000 + { 3500000, B3500000 }, +#endif +#ifdef B4000000 + { 4000000, B4000000 }, +#endif +#ifdef B6250000 + { 6250000, B6250000 }, +#endif +#ifdef B12500000 + { 12500000, B12500000 }, +#endif + }; + + +/* Set both the input and output baud rates stored in *TERMIOS_P to SPEED. */ +int cfsetspeed (struct termios *termios_p, speed_t speed) +{ + size_t cnt; + + for (cnt = 0; cnt < sizeof (speeds) / sizeof (speeds[0]); ++cnt) + if (speed == speeds[cnt].internal) + { + cfsetispeed (termios_p, speed); + cfsetospeed (termios_p, speed); + return 0; + } + else if (speed == speeds[cnt].value) + { + cfsetispeed (termios_p, speeds[cnt].internal); + cfsetospeed (termios_p, speeds[cnt].internal); + return 0; + } + + __set_errno (EINVAL); + + return -1; +} +#endif diff --git a/libc/termios/isatty.c b/libc/termios/isatty.c new file mode 100644 index 0000000..7532f33 --- /dev/null +++ b/libc/termios/isatty.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libc_hidden_proto(isatty) +libc_hidden_proto(tcgetattr) + +/* Return 1 if FD is a terminal, 0 if not. */ +int isatty (int fd) +{ + struct termios term; + + return tcgetattr (fd, &term) == 0; +} +libc_hidden_def(isatty) diff --git a/libc/termios/kernel_termios.h b/libc/termios/kernel_termios.h new file mode 100644 index 0000000..87d5c07 --- /dev/null +++ b/libc/termios/kernel_termios.h @@ -0,0 +1,139 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _KERNEL_TERMIOS_H +#define _KERNEL_TERMIOS_H 1 + +/* We need the definition of tcflag_t, cc_t, and speed_t. */ +#include + +/* The following corresponds to the values from the Linux 2.1.20 kernel. */ + + + + +#if defined( __sparc__ ) + + +#define __KERNEL_NCCS 17 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + + + +#elif defined(__powerpc__) + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ + }; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + +/* We have the kernel termios structure, so we can presume this code knows + what it's doing... */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('t', 19, struct __kernel_termios) +#define TCSETS _IOW ('t', 20, struct __kernel_termios) +#define TCSETSW _IOW ('t', 21, struct __kernel_termios) +#define TCSETSF _IOW ('t', 22, struct __kernel_termios) + + + +#elif defined(__mips__) + + + +#define __KERNEL_NCCS 23 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + + + +#elif defined(__alpha__) + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + + + +#else /* None of the above */ + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + +#endif + + + + +#endif /* kernel_termios.h */ + diff --git a/libc/termios/speed.c b/libc/termios/speed.c new file mode 100644 index 0000000..52647b9 --- /dev/null +++ b/libc/termios/speed.c @@ -0,0 +1,97 @@ +/* `struct termios' speed frobnication functions. Linux version. + Copyright (C) 1991,1992,1993,1995,1996,1997,1998,2000,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(cfsetispeed) +libc_hidden_proto(cfsetospeed) + +/* This is a gross hack around a kernel bug. If the cfsetispeed functions + is called with the SPEED argument set to zero this means use the same + speed as for output. But we don't have independent input and output + speeds and therefore cannot record this. + + We use an unused bit in the `c_iflag' field to keep track of this + use of `cfsetispeed'. The value here must correspond to the one used + in `tcsetattr.c'. */ +#define IBAUD0 020000000000 + + +/* Return the output baud rate stored in *TERMIOS_P. */ +speed_t cfgetospeed (const struct termios *termios_p) +{ + return termios_p->c_cflag & (CBAUD | CBAUDEX); +} + +/* Return the input baud rate stored in *TERMIOS_P. + Although for Linux there is no difference between input and output + speed, the numerical 0 is a special case for the input baud rate. It + should set the input baud rate to the output baud rate. */ +speed_t cfgetispeed (const struct termios *termios_p) +{ + return ((termios_p->c_iflag & IBAUD0) + ? 0 : termios_p->c_cflag & (CBAUD | CBAUDEX)); +} + +/* Set the output baud rate stored in *TERMIOS_P to SPEED. */ +int cfsetospeed (struct termios *termios_p, speed_t speed) +{ + if ((speed & ~CBAUD) != 0 + && (speed < B57600 || speed > __MAX_BAUD)) + { + __set_errno (EINVAL); + return -1; + } + + termios_p->c_cflag &= ~(CBAUD | CBAUDEX); + termios_p->c_cflag |= speed; + + return 0; +} +libc_hidden_def (cfsetospeed) + + +/* Set the input baud rate stored in *TERMIOS_P to SPEED. + Although for Linux there is no difference between input and output + speed, the numerical 0 is a special case for the input baud rate. It + should set the input baud rate to the output baud rate. */ +int cfsetispeed (struct termios *termios_p, speed_t speed) +{ + if ((speed & ~CBAUD) != 0 + && (speed < B57600 || speed > __MAX_BAUD)) + { + __set_errno (EINVAL); + return -1; + } + + if (speed == 0) + termios_p->c_iflag |= IBAUD0; + else + { + termios_p->c_iflag &= ~IBAUD0; + termios_p->c_cflag &= ~(CBAUD | CBAUDEX); + termios_p->c_cflag |= speed; + } + + return 0; +} +libc_hidden_def (cfsetispeed) diff --git a/libc/termios/tcdrain.c b/libc/termios/tcdrain.c new file mode 100644 index 0000000..a13374c --- /dev/null +++ b/libc/termios/tcdrain.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(ioctl) + +extern __typeof(tcdrain) __libc_tcdrain; +/* Wait for pending output to be written on FD. */ +int __libc_tcdrain (int fd) +{ + return ioctl(fd, TCSBRK, 1); +} +weak_alias(__libc_tcdrain,tcdrain) diff --git a/libc/termios/tcflow.c b/libc/termios/tcflow.c new file mode 100644 index 0000000..63f96a8 --- /dev/null +++ b/libc/termios/tcflow.c @@ -0,0 +1,30 @@ +/* tcflow -- Suspend or restart transmission on termios file descriptor. + Copyright (C) 1993,1997,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(ioctl) + +/* Suspend or restart transmission on FD. */ +int tcflow (int fd, int action) +{ + return ioctl (fd, TCXONC, action); +} diff --git a/libc/termios/tcflush.c b/libc/termios/tcflush.c new file mode 100644 index 0000000..159231f --- /dev/null +++ b/libc/termios/tcflush.c @@ -0,0 +1,31 @@ +/* tcflush -- Flush pending data on termios file descriptor. Linux version. + Copyright (C) 1993,1997,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +libc_hidden_proto(ioctl) + +/* Flush pending data on FD. */ +int +tcflush (int fd, int queue_selector) +{ + return ioctl (fd, TCFLSH, queue_selector); +} diff --git a/libc/termios/tcgetattr.c b/libc/termios/tcgetattr.c new file mode 100644 index 0000000..541beb4 --- /dev/null +++ b/libc/termios/tcgetattr.c @@ -0,0 +1,82 @@ +/* Copyright (C) 1992, 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(ioctl) +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(mempcpy) */ +libc_hidden_proto(tcgetattr) + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include "kernel_termios.h" + +/* Put the state of FD into *TERMIOS_P. */ +int tcgetattr (int fd, struct termios *termios_p) +{ + struct __kernel_termios k_termios; + int retval; + + retval = ioctl (fd, TCGETS, &k_termios); + if(likely(retval == 0)) { + termios_p->c_iflag = k_termios.c_iflag; + termios_p->c_oflag = k_termios.c_oflag; + termios_p->c_cflag = k_termios.c_cflag; + termios_p->c_lflag = k_termios.c_lflag; + termios_p->c_line = k_termios.c_line; +#ifdef _HAVE_C_ISPEED + termios_p->c_ispeed = k_termios.c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + termios_p->c_ospeed = k_termios.c_ospeed; +#endif + + + if (sizeof (cc_t) == 1 || _POSIX_VDISABLE == 0 + || (unsigned char) _POSIX_VDISABLE == (unsigned char) -1) + { + memset (mempcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)), + _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t)); +#if 0 + memset ( (memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)) + (__KERNEL_NCCS * sizeof (cc_t))) , + _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t)); +#endif + } else { + size_t cnt; + + memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + for (cnt = __KERNEL_NCCS; cnt < NCCS; ++cnt) + termios_p->c_cc[cnt] = _POSIX_VDISABLE; + } + } + + return retval; +} +libc_hidden_def(tcgetattr) diff --git a/libc/termios/tcgetpgrp.c b/libc/termios/tcgetpgrp.c new file mode 100644 index 0000000..1ad3171 --- /dev/null +++ b/libc/termios/tcgetpgrp.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(tcgetpgrp) +libc_hidden_proto(ioctl) + +/* Return the foreground process group ID of FD. */ +pid_t tcgetpgrp (int fd) +{ + pid_t pgrp; + + if (ioctl (fd, TIOCGPGRP, &pgrp) < 0) + return -1; + return pgrp; +} +libc_hidden_def (tcgetpgrp) diff --git a/libc/termios/tcgetsid.c b/libc/termios/tcgetsid.c new file mode 100644 index 0000000..8d3a402 --- /dev/null +++ b/libc/termios/tcgetsid.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(ioctl) +libc_hidden_proto(getsid) +libc_hidden_proto(tcgetpgrp) + +/* Return the session ID of FD. */ +pid_t +tcgetsid (int fd) +{ + pid_t pgrp; + pid_t sid; +#ifdef TIOCGSID + static smallint tiocgsid_does_not_work; + + if (! tiocgsid_does_not_work) + { + int serrno = errno; + + if (ioctl (fd, TIOCGSID, &sid) < 0) + { + if (errno == EINVAL) + { + tiocgsid_does_not_work = 1; + __set_errno (serrno); + } + else + return (pid_t) -1; + } + else + return (pid_t) sid; + } +#endif + + pgrp = tcgetpgrp (fd); + if (pgrp == -1) + return (pid_t) -1; + + sid = getsid (pgrp); + if (sid == -1 && errno == ESRCH) + __set_errno (ENOTTY); + + return sid; +} diff --git a/libc/termios/tcsendbrk.c b/libc/termios/tcsendbrk.c new file mode 100644 index 0000000..ae04cb9 --- /dev/null +++ b/libc/termios/tcsendbrk.c @@ -0,0 +1,48 @@ +/* Send break to terminal. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(ioctl) + +/* Send zero bits on FD. */ +int +tcsendbreak (int fd, int duration) +{ + /* The break lasts 0.25 to 0.5 seconds if DURATION is zero, + and an implementation-defined period if DURATION is nonzero. + We define a positive DURATION to be number of milliseconds to break. */ + if (duration <= 0) + return ioctl (fd, TCSBRK, 0); + +#ifdef TCSBRKP + /* Probably Linux-specific: a positive third TCSBRKP ioctl argument is + defined to be the number of 100ms units to break. */ + return ioctl (fd, TCSBRKP, (duration + 99) / 100); +#else + /* ioctl can't send a break of any other duration for us. + This could be changed to use trickery (e.g. lower speed and + send a '\0') to send the break, but for now just return an error. */ + __set_errno (EINVAL); + return -1; +#endif +} diff --git a/libc/termios/tcsetattr.c b/libc/termios/tcsetattr.c new file mode 100644 index 0000000..d0d82c2 --- /dev/null +++ b/libc/termios/tcsetattr.c @@ -0,0 +1,121 @@ +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +libc_hidden_proto(tcsetattr) +/* Experimentally off - libc_hidden_proto(memcpy) */ +libc_hidden_proto(ioctl) + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include "kernel_termios.h" + + +/* This is a gross hack around a kernel bug. If the cfsetispeed functions + is called with the SPEED argument set to zero this means use the same + speed as for output. But we don't have independent input and output + speeds and therefore cannot record this. + + We use an unused bit in the `c_iflag' field to keep track of this + use of `cfsetispeed'. The value here must correspond to the one used + in `speed.c'. */ +#if !defined _HAVE_C_ISPEED || !defined _HAVE_C_OSPEED +# define IBAUD0 020000000000 +#else +/* If we have separate values for input and output speed don't bother + with this. Define the value as zero so the compiler sees we don't + have to do the AND below. */ +# define IBAUD0 0 +#endif + + +/* Set the state of FD to *TERMIOS_P. */ +int tcsetattr (int fd, int optional_actions, const struct termios *termios_p) +{ + struct __kernel_termios k_termios; + unsigned long int cmd; + int retval; + + switch (optional_actions) + { + case TCSANOW: + cmd = TCSETS; + break; + case TCSADRAIN: + cmd = TCSETSW; + break; + case TCSAFLUSH: + cmd = TCSETSF; + break; + default: + __set_errno (EINVAL); + return -1; + } + + k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0; + k_termios.c_oflag = termios_p->c_oflag; + k_termios.c_cflag = termios_p->c_cflag; + k_termios.c_lflag = termios_p->c_lflag; + k_termios.c_line = termios_p->c_line; +#ifdef _HAVE_C_ISPEED + k_termios.c_ispeed = termios_p->c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + k_termios.c_ospeed = termios_p->c_ospeed; +#endif + memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + retval = ioctl (fd, cmd, &k_termios); + + if (retval == 0 && cmd == TCSETS) + { + /* The Linux kernel has a bug which silently ignore the invalid + c_cflag on pty. We have to check it here. */ + int save = errno; + retval = ioctl (fd, TCGETS, &k_termios); + if (retval) + { + /* We cannot verify if the setting is ok. We don't return + an error (?). */ + __set_errno (save); + retval = 0; + } + else if ((termios_p->c_cflag & (PARENB | CREAD)) + != (k_termios.c_cflag & (PARENB | CREAD)) + || ((termios_p->c_cflag & CSIZE) + && ((termios_p->c_cflag & CSIZE) + != (k_termios.c_cflag & CSIZE)))) + { + /* It looks like the Linux kernel silently changed the + PARENB/CREAD/CSIZE bits in c_cflag. Report it as an + error. */ + __set_errno (EINVAL); + retval = -1; + } + } + + return retval; +} +libc_hidden_def(tcsetattr) diff --git a/libc/termios/tcsetpgrp.c b/libc/termios/tcsetpgrp.c new file mode 100644 index 0000000..9bf1cda --- /dev/null +++ b/libc/termios/tcsetpgrp.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(ioctl) + +/* Set the foreground process group ID of FD set PGRP_ID. */ +int tcsetpgrp (int fd, pid_t pgrp_id) +{ + return ioctl (fd, TIOCSPGRP, &pgrp_id); +} diff --git a/libc/termios/ttyname.c b/libc/termios/ttyname.c new file mode 100644 index 0000000..9d6a8ce --- /dev/null +++ b/libc/termios/ttyname.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) Jan 1, 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Kept the same approach, but rewrote the code for the most part. + * Fixed some minor issues plus (as I recall) one SUSv3 errno case. + */ + +/* This is a fairly slow approach. We do a linear search through some + * directories looking for a match. Yes this is lame. But it should + * work, should be small, and will return names that match what is on + * disk. Another approach we could use would be to use the info in + * /proc/self/fd, but that is even more lame since it requires /proc */ + +/* SUSv3 mandates TTY_NAME_MAX as 9. This is obviously insufficient. + * However, there is no need to waste space and support non-standard + * tty names either. So we compromise and use the following buffer + * length. (Erik and Manuel agreed that 32 was more than reasonable.) + * + * If you change this, also change _SC_TTY_NAME_MAX in libc/unistd/sysconf.c + */ + +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(ttyname_r) +libc_hidden_proto(fstat) +libc_hidden_proto(lstat) +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(opendir) +libc_hidden_proto(closedir) +libc_hidden_proto(readdir) +libc_hidden_proto(isatty) + +#define TTYNAME_BUFLEN 32 + +static const char dirlist[] = +/* 12345670123 */ +"\010/dev/vc/\0" /* Try /dev/vc first (be devfs compatible) */ +"\011/dev/tts/\0" /* and /dev/tts next (be devfs compatible) */ +"\011/dev/pty/\0" /* and /dev/pty next (be devfs compatible) */ +"\011/dev/pts/\0" /* and try /dev/pts next */ +"\005/dev/\0"; /* and try walking through /dev last */ + +int ttyname_r(int fd, char *ubuf, size_t ubuflen) +{ + struct dirent *d; + struct stat st; + struct stat dst; + const char *p; + char *s; + DIR *fp; + int rv; + size_t len; + char buf[TTYNAME_BUFLEN]; + + if (fstat(fd, &st) < 0) { + return errno; + } + + rv = ENOTTY; /* Set up the default return value. */ + + if (!isatty(fd)) { + goto DONE; + } + + for (p = dirlist ; *p ; p += 1 + p[-1]) { + len = *p++; + + assert(len + 2 <= TTYNAME_BUFLEN); /* dirname + 1 char + nul */ + + strcpy(buf, p); + s = buf + len; + len = (TTYNAME_BUFLEN-2) - len; /* Available non-nul space. */ + + if (!(fp = opendir(p))) { + continue; + } + + while ((d = readdir(fp)) != NULL) { + /* This should never trigger for standard names, but we + * check it to be safe. */ + if (strlen(d->d_name) > len) { /* Too big? */ + continue; + } + + strcpy(s, d->d_name); + + if ((lstat(buf, &dst) == 0) +#if 0 + /* Stupid filesystems like cramfs fail to guarantee that + * st_ino and st_dev uniquely identify a file, contrary to + * SuSv3, so we cannot be quite so precise as to require an + * exact match. Settle for something less... Grumble... */ + && (st.st_dev == dst.st_dev) && (st.st_ino == dst.st_ino) +#else + && S_ISCHR(dst.st_mode) && (st.st_rdev == dst.st_rdev) +#endif + ) { /* Found it! */ + closedir(fp); + + /* We treat NULL buf as ERANGE rather than EINVAL. */ + rv = ERANGE; + if (ubuf && (strlen(buf) <= ubuflen)) { + strcpy(ubuf, buf); + rv = 0; + } + goto DONE; + } + } + + closedir(fp); + } + + DONE: + __set_errno(rv); + + return rv; +} +libc_hidden_def(ttyname_r) + +char *ttyname(int fd) +{ + static char name[TTYNAME_BUFLEN]; + + return ttyname_r(fd, name, TTYNAME_BUFLEN) ? NULL : name; +} diff --git a/libc/unistd/.indent.pro b/libc/unistd/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/libc/unistd/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/libc/unistd/Makefile b/libc/unistd/Makefile new file mode 100644 index 0000000..11f362a --- /dev/null +++ b/libc/unistd/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/unistd/Makefile.in b/libc/unistd/Makefile.in new file mode 100644 index 0000000..b447a85 --- /dev/null +++ b/libc/unistd/Makefile.in @@ -0,0 +1,48 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +UNISTD_DIR := $(top_srcdir)libc/unistd +UNISTD_OUT := $(top_builddir)libc/unistd + +CSRC := $(notdir $(wildcard $(UNISTD_DIR)/*.c)) +# multi source +CSRC := $(filter-out exec.c,$(CSRC)) + +ifeq ($(ARCH_USE_MMU),y) +CSRC := $(filter-out __exec_alloc.c,$(CSRC)) +else +CSRC := $(filter-out daemon.c,$(CSRC)) +endif + +ifeq ($(UCLIBC_HAS_GNU_GETOPT),y) +CSRC := $(filter-out getopt-susv3.c getopt_long-simple.c,$(CSRC)) +else +CSRC := $(filter-out getopt.c,$(CSRC)) +ifneq ($(UCLIBC_HAS_GETOPT_LONG),y) +CSRC := $(filter-out getopt_long-simple.c,$(CSRC)) +endif +endif + +ifeq ($(UCLIBC_HAS_GNU_GETSUBOPT),y) +CSRC := $(filter-out getsubopt-susv3.c,$(CSRC)) +else +CSRC := $(filter-out getsubopt.c,$(CSRC)) +endif + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC := $(filter-out sleep.c,$(CSRC)) +endif + +UNISTD_SRC := $(patsubst %.c,$(UNISTD_DIR)/%.c,$(CSRC)) +UNISTD_OBJ := $(patsubst %.c,$(UNISTD_OUT)/%.o,$(CSRC)) + +libc-y += $(UNISTD_OBJ) + +objclean-y += unistd_clean + +unistd_clean: + $(do_rm) $(addprefix $(UNISTD_OUT)/*., o os) diff --git a/libc/unistd/__exec_alloc.c b/libc/unistd/__exec_alloc.c new file mode 100644 index 0000000..837ffb4 --- /dev/null +++ b/libc/unistd/__exec_alloc.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___exec_alloc +#include "exec.c" diff --git a/libc/unistd/confstr.c b/libc/unistd/confstr.c new file mode 100644 index 0000000..67a9d58 --- /dev/null +++ b/libc/unistd/confstr.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1991, 1996, 1997, 2000-2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +#define CS_PATH "/bin:/usr/bin" + +/* If BUF is not NULL and LEN > 0, fill in at most LEN - 1 bytes + of BUF with the value corresponding to NAME and zero-terminate BUF. + Return the number of bytes required to hold NAME's entire value. */ +size_t confstr (int name, char *buf, size_t len) +{ + const char *string; + size_t string_len; + + switch (name) + { + case _CS_PATH: + { + static const char cs_path[] = CS_PATH; + string = cs_path; + string_len = sizeof (cs_path); + } + break; + default: + __set_errno (EINVAL); + return 0; + } + + if (len > 0 && buf != NULL) + { + if (string_len <= len) + memcpy (buf, string, string_len); + else + { + memcpy (buf, string, len - 1); + buf[len - 1] = '\0'; + } + } + return string_len; +} diff --git a/libc/unistd/daemon.c b/libc/unistd/daemon.c new file mode 100644 index 0000000..d565ed4 --- /dev/null +++ b/libc/unistd/daemon.c @@ -0,0 +1,92 @@ +/* vi: set sw=4 ts=4: */ +/* daemon implementation for uClibc + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. + * + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * Modified for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) + +libc_hidden_proto(open) +libc_hidden_proto(close) +libc_hidden_proto(_exit) +libc_hidden_proto(dup2) +libc_hidden_proto(setsid) +libc_hidden_proto(chdir) +libc_hidden_proto(fork) + +int daemon( int nochdir, int noclose ) +{ + int fd; + + switch (fork()) { + case -1: + return(-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return(-1); + + /* Make certain we are not a session leader, or else we + * might reacquire a controlling terminal */ + if (fork()) + _exit(0); + + if (!nochdir) + chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > 2) + close(fd); + } + return(0); +} +#endif diff --git a/libc/unistd/exec.c b/libc/unistd/exec.c new file mode 100644 index 0000000..9134e43 --- /dev/null +++ b/libc/unistd/exec.c @@ -0,0 +1,344 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Jan 1, 2004 + * Initial version of a SUSv3 compliant exec*() functions. + * Feb 17, 2004 + * Sigh... Fall back to alloca() if munmap() is broken on uClinux. + */ + +/* NOTE: Strictly speaking, there could be problems from accessing + * __environ in multithreaded programs. The only way around this + * that I see is to essentially lock __environ access (modifying + * the setenv code), make a copy of the environment table (just the + * pointers since the strings themselves are never freed), and then + * unlock prior to the execve call. If that fails, then we'd need + * to free the storage allocated for the copy. Better ideas anyone? + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(execl) +libc_hidden_proto(execle) +libc_hidden_proto(execlp) +libc_hidden_proto(execv) +libc_hidden_proto(execvp) + +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(execve) +libc_hidden_proto(mmap) +libc_hidden_proto(munmap) +libc_hidden_proto(getenv) + +/**********************************************************************/ +#define EXEC_FUNC_COMMON 0 +#define EXEC_FUNC_EXECVP 1 +#if defined(__ARCH_USE_MMU__) + +/* We have an MMU, so use alloca() to grab space for buffers and arg lists. */ + +# define EXEC_ALLOC_SIZE(VAR) /* nothing to do */ +# define EXEC_ALLOC(SIZE,VAR,FUNC) alloca((SIZE)) +# define EXEC_FREE(PTR,VAR) ((void)0) + +#else + +/* We do not have an MMU, so using alloca() is not an option (as this will + * easily overflow the stack in most setups). Less obviously, using malloc() + * is not an option either since malloc()ed memory can leak in from a vfork()ed + * child into the parent as no one is around after the child calls exec*() to + * free() the memory. Therefore, we must use mmap() and unmap() directly, + * caching the result as we go. This way we minimize the leak by reusing the + * memory with every call to an exec*(). + * + * To prevent recursive use of the same cached memory, we have to give execvp() + * its own cache. Here are the nested exec calls (a/-: alloc/no-alloc): + * execve(-) -> calls straight to kernel + * execl(a) -> execve(-) + * execlp(a) -> execvp(a) !! recursive usage !! + * execle(a) -> execve(-) + * execv(-) -> execve(-) + * execvp(a) -> execve(-) + */ + +# define EXEC_ALLOC_SIZE(VAR) /* nothing to do */ +# define EXEC_ALLOC(SIZE,VAR,FUNC) __exec_alloc((SIZE), FUNC) +# define EXEC_FREE(PTR,VAR) ((void)0) + +extern void *__exec_alloc(size_t size, int func) attribute_hidden; + +# ifdef L___exec_alloc + +void attribute_hidden *__exec_alloc(size_t size, int func) +{ + static void *common_cache, *execvp_cache; + static size_t common_size, execvp_size; + + void **cache = (func ? &execvp_cache : &common_cache); + size_t *cache_size = (func ? &execvp_size : &common_size); + + if (*cache_size >= size) + return *cache; + else if (*cache) + munmap(*cache, *cache_size); + + *cache_size = size; + return *cache = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + + /* We don't actually handle OOM in the exec funcs ... + if (*cache != MAP_FAILED) + return *cache; + else + return (*cache = NULL); + */ +} + +# endif + +#endif +/**********************************************************************/ +#ifdef L_execl + +int execl(const char *path, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execve(path, (char *const *) argv, __environ); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execl) + +#endif +/**********************************************************************/ +#ifdef L_execv + +int execv(__const char *path, char *__const argv[]) +{ + return execve(path, argv, __environ); +} +libc_hidden_def(execv) + +#endif +/**********************************************************************/ +#ifdef L_execle + +int execle(const char *path, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + char *const *envp; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + envp = va_arg(args, char *const *); /* Varies from execl and execlp. */ + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execve(path, (char *const *) argv, envp); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execle) + +#endif +/**********************************************************************/ +#ifdef L_execlp + +int execlp(const char *file, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execvp(file, (char *const *) argv); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execlp) + +#endif +/**********************************************************************/ +#ifdef L_execvp + +/* Experimentally off - libc_hidden_proto(strchrnul) */ + +/* Use a default path that matches glibc behavior, since SUSv3 says + * this is implementation-defined. The default is current working dir, + * /bin, and then /usr/bin. */ +static const char default_path[] = ":/bin:/usr/bin"; + +int execvp(const char *path, char *const argv[]) +{ + char *buf = NULL; + char *p; + char *e; + char *s0; + char *s; + EXEC_ALLOC_SIZE(size = 0) /* Do NOT add a semicolon! */ + size_t len; + size_t plen; + + if (!path || !*path) { /* Comply with SUSv3. */ + BAD: + __set_errno(ENOENT); + return -1; + } + + if (strchr(path, '/')) { + execve(path, argv, __environ); + if (errno == ENOEXEC) { + char **nargv; + EXEC_ALLOC_SIZE(size2) /* Do NOT add a semicolon! */ + size_t n; + RUN_BIN_SH: + /* Need the dimension - 1. We omit counting the trailing + * NULL but we actually omit the first entry. */ + for (n=0 ; argv[n] ; n++) {} + nargv = (char **) EXEC_ALLOC((n+2) * sizeof(char *), size2, EXEC_FUNC_EXECVP); + nargv[0] = argv[0]; + nargv[1] = (char *)path; + memcpy(nargv+2, argv+1, n*sizeof(char *)); + execve("/bin/sh", nargv, __environ); + EXEC_FREE(nargv, size2); + } + } else { + if ((p = getenv("PATH")) != NULL) { + if (!*p) { + goto BAD; + } + } else { + p = (char *) default_path; + } + + plen = strlen(path); + if (plen > (FILENAME_MAX - 1)) { + ALL_TOO_LONG: + __set_errno(ENAMETOOLONG); + return -1; + } + len = (FILENAME_MAX - 1) - plen; + + buf = EXEC_ALLOC(FILENAME_MAX, size, EXEC_FUNC_EXECVP); + { + int seen_small = 0; + s0 = buf + len; + memcpy(s0, path, plen+1); + + do { + s = s0; + e = strchrnul(p, ':'); + if (e > p) { + plen = e - p; + if (e[-1] != '/') { + ++plen; + } + if (plen > len) { + goto NEXT; + } + s -= plen; + memcpy(s, p, plen); + s[plen-1] = '/'; + } + + execve(s, argv, __environ); + + seen_small = 1; + + if (errno == ENOEXEC) { + path = s; + goto RUN_BIN_SH; + } + + NEXT: + if (!*e) { + if (!seen_small) { + goto ALL_TOO_LONG; + } + break; + } + p = e + 1; + } while (1); + } + } + + EXEC_FREE(buf, size); + + return -1; +} +libc_hidden_def(execvp) + +#endif +/**********************************************************************/ diff --git a/libc/unistd/execl.c b/libc/unistd/execl.c new file mode 100644 index 0000000..176b18b --- /dev/null +++ b/libc/unistd/execl.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execl +#include "exec.c" diff --git a/libc/unistd/execle.c b/libc/unistd/execle.c new file mode 100644 index 0000000..05dd3a0 --- /dev/null +++ b/libc/unistd/execle.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execle +#include "exec.c" diff --git a/libc/unistd/execlp.c b/libc/unistd/execlp.c new file mode 100644 index 0000000..b7e615d --- /dev/null +++ b/libc/unistd/execlp.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execlp +#include "exec.c" diff --git a/libc/unistd/execv.c b/libc/unistd/execv.c new file mode 100644 index 0000000..2503042 --- /dev/null +++ b/libc/unistd/execv.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execv +#include "exec.c" diff --git a/libc/unistd/execvp.c b/libc/unistd/execvp.c new file mode 100644 index 0000000..9fc025f --- /dev/null +++ b/libc/unistd/execvp.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execvp +#include "exec.c" diff --git a/libc/unistd/fpathconf.c b/libc/unistd/fpathconf.c new file mode 100644 index 0000000..7b0457c --- /dev/null +++ b/libc/unistd/fpathconf.c @@ -0,0 +1,258 @@ +/* fpathconf -- adjusted for busybox + Copyright (C) 1991,95,96,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +//#include + +//#include "linux_fsinfo.h" + +libc_hidden_proto(fstat) + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs; +libc_hidden_proto(__libc_fstatfs) + +/* The Linux kernel headers mention this as a kind of generic value. */ +#define LINUX_LINK_MAX 127 + + +/* Get file-specific information about descriptor FD. */ +long int fpathconf(int fd, int name) +{ + if (fd < 0) + { + __set_errno (EBADF); + return -1; + } + + if (name == _PC_LINK_MAX) + { + /* Cut some corners */ +#if 0 + struct statfs fsbuf; + + /* Determine the filesystem type. */ + if (__libc_fstatfs (fd, &fsbuf) < 0) + { + if (errno == ENOSYS) + /* not possible, return the default value. */ + return LINUX_LINK_MAX; + + /* Some error occured. */ + return -1; + } + + switch (fsbuf.f_type) + { + case EXT2_SUPER_MAGIC: + return EXT2_LINK_MAX; + + case MINIX_SUPER_MAGIC: + case MINIX_SUPER_MAGIC2: + return MINIX_LINK_MAX; + + case MINIX2_SUPER_MAGIC: + case MINIX2_SUPER_MAGIC2: + return MINIX2_LINK_MAX; + + case XENIX_SUPER_MAGIC: + return XENIX_LINK_MAX; + + case SYSV4_SUPER_MAGIC: + case SYSV2_SUPER_MAGIC: + return SYSV_LINK_MAX; + + case COH_SUPER_MAGIC: + return COH_LINK_MAX; + + case UFS_MAGIC: + case UFS_CIGAM: + return UFS_LINK_MAX; + + case REISERFS_SUPER_MAGIC: + return REISERFS_LINK_MAX; + + default: + return LINUX_LINK_MAX; + } +#else + return LINUX_LINK_MAX; +#endif + } + + switch (name) + { + default: + __set_errno (EINVAL); + return -1; + + case _PC_MAX_CANON: +#ifdef MAX_CANON + return MAX_CANON; +#else + return -1; +#endif + + case _PC_MAX_INPUT: +#ifdef MAX_INPUT + return MAX_INPUT; +#else + return -1; +#endif + + case _PC_NAME_MAX: +#ifdef NAME_MAX + { + struct statfs buf; + int save_errno = errno; + + if (__libc_fstatfs (fd, &buf) < 0) + { + if (errno == ENOSYS) + { + errno = save_errno; + return NAME_MAX; + } + return -1; + } + else + { +#ifdef _STATFS_F_NAMELEN + return buf.f_namelen; +#else +# ifdef _STATFS_F_NAME_MAX + return buf.f_name_max; +# else + return NAME_MAX; +# endif +#endif + } + } +#else + return -1; +#endif + + case _PC_PATH_MAX: +#ifdef PATH_MAX + return PATH_MAX; +#else + return -1; +#endif + + case _PC_PIPE_BUF: +#ifdef PIPE_BUF + return PIPE_BUF; +#else + return -1; +#endif + + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + + case _PC_SYNC_IO: +#ifdef _POSIX_SYNC_IO + return _POSIX_SYNC_IO; +#else + return -1; +#endif + + case _PC_ASYNC_IO: +#if defined _POSIX_ASYNC_IO && defined __UCLIBC_HAS_LFS__ + { + /* AIO is only allowed on regular files and block devices. */ + struct stat st; + + if (fstat (fd, &st) < 0 || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) + return -1; + else + return 1; + } +#else + return -1; +#endif + + case _PC_PRIO_IO: +#ifdef _POSIX_PRIO_IO + return _POSIX_PRIO_IO; +#else + return -1; +#endif + + case _PC_SOCK_MAXBUF: +#ifdef SOCK_MAXBUF + return SOCK_MAXBUF; +#else + return -1; +#endif + + case _PC_FILESIZEBITS: +#ifdef FILESIZEBITS + return FILESIZEBITS; +#else + /* We let platforms with larger file sizes overwrite this value. */ + return 32; +#endif + + /* Be lazy -- skip these */ + case _PC_REC_INCR_XFER_SIZE: + case _PC_REC_MAX_XFER_SIZE: + case _PC_REC_MIN_XFER_SIZE: + case _PC_REC_XFER_ALIGN: + case _PC_ALLOC_SIZE_MIN: + case _PC_SYMLINK_MAX: + return -1; + } + +} + diff --git a/libc/unistd/getlogin.c b/libc/unistd/getlogin.c new file mode 100644 index 0000000..1998a7f --- /dev/null +++ b/libc/unistd/getlogin.c @@ -0,0 +1,49 @@ +/* vi: set sw=4 ts=4: */ +/* + * getlogin for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strncpy) */ +libc_hidden_proto(getenv) + +/* uClibc makes it policy to not mess with the utmp file whenever + * possible, since I consider utmp a complete waste of time. Since + * getlogin() should never be used for security purposes, we kindly let + * the user specify whatever they want via the LOGNAME environment + * variable, or we return NULL if getenv() fails to find anything */ + +libc_hidden_proto(getlogin) +char * getlogin(void) +{ + return (getenv("LOGNAME")); +} +libc_hidden_def(getlogin) + +int getlogin_r(char *name, size_t len) +{ + char * foo = getenv("LOGNAME"); + + if (! foo) + return -1; + + strncpy(name, foo, len); + name[len-1] = '\0'; + return 0; +} + +char *cuserid(char *s) +{ + char *name = getlogin(); + if (s) { + return(strcpy(s, name ? name : "")); + } + return name; +} diff --git a/libc/unistd/getopt-susv3.c b/libc/unistd/getopt-susv3.c new file mode 100644 index 0000000..c22dd9f --- /dev/null +++ b/libc/unistd/getopt-susv3.c @@ -0,0 +1,126 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +/* Sep 7, 2003 + * Initial version of a SUSv3 compliant getopt(). + */ + +#include +#include +#include +#include + +libc_hidden_proto(fprintf) +/* Experimentally off - libc_hidden_proto(strchr) */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Enable gettext awareness. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#undef _ +#define _(X) X + +#ifdef __BCC__ +static const char missing[] = "option requires an argument"; +static const char illegal[] = "illegal option"; +#else +static const char missing[] = "%s: option requires an argument -- %c\n"; +static const char illegal[] = "%s: illegal option -- %c\n"; +#endif + +int opterr = 1; +int optind = 1; +int optopt = 0; +char *optarg = NULL; + +libc_hidden_proto(getopt) +int getopt(int argc, char * const argv[], const char *optstring) +{ + static const char *o; /* multi opt position */ + register const char *p; + register const char *s; + int retval = -1; + + optopt = 0; + optarg = NULL; + + if (!o) { /* Not in a multi-option arg. */ + if ((optind >= argc) /* No more args? */ + || ((p = argv[optind]) == NULL) /* Missing? */ + || (*p != '-') /* Not an option? */ + || (!*++p) /* "-" case? */ + ) { + goto DONE; + } + if ((*p == '-') && (p[1] == 0)) { /* "--" case. */ +/* ++optind; */ +/* goto DONE; */ + goto NEXTOPT; /* Less code generated... */ + } + o = p; + } + +#ifdef __BCC__ + p = o; /* Sigh... Help out bcc. */ +#define o p +#endif + retval = (unsigned char) *o; /* Avoid problems for char val of -1. */ + + if ((*o == ':') || !(s = strchr(optstring, *o))) { /* Illegal option? */ + s = illegal; + retval = '?'; + goto BAD; + } + + if (s[1] == ':') { /* Option takes an arg? */ + if (o[1]) { /* No space between option and arg? */ + optarg = (char *)(o + 1); + goto NEXTOPT; + } + + if (optind + 1 < argc) { /* Space between option and arg? */ + optarg = argv[++optind]; + } else { /* Out of args! */ + s = missing; + retval = ':'; + BAD: + optopt = *o; + if (*optstring != ':') { + retval = '?'; + if (opterr) { +#ifdef __BCC__ + fprintf(stderr, "%s: %s -- %c\n", argv[0], s, *o); +#else + fprintf(stderr, _(s), argv[0], *o); +#endif + } + } + } + } + +#ifdef __BCC__ +#undef o +#endif + + if (!*++o) { + NEXTOPT: + o = NULL; + ++optind; + } + DONE: + return retval; +} +libc_hidden_def(getopt) diff --git a/libc/unistd/getopt.c b/libc/unistd/getopt.c new file mode 100644 index 0000000..ac005e4 --- /dev/null +++ b/libc/unistd/getopt.c @@ -0,0 +1,1203 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Modified for uClibc by Manuel Novoa III on 1/5/01. + * Modified once again for uClibc by Erik Andersen 8/7/02 + */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define __FORCE_GLIBC +#include + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#include + +#ifdef VMS +# include +#endif + +#if !defined __UCLIBC__ && !defined __UCLIBC_HAS_GETTEXT_AWARENESS__ +#ifdef _LIBC +# include +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif +#else +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Enable gettext awareness. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#undef _ +#define _(X) X + +#endif + +/* Treat '-W foo' the same as the long option '--foo', + * disabled for the moment since it costs about 2k... */ +#undef SPECIAL_TREATMENT_FOR_W + +#if defined _LIBC && defined USE_IN_LIBIO +# include +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include +#include "getopt_int.h" + +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strcmp) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +libc_hidden_proto(getenv) +libc_hidden_proto(fprintf) + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + + +#ifndef __GNU_LIBRARY__ + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +#endif /* not __GNU_LIBRARY__ */ + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +# ifdef USE_NONOPTION_FLAGS +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +# define SWAP_FLAGS(ch1, ch2) \ + if (d->__nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (attribute_unused int argc, attribute_unused char *const *argv, const char *optstring, + struct _getopt_data *d) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + d->__first_nonopt = d->__last_nonopt = d->optind; + + d->__nextchar = NULL; + + d->__posixly_correct = !!getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (!d->__posixly_correct + && argc == __libc_argc && argv == __libc_argv) + { + if (d->__nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + d->__nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (d->__nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + d->__nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', d->__nonoption_flags_max_len - len); + } + } + d->__nonoption_flags_len = d->__nonoption_flags_max_len; + } + else + d->__nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +static int +_getopt_internal_r (int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d) +{ + int print_errors = d->opterr; + if (optstring[0] == ':') + print_errors = 0; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, d); + d->__initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) +#else +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') +#endif + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + + d->__nextchar += strlen (d->__nextchar); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + char *temp = strchr (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (d->__posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } + else + { +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->optopt = c; + return '?'; + } +#ifdef SPECIAL_TREATMENT_FOR_W + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `d->optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + d->__nextchar += strlen (d->__nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } +#endif + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longind, int long_only) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +int +getopt_long (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + +#endif /* Not ELIDE_CODE. */ diff --git a/libc/unistd/getopt_int.h b/libc/unistd/getopt_int.h new file mode 100644 index 0000000..a871785 --- /dev/null +++ b/libc/unistd/getopt_int.h @@ -0,0 +1,134 @@ +/* Internal declarations for getopt. + Copyright (C) 1989-1994,1996-1999,2001,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GETOPT_INT_H +#define _GETOPT_INT_H 1 + +extern int _getopt_internal (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only) attribute_hidden; + + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* For __ordering member */ +enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +}; + +/* Data type for reentrant functions. */ + +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + char *optarg; + smalluint optopt; /* we store characters here, a byte is enough */ + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + smallint __initialized; + + /* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + smallint __ordering; + + /* If the POSIXLY_CORRECT environment variable is set. */ + smallint __posixly_correct; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first + of them; `last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + int __nonoption_flags_max_len; + int __nonoption_flags_len; +# endif +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +#if 0 /* first is static on uClibc, the others not used */ +extern int _getopt_internal_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data); + +extern int _getopt_long_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); + +extern int _getopt_long_only_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); +#endif + +#endif /* getopt_int.h */ diff --git a/libc/unistd/getopt_long-simple.c b/libc/unistd/getopt_long-simple.c new file mode 100644 index 0000000..2dae341 --- /dev/null +++ b/libc/unistd/getopt_long-simple.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(getopt) + +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]+2; + 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/libc/unistd/getpass.c b/libc/unistd/getpass.c new file mode 100644 index 0000000..d1100b3 --- /dev/null +++ b/libc/unistd/getpass.c @@ -0,0 +1,120 @@ +/* Copyright (C) 1992-1999,2001,2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) + +/* Experimentally off - libc_hidden_proto(strlen) */ +libc_hidden_proto(tcsetattr) +libc_hidden_proto(tcgetattr) +libc_hidden_proto(setvbuf) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(fileno) +libc_hidden_proto(fflush) +libc_hidden_proto(fgets) +libc_hidden_proto(fputs) +libc_hidden_proto(fputc) +libc_hidden_proto(putc) +libc_hidden_proto(__fputc_unlocked) + +/* It is desirable to use this bit on systems that have it. + The only bit of terminal state we want to twiddle is echoing, which is + done in software; there is no need to change the state of the terminal + hardware. */ + +#ifndef TCSASOFT +#define TCSASOFT 0 +#endif +#define PWD_BUFFER_SIZE 256 + +char * getpass (const char *prompt) +{ + FILE *in, *out; + struct termios s, t; + int tty_changed; + static char buf[PWD_BUFFER_SIZE]; + int nread; + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "r+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + /* Save the old one. */ + s = t; + /* Tricky, tricky. */ + t.c_lflag &= ~(ECHO|ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); + if (in != stdin) { + /* Disable buffering for read/write FILE to prevent problems with + * fseek and buffering for read/write auto-transitioning. */ + setvbuf(in, NULL, _IONBF, 0); + } + } + else + tty_changed = 0; + + /* Write the prompt. */ + fputs(prompt, out); + fflush(out); + + /* Read the password. */ + fgets (buf, PWD_BUFFER_SIZE-1, in); + if (buf != NULL) + { + nread = strlen(buf); + if (nread < 0) + buf[0] = '\0'; + else if (buf[nread - 1] == '\n') + { + /* Remove the newline. */ + buf[nread - 1] = '\0'; + if (tty_changed) + /* Write the newline that was not echoed. */ + putc('\n', out); + } + } + + /* Restore the original setting. */ + if (tty_changed) { + (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); + } + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + return buf; +} +#endif diff --git a/libc/unistd/getsubopt-susv3.c b/libc/unistd/getsubopt-susv3.c new file mode 100644 index 0000000..10c97ca --- /dev/null +++ b/libc/unistd/getsubopt-susv3.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* Experimentally off - libc_hidden_proto(strchr) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ + +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/libc/unistd/getsubopt.c b/libc/unistd/getsubopt.c new file mode 100644 index 0000000..3014102 --- /dev/null +++ b/libc/unistd/getsubopt.c @@ -0,0 +1,75 @@ +/* Parse comma separate list into words. + Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Experimentally off - libc_hidden_proto(memchr) */ +/* Experimentally off - libc_hidden_proto(strncmp) */ +/* Experimentally off - libc_hidden_proto(strchrnul) */ + +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +int +getsubopt (char **optionp, char *const *tokens, char **valuep) +{ + char *endp, *vstart; + int cnt; + + if (**optionp == '\0') + return -1; + + /* Find end of next token. */ + endp = strchrnul (*optionp, ','); + + /* Find start of value. */ + vstart = memchr (*optionp, '=', endp - *optionp); + if (vstart == NULL) + vstart = endp; + + /* Try to match the characters between *OPTIONP and VSTART against + one of the TOKENS. */ + for (cnt = 0; tokens[cnt] != NULL; ++cnt) + if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0 + && tokens[cnt][vstart - *optionp] == '\0') + { + /* We found the current option in TOKENS. */ + *valuep = vstart != endp ? vstart + 1 : NULL; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return cnt; + } + + /* The current suboption does not match any option. */ + *valuep = *optionp; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return -1; +} diff --git a/libc/unistd/pathconf.c b/libc/unistd/pathconf.c new file mode 100644 index 0000000..7f7efbb --- /dev/null +++ b/libc/unistd/pathconf.c @@ -0,0 +1,202 @@ +/* Copyright (C) 1991,1995,1996,1998,2000,2001,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* pathconf -- adjusted for busybox */ + +/* It would be great it this could be implemented using fpathconf, + * but that doesn't work out very well (think FIFOs and sockets) */ + +#include +#include +#include +#include +#include +#include +#include +//#include + +extern __typeof(statfs) __libc_statfs; +libc_hidden_proto(__libc_statfs) +libc_hidden_proto(stat) + + +/* The Linux kernel headers mention this as a kind of generic value. */ +#ifndef LINK_MAX +# define LINK_MAX 127 +#endif + +/* Get file-specific information about PATH. */ +long int +pathconf (const char *path, int name) +{ + if (path[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + switch (name) + { + default: + __set_errno (EINVAL); + return -1; + + case _PC_LINK_MAX: +#ifdef LINK_MAX + return LINK_MAX; +#else + return -1; +#endif + + case _PC_MAX_CANON: +#ifdef MAX_CANON + return MAX_CANON; +#else + return -1; +#endif + + case _PC_MAX_INPUT: +#ifdef MAX_INPUT + return MAX_INPUT; +#else + return -1; +#endif + + case _PC_NAME_MAX: +#ifdef NAME_MAX + { + struct statfs buf; + int save_errno = errno; + + if (__libc_statfs (path, &buf) < 0) + { + if (errno == ENOSYS) + { + errno = save_errno; + return NAME_MAX; + } + return -1; + } + else + { +#ifdef _STATFS_F_NAMELEN + return buf.f_namelen; +#else +# ifdef _STATFS_F_NAME_MAX + return buf.f_name_max; +# else + return NAME_MAX; +# endif +#endif + } + } +#else + return -1; +#endif + + case _PC_PATH_MAX: +#ifdef PATH_MAX + return PATH_MAX; +#else + return -1; +#endif + + case _PC_PIPE_BUF: +#ifdef PIPE_BUF + return PIPE_BUF; +#else + return -1; +#endif + + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + + case _PC_SYNC_IO: +#ifdef _POSIX_SYNC_IO + return _POSIX_SYNC_IO; +#else + return -1; +#endif + + case _PC_ASYNC_IO: +#if defined _POSIX_ASYNC_IO && defined __UCLIBC_HAS_LFS__ + { + /* AIO is only allowed on regular files and block devices. */ + struct stat st; + + if (stat (path, &st) < 0 + || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) + return -1; + else + return 1; + } +#else + return -1; +#endif + + case _PC_PRIO_IO: +#ifdef _POSIX_PRIO_IO + return _POSIX_PRIO_IO; +#else + return -1; +#endif + + case _PC_SOCK_MAXBUF: +#ifdef SOCK_MAXBUF + return SOCK_MAXBUF; +#else + return -1; +#endif + + case _PC_FILESIZEBITS: +#ifdef FILESIZEBITS + return FILESIZEBITS; +#else + /* We let platforms with larger file sizes overwrite this value. */ + return 32; +#endif + + /* Be lazy -- skip these */ + case _PC_REC_INCR_XFER_SIZE: + case _PC_REC_MAX_XFER_SIZE: + case _PC_REC_MIN_XFER_SIZE: + case _PC_REC_XFER_ALIGN: + case _PC_ALLOC_SIZE_MIN: + case _PC_SYMLINK_MAX: + return -1; + } +} diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c new file mode 100644 index 0000000..435d105 --- /dev/null +++ b/libc/unistd/sleep.c @@ -0,0 +1,172 @@ +/* Implementation of the POSIX sleep function using nanosleep. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +libc_hidden_proto(sleep) + +libc_hidden_proto(sigaction) +libc_hidden_proto(sigprocmask) + +/* version perusing nanosleep */ +#if defined __UCLIBC_HAS_REALTIME__ +//libc_hidden_proto(__sigaddset) +//libc_hidden_proto(__sigemptyset) +//libc_hidden_proto(__sigismember) +/*libc_hidden_proto(nanosleep) need the reloc for cancellation*/ + +#if 0 +/* This is a quick and dirty, but not 100% compliant with + * the stupid SysV SIGCHLD vs. SIG_IGN behaviour. It is + * fine unless you are messing with SIGCHLD... */ +unsigned int sleep (unsigned int sec) +{ + unsigned int res; + struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 }; + res = nanosleep(&ts, &ts); + if (res) res = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); + return res; +} + +#else + +/* We are going to use the `nanosleep' syscall of the kernel. But the + kernel does not implement the sstupid SysV SIGCHLD vs. SIG_IGN + behaviour for this syscall. Therefore we have to emulate it here. */ +unsigned int sleep (unsigned int seconds) +{ + struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 }; + sigset_t set, oset; + unsigned int result; + + /* This is not necessary but some buggy programs depend on this. */ + if (seconds == 0) + return 0; + + /* Linux will wake up the system call, nanosleep, when SIGCHLD + arrives even if SIGCHLD is ignored. We have to deal with it + in libc. We block SIGCHLD first. */ + if (__sigemptyset (&set) < 0 + || __sigaddset (&set, SIGCHLD) < 0 + || sigprocmask (SIG_BLOCK, &set, &oset)) + return -1; + + /* If SIGCHLD is already blocked, we don't have to do anything. */ + if (!__sigismember (&oset, SIGCHLD)) + { + int saved_errno; + struct sigaction oact; + + if (__sigemptyset (&set) < 0 || __sigaddset (&set, SIGCHLD) < 0) + return -1; + + /* We get the signal handler for SIGCHLD. */ + if (sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0) + { + saved_errno = errno; + /* Restore the original signal mask. */ + (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); + __set_errno (saved_errno); + return -1; + } + + if (oact.sa_handler == SIG_IGN) + { + /* We should leave SIGCHLD blocked. */ + result = nanosleep (&ts, &ts); + + saved_errno = errno; + /* Restore the original signal mask. */ + (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); + __set_errno (saved_errno); + } + else + { + /* We should unblock SIGCHLD. Restore the original signal mask. */ + (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL); + result = nanosleep (&ts, &ts); + } + } + else + result = nanosleep (&ts, &ts); + + if (result != 0) + /* Round remaining time. */ + result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); + + return result; +} +#endif +#else /* __UCLIBC_HAS_REALTIME__ */ +libc_hidden_proto(sigaction) +/* no nanosleep, use signals and alarm() */ +static void sleep_alarm_handler(int attribute_unused sig) +{ +} +unsigned int sleep (unsigned int seconds) +{ + struct sigaction act, oact; + sigset_t set, oset; + unsigned int result, remaining; + time_t before, after; + int old_errno = errno; + + /* This is not necessary but some buggy programs depend on this. */ + if (seconds == 0) + return 0; + + /* block SIGALRM */ + if (__sigemptyset (&set) < 0 + || __sigaddset (&set, SIGALRM) < 0 + || sigprocmask (SIG_BLOCK, &set, &oset)) + return seconds; + + act.sa_handler = sleep_alarm_handler; + act.sa_flags = 0; + act.sa_mask = oset; + if (sigaction(SIGALRM, &act, &oact) < 0) + return seconds; + + before = time(NULL); + remaining = alarm(seconds); + if (remaining && remaining > seconds) { + /* restore user's alarm */ + (void) sigaction(SIGALRM, &oact, (struct sigaction *) NULL); + alarm(remaining); /* restore old alarm */ + sigsuspend(&oset); + after = time(NULL); + } else { + sigsuspend (&oset); + after = time(NULL); + (void) sigaction (SIGALRM, &oact, NULL); + } + result = after - before; + alarm(remaining > result ? remaining - result : 0); + sigprocmask (SIG_SETMASK, &oset, NULL); + + __set_errno(old_errno); + + return result > seconds ? 0 : seconds - result; +} +#endif /* __UCLIBC_HAS_REALTIME__ */ +libc_hidden_def(sleep) diff --git a/libc/unistd/swab.c b/libc/unistd/swab.c new file mode 100644 index 0000000..70ea464 --- /dev/null +++ b/libc/unistd/swab.c @@ -0,0 +1,23 @@ +#include +#include +#include + +/* Updated implementation based on byteswap.h from Miles Bader + * . This should be much faster on arches with machine + * specific, optimized definitions in include/bits/byteswap.h (i.e. on + * x86, use the bswap instruction on i486 and better boxes). For + * platforms that lack such support, this should be no slower than it + * was before... */ +void swab (const void *source, void *dest, ssize_t count) +{ + const unsigned short *from = source, *from_end = from + (count >> 1); + unsigned short junk; + unsigned short *to = dest; + + while (from < from_end) { + /* Don't put '*from++'into the bswap_16() macros + * or mad things will happen on macro expansion */ + junk=*from++; + *to++ = bswap_16 (junk); + } +} diff --git a/libc/unistd/sysconf.c b/libc/unistd/sysconf.c new file mode 100644 index 0000000..549c13c --- /dev/null +++ b/libc/unistd/sysconf.c @@ -0,0 +1,896 @@ +/* Copyright (C) 1991, 93, 95, 96, 97, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_REGEX__ +#include +#endif + +libc_hidden_proto(sysconf) + +libc_hidden_proto(getpagesize) +libc_hidden_proto(getdtablesize) + +#ifndef __UCLIBC_CLK_TCK_CONST +#error __UCLIBC_CLK_TCK_CONST not defined! +#endif + +/***********************************************************************/ +/* + * Manuel Novoa III Jan 2001 + * + * On i386, the switch-based implementation generates 796 bytes of code. + * However, many of the return values are repeats. By collecting these + * repeats and moving to a table-based implementation, we generate 283 + * bytes on i386 (-Os -fomit-frame-pointer). + */ + +#ifdef _UCLIBC_GENERATE_SYSCONF_ARCH +/* + * Set some errno's so the auto-gen code knows what it is dealing with. + * 1) ENOSYS signifies that we're returning a default value. + * This is just extra info for development. + * 2) EISNAM signifies that the value returned varies at runtime. + * + * Option: GETPAGESIZE_IS_DYNAMIC + * The current implementation of getpagesize in uClibc returns + * a constant. The pagesize on the target arch should not vary, + * so it should be safe to set this as 0. + */ +#define RETURN_NEG_1 __set_errno(ENOSYS); return -1 +#define RETURN_FUNCTION(f) __set_errno(EISNAM); return (long int) #f +#define GETPAGESIZE_IS_DYNAMIC 0 +#else +#define RETURN_NEG_1 return -1 +#define RETURN_FUNCTION(f) return f; +#endif /* _UCLIBC_GENERATE_SYSCONF_ARCH */ + +/* Get the value of the system variable NAME. */ +long int sysconf(int name) +{ + switch (name) + { + default: + __set_errno(EINVAL); + return -1; + + case _SC_ARG_MAX: +#ifdef ARG_MAX + return ARG_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CHILD_MAX: +#ifdef CHILD_MAX + return CHILD_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CLK_TCK: + /* Can't use CLK_TCK here since that calls __sysconf(_SC_CLK_TCK) */ + return __UCLIBC_CLK_TCK_CONST; + + case _SC_NGROUPS_MAX: +#ifdef NGROUPS_MAX + return NGROUPS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_OPEN_MAX: + RETURN_FUNCTION(getdtablesize()); + + case _SC_STREAM_MAX: +#ifdef STREAM_MAX + return STREAM_MAX; +#else + return FOPEN_MAX; +#endif + + case _SC_TZNAME_MAX: + return _POSIX_TZNAME_MAX; + + case _SC_JOB_CONTROL: +#ifdef _POSIX_JOB_CONTROL + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SAVED_IDS: +#ifdef _POSIX_SAVED_IDS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_REALTIME_SIGNALS: +#ifdef _POSIX_REALTIME_SIGNALS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PRIORITY_SCHEDULING: +#ifdef _POSIX_PRIORITY_SCHEDULING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_TIMERS: +#ifdef _POSIX_TIMERS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_ASYNCHRONOUS_IO: +#ifdef _POSIX_ASYNCHRONOUS_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PRIORITIZED_IO: +#ifdef _POSIX_PRIORITIZED_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SYNCHRONIZED_IO: +#ifdef _POSIX_SYNCHRONIZED_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_FSYNC: +#ifdef _POSIX_FSYNC + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MAPPED_FILES: +#ifdef _POSIX_MAPPED_FILES + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMLOCK: +#ifdef _POSIX_MEMLOCK + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMLOCK_RANGE: +#ifdef _POSIX_MEMLOCK_RANGE + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMORY_PROTECTION: +#ifdef _POSIX_MEMORY_PROTECTION + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MESSAGE_PASSING: +#ifdef _POSIX_MESSAGE_PASSING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SEMAPHORES: +#ifdef _POSIX_SEMAPHORES + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SHARED_MEMORY_OBJECTS: +#ifdef _POSIX_SHARED_MEMORY_OBJECTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_VERSION: + return _POSIX_VERSION; + + case _SC_PAGESIZE: +#if defined(GETPAGESIZE_IS_DYNAMIC) && (GETPAGESIZE_IS_DYNAMIC == 1) + RETURN_FUNCTION(getpagesize()); +#else + return getpagesize(); /* note: currently this is not dynamic */ +#endif + + case _SC_AIO_LISTIO_MAX: +#ifdef AIO_LISTIO_MAX + return AIO_LISTIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_AIO_MAX: +#ifdef AIO_MAX + return AIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_AIO_PRIO_DELTA_MAX: +#ifdef AIO_PRIO_DELTA_MAX + return AIO_PRIO_DELTA_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_DELAYTIMER_MAX: +#ifdef DELAYTIMER_MAX + return DELAYTIMER_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_MQ_OPEN_MAX: +#ifdef MQ_OPEN_MAX + return MQ_OPEN_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_MQ_PRIO_MAX: +#ifdef MQ_PRIO_MAX + return MQ_PRIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_RTSIG_MAX: +#ifdef RTSIG_MAX + return RTSIG_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SEM_NSEMS_MAX: +#ifdef SEM_NSEMS_MAX + return SEM_NSEMS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SEM_VALUE_MAX: +#ifdef SEM_VALUE_MAX + return SEM_VALUE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SIGQUEUE_MAX: +#ifdef SIGQUEUE_MAX + return SIGQUEUE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_TIMER_MAX: +#ifdef TIMER_MAX + return TIMER_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_BASE_MAX: +#ifdef BC_BASE_MAX + return BC_BASE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_DIM_MAX: +#ifdef BC_DIM_MAX + return BC_DIM_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_SCALE_MAX: +#ifdef BC_SCALE_MAX + return BC_SCALE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_STRING_MAX: +#ifdef BC_STRING_MAX + return BC_STRING_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_COLL_WEIGHTS_MAX: +#ifdef COLL_WEIGHTS_MAX + return COLL_WEIGHTS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_EQUIV_CLASS_MAX: +#ifdef EQUIV_CLASS_MAX + return EQUIV_CLASS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_EXPR_NEST_MAX: +#ifdef EXPR_NEST_MAX + return EXPR_NEST_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_LINE_MAX: +#ifdef LINE_MAX + return LINE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_RE_DUP_MAX: +#ifdef RE_DUP_MAX + return RE_DUP_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CHARCLASS_NAME_MAX: +#ifdef CHARCLASS_NAME_MAX + return CHARCLASS_NAME_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_PII: +#ifdef _POSIX_PII + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_XTI: +#ifdef _POSIX_PII_XTI + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_SOCKET: +#ifdef _POSIX_PII_SOCKET + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET: +#ifdef _POSIX_PII_INTERNET + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI: +#ifdef _POSIX_PII_OSI + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_POLL: +#ifdef _POSIX_POLL + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SELECT: +#ifdef _POSIX_SELECT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_UIO_MAXIOV: +#ifdef UIO_MAXIOV + return UIO_MAXIOV; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET_STREAM: +#ifdef _POSIX_PII_INTERNET_STREAM + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET_DGRAM: +#ifdef _POSIX_PII_INTERNET_DGRAM + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_COTS: +#ifdef _POSIX_PII_OSI_COTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_CLTS: +#ifdef _POSIX_PII_OSI_CLTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_M: +#ifdef _POSIX_PII_OSI_M + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_T_IOV_MAX: +#ifdef _T_IOV_MAX + return _T_IOV_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_2_VERSION: + return _POSIX2_VERSION; + + case _SC_2_C_BIND: +#ifdef _POSIX2_C_BIND + return _POSIX2_C_BIND; +#else + RETURN_NEG_1; +#endif + + case _SC_2_C_DEV: +#ifdef _POSIX2_C_DEV + return _POSIX2_C_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_C_VERSION: +#ifdef _POSIX2_C_VERSION + return _POSIX2_C_VERSION; +#else + RETURN_NEG_1; +#endif + + case _SC_2_FORT_DEV: +#ifdef _POSIX2_FORT_DEV + return _POSIX2_FORT_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_FORT_RUN: +#ifdef _POSIX2_FORT_RUN + return _POSIX2_FORT_RUN; +#else + RETURN_NEG_1; +#endif + + case _SC_2_LOCALEDEF: +#ifdef _POSIX2_LOCALEDEF + return _POSIX2_LOCALEDEF; +#else + RETURN_NEG_1; +#endif + + case _SC_2_SW_DEV: +#ifdef _POSIX2_SW_DEV + return _POSIX2_SW_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_CHAR_TERM: +#ifdef _POSIX2_CHAR_TERM + return _POSIX2_CHAR_TERM; +#else + RETURN_NEG_1; +#endif + + case _SC_2_UPE: +#ifdef _POSIX2_UPE + return _POSIX2_UPE; +#else + RETURN_NEG_1; +#endif + + /* POSIX 1003.1c (POSIX Threads). */ + case _SC_THREADS: +#ifdef __UCLIBC_HAS_THREADS__ + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_SAFE_FUNCTIONS: +#ifdef __UCLIBC_HAS_THREADS__ + return 1; +#else + RETURN_NEG_1; +#endif + +/* If you change these, also change libc/pwd_grp/pwd_grp.c to match */ + case _SC_GETGR_R_SIZE_MAX: + return __UCLIBC_GRP_BUFFER_SIZE__; + + case _SC_GETPW_R_SIZE_MAX: + return __UCLIBC_PWD_BUFFER_SIZE__; + +/* getlogin() is a worthless interface. In uClibc we let the user specify + * whatever they want via the LOGNAME environment variable, or we return NULL + * if getenv() fails to find anything. So this is merely how large a env + * variable can be. Lets use 256 */ + case _SC_LOGIN_NAME_MAX: + return 256; + +/* If you change this, also change _SC_TTY_NAME_MAX in libc/unistd/sysconf.c */ +#define TTYNAME_BUFLEN 32 + case _SC_TTY_NAME_MAX: + return TTYNAME_BUFLEN; + + case _SC_THREAD_DESTRUCTOR_ITERATIONS: +#ifdef _POSIX_THREAD_DESTRUCTOR_ITERATIONS + return _POSIX_THREAD_DESTRUCTOR_ITERATIONS; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_KEYS_MAX: +#ifdef PTHREAD_KEYS_MAX + return PTHREAD_KEYS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_STACK_MIN: +#ifdef PTHREAD_STACK_MIN + return PTHREAD_STACK_MIN; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_THREADS_MAX: +#ifdef PTHREAD_THREADS_MAX + return PTHREAD_THREADS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_ATTR_STACKADDR: +#ifdef _POSIX_THREAD_ATTR_STACKADDR + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_ATTR_STACKSIZE: +#ifdef _POSIX_THREAD_ATTR_STACKSIZE + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIORITY_SCHEDULING: +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIO_INHERIT: +#ifdef _POSIX_THREAD_PRIO_INHERIT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIO_PROTECT: +#ifdef _POSIX_THREAD_PRIO_PROTECT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PROCESS_SHARED: +#ifdef _POSIX_THREAD_PROCESS_SHARED + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_NPROCESSORS_CONF: +#if 0 + RETURN_FUNCTION(get_nprocs_conf()); +#else + /* this is a hack. for now always claim we have exactly one cpu */ + return 1; +#endif + + case _SC_NPROCESSORS_ONLN: +#if 0 + RETURN_FUNCTION(get_nprocs()); +#else + /* this is a hack. for now always claim we have exactly one cpu */ + return 1; +#endif + + case _SC_PHYS_PAGES: +#if 0 + RETURN_FUNCTION(get_phys_pages()); +#else + RETURN_NEG_1; +#endif + + case _SC_AVPHYS_PAGES: +#if 0 + RETURN_FUNCTION(get_avphys_pages()); +#else + RETURN_NEG_1; +#endif + + case _SC_ATEXIT_MAX: + return __UCLIBC_MAX_ATEXIT; + + case _SC_PASS_MAX: + /* We have no limit but since the return value might be used to + allocate a buffer we restrict the value. */ + return BUFSIZ; + + case _SC_XOPEN_VERSION: + return _XOPEN_VERSION; + + case _SC_XOPEN_XCU_VERSION: + return _XOPEN_XCU_VERSION; + + case _SC_XOPEN_UNIX: + return _XOPEN_UNIX; + + case _SC_XOPEN_CRYPT: +#ifdef _XOPEN_CRYPT + return _XOPEN_CRYPT; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_ENH_I18N: +#ifdef _XOPEN_ENH_I18N + return _XOPEN_ENH_I18N; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_SHM: +#ifdef _XOPEN_SHM + return _XOPEN_SHM; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG2: +#ifdef _XOPEN_XPG2 + return _XOPEN_XPG2; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG3: +#ifdef _XOPEN_XPG3 + return _XOPEN_XPG3; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG4: +#ifdef _XOPEN_XPG4 + return _XOPEN_XPG4; +#else + RETURN_NEG_1; +#endif + + case _SC_CHAR_BIT: + return CHAR_BIT; + + case _SC_CHAR_MAX: + return CHAR_MAX; + + case _SC_CHAR_MIN: + return CHAR_MIN; + + case _SC_INT_MAX: + return INT_MAX; + + case _SC_INT_MIN: + return INT_MIN; + + case _SC_LONG_BIT: + return sizeof (long int) * CHAR_BIT; + + case _SC_WORD_BIT: + return sizeof (int) * CHAR_BIT; + + case _SC_MB_LEN_MAX: + return MB_LEN_MAX; + + case _SC_NZERO: + return NZERO; + + case _SC_SSIZE_MAX: + return _POSIX_SSIZE_MAX; + + case _SC_SCHAR_MAX: + return SCHAR_MAX; + + case _SC_SCHAR_MIN: + return SCHAR_MIN; + + case _SC_SHRT_MAX: + return SHRT_MAX; + + case _SC_SHRT_MIN: + return SHRT_MIN; + + case _SC_UCHAR_MAX: + return UCHAR_MAX; + + case _SC_UINT_MAX: + return UINT_MAX; + + case _SC_ULONG_MAX: + return ULONG_MAX; + + case _SC_USHRT_MAX: + return USHRT_MAX; + + case _SC_NL_ARGMAX: +#ifdef NL_ARGMAX + return NL_ARGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_LANGMAX: +#ifdef NL_LANGMAX + return NL_LANGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_MSGMAX: +#ifdef NL_MSGMAX + return NL_MSGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_NMAX: +#ifdef NL_NMAX + return NL_NMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_SETMAX: +#ifdef NL_SETMAX + return NL_SETMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_TEXTMAX: +#ifdef NL_TEXTMAX + return NL_TEXTMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_XBS5_ILP32_OFF32: +#ifdef _XBS5_ILP32_OFF32 + return _XBS5_ILP32_OFF32; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_ILP32_OFFBIG: +#ifdef _XBS5_ILP32_OFFBIG + return _XBS5_ILP32_OFFBIG; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_LP64_OFF64: +#ifdef _XBS5_LP64_OFF64 + return _XBS5_LP64_OFF64; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_LPBIG_OFFBIG: +#ifdef _XBS5_LPBIG_OFFBIG + return _XBS5_LPBIG_OFFBIG; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_LEGACY: + return _XOPEN_LEGACY; + + case _SC_XOPEN_REALTIME: +#ifdef _XOPEN_REALTIME + return _XOPEN_REALTIME; +#else + RETURN_NEG_1; +#endif + case _SC_XOPEN_REALTIME_THREADS: +#ifdef _XOPEN_REALTIME_THREADS + return _XOPEN_REALTIME_THREADS; +#else + RETURN_NEG_1; +#endif + + case _SC_MONOTONIC_CLOCK: +#if defined __UCLIBC_HAS_REALTIME__ && defined __NR_clock_getres + /* Check using the clock_getres system call. */ + if (clock_getres(CLOCK_MONOTONIC, NULL) >= 0) + return _POSIX_VERSION; +#endif + + RETURN_NEG_1; + } +} +libc_hidden_def(sysconf) diff --git a/libc/unistd/ualarm.c b/libc/unistd/ualarm.c new file mode 100644 index 0000000..07bea2a --- /dev/null +++ b/libc/unistd/ualarm.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +libc_hidden_proto(setitimer) + +useconds_t ualarm(useconds_t value, useconds_t interval) +{ + struct itimerval otimer; + const struct itimerval itimer = { + { 0, interval }, + { 0, value} + }; + + if (setitimer(ITIMER_REAL, &itimer, &otimer) < 0) { + return -1; + } + return((otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec); +} diff --git a/libc/unistd/usershell.c b/libc/unistd/usershell.c new file mode 100644 index 0000000..1bf143d --- /dev/null +++ b/libc/unistd/usershell.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This version has been hevily modified for use with uClibc + * November 2002, Erik Andersen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) + +libc_hidden_proto(fstat) +libc_hidden_proto(fopen) +libc_hidden_proto(fclose) +libc_hidden_proto(__fsetlocking) +libc_hidden_proto(fileno) +libc_hidden_proto(fgets_unlocked) +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ +libc_hidden_proto(__ctype_b) +#endif + +/* + * Local shells should NOT be added here. They should be added in + * /etc/shells. + */ + +static const char * const validsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; +static char **curshell, **shells, *strings; +static char **initshells __P((void)); + +/* + * Get a list of shells from _PATH_SHELLS, if it exists. + */ +char * getusershell(void) +{ + char *ret; + + if (curshell == NULL) + curshell = initshells(); + ret = *curshell; + if (ret != NULL) + curshell++; + return (ret); +} + +static void __free_initshell_memory(void) +{ + free(shells); + shells = NULL; + free(strings); + strings = NULL; +} + +void endusershell(void) +{ + __free_initshell_memory(); + curshell = NULL; +} + +void setusershell(void) +{ + curshell = initshells(); +} + +static char ** initshells(void) +{ + register char **sp, *cp; + register FILE *fp; + struct stat statb; + int flen; + + __free_initshell_memory(); + + if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) + return (char **) validsh; + if (fstat(fileno(fp), &statb) == -1) { + goto cleanup; + } + if ((strings = malloc((unsigned)statb.st_size + 1)) == NULL) { + goto cleanup; + } + if ((shells = calloc((unsigned)statb.st_size / 3, sizeof (char *))) == NULL) { + goto cleanup; + } + /* No threads using this stream. */ +#ifdef __UCLIBC_HAS_THREADS__ + __fsetlocking (fp, FSETLOCKING_BYCALLER); +#endif + sp = shells; + cp = strings; + flen = statb.st_size; + while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) { + while (*cp != '#' && *cp != '/' && *cp != '\0') + cp++; + if (*cp == '#' || *cp == '\0') + continue; + *sp++ = cp; + while (!isspace(*cp) && *cp != '#' && *cp != '\0') + cp++; + *cp++ = '\0'; + } + *sp = NULL; + fclose(fp); + return (shells); + +cleanup: + __free_initshell_memory(); + fclose(fp); + return (char **) validsh; +} +#endif diff --git a/libc/unistd/usleep.c b/libc/unistd/usleep.c new file mode 100644 index 0000000..8a27f90 --- /dev/null +++ b/libc/unistd/usleep.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD || defined __USE_POSIX98 +#if defined __UCLIBC_HAS_REALTIME__ +/*libc_hidden_proto(nanosleep) need the reloc for cancellation*/ + +int usleep (__useconds_t usec) +{ + const struct timespec ts = { + .tv_sec = (long int) (usec / 1000000), + .tv_nsec = (long int) (usec % 1000000) * 1000ul + }; + return(nanosleep(&ts, NULL)); +} +#else /* __UCLIBC_HAS_REALTIME__ */ +libc_hidden_proto(select) +int usleep (__useconds_t usec) +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = usec; + return select(0, NULL, NULL, NULL, &tv); +} +#endif /* __UCLIBC_HAS_REALTIME__ */ +#endif diff --git a/libcrypt/Makefile b/libcrypt/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libcrypt/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libcrypt/Makefile.in b/libcrypt/Makefile.in new file mode 100644 index 0000000..f394c41 --- /dev/null +++ b/libcrypt/Makefile.in @@ -0,0 +1,68 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libcrypt := -DNOT_IN_libc -DIS_IN_libcrypt $(SSP_ALL_CFLAGS) + +LDFLAGS-libcrypt.so := $(LDFLAGS) + +LIBS-libcrypt.so := $(LIBS) + +libcrypt_FULL_NAME := libcrypt-$(VERSION).so + +libcrypt_DIR := $(top_srcdir)libcrypt +libcrypt_OUT := $(top_builddir)libcrypt + +ifeq ($(UCLIBC_HAS_CRYPT_IMPL),y) +CSRC := crypt.c des.c md5.c +endif +ifeq ($(UCLIBC_HAS_CRYPT_STUB),y) +CSRC := crypt_stub.c +endif + +libcrypt_SRC := $(addprefix $(libcrypt_DIR)/,$(CSRC)) +libcrypt_OBJ := $(patsubst $(libcrypt_DIR)/%.c,$(libcrypt_OUT)/%.o,$(libcrypt_SRC)) + +ifeq ($(DOPIC),y) +libcrypt-a-y := $(libcrypt_OBJ:.o=.os) +else +libcrypt-a-y := $(libcrypt_OBJ) +endif +libcrypt-so-y := $(libcrypt_OBJ:.o=.os) + +ifeq ($(UCLIBC_HAS_CRYPT),y) +lib-a-y += $(top_builddir)lib/libcrypt.a +lib-so-y += $(top_builddir)lib/libcrypt.so +endif +objclean-y += libcrypt_clean + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libcrypt.so: $(top_builddir)lib/libcrypt.a $(libc.depend) +else +$(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt_so.a $(libc.depend) +endif + $(call link.so,$(libcrypt_FULL_NAME),$(MAJOR_VERSION)) +else +$(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt.oS | $(libc.depend) + $(call linkm.so,$(libcrypt_FULL_NAME),$(MAJOR_VERSION)) +endif + +$(libcrypt_OUT)/libcrypt_so.a: $(libcrypt-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libcrypt_OUT)/libcrypt.oS: $(libcrypt_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libcrypt.a: $(libcrypt-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +libcrypt_clean: + $(do_rm) $(addprefix $(libcrypt_OUT)/*., o os oS a) diff --git a/libcrypt/crypt.c b/libcrypt/crypt.c new file mode 100644 index 0000000..8b361d3 --- /dev/null +++ b/libcrypt/crypt.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * crypt() for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include "libcrypt.h" + +char *crypt(const char *key, const char *salt) +{ + /* First, check if we are supposed to be using the MD5 replacement + * instead of DES... */ + if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') + return __md5_crypt((unsigned char*)key, (unsigned char*)salt); + else + return __des_crypt((unsigned char*)key, (unsigned char*)salt); +} diff --git a/libcrypt/crypt_stub.c b/libcrypt/crypt_stub.c new file mode 100644 index 0000000..76645a0 --- /dev/null +++ b/libcrypt/crypt_stub.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * crypt() for uClibc + * Copyright (C) 2008 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include "libcrypt.h" +#include + +char *crypt(const char *key attribute_unused, const char *salt attribute_unused) +{ + __set_errno(ENOSYS); + return NULL; +} + +void +setkey(const char *key attribute_unused) +{ + __set_errno(ENOSYS); +} + +void +encrypt(char *block attribute_unused, int flag attribute_unused) +{ + __set_errno(ENOSYS); +} diff --git a/libcrypt/des.c b/libcrypt/des.c new file mode 100644 index 0000000..eb1e13f --- /dev/null +++ b/libcrypt/des.c @@ -0,0 +1,755 @@ +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * this file should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * Adapted for FreeBSD-4.0 by Mark R V Murray + * this file should now *only* export crypt_des(), in order to make + * a module that can be optionally included in libcrypt. + * + * 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 . + * + * 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 u_int32_t's (ie. the CPU is not picky about + * alignment). + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include "libcrypt.h" + +/* Re-entrantify me -- all this junk needs to be in + * struct crypt_data to make this really reentrant... */ +static u_char inv_key_perm[64]; +static u_char inv_comp_perm[56]; +static u_char un_pbox[32]; +static u_int32_t en_keysl[16], en_keysr[16]; +static u_int32_t de_keysl[16], de_keysr[16]; +static u_int32_t ip_maskl[8][256], ip_maskr[8][256]; +static u_int32_t fp_maskl[8][256], fp_maskr[8][256]; +static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; +static u_int32_t comp_maskl[8][128], comp_maskr[8][128]; +static u_int32_t saltbits; +static u_int32_t old_salt; +static u_int32_t old_rawkey0, old_rawkey1; + + +/* Static stuff that stays resident and doesn't change after + * being initialized, and therefore doesn't need to be made + * reentrant. */ +static u_char init_perm[64], final_perm[64]; +static u_char m_sbox[4][4096]; +static u_int32_t psbox[4][256]; + + + + +/* A pile of data */ +static const u_char ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static const u_char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static const u_char 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 u_char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static const u_char 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 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static const u_char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static const u_char 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 const u_int32_t bits32[32] = +{ + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static const u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + + +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); +} + +static void +des_init(void) +{ + static int des_initialised = 0; + + int i, j, b, k, inbit, obit; + u_int32_t *p, *il, *ir, *fl, *fr; + const u_int32_t *bits28, *bits24; + u_char u_sbox[8][64]; + + if (des_initialised==1) + return; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for (b = 0; b < 4; b++) + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_char)((u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]); + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for (i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = (u_char)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] = (u_char)i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for (i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = (u_char)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++) { + for (i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for (i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * 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] = (u_char)i; + + for (b = 0; b < 4; b++) + for (i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + + +static void +setup_salt(u_int32_t salt) +{ + u_int32_t obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + + +static void +des_setkey(const char *key) +{ + u_int32_t k0, k1, rawkey0, rawkey1; + int shifts, round; + + des_init(); + + rawkey0 = ntohl(*(const u_int32_t *) key); + rawkey1 = ntohl(*(const u_int32_t *) (key + 4)); + + if ((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return; + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * 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++) { + u_int32_t t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + 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]; + + de_keysr[15 - round] = + 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 int +do_des( u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out, int count) +{ + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + u_int32_t l, r, *kl, *kr, *kl1, *kr1; + u_int32_t f, r48l, r48r; + int round; + + if (count == 0) { + return(1); + } else if (count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while (count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while (round--) { + /* + * 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; + } + r = l; + l = f; + } + /* + * 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]; + return(0); +} + + +#if 0 +static int +des_cipher(const char *in, char *out, u_int32_t salt, int count) +{ + u_int32_t l_out, r_out, rawl, rawr; + int retval; + union { + u_int32_t *ui32; + const char *c; + } trans; + + des_init(); + + setup_salt(salt); + + trans.c = in; + rawl = ntohl(*trans.ui32++); + rawr = ntohl(*trans.ui32); + + retval = do_des(rawl, rawr, &l_out, &r_out, count); + + trans.c = out; + *trans.ui32++ = htonl(l_out); + *trans.ui32 = htonl(r_out); + return(retval); +} +#endif + + +void +setkey(const char *key) +{ + int i, j; + u_int32_t packed_keys[2]; + u_char *p; + + p = (u_char *) packed_keys; + + for (i = 0; i < 8; i++) { + p[i] = 0; + for (j = 0; j < 8; j++) + if (*key++ & 1) + p[i] |= bits8[j]; + } + des_setkey((char *)p); +} + + +void +encrypt(char *block, int flag) +{ + u_int32_t io[2]; + u_char *p; + int i, j; + + des_init(); + + setup_salt(0L); + p = (u_char*)block; + for (i = 0; i < 2; i++) { + io[i] = 0L; + for (j = 0; j < 32; j++) + if (*p++ & 1) + io[i] |= bits32[j]; + } + do_des(io[0], io[1], io, io + 1, flag ? -1 : 1); + for (i = 0; i < 2; i++) + for (j = 0; j < 32; j++) + block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0; +} + +char *__des_crypt(const unsigned char *key, const unsigned char *setting) +{ + u_int32_t count, salt, l, r0, r1, keybuf[2]; + u_char *p, *q; + static char output[21]; + + des_init(); + + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (u_char *)keybuf; + while (q - (u_char *)keybuf - 8) { + *q++ = *key << 1; + if (*(q - 1)) + key++; + } + des_setkey((char *)keybuf); + +#if 0 + if (*setting == _PASSWORD_EFMT1) { + int i; + /* + * "new"-style: + * setting - underscore, 4 bytes of count, 4 bytes of salt + * key - unlimited characters + */ + for (i = 1, count = 0L; i < 5; i++) + count |= ascii_to_bin(setting[i]) << ((i - 1) * 6); + + for (i = 5, salt = 0L; i < 9; i++) + salt |= ascii_to_bin(setting[i]) << ((i - 5) * 6); + + while (*key) { + /* + * Encrypt the key with itself. + */ + if (des_cipher((char *)keybuf, (char *)keybuf, 0L, 1)) + return(NULL); + /* + * And XOR with the next 8 characters of the key. + */ + q = (u_char *)keybuf; + while (q - (u_char *)keybuf - 8 && *key) + *q++ ^= *key++ << 1; + + des_setkey((char *)keybuf); + } + strncpy(output, setting, 9); + + /* + * Double check that we weren't given a short setting. + * If we were, the above code will probably have created + * wierd values for count and salt, but we don't really care. + * Just make sure the output string doesn't have an extra + * NUL in it. + */ + output[9] = '\0'; + p = (u_char *)output + strlen(output); + } else +#endif + { + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + 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]; + + p = (u_char *)output + 2; + } + setup_salt(salt); + /* + * Do it. + */ + if (do_des(0L, 0L, &r0, &r1, (int)count)) + return(NULL); + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return(output); +} + diff --git a/libcrypt/libcrypt.h b/libcrypt/libcrypt.h new file mode 100644 index 0000000..1186620 --- /dev/null +++ b/libcrypt/libcrypt.h @@ -0,0 +1,20 @@ +/* prototypes for internal crypt functions + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __LIBCRYPT_H__ +#define __LIBCRYPT_H__ + +extern char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden; +extern char *__des_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden; + +/* shut up gcc-4.x signed warnings */ +#define strcpy(dst,src) strcpy((char*)dst,(char*)src) +#define strlen(s) strlen((char*)s) +#define strncat(dst,src,n) strncat((char*)dst,(char*)src,n) +#define strncmp(s1,s2,n) strncmp((char*)s1,(char*)s2,n) + +#endif diff --git a/libcrypt/md5.c b/libcrypt/md5.c new file mode 100644 index 0000000..ab5548c --- /dev/null +++ b/libcrypt/md5.c @@ -0,0 +1,634 @@ +/* + * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + * + * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $ + * + * This code is the same as the code published by RSA Inc. It has been + * edited for clarity and style only. + * + * ---------------------------------------------------------------------------- + * The md5_crypt() function was taken from freeBSD's libcrypt and contains + * this license: + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * + * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $ + * + * ---------------------------------------------------------------------------- + * On April 19th, 2001 md5_crypt() was modified to make it reentrant + * by Erik Andersen + * + * + * June 28, 2001 Manuel Novoa III + * + * "Un-inlined" code using loops and static const tables in order to + * reduce generated code size (on i386 from approx 4k to approx 2.5k). + * + * June 29, 2001 Manuel Novoa III + * + * Completely removed static PADDING array. + * + * Reintroduced the loop unrolling in MD5_Transform and added the + * MD5_SIZE_OVER_SPEED option for configurability. Define below as: + * 0 fully unrolled loops + * 1 partially unrolled (4 ops per loop) + * 2 no unrolling -- introduces the need to swap 4 variables (slow) + * 3 no unrolling and all 4 loops merged into one with switch + * in each loop (glacial) + * On i386, sizes are roughly (-Os -fno-builtin): + * 0: 3k 1: 2.5k 2: 2.2k 3: 2k + * + * + * Since SuSv3 does not require crypt_r, modified again August 7, 2002 + * by Erik Andersen to remove reentrance stuff... + */ + +/* + * Valid values are 1 (fastest/largest) to 3 (smallest/slowest). + */ +#define MD5_SIZE_OVER_SPEED 3 + +/**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "libcrypt.h" + +/* MD5 context. */ +struct MD5Context { + u_int32_t state[4]; /* state (ABCD) */ + u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +}; + +static void __md5_Init (struct MD5Context *); +static void __md5_Update (struct MD5Context *, const unsigned char *, unsigned int); +static void __md5_Pad (struct MD5Context *); +static void __md5_Final (unsigned char [16], struct MD5Context *); +static void __md5_Transform __P((u_int32_t [4], const unsigned char [64])); + + +#define MD5_MAGIC_STR "$1$" +#define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1) +static const unsigned char __md5__magic[] = MD5_MAGIC_STR; +static const unsigned char __md5_itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + +#ifdef i386 +#define __md5_Encode memcpy +#define __md5_Decode memcpy +#else /* i386 */ + +/* + * __md5_Encodes input (u_int32_t) into output (unsigned char). Assumes len is + * a multiple of 4. + */ + +static void +__md5_Encode (unsigned char *output, u_int32_t *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* + * __md5_Decodes input (unsigned char) into output (u_int32_t). Assumes len is + * a multiple of 4. + */ + +static void +__md5_Decode (u_int32_t *output, const unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) | + (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24); +} +#endif /* i386 */ + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. */ + +static void __md5_Init (struct MD5Context *context) +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ + +static void __md5_Update ( struct MD5Context *context, const unsigned char *input, unsigned int inputLen) +{ + unsigned int i, idx, partLen; + + /* Compute number of bytes mod 64 */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((u_int32_t)inputLen << 3)) + < ((u_int32_t)inputLen << 3)) + context->count[1]++; + context->count[1] += ((u_int32_t)inputLen >> 29); + + partLen = 64 - idx; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy((void *)&context->buffer[idx], (const void *)input, + partLen); + __md5_Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + __md5_Transform (context->state, &input[i]); + + idx = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy ((void *)&context->buffer[idx], (const void *)&input[i], + inputLen-i); +} + +/* + * MD5 padding. Adds padding followed by original length. + */ + +static void __md5_Pad ( struct MD5Context *context) +{ + unsigned char bits[8]; + unsigned int idx, padLen; + unsigned char PADDING[64]; + + memset(PADDING, 0, sizeof(PADDING)); + PADDING[0] = 0x80; + + /* Save number of bits */ + __md5_Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (idx < 56) ? (56 - idx) : (120 - idx); + __md5_Update (context, PADDING, padLen); + + /* Append length (before padding) */ + __md5_Update (context, bits, 8); +} + +/* + * MD5 finalization. Ends an MD5 message-digest operation, writing the + * the message digest and zeroizing the context. + */ + +static void __md5_Final ( unsigned char digest[16], struct MD5Context *context) +{ + /* Do padding. */ + __md5_Pad (context); + + /* Store state in digest */ + __md5_Encode (digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset ((void *)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ + +static void __md5_Transform (u_int32_t state[4], const unsigned char block[64]) +{ + u_int32_t a, b, c, d, x[16]; +#if MD5_SIZE_OVER_SPEED > 1 + u_int32_t temp; + const char *ps; + + static const char S[] = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; +#endif /* MD5_SIZE_OVER_SPEED > 1 */ + +#if MD5_SIZE_OVER_SPEED > 0 + const u_int32_t *pc; + const char *pp; + int i; + + static const u_int32_t C[] = { + /* round 1 */ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + /* round 2 */ + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + /* round 3 */ + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + /* round 4 */ + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + static const char P[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ + }; + +#endif /* MD5_SIZE_OVER_SPEED > 0 */ + + __md5_Decode (x, block, 64); + + a = state[0]; b = state[1]; c = state[2]; d = state[3]; + +#if MD5_SIZE_OVER_SPEED > 2 + pc = C; pp = P; ps = S - 4; + + for ( i = 0 ; i < 64 ; i++ ) { + if ((i&0x0f) == 0) ps += 4; + temp = a; + switch (i>>4) { + case 0: + temp += F(b,c,d); + break; + case 1: + temp += G(b,c,d); + break; + case 2: + temp += H(b,c,d); + break; + case 3: + temp += I(b,c,d); + break; + } + temp += x[(int)(*pp++)] + *pc++; + temp = ROTATE_LEFT(temp, ps[i&3]); + temp += b; + a = d; d = c; c = b; b = temp; + } +#elif MD5_SIZE_OVER_SPEED > 1 + pc = C; pp = P; ps = S; + + /* Round 1 */ + for ( i = 0 ; i < 16 ; i++ ) { + FF (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + + /* Round 2 */ + ps += 4; + for ( ; i < 32 ; i++ ) { + GG (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + /* Round 3 */ + ps += 4; + for ( ; i < 48 ; i++ ) { + HH (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + + /* Round 4 */ + ps += 4; + for ( ; i < 64 ; i++ ) { + II (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } +#elif MD5_SIZE_OVER_SPEED > 0 + pc = C; pp = P; + + /* Round 1 */ + for ( i = 0 ; i < 4 ; i++ ) { + FF (a, b, c, d, x[(int)(*pp++)], 7, *pc++); + FF (d, a, b, c, x[(int)(*pp++)], 12, *pc++); + FF (c, d, a, b, x[(int)(*pp++)], 17, *pc++); + FF (b, c, d, a, x[(int)(*pp++)], 22, *pc++); + } + + /* Round 2 */ + for ( i = 0 ; i < 4 ; i++ ) { + GG (a, b, c, d, x[(int)(*pp++)], 5, *pc++); + GG (d, a, b, c, x[(int)(*pp++)], 9, *pc++); + GG (c, d, a, b, x[(int)(*pp++)], 14, *pc++); + GG (b, c, d, a, x[(int)(*pp++)], 20, *pc++); + } + /* Round 3 */ + for ( i = 0 ; i < 4 ; i++ ) { + HH (a, b, c, d, x[(int)(*pp++)], 4, *pc++); + HH (d, a, b, c, x[(int)(*pp++)], 11, *pc++); + HH (c, d, a, b, x[(int)(*pp++)], 16, *pc++); + HH (b, c, d, a, x[(int)(*pp++)], 23, *pc++); + } + + /* Round 4 */ + for ( i = 0 ; i < 4 ; i++ ) { + II (a, b, c, d, x[(int)(*pp++)], 6, *pc++); + II (d, a, b, c, x[(int)(*pp++)], 10, *pc++); + II (c, d, a, b, x[(int)(*pp++)], 15, *pc++); + II (b, c, d, a, x[(int)(*pp++)], 21, *pc++); + } +#else + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ +#endif + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset ((void *)x, 0, sizeof (x)); +} + + +static void __md5_to64( char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = __md5_itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) +{ + /* Static stuff */ + static char passwd[120]; + + const unsigned char *sp, *ep; + char *p; + unsigned char final[17]; /* final[16] exists only to aid in looping */ + int sl,pl,i,pw_len; + struct MD5Context ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp(sp,__md5__magic,MD5_MAGIC_LEN)) + sp += MD5_MAGIC_LEN; + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + __md5_Init(&ctx); + + /* The password first, since that is what is most unknown */ + pw_len = strlen(pw); + __md5_Update(&ctx,pw,pw_len); + + /* Then our magic string */ + __md5_Update(&ctx,__md5__magic,MD5_MAGIC_LEN); + + /* Then the raw salt */ + __md5_Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + __md5_Init(&ctx1); + __md5_Update(&ctx1,pw,pw_len); + __md5_Update(&ctx1,sp,sl); + __md5_Update(&ctx1,pw,pw_len); + __md5_Final(final,&ctx1); + for(pl = pw_len; pl > 0; pl -= 16) + __md5_Update(&ctx,final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (i = pw_len; i ; i >>= 1) { + __md5_Update(&ctx, ((i&1) ? final : (const unsigned char *) pw), 1); + } + + /* Now make the output string */ + strcpy(passwd,__md5__magic); + strncat(passwd,sp,sl); + strcat(passwd,"$"); + + __md5_Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + __md5_Init(&ctx1); + if(i & 1) + __md5_Update(&ctx1,pw,pw_len); + else + __md5_Update(&ctx1,final,16); + + if(i % 3) + __md5_Update(&ctx1,sp,sl); + + if(i % 7) + __md5_Update(&ctx1,pw,pw_len); + + if(i & 1) + __md5_Update(&ctx1,final,16); + else + __md5_Update(&ctx1,pw,pw_len); + __md5_Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + final[16] = final[5]; + for ( i=0 ; i < 5 ; i++ ) { + l = (final[i]<<16) | (final[i+6]<<8) | final[i+12]; + __md5_to64(p,l,4); p += 4; + } + l = final[11]; + __md5_to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + diff --git a/libintl/Makefile b/libintl/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libintl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libintl/Makefile.in b/libintl/Makefile.in new file mode 100644 index 0000000..d4da42c --- /dev/null +++ b/libintl/Makefile.in @@ -0,0 +1,74 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libintl := -DNOT_IN_libc -DIS_IN_libintl $(SSP_ALL_CFLAGS) + +LDFLAGS-libintl.so := $(LDFLAGS) + +LIBS-libintl.so := $(LIBS) + +libintl_FULL_NAME := libintl-$(VERSION).so + +MOBJ := \ + gettext.o ngettext.o dgettext.o dcgettext.o dngettext.o dcngettext.o \ + textdomain.o bindtextdomain.o bind_textdomain_codeset.o \ + _nl_expand_alias.o _nl_msg_cat_cntr.o # glibc-isms + +libintl_DIR := $(top_srcdir)libintl +libintl_OUT := $(top_builddir)libintl + +libintl_MSRC := $(libintl_DIR)/intl.c +libintl_MOBJ := $(patsubst %.o,$(libintl_OUT)/%.o,$(MOBJ)) + +ifneq ($(DOMULTI),n) +CFLAGS-libintl += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libintl_MOBJ)))) +endif + +ifeq ($(DOPIC),y) +libintl-a-y := $(libintl_MOBJ:.o=.os) +else +libintl-a-y := $(libintl_MOBJ) +endif +libintl-so-y := $(libintl_MOBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_GETTEXT_AWARENESS) += $(top_builddir)lib/libintl.a +lib-so-$(UCLIBC_HAS_GETTEXT_AWARENESS) += $(top_builddir)lib/libintl.so +objclean-y += libintl_clean + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libintl.so: $(top_builddir)lib/libintl.a $(libc) +else +$(top_builddir)lib/libintl.so: $(libintl_OUT)/libintl_so.a $(libc) +endif + $(call link.so,$(libintl_FULL_NAME),$(MAJOR_VERSION)) +else +$(top_builddir)lib/libintl.so: $(libintl_OUT)/libintl.oS | $(libc) + $(call linkm.so,$(libintl_FULL_NAME),$(MAJOR_VERSION)) +endif + +$(libintl_OUT)/libintl_so.a: $(libintl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libintl_OUT)/libintl.oS: $(libintl_MSRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libintl.a: $(libintl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(libintl_MOBJ): $(libintl_MSRC) + $(compile.m) + +$(libintl_MOBJ:.o=.os): $(libintl_MSRC) + $(compile.m) + +libintl_clean: + $(do_rm) $(addprefix $(libintl_OUT)/*., o os oS a) diff --git a/libintl/intl.c b/libintl/intl.c new file mode 100644 index 0000000..e42a999 --- /dev/null +++ b/libintl/intl.c @@ -0,0 +1,154 @@ +/* Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Stub version of libintl. + * + * Aug 30, 2003 + * Add some hidden names to support locale-enabled libstd++. + */ + +#include +#include +#include + +#undef __OPTIMIZE__ +#include + +/**********************************************************************/ +#ifdef L_gettext + +char *gettext(const char *msgid) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_dgettext + +char *dgettext(const char *domainname, + const char *msgid) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_dcgettext + +char *dcgettext(const char *domainname, + const char *msgid, int category) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_ngettext + +char *ngettext(const char *msgid1, const char *msgid2, + unsigned long int n) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_dngettext + +char *dngettext(const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_dcngettext + +char *dcngettext(const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n, + int category) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_textdomain + +char *textdomain(const char *domainname) +{ + static const char default_str[] = "messages"; + + if (domainname && *domainname && strcmp(domainname, default_str)) { + __set_errno(EINVAL); + return NULL; + } + return (char *) default_str; +} + +#endif +/**********************************************************************/ +#ifdef L_bindtextdomain + +char *bindtextdomain(const char *domainname, const char *dirname) +{ + static const char dir[] = "/"; + + if (!domainname || !*domainname + || (dirname +#if 1 + && ((dirname[0] != '/') || dirname[1]) +#else + && strcmp(dirname, dir) +#endif + ) + ) { + __set_errno(EINVAL); + return NULL; + } + + return (char *) dir; +} + +#endif +/**********************************************************************/ +#ifdef L_bind_textdomain_codeset + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +char *bind_textdomain_codeset(const char *domainname, const char *codeset) +{ + if (!domainname || !*domainname || codeset) { + __set_errno(EINVAL); + } + return NULL; +} + +#endif +/**********************************************************************/ +#ifdef L__nl_expand_alias + +/* glibc-ism */ + +const char *_nl_expand_alias(const char * name); +const char *_nl_expand_alias(const char * name) +{ + return NULL; /* uClibc does not support locale aliases. */ +} + +#endif +/**********************************************************************/ +#ifdef L__nl_msg_cat_cntr + +/* glibc-ism */ + +int _nl_msg_cat_cntr = 0; + +#endif +/**********************************************************************/ diff --git a/libm/Makefile b/libm/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libm/Makefile.in b/libm/Makefile.in new file mode 100644 index 0000000..9ddd8c8 --- /dev/null +++ b/libm/Makefile.in @@ -0,0 +1,207 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# The routines included in this math library are derived from the +# math library for Apple's MacOS X/Darwin math library, which was +# itself swiped from FreeBSD. The original copyright information +# is as follows: +# +# 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. +# +# It has been ported to work with uClibc and generally behave +# by Erik Andersen +# + +CFLAGS-libm := -DNOT_IN_libc -DIS_IN_libm $(SSP_ALL_CFLAGS) +CFLAGS-libm += -D_IEEE_LIBM + +LDFLAGS-libm.so := $(LDFLAGS) + +LIBS-libm.so := $(LIBS) + +libm_FULL_NAME := libm-$(VERSION).so + +libm_DIR:=$(top_srcdir)libm +libm_OUT:=$(top_builddir)libm + +# Fix builds for powerpc as there are different cores in this +# section now.` +ifeq ($(TARGET_ARCH)-$(CONFIG_E500),powerpc-y) +libm_ARCH_DIR:=$(libm_DIR)/$(TARGET_ARCH)/e500 +libm_ARCH_OUT:=$(libm_OUT)/$(TARGET_ARCH)/e500 +else +libm_ARCH_DIR:=$(libm_DIR)/$(TARGET_ARCH) +libm_ARCH_OUT:=$(libm_OUT)/$(TARGET_ARCH) +endif + +libm_ARCH_fpu_DIR:=$(libm_ARCH_DIR)/fpu +libm_ARCH_fpu_OUT:=$(libm_ARCH_OUT)/fpu + +ifeq ($(UCLIBC_HAS_FPU),y) +ifeq ($(DO_C99_MATH),y) +-include $(libm_ARCH_DIR)/Makefile.arch +endif +endif + +FL_MSRC := float_wrappers.c +LD_MSRC := ldouble_wrappers.c + +ifeq ($(DO_C99_MATH),y) +libm_CSRC := \ + e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \ + e_exp.c e_fmod.c e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ + e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c e_log.c e_log2.c e_log10.c \ + e_pow.c e_remainder.c e_rem_pio2.c e_scalb.c e_sinh.c \ + e_sqrt.c k_cos.c k_rem_pio2.c k_sin.c k_standard.c k_tan.c \ + s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c s_cos.c \ + s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c s_frexp.c \ + s_ilogb.c s_ldexp.c s_lib_version.c s_lrint.c s_lround.c s_llround.c \ + s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c s_round.c \ + s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c s_tan.c \ + s_tanh.c s_trunc.c w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c \ + w_cabs.c w_cosh.c w_drem.c w_exp.c w_fmod.c w_gamma.c \ + w_hypot.c w_j0.c w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ + w_log.c w_log2.c w_log10.c w_pow.c w_remainder.c w_scalb.c w_sinh.c \ + w_sqrt.c nan.c carg.c s_llrint.c \ + s_fpclassify.c s_fpclassifyf.c s_signbit.c s_signbitf.c \ + s_isnan.c s_isnanf.c s_isinf.c s_isinff.c s_finitef.c \ + s_fdim.c s_fma.c s_fmax.c s_fmin.c s_nearbyint.c \ + s_remquo.c s_scalbln.c w_exp2.c w_tgamma.c +# REMOVED: w_gamma_r.c +FL_MOBJ := \ + acosf.o acoshf.o asinf.o asinhf.o atan2f.o atanf.o atanhf.o cbrtf.o \ + ceilf.o copysignf.o cosf.o coshf.o erfcf.o erff.o exp2f.o expf.o \ + expm1f.o fabsf.o fdimf.o floorf.o fmaf.o fmaxf.o fminf.o fmodf.o \ + frexpf.o hypotf.o ilogbf.o ldexpf.o lgammaf.o llroundf.o log10f.o \ + log1pf.o log2f.o logbf.o logf.o lrintf.o lroundf.o modff.o nearbyintf.o \ + nextafterf.o powf.o remainderf.o remquof.o rintf.o roundf.o \ + scalblnf.o scalbnf.o sinf.o sinhf.o sqrtf.o tanf.o tanhf.o \ + tgammaf.o truncf.o cargf.o llrintf.o + +LD_MOBJ := acoshl.o acosl.o asinhl.o asinl.o atan2l.o atanhl.o atanl.o cbrtl.o \ + ceill.o copysignl.o coshl.o cosl.o erfcl.o erfl.o exp2l.o expl.o \ + expm1l.o fabsl.o fdiml.o floorl.o fmal.o fmaxl.o fminl.o fmodl.o \ + frexpl.o gammal.o hypotl.o ilogbl.o ldexpl.o lgammal.o llrintl.o \ + llroundl.o log10l.o log1pl.o XXXlog2l.o logbl.o logl.o lrintl.o lroundl.o \ + modfl.o nearbyintl.o nextafterl.o XXXnexttowardl.o powl.o remainderl.o \ + remquol.o rintl.o roundl.o scalblnl.o scalbnl.o sinhl.o sinl.o sqrtl.o \ + tanhl.o tanl.o tgammal.o truncl.o +else +# This list of math functions was taken from POSIX/IEEE 1003.1b-1993 +libm_CSRC := \ + w_acos.c w_asin.c s_atan.c w_atan2.c s_ceil.c s_cos.c \ + w_cosh.c w_exp.c s_fabs.c s_floor.c w_fmod.c s_frexp.c \ + s_ldexp.c w_log.c w_log10.c s_modf.c w_pow.c s_sin.c \ + w_sinh.c w_sqrt.c s_tan.c s_tanh.c \ + s_expm1.c s_scalbn.c s_copysign.c e_acos.c e_asin.c e_atan2.c \ + k_cos.c e_cosh.c e_exp.c e_fmod.c e_log.c e_log10.c e_pow.c \ + k_sin.c e_sinh.c e_sqrt.c k_tan.c e_rem_pio2.c k_rem_pio2.c \ + s_finite.c +# We'll add sqrtf to avoid problems with libstdc++ +FL_MOBJ := sqrtf.o +endif + +# assume that arch specific versions are provided as single sources/objects +ifeq ($(UCLIBC_HAS_FPU),y) +ifeq ($(DO_C99_MATH),y) +ifneq ($(strip $(libm_ARCH_OBJS)),) +ifeq ($(TARGET_ARCH)-$(CONFIG_E500),powerpc-y) +CFLAGS-libm/$(TARGET_ARCH)/e500/ := $(CFLAGS-libm) +else +CFLAGS-libm/$(TARGET_ARCH)/ := $(CFLAGS-libm) +endif + +# remove generic sources, if arch specific version is present +ifneq ($(strip $(libm_ARCH_SRC)),) +libm_CSRC := $(filter-out $(notdir $(libm_ARCH_SRC)),$(libm_CSRC)) +endif + +# remove generic objects built from multi-sources, if arch specific version is present +FL_MOBJ := $(filter-out $(notdir $(libm_ARCH_OBJS)),$(FL_MOBJ)) +LD_MOBJ := $(filter-out $(notdir $(libm_ARCH_OBJS)),$(LD_MOBJ)) + +# we also try to remove % if s_% is in arch specific subdir +FL_MOBJ := $(filter-out $(patsubst s_%.o,%.o,$(notdir $(libm_ARCH_OBJS))),$(FL_MOBJ)) +LD_MOBJ := $(filter-out $(patsubst s_%.o,%.o,$(notdir $(libm_ARCH_OBJS))),$(LD_MOBJ)) +endif +endif +endif + +libm_SRC := $(patsubst %.c,$(libm_DIR)/%.c,$(libm_CSRC)) +libm_OBJ := $(patsubst $(libm_DIR)/%.c,$(libm_OUT)/%.o,$(libm_SRC)) + +ifeq ($(strip $(UCLIBC_HAS_LONG_DOUBLE_MATH)),y) +libm_MSRC2 := $(libm_DIR)/$(LD_MSRC) +libm_MOBJ2 := $(patsubst %.o,$(libm_OUT)/%.o,$(LD_MOBJ)) +endif +libm_MSRC := $(libm_DIR)/$(FL_MSRC) +libm_MOBJ := $(patsubst %.o,$(libm_OUT)/%.o,$(FL_MOBJ)) + + +ifneq ($(DOMULTI),n) +CFLAGS-libm += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libm_MOBJ)))) +ifeq ($(strip $(UCLIBC_HAS_LONG_DOUBLE_MATH)),y) +CFLAGS-libm += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libm_MOBJ2)))) +endif +endif + +libm_OBJS := $(libm_OBJ) $(libm_MOBJ) $(libm_MOBJ2) + +ifeq ($(DOPIC),y) +libm-a-y += $(libm_OBJS:.o=.os) +else +libm-a-y += $(libm_OBJS) +endif +libm-so-y += $(libm_OBJS:.o=.os) + +lib-a-$(UCLIBC_HAS_FLOATS) += $(top_builddir)lib/libm.a +lib-so-$(UCLIBC_HAS_FLOATS) += $(top_builddir)lib/libm.so +objclean-y += libm_clean + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libm.so: $(top_builddir)lib/libm.a $(libc.depend) +else +$(top_builddir)lib/libm.so: $(libm_OUT)/libm_so.a $(libc.depend) +endif + $(call link.so,$(libm_FULL_NAME),$(MAJOR_VERSION)) +else +$(top_builddir)lib/libm.so: $(libm_OUT)/libm.oS | $(libc.depend) + $(call linkm.so,$(libm_FULL_NAME),$(MAJOR_VERSION)) +endif + +$(libm_OUT)/libm_so.a: $(libm-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libm_OUT)/libm.oS: $(libm_SRC) $(libm_MSRC) $(libm_MSRC2) $(libm_ARCH_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libm.a: $(libm-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(libm_MOBJ): $(libm_MSRC) + $(compile.m) + +$(libm_MOBJ2): $(libm_MSRC2) + $(compile.m) + +$(libm_MOBJ:.o=.os): $(libm_MSRC) + $(compile.m) + +$(libm_MOBJ2:.o=.os): $(libm_MSRC2) + $(compile.m) + +libm_clean: + $(do_rm) $(addprefix $(libm_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*. */*/*.,$(d)$(e)))) diff --git a/libm/README b/libm/README new file mode 100644 index 0000000..2c69a54 --- /dev/null +++ b/libm/README @@ -0,0 +1,16 @@ +The routines included in this math library are derived from the +math library for Apple's MacOS X/Darwin math library, which was +itself swiped from FreeBSD. The original copyright information +is as follows: + + 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. + +It has been ported to work with uClibc and generally behave +by Erik Andersen + 22 May, 2001 + diff --git a/libm/carg.c b/libm/carg.c new file mode 100644 index 0000000..7b290b0 --- /dev/null +++ b/libm/carg.c @@ -0,0 +1,29 @@ +/* Compute argument of complex double value. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +double +carg (__complex__ double x) +{ + return atan2 (__imag__ x, __real__ x); +} +libm_hidden_def(carg) diff --git a/libm/e_acos.c b/libm/e_acos.c new file mode 100644 index 0000000..2656193 --- /dev/null +++ b/libm/e_acos.c @@ -0,0 +1,111 @@ +/* @(#)e_acos.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_acos.c,v 1.9 1995/05/12 04:57:13 jtc Exp $"; +#endif + +/* __ieee754_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: __ieee754_sqrt + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_acos(double x) +#else + double attribute_hidden __ieee754_acos(x) + double x; +#endif +{ + 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 */ + u_int32_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 = __ieee754_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 = __ieee754_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/libm/e_acosh.c b/libm/e_acosh.c new file mode 100644 index 0000000..3d0a038 --- /dev/null +++ b/libm/e_acosh.c @@ -0,0 +1,70 @@ +/* @(#)e_acosh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_acosh.c,v 1.9 1995/05/12 04:57:18 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.0, +ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_acosh(double x) +#else + double attribute_hidden __ieee754_acosh(x) + double x; +#endif +{ + double t; + int32_t hx; + u_int32_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 __ieee754_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 __ieee754_log(2.0*x-one/(x+__ieee754_sqrt(t-one))); + } else { /* 10.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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_asin(double x) +#else + double attribute_hidden __ieee754_asin(x) + double x; +#endif +{ + 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 */ + u_int32_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 = __ieee754_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/libm/e_atan2.c b/libm/e_atan2.c new file mode 100644 index 0000000..407a129 --- /dev/null +++ b/libm/e_atan2.c @@ -0,0 +1,131 @@ +/* @(#)e_atan2.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_atan2.c,v 1.8 1995/05/10 20:44:51 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_atan2(double y, double x) +#else + double attribute_hidden __ieee754_atan2(y,x) + double y,x; +#endif +{ + double z; + int32_t k,m,hx,hy,ix,iy; + u_int32_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: { + u_int32_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/libm/e_atanh.c b/libm/e_atanh.c new file mode 100644 index 0000000..c6c47bc --- /dev/null +++ b/libm/e_atanh.c @@ -0,0 +1,75 @@ +/* @(#)e_atanh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_atanh.c,v 1.8 1995/05/10 20:44:55 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double one = 1.0, huge = 1e300; +#else +static double one = 1.0, huge = 1e300; +#endif + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_atanh(double x) +#else + double attribute_hidden __ieee754_atanh(x) + double x; +#endif +{ + double t; + int32_t hx,ix; + u_int32_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/libm/e_cosh.c b/libm/e_cosh.c new file mode 100644 index 0000000..a7e5e44 --- /dev/null +++ b/libm/e_cosh.c @@ -0,0 +1,94 @@ +/* @(#)e_cosh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_cosh.c,v 1.7 1995/05/10 20:44:58 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double one = 1.0, half=0.5, huge = 1.0e300; +#else +static double one = 1.0, half=0.5, huge = 1.0e300; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_cosh(double x) +#else + double attribute_hidden __ieee754_cosh(x) + double x; +#endif +{ + double t,w; + int32_t ix; + u_int32_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 = __ieee754_exp(fabs(x)); + return half*t+half/t; + } + + /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ + if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x)); + + /* |x| in [log(maxdouble), overflowthresold] */ + GET_LOW_WORD(lx,x); + if (ix<0x408633CE || + ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) { + w = __ieee754_exp(half*fabs(x)); + t = half*w; + return t*w; + } + + /* |x| > overflowthresold, cosh(x) overflow */ + return huge*huge; +} diff --git a/libm/e_exp.c b/libm/e_exp.c new file mode 100644 index 0000000..f9c5371 --- /dev/null +++ b/libm/e_exp.c @@ -0,0 +1,172 @@ +/* @(#)e_exp.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_exp.c,v 1.8 1995/05/10 20:45:03 jtc Exp $"; +#endif + +/* __ieee754_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 Reme 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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + + +#ifdef __STDC__ + double attribute_hidden __ieee754_exp(double x) /* default IEEE double exp */ +#else + double attribute_hidden __ieee754_exp(x) /* default IEEE double exp */ + double x; +#endif +{ + double y; + double hi = 0.0; + double lo = 0.0; + double c; + double t; + int32_t k=0; + int32_t xsb; + u_int32_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) { + u_int32_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 = 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) { + u_int32_t hy; + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(y,hy+(k<<20)); /* add k to y's exponent */ + return y; + } else { + u_int32_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/libm/e_fmod.c b/libm/e_fmod.c new file mode 100644 index 0000000..1e8487c --- /dev/null +++ b/libm/e_fmod.c @@ -0,0 +1,140 @@ +/* @(#)e_fmod.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_fmod.c,v 1.8 1995/05/10 20:45:07 jtc Exp $"; +#endif + +/* + * __ieee754_fmod(x,y) + * Return x mod y in exact arithmetic + * Method: shift and subtract + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double one = 1.0, Zero[] = {0.0, -0.0,}; +#else +static double one = 1.0, Zero[] = {0.0, -0.0,}; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_fmod(double x, double y) +#else + double attribute_hidden __ieee754_fmod(x,y) + double x,y ; +#endif +{ + int32_t n,hx,hy,hz,ix,iy,sx,i; + u_int32_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>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<>(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<>(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>31); lx = lx+lx;} + else { + if((hz|lz)==0) /* return sign(x)*0 */ + return Zero[(u_int32_t)sx>>31]; + hx = hz+hz+(lz>>31); lx = lz+lz; + } + } + hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} + + /* convert back to floating value and restore the sign */ + if((hx|lx)==0) /* return sign(x)*0 */ + return Zero[(u_int32_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)|((u_int32_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/libm/e_gamma.c b/libm/e_gamma.c new file mode 100644 index 0000000..05b3b86 --- /dev/null +++ b/libm/e_gamma.c @@ -0,0 +1,34 @@ + +/* @(#)e_gamma.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. + * ==================================================== + * + */ + +/* __ieee754_gamma(x) + * Return the logarithm of the Gamma function of x. + * + * Method: call __ieee754_gamma_r + */ + +#include +#include "math_private.h" + +libm_hidden_proto(signgam) +#ifdef __STDC__ + /* __private_extern__ */ + double attribute_hidden __ieee754_gamma(double x) +#else + double attribute_hidden __ieee754_gamma(x) + double x; +#endif +{ + return __ieee754_gamma_r(x,&signgam); +} diff --git a/libm/e_gamma_r.c b/libm/e_gamma_r.c new file mode 100644 index 0000000..620f692 --- /dev/null +++ b/libm/e_gamma_r.c @@ -0,0 +1,33 @@ + +/* @(#)e_gamma_r.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. + * ==================================================== + * + */ + +/* __ieee754_gamma_r(x, signgamp) + * Reentrant version of the logarithm of the Gamma function + * with user provide pointer for the sign of Gamma(x). + * + * Method: See __ieee754_lgamma_r + */ + +#include "math_private.h" + +#ifdef __STDC__ + /* __private_extern__ */ + double attribute_hidden __ieee754_gamma_r(double x, int *signgamp) +#else + double attribute_hidden __ieee754_gamma_r(x,signgamp) + double x; int *signgamp; +#endif +{ + return __ieee754_lgamma_r(x,signgamp); +} diff --git a/libm/e_hypot.c b/libm/e_hypot.c new file mode 100644 index 0000000..62acc8d --- /dev/null +++ b/libm/e_hypot.c @@ -0,0 +1,128 @@ +/* @(#)e_hypot.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; +#endif + +/* __ieee754_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" + +#ifdef __STDC__ + double attribute_hidden __ieee754_hypot(double x, double y) +#else + double attribute_hidden __ieee754_hypot(x,y) + double x, y; +#endif +{ + 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 */ + u_int32_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 */ + u_int32_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 = __ieee754_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 = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); + } + if(k!=0) { + u_int32_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/libm/e_j0.c b/libm/e_j0.c new file mode 100644 index 0000000..7778788 --- /dev/null +++ b/libm/e_j0.c @@ -0,0 +1,488 @@ +/* @(#)e_j0.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_j0.c,v 1.8 1995/05/10 20:45:23 jtc Exp $"; +#endif + +/* __ieee754_j0(x), __ieee754_y0(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; + * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * where + * U(z) = u00 + u01*z + ... + u06*z^6 + * V(z) = 1 + v01*z + ... + v04*z^4 + * with absolute approximation error bounded by 2**-72. + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ +static double pzero(double), qzero(double); +#else +static double pzero(), qzero(); +#endif + +#ifdef __STDC__ +static const double +#else +static double +#endif +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0, 2.00] */ +R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ +R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ +R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ +R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ +S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ +S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ +S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ +S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_j0(double x) +#else + double attribute_hidden __ieee754_j0(x) + double x; +#endif +{ + double z, s,c,ss,cc,r,u,v; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/(x*x); + x = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*cc)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*cc-v*ss)/sqrt(x); + } + return z; + } + if(ix<0x3f200000) { /* |x| < 2**-13 */ + if(huge+x>one) { /* raise inexact if x != 0 */ + if(ix<0x3e400000) return one; /* |x|<2**-27 */ + else return one - 0.25*x*x; + } + } + z = x*x; + r = z*(R02+z*(R03+z*(R04+z*R05))); + s = one+z*(S01+z*(S02+z*(S03+z*S04))); + if(ix < 0x3FF00000) { /* |x| < 1.00 */ + return one + z*(-0.25+(r/s)); + } else { + u = 0.5*x; + return((one+u)*(one-u)+z*(r/s)); + } +} + +#ifdef __STDC__ +static const double +#else +static double +#endif +u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ +u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ +u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ +u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ +u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ +u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ +u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ +v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ +v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ +v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ +v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ + +#ifdef __STDC__ + double attribute_hidden __ieee754_y0(double x) +#else + double attribute_hidden __ieee754_y0(x) + double x; +#endif +{ + double z, s,c,ss,cc,u,v; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*ss)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if(ix<=0x3e400000) { /* x < 2**-27 */ + return(u00 + tpi*__ieee754_log(x)); + } + z = x*x; + u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); + v = one+z*(v01+z*(v02+z*(v03+z*v04))); + return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 + * S = 1 + pS0*s^2 + ... + pS4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +#ifdef __STDC__ +static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ + -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ + -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ + -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ + -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ +}; +#ifdef __STDC__ +static const double pS8[5] = { +#else +static double pS8[5] = { +#endif + 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ + 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ + 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ + 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ + 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ +}; + +#ifdef __STDC__ +static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ + -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ + -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ + -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ + -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ + -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ +}; +#ifdef __STDC__ +static const double pS5[5] = { +#else +static double pS5[5] = { +#endif + 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ + 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ + 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ + 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ + 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ +}; + +#ifdef __STDC__ +static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#else +static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ + -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ + -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ + -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ + -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ + -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ +}; +#ifdef __STDC__ +static const double pS3[5] = { +#else +static double pS3[5] = { +#endif + 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ + 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ + 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ + 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ + 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ +}; + +#ifdef __STDC__ +static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ + -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ + -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ + -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ + -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ + -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ +}; +#ifdef __STDC__ +static const double pS2[5] = { +#else +static double pS2[5] = { +#endif + 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ + 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ + 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ + 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ + 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ +}; + +#ifdef __STDC__ + static double pzero(double x) +#else + static double pzero(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p = 0,*q = 0; +#else + double *p,*q; +#endif + double z,r,s; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pR8; q= pS8;} + else if(ix>=0x40122E8B){p = pR5; q= pS5;} + else if(ix>=0x4006DB6D){p = pR3; q= pS3;} + else if(ix>=0x40000000){p = pR2; q= pS2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 + * S = 1 + qS0*s^2 + ... + qS5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +#ifdef __STDC__ +static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ + 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ + 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ + 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ + 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ +}; +#ifdef __STDC__ +static const double qS8[6] = { +#else +static double qS8[6] = { +#endif + 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ + 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ + 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ + 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ + 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ + -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ +}; + +#ifdef __STDC__ +static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ + 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ + 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ + 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ + 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ + 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ +}; +#ifdef __STDC__ +static const double qS5[6] = { +#else +static double qS5[6] = { +#endif + 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ + 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ + 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ + 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ + 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ + -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ +}; + +#ifdef __STDC__ +static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#else +static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ + 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ + 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ + 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ + 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ + 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ +}; +#ifdef __STDC__ +static const double qS3[6] = { +#else +static double qS3[6] = { +#endif + 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ + 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ + 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ + 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ + 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ + -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ +}; + +#ifdef __STDC__ +static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ + 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ + 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ + 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ + 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ + 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ +}; +#ifdef __STDC__ +static const double qS2[6] = { +#else +static double qS2[6] = { +#endif + 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ + 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ + 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ + 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ + 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ + -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ +}; + +#ifdef __STDC__ + static double qzero(double x) +#else + static double qzero(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p=0,*q=0; +#else + double *p,*q; +#endif + double s,r,z; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qR8; q= qS8;} + else if(ix>=0x40122E8B){p = qR5; q= qS5;} + else if(ix>=0x4006DB6D){p = qR3; q= qS3;} + else if(ix>=0x40000000){p = qR2; q= qS2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (-.125 + r/s)/x; +} diff --git a/libm/e_j1.c b/libm/e_j1.c new file mode 100644 index 0000000..4b4274a --- /dev/null +++ b/libm/e_j1.c @@ -0,0 +1,487 @@ +/* @(#)e_j1.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_j1.c,v 1.8 1995/05/10 20:45:27 jtc Exp $"; +#endif + +/* __ieee754_j1(x), __ieee754_y1(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follow: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * where for x in [0,2] (abs err less than 2**-65.89) + * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 + * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ +static double pone(double), qone(double); +#else +static double pone(), qone(); +#endif + +#ifdef __STDC__ +static const double +#else +static double +#endif +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0,2] */ +r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ +r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ +r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ +r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ +s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ +s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ +s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ +s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ +s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_j1(double x) +#else + double attribute_hidden __ieee754_j1(x) + double x; +#endif +{ + double z, s,c,ss,cc,r,u,v,y; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/x; + y = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(y); + c = cos(y); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure y+y not overflow */ + z = cos(y+y); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* + * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) + * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) + */ + if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y); + else { + u = pone(y); v = qone(y); + z = invsqrtpi*(u*cc-v*ss)/sqrt(y); + } + if(hx<0) return -z; + else return z; + } + if(ix<0x3e400000) { /* |x|<2**-27 */ + if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ + } + z = x*x; + r = z*(r00+z*(r01+z*(r02+z*r03))); + s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); + r *= x; + return(x*0.5+r/s); +} + +#ifdef __STDC__ +static const double U0[5] = { +#else +static double U0[5] = { +#endif + -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ + 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ + -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ + 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ + -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ +}; +#ifdef __STDC__ +static const double V0[5] = { +#else +static double V0[5] = { +#endif + 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ + 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ + 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ + 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ + 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ +}; + +#ifdef __STDC__ + double attribute_hidden __ieee754_y1(double x) +#else + double attribute_hidden __ieee754_y1(x) + double x; +#endif +{ + double z, s,c,ss,cc,u,v; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = cos(x+x); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x); + else { + u = pone(x); v = qone(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if(ix<=0x3c900000) { /* x < 2**-54 */ + return(-tpi/x); + } + z = x*x; + u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); + v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); + return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); +} + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +#ifdef __STDC__ +static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ + 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ + 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ + 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ + 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ +}; +#ifdef __STDC__ +static const double ps8[5] = { +#else +static double ps8[5] = { +#endif + 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ + 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ + 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ + 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ + 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ +}; + +#ifdef __STDC__ +static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ + 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ + 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ + 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ + 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ + 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ +}; +#ifdef __STDC__ +static const double ps5[5] = { +#else +static double ps5[5] = { +#endif + 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ + 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ + 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ + 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ + 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ +}; + +#ifdef __STDC__ +static const double pr3[6] = { +#else +static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ + 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ + 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ + 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ + 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ + 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ +}; +#ifdef __STDC__ +static const double ps3[5] = { +#else +static double ps3[5] = { +#endif + 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ + 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ + 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ + 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ + 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ +}; + +#ifdef __STDC__ +static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ + 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ + 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ + 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ + 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ + 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ +}; +#ifdef __STDC__ +static const double ps2[5] = { +#else +static double ps2[5] = { +#endif + 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ + 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ + 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ + 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ + 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ +}; + +#ifdef __STDC__ + static double pone(double x) +#else + static double pone(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p=0,*q=0; +#else + double *p,*q; +#endif + double z,r,s; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pr8; q= ps8;} + else if(ix>=0x40122E8B){p = pr5; q= ps5;} + else if(ix>=0x4006DB6D){p = pr3; q= ps3;} + else if(ix>=0x40000000){p = pr2; q= ps2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +#ifdef __STDC__ +static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#else +static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ +#endif + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ + -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ + -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ + -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ + -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ +}; +#ifdef __STDC__ +static const double qs8[6] = { +#else +static double qs8[6] = { +#endif + 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ + 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ + 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ + 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ + 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ + -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ +}; + +#ifdef __STDC__ +static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#else +static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ +#endif + -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ + -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ + -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ + -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ + -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ + -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ +}; +#ifdef __STDC__ +static const double qs5[6] = { +#else +static double qs5[6] = { +#endif + 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ + 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ + 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ + 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ + 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ + -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ +}; + +#ifdef __STDC__ +static const double qr3[6] = { +#else +static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ +#endif + -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ + -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ + -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ + -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ + -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ + -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ +}; +#ifdef __STDC__ +static const double qs3[6] = { +#else +static double qs3[6] = { +#endif + 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ + 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ + 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ + 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ + 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ + -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ +}; + +#ifdef __STDC__ +static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#else +static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ +#endif + -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ + -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ + -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ + -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ + -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ + -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ +}; +#ifdef __STDC__ +static const double qs2[6] = { +#else +static double qs2[6] = { +#endif + 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ + 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ + 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ + 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ + 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ + -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ +}; + +#ifdef __STDC__ + static double qone(double x) +#else + static double qone(x) + double x; +#endif +{ +#ifdef __STDC__ + const double *p=0,*q=0; +#else + double *p,*q; +#endif + double s,r,z; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qr8; q= qs8;} + else if(ix>=0x40122E8B){p = qr5; q= qs5;} + else if(ix>=0x4006DB6D){p = qr3; q= qs3;} + else if(ix>=0x40000000){p = qr2; q= qs2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (.375 + r/s)/x; +} diff --git a/libm/e_jn.c b/libm/e_jn.c new file mode 100644 index 0000000..7771eaf --- /dev/null +++ b/libm/e_jn.c @@ -0,0 +1,282 @@ +/* @(#)e_jn.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $"; +#endif + +/* + * __ieee754_jn(n, x), __ieee754_yn(n, x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ +one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ + +#ifdef __STDC__ +static const double zero = 0.00000000000000000000e+00; +#else +static double zero = 0.00000000000000000000e+00; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_jn(int n, double x) +#else + double attribute_hidden __ieee754_jn(n,x) + int n; double x; +#endif +{ + int32_t i,hx,ix,lx, sgn; + double a, b, temp=0, di; + double z, w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if J(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if(n<0){ + n = -n; + x = -x; + hx ^= 0x80000000; + } + if(n==0) return(__ieee754_j0(x)); + if(n==1) return(__ieee754_j1(x)); + sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ + x = fabs(x); + if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ + b = zero; + else if((double)n<=x) { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch(n&3) { + case 0: temp = cos(x)+sin(x); break; + case 1: temp = -cos(x)+sin(x); break; + case 2: temp = -cos(x)-sin(x); break; + case 3: temp = cos(x)-sin(x); break; + } + b = invsqrtpi*temp/sqrt(x); + } else { + a = __ieee754_j0(x); + b = __ieee754_j1(x); + for(i=1;i33) /* underflow */ + b = zero; + else { + temp = x*0.5; b = temp; + for (a=one,i=2;i<=n;i++) { + a *= (double)i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + b = b/a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + double t,v; + double q0,q1,h,tmp; int32_t k,m; + w = (n+n)/(double)x; h = 2.0/(double)x; + q0 = w; z = w+h; q1 = w*z - 1.0; k=1; + while(q1<1.0e9) { + k += 1; z += h; + tmp = z*q1 - q0; + q0 = q1; + q1 = tmp; + } + m = n+n; + for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = n; + v = two/x; + tmp = tmp*__ieee754_log(fabs(v*tmp)); + if(tmp<7.09782712893383973096e+02) { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + } + } else { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + /* scale b to avoid spurious overflow */ + if(b>1e100) { + a /= b; + t /= b; + b = one; + } + } + } + b = (t*__ieee754_j0(x)/b); + } + } + if(sgn==1) return -b; else return b; +} + +#ifdef __STDC__ + double attribute_hidden __ieee754_yn(int n, double x) +#else + double attribute_hidden __ieee754_yn(n,x) + int n; double x; +#endif +{ + int32_t i,hx,ix,lx; + int32_t sign; + double a, b, temp=0; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + sign = 1; + if(n<0){ + n = -n; + sign = 1 - ((n&1)<<1); + } + if(n==0) return(__ieee754_y0(x)); + if(n==1) return(sign*__ieee754_y1(x)); + if(ix==0x7ff00000) return zero; + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch(n&3) { + case 0: temp = sin(x)-cos(x); break; + case 1: temp = -sin(x)-cos(x); break; + case 2: temp = -sin(x)+cos(x); break; + case 3: temp = sin(x)+cos(x); break; + } + b = invsqrtpi*temp/sqrt(x); + } else { + u_int32_t high; + a = __ieee754_y0(x); + b = __ieee754_y1(x); + /* quit if b is -inf */ + GET_HIGH_WORD(high,b); + for(i=1;i0) return b; else return -b; +} diff --git a/libm/e_lgamma.c b/libm/e_lgamma.c new file mode 100644 index 0000000..af7cccf --- /dev/null +++ b/libm/e_lgamma.c @@ -0,0 +1,34 @@ + +/* @(#)e_lgamma.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. + * ==================================================== + * + */ + +/* __ieee754_lgamma(x) + * Return the logarithm of the Gamma function of x. + * + * Method: call __ieee754_lgamma_r + */ + +#include +#include "math_private.h" + +libm_hidden_proto(signgam) +#ifdef __STDC__ + /* __private_extern__ */ + double attribute_hidden __ieee754_lgamma(double x) +#else + double attribute_hidden __ieee754_lgamma(x) + double x; +#endif +{ + return __ieee754_lgamma_r(x,&signgam); +} diff --git a/libm/e_lgamma_r.c b/libm/e_lgamma_r.c new file mode 100644 index 0000000..42b48b3 --- /dev/null +++ b/libm/e_lgamma_r.c @@ -0,0 +1,316 @@ +/* @(#)er_lgamma.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_lgamma_r.c,v 1.7 1995/05/10 20:45:42 jtc Exp $"; +#endif + +/* __ieee754_lgamma_r(x, signgamp) + * Reentrant version of the logarithm of the Gamma function + * with user provide pointer for the sign of Gamma(x). + * + * Method: + * 1. Argument Reduction for 0 < x <= 8 + * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may + * reduce x to a number in [1.5,2.5] by + * lgamma(1+s) = log(s) + lgamma(s) + * for example, + * lgamma(7.3) = log(6.3) + lgamma(6.3) + * = log(6.3*5.3) + lgamma(5.3) + * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) + * 2. Polynomial approximation of lgamma around its + * minimun ymin=1.461632144968362245 to maintain monotonicity. + * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + * Let z = x-ymin; + * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) + * where + * poly(z) is a 14 degree polynomial. + * 2. Rational approximation in the primary interval [2,3] + * We use the following approximation: + * s = x-2.0; + * lgamma(x) = 0.5*s + s*P(s)/Q(s) + * with accuracy + * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 + * Our algorithms are based on the following observation + * + * zeta(2)-1 2 zeta(3)-1 3 + * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + * 2 3 + * + * where Euler = 0.5771... is the Euler constant, which is very + * close to 0.5. + * + * 3. For x>=8, we have + * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + * (better formula: + * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + * Let z = 1/x, then we approximation + * f(z) = lgamma(x) - (x-0.5)(log(x)-1) + * by + * 3 5 11 + * w = w0 + w1*z + w2*z + w3*z + ... + w6*z + * where + * |w - f(z)| < 2**-58.74 + * + * 4. For negative x, since (G is gamma function) + * -x*G(-x)*G(x) = pi/sin(pi*x), + * we have + * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) + * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 + * Hence, for x<0, signgam = sign(sin(pi*x)) and + * lgamma(x) = log(|Gamma(x)|) + * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); + * Note: one should avoid compute pi*(-x) directly in the + * computation of sin(pi*(-x)). + * + * 5. Special Cases + * lgamma(2+s) ~ s*(1-Euler) for tiny s + * lgamma(1)=lgamma(2)=0 + * lgamma(x) ~ -log(x) for tiny x + * lgamma(0) = lgamma(inf) = inf + * lgamma(-integer) = +-inf + * + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ +a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ +a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ +a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ +a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ +a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ +a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ +a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ +a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ +a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ +a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ +a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ +tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ +tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ +/* tt = -(tail of tf) */ +tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ +t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ +t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ +t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ +t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ +t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ +t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ +t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ +t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ +t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ +t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ +t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ +t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ +t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ +t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ +t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ +u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ +u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ +u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ +u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ +u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ +v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ +v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ +v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ +v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ +v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ +s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ +s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ +s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ +s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ +s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ +s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ +r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ +r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ +r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ +r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ +r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ +r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ +w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ +w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ +w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ +w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ +w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ +w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ +w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ + +#ifdef __STDC__ +static const double zero= 0.00000000000000000000e+00; +#else +static double zero= 0.00000000000000000000e+00; +#endif + +static +#ifdef __GNUC__ +__inline__ +#endif +#ifdef __STDC__ + double sin_pi(double x) +#else + double sin_pi(x) + double x; +#endif +{ + double y,z; + int n,ix; + + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + + if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0); + y = -x; /* x is assume negative */ + + /* + * argument reduction, make sure inexact flag not raised if input + * is an integer + */ + z = floor(y); + if(z!=y) { /* inexact anyway */ + y *= 0.5; + y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */ + n = (int) (y*4.0); + } else { + if(ix>=0x43400000) { + y = zero; n = 0; /* y must be even */ + } else { + if(ix<0x43300000) z = y+two52; /* exact */ + GET_LOW_WORD(n,z); + n &= 1; + y = n; + n<<= 2; + } + } + switch (n) { + case 0: y = __kernel_sin(pi*y,zero,0); break; + case 1: + case 2: y = __kernel_cos(pi*(0.5-y),zero); break; + case 3: + case 4: y = __kernel_sin(pi*(one-y),zero,0); break; + case 5: + case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; + default: y = __kernel_sin(pi*(y-2.0),zero,0); break; + } + return -y; +} + + +#ifdef __STDC__ + double attribute_hidden __ieee754_lgamma_r(double x, int *signgamp) +#else + double attribute_hidden __ieee754_lgamma_r(x,signgamp) + double x; int *signgamp; +#endif +{ + double t,y,z,nadj=0,p,p1,p2,p3,q,r,w; + int i,hx,lx,ix; + + EXTRACT_WORDS(hx,lx,x); + + /* purge off +-inf, NaN, +-0, and negative arguments */ + *signgamp = 1; + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return x*x; + if((ix|lx)==0) return one/zero; + if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ + if(hx<0) { + *signgamp = -1; + return -__ieee754_log(-x); + } else return -__ieee754_log(x); + } + if(hx<0) { + if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ + return one/zero; + t = sin_pi(x); + if(t==zero) return one/zero; /* -integer */ + nadj = __ieee754_log(pi/fabs(t*x)); + if(t=0x3FE76944) {y = one-x; i= 0;} + else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} + else {y = x; i=2;} + } else { + r = zero; + if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ + else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ + else {y=x-one;i=2;} + } + switch(i) { + case 0: + z = y*y; + p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); + p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); + p = y*p1+p2; + r += (p-0.5*y); break; + case 1: + z = y*y; + w = z*y; + p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ + p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); + p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); + p = z*p1-(tt-w*(p2+y*p3)); + r += (tf + p); break; + case 2: + p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); + p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); + r += (-0.5*y + p1/p2); + } + } + else if(ix<0x40200000) { /* x < 8.0 */ + i = (int)x; + t = zero; + y = x-(double)i; + p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); + q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); + r = half*y+p/q; + z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ + switch(i) { + case 7: z *= (y+6.0); /* FALLTHRU */ + case 6: z *= (y+5.0); /* FALLTHRU */ + case 5: z *= (y+4.0); /* FALLTHRU */ + case 4: z *= (y+3.0); /* FALLTHRU */ + case 3: z *= (y+2.0); /* FALLTHRU */ + r += __ieee754_log(z); break; + } + /* 8.0 <= x < 2**58 */ + } else if (ix < 0x43900000) { + t = __ieee754_log(x); + z = one/x; + y = z*z; + w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); + r = (x-half)*(t-one)+w; + } else + /* 2**58 <= x <= inf */ + r = x*(__ieee754_log(x)-one); + if(hx<0) r = nadj - r; + return r; +} diff --git a/libm/e_log.c b/libm/e_log.c new file mode 100644 index 0000000..fce0617 --- /dev/null +++ b/libm/e_log.c @@ -0,0 +1,147 @@ +/* @(#)e_log.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $"; +#endif + +/* __ieee754_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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_log(double x) +#else + double attribute_hidden __ieee754_log(x) + double x; +#endif +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_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/libm/e_log10.c b/libm/e_log10.c new file mode 100644 index 0000000..5b25c0f --- /dev/null +++ b/libm/e_log10.c @@ -0,0 +1,98 @@ +/* @(#)e_log10.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_log10.c,v 1.9 1995/05/10 20:45:51 jtc Exp $"; +#endif + +/* __ieee754_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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_log10(double x) +#else + double attribute_hidden __ieee754_log10(x) + double x; +#endif +{ + double y,z; + int32_t i,k,hx; + u_int32_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 = ((u_int32_t)k&0x80000000)>>31; + hx = (hx&0x000fffff)|((0x3ff-i)<<20); + y = (double)(k+i); + SET_HIGH_WORD(x,hx); + z = y*log10_2lo + ivln10*__ieee754_log(x); + return z+y*log10_2hi; +} diff --git a/libm/e_log2.c b/libm/e_log2.c new file mode 100644 index 0000000..894a96d --- /dev/null +++ b/libm/e_log2.c @@ -0,0 +1,130 @@ +/* Adapted for log2 by Ulrich Drepper . */ +/* + * ==================================================== + * 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_log2(x) + * Return the logarithm to base 2 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 + log(1+f). + * = k+(f-(hfsq-(s*(hfsq+R)))) + * + * Special cases: + * log2(x) is NaN with signal if x < 0 (including -INF) ; + * log2(+INF) is +INF; log(0) is -INF with signal; + * log2(NaN) is that NaN with no signal. + * + * 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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +ln2 = 0.69314718055994530942, +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 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double __ieee754_log2(double x) +#else + double __ieee754_log2(x) + double x; +#endif +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/(x-x); /* log(+-0)=-inf */ + if (hx<0) return (x-x)/(x-x); /* 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); + dk = (double) k; + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) return dk; + R = f*f*(0.5-0.33333333333333333*f); + return dk-(R-f)/ln2; + } + s = f/(2.0+f); + 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; + return dk-((hfsq-(s*(hfsq+R)))-f)/ln2; + } else { + return dk-((s*(f-R))-f)/ln2; + } +} diff --git a/libm/e_pow.c b/libm/e_pow.c new file mode 100644 index 0000000..53ec813 --- /dev/null +++ b/libm/e_pow.c @@ -0,0 +1,309 @@ +/* @(#)e_pow.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +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*/ + +#ifdef __STDC__ + double attribute_hidden __ieee754_pow(double x, double y) +#else + double attribute_hidden __ieee754_pow(x,y) + double x, y; +#endif +{ + 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; + u_int32_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 __ieee754_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; + } + } + + /* (x<0)**(non-int) is NaN */ + if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x); + + /* |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)? huge*huge:tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? huge*huge: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 = x-1; /* 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 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|>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 = 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 = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-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; + 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) = (s+..)*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); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0) + s = -one;/* (-ve)**(odd int) */ + + /* 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/libm/e_rem_pio2.c b/libm/e_rem_pio2.c new file mode 100644 index 0000000..92deaa3 --- /dev/null +++ b/libm/e_rem_pio2.c @@ -0,0 +1,184 @@ +/* @(#)e_rem_pio2.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $"; +#endif + +/* __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 + */ +#ifdef __STDC__ +static const int32_t two_over_pi[] = { +#else +static int32_t two_over_pi[] = { +#endif +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, +}; + +#ifdef __STDC__ +static const int32_t npio2_hw[] = { +#else +static int32_t npio2_hw[] = { +#endif +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) + */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + int32_t attribute_hidden __ieee754_rem_pio2(double x, double *y) +#else + int32_t attribute_hidden __ieee754_rem_pio2(x,y) + double x,y[]; +#endif +{ + double z=0.0,w,t,r,fn; + double tx[3]; + int32_t e0,i,j,nx,n,ix,hx; + u_int32_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 { + u_int32_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); + SET_LOW_WORD(z,low); + e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20))); + 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/libm/e_remainder.c b/libm/e_remainder.c new file mode 100644 index 0000000..95eee74 --- /dev/null +++ b/libm/e_remainder.c @@ -0,0 +1,81 @@ +/* @(#)e_remainder.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_remainder.c,v 1.8 1995/05/10 20:46:05 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + + +#ifdef __STDC__ + double attribute_hidden __ieee754_remainder(double x, double p) +#else + double attribute_hidden __ieee754_remainder(x,p) + double x,p; +#endif +{ + int32_t hx,hp; + u_int32_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 = __ieee754_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/libm/e_scalb.c b/libm/e_scalb.c new file mode 100644 index 0000000..2f0dba1 --- /dev/null +++ b/libm/e_scalb.c @@ -0,0 +1,56 @@ +/* @(#)e_scalb.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_scalb.c,v 1.6 1995/05/10 20:46:09 jtc Exp $"; +#endif + +/* + * __ieee754_scalb(x, fn) is provide for + * passing various standard test suite. One + * should use scalbn() instead. + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef _SCALB_INT +#ifdef __STDC__ + double attribute_hidden __ieee754_scalb(double x, int fn) +#else + double attribute_hidden __ieee754_scalb(x,fn) + double x; int fn; +#endif +#else +#ifdef __STDC__ + double attribute_hidden __ieee754_scalb(double x, double fn) +#else + double attribute_hidden __ieee754_scalb(x,fn) + double x, fn; +#endif +#endif +{ +#ifdef _SCALB_INT + return scalbn(x,fn); +#else + if (isnan(x)||isnan(fn)) return x*fn; + if (!finite(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); +#endif +} diff --git a/libm/e_sinh.c b/libm/e_sinh.c new file mode 100644 index 0000000..ec2b1d8 --- /dev/null +++ b/libm/e_sinh.c @@ -0,0 +1,87 @@ +/* @(#)e_sinh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_sinh.c,v 1.7 1995/05/10 20:46:13 jtc Exp $"; +#endif + +/* __ieee754_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" + + +#ifdef __STDC__ +static const double one = 1.0, shuge = 1.0e307; +#else +static double one = 1.0, shuge = 1.0e307; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_sinh(double x) +#else + double attribute_hidden __ieee754_sinh(x) + double x; +#endif +{ + double t,w,h; + int32_t ix,jx; + u_int32_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*__ieee754_exp(fabs(x)); + + /* |x| in [log(maxdouble), overflowthresold] */ + GET_LOW_WORD(lx,x); + if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) { + w = __ieee754_exp(0.5*fabs(x)); + t = h*w; + return t*w; + } + + /* |x| > overflowthresold, sinh(x) overflow */ + return x*shuge; +} diff --git a/libm/e_sqrt.c b/libm/e_sqrt.c new file mode 100644 index 0000000..c8385d6 --- /dev/null +++ b/libm/e_sqrt.c @@ -0,0 +1,453 @@ +/* @(#)e_sqrt.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $"; +#endif + +/* __ieee754_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" + +#ifdef __STDC__ +static const double one = 1.0, tiny=1.0e-300; +#else +static double one = 1.0, tiny=1.0e-300; +#endif + +#ifdef __STDC__ + double attribute_hidden __ieee754_sqrt(double x) +#else + double attribute_hidden __ieee754_sqrt(x) + double x; +#endif +{ + double z; + int32_t sign = (int)0x80000000; + int32_t ix0,s0,q,m,t,i; + u_int32_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>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==(u_int32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(u_int32_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+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/libm/float_wrappers.c b/libm/float_wrappers.c new file mode 100644 index 0000000..58d3926 --- /dev/null +++ b/libm/float_wrappers.c @@ -0,0 +1,534 @@ +/* vi: set sw=4 ts=4: */ +/* + * Wrapper functions implementing all the float math functions + * defined by SuSv3 by actually calling the double version of + * each function and then casting the result back to a float + * to return to the user. + * + * Copyright (C) 2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#include +#include + +/* For the time being, do _NOT_ implement these functions + * that are defined by SuSv3 */ +#undef L_exp2f /*float exp2f(float);*/ +#undef L_fdimf /*float fdimf(float, float);*/ +#undef L_fmaf /*float fmaf(float, float, float);*/ +#undef L_fmaxf /*float fmaxf(float, float);*/ +#undef L_fminf /*float fminf(float, float);*/ +#undef L_log2f /*float log2f(float);*/ +#undef L_nearbyintf /*float nearbyintf(float);*/ +#undef L_nexttowardf /*float nexttowardf(float, long double);*/ +#undef L_remquof /*float remquof(float, float, int *);*/ +#undef L_scalblnf /*float scalblnf(float, long);*/ +#undef L_tgammaf /*float tgammaf(float);*/ + +/* Implement the following, as defined by SuSv3 */ +#if 0 +float acosf(float); +float acoshf(float); +float asinf(float); +float asinhf(float); +float atan2f(float, float); +float atanf(float); +float atanhf(float); +float cbrtf(float); +float ceilf(float); +float copysignf(float, float); +float cosf(float); +float coshf(float); +float erfcf(float); +float erff(float); +float expf(float); +float expm1f(float); +float fabsf(float); +float floorf(float); +float fmodf(float, float); +float frexpf(float value, int *); +float hypotf(float, float); +int ilogbf(float); +float ldexpf(float, int); +float lgammaf(float); +long long llroundf(float); +float log10f(float); +float log1pf(float); +float logbf(float); +float logf(float); +long lroundf(float); +float modff(float, float *); +float nextafterf(float, float); +float powf(float, float); +float remainderf(float, float); +float rintf(float); +float roundf(float); +float scalbnf(float, int); +float sinf(float); +float sinhf(float); +float sqrtf(float); +float tanf(float); +float tanhf(float); +#endif + + +#ifdef L_acosf +float acosf (float x) +{ + return (float) acos( (double)x ); +} +#endif + + +#ifdef L_acoshf +float acoshf (float x) +{ + return (float) acosh( (double)x ); +} +#endif + + +#ifdef L_asinf +float asinf (float x) +{ + return (float) asin( (double)x ); +} +#endif + + +#ifdef L_asinhf +float asinhf (float x) +{ + return (float) asinh( (double)x ); +} +#endif + + +#ifdef L_atan2f +float atan2f (float x, float y) +{ + return (float) atan2( (double)x, (double)y ); +} +#endif + + +#ifdef L_atanf +float atanf (float x) +{ + return (float) atan( (double)x ); +} +#endif + + +#ifdef L_atanhf +float atanhf (float x) +{ + return (float) atanh( (double)x ); +} +#endif + + +#ifdef L_cargf +float cargf (float complex x) +{ + return (float) carg( (double)x ); +} +#endif + + +#ifdef L_cbrtf +float cbrtf (float x) +{ + return (float) cbrt( (double)x ); +} +#endif + + +#ifdef L_ceilf +float ceilf (float x) +{ + return (float) ceil( (double)x ); +} +#endif + + +#ifdef L_copysignf +float copysignf (float x, float y) +{ + return (float) copysign( (double)x, (double)y ); +} +#endif + + +#ifdef L_cosf +float cosf (float x) +{ + return (float) cos( (double)x ); +} +#endif + + +#ifdef L_coshf +float coshf (float x) +{ + return (float) cosh( (double)x ); +} +#endif + + +#ifdef L_erfcf +float erfcf (float x) +{ + return (float) erfc( (double)x ); +} +#endif + + +#ifdef L_erff +float erff (float x) +{ + return (float) erf( (double)x ); +} +#endif + + +#ifdef L_exp2f +float exp2f (float x) +{ + return (float) exp2( (double)x ); +} +#endif + + +#ifdef L_expf +float expf (float x) +{ + return (float) exp( (double)x ); +} +#endif + + +#ifdef L_expm1f +float expm1f (float x) +{ + return (float) expm1( (double)x ); +} +#endif + + +#ifdef L_fabsf +float fabsf (float x) +{ + return (float) fabs( (double)x ); +} +#endif + + +#ifdef L_fdimf +float fdimf (float x, float y) +{ + return (float) fdim( (double)x, (double)y ); +} +#endif + + +#ifdef L_floorf +float floorf (float x) +{ + return (float) floor( (double)x ); +} +#endif + + +#ifdef L_fmaf +float fmaf (float x, float y, float z) +{ + return (float) fma( (double)x, (double)y, (double)z ); +} +#endif + + +#ifdef L_fmaxf +float fmaxf (float x, float y) +{ + return (float) fmax( (double)x, (double)y ); +} +#endif + + +#ifdef L_fminf +float fminf (float x, float y) +{ + return (float) fmin( (double)x, (double)y ); +} +#endif + + +#ifdef L_fmodf +float fmodf (float x, float y) +{ + return (float) fmod( (double)x, (double)y ); +} +#endif + + +#ifdef L_frexpf +float frexpf (float x, int *_exp) +{ + return (float) frexp( (double)x, _exp ); +} +#endif + + +#ifdef L_hypotf +float hypotf (float x, float y) +{ + return (float) hypot( (double)x, (double)y ); +} +#endif + + +#ifdef L_ilogbf +int ilogbf (float x) +{ + return (int) ilogb( (double)x ); +} +#endif + + +#ifdef L_ldexpf +float ldexpf (float x, int _exp) +{ + return (float) ldexp( (double)x, _exp ); +} +#endif + + +#ifdef L_lgammaf +float lgammaf (float x) +{ + return (float) lgamma( (double)x ); +} +#endif + + +#ifdef L_llrintf +long long llrintf (float x) +{ + return (long long) llrint( (double)x ); +} +#endif + + +#ifdef L_llroundf +long long llroundf (float x) +{ + return (long long) llround( (double)x ); +} +#endif + + +#ifdef L_log10f +float log10f (float x) +{ + return (float) log10( (double)x ); +} +#endif + + +#ifdef L_log1pf +float log1pf (float x) +{ + return (float) log1p( (double)x ); +} +#endif + + +#ifdef L_log2f +float log2f (float x) +{ + return (float) log2( (double)x ); +} +#endif + + +#ifdef L_logbf +float logbf (float x) +{ + return (float) logb( (double)x ); +} +#endif + + +#ifdef L_logf +float logf (float x) +{ + return (float) log( (double)x ); +} +#endif + + +#ifdef L_lrintf +long lrintf (float x) +{ + return (long) lrint( (double)x ); +} +#endif + + +#ifdef L_lroundf +long lroundf (float x) +{ + return (long) lround( (double)x ); +} +#endif + + +#ifdef L_modff +float modff (float x, float *iptr) +{ + double y, result; + result = modf ( x, &y ); + *iptr = (float)y; + return (float) result; + +} +#endif + + +#ifdef L_nearbyintf +float nearbyintf (float x) +{ + return (float) nearbyint( (double)x ); +} +#endif + + +#ifdef L_nextafterf +float nextafterf (float x, float y) +{ + return (float) nextafter( (double)x, (double)y ); +} +#endif + + +#ifdef L_nexttowardf +float nexttowardf (float x, long double y) +{ + return (float) nexttoward( (double)x, (double)y ); +} +#endif + + +#ifdef L_powf +float powf (float x, float y) +{ + return (float) pow( (double)x, (double)y ); +} +#endif + + +#ifdef L_remainderf +float remainderf (float x, float y) +{ + return (float) remainder( (double)x, (double)y ); +} +#endif + + +#ifdef L_remquof +float remquof (float x, float y, int *quo) +{ + return (float) remquo( (double)x, (double)y, quo ); +} +#endif + + +#ifdef L_rintf +float rintf (float x) +{ + return (float) rint( (double)x ); +} +#endif + + +#ifdef L_roundf +float roundf (float x) +{ + return (float) round( (double)x ); +} +#endif + + +#ifdef L_scalblnf +float scalblnf (float x, long _exp) +{ + return (float) scalbln( (double)x, _exp ); +} +#endif + + +#ifdef L_scalbnf +float scalbnf (float x, int _exp) +{ + return (float) scalbn( (double)x, _exp ); +} +#endif + + +#ifdef L_sinf +float sinf (float x) +{ + return (float) sin( (double)x ); +} +#endif + + +#ifdef L_sinhf +float sinhf (float x) +{ + return (float) sinh( (double)x ); +} +#endif + + +#ifdef L_sqrtf +float sqrtf (float x) +{ + return (float) sqrt( (double)x ); +} +#endif + + +#ifdef L_tanf +float tanf (float x) +{ + return (float) tan( (double)x ); +} +#endif + + +#ifdef L_tanhf +float tanhf (float x) +{ + return (float) tanh( (double)x ); +} +#endif + + +#ifdef L_tgammaf +float tgammaf (float x) +{ + return (float) tgamma( (double)x ); +} +#endif + + +#ifdef L_truncf +float truncf (float x) +{ + return (float) trunc( (double)x ); +} +#endif diff --git a/libm/i386/Makefile.arch b/libm/i386/Makefile.arch new file mode 100644 index 0000000..e1be961 --- /dev/null +++ b/libm/i386/Makefile.arch @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# The routines included in this math library are derived from +# glibc's libm. +# + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) + diff --git a/libm/i386/fclrexcpt.c b/libm/i386/fclrexcpt.c new file mode 100644 index 0000000..a34060c --- /dev/null +++ b/libm/i386/fclrexcpt.c @@ -0,0 +1,61 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1997,99,2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feclearexcept (int excepts) +{ + fenv_t temp; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + /* Clear the relevant bits. */ + temp.__status_word &= excepts ^ FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we clear the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Clear the relevant bits. */ + xnew_exc &= ~excepts; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/libm/i386/fedisblxcpt.c b/libm/i386/fedisblxcpt.c new file mode 100644 index 0000000..75dc178 --- /dev/null +++ b/libm/i386/fedisblxcpt.c @@ -0,0 +1,55 @@ +/* Disable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fedisableexcept (int excepts) +{ + unsigned short int new_exc, old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc |= excepts << 7; + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/libm/i386/feenablxcpt.c b/libm/i386/feenablxcpt.c new file mode 100644 index 0000000..174f9f1 --- /dev/null +++ b/libm/i386/feenablxcpt.c @@ -0,0 +1,55 @@ +/* Enable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feenableexcept (int excepts) +{ + unsigned short int new_exc; + unsigned short int old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + excepts &= FE_ALL_EXCEPT; + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + new_exc &= ~excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc &= ~(excepts << 7); + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/libm/i386/fegetenv.c b/libm/i386/fegetenv.c new file mode 100644 index 0000000..abbf179 --- /dev/null +++ b/libm/i386/fegetenv.c @@ -0,0 +1,34 @@ +/* Store current floating-point environment. + Copyright (C) 1997,1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetenv (fenv_t *envp) +{ + __asm__ ("fnstenv %0" : "=m" (*envp)); + /* And load it right back since the processor changes the mask. + Intel thought this opcode to be used in interrupt handlers which + would block all exceptions. */ + __asm__ ("fldenv %0" : : "m" (*envp)); + + /* Success. */ + return 0; +} diff --git a/libm/i386/fegetexcept.c b/libm/i386/fegetexcept.c new file mode 100644 index 0000000..71bac78 --- /dev/null +++ b/libm/i386/fegetexcept.c @@ -0,0 +1,32 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexcept (void) +{ + unsigned short int exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&exc)); + + return (~exc) & FE_ALL_EXCEPT; +} diff --git a/libm/i386/fegetround.c b/libm/i386/fegetround.c new file mode 100644 index 0000000..8ae0c3a --- /dev/null +++ b/libm/i386/fegetround.c @@ -0,0 +1,31 @@ +/* Return current rounding direction. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetround (void) +{ + int cw; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} diff --git a/libm/i386/feholdexcpt.c b/libm/i386/feholdexcpt.c new file mode 100644 index 0000000..d283e9e --- /dev/null +++ b/libm/i386/feholdexcpt.c @@ -0,0 +1,59 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997, 1999, 2003, 2004, 2005, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + fenv_t temp; + + /* Store the environment. */ + __asm__ ("fnstenv %0" : "=m" (temp)); + *envp = temp; + + /* Now set all exceptions to non-stop. */ + temp.__control_word |= 0x3f; + + /* And clear all exceptions. */ + temp.__status_word &= ~0x3f; + + __asm__ ("fldenv %0" : : "m" (temp)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xwork; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xwork)); + + /* Set all exceptions to non-stop and clear them. */ + xwork = (xwork | 0x1f80) & ~0x3f; + + __asm__ ("ldmxcsr %0" : : "m" (*&xwork)); + } +#endif + + return 0; +} diff --git a/libm/i386/fesetenv.c b/libm/i386/fesetenv.c new file mode 100644 index 0000000..fdb4fcc --- /dev/null +++ b/libm/i386/fesetenv.c @@ -0,0 +1,80 @@ +/* Install given floating-point environment. + Copyright (C) 1997,98,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* The memory block used by fstenv/fldenv has a size of 28 bytes. */ + assert (sizeof (fenv_t) == 28); + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + if (envp == FE_DFL_ENV) + { + temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word &= ~FE_TOWARDZERO; + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else if (envp == FE_NOMASK_ENV) + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word |= (envp->__control_word + & (FE_ALL_EXCEPT | FE_TOWARDZERO)); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + temp.__eip = envp->__eip; + temp.__cs_selector = envp->__cs_selector; + temp.__opcode = envp->__opcode; + temp.__data_offset = envp->__data_offset; + temp.__data_selector = envp->__data_selector; + } + + __asm__ ("fldenv %0" : : "m" (temp)); + + /* Success. */ + return 0; +} +libm_hidden_def(fesetenv) diff --git a/libm/i386/fesetround.c b/libm/i386/fesetround.c new file mode 100644 index 0000000..e1ba169 --- /dev/null +++ b/libm/i386/fesetround.c @@ -0,0 +1,52 @@ +/* Set current rounding direction. + Copyright (C) 1997, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fesetround (int round) +{ + unsigned short int cw; + + if ((round & ~0xc00) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + __asm__ ("fldcw %0" : : "m" (*&cw)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xcw; + + __asm__ ("stmxcsr %0" : "=m" (*&xcw)); + xcw &= ~0x6000; + xcw |= round << 3; + __asm__ ("ldmxcsr %0" : : "m" (*&xcw)); + } +#endif + + return 0; +} diff --git a/libm/i386/feupdateenv.c b/libm/i386/feupdateenv.c new file mode 100644 index 0000000..91b535d --- /dev/null +++ b/libm/i386/feupdateenv.c @@ -0,0 +1,56 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1997,99,2000,01,07 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) +libm_hidden_proto(feraiseexcept) + +int +feupdateenv (const fenv_t *envp) +{ + fexcept_t temp; + /* unsigned int xtemp = 0; */ + + /* Save current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); + + temp = (temp | xtemp) & FE_ALL_EXCEPT; +#else + temp &= FE_ALL_EXCEPT; +#endif + + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidently for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept ((int) temp); + + /* Success. */ + return 0; +} diff --git a/libm/i386/fgetexcptflg.c b/libm/i386/fgetexcptflg.c new file mode 100644 index 0000000..f991226 --- /dev/null +++ b/libm/i386/fgetexcptflg.c @@ -0,0 +1,35 @@ +/* Store current representation for exceptions. + Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t temp; + + /* Get the current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/libm/i386/fraiseexcpt.c b/libm/i386/fraiseexcpt.c new file mode 100644 index 0000000..fcb3d0e --- /dev/null +++ b/libm/i386/fraiseexcpt.c @@ -0,0 +1,118 @@ +/* Raise given exceptions. + Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(feraiseexcept) + +int +feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if ((FE_INVALID & excepts) != 0) + { + /* One example of a invalid operation is 0.0 / 0.0. */ + double d; + __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d)); + (void) &d; + } + + /* Next: division by zero. */ + if ((FE_DIVBYZERO & excepts) != 0) + { + double d; + __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait" + : "=t" (d)); + (void) &d; + } + + /* Next: overflow. */ + if ((FE_OVERFLOW & excepts) != 0) + { + /* There is no way to raise only the overflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_OVERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Next: underflow. */ + if ((FE_UNDERFLOW & excepts) != 0) + { + /* There is no way to raise only the underflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_UNDERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Last: inexact. */ + if ((FE_INEXACT & excepts) != 0) + { + /* There is no way to raise only the inexact flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_INEXACT; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Success. */ + return 0; +} +libm_hidden_def(feraiseexcept) diff --git a/libm/i386/fsetexcptflg.c b/libm/i386/fsetexcptflg.c new file mode 100644 index 0000000..bdd1dcc --- /dev/null +++ b/libm/i386/fsetexcptflg.c @@ -0,0 +1,62 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997,99,2000,01, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fenv_t temp; + + /* Get the current environment. We have to do this since we cannot + separately set the status word. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + temp.__status_word &= ~(excepts & FE_ALL_EXCEPT); + temp.__status_word |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed unless + the next floating-point instruction. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Set the relevant bits. */ + xnew_exc &= ~(excepts & FE_ALL_EXCEPT); + xnew_exc |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/libm/i386/ftestexcept.c b/libm/i386/ftestexcept.c new file mode 100644 index 0000000..f45bece --- /dev/null +++ b/libm/i386/ftestexcept.c @@ -0,0 +1,40 @@ +/* Test exception in current environment. + Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fetestexcept (int excepts) +{ + short temp; + int xtemp = 0; + + /* Get current exceptions. */ + __asm__ ("fnstsw %0" : "=a" (temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); +#endif + + return (temp | xtemp) & excepts & FE_ALL_EXCEPT; +} diff --git a/libm/k_cos.c b/libm/k_cos.c new file mode 100644 index 0000000..b2bbca0 --- /dev/null +++ b/libm/k_cos.c @@ -0,0 +1,96 @@ +/* @(#)k_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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_cos.c,v 1.8 1995/05/10 20:46:22 jtc Exp $"; +#endif + +/* + * __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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double attribute_hidden __kernel_cos(double x, double y) +#else + double attribute_hidden __kernel_cos(x, y) + double x,y; +#endif +{ + 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/libm/k_rem_pio2.c b/libm/k_rem_pio2.c new file mode 100644 index 0000000..8d1388d --- /dev/null +++ b/libm/k_rem_pio2.c @@ -0,0 +1,321 @@ +/* @(#)k_rem_pio2.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_rem_pio2.c,v 1.7 1995/05/10 20:46:25 jtc Exp $"; +#endif + +/* + * __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" + + +#ifdef __STDC__ +static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ +#else +static int init_jk[] = {2,3,4,6}; +#endif + +#ifdef __STDC__ +static const double PIo2[] = { +#else +static double PIo2[] = { +#endif + 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 */ +}; + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.0, +one = 1.0, +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ + +#ifdef __STDC__ + int attribute_hidden __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2) +#else + int attribute_hidden __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + double x[], y[]; int e0,nx,prec; int32_t ipio2[]; +#endif +{ + 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;i0) { /* 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/libm/k_sin.c b/libm/k_sin.c new file mode 100644 index 0000000..153f37e --- /dev/null +++ b/libm/k_sin.c @@ -0,0 +1,79 @@ +/* @(#)k_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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_sin.c,v 1.8 1995/05/10 20:46:31 jtc Exp $"; +#endif + +/* __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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double attribute_hidden __kernel_sin(double x, double y, int iy) +#else + double attribute_hidden __kernel_sin(x, y, iy) + double x,y; int iy; /* iy=0 if y is zero */ +#endif +{ + 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/libm/k_standard.c b/libm/k_standard.c new file mode 100644 index 0000000..ed8062c --- /dev/null +++ b/libm/k_standard.c @@ -0,0 +1,786 @@ +/* @(#)k_standard.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $"; +#endif + +#include +#include "math_private.h" +#include + +#ifndef _IEEE_LIBM + + +#ifndef _USE_WRITE +#include /* fputs(), stderr */ +#define WRITE2(u,v) fputs(u, stderr) +#else /* !defined(_USE_WRITE) */ +#include /* write */ +#define WRITE2(u,v) write(2, u, v) +#undef fflush +#endif /* !defined(_USE_WRITE) */ + +#ifdef __STDC__ +static const double zero = 0.0; /* used as const */ +#else +static double zero = 0.0; /* used as const */ +#endif + +/* + * Standard conformance (non-IEEE) on exception cases. + * Mapping: + * 1 -- acos(|x|>1) + * 2 -- asin(|x|>1) + * 3 -- atan2(+-0,+-0) + * 4 -- hypot overflow + * 5 -- cosh overflow + * 6 -- exp overflow + * 7 -- exp underflow + * 8 -- y0(0) + * 9 -- y0(-ve) + * 10-- y1(0) + * 11-- y1(-ve) + * 12-- yn(0) + * 13-- yn(-ve) + * 14-- lgamma(finite) overflow + * 15-- lgamma(-integer) + * 16-- log(0) + * 17-- log(x<0) + * 18-- log10(0) + * 19-- log10(x<0) + * 20-- pow(0.0,0.0) + * 21-- pow(x,y) overflow + * 22-- pow(x,y) underflow + * 23-- pow(0,negative) + * 24-- pow(neg,non-integral) + * 25-- sinh(finite) overflow + * 26-- sqrt(negative) + * 27-- fmod(x,0) + * 28-- remainder(x,0) + * 29-- acosh(x<1) + * 30-- atanh(|x|>1) + * 31-- atanh(|x|=1) + * 32-- scalb overflow + * 33-- scalb underflow + * 34-- j0(|x|>X_TLOSS) + * 35-- y0(x>X_TLOSS) + * 36-- j1(|x|>X_TLOSS) + * 37-- y1(x>X_TLOSS) + * 38-- jn(|x|>X_TLOSS, n) + * 39-- yn(x>X_TLOSS, n) + * 40-- gamma(finite) overflow + * 41-- gamma(-integer) + * 42-- pow(NaN,0.0) + */ + + +#ifdef __STDC__ + double __kernel_standard(double x, double y, int type) +#else + double __kernel_standard(x,y,type) + double x,y; int type; +#endif +{ + struct exception exc; +#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ +#endif + +#ifdef _USE_WRITE + (void) fflush(stdout); +#endif + exc.arg1 = x; + exc.arg2 = y; + switch(type) { + case 1: + case 101: + /* acos(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "acos" : "acosf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("acos: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 2: + case 102: + /* asin(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "asin" : "asinf"; + exc.retval = zero; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("asin: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 3: + case 103: + /* atan2(+-0,+-0) */ + exc.arg1 = y; + exc.arg2 = x; + exc.type = DOMAIN; + exc.name = type < 100 ? "atan2" : "atan2f"; + exc.retval = zero; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("atan2: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 4: + case 104: + /* hypot(finite,finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "hypot" : "hypotf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 5: + case 105: + /* cosh(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "cosh" : "coshf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 6: + case 106: + /* exp(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "exp" : "expf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 7: + case 107: + /* exp(finite) underflow */ + exc.type = UNDERFLOW; + exc.name = type < 100 ? "exp" : "expf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 8: + case 108: + /* y0(0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "y0" : "y0f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y0: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 9: + case 109: + /* y0(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "y0" : "y0f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y0: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 10: + case 110: + /* y1(0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "y1" : "y1f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y1: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 11: + case 111: + /* y1(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "y1" : "y1f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y1: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 12: + case 112: + /* yn(n,0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "yn" : "ynf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("yn: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 13: + case 113: + /* yn(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "yn" : "ynf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("yn: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 14: + case 114: + /* lgamma(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "lgamma" : "lgammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 15: + case 115: + /* lgamma(-integer) or lgamma(0) */ + exc.type = SING; + exc.name = type < 100 ? "lgamma" : "lgammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("lgamma: SING error\n", 19); + } + errno = EDOM; + } + break; + case 16: + case 116: + /* log(0) */ + exc.type = SING; + exc.name = type < 100 ? "log" : "logf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log: SING error\n", 16); + } + errno = EDOM; + } + break; + case 17: + case 117: + /* log(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "log" : "logf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log: DOMAIN error\n", 18); + } + errno = EDOM; + } + break; + case 18: + case 118: + /* log10(0) */ + exc.type = SING; + exc.name = type < 100 ? "log10" : "log10f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log10: SING error\n", 18); + } + errno = EDOM; + } + break; + case 19: + case 119: + /* log10(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "log10" : "log10f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log10: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 20: + case 120: + /* pow(0.0,0.0) */ + /* error only if _LIB_VERSION == _SVID_ */ + exc.type = DOMAIN; + exc.name = type < 100 ? "pow" : "powf"; + exc.retval = zero; + if (_LIB_VERSION != _SVID_) exc.retval = 1.0; + else if (!matherr(&exc)) { + (void) WRITE2("pow(0,0): DOMAIN error\n", 23); + errno = EDOM; + } + break; + case 21: + case 121: + /* pow(x,y) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "pow" : "powf"; + if (_LIB_VERSION == _SVID_) { + exc.retval = HUGE; + y *= 0.5; + if(xzero) ? HUGE : -HUGE); + else + exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 26: + case 126: + /* sqrt(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "sqrt" : "sqrtf"; + if (_LIB_VERSION == _SVID_) + exc.retval = zero; + else + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("sqrt: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 27: + case 127: + /* fmod(x,0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "fmod" : "fmodf"; + if (_LIB_VERSION == _SVID_) + exc.retval = x; + else + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("fmod: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 28: + case 128: + /* remainder(x,0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "remainder" : "remainderf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("remainder: DOMAIN error\n", 24); + } + errno = EDOM; + } + break; + case 29: + case 129: + /* acosh(x<1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "acosh" : "acoshf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("acosh: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 30: + case 130: + /* atanh(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "atanh" : "atanhf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("atanh: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 31: + case 131: + /* atanh(|x|=1) */ + exc.type = SING; + exc.name = type < 100 ? "atanh" : "atanhf"; + exc.retval = x/zero; /* sign(x)*inf */ + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("atanh: SING error\n", 18); + } + errno = EDOM; + } + break; + case 32: + case 132: + /* scalb overflow; SVID also returns +-HUGE_VAL */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "scalb" : "scalbf"; + exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 33: + case 133: + /* scalb underflow */ + exc.type = UNDERFLOW; + exc.name = type < 100 ? "scalb" : "scalbf"; + exc.retval = copysign(zero,x); + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 34: + case 134: + /* j0(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "j0" : "j0f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 35: + case 135: + /* y0(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "y0" : "y0f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 36: + case 136: + /* j1(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "j1" : "j1f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 37: + case 137: + /* y1(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "y1" : "y1f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 38: + case 138: + /* jn(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "jn" : "jnf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 39: + case 139: + /* yn(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "yn" : "ynf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 40: + case 140: + /* gamma(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "gamma" : "gammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 41: + case 141: + /* gamma(-integer) or gamma(0) */ + exc.type = SING; + exc.name = type < 100 ? "gamma" : "gammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("gamma: SING error\n", 18); + } + errno = EDOM; + } + break; + case 42: + case 142: + /* pow(NaN,0.0) */ + /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ + exc.type = DOMAIN; + exc.name = type < 100 ? "pow" : "powf"; + exc.retval = x; + if (_LIB_VERSION == _IEEE_ || + _LIB_VERSION == _POSIX_) exc.retval = 1.0; + else if (!matherr(&exc)) { + errno = EDOM; + } + break; + } + return exc.retval; +} +#endif /* _IEEE_LIBM */ diff --git a/libm/k_tan.c b/libm/k_tan.c new file mode 100644 index 0000000..95ec151 --- /dev/null +++ b/libm/k_tan.c @@ -0,0 +1,133 @@ +/* @(#)k_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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: k_tan.c,v 1.8 1995/05/10 20:46:37 jtc Exp $"; +#endif + +/* __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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ +T[] = { + 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ + 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ + 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ + 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ + 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ + 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ + 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ + 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ + 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ + 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ + 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ + -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ + 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ +}; + +#ifdef __STDC__ + double attribute_hidden __kernel_tan(double x, double y, int iy) +#else + double attribute_hidden __kernel_tan(x, y, iy) + double x,y; int iy; +#endif +{ + 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 */ + u_int32_t low; + GET_LOW_WORD(low,x); + if(((ix|low)|(iy+1))==0) return one/fabs(x); + else return (iy==1)? x: -one/x; + } + } + 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/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c new file mode 100644 index 0000000..d82436d --- /dev/null +++ b/libm/ldouble_wrappers.c @@ -0,0 +1,523 @@ +/* vi: set sw=4 ts=4: */ +/* + * Wrapper functions implementing all the long double math functions + * defined by SuSv3 by actually calling the double version of + * each function and then casting the result back to a long double + * to return to the user. + * + * Copyright (C) 2005 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "math.h" + +/* Implement the following, as defined by SuSv3 */ +#if 0 +long double acoshl(long double); +long double acosl(long double); +long double asinhl(long double); +long double asinl(long double); +long double atan2l(long double, long double); +long double atanhl(long double); +long double atanl(long double); +long double cbrtl(long double); +long double ceill(long double); +long double copysignl(long double, long double); +long double coshl(long double); +long double cosl(long double); +long double erfcl(long double); +long double erfl(long double); +long double exp2l(long double); +long double expl(long double); +long double expm1l(long double); +long double fabsl(long double); +long double fdiml(long double, long double); +long double floorl(long double); +long double fmal(long double, long double, long double); +long double fmaxl(long double, long double); +long double fminl(long double, long double); +long double fmodl(long double, long double); +long double frexpl(long double value, int *); +long double hypotl(long double, long double); +int ilogbl(long double); +long double ldexpl(long double, int); +long double lgammal(long double); +long long llrintl(long double); +long long llroundl(long double); +long double log10l(long double); +long double log1pl(long double); +long double log2l(long double); +long double logbl(long double); +long double logl(long double); +long lrintl(long double); +long lroundl(long double); +long double modfl(long double, long double *); +long double nearbyintl(long double); +long double nextafterl(long double, long double); +long double nexttowardl(long double, long double); +long double powl(long double, long double); +long double remainderl(long double, long double); +long double remquol(long double, long double, int *); +long double rintl(long double); +long double roundl(long double); +long double scalblnl(long double, long); +long double scalbnl(long double, int); +long double sinhl(long double); +long double sinl(long double); +long double sqrtl(long double); +long double tanhl(long double); +long double tanl(long double); +long double tgammal(long double); +long double truncl(long double); +#endif + +#ifdef L_acoshl +long double acoshl (long double x) +{ + return (long double) acosh( (double)x ); +} +#endif + + +#ifdef L_acosl +long double acosl (long double x) +{ + return (long double) acos( (double)x ); +} +#endif + + +#ifdef L_asinhl +long double asinhl (long double x) +{ + return (long double) asinh( (double)x ); +} +#endif + + +#ifdef L_asinl +long double asinl (long double x) +{ + return (long double) asin( (double)x ); +} +#endif + + +#ifdef L_atan2l +long double atan2l (long double x, long double y) +{ + return (long double) atan2( (double)x, (double)y ); +} +#endif + + +#ifdef L_atanhl +long double atanhl (long double x) +{ + return (long double) atanh( (double)x ); +} +#endif + + +#ifdef L_atanl +long double atanl (long double x) +{ + return (long double) atan( (double)x ); +} +#endif + + +#ifdef L_cbrtl +long double cbrtl (long double x) +{ + return (long double) cbrt( (double)x ); +} +#endif + + +#ifdef L_ceill +long double ceill (long double x) +{ + return (long double) ceil( (double)x ); +} +#endif + + +#ifdef L_copysignl +long double copysignl (long double x, long double y) +{ + return (long double) copysign( (double)x, (double)y ); +} +#endif + + +#ifdef L_coshl +long double coshl (long double x) +{ + return (long double) cosh( (double)x ); +} +#endif + + +#ifdef L_cosl +long double cosl (long double x) +{ + return (long double) cos( (double)x ); +} +#endif + + +#ifdef L_erfcl +long double erfcl (long double x) +{ + return (long double) erfc( (double)x ); +} +#endif + + +#ifdef L_erfl +long double erfl (long double x) +{ + return (long double) erf( (double)x ); +} +#endif + + +#ifdef L_exp2l +long double exp2l (long double x) +{ + return (long double) exp2( (double)x ); +} +#endif + + +#ifdef L_expl +long double expl (long double x) +{ + return (long double) exp( (double)x ); +} +#endif + + +#ifdef L_expm1l +long double expm1l (long double x) +{ + return (long double) expm1( (double)x ); +} +#endif + + +#ifdef L_fabsl +long double fabsl (long double x) +{ + return (long double) fabs( (double)x ); +} +#endif + + +#ifdef L_fdiml +long double fdiml (long double x, long double y) +{ + return (long double) fdim( (double)x, (double)y ); +} +#endif + + +#ifdef L_floorl +long double floorl (long double x) +{ + return (long double) floor( (double)x ); +} +#endif + + +#ifdef L_fmal +long double fmal (long double x, long double y, long double z) +{ + return (long double) fma( (double)x, (double)y, (double)z ); +} +#endif + + +#ifdef L_fmaxl +long double fmaxl (long double x, long double y) +{ + return (long double) fmax( (double)x, (double)y ); +} +#endif + + +#ifdef L_fminl +long double fminl (long double x, long double y) +{ + return (long double) fmin( (double)x, (double)y ); +} +#endif + + +#ifdef L_fmodl +long double fmodl (long double x, long double y) +{ + return (long double) fmod( (double)x, (double)y ); +} +#endif + + +#ifdef L_frexpl +long double frexpl (long double x, int *exp) +{ + return (long double) frexp( (double)x, exp ); +} +#endif + + +#ifdef L_hypotl +long double hypotl (long double x, long double y) +{ + return (long double) hypot( (double)x, (double)y ); +} +#endif + + +#ifdef L_ilogbl +int ilogbl (long double x) +{ + return (long double) ilogb( (double)x ); +} +#endif + + +#ifdef L_ldexpl +long double ldexpl (long double x, int exp) +{ + return (long double) ldexp( (double)x, exp ); +} +#endif + + +#ifdef L_lgammal +long double lgammal (long double x) +{ + return (long double) lgamma( (double)x ); +} +#endif + + +#ifdef L_llrintl +long long llrintl (long double x) +{ + return (long double) llrint( (double)x ); +} +#endif + + +#ifdef L_llroundl +long long llroundl (long double x) +{ + return (long double) llround( (double)x ); +} +#endif + +#ifdef L_log10l +long double log10l (long double x) +{ + return (long double) log10( (double)x ); +} +#endif + + +#ifdef L_log1pl +long double log1pl (long double x) +{ + return (long double) log1p( (double)x ); +} +#endif + + +#ifdef L_log2l +long double log2l (long double x) +{ + return (long double) log2( (double)x ); +} +#endif + + +#ifdef L_logbl +long double logbl (long double x) +{ + return (long double) logb( (double)x ); +} +#endif + + +#ifdef L_logl +long double logl (long double x) +{ + return (long double) log( (double)x ); +} +#endif + + +#ifdef L_lrintl +long lrintl (long double x) +{ + return (long double) lrint( (double)x ); +} +#endif + + +#ifdef L_lroundl +long lroundl (long double x) +{ + return (long double) lround( (double)x ); +} +#endif + + +#ifdef L_modfl +long double modfl (long double x, long double *iptr) +{ + double y, result; + result = modf ( x, &y ); + *iptr = (long double)y; + return (long double) result; + +} +#endif + + +#ifdef L_nearbyintl +long double nearbyintl (long double x) +{ + return (long double) nearbyint( (double)x ); +} +#endif + + +#ifdef L_nextafterl +long double nextafterl (long double x, long double y) +{ + return (long double) nextafter( (double)x, (double)y ); +} +#endif + + +#ifdef L_nexttowardl +long double nexttowardl (long double x, long double y) +{ + return (long double) nexttoward( (double)x, (double)y ); +} +#endif + + +#ifdef L_powl +long double powl (long double x, long double y) +{ + return (long double) pow( (double)x, (double)y ); +} +#endif + + +#ifdef L_remainderl +long double remainderl (long double x, long double y) +{ + return (long double) remainder( (double)x, (double)y ); +} +#endif + + +#ifdef L_remquol +long double remquol (long double x, long double y, int *quo) +{ + return (long double) remquo( (double)x, (double)y, quo ); +} +#endif + + +#ifdef L_rintl +long double rintl (long double x) +{ + return (long double) rint( (double)x ); +} +#endif + + +#ifdef L_roundl +long double roundl (long double x) +{ + return (long double) round( (double)x ); +} +#endif + + +#ifdef L_scalblnl +long double scalblnl (long double x, long exp) +{ + return (long double) scalbln( (double)x, exp ); +} +#endif + + +#ifdef L_scalbnl +long double scalbnl (long double x, int exp) +{ + return (long double) scalbn( (double)x, exp ); +} +#endif + + +#ifdef L_sinhl +long double sinhl (long double x) +{ + return (long double) sinh( (double)x ); +} +#endif + + +#ifdef L_sinl +long double sinl (long double x) +{ + return (long double) sin( (double)x ); +} +#endif + + +#ifdef L_sqrtl +long double sqrtl (long double x) +{ + return (long double) sqrt( (double)x ); +} +#endif + + +#ifdef L_tanhl +long double tanhl (long double x) +{ + return (long double) tanh( (double)x ); +} +#endif + + +#ifdef L_tanl +long double tanl (long double x) +{ + return (long double) tan( (double)x ); +} +#endif + + +#ifdef L_tgammal +long double tgammal (long double x) +{ + return (long double) tgamma( (double)x ); +} +#endif + + +#ifdef L_truncl +long double truncl (long double x) +{ + return (long double) trunc( (double)x ); +} +#endif diff --git a/libm/math_private.h b/libm/math_private.h new file mode 100644 index 0000000..f85db12 --- /dev/null +++ b/libm/math_private.h @@ -0,0 +1,199 @@ +/* + * ==================================================== + * 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. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + * $Id: math_private.h,v 1.3 2004/02/09 07:10:38 andersen Exp $ + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +#include +#include + +/* 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. */ + +/* + * Math on arm is special (read: stupid): + * For FPA, float words are always big-endian. + * For VFP, float words follow the memory system mode. + * For Maverick, float words are always little-endian. + */ + +#if !defined(__MAVERICK__) && ((__BYTE_ORDER == __BIG_ENDIAN) || \ + (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__)))) + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; +} ieee_double_shape_type; + +#else + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* 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.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} 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.parts.msw; \ +} 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) = gl_u.parts.lsw; \ +} 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.parts.msw = (ix0); \ + iw_u.parts.lsw = (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.parts.msw = (v); \ + (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.parts.lsw = (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; + u_int32_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) + +/* ieee style elementary functions */ +extern double __ieee754_sqrt (double) attribute_hidden; +extern double __ieee754_acos (double) attribute_hidden; +extern double __ieee754_acosh (double) attribute_hidden; +extern double __ieee754_log (double) attribute_hidden; +extern double __ieee754_log2 (double) attribute_hidden; +extern double __ieee754_atanh (double) attribute_hidden; +extern double __ieee754_asin (double) attribute_hidden; +extern double __ieee754_atan2 (double,double) attribute_hidden; +extern double __ieee754_exp (double) attribute_hidden; +extern double __ieee754_cosh (double) attribute_hidden; +extern double __ieee754_fmod (double,double) attribute_hidden; +extern double __ieee754_pow (double,double) attribute_hidden; +extern double __ieee754_lgamma_r (double,int *) attribute_hidden; +extern double __ieee754_gamma_r (double,int *) attribute_hidden; +extern double __ieee754_lgamma (double) attribute_hidden; +extern double __ieee754_gamma (double) attribute_hidden; +extern double __ieee754_log10 (double) attribute_hidden; +extern double __ieee754_sinh (double) attribute_hidden; +extern double __ieee754_hypot (double,double) attribute_hidden; +extern double __ieee754_j0 (double) attribute_hidden; +extern double __ieee754_j1 (double) attribute_hidden; +extern double __ieee754_y0 (double) attribute_hidden; +extern double __ieee754_y1 (double) attribute_hidden; +extern double __ieee754_jn (int,double) attribute_hidden; +extern double __ieee754_yn (int,double) attribute_hidden; +extern double __ieee754_remainder (double,double) attribute_hidden; +extern int __ieee754_rem_pio2 (double,double*) attribute_hidden; +#if defined(_SCALB_INT) +extern double __ieee754_scalb (double,int) attribute_hidden; +#else +extern double __ieee754_scalb (double,double) attribute_hidden; +#endif + +/* fdlibm kernel function */ +#ifndef _IEEE_LIBM +extern double __kernel_standard (double,double,int) attribute_hidden; +#endif +extern double __kernel_sin (double,double,int) attribute_hidden; +extern double __kernel_cos (double,double) attribute_hidden; +extern double __kernel_tan (double,double,int) attribute_hidden; +extern int __kernel_rem_pio2 (double*,double*,int,int,int,const int*) attribute_hidden; + +#endif /* _MATH_PRIVATE_H_ */ diff --git a/libm/nan.c b/libm/nan.c new file mode 100644 index 0000000..ec221ea --- /dev/null +++ b/libm/nan.c @@ -0,0 +1,60 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2002 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/*********************************************************************** + nan, nanf, nanl - return quiet NaN + + These functions shall return a quiet NaN, if available, with content + indicated through tagp. + + If the implementation does not support quiet NaNs, these functions + shall return zero. + + Calls: strlen(), sprintf(), strtod() + +***********************************************************************/ +#include +#include +#include +#include + +double nan (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtod (buf, NULL); + } + return NAN; +} +libm_hidden_def(nan) + +libm_hidden_proto(nanf) +float nanf (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtof (buf, NULL); + } + return NAN; +} +libm_hidden_def(nanf) + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +libm_hidden_proto(nanl) +long double nanl (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtold (buf, NULL); + } + return NAN; +} +libm_hidden_def(nanl) +#endif diff --git a/libm/powerpc/classic/Makefile.arch b/libm/powerpc/classic/Makefile.arch new file mode 100644 index 0000000..7c7600f --- /dev/null +++ b/libm/powerpc/classic/Makefile.arch @@ -0,0 +1,18 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/powerpc/e500/Makefile.arch b/libm/powerpc/e500/Makefile.arch new file mode 100644 index 0000000..bec21ca --- /dev/null +++ b/libm/powerpc/e500/Makefile.arch @@ -0,0 +1,9 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +-include $(libm_ARCH_fpu_DIR)/Makefile.arch + diff --git a/libm/powerpc/e500/README.txt b/libm/powerpc/e500/README.txt new file mode 100644 index 0000000..354d792 --- /dev/null +++ b/libm/powerpc/e500/README.txt @@ -0,0 +1,8 @@ +The routines this math library have been derived from the e500 math +library in eglibc. The original e500 port to glibc was done by +Aldy Hernandez, , and the port to eglibc was done by +Joseph S. Myers, + +It has been ported to uClibc by Steve Papacharalambous + 19 December, 2006 + diff --git a/libm/powerpc/e500/fpu/Makefile.arch b/libm/powerpc/e500/fpu/Makefile.arch new file mode 100644 index 0000000..8f00e09 --- /dev/null +++ b/libm/powerpc/e500/fpu/Makefile.arch @@ -0,0 +1,19 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + + +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_fpu_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_fpu_DIR)/%.c,$(libm_ARCH_fpu_OUT)/%.o,$(libm_ARCH_SRC)) + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/libm/powerpc/e500/fpu/fclrexcpt.c b/libm/powerpc/e500/fpu/fclrexcpt.c new file mode 100644 index 0000000..42e8b6b --- /dev/null +++ b/libm/powerpc/e500/fpu/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#undef feclearexcept +int +__feclearexcept (int excepts) +{ + unsigned int fpescr; + + /* Get the current state. */ + fpescr = fegetenv_register (); + + /* Clear the relevant bits. */ + fpescr &= ~(excepts & FE_ALL_EXCEPT); + + /* Put the new state in effect. */ + fesetenv_register (fpescr); + + /* Success. */ + return 0; +} + diff --git a/libm/powerpc/e500/fpu/fe_nomask.c b/libm/powerpc/e500/fpu/fe_nomask.c new file mode 100644 index 0000000..ad7b324 --- /dev/null +++ b/libm/powerpc/e500/fpu/fe_nomask.c @@ -0,0 +1,32 @@ +/* Procedure definition for FE_NOMASK_ENV. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* This is presently a stub, until it's decided how the kernels should + support this. */ + +const fenv_t * +__fe_nomask_env(void) +{ + __set_errno (ENOSYS); + return FE_ENABLED_ENV; +} + diff --git a/libm/powerpc/e500/fpu/fedisblxcpt.c b/libm/powerpc/e500/fpu/fedisblxcpt.c new file mode 100644 index 0000000..aeca87b --- /dev/null +++ b/libm/powerpc/e500/fpu/fedisblxcpt.c @@ -0,0 +1,60 @@ +/* Disable floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +fedisableexcept (int excepts) +{ + unsigned int result = 0, pflags, r; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + + /* Save old enable bits. */ + if (pflags & PR_FP_EXC_OVF) + result |= FE_OVERFLOW; + if (pflags & PR_FP_EXC_UND) + result |= FE_UNDERFLOW; + if (pflags & PR_FP_EXC_INV) + result |= FE_INVALID; + if (pflags & PR_FP_EXC_DIV) + result |= FE_DIVBYZERO; + if (pflags & PR_FP_EXC_RES) + result |= FE_INEXACT; + + if (excepts & FE_INEXACT) + pflags &= ~PR_FP_EXC_RES; + if (excepts & FE_DIVBYZERO) + pflags &= ~PR_FP_EXC_DIV; + if (excepts & FE_UNDERFLOW) + pflags &= ~PR_FP_EXC_UND; + if (excepts & FE_OVERFLOW) + pflags &= ~PR_FP_EXC_OVF; + if (excepts & FE_INVALID) + pflags &= ~PR_FP_EXC_INV; + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + if (INTERNAL_SYSCALL_ERROR_P (r, err)) + return -1; + + return result; +} diff --git a/libm/powerpc/e500/fpu/feenablxcpt.c b/libm/powerpc/e500/fpu/feenablxcpt.c new file mode 100644 index 0000000..999fdd7 --- /dev/null +++ b/libm/powerpc/e500/fpu/feenablxcpt.c @@ -0,0 +1,60 @@ +/* Enable floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +feenableexcept (int excepts) +{ + unsigned int result = 0, pflags, r; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + + /* Save old enable bits. */ + if (pflags & PR_FP_EXC_OVF) + result |= FE_OVERFLOW; + if (pflags & PR_FP_EXC_UND) + result |= FE_UNDERFLOW; + if (pflags & PR_FP_EXC_INV) + result |= FE_INVALID; + if (pflags & PR_FP_EXC_DIV) + result |= FE_DIVBYZERO; + if (pflags & PR_FP_EXC_RES) + result |= FE_INEXACT; + + if (excepts & FE_INEXACT) + pflags |= PR_FP_EXC_RES; + if (excepts & FE_DIVBYZERO) + pflags |= PR_FP_EXC_DIV; + if (excepts & FE_UNDERFLOW) + pflags |= PR_FP_EXC_UND; + if (excepts & FE_OVERFLOW) + pflags |= PR_FP_EXC_OVF; + if (excepts & FE_INVALID) + pflags |= PR_FP_EXC_INV; + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + if (INTERNAL_SYSCALL_ERROR_P (r, err)) + return -1; + + return result; +} diff --git a/libm/powerpc/e500/fpu/fegetenv.c b/libm/powerpc/e500/fpu/fegetenv.c new file mode 100644 index 0000000..fbafdc2 --- /dev/null +++ b/libm/powerpc/e500/fpu/fegetenv.c @@ -0,0 +1,38 @@ +/* Store current floating-point environment. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Aldy Hernandez , 2004 + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__fegetenv (fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]); + u.l[1] = fegetenv_register (); + *envp = u.fenv; + + /* Success. */ + return 0; +} + diff --git a/libm/powerpc/e500/fpu/fegetexcept.c b/libm/powerpc/e500/fpu/fegetexcept.c new file mode 100644 index 0000000..c039846 --- /dev/null +++ b/libm/powerpc/e500/fpu/fegetexcept.c @@ -0,0 +1,31 @@ +/* Get floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fegetexcept (void) +{ + unsigned long fpescr; + + fpescr = fegetenv_register (); + + return fpescr & FE_ALL_EXCEPT; +} diff --git a/libm/powerpc/e500/fpu/fegetround.c b/libm/powerpc/e500/fpu/fegetround.c new file mode 100644 index 0000000..6e568fa --- /dev/null +++ b/libm/powerpc/e500/fpu/fegetround.c @@ -0,0 +1,31 @@ +/* Return current rounding direction. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +#undef fegetround +int +fegetround (void) +{ + unsigned long fpescr; + + fpescr = fegetenv_register (); + return fpescr & 3; +} diff --git a/libm/powerpc/e500/fpu/feholdexcpt.c b/libm/powerpc/e500/fpu/feholdexcpt.c new file mode 100644 index 0000000..eccde42 --- /dev/null +++ b/libm/powerpc/e500/fpu/feholdexcpt.c @@ -0,0 +1,45 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + + /* Get the current state. */ + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]); + u.l[1] = fegetenv_register (); + *envp = u.fenv; + + /* Clear everything except for the rounding mode. */ + u.l[1] &= 3; + + /* Put the new state in effect. */ + fesetenv_register (u.l[1]); + + return 0; +} +libm_hidden_def (feholdexcept) diff --git a/libm/powerpc/e500/fpu/fenv_const.c b/libm/powerpc/e500/fpu/fenv_const.c new file mode 100644 index 0000000..073fc92 --- /dev/null +++ b/libm/powerpc/e500/fpu/fenv_const.c @@ -0,0 +1,27 @@ +/* Constants for fenv_bits.h. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* If the default argument is used we use this value. */ +const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = +0x0ULL; + +/* Floating-point environment where none of the exceptions are masked. */ +const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = +0xF00000000ULL; diff --git a/libm/powerpc/e500/fpu/fenv_libc.h b/libm/powerpc/e500/fpu/fenv_libc.h new file mode 100644 index 0000000..22c3f14 --- /dev/null +++ b/libm/powerpc/e500/fpu/fenv_libc.h @@ -0,0 +1,77 @@ +/* Internal libc stuff for floating point environment routines. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Aldy Hernandez , 2004 + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H 1 + +#include + +extern int __feraiseexcept_internal (int __excepts); + +/* Equivalent to fegetenv, but returns a fenv_t instead of taking a + pointer. */ +#define fegetenv_register() \ + ({ unsigned fscr; __asm__ __volatile__ ("mfspefscr %0" : "=r" (fscr)); fscr; }) + +/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ +#define fesetenv_register(fscr) \ + ({ __asm__ __volatile__ ("mtspefscr %0" : : "r" (fscr)); }) + +typedef union +{ + fenv_t fenv; + unsigned int l[2]; +} fenv_union_t; + +/* Definitions of all the SPEFSCR bit numbers. */ +enum { + SPEFSCR_SOVH = 0x80000000, + SPEFSCR_OVH = 0x40000000, + SPEFSCR_FGH = 0x20000000, + SPEFSCR_FXH = 0x10000000, + SPEFSCR_FINVH = 0x08000000, + SPEFSCR_FDBZH = 0x04000000, + SPEFSCR_FUNFH = 0x02000000, + SPEFSCR_FOVFH = 0x01000000, + /* 2 unused bits. */ + SPEFSCR_FINXS = 0x00200000, + SPEFSCR_FINVS = 0x00100000, + SPEFSCR_FDBZS = 0x00080000, + SPEFSCR_FUNFS = 0x00040000, + SPEFSCR_FOVFS = 0x00020000, + SPEFSCR_MODE = 0x00010000, + SPEFSCR_SOV = 0x00008000, + SPEFSCR_OV = 0x00004000, + SPEFSCR_FG = 0x00002000, + SPEFSCR_FX = 0x00001000, + SPEFSCR_FINV = 0x00000800, + SPEFSCR_FDBZ = 0x00000400, + SPEFSCR_FUNF = 0x00000200, + SPEFSCR_FOVF = 0x00000100, + /* 1 unused bit. */ + SPEFSCR_FINXE = 0x00000040, + SPEFSCR_FINVE = 0x00000020, + SPEFSCR_FDBZE = 0x00000010, + SPEFSCR_FUNFE = 0x00000008, + SPEFSCR_FOVFE = 0x00000004, + SPEFSCR_FRMC = 0x00000003 +}; + +#endif /* fenv_libc.h */ diff --git a/libm/powerpc/e500/fpu/fesetenv.c b/libm/powerpc/e500/fpu/fesetenv.c new file mode 100644 index 0000000..cc0cc18 --- /dev/null +++ b/libm/powerpc/e500/fpu/fesetenv.c @@ -0,0 +1,38 @@ +/* Install given floating-point environment. + Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__fesetenv (const fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + u.fenv = *envp; + INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, &u.l[0]); + fesetenv_register (u.l[1]); + + /* Success. */ + return 0; +} + +libm_hidden_ver (__fesetenv, fesetenv) diff --git a/libm/powerpc/e500/fpu/fesetround.c b/libm/powerpc/e500/fpu/fesetround.c new file mode 100644 index 0000000..0f29a91 --- /dev/null +++ b/libm/powerpc/e500/fpu/fesetround.c @@ -0,0 +1,37 @@ +/* Set current rounding direction. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fesetround (int round) +{ + unsigned long fpescr; + + if ((unsigned int) round > 3) + return 1; + + fpescr = fegetenv_register (); + fpescr = (fpescr & ~SPEFSCR_FRMC) | (round & 3); + fesetenv_register (fpescr); + + return 0; +} +libm_hidden_def (fesetround) diff --git a/libm/powerpc/e500/fpu/feupdateenv.c b/libm/powerpc/e500/fpu/feupdateenv.c new file mode 100644 index 0000000..03f3af8 --- /dev/null +++ b/libm/powerpc/e500/fpu/feupdateenv.c @@ -0,0 +1,49 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__feupdateenv (const fenv_t *envp) +{ + unsigned long fpescr, old, new, pflags; + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + /* Save the currently set exceptions. */ + u.fenv = *envp; + new = u.l[1]; + old = fegetenv_register (); + new |= (old & FE_ALL_EXCEPT); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + pflags |= u.l[0]; + INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + + /* Enable and raise (if appropriate) exceptions set in `new'. */ + fesetenv_register (new); + feraiseexcept (new & FE_ALL_EXCEPT); + + /* Success. */ + return 0; +} + diff --git a/libm/powerpc/e500/fpu/fgetexcptflg.c b/libm/powerpc/e500/fpu/fgetexcptflg.c new file mode 100644 index 0000000..62d7f2c --- /dev/null +++ b/libm/powerpc/e500/fpu/fgetexcptflg.c @@ -0,0 +1,39 @@ +/* Store current representation for exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +__fegetexceptflag (fexcept_t *flagp, int excepts) +{ + unsigned long fpescr; + + /* Get the current state. */ + fpescr = fegetenv_register (); + + /* ?? Classic PPC doesn't do anything with `excepts', so we'll do + the same here. (We should really be ignoring exceptions in + excepts) ?? */ + *flagp = fpescr & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} + diff --git a/libm/powerpc/e500/fpu/fraiseexcpt.c b/libm/powerpc/e500/fpu/fraiseexcpt.c new file mode 100644 index 0000000..39caf79 --- /dev/null +++ b/libm/powerpc/e500/fpu/fraiseexcpt.c @@ -0,0 +1,29 @@ +/* Raise given exceptions. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +#undef feraiseexcept + +#define __FERAISEEXCEPT_INTERNAL feraiseexcept + +#include "../spe-raise.c" + +libm_hidden_def (feraiseexcept) diff --git a/libm/powerpc/e500/fpu/fsetexcptflg.c b/libm/powerpc/e500/fpu/fsetexcptflg.c new file mode 100644 index 0000000..8e4bb89 --- /dev/null +++ b/libm/powerpc/e500/fpu/fsetexcptflg.c @@ -0,0 +1,46 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997,99,2000,01,04 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +__fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + unsigned long spefscr; + fexcept_t flag; + + /* Get the current state. */ + spefscr = fegetenv_register (); + + /* Ignore exceptions not listed in 'excepts'. */ + flag = *flagp & excepts; + + /* Replace the exception status */ + spefscr = (spefscr & ~FE_ALL_EXCEPT) | flag; + + /* Store the new status word (along with the rest of the environment). + This may cause floating-point exceptions if the restored state + requests it. */ + fesetenv_register (spefscr); + feraiseexcept (spefscr & FE_ALL_EXCEPT); + + /* Success. */ + return 0; +} + diff --git a/libm/powerpc/e500/fpu/ftestexcept.c b/libm/powerpc/e500/fpu/ftestexcept.c new file mode 100644 index 0000000..971c519 --- /dev/null +++ b/libm/powerpc/e500/fpu/ftestexcept.c @@ -0,0 +1,32 @@ +/* Test exception in current environment. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fetestexcept (int excepts) +{ + unsigned long f; + + /* Get the current state. */ + f = fegetenv_register (); + + return f & excepts; +} diff --git a/libm/powerpc/e500/spe-raise.c b/libm/powerpc/e500/spe-raise.c new file mode 100644 index 0000000..b83087f --- /dev/null +++ b/libm/powerpc/e500/spe-raise.c @@ -0,0 +1,67 @@ +/* Raise given exceptions. + Copyright (C) 1997,99,2000,01,02,04 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fpu/fenv_libc.h" + +int +__FERAISEEXCEPT_INTERNAL (int excepts) +{ + unsigned long f; + + f = fegetenv_register (); + f |= (excepts & FE_ALL_EXCEPT); + fesetenv_register (f); + + /* Force the operations that cause the exceptions. */ + if ((FE_INVALID & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* 0 / 0 */ + __asm__ __volatile__ ("efsdiv %0,%0,%1" : : "r" (0), "r" (0)); + } + + if ((FE_DIVBYZERO & excepts) != 0) + { + /* 1.0 / 0.0 */ + __asm__ __volatile__ ("efsdiv %0,%0,%1" : : "r" (1.0F), "r" (0)); + } + + if ((FE_OVERFLOW & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* Largest normalized number plus itself. */ + __asm__ __volatile__ ("efsadd %0,%0,%1" : : "r" (0x7f7fffff), "r" (0x7f7fffff)); + } + + if ((FE_UNDERFLOW & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* Smallest normalized number times itself. */ + __asm__ __volatile__ ("efsmul %0,%0,%1" : : "r" (0x800000), "r" (0x800000)); + } + + if ((FE_INEXACT & excepts) != 0) + { + /* Smallest normalized minus 1.0 raises the inexact flag. */ + __asm__ __volatile__ ("efssub %0,%0,%1" : : "r" (0x00800000), "r" (1.0F)); + } + + /* Success. */ + return 0; +} diff --git a/libm/s_asinh.c b/libm/s_asinh.c new file mode 100644 index 0000000..efdee84 --- /dev/null +++ b/libm/s_asinh.c @@ -0,0 +1,67 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_asinh.c,v 1.9 1995/05/12 04:57:37 jtc Exp $"; +#endif + +/* 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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +huge= 1.00000000000000000000e+300; + +#ifdef __STDC__ + double asinh(double x) +#else + double asinh(x) + double x; +#endif +{ + 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 = __ieee754_log(fabs(x))+ln2; + } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ + t = fabs(x); + w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t)); + } else { /* 2.0 > |x| > 2**-28 */ + t = x*x; + w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t))); + } + if(hx>0) return w; else return -w; +} +libm_hidden_def(asinh) diff --git a/libm/s_atan.c b/libm/s_atan.c new file mode 100644 index 0000000..7546ae9 --- /dev/null +++ b/libm/s_atan.c @@ -0,0 +1,141 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_atan.c,v 1.8 1995/05/10 20:46:45 jtc Exp $"; +#endif + +/* 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" + + +#ifdef __STDC__ +static const double atanhi[] = { +#else +static double atanhi[] = { +#endif + 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 */ +}; + +#ifdef __STDC__ +static const double atanlo[] = { +#else +static double atanlo[] = { +#endif + 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 */ +}; + +#ifdef __STDC__ +static const double aT[] = { +#else +static double aT[] = { +#endif + 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 */ +}; + +#ifdef __STDC__ + static const double +#else + static double +#endif +one = 1.0, +huge = 1.0e300; + +#ifdef __STDC__ + double atan(double x) +#else + double atan(x) + double x; +#endif +{ + 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 */ + u_int32_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; + } +} +libm_hidden_def(atan) diff --git a/libm/s_cbrt.c b/libm/s_cbrt.c new file mode 100644 index 0000000..d47373e --- /dev/null +++ b/libm/s_cbrt.c @@ -0,0 +1,94 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_cbrt.c,v 1.8 1995/05/10 20:46:49 jtc Exp $"; +#endif + +#include "math.h" +#include "math_private.h" + +/* cbrt(x) + * Return cube root of x + */ +#ifdef __STDC__ +static const u_int32_t +#else +static u_int32_t +#endif + B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ + B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double cbrt(double x) +#else + double cbrt(x) + double x; +#endif +{ + int32_t hx; + double r,s,t=0.0,w; + u_int32_t sign; + u_int32_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); +} +libm_hidden_def(cbrt) diff --git a/libm/s_ceil.c b/libm/s_ceil.c new file mode 100644 index 0000000..76be3ea --- /dev/null +++ b/libm/s_ceil.c @@ -0,0 +1,81 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_ceil.c,v 1.8 1995/05/10 20:46:53 jtc Exp $"; +#endif + +/* + * 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" + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ + double ceil(double x) +#else + double ceil(x) + double x; +#endif +{ + int32_t i0,i1,j0; + u_int32_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 = ((u_int32_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=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); + } + } +} +libm_hidden_def(cos) diff --git a/libm/s_erf.c b/libm/s_erf.c new file mode 100644 index 0000000..0996a39 --- /dev/null +++ b/libm/s_erf.c @@ -0,0 +1,317 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_erf.c,v 1.8 1995/05/10 20:47:05 jtc Exp $"; +#endif + +/* 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 >= 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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double erf(double x) +#else + double erf(x) + double x; +#endif +{ + 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 = ((u_int32_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 = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); + if(hx>=0) return one-r/x; else return r/x-one; +} +libm_hidden_def(erf) + +#ifdef __STDC__ + double erfc(double x) +#else + double erfc(x) + double x; +#endif +{ + 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)(((u_int32_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 = __ieee754_exp(-z*z-0.5625)* + __ieee754_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; + } +} +libm_hidden_def(erfc) diff --git a/libm/s_expm1.c b/libm/s_expm1.c new file mode 100644 index 0000000..4eab15c --- /dev/null +++ b/libm/s_expm1.c @@ -0,0 +1,230 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_expm1.c,v 1.8 1995/05/10 20:47:09 jtc Exp $"; +#endif + +/* 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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ + double expm1(double x) +#else + double expm1(x) + double x; +#endif +{ + double y,hi,lo,c=0.0,t,e,hxs,hfx,r1; + int32_t k,xsb; + u_int32_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) { + u_int32_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 */ + u_int32_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) { + u_int32_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 { + u_int32_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; +} +libm_hidden_def(expm1) diff --git a/libm/s_fabs.c b/libm/s_fabs.c new file mode 100644 index 0000000..deb9138 --- /dev/null +++ b/libm/s_fabs.c @@ -0,0 +1,36 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_fabs.c,v 1.7 1995/05/10 20:47:13 jtc Exp $"; +#endif + +/* + * fabs(x) returns the absolute value of x. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double fabs(double x) +#else + double fabs(x) + double x; +#endif +{ + u_int32_t high; + GET_HIGH_WORD(high,x); + SET_HIGH_WORD(x,high&0x7fffffff); + return x; +} +libm_hidden_def(fabs) diff --git a/libm/s_fdim.c b/libm/s_fdim.c new file mode 100644 index 0000000..98f140d --- /dev/null +++ b/libm/s_fdim.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. 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" + +#ifdef __STDC__ + double fdim(double x, double y) +#else + double fdim(x,y) + double x; + double y; +#endif +{ + int c = __fpclassify(x); + if (c == FP_NAN || c == FP_INFINITE) + return HUGE_VAL; + + return x > y ? x - y : 0.0; +} +libm_hidden_def(fdim) diff --git a/libm/s_finite.c b/libm/s_finite.c new file mode 100644 index 0000000..758da9a --- /dev/null +++ b/libm/s_finite.c @@ -0,0 +1,29 @@ +/* @(#)s_finite.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. + * ==================================================== + */ + +/* + * finite(x) returns 1 is x is finite, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __finite(double x) +{ + int32_t hx; + GET_HIGH_WORD(hx,x); + return (int)((u_int32_t)((hx&0x7fffffff)-0x7ff00000)>>31); +} +libm_hidden_def(__finite) +weak_alias(__finite,finite) +libm_hidden_weak(finite) diff --git a/libm/s_finitef.c b/libm/s_finitef.c new file mode 100644 index 0000000..66eba8f --- /dev/null +++ b/libm/s_finitef.c @@ -0,0 +1,32 @@ +/* s_finitef.c -- float version of s_finite.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. + * ==================================================== + */ + +/* + * finitef(x) returns 1 is x is finite, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(__finitef) +int __finitef(float x) +{ + int32_t ix; + GET_FLOAT_WORD(ix,x); + return (int)((u_int32_t)((ix&0x7fffffff)-0x7f800000)>>31); +} +libm_hidden_def(__finitef) +strong_alias(__finitef,finitef) diff --git a/libm/s_floor.c b/libm/s_floor.c new file mode 100644 index 0000000..1eccfcd --- /dev/null +++ b/libm/s_floor.c @@ -0,0 +1,82 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_floor.c,v 1.8 1995/05/10 20:47:20 jtc Exp $"; +#endif + +/* + * 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" + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ + double floor(double x) +#else + double floor(x) + double x; +#endif +{ + int32_t i0,i1,j0; + u_int32_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 = ((u_int32_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, 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +libm_hidden_proto(__fma) +double +__fma (double x, double y, double z) +{ + return (x * y) + z; +} +libm_hidden_def(__fma) +strong_alias (__fma, fma) diff --git a/libm/s_fmax.c b/libm/s_fmax.c new file mode 100644 index 0000000..e3cda76 --- /dev/null +++ b/libm/s_fmax.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. 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" + +#ifdef __STDC__ + double fmax(double x, double y) +#else + double fmax(x,y) + double x; + double y; +#endif +{ + if (__fpclassify(x) == FP_NAN) + return x; + if (__fpclassify(y) == FP_NAN) + return y; + + return x > y ? x : y; +} +libm_hidden_def(fmax) diff --git a/libm/s_fmin.c b/libm/s_fmin.c new file mode 100644 index 0000000..4d2a0cf --- /dev/null +++ b/libm/s_fmin.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. 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" + +#ifdef __STDC__ + double fmin(double x, double y) +#else + double fmin(x,y) + double x; + double y; +#endif +{ + if (__fpclassify(x) == FP_NAN) + return x; + if (__fpclassify(y) == FP_NAN) + return y; + + return x < y ? x : y; +} +libm_hidden_def(fmin) diff --git a/libm/s_fpclassify.c b/libm/s_fpclassify.c new file mode 100644 index 0000000..d2c4c82 --- /dev/null +++ b/libm/s_fpclassify.c @@ -0,0 +1,43 @@ +/* Return classification value corresponding to argument. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +int +__fpclassify (double x) +{ + u_int32_t hx, lx; + int retval = FP_NORMAL; + + EXTRACT_WORDS (hx, lx, x); + lx |= hx & 0xfffff; + hx &= 0x7ff00000; + if ((hx | lx) == 0) + retval = FP_ZERO; + else if (hx == 0) + retval = FP_SUBNORMAL; + else if (hx == 0x7ff00000) + retval = lx != 0 ? FP_NAN : FP_INFINITE; + + return retval; +} +libm_hidden_def (__fpclassify) diff --git a/libm/s_fpclassifyf.c b/libm/s_fpclassifyf.c new file mode 100644 index 0000000..602d8b2 --- /dev/null +++ b/libm/s_fpclassifyf.c @@ -0,0 +1,42 @@ +/* Return classification value corresponding to argument. + Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +libm_hidden_proto (__fpclassifyf) +int +__fpclassifyf (float x) +{ + u_int32_t wx; + int retval = FP_NORMAL; + + GET_FLOAT_WORD (wx, x); + wx &= 0x7fffffff; + if (wx == 0) + retval = FP_ZERO; + else if (wx < 0x800000) + retval = FP_SUBNORMAL; + else if (wx >= 0x7f800000) + retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE; + + return retval; +} +libm_hidden_def (__fpclassifyf) diff --git a/libm/s_frexp.c b/libm/s_frexp.c new file mode 100644 index 0000000..9ec4624 --- /dev/null +++ b/libm/s_frexp.c @@ -0,0 +1,60 @@ +/* @(#)s_frexp.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_frexp.c,v 1.9 1995/05/10 20:47:24 jtc Exp $"; +#endif + +/* + * for non-zero x + * x = frexp(arg,&exp); + * return a double fp quantity x such that 0.5 <= |x| <1.0 + * and the corresponding binary exponent "exp". That is + * arg = x*2^exp. + * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg + * with *exp=0. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + +#ifdef __STDC__ + double frexp(double x, int *eptr) +#else + double frexp(x, eptr) + double x; int *eptr; +#endif +{ + int32_t hx, ix, lx; + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + *eptr = 0; + if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ + if (ix<0x00100000) { /* subnormal */ + x *= two54; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + *eptr = -54; + } + *eptr += (ix>>20)-1022; + hx = (hx&0x800fffff)|0x3fe00000; + SET_HIGH_WORD(x,hx); + return x; +} +libm_hidden_def(frexp) diff --git a/libm/s_ilogb.c b/libm/s_ilogb.c new file mode 100644 index 0000000..2617757 --- /dev/null +++ b/libm/s_ilogb.c @@ -0,0 +1,52 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_ilogb.c,v 1.9 1995/05/10 20:47:28 jtc Exp $"; +#endif + +/* ilogb(double x) + * return the binary exponent of non-zero x + * ilogb(0) = 0x80000001 + * ilogb(inf/NaN) = 0x7fffffff (no signal is raised) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + int ilogb(double x) +#else + int ilogb(x) + double x; +#endif +{ + int32_t hx,lx,ix; + + GET_HIGH_WORD(hx,x); + hx &= 0x7fffffff; + if(hx<0x00100000) { + GET_LOW_WORD(lx,x); + if((hx|lx)==0) + return 0x80000001; /* ilogb(0) = 0x80000001 */ + 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 return 0x7fffffff; +} +libm_hidden_def(ilogb) diff --git a/libm/s_isinf.c b/libm/s_isinf.c new file mode 100644 index 0000000..99a1cdf --- /dev/null +++ b/libm/s_isinf.c @@ -0,0 +1,26 @@ +/* + * Written by J.T. Conklin . + * Changed to return -1 for -Inf by Ulrich Drepper . + * Public domain. + */ + +/* + * isinf(x) returns 1 is x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int +__isinf (double x) +{ + int32_t hx,lx; + EXTRACT_WORDS(hx,lx,x); + lx |= (hx & 0x7fffffff) ^ 0x7ff00000; + lx |= -lx; + return ~(lx >> 31) & (hx >> 30); +} +libm_hidden_def(__isinf) +weak_alias (__isinf, isinf) +libm_hidden_weak(isinf) diff --git a/libm/s_isinff.c b/libm/s_isinff.c new file mode 100644 index 0000000..6827024 --- /dev/null +++ b/libm/s_isinff.c @@ -0,0 +1,26 @@ +/* + * Written by J.T. Conklin . + * Public domain. + */ + +/* + * isinff(x) returns 1 if x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(__isinff) +int +__isinff (float x) +{ + int32_t ix,t; + GET_FLOAT_WORD(ix,x); + t = ix & 0x7fffffff; + t ^= 0x7f800000; + t |= -t; + return ~(t >> 31) & (ix >> 30); +} +libm_hidden_def(__isinff) +strong_alias (__isinff, isinff) diff --git a/libm/s_isnan.c b/libm/s_isnan.c new file mode 100644 index 0000000..671c5cb --- /dev/null +++ b/libm/s_isnan.c @@ -0,0 +1,37 @@ +/* @(#)s_isnan.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. + * ==================================================== + */ + +/* + * isnan(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + int __isnan(double x) +#else + int __isnan(x) + double x; +#endif +{ + int32_t hx,lx; + EXTRACT_WORDS(hx,lx,x); + hx &= 0x7fffffff; + hx |= (u_int32_t)(lx|(-lx))>>31; + hx = 0x7ff00000 - hx; + return (int)(((u_int32_t)hx)>>31); +} +libm_hidden_def(__isnan) +weak_alias(__isnan,isnan) +libm_hidden_weak(isnan) diff --git a/libm/s_isnanf.c b/libm/s_isnanf.c new file mode 100644 index 0000000..97c354d --- /dev/null +++ b/libm/s_isnanf.c @@ -0,0 +1,34 @@ +/* s_isnanf.c -- float version of s_isnan.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. + * ==================================================== + */ + +/* + * isnanf(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto (__isnanf) +int __isnanf(float x) +{ + int32_t ix; + GET_FLOAT_WORD(ix,x); + ix &= 0x7fffffff; + ix = 0x7f800000 - ix; + return (int)(((u_int32_t)(ix))>>31); +} +libm_hidden_def (__isnanf) +weak_alias (__isnanf, isnanf) diff --git a/libm/s_ldexp.c b/libm/s_ldexp.c new file mode 100644 index 0000000..a065f5a --- /dev/null +++ b/libm/s_ldexp.c @@ -0,0 +1,34 @@ +/* @(#)s_ldexp.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_ldexp.c,v 1.6 1995/05/10 20:47:40 jtc Exp $"; +#endif + +#include "math.h" +#include "math_private.h" +#include + + +#ifdef __STDC__ + double ldexp(double value, int exp) +#else + double ldexp(value, exp) + double value; int exp; +#endif +{ + if(!finite(value)||value==0.0) return value; + value = scalbn(value,exp); + if(!finite(value)||value==0.0) errno = ERANGE; + return value; +} +libm_hidden_def(ldexp) diff --git a/libm/s_lib_version.c b/libm/s_lib_version.c new file mode 100644 index 0000000..fde8e3b --- /dev/null +++ b/libm/s_lib_version.c @@ -0,0 +1,39 @@ +/* @(#)s_lib_ver.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_lib_version.c,v 1.6 1995/05/10 20:47:44 jtc Exp $"; +#endif + +/* + * MACRO for standards + */ + +#include "math.h" +#include "math_private.h" + +/* + * define and initialize _LIB_VERSION + */ +#ifdef _POSIX_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _POSIX_; +#else +#ifdef _XOPEN_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_; +#else +#ifdef _SVID3_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _SVID_; +#else /* default _IEEE_MODE */ +_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; +#endif +#endif +#endif diff --git a/libm/s_llrint.c b/libm/s_llrint.c new file mode 100644 index 0000000..96e1495 --- /dev/null +++ b/libm/s_llrint.c @@ -0,0 +1,88 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 1997, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +static const double two52[2] = +{ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +long long int +llrint (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long long int result; + volatile double w; + double t; + int sx; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sx = i0 >> 31; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + result = (j0 < 0 ? 0 : i0 >> (20 - j0)); + } + else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = (((long long int) i0 << 32) | i1) << (j0 - 52); + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 == 20) + result = (long long int) i0; + else + result = ((long long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long long int) x; + } + + return sx ? -result : result; +} + +libm_hidden_def(llrint) diff --git a/libm/s_llround.c b/libm/s_llround.c new file mode 100644 index 0000000..a549ccc --- /dev/null +++ b/libm/s_llround.c @@ -0,0 +1,75 @@ +/* Round double value to long long int. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +long long int +llround (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long long int result; + int sign; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < 0) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = (((long long int) i0 << 32) | i1) << (j0 - 52); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long long int) i0; + else + result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long long int) x; + } + + return sign * result; +} +libm_hidden_def(llround) diff --git a/libm/s_log1p.c b/libm/s_log1p.c new file mode 100644 index 0000000..695019a --- /dev/null +++ b/libm/s_log1p.c @@ -0,0 +1,175 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_log1p.c,v 1.8 1995/05/10 20:47:46 jtc Exp $"; +#endif + +/* 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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +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 */ + +#ifdef __STDC__ +static const double zero = 0.0; +#else +static double zero = 0.0; +#endif + +#ifdef __STDC__ + double log1p(double x) +#else + double log1p(x) + double x; +#endif +{ + 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= 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); +} +libm_hidden_def(log1p) diff --git a/libm/s_logb.c b/libm/s_logb.c new file mode 100644 index 0000000..173b477 --- /dev/null +++ b/libm/s_logb.c @@ -0,0 +1,44 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_logb.c,v 1.8 1995/05/10 20:47:50 jtc Exp $"; +#endif + +/* + * double logb(x) + * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. + * Use ilogb instead. + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ + double logb(double x) +#else + double logb(x) + double x; +#endif +{ + 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); +} +libm_hidden_def(logb) diff --git a/libm/s_lrint.c b/libm/s_lrint.c new file mode 100644 index 0000000..a0db12d --- /dev/null +++ b/libm/s_lrint.c @@ -0,0 +1,93 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +static const double two52[2] = +{ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + + +long int +lrint (double x) +{ + int32_t j0; + u_int32_t i0,i1; + volatile double w; + double t; + long int result; + int sx; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sx = i0 >> 31; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < -1) + return 0; + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 == 20) + result = (long int) i0; + else + result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sx ? -result : result; +} +libm_hidden_def(lrint) diff --git a/libm/s_lround.c b/libm/s_lround.c new file mode 100644 index 0000000..056a487 --- /dev/null +++ b/libm/s_lround.c @@ -0,0 +1,75 @@ +/* Round double value to long int. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +long int +lround (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long int result; + int sign; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < 0) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long int) i0; + else + result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sign * result; +} +libm_hidden_def(lround) diff --git a/libm/s_matherr.c b/libm/s_matherr.c new file mode 100644 index 0000000..fda4e19 --- /dev/null +++ b/libm/s_matherr.c @@ -0,0 +1,34 @@ +/* @(#)s_matherr.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_matherr.c,v 1.6 1995/05/10 20:47:53 jtc Exp $"; +#endif + +#include "math.h" +#include "math_private.h" + +#ifndef _IEEE_LIBM + +#ifdef __STDC__ + int matherr(struct exception *x) +#else + int matherr(x) + struct exception *x; +#endif +{ + int n=0; + if(x->arg1!=x->arg1) return 0; + return n; +} +libm_hidden_def(matherr) +#endif diff --git a/libm/s_modf.c b/libm/s_modf.c new file mode 100644 index 0000000..24369c0 --- /dev/null +++ b/libm/s_modf.c @@ -0,0 +1,84 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_modf.c,v 1.8 1995/05/10 20:47:55 jtc Exp $"; +#endif + +/* + * 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" + +#ifdef __STDC__ +static const double one = 1.0; +#else +static double one = 1.0; +#endif + +#ifdef __STDC__ + double modf(double x, double *iptr) +#else + double modf(x, iptr) + double x,*iptr; +#endif +{ + int32_t i0,i1,j0; + u_int32_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 */ + u_int32_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 */ + u_int32_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 = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) { /* x is integral */ + u_int32_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; + } + } +} +libm_hidden_def(modf) diff --git a/libm/s_nearbyint.c b/libm/s_nearbyint.c new file mode 100644 index 0000000..52ebbdb --- /dev/null +++ b/libm/s_nearbyint.c @@ -0,0 +1,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" + +#ifdef __STDC__ + double nearbyint(double x) +#else + double nearbyint(x) + double x; +#endif +{ + return rint(x); +} +libm_hidden_def(nearbyint) diff --git a/libm/s_nextafter.c b/libm/s_nextafter.c new file mode 100644 index 0000000..1034e32 --- /dev/null +++ b/libm/s_nextafter.c @@ -0,0 +1,80 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_nextafter.c,v 1.8 1995/05/10 20:47:58 jtc Exp $"; +#endif + +/* 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" + +#ifdef __STDC__ + double nextafter(double x, double y) +#else + double nextafter(x,y) + double x,y; +#endif +{ + int32_t hx,hy,ix,iy; + u_int32_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 x; /* x=y, return x */ + if((ix|lx)==0) { /* x == 0 */ + INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */ + y = x*x; + if(y==x) return y; 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 */ + y = x*x; + if(y!=x) { /* raise underflow flag */ + INSERT_WORDS(y,hx,lx); + return y; + } + } + INSERT_WORDS(x,hx,lx); + return x; +} +libm_hidden_def(nextafter) diff --git a/libm/s_remquo.c b/libm/s_remquo.c new file mode 100644 index 0000000..9cbf8c4 --- /dev/null +++ b/libm/s_remquo.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. 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" + +#ifdef __STDC__ + double remquo(double x, double y, int *quo) /* wrapper remquo */ +#else + double remquo(x,y,quo) /* wrapper remquo */ + double x,y; + int *quo; +#endif +{ + int signx, signy, signres; + int mswx; + int mswy; + double x_over_y; + + GET_HIGH_WORD(mswx, x); + GET_HIGH_WORD(mswy, y); + + signx = (mswx & 0x80000000) >> 31; + signy = (mswy & 0x80000000) >> 31; + + signres = (signx ^ signy) ? -1 : 1; + + x_over_y = fabs(x / y); + + *quo = signres * (lrint(x_over_y) & 0x7f); + + return remainder(x,y); +} +libm_hidden_def(remquo) diff --git a/libm/s_rint.c b/libm/s_rint.c new file mode 100644 index 0000000..d20f1bd --- /dev/null +++ b/libm/s_rint.c @@ -0,0 +1,87 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $"; +#endif + +/* + * 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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double rint(double x) +#else + double rint(x) + double x; +#endif +{ + int32_t i0,j0,sx; + u_int32_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 = ((u_int32_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]; +} +libm_hidden_def(rint) diff --git a/libm/s_round.c b/libm/s_round.c new file mode 100644 index 0000000..7965c6f --- /dev/null +++ b/libm/s_round.c @@ -0,0 +1,92 @@ +/* Round double to integer away from zero. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +static const double huge = 1.0e300; + +double +round (double x) +{ + int32_t i0, j0; + u_int32_t i1; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + { + if (huge + x > 0.0) + { + i0 &= 0x80000000; + if (j0 == -1) + i0 |= 0x3ff00000; + i1 = 0; + } + } + else + { + u_int32_t i = 0x000fffff >> j0; + if (((i0 & i) | i1) == 0) + /* X is integral. */ + return x; + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + i0 += 0x00080000 >> j0; + i0 &= ~i; + i1 = 0; + } + } + } + else if (j0 > 51) + { + if (j0 == 0x400) + /* Inf or NaN. */ + return x + x; + else + return x; + } + else + { + u_int32_t i = 0xffffffff >> (j0 - 20); + if ((i1 & i) == 0) + /* X is integral. */ + return x; + + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + u_int32_t j = i1 + (1 << (51 - j0)); + if (j < i1) + i0 += 1; + i1 = j; + } + i1 &= ~i; + } + + INSERT_WORDS (x, i0, i1); + return x; +} +libm_hidden_def(round) diff --git a/libm/s_scalbln.c b/libm/s_scalbln.c new file mode 100644 index 0000000..d2ea791 --- /dev/null +++ b/libm/s_scalbln.c @@ -0,0 +1,62 @@ +/* @(#)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" + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#ifdef __STDC__ + double scalbln (double x, long int n) +#else + double scalbln (x,n) + double x; long int n; +#endif +{ + 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 (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (n> 50000 || k > 0x7fe) + return huge*copysign(huge,x); /* overflow */ + if (n< -50000) return tiny*copysign(tiny,x); /*underflow*/ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) + return tiny*copysign(tiny,x); /*underflow*/ + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} +libm_hidden_def(scalbln) diff --git a/libm/s_scalbn.c b/libm/s_scalbn.c new file mode 100644 index 0000000..2c5ada3 --- /dev/null +++ b/libm/s_scalbn.c @@ -0,0 +1,69 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_scalbn.c,v 1.8 1995/05/10 20:48:08 jtc Exp $"; +#endif + +/* + * 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" + + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#ifdef __STDC__ + double scalbn (double x, int n) +#else + double scalbn (x,n) + double x; int n; +#endif +{ + 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; +} +libm_hidden_def(scalbn) diff --git a/libm/s_signbit.c b/libm/s_signbit.c new file mode 100644 index 0000000..c9f6527 --- /dev/null +++ b/libm/s_signbit.c @@ -0,0 +1,33 @@ +/* Return nonzero value if number is negative. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +int +__signbit (double x) +{ + int32_t hx; + + GET_HIGH_WORD (hx, x); + return hx & 0x80000000; +} +libm_hidden_def(__signbit) diff --git a/libm/s_signbitf.c b/libm/s_signbitf.c new file mode 100644 index 0000000..ef83d6b --- /dev/null +++ b/libm/s_signbitf.c @@ -0,0 +1,34 @@ +/* Return nonzero value if number is negative. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +libm_hidden_proto(__signbitf) +int +__signbitf (float x) +{ + int32_t hx; + + GET_FLOAT_WORD (hx, x); + return hx & 0x80000000; +} +libm_hidden_def(__signbitf) diff --git a/libm/s_signgam.c b/libm/s_signgam.c new file mode 100644 index 0000000..13d2a1c --- /dev/null +++ b/libm/s_signgam.c @@ -0,0 +1,5 @@ +#include "math.h" +#include "math_private.h" +libm_hidden_proto(signgam) +int signgam = 0; +libm_hidden_def(signgam) diff --git a/libm/s_significand.c b/libm/s_significand.c new file mode 100644 index 0000000..2a7980a --- /dev/null +++ b/libm/s_significand.c @@ -0,0 +1,36 @@ +/* @(#)s_signif.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_significand.c,v 1.6 1995/05/10 20:48:11 jtc Exp $"; +#endif + +/* + * significand(x) computes just + * scalb(x, (double) -ilogb(x)), + * for exercising the fraction-part(F) IEEE 754-1985 test vector. + */ + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ + double significand(double x) +#else + double significand(x) + double x; +#endif +{ + return __ieee754_scalb(x,(double) -ilogb(x)); +} +libm_hidden_def(significand) diff --git a/libm/s_sin.c b/libm/s_sin.c new file mode 100644 index 0000000..c14709b --- /dev/null +++ b/libm/s_sin.c @@ -0,0 +1,83 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_sin.c,v 1.7 1995/05/10 20:48:15 jtc Exp $"; +#endif + +/* 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" + +#ifdef __STDC__ + double sin(double x) +#else + double sin(x) + double x; +#endif +{ + 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]); + } + } +} +libm_hidden_def(sin) diff --git a/libm/s_tan.c b/libm/s_tan.c new file mode 100644 index 0000000..26bb39f --- /dev/null +++ b/libm/s_tan.c @@ -0,0 +1,77 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_tan.c,v 1.7 1995/05/10 20:48:18 jtc Exp $"; +#endif + +/* 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" + +#ifdef __STDC__ + double tan(double x) +#else + double tan(x) + double x; +#endif +{ + 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 */ + } +} +libm_hidden_def(tan) diff --git a/libm/s_tanh.c b/libm/s_tanh.c new file mode 100644 index 0000000..edadbfe --- /dev/null +++ b/libm/s_tanh.c @@ -0,0 +1,88 @@ +/* @(#)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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_tanh.c,v 1.7 1995/05/10 20:48:22 jtc Exp $"; +#endif + +/* 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" + + +#ifdef __STDC__ +static const double one=1.0, two=2.0, tiny = 1.0e-300; +#else +static double one=1.0, two=2.0, tiny = 1.0e-300; +#endif + +#ifdef __STDC__ + double tanh(double x) +#else + double tanh(x) + double x; +#endif +{ + 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; +} +libm_hidden_def(tanh) diff --git a/libm/s_trunc.c b/libm/s_trunc.c new file mode 100644 index 0000000..6e5678b --- /dev/null +++ b/libm/s_trunc.c @@ -0,0 +1,57 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +double +trunc (double x) +{ + int32_t i0, j0; + u_int32_t i1; + int sx; + + EXTRACT_WORDS (i0, i1, x); + sx = i0 & 0x80000000; + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + /* The magnitude of the number is < 1 so the result is +-0. */ + INSERT_WORDS (x, sx, 0); + else + INSERT_WORDS (x, sx | (i0 & ~(0x000fffff >> j0)), 0); + } + else if (j0 > 51) + { + if (j0 == 0x400) + /* x is inf or NaN. */ + return x + x; + } + else + { + INSERT_WORDS (x, i0, i1 & ~(0xffffffffu >> (j0 - 20))); + } + + return x; +} +libm_hidden_def(trunc) diff --git a/libm/w_acos.c b/libm/w_acos.c new file mode 100644 index 0000000..f93f6bb --- /dev/null +++ b/libm/w_acos.c @@ -0,0 +1,43 @@ +/* @(#)w_acos.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_acos.c,v 1.6 1995/05/10 20:48:26 jtc Exp $"; +#endif + +/* + * wrap_acos(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double acos(double x) /* wrapper acos */ +#else + double acos(x) /* wrapper acos */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_acos(x); +#else + double z; + z = __ieee754_acos(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>1.0) { + return __kernel_standard(x,x,1); /* acos(|x|>1) */ + } else + return z; +#endif +} +libm_hidden_def(acos) diff --git a/libm/w_acosh.c b/libm/w_acosh.c new file mode 100644 index 0000000..3268218 --- /dev/null +++ b/libm/w_acosh.c @@ -0,0 +1,43 @@ +/* @(#)w_acosh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_acosh.c,v 1.6 1995/05/10 20:48:31 jtc Exp $"; +#endif + +/* + * wrapper acosh(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double acosh(double x) /* wrapper acosh */ +#else + double acosh(x) /* wrapper acosh */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_acosh(x); +#else + double z; + z = __ieee754_acosh(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(x<1.0) { + return __kernel_standard(x,x,29); /* acosh(x<1) */ + } else + return z; +#endif +} +libm_hidden_def(acosh) diff --git a/libm/w_asin.c b/libm/w_asin.c new file mode 100644 index 0000000..a028a1d --- /dev/null +++ b/libm/w_asin.c @@ -0,0 +1,45 @@ +/* @(#)w_asin.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_asin.c,v 1.6 1995/05/10 20:48:35 jtc Exp $"; +#endif + +/* + * wrapper asin(x) + */ + + +#include "math.h" +#include "math_private.h" + + +#ifdef __STDC__ + double asin(double x) /* wrapper asin */ +#else + double asin(x) /* wrapper asin */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_asin(x); +#else + double z; + z = __ieee754_asin(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>1.0) { + return __kernel_standard(x,x,2); /* asin(|x|>1) */ + } else + return z; +#endif +} +libm_hidden_def(asin) diff --git a/libm/w_atan2.c b/libm/w_atan2.c new file mode 100644 index 0000000..6a13d2b --- /dev/null +++ b/libm/w_atan2.c @@ -0,0 +1,42 @@ +/* @(#)w_atan2.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_atan2.c,v 1.6 1995/05/10 20:48:39 jtc Exp $"; +#endif + +/* + * wrapper atan2(y,x) + */ +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double atan2(double y, double x) /* wrapper atan2 */ +#else + double atan2(y,x) /* wrapper atan2 */ + double y,x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_atan2(y,x); +#else + double z; + z = __ieee754_atan2(y,x); + if(_LIB_VERSION == _IEEE_||isnan(x)||isnan(y)) return z; + if(x==0.0&&y==0.0) { + return __kernel_standard(y,x,3); /* atan2(+-0,+-0) */ + } else + return z; +#endif +} +libm_hidden_def(atan2) diff --git a/libm/w_atanh.c b/libm/w_atanh.c new file mode 100644 index 0000000..9839313 --- /dev/null +++ b/libm/w_atanh.c @@ -0,0 +1,47 @@ +/* @(#)w_atanh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_atanh.c,v 1.6 1995/05/10 20:48:43 jtc Exp $"; +#endif + +/* + * wrapper atanh(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double atanh(double x) /* wrapper atanh */ +#else + double atanh(x) /* wrapper atanh */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_atanh(x); +#else + double z,y; + z = __ieee754_atanh(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + y = fabs(x); + if(y>=1.0) { + if(y>1.0) + return __kernel_standard(x,x,30); /* atanh(|x|>1) */ + else + return __kernel_standard(x,x,31); /* atanh(|x|==1) */ + } else + return z; +#endif +} +libm_hidden_def(atanh) diff --git a/libm/w_cabs.c b/libm/w_cabs.c new file mode 100644 index 0000000..d2a54cd --- /dev/null +++ b/libm/w_cabs.c @@ -0,0 +1,16 @@ +/* + * cabs() wrapper for hypot(). + * + * Written by J.T. Conklin, + * Placed into the Public Domain, 1994. + */ + +#include +#include + + +double cabs(double _Complex z) +{ + return hypot(__real__ z, __imag__ z); +} +libm_hidden_def(cabs) diff --git a/libm/w_cosh.c b/libm/w_cosh.c new file mode 100644 index 0000000..0766e37 --- /dev/null +++ b/libm/w_cosh.c @@ -0,0 +1,43 @@ +/* @(#)w_cosh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_cosh.c,v 1.6 1995/05/10 20:48:47 jtc Exp $"; +#endif + +/* + * wrapper cosh(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double cosh(double x) /* wrapper cosh */ +#else + double cosh(x) /* wrapper cosh */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_cosh(x); +#else + double z; + z = __ieee754_cosh(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>7.10475860073943863426e+02) { + return __kernel_standard(x,x,5); /* cosh overflow */ + } else + return z; +#endif +} +libm_hidden_def(cosh) diff --git a/libm/w_drem.c b/libm/w_drem.c new file mode 100644 index 0000000..6b3dd39 --- /dev/null +++ b/libm/w_drem.c @@ -0,0 +1,15 @@ +/* + * drem() wrapper for remainder(). + * + * Written by J.T. Conklin, + * Placed into the Public Domain, 1994. + */ + +#include + + +double drem(double x, double y) +{ + return remainder(x, y); +} +libm_hidden_def(drem) diff --git a/libm/w_exp.c b/libm/w_exp.c new file mode 100644 index 0000000..e112224 --- /dev/null +++ b/libm/w_exp.c @@ -0,0 +1,54 @@ +/* @(#)w_exp.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_exp.c,v 1.6 1995/05/10 20:48:51 jtc Exp $"; +#endif + +/* + * wrapper exp(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +u_threshold= -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ + +#ifdef __STDC__ + double exp(double x) /* wrapper exp */ +#else + double exp(x) /* wrapper exp */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_exp(x); +#else + double z; + z = __ieee754_exp(x); + if(_LIB_VERSION == _IEEE_) return z; + if(finite(x)) { + if(x>o_threshold) + return __kernel_standard(x,x,6); /* exp overflow */ + else if(x +#include "math_private.h" + +libm_hidden_proto(signgam) +#ifdef __STDC__ + double gamma(double x) +#else + double gamma(x) + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_lgamma_r(x,&signgam); +#else + double y; + y = __ieee754_lgamma_r(x,&signgam); + if(_LIB_VERSION == _IEEE_) return y; + if(!finite(y)&&finite(x)) { + if(floor(x)==x&&x<=0.0) + return __kernel_standard(x,x,41); /* gamma pole */ + else + return __kernel_standard(x,x,40); /* gamma overflow */ + } else + return y; +#endif +} +libm_hidden_def(gamma) diff --git a/libm/w_gamma_r.c b/libm/w_gamma_r.c new file mode 100644 index 0000000..b9f14fb --- /dev/null +++ b/libm/w_gamma_r.c @@ -0,0 +1,49 @@ +/* @(#)wr_gamma.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_gamma_r.c,v 1.7 1995/11/20 22:06:45 jtc Exp $"; +#endif + +/* + * wrapper double gamma_r(double x, int *signgamp) + */ + +#include "math.h" +#include "math_private.h" + + +double gamma_r(double x, int *signgamp); +libm_hidden_proto(gamma_r) +#ifdef __STDC__ + double gamma_r(double x, int *signgamp) /* wrapper lgamma_r */ +#else + double gamma_r(x,signgamp) /* wrapper lgamma_r */ + double x; int *signgamp; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_lgamma_r(x,signgamp); +#else + double y; + y = __ieee754_lgamma_r(x,signgamp); + if(_LIB_VERSION == _IEEE_) return y; + if(!finite(y)&&finite(x)) { + if(floor(x)==x&&x<=0.0) + return __kernel_standard(x,x,41); /* gamma pole */ + else + return __kernel_standard(x,x,40); /* gamma overflow */ + } else + return y; +#endif +} +libm_hidden_def(gamma_r) diff --git a/libm/w_hypot.c b/libm/w_hypot.c new file mode 100644 index 0000000..9ed348e --- /dev/null +++ b/libm/w_hypot.c @@ -0,0 +1,43 @@ +/* @(#)w_hypot.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_hypot.c,v 1.6 1995/05/10 20:49:07 jtc Exp $"; +#endif + +/* + * wrapper hypot(x,y) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double hypot(double x, double y)/* wrapper hypot */ +#else + double hypot(x,y) /* wrapper hypot */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_hypot(x,y); +#else + double z; + z = __ieee754_hypot(x,y); + if(_LIB_VERSION == _IEEE_) return z; + if((!finite(z))&&finite(x)&&finite(y)) + return __kernel_standard(x,y,4); /* hypot overflow */ + else + return z; +#endif +} +libm_hidden_def(hypot) diff --git a/libm/w_j0.c b/libm/w_j0.c new file mode 100644 index 0000000..27290c8 --- /dev/null +++ b/libm/w_j0.c @@ -0,0 +1,71 @@ +/* @(#)w_j0.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_j0.c,v 1.6 1995/05/10 20:49:11 jtc Exp $"; +#endif + +/* + * wrapper j0(double x), y0(double x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double j0(double x) /* wrapper j0 */ +#else + double j0(x) /* wrapper j0 */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_j0(x); +#else + double z = __ieee754_j0(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(fabs(x)>X_TLOSS) { + return __kernel_standard(x,x,34); /* j0(|x|>X_TLOSS) */ + } else + return z; +#endif +} +libm_hidden_def(j0) + +#ifdef __STDC__ + double y0(double x) /* wrapper y0 */ +#else + double y0(x) /* wrapper y0 */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_y0(x); +#else + double z; + z = __ieee754_y0(x); + if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; + if(x <= 0.0){ + if(x==0.0) + /* d= -one/(x-x); */ + return __kernel_standard(x,x,8); + else + /* d = zero/(x-x); */ + return __kernel_standard(x,x,9); + } + if(x>X_TLOSS) { + return __kernel_standard(x,x,35); /* y0(x>X_TLOSS) */ + } else + return z; +#endif +} +libm_hidden_def(y0) diff --git a/libm/w_j1.c b/libm/w_j1.c new file mode 100644 index 0000000..9ce34cc --- /dev/null +++ b/libm/w_j1.c @@ -0,0 +1,72 @@ +/* @(#)w_j1.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_j1.c,v 1.6 1995/05/10 20:49:15 jtc Exp $"; +#endif + +/* + * wrapper of j1,y1 + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double j1(double x) /* wrapper j1 */ +#else + double j1(x) /* wrapper j1 */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_j1(x); +#else + double z; + z = __ieee754_j1(x); + if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; + if(fabs(x)>X_TLOSS) { + return __kernel_standard(x,x,36); /* j1(|x|>X_TLOSS) */ + } else + return z; +#endif +} +libm_hidden_def(j1) + +#ifdef __STDC__ + double y1(double x) /* wrapper y1 */ +#else + double y1(x) /* wrapper y1 */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_y1(x); +#else + double z; + z = __ieee754_y1(x); + if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; + if(x <= 0.0){ + if(x==0.0) + /* d= -one/(x-x); */ + return __kernel_standard(x,x,10); + else + /* d = zero/(x-x); */ + return __kernel_standard(x,x,11); + } + if(x>X_TLOSS) { + return __kernel_standard(x,x,37); /* y1(x>X_TLOSS) */ + } else + return z; +#endif +} +libm_hidden_def(y1) diff --git a/libm/w_jn.c b/libm/w_jn.c new file mode 100644 index 0000000..2ba74d8 --- /dev/null +++ b/libm/w_jn.c @@ -0,0 +1,94 @@ +/* @(#)w_jn.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_jn.c,v 1.6 1995/05/10 20:49:19 jtc Exp $"; +#endif + +/* + * wrapper jn(int n, double x), yn(int n, double x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double jn(int n, double x) /* wrapper jn */ +#else + double jn(n,x) /* wrapper jn */ + double x; int n; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_jn(n,x); +#else + double z; + z = __ieee754_jn(n,x); + if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; + if(fabs(x)>X_TLOSS) { + return __kernel_standard((double)n,x,38); /* jn(|x|>X_TLOSS,n) */ + } else + return z; +#endif +} +libm_hidden_def(jn) + +#ifdef __STDC__ + double yn(int n, double x) /* wrapper yn */ +#else + double yn(n,x) /* wrapper yn */ + double x; int n; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_yn(n,x); +#else + double z; + z = __ieee754_yn(n,x); + if(_LIB_VERSION == _IEEE_ || isnan(x) ) return z; + if(x <= 0.0){ + if(x==0.0) + /* d= -one/(x-x); */ + return __kernel_standard((double)n,x,12); + else + /* d = zero/(x-x); */ + return __kernel_standard((double)n,x,13); + } + if(x>X_TLOSS) { + return __kernel_standard((double)n,x,39); /* yn(x>X_TLOSS,n) */ + } else + return z; +#endif +} +libm_hidden_def(yn) diff --git a/libm/w_lgamma.c b/libm/w_lgamma.c new file mode 100644 index 0000000..24b8b02 --- /dev/null +++ b/libm/w_lgamma.c @@ -0,0 +1,49 @@ +/* @(#)w_lgamma.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_lgamma.c,v 1.6 1995/05/10 20:49:24 jtc Exp $"; +#endif + +/* double lgamma(double x) + * Return the logarithm of the Gamma function of x. + * + * Method: call __ieee754_lgamma_r + */ + +#include +#include "math_private.h" + +libm_hidden_proto(signgam) +#ifdef __STDC__ + double lgamma(double x) +#else + double lgamma(x) + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_lgamma_r(x,&signgam); +#else + double y; + y = __ieee754_lgamma_r(x,&signgam); + if(_LIB_VERSION == _IEEE_) return y; + if(!finite(y)&&finite(x)) { + if(floor(x)==x&&x<=0.0) + return __kernel_standard(x,x,15); /* lgamma pole */ + else + return __kernel_standard(x,x,14); /* lgamma overflow */ + } else + return y; +#endif +} +libm_hidden_def(lgamma) diff --git a/libm/w_lgamma_r.c b/libm/w_lgamma_r.c new file mode 100644 index 0000000..20b0026 --- /dev/null +++ b/libm/w_lgamma_r.c @@ -0,0 +1,46 @@ +/* @(#)wr_lgamma.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_lgamma_r.c,v 1.6 1995/05/10 20:49:27 jtc Exp $"; +#endif + +/* + * wrapper double lgamma_r(double x, int *signgamp) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */ +#else + double lgamma_r(x,signgamp) /* wrapper lgamma_r */ + double x; int *signgamp; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_lgamma_r(x,signgamp); +#else + double y; + y = __ieee754_lgamma_r(x,signgamp); + if(_LIB_VERSION == _IEEE_) return y; + if(!finite(y)&&finite(x)) { + if(floor(x)==x&&x<=0.0) + return __kernel_standard(x,x,15); /* lgamma pole */ + else + return __kernel_standard(x,x,14); /* lgamma overflow */ + } else + return y; +#endif +} +libm_hidden_def(lgamma_r) diff --git a/libm/w_log.c b/libm/w_log.c new file mode 100644 index 0000000..22cdda1 --- /dev/null +++ b/libm/w_log.c @@ -0,0 +1,43 @@ +/* @(#)w_log.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_log.c,v 1.6 1995/05/10 20:49:33 jtc Exp $"; +#endif + +/* + * wrapper log(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double log(double x) /* wrapper log */ +#else + double log(x) /* wrapper log */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_log(x); +#else + double z; + z = __ieee754_log(x); + if(_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) return z; + if(x==0.0) + return __kernel_standard(x,x,16); /* log(0) */ + else + return __kernel_standard(x,x,17); /* log(x<0) */ +#endif +} +libm_hidden_def(log) diff --git a/libm/w_log10.c b/libm/w_log10.c new file mode 100644 index 0000000..efb523e --- /dev/null +++ b/libm/w_log10.c @@ -0,0 +1,46 @@ +/* @(#)w_log10.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_log10.c,v 1.6 1995/05/10 20:49:35 jtc Exp $"; +#endif + +/* + * wrapper log10(X) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double log10(double x) /* wrapper log10 */ +#else + double log10(x) /* wrapper log10 */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_log10(x); +#else + double z; + z = __ieee754_log10(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(x<=0.0) { + if(x==0.0) + return __kernel_standard(x,x,18); /* log10(0) */ + else + return __kernel_standard(x,x,19); /* log10(x<0) */ + } else + return z; +#endif +} +libm_hidden_def(log10) diff --git a/libm/w_log2.c b/libm/w_log2.c new file mode 100644 index 0000000..ec274f7 --- /dev/null +++ b/libm/w_log2.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2008 by Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include "math_private.h" + +double log2 (double d) +{ + return __ieee754_log2 (d); +} +libm_hidden_def(log2) diff --git a/libm/w_pow.c b/libm/w_pow.c new file mode 100644 index 0000000..94d30bc --- /dev/null +++ b/libm/w_pow.c @@ -0,0 +1,61 @@ + + +/* @(#)w_pow.c 5.2 93/10/01 */ +/* + * ==================================================== + * 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. + * ==================================================== + */ + +/* + * wrapper pow(x,y) return x**y + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double pow(double x, double y) /* wrapper pow */ +#else + double pow(x,y) /* wrapper pow */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_pow(x,y); +#else + double z; + z=__ieee754_pow(x,y); + if(_LIB_VERSION == _IEEE_|| isnan(y)) return z; + if(isnan(x)) { + if(y==0.0) + return __kernel_standard(x,y,42); /* pow(NaN,0.0) */ + else + return z; + } + if(x==0.0){ + if(y==0.0) + return __kernel_standard(x,y,20); /* pow(0.0,0.0) */ + if(finite(y)&&y<0.0) + return __kernel_standard(x,y,23); /* pow(0.0,negative) */ + return z; + } + if(!finite(z)) { + if(finite(x)&&finite(y)) { + if(isnan(z)) + return __kernel_standard(x,y,24); /* pow neg**non-int */ + else + return __kernel_standard(x,y,21); /* pow overflow */ + } + } + if(z==0.0&&finite(x)&&finite(y)) + return __kernel_standard(x,y,22); /* pow underflow */ + return z; +#endif +} +libm_hidden_def(pow) diff --git a/libm/w_remainder.c b/libm/w_remainder.c new file mode 100644 index 0000000..a30ff88 --- /dev/null +++ b/libm/w_remainder.c @@ -0,0 +1,43 @@ +/* @(#)w_remainder.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_remainder.c,v 1.6 1995/05/10 20:49:44 jtc Exp $"; +#endif + +/* + * wrapper remainder(x,p) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double remainder(double x, double y) /* wrapper remainder */ +#else + double remainder(x,y) /* wrapper remainder */ + double x,y; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_remainder(x,y); +#else + double z; + z = __ieee754_remainder(x,y); + if(_LIB_VERSION == _IEEE_ || isnan(y)) return z; + if(y==0.0) + return __kernel_standard(x,y,28); /* remainder(x,0) */ + else + return z; +#endif +} +libm_hidden_def(remainder) diff --git a/libm/w_scalb.c b/libm/w_scalb.c new file mode 100644 index 0000000..a770877 --- /dev/null +++ b/libm/w_scalb.c @@ -0,0 +1,61 @@ +/* @(#)w_scalb.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_scalb.c,v 1.6 1995/05/10 20:49:48 jtc Exp $"; +#endif + +/* + * wrapper scalb(double x, double fn) is provide for + * passing various standard test suite. One + * should use scalbn() instead. + */ + +#include +#include "math_private.h" + +#include + +#ifdef __STDC__ +#ifdef _SCALB_INT + double scalb(double x, int fn) /* wrapper scalb */ +#else + double scalb(double x, double fn) /* wrapper scalb */ +#endif +#else + double scalb(x,fn) /* wrapper scalb */ +#ifdef _SCALB_INT + double x; int fn; +#else + double x,fn; +#endif +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_scalb(x,fn); +#else + double z; + z = __ieee754_scalb(x,fn); + if(_LIB_VERSION == _IEEE_) return z; + if(!(finite(z)||isnan(z))&&finite(x)) { + return __kernel_standard(x,(double)fn,32); /* scalb overflow */ + } + if(z==0.0&&z!=x) { + return __kernel_standard(x,(double)fn,33); /* scalb underflow */ + } +#ifndef _SCALB_INT + if(!finite(fn)) errno = ERANGE; +#endif + return z; +#endif +} +libm_hidden_def(scalb) diff --git a/libm/w_sinh.c b/libm/w_sinh.c new file mode 100644 index 0000000..dabfdd9 --- /dev/null +++ b/libm/w_sinh.c @@ -0,0 +1,43 @@ +/* @(#)w_sinh.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_sinh.c,v 1.6 1995/05/10 20:49:51 jtc Exp $"; +#endif + +/* + * wrapper sinh(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double sinh(double x) /* wrapper sinh */ +#else + double sinh(x) /* wrapper sinh */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_sinh(x); +#else + double z; + z = __ieee754_sinh(x); + if(_LIB_VERSION == _IEEE_) return z; + if(!finite(z)&&finite(x)) { + return __kernel_standard(x,x,25); /* sinh overflow */ + } else + return z; +#endif +} +libm_hidden_def(sinh) diff --git a/libm/w_sqrt.c b/libm/w_sqrt.c new file mode 100644 index 0000000..d695b1d --- /dev/null +++ b/libm/w_sqrt.c @@ -0,0 +1,43 @@ +/* @(#)w_sqrt.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. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: w_sqrt.c,v 1.6 1995/05/10 20:49:55 jtc Exp $"; +#endif + +/* + * wrapper sqrt(x) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double sqrt(double x) /* wrapper sqrt */ +#else + double sqrt(x) /* wrapper sqrt */ + double x; +#endif +{ +#ifdef _IEEE_LIBM + return __ieee754_sqrt(x); +#else + double z; + z = __ieee754_sqrt(x); + if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; + if(x<0.0) { + return __kernel_standard(x,x,26); /* sqrt(negative) */ + } else + return z; +#endif +} +libm_hidden_def(sqrt) diff --git a/libm/w_tgamma.c b/libm/w_tgamma.c new file mode 100644 index 0000000..0449e16 --- /dev/null +++ b/libm/w_tgamma.c @@ -0,0 +1,47 @@ +/* @(#)w_gamma.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 gamma(double x) + * Return the logarithm of the Gamma function of x or the Gamma function of x, + * depending on the library mode. + */ + +#include "math.h" +#include "math_private.h" + +libm_hidden_proto(signgam) +#ifdef __STDC__ + double tgamma(double x) +#else + double tgamma(x) + double x; +#endif +{ + double y; + int local_signgam; + y = __ieee754_gamma_r(x,&local_signgam); + if (local_signgam < 0) y = -y; +#ifdef _IEEE_LIBM + return y; +#else + if(_LIB_VERSION == _IEEE_) return y; + + if(!finite(y)&&finite(x)) { + if(floor(x)==x&&x<=0.0) + return __kernel_standard(x,x,41); /* tgamma pole */ + else + return __kernel_standard(x,x,40); /* tgamma overflow */ + } + return y; +#endif +} +libm_hidden_def(tgamma) diff --git a/libnsl/Makefile b/libnsl/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libnsl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libnsl/Makefile.in b/libnsl/Makefile.in new file mode 100644 index 0000000..7cf64a6 --- /dev/null +++ b/libnsl/Makefile.in @@ -0,0 +1,50 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libnsl := -DNOT_IN_libc -DIS_IN_libnsl $(SSP_ALL_CFLAGS) + +LDFLAGS-libnsl.so := $(LDFLAGS) + +LIBS-libnsl.so := $(LIBS) + +libnsl_FULL_NAME := libnsl-$(VERSION).so + +libnsl_DIR := $(top_srcdir)libnsl +libnsl_OUT := $(top_builddir)libnsl + +libnsl_SRC := $(libnsl_DIR)/nsl.c +libnsl_OBJ := $(patsubst $(libnsl_DIR)/%.c,$(libnsl_OUT)/%.o,$(libnsl_SRC)) + +ifeq ($(DOPIC),y) +libnsl-a-y := $(libnsl_OBJ:.o=.os) +else +libnsl-a-y := $(libnsl_OBJ) +endif +libnsl-so-y := $(libnsl_OBJ:.o=.os) + +lib-a-y += $(top_builddir)lib/libnsl.a +lib-so-y += $(top_builddir)lib/libnsl.so +objclean-y += libnsl_clean + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libnsl.so: $(top_builddir)lib/libnsl.a $(libc.depend) +else +$(top_builddir)lib/libnsl.so: $(libnsl_OUT)/libnsl_so.a $(libc.depend) +endif + $(call link.so,$(libnsl_FULL_NAME),$(MAJOR_VERSION)) + +$(libnsl_OUT)/libnsl_so.a: $(libnsl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libnsl.a: $(libnsl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +libnsl_clean: + $(do_rm) $(addprefix $(libnsl_OUT)/*., o os a) diff --git a/libnsl/nsl.c b/libnsl/nsl.c new file mode 100644 index 0000000..37d5b93 --- /dev/null +++ b/libnsl/nsl.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * libnsl for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +void __stub2(void); +void __stub2(void) +{ + return; +} +link_warning (__stub2, "the `libnsl' library is a stub. Do you really need it?") diff --git a/libpthread/Makefile b/libpthread/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libpthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/Makefile.in b/libpthread/Makefile.in new file mode 100644 index 0000000..bda935b --- /dev/null +++ b/libpthread/Makefile.in @@ -0,0 +1,11 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifneq ($(PTNAME),) +include $(PTDIR)/Makefile.in +include $(PTDIR)_db/Makefile.in +endif diff --git a/libpthread/linuxthreads.old/Makefile b/libpthread/linuxthreads.old/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/libpthread/linuxthreads.old/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/linuxthreads.old/Makefile.in b/libpthread/linuxthreads.old/Makefile.in new file mode 100644 index 0000000..d504b99 --- /dev/null +++ b/libpthread/linuxthreads.old/Makefile.in @@ -0,0 +1,123 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-dir_linuxthreads.old := -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-linuxthreads.old := $(CFLAGS-dir_linuxthreads.old) $(SSP_ALL_CFLAGS) + +CFLAGS-libpthread/linuxthreads.old/sysdeps/$(TARGET_ARCH)/ := $(CFLAGS-linuxthreads.old) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LIBS-libpthread.so := $(LIBS) $(ldso) + +START_FILE-libpthread.so := $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) + +libpthread_FULL_NAME := libpthread-$(VERSION).so + +libpthread_DIR := $(top_srcdir)libpthread/linuxthreads.old +libpthread_OUT := $(top_builddir)libpthread/linuxthreads.old + +-include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch + +libpthread_SRC := \ + attr.c cancel.c condvar.c errno.c events.c join.c lockfile.c manager.c \ + mutex.c oldsemaphore.c pt-machine.c ptfork.c ptlongjmp.c \ + rwlock.c semaphore.c signals.c specific.c spinlock.c wrapsyscall.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +libpthread_SRC += locale.c +endif + +libpthread_SPEC_SRC := pthread.c +libpthread_SPEC_SRC := $(patsubst %.c,$(libpthread_DIR)/%.c,$(libpthread_SPEC_SRC)) + +# remove generic sources, if arch specific version is present +ifneq ($(strip $(libpthread_ARCH_SRC)),) +libpthread_SRC := $(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(notdir $(libpthread_ARCH_SRC))),$(libpthread_SRC)) +endif + +libpthread_SRC := $(patsubst %,$(libpthread_DIR)/%,$(libpthread_SRC)) + +libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC)) + +# +# Stuff that goes into libc.so, not libpthread.so +# +CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads.old) +CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads.old) +libpthread_libc_CSRC := forward.c libc_pthread_init.c +libpthread_libc_OBJ := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC)) +libc-static-y += $(libpthread_OUT)/libc_pthread_init.o +libc-shared-y += $(libpthread_libc_OBJ:.o=.oS) + +libpthread-static-y += $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SPEC_SRC)) +libpthread-shared-y += $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.oS,$(libpthread_SPEC_SRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(libpthread_OBJ:.o=.os) $(libpthread-static-y:.o=.os) +else +libpthread-a-y += $(libpthread_OBJ) $(libpthread-static-y) +endif +libpthread-so-y += $(libpthread_OBJ:.o=.os) $(libpthread-shared-y) + +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +#ifeq ($(DOMULTI),n) +$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) + $(call link.so,$(libpthread_FULL_NAME),$(MAJOR_VERSION)) +#else +#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend) +# $(call linkm.so,$(libpthread_FULL_NAME),$(MAJOR_VERSION)) +#endif + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ + $(do_ar) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC) $(libpthread_SPEC_SRC) + $(Q)$(RM) $@ + $(compile-m) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +include/pthread.h: + $(do_ln) ../$(PTDIR)/sysdeps/pthread/$(@F) $(top_builddir)$@ +include/semaphore.h: + $(do_ln) ../$(PTDIR)/$(@F) $(top_builddir)$@ +include/bits/pthreadtypes.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/pthread/bits/$(@F) $(top_builddir)$@ + +linuxthreads_headers := include/pthread.h include/semaphore.h \ + include/bits/pthreadtypes.h +$(linuxthreads_headers): $(wildcard $(addprefix include/config/linuxthreads/,old.h new.h)) +headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers) + +objclean-y += libpthread_clean +headers_clean-y += linuxthreads_headers_clean +linuxthreads_headers_clean: + $(do_rm) $(addprefix $(top_builddir),$(linuxthreads_headers)) + +libpthread_clean: + $(do_rm) $(addprefix $(libpthread_OUT)/*., o os oS a) diff --git a/libpthread/linuxthreads.old/attr.c b/libpthread/linuxthreads.old/attr.c new file mode 100644 index 0000000..30294af --- /dev/null +++ b/libpthread/linuxthreads.old/attr.c @@ -0,0 +1,238 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* changed for uClibc */ +#define __sched_get_priority_min sched_get_priority_min +#define __sched_get_priority_max sched_get_priority_max + +/* Handling of thread attributes */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +libpthread_hidden_proto(pthread_attr_destroy) +libpthread_hidden_proto(pthread_attr_init) +libpthread_hidden_proto(pthread_attr_getdetachstate) +libpthread_hidden_proto(pthread_attr_setdetachstate) +libpthread_hidden_proto(pthread_attr_getinheritsched) +libpthread_hidden_proto(pthread_attr_setinheritsched) +libpthread_hidden_proto(pthread_attr_setschedparam) +libpthread_hidden_proto(pthread_attr_getschedparam) +libpthread_hidden_proto(pthread_attr_getschedpolicy) +libpthread_hidden_proto(pthread_attr_setschedpolicy) +libpthread_hidden_proto(pthread_attr_getscope) +libpthread_hidden_proto(pthread_attr_setscope) + +/* NOTE: With uClibc I don't think we need this versioning stuff. + * Therefore, define the function pthread_attr_init() here using + * a strong symbol. */ + +//int __pthread_attr_init_2_1(pthread_attr_t *attr) +int pthread_attr_init(pthread_attr_t *attr) +{ + size_t ps = getpagesize (); + + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + attr->__guardsize = ps; + attr->__stackaddr = NULL; + attr->__stackaddr_set = 0; + attr->__stacksize = STACK_SIZE - ps; + return 0; +} +libpthread_hidden_def(pthread_attr_init) + +/* uClibc: leave out this for now. */ +#if DO_PTHREAD_VERSIONING_WITH_UCLIBC +#if defined __PIC__ && defined DO_VERSIONING +default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1); + +int __pthread_attr_init_2_0(pthread_attr_t *attr) +{ + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + return 0; +} +symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0); +#else +strong_alias (__pthread_attr_init_2_1, pthread_attr_init) +#endif +#endif /* DO_PTHREAD_VERSIONING_WITH_UCLIBC */ + +int pthread_attr_destroy(pthread_attr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_attr_destroy) + + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + if (detachstate < PTHREAD_CREATE_JOINABLE || + detachstate > PTHREAD_CREATE_DETACHED) + return EINVAL; + attr->__detachstate = detachstate; + return 0; +} +libpthread_hidden_def(pthread_attr_setdetachstate) + +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + *detachstate = attr->__detachstate; + return 0; +} +libpthread_hidden_def(pthread_attr_getdetachstate) + +int pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + int max_prio = __sched_get_priority_max(attr->__schedpolicy); + int min_prio = __sched_get_priority_min(attr->__schedpolicy); + + if (param->sched_priority < min_prio || param->sched_priority > max_prio) + return EINVAL; + memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); + return 0; +} +libpthread_hidden_def(pthread_attr_setschedparam) + +int pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); + return 0; +} +libpthread_hidden_def(pthread_attr_getschedparam) + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + attr->__schedpolicy = policy; + return 0; +} +libpthread_hidden_def(pthread_attr_setschedpolicy) + +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + *policy = attr->__schedpolicy; + return 0; +} +libpthread_hidden_def(pthread_attr_getschedpolicy) + +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + attr->__inheritsched = inherit; + return 0; +} +libpthread_hidden_def(pthread_attr_setinheritsched) + +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + *inherit = attr->__inheritsched; + return 0; +} +libpthread_hidden_def(pthread_attr_getinheritsched) + +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + switch (scope) { + case PTHREAD_SCOPE_SYSTEM: + attr->__scope = scope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +} +libpthread_hidden_def(pthread_attr_setscope) + +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + *scope = attr->__scope; + return 0; +} +libpthread_hidden_def(pthread_attr_getscope) + +int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +{ + size_t ps = getpagesize (); + + /* First round up the guard size. */ + guardsize = roundup (guardsize, ps); + + /* The guard size must not be larger than the stack itself */ + if (guardsize >= attr->__stacksize) return EINVAL; + + attr->__guardsize = guardsize; + + return 0; +} +weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) + +int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +{ + *guardsize = attr->__guardsize; + return 0; +} +weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) + +int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + attr->__stackaddr_set = 1; + return 0; +} +weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ + *stackaddr = attr->__stackaddr; + return 0; +} +weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + /* We don't accept value smaller than PTHREAD_STACK_MIN. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} +weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) + +int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +{ + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/libpthread/linuxthreads.old/cancel.c b/libpthread/linuxthreads.old/cancel.c new file mode 100644 index 0000000..239b821 --- /dev/null +++ b/libpthread/linuxthreads.old/cancel.c @@ -0,0 +1,221 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread cancellation */ + +#define __FORCE_GLIBC +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#ifdef __UCLIBC_HAS_RPC__ +#include +extern void __rpc_thread_destroy(void); +#endif +#include + +#include + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +libpthread_hidden_proto(pthread_setcancelstate) +libpthread_hidden_proto(pthread_setcanceltype) + +int pthread_setcancelstate(int state, int * oldstate) +{ + pthread_descr self = thread_self(); + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); + THREAD_SETMEM(self, p_cancelstate, state); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +libpthread_hidden_def(pthread_setcancelstate) + +int pthread_setcanceltype(int type, int * oldtype) +{ + pthread_descr self = thread_self(); + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, type); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +libpthread_hidden_def(pthread_setcanceltype) + +int pthread_cancel(pthread_t thread) +{ + pthread_handle handle = thread_handle(thread); + int pid; + int dorestart = 0; + pthread_descr th; + pthread_extricate_if *pextricate; + int already_canceled; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + + th = handle->h_descr; + + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { + __pthread_unlock(&handle->h_lock); + return 0; + } + + pextricate = th->p_extricate; + pid = th->p_pid; + + /* If the thread has registered an extrication interface, then + invoke the interface. If it returns 1, then we succeeded in + dequeuing the thread from whatever waiting object it was enqueued + with. In that case, it is our responsibility to wake it up. + And also to set the p_woken_by_cancel flag so the woken thread + can tell that it was woken by cancellation. */ + + if (pextricate != NULL) { + dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); + th->p_woken_by_cancel = dorestart; + } + + __pthread_unlock(&handle->h_lock); + + /* If the thread has suspended or is about to, then we unblock it by + issuing a restart, instead of a cancel signal. Otherwise we send + the cancel signal to unblock the thread from a cancellation point, + or to initiate asynchronous cancellation. The restart is needed so + we have proper accounting of restarts; suspend decrements the thread's + resume count, and restart() increments it. This also means that suspend's + handling of the cancel signal is obsolete. */ + + if (dorestart) + restart(th); + else + kill(pid, __pthread_sig_cancel); + + return 0; +} + +void pthread_testcancel(void) +{ + pthread_descr self = thread_self(); + if (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); +} + +void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + THREAD_SETMEM(self, p_cleanup, buffer); +} +strong_alias(_pthread_cleanup_push_defer,__pthread_cleanup_push_defer) + +void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); + THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} +strong_alias(_pthread_cleanup_pop_restore,__pthread_cleanup_pop_restore) + + +void __pthread_perform_cleanup(char *currentframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev) + { +#if _STACK_GROWS_DOWN + if ((char *) c <= currentframe) + break; +#elif _STACK_GROWS_UP + if ((char *) c >= currentframe) + break; +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + +#ifdef __UCLIBC_HAS_RPC__ + /* And the TSD which needs special help. */ + if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) + __rpc_thread_destroy (); +#endif +} + +#ifndef __PIC__ +/* We need a hook to force the cancelation wrappers to be linked in when + static libpthread is used. */ +extern const int __pthread_provide_wrappers; +static const int * const __pthread_require_wrappers = + &__pthread_provide_wrappers; +#endif diff --git a/libpthread/linuxthreads.old/condvar.c b/libpthread/linuxthreads.old/condvar.c new file mode 100644 index 0000000..23e7139 --- /dev/null +++ b/libpthread/linuxthreads.old/condvar.c @@ -0,0 +1,314 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* and Pavel Krauz (krauz@fsid.cvut.cz). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Condition variables */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +libpthread_hidden_proto(pthread_cond_broadcast) +libpthread_hidden_proto(pthread_cond_destroy) +libpthread_hidden_proto(pthread_cond_init) +libpthread_hidden_proto(pthread_cond_signal) +libpthread_hidden_proto(pthread_cond_wait) +libpthread_hidden_proto(pthread_cond_timedwait) + +libpthread_hidden_proto(pthread_condattr_destroy) +libpthread_hidden_proto(pthread_condattr_init) + +int pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr attribute_unused) +{ + __pthread_init_lock(&cond->__c_lock); + cond->__c_waiting = NULL; + return 0; +} +libpthread_hidden_def(pthread_cond_init) + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + if (cond->__c_waiting != NULL) return EBUSY; + return 0; +} +libpthread_hidden_def(pthread_cond_destroy) + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int cond_extricate_func(void *obj, pthread_descr th) +{ + volatile pthread_descr self = thread_self(); + pthread_cond_t *cond = obj; + int did_remove = 0; + + __pthread_lock(&cond->__c_lock, self); + did_remove = remove_from_queue(&cond->__c_waiting, th); + __pthread_unlock(&cond->__c_lock); + + return did_remove; +} + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + volatile pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Atomically enqueue thread for waiting, but only if it is not + canceled. If the thread is canceled, then it will fall through the + suspend call below, and then call pthread_exit without + having to worry about whether it is still on the condition variable queue. + This depends on pthread_cancel setting p_canceled before calling the + extricate function. */ + + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + __pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Check for cancellation again, to provide correct cancellation + point behavior */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + __pthread_mutex_lock(mutex); + return 0; +} +libpthread_hidden_def(pthread_cond_wait) + +static int +pthread_cond_timedwait_relative(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + volatile pthread_descr self = thread_self(); + int already_canceled = 0; + pthread_extricate_if extr; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Enqueue to wait on the condition and check for cancellation. */ + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + __pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + if (!timedsuspend(self, abstime)) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&cond->__c_lock, self); + was_on_queue = remove_from_queue(&cond->__c_waiting, self); + __pthread_unlock(&cond->__c_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __pthread_mutex_lock(mutex); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* The remaining logic is the same as in other cancellable waits, + such as pthread_join sem_wait or pthread_cond wait. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + __pthread_mutex_lock(mutex); + return 0; +} + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + /* Indirect call through pointer! */ + return pthread_cond_timedwait_relative(cond, mutex, abstime); +} +libpthread_hidden_def(pthread_cond_timedwait) + +int pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_descr th; + + __pthread_lock(&cond->__c_lock, NULL); + th = dequeue(&cond->__c_waiting); + __pthread_unlock(&cond->__c_lock); + if (th != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +libpthread_hidden_def(pthread_cond_signal) + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_descr tosignal, th; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ + tosignal = cond->__c_waiting; + cond->__c_waiting = NULL; + __pthread_unlock(&cond->__c_lock); + /* Now signal each process in the queue */ + while ((th = dequeue(&tosignal)) != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +libpthread_hidden_def(pthread_cond_broadcast) + +int pthread_condattr_init(pthread_condattr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_condattr_init) + +int pthread_condattr_destroy(pthread_condattr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_condattr_destroy) + +int pthread_condattr_getpshared (const pthread_condattr_t *attr attribute_unused, int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_condattr_setpshared (pthread_condattr_t *attr attribute_unused, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/libpthread/linuxthreads.old/debug.h b/libpthread/linuxthreads.old/debug.h new file mode 100644 index 0000000..76779da --- /dev/null +++ b/libpthread/linuxthreads.old/debug.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** NAME: +** debug.h +** +** DESCRIPTION: +** This header file defines the debug macros used in pthreads. To turn +** debugging on, add -DDEBUG_PT to CFLAGS. It was added to the original +** distribution of linuxthreads. +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Library General Public License for more details. +** +****************************************************************************/ + +#ifndef _PT_DEBUG_H +#define _PT_DEBUG_H + +#include + +#ifdef __DODEBUG_PT__ +# define DEBUG_PT +#endif + +/* define the PDEBUG macro here */ +#undef PDEBUG +#ifdef DEBUG_PT +# define PDEBUG(fmt, args...) __pthread_message("%s: " fmt, __FUNCTION__, ## args) +#else +# define PDEBUG(fmt, args...) /* debug switched off */ +#endif + +#endif /* _PT_DEBUG_H */ diff --git a/libpthread/linuxthreads.old/errno.c b/libpthread/linuxthreads.old/errno.c new file mode 100644 index 0000000..f5778f9 --- /dev/null +++ b/libpthread/linuxthreads.old/errno.c @@ -0,0 +1,37 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Define the location of errno for the remainder of the C library */ + +#define __FORCE_GLIBC +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include + +int * +__errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_errnop); +} + +int * +__h_errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_h_errnop); +} diff --git a/libpthread/linuxthreads.old/events.c b/libpthread/linuxthreads.old/events.c new file mode 100644 index 0000000..a4bf1f8 --- /dev/null +++ b/libpthread/linuxthreads.old/events.c @@ -0,0 +1,37 @@ +/* Event functions used while debugging. + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The functions contained here do nothing, they just return. */ + +#include "internals.h" + +void +__linuxthreads_create_event (void) +{ +} + +void +__linuxthreads_death_event (void) +{ +} + +void +__linuxthreads_reap_event (void) +{ +} diff --git a/libpthread/linuxthreads.old/forward.c b/libpthread/linuxthreads.old/forward.c new file mode 100644 index 0000000..5dc9cf4 --- /dev/null +++ b/libpthread/linuxthreads.old/forward.c @@ -0,0 +1,168 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* psm: keep this before internals.h */ +libc_hidden_proto(exit) +#if 0 +vda: here is why: +In libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h +adding libc_hidden_proto(foo) just before weak_extern (__pthread_initialize) +will not warn: + /* libc_hidden_proto(foo) */ + weak_extern (__pthread_initialize) + /* libc_hidden_proto(foo) */ +but adding after will! Which is extremely strange - +weak_extern expands into just "#pragma weak __pthread_initialize". +TODO: determine whether it is a gcc bug or what +(see gcc.gnu.org/PR36282). +For now, just include all headers before internals.h +(they are again included in internals.h - maybe remove them there later) +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "internals.h" + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +# define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) + +FORWARD (pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit) + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) +strong_alias(pthread_mutex_init, __pthread_mutex_init) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) +FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) + +FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) +FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/libpthread/linuxthreads.old/internals.h b/libpthread/linuxthreads.old/internals.h new file mode 100644 index 0000000..0cb9735 --- /dev/null +++ b/libpthread/linuxthreads.old/internals.h @@ -0,0 +1,532 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _INTERNALS_H +#define _INTERNALS_H 1 + +/* Internal data structures */ + +/* Includes */ + +#include /* for _LIBC_TSD_KEY_N */ +#include +#include +#include +#include +#include +#include +#include +#include "pt-machine.h" +#include "semaphore.h" +#include "../linuxthreads.old_db/thread_dbP.h" +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#ifndef THREAD_GETMEM +# define THREAD_GETMEM(descr, member) descr->member +#endif +#ifndef THREAD_GETMEM_NC +# define THREAD_GETMEM_NC(descr, member) descr->member +#endif +#ifndef THREAD_SETMEM +# define THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif +#ifndef THREAD_SETMEM_NC +# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) +#endif + +/* Arguments passed to thread creation routine */ + +struct pthread_start_args { + void * (*start_routine)(void *); /* function to run */ + void * arg; /* its argument */ + sigset_t mask; /* initial signal mask for thread */ + int schedpolicy; /* initial scheduling policy (if any) */ + struct sched_param schedparam; /* initial scheduling parameters (if any) */ +}; + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + +typedef void (*destr_function)(void *); + +struct pthread_key_struct { + int in_use; /* already allocated? */ + destr_function destr; /* destruction routine */ +}; + + +#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } } + +/* The type of thread descriptors */ + +typedef struct _pthread_descr_struct * pthread_descr; + +/* Callback interface for removing the thread from waiting on an + object if it is cancelled while waiting or about to wait. + This hold a pointer to the object, and a pointer to a function + which ``extricates'' the thread from its enqueued state. + The function takes two arguments: pointer to the wait object, + and a pointer to the thread. It returns 1 if an extrication + actually occured, and hence the thread must also be signalled. + It returns 0 if the thread had already been extricated. */ + +typedef struct _pthread_extricate_struct { + void *pu_object; + int (*pu_extricate_func)(void *, pthread_descr); +} pthread_extricate_if; + +/* Atomic counter made possible by compare_and_swap */ + +struct pthread_atomic { + long p_count; + int p_spinlock; +}; + +/* Context info for read write locks. The pthread_rwlock_info structure + is information about a lock that has been read-locked by the thread + in whose list this structure appears. The pthread_rwlock_context + is embedded in the thread context and contains a pointer to the + head of the list of lock info structures, as well as a count of + read locks that are untracked, because no info structure could be + allocated for them. */ + +struct _pthread_rwlock_t; + +typedef struct _pthread_rwlock_info { + struct _pthread_rwlock_info *pr_next; + struct _pthread_rwlock_t *pr_lock; + int pr_lock_count; +} pthread_readlock_info; + +struct _pthread_descr_struct { + pthread_descr p_nextlive, p_prevlive; + /* Double chaining of active threads */ + pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ + pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ + pthread_t p_tid; /* Thread identifier */ + int p_pid; /* PID of Unix process */ + int p_priority; /* Thread priority (== 0 if not realtime) */ + struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ + int p_signal; /* last signal received */ + sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */ + sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ + char p_terminated; /* true if terminated e.g. by pthread_exit */ + char p_detached; /* true if detached */ + char p_exited; /* true if the assoc. process terminated */ + void * p_retval; /* placeholder for return value */ + int p_retcode; /* placeholder for return code */ + pthread_descr p_joining; /* thread joining on that thread or NULL */ + struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ + char p_cancelstate; /* cancellation state */ + char p_canceltype; /* cancellation type (deferred/async) */ + char p_canceled; /* cancellation request pending */ + int * p_errnop; /* pointer to used errno variable */ + int p_errno; /* error returned by last system call */ + int * p_h_errnop; /* pointer to used h_errno variable */ + int p_h_errno; /* error returned by last netdb function */ + char * p_in_sighandler; /* stack address of sighandler, or NULL */ + char p_sigwaiting; /* true if a sigwait() is in progress */ + struct pthread_start_args p_start_args; /* arguments for thread creation */ + void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ + void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ + int p_userstack; /* nonzero if the user provided the stack */ + void *p_guardaddr; /* address of guard area or NULL */ + size_t p_guardsize; /* size of guard area */ + pthread_descr p_self; /* Pointer to this structure */ + int p_nr; /* Index of descriptor in __pthread_handles */ + int p_report_events; /* Nonzero if events must be reported. */ + td_eventbuf_t p_eventbuf; /* Data for event. */ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ + char p_condvar_avail; /* flag if conditional variable became avail */ + char p_sem_avail; /* flag if semaphore became available */ + pthread_extricate_if *p_extricate; /* See above */ + pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ + pthread_readlock_info *p_readlock_free; /* Free list of structs */ + int p_untracked_readlock_count; /* Readlocks not tracked by list */ + /* New elements must be added at the end. */ +#ifdef __UCLIBC_HAS_XLOCALE__ + __locale_t locale; /* thread-specific locale from uselocale() only! */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +} __attribute__ ((aligned(32))); /* We need to align the structure so that + doubles are aligned properly. This is 8 + bytes on MIPS and 16 bytes on MIPS64. + 32 bytes might give better cache + utilization. */ + +/* The type of thread handles. */ + +typedef struct pthread_handle_struct * pthread_handle; + +struct pthread_handle_struct { + struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */ + pthread_descr h_descr; /* Thread descriptor or NULL if invalid */ + char * h_bottom; /* Lowest address in the stack thread */ +}; + +/* The type of messages sent to the thread manager thread */ + +struct pthread_request { + pthread_descr req_thread; /* Thread doing the request */ + enum { /* Request kind */ + REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, + REQ_POST, REQ_DEBUG, REQ_KICK + } req_kind; + union { /* Arguments for request */ + struct { /* For REQ_CREATE: */ + const pthread_attr_t * attr; /* thread attributes */ + void * (*fn)(void *); /* start function */ + void * arg; /* argument to start function */ + sigset_t mask; /* signal mask */ + } create; + struct { /* For REQ_FREE: */ + pthread_t thread_id; /* identifier of thread to free */ + } free; + struct { /* For REQ_PROCESS_EXIT: */ + int code; /* exit status */ + } exit; + void * post; /* For REQ_POST: the semaphore */ + } req_args; +}; + + +/* Signals used for suspend/restart and for cancellation notification. */ + +extern int __pthread_sig_restart; +extern int __pthread_sig_cancel; + +/* Signal used for interfacing with gdb */ + +extern int __pthread_sig_debug; + +/* Global array of thread handles, used for validating a thread id + and retrieving the corresponding thread descriptor. Also used for + mapping the available stack segments. */ + +extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; + +/* Descriptor of the initial thread */ + +extern struct _pthread_descr_struct __pthread_initial_thread; + +/* Descriptor of the manager thread */ + +extern struct _pthread_descr_struct __pthread_manager_thread; + +/* Descriptor of the main thread */ + +extern pthread_descr __pthread_main_thread; + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. + Initially 0, meaning that the current thread is (by definition) + the initial thread. */ + +/* For non-MMU systems also remember to stack top of the initial thread. + * This is adapted when other stacks are malloc'ed since we don't know + * the bounds a-priori. -StS */ + +extern char *__pthread_initial_thread_bos; +#ifndef __ARCH_USE_MMU__ +extern char *__pthread_initial_thread_tos; +#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) \ + if ((tos)>=__pthread_initial_thread_bos \ + && (bos)<__pthread_initial_thread_tos) \ + __pthread_initial_thread_bos = (tos)+1 +#else +#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */ +#endif /* __ARCH_USE_MMU__ */ + + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or all threads have stacks supplied by LinuxThreads (if 0). */ + +extern int __pthread_nonstandard_stacks; + +/* File descriptor for sending requests to the thread manager. + Initially -1, meaning that __pthread_initialize_manager must be called. */ + +extern int __pthread_manager_request; + +/* Other end of the pipe for sending requests to the thread manager. */ + +extern int __pthread_manager_reader; + +/* Limits of the thread manager stack. */ + +extern char *__pthread_manager_thread_bos; +extern char *__pthread_manager_thread_tos; + +/* Pending request for a process-wide exit */ + +extern int __pthread_exit_requested, __pthread_exit_code; + +/* Set to 1 by gdb if we're debugging */ + +extern volatile int __pthread_threads_debug; + +/* Globally enabled events. */ +extern volatile td_thr_events_t __pthread_threads_events; + +/* Pointer to descriptor of thread with last event. */ +extern volatile pthread_descr __pthread_last_event; + +/* Return the handle corresponding to a thread id */ + +static __inline__ pthread_handle thread_handle(pthread_t id) +{ + return &__pthread_handles[id % PTHREAD_THREADS_MAX]; +} + +/* Validate a thread handle. Must have acquired h->h_spinlock before. */ + +static __inline__ int invalid_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id; +} + +/* Fill in defaults left unspecified by pt-machine.h. */ + +/* The page size we can get from the system. This should likely not be + changed by the machine file but, you never know. */ +extern size_t __pagesize; +#include +#ifndef PAGE_SIZE +#define PAGE_SIZE (sysconf (_SC_PAGESIZE)) +#endif + +/* The max size of the thread stack segments. If the default + THREAD_SELF implementation is used, this must be a power of two and + a multiple of PAGE_SIZE. */ +#ifndef STACK_SIZE +#ifdef __ARCH_USE_MMU__ +#define STACK_SIZE (2 * 1024 * 1024) +#else +#define STACK_SIZE (4 * __pagesize) +#endif +#endif + +/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE (4 * __pagesize) +#endif + +/* Size of the thread manager stack. The "- 32" avoids wasting space + with some malloc() implementations. */ +#ifndef THREAD_MANAGER_STACK_SIZE +#define THREAD_MANAGER_STACK_SIZE (2 * __pagesize - 32) +#endif + +/* The base of the "array" of thread stacks. The array will grow down from + here. Defaults to the calculated bottom of the initial application + stack. */ +#ifndef THREAD_STACK_START_ADDRESS +#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the + architecture doesn't need a memory barrier instruction (e.g. Intel + x86). Still we need the compiler to respect the barrier and emit + all outstanding operations which modify memory. Some architectures + distinguish between full, read and write barriers. */ +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER() __asm__ ("" : : : "memory") +#endif +#ifndef READ_MEMORY_BARRIER +#define READ_MEMORY_BARRIER() MEMORY_BARRIER() +#endif +#ifndef WRITE_MEMORY_BARRIER +#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() +#endif + +/* Recover thread descriptor for the current thread */ + +extern pthread_descr __pthread_find_self (void) __attribute__ ((const)); + +static __inline__ pthread_descr thread_self (void) __attribute__ ((const)); +static __inline__ pthread_descr thread_self (void) +{ +#ifdef THREAD_SELF + return THREAD_SELF; +#else + char *sp = CURRENT_STACK_FRAME; +#ifdef __ARCH_USE_MMU__ + if (sp >= __pthread_initial_thread_bos) + return &__pthread_initial_thread; + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) + return &__pthread_manager_thread; + else if (__pthread_nonstandard_stacks) + return __pthread_find_self(); + else + return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; +#else + /* For non-MMU we need to be more careful about the initial thread stack. + * We refine the initial thread stack bounds dynamically as we allocate + * the other stack frame such that it doesn't overlap with them. Then + * we can be sure to pick the right thread according to the current SP */ + + /* Since we allow other stack frames to be above or below, we need to + * treat this case special. When pthread_initialize() wasn't called yet, + * only the initial thread is there. */ + if (__pthread_initial_thread_bos == NULL) { + return &__pthread_initial_thread; + } + else if (sp >= __pthread_initial_thread_bos + && sp < __pthread_initial_thread_tos) { + return &__pthread_initial_thread; + } + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) { + return &__pthread_manager_thread; + } + else { + return __pthread_find_self(); + } +#endif /* __ARCH_USE_MMU__ */ +#endif +} + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads attribute_hidden; +extern int __librt_multiple_threads; + +/* Internal global functions */ + +void __pthread_do_exit (void *retval, char *currentframe) + __attribute__ ((__noreturn__)); +void __pthread_destroy_specifics(void); +void __pthread_perform_cleanup(char *currentframe); +int __pthread_initialize_manager(void); +void __pthread_message(char * fmt, ...); +int __pthread_manager(void *reqfd); +int __pthread_manager_event(void *reqfd); +void __pthread_manager_sighandler(int sig); +void __pthread_reset_main_thread(void); +void __fresetlockfiles(void); +void __pthread_manager_adjust_prio(int thread_prio); +void __pthread_initialize_minimal (void); + +extern void __pthread_exit (void *retval) +#if defined NOT_IN_libc && defined IS_IN_libpthread + attribute_noreturn +#endif + ; + +extern int __pthread_attr_setguardsize __P ((pthread_attr_t *__attr, + size_t __guardsize)); +extern int __pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr, + size_t *__guardsize)); +extern int __pthread_attr_setstackaddr __P ((pthread_attr_t *__attr, + void *__stackaddr)); +extern int __pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr, + void **__stackaddr)); +extern int __pthread_attr_setstacksize __P ((pthread_attr_t *__attr, + size_t __stacksize)); +extern int __pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr, + size_t *__stacksize)); +extern int __pthread_getconcurrency __P ((void)); +extern int __pthread_setconcurrency __P ((int __level)); +extern void __pthread_kill_other_threads_np __P ((void)); + +extern void __pthread_restart_old(pthread_descr th); +extern void __pthread_suspend_old(pthread_descr self); +extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_restart_new(pthread_descr th); +extern void __pthread_suspend_new(pthread_descr self); +extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_wait_for_restart_signal(pthread_descr self); + +/* Global pointers to old or new suspend functions */ + +extern void (*__pthread_restart)(pthread_descr); +extern void (*__pthread_suspend)(pthread_descr); + +/* Prototypes for the function without cancelation support when the + normal version has it. */ +extern __typeof(close) __libc_close; +extern __typeof(nanosleep) __libc_nanosleep; +extern __typeof(read) __libc_read; +extern __typeof(waitpid) __libc_waitpid; +extern __typeof(write) __libc_write; + +extern __typeof(pthread_mutex_init) __pthread_mutex_init attribute_hidden; +extern __typeof(pthread_mutex_destroy) __pthread_mutex_destroy attribute_hidden; +extern __typeof(pthread_mutex_lock) __pthread_mutex_lock attribute_hidden; +extern __typeof(pthread_mutex_trylock) __pthread_mutex_trylock attribute_hidden; +extern __typeof(pthread_mutex_unlock) __pthread_mutex_attribute_hidden; + +/* Prototypes for some of the new semaphore functions. */ +extern int __new_sem_post (sem_t * sem); + +/* TSD. */ +extern int __pthread_internal_tsd_set (int key, const void * pointer); +extern void * __pthread_internal_tsd_get (int key); +extern void ** __attribute__ ((__const__)) + __pthread_internal_tsd_address (int key); + +/* The functions called the signal events. */ +extern void __linuxthreads_create_event (void); +extern void __linuxthreads_death_event (void); +extern void __linuxthreads_reap_event (void); + +#include + +extern int * __libc_pthread_init (const struct pthread_functions *functions); + +#endif /* internals.h */ diff --git a/libpthread/linuxthreads.old/join.c b/libpthread/linuxthreads.old/join.c new file mode 100644 index 0000000..a46d0b6 --- /dev/null +++ b/libpthread/linuxthreads.old/join.c @@ -0,0 +1,231 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread termination and joining */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "debug.h" /* PDEBUG, added by StS */ + +libpthread_hidden_proto (pthread_exit) +void pthread_exit(void * retval) +{ + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} +libpthread_hidden_def (pthread_exit) + +void __pthread_do_exit(void *retval, char *currentframe) +{ + pthread_descr self = thread_self(); + pthread_descr joining; + struct pthread_request request; + PDEBUG("self=%p, pid=%d\n", self, self->p_pid); + + /* obey POSIX behavior and prevent cancellation functions from + * being called more than once. + * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html + */ + THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + + /* Call cleanup functions and destroy the thread-specific data */ + __pthread_perform_cleanup(currentframe); + __pthread_destroy_specifics(); + /* Store return value */ + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_retval, retval); + /* See whether we have to signal the death. */ + if (THREAD_GETMEM(self, p_report_events)) + { + /* See whether TD_DEATH is in any of the mask. */ + int idx = __td_eventword (TD_DEATH); + uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | THREAD_GETMEM_NC(self, + p_eventbuf.eventmask).event_bits[idx])) + != 0) + { + /* Yep, we have to signal the death. */ + THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); + THREAD_SETMEM(self, p_eventbuf.eventdata, self); + __pthread_last_event = self; + + /* Now call the function to signal the event. */ + __linuxthreads_death_event(); + } + } + /* Say that we've terminated */ + THREAD_SETMEM(self, p_terminated, 1); + /* See if someone is joining on us */ + joining = THREAD_GETMEM(self, p_joining); + PDEBUG("joining = %p, pid=%d\n", joining, joining->p_pid); + __pthread_unlock(THREAD_GETMEM(self, p_lock)); + /* Restart joining thread if any */ + if (joining != NULL) restart(joining); + /* If this is the initial thread, block until all threads have terminated. + If another thread calls exit, we'll be terminated from our signal + handler. */ + if (self == __pthread_main_thread && __pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_MAIN_THREAD_EXIT; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *)&request, sizeof(request))); + suspend(self); + /* Main thread flushes stdio streams and runs atexit functions. + * It also calls a handler within LinuxThreads which sends a process exit + * request to the thread manager. */ + exit(0); + } + /* Exit the process (but don't flush stdio streams, and don't run + atexit functions). */ + _exit(0); +} + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int join_extricate_func(void *obj, pthread_descr th attribute_unused) +{ + volatile pthread_descr self = thread_self(); + pthread_handle handle = obj; + pthread_descr jo; + int did_remove = 0; + + __pthread_lock(&handle->h_lock, self); + jo = handle->h_descr; + did_remove = jo->p_joining != NULL; + jo->p_joining = NULL; + __pthread_unlock(&handle->h_lock); + + return did_remove; +} + +int pthread_join(pthread_t thread_id, void ** thread_return) +{ + volatile pthread_descr self = thread_self(); + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + pthread_extricate_if extr; + int already_canceled = 0; + PDEBUG("\n"); + + /* Set up extrication interface */ + extr.pu_object = handle; + extr.pu_extricate_func = join_extricate_func; + + __pthread_lock(&handle->h_lock, self); + if (invalid_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (th == self) { + __pthread_unlock(&handle->h_lock); + return EDEADLK; + } + /* If detached or already joined, error */ + if (th->p_detached || th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If not terminated yet, suspend ourselves. */ + if (! th->p_terminated) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + th->p_joining = self; + else + already_canceled = 1; + __pthread_unlock(&handle->h_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + PDEBUG("before suspend\n"); + suspend(self); + PDEBUG("after suspend\n"); + /* Deregister extrication interface */ + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + __pthread_lock(&handle->h_lock, self); + } + /* Get return value */ + if (thread_return != NULL) *thread_return = th->p_retval; + __pthread_unlock(&handle->h_lock); + /* Send notification to thread manager */ + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int pthread_detach(pthread_t thread_id) +{ + int terminated; + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + /* If already detached, error */ + if (th->p_detached) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If already joining, don't do anything. */ + if (th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return 0; + } + /* Mark as detached */ + th->p_detached = 1; + terminated = th->p_terminated; + __pthread_unlock(&handle->h_lock); + /* If already terminated, notify thread manager to reclaim resources */ + if (terminated && __pthread_manager_request >= 0) { + request.req_thread = thread_self(); + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} diff --git a/libpthread/linuxthreads.old/libc_pthread_init.c b/libpthread/linuxthreads.old/libc_pthread_init.c new file mode 100644 index 0000000..09606ef --- /dev/null +++ b/libpthread/linuxthreads.old/libc_pthread_init.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "internals.h" +#include "sysdeps/pthread/pthread-functions.h" + +/* Experimentally off - libc_hidden_proto(memcpy) */ + +#if !(USE_TLS && HAVE___THREAD) && defined __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(uselocale) +#endif + +int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); + +int * __libc_pthread_init (const struct pthread_functions *functions) +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#if !(USE_TLS && HAVE___THREAD) && defined __UCLIBC_HAS_XLOCALE__ + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/libpthread/linuxthreads.old/linuxthreads.texi b/libpthread/linuxthreads.old/linuxthreads.texi new file mode 100644 index 0000000..795fb70 --- /dev/null +++ b/libpthread/linuxthreads.old/linuxthreads.texi @@ -0,0 +1,1627 @@ +@node POSIX Threads +@c @node POSIX Threads, , Top, Top +@chapter POSIX Threads +@c %MENU% The standard threads library + +@c This chapter needs more work bigtime. -zw + +This chapter describes the pthreads (POSIX threads) library. This +library provides support functions for multithreaded programs: thread +primitives, synchronization objects, and so forth. It also implements +POSIX 1003.1b semaphores (not to be confused with System V semaphores). + +The threads operations (@samp{pthread_*}) do not use @var{errno}. +Instead they return an error code directly. The semaphore operations do +use @var{errno}. + +@menu +* Basic Thread Operations:: Creating, terminating, and waiting for threads. +* Thread Attributes:: Tuning thread scheduling. +* Cancellation:: Stopping a thread before it's done. +* Cleanup Handlers:: Deallocating resources when a thread is + canceled. +* Mutexes:: One way to synchronize threads. +* Condition Variables:: Another way. +* POSIX Semaphores:: And a third way. +* Thread-Specific Data:: Variables with different values in + different threads. +* Threads and Signal Handling:: Why you should avoid mixing the two, and + how to do it if you must. +* Threads and Fork:: Interactions between threads and the + @code{fork} function. +* Streams and Fork:: Interactions between stdio streams and + @code{fork}. +* Miscellaneous Thread Functions:: A grab bag of utility routines. +@end menu + +@node Basic Thread Operations +@section Basic Thread Operations + +These functions are the thread equivalents of @code{fork}, @code{exit}, +and @code{wait}. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_create (pthread_t * @var{thread}, pthread_attr_t * @var{attr}, void * (*@var{start_routine})(void *), void * @var{arg}) +@code{pthread_create} creates a new thread of control that executes +concurrently with the calling thread. The new thread calls the +function @var{start_routine}, passing it @var{arg} as first argument. The +new thread terminates either explicitly, by calling @code{pthread_exit}, +or implicitly, by returning from the @var{start_routine} function. The +latter case is equivalent to calling @code{pthread_exit} with the result +returned by @var{start_routine} as exit code. + +The @var{attr} argument specifies thread attributes to be applied to the +new thread. @xref{Thread Attributes}, for details. The @var{attr} +argument can also be @code{NULL}, in which case default attributes are +used: the created thread is joinable (not detached) and has an ordinary +(not realtime) scheduling policy. + +On success, the identifier of the newly created thread is stored in the +location pointed by the @var{thread} argument, and a 0 is returned. On +error, a non-zero error code is returned. + +This function may return the following errors: +@table @code +@item EAGAIN +Not enough system resources to create a process for the new thread, +or more than @code{PTHREAD_THREADS_MAX} threads are already active. +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_exit (void *@var{retval}) +@code{pthread_exit} terminates the execution of the calling thread. All +cleanup handlers (@pxref{Cleanup Handlers}) that have been set for the +calling thread with @code{pthread_cleanup_push} are executed in reverse +order (the most recently pushed handler is executed first). Finalization +functions for thread-specific data are then called for all keys that +have non-@code{NULL} values associated with them in the calling thread +(@pxref{Thread-Specific Data}). Finally, execution of the calling +thread is stopped. + +The @var{retval} argument is the return value of the thread. It can be +retrieved from another thread using @code{pthread_join}. + +The @code{pthread_exit} function never returns. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cancel (pthread_t @var{thread}) + +@code{pthread_cancel} sends a cancellation request to the thread denoted +by the @var{thread} argument. If there is no such thread, +@code{pthread_cancel} fails and returns @code{ESRCH}. Otherwise it +returns 0. @xref{Cancellation}, for details. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return}) +@code{pthread_join} suspends the execution of the calling thread until +the thread identified by @var{th} terminates, either by calling +@code{pthread_exit} or by being canceled. + +If @var{thread_return} is not @code{NULL}, the return value of @var{th} +is stored in the location pointed to by @var{thread_return}. The return +value of @var{th} is either the argument it gave to @code{pthread_exit}, +or @code{PTHREAD_CANCELED} if @var{th} was canceled. + +The joined thread @code{th} must be in the joinable state: it must not +have been detached using @code{pthread_detach} or the +@code{PTHREAD_CREATE_DETACHED} attribute to @code{pthread_create}. + +When a joinable thread terminates, its memory resources (thread +descriptor and stack) are not deallocated until another thread performs +@code{pthread_join} on it. Therefore, @code{pthread_join} must be called +once for each joinable thread created to avoid memory leaks. + +At most one thread can wait for the termination of a given +thread. Calling @code{pthread_join} on a thread @var{th} on which +another thread is already waiting for termination returns an error. + +@code{pthread_join} is a cancellation point. If a thread is canceled +while suspended in @code{pthread_join}, the thread execution resumes +immediately and the cancellation is executed without waiting for the +@var{th} thread to terminate. If cancellation occurs during +@code{pthread_join}, the @var{th} thread remains not joined. + +On success, the return value of @var{th} is stored in the location +pointed to by @var{thread_return}, and 0 is returned. On error, one of +the following values is returned: +@table @code +@item ESRCH +No thread could be found corresponding to that specified by @var{th}. +@item EINVAL +The @var{th} thread has been detached, or another thread is already +waiting on termination of @var{th}. +@item EDEADLK +The @var{th} argument refers to the calling thread. +@end table +@end deftypefun + +@node Thread Attributes +@section Thread Attributes + +@comment pthread.h +@comment POSIX + +Threads have a number of attributes that may be set at creation time. +This is done by filling a thread attribute object @var{attr} of type +@code{pthread_attr_t}, then passing it as second argument to +@code{pthread_create}. Passing @code{NULL} is equivalent to passing a +thread attribute object with all attributes set to their default values. + +Attribute objects are consulted only when creating a new thread. The +same attribute object can be used for creating several threads. +Modifying an attribute object after a call to @code{pthread_create} does +not change the attributes of the thread previously created. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_init (pthread_attr_t *@var{attr}) +@code{pthread_attr_init} initializes the thread attribute object +@var{attr} and fills it with default values for the attributes. (The +default values are listed below for each attribute.) + +Each attribute @var{attrname} (see below for a list of all attributes) +can be individually set using the function +@code{pthread_attr_set@var{attrname}} and retrieved using the function +@code{pthread_attr_get@var{attrname}}. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_destroy (pthread_attr_t *@var{attr}) +@code{pthread_attr_destroy} destroys the attribute object pointed to by +@var{attr} releasing any resources associated with it. @var{attr} is +left in an undefined state, and you must not use it again in a call to +any pthreads function until it has been reinitialized. +@end deftypefun + +@findex pthread_attr_setdetachstate +@findex pthread_attr_setguardsize +@findex pthread_attr_setinheritsched +@findex pthread_attr_setschedparam +@findex pthread_attr_setschedpolicy +@findex pthread_attr_setscope +@findex pthread_attr_setstack +@findex pthread_attr_setstackaddr +@findex pthread_attr_setstacksize +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value}) +Set attribute @var{attr} to @var{value} in the attribute object pointed +to by @var{obj}. See below for a list of possible attributes and the +values they can take. + +On success, these functions return 0. If @var{value} is not meaningful +for the @var{attr} being modified, they will return the error code +@code{EINVAL}. Some of the functions have other failure modes; see +below. +@end deftypefun + +@findex pthread_attr_getdetachstate +@findex pthread_attr_getguardsize +@findex pthread_attr_getinheritsched +@findex pthread_attr_getschedparam +@findex pthread_attr_getschedpolicy +@findex pthread_attr_getscope +@findex pthread_attr_getstack +@findex pthread_attr_getstackaddr +@findex pthread_attr_getstacksize +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value}) +Store the current setting of @var{attr} in @var{obj} into the variable +pointed to by @var{value}. + +These functions always return 0. +@end deftypefun + +The following thread attributes are supported: +@table @samp +@item detachstate +Choose whether the thread is created in the joinable state (value +@code{PTHREAD_CREATE_JOINABLE}) or in the detached state +(@code{PTHREAD_CREATE_DETACHED}). The default is +@code{PTHREAD_CREATE_JOINABLE}. + +In the joinable state, another thread can synchronize on the thread +termination and recover its termination code using @code{pthread_join}, +but some of the thread resources are kept allocated after the thread +terminates, and reclaimed only when another thread performs +@code{pthread_join} on that thread. + +In the detached state, the thread resources are immediately freed when +it terminates, but @code{pthread_join} cannot be used to synchronize on +the thread termination. + +A thread created in the joinable state can later be put in the detached +thread using @code{pthread_detach}. + +@item schedpolicy +Select the scheduling policy for the thread: one of @code{SCHED_OTHER} +(regular, non-realtime scheduling), @code{SCHED_RR} (realtime, +round-robin) or @code{SCHED_FIFO} (realtime, first-in first-out). +The default is @code{SCHED_OTHER}. +@c Not doc'd in our manual: FIXME. +@c See @code{sched_setpolicy} for more information on scheduling policies. + +The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} +are available only to processes with superuser privileges. +@code{pthread_attr_setschedparam} will fail and return @code{ENOTSUP} if +you try to set a realtime policy when you are unprivileged. + +The scheduling policy of a thread can be changed after creation with +@code{pthread_setschedparam}. + +@item schedparam +Change the scheduling parameter (the scheduling priority) +for the thread. The default is 0. + +This attribute is not significant if the scheduling policy is +@code{SCHED_OTHER}; it only matters for the realtime policies +@code{SCHED_RR} and @code{SCHED_FIFO}. + +The scheduling priority of a thread can be changed after creation with +@code{pthread_setschedparam}. + +@item inheritsched +Choose whether the scheduling policy and scheduling parameter for the +newly created thread are determined by the values of the +@var{schedpolicy} and @var{schedparam} attributes (value +@code{PTHREAD_EXPLICIT_SCHED}) or are inherited from the parent thread +(value @code{PTHREAD_INHERIT_SCHED}). The default is +@code{PTHREAD_EXPLICIT_SCHED}. + +@item scope +Choose the scheduling contention scope for the created thread. The +default is @code{PTHREAD_SCOPE_SYSTEM}, meaning that the threads contend +for CPU time with all processes running on the machine. In particular, +thread priorities are interpreted relative to the priorities of all +other processes on the machine. The other possibility, +@code{PTHREAD_SCOPE_PROCESS}, means that scheduling contention occurs +only between the threads of the running process: thread priorities are +interpreted relative to the priorities of the other threads of the +process, regardless of the priorities of other processes. + +@code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads. If you +try to set the scope to this value, @code{pthread_attr_setscope} will +fail and return @code{ENOTSUP}. + +@item stackaddr +Provide an address for an application managed stack. The size of the +stack must be at least @code{PTHREAD_STACK_MIN}. + +@item stacksize +Change the size of the stack created for the thread. The value defines +the minimum stack size, in bytes. + +If the value exceeds the system's maximum stack size, or is smaller +than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will +fail and return @code{EINVAL}. + +@item stack +Provide both the address and size of an application managed stack to +use for the new thread. The base of the memory area is @var{stackaddr} +with the size of the memory area, @var{stacksize}, measured in bytes. + +If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN}, +or greater than the system's maximum stack size, or if the value of +@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack} +will fail and return @code{EINVAL}. + +@item guardsize +Change the minimum size in bytes of the guard area for the thread's +stack. The default size is a single page. If this value is set, it +will be rounded up to the nearest page size. If the value is set to 0, +a guard area will not be created for this thread. The space allocated +for the guard area is used to catch stack overflow. Therefore, when +allocating large structures on the stack, a larger guard area may be +required to catch a stack overflow. + +If the caller is managing their own stacks (if the @code{stackaddr} +attribute has been set), then the @code{guardsize} attribute is ignored. + +If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize} +will fail and return @code{EINVAL}. +@end table + +@node Cancellation +@section Cancellation + +Cancellation is the mechanism by which a thread can terminate the +execution of another thread. More precisely, a thread can send a +cancellation request to another thread. Depending on its settings, the +target thread can then either ignore the request, honor it immediately, +or defer it till it reaches a cancellation point. When threads are +first created by @code{pthread_create}, they always defer cancellation +requests. + +When a thread eventually honors a cancellation request, it behaves as if +@code{pthread_exit(PTHREAD_CANCELED)} was called. All cleanup handlers +are executed in reverse order, finalization functions for +thread-specific data are called, and finally the thread stops executing. +If the canceled thread was joinable, the return value +@code{PTHREAD_CANCELED} is provided to whichever thread calls +@var{pthread_join} on it. See @code{pthread_exit} for more information. + +Cancellation points are the points where the thread checks for pending +cancellation requests and performs them. The POSIX threads functions +@code{pthread_join}, @code{pthread_cond_wait}, +@code{pthread_cond_timedwait}, @code{pthread_testcancel}, +@code{sem_wait}, and @code{sigwait} are cancellation points. In +addition, these system calls are cancellation points: + +@multitable @columnfractions .33 .33 .33 +@item @t{accept} @tab @t{open} @tab @t{sendmsg} +@item @t{close} @tab @t{pause} @tab @t{sendto} +@item @t{connect} @tab @t{read} @tab @t{system} +@item @t{fcntl} @tab @t{recv} @tab @t{tcdrain} +@item @t{fsync} @tab @t{recvfrom} @tab @t{wait} +@item @t{lseek} @tab @t{recvmsg} @tab @t{waitpid} +@item @t{msync} @tab @t{send} @tab @t{write} +@item @t{nanosleep} +@end multitable + +@noindent +All library functions that call these functions (such as +@code{printf}) are also cancellation points. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setcancelstate (int @var{state}, int *@var{oldstate}) +@code{pthread_setcancelstate} changes the cancellation state for the +calling thread -- that is, whether cancellation requests are ignored or +not. The @var{state} argument is the new cancellation state: either +@code{PTHREAD_CANCEL_ENABLE} to enable cancellation, or +@code{PTHREAD_CANCEL_DISABLE} to disable cancellation (cancellation +requests are ignored). + +If @var{oldstate} is not @code{NULL}, the previous cancellation state is +stored in the location pointed to by @var{oldstate}, and can thus be +restored later by another call to @code{pthread_setcancelstate}. + +If the @var{state} argument is not @code{PTHREAD_CANCEL_ENABLE} or +@code{PTHREAD_CANCEL_DISABLE}, @code{pthread_setcancelstate} fails and +returns @code{EINVAL}. Otherwise it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setcanceltype (int @var{type}, int *@var{oldtype}) +@code{pthread_setcanceltype} changes the type of responses to +cancellation requests for the calling thread: asynchronous (immediate) +or deferred. The @var{type} argument is the new cancellation type: +either @code{PTHREAD_CANCEL_ASYNCHRONOUS} to cancel the calling thread +as soon as the cancellation request is received, or +@code{PTHREAD_CANCEL_DEFERRED} to keep the cancellation request pending +until the next cancellation point. If @var{oldtype} is not @code{NULL}, +the previous cancellation state is stored in the location pointed to by +@var{oldtype}, and can thus be restored later by another call to +@code{pthread_setcanceltype}. + +If the @var{type} argument is not @code{PTHREAD_CANCEL_DEFERRED} or +@code{PTHREAD_CANCEL_ASYNCHRONOUS}, @code{pthread_setcanceltype} fails +and returns @code{EINVAL}. Otherwise it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_testcancel (@var{void}) +@code{pthread_testcancel} does nothing except testing for pending +cancellation and executing it. Its purpose is to introduce explicit +checks for cancellation in long sequences of code that do not call +cancellation point functions otherwise. +@end deftypefun + +@node Cleanup Handlers +@section Cleanup Handlers + +Cleanup handlers are functions that get called when a thread terminates, +either by calling @code{pthread_exit} or because of +cancellation. Cleanup handlers are installed and removed following a +stack-like discipline. + +The purpose of cleanup handlers is to free the resources that a thread +may hold at the time it terminates. In particular, if a thread exits or +is canceled while it owns a locked mutex, the mutex will remain locked +forever and prevent other threads from executing normally. The best way +to avoid this is, just before locking the mutex, to install a cleanup +handler whose effect is to unlock the mutex. Cleanup handlers can be +used similarly to free blocks allocated with @code{malloc} or close file +descriptors on thread termination. + +Here is how to lock a mutex @var{mut} in such a way that it will be +unlocked if the thread is canceled while @var{mut} is locked: + +@smallexample +pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_mutex_unlock(&mut); +pthread_cleanup_pop(0); +@end smallexample + +Equivalently, the last two lines can be replaced by + +@smallexample +pthread_cleanup_pop(1); +@end smallexample + +Notice that the code above is safe only in deferred cancellation mode +(see @code{pthread_setcanceltype}). In asynchronous cancellation mode, a +cancellation can occur between @code{pthread_cleanup_push} and +@code{pthread_mutex_lock}, or between @code{pthread_mutex_unlock} and +@code{pthread_cleanup_pop}, resulting in both cases in the thread trying +to unlock a mutex not locked by the current thread. This is the main +reason why asynchronous cancellation is difficult to use. + +If the code above must also work in asynchronous cancellation mode, +then it must switch to deferred mode for locking and unlocking the +mutex: + +@smallexample +pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); +pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_cleanup_pop(1); +pthread_setcanceltype(oldtype, NULL); +@end smallexample + +The code above can be rewritten in a more compact and efficient way, +using the non-portable functions @code{pthread_cleanup_push_defer_np} +and @code{pthread_cleanup_pop_restore_np}: + +@smallexample +pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_cleanup_pop_restore_np(1); +@end smallexample + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_cleanup_push (void (*@var{routine}) (void *), void *@var{arg}) + +@code{pthread_cleanup_push} installs the @var{routine} function with +argument @var{arg} as a cleanup handler. From this point on to the +matching @code{pthread_cleanup_pop}, the function @var{routine} will be +called with arguments @var{arg} when the thread terminates, either +through @code{pthread_exit} or by cancellation. If several cleanup +handlers are active at that point, they are called in LIFO order: the +most recently installed handler is called first. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_cleanup_pop (int @var{execute}) +@code{pthread_cleanup_pop} removes the most recently installed cleanup +handler. If the @var{execute} argument is not 0, it also executes the +handler, by calling the @var{routine} function with arguments +@var{arg}. If the @var{execute} argument is 0, the handler is only +removed but not executed. +@end deftypefun + +Matching pairs of @code{pthread_cleanup_push} and +@code{pthread_cleanup_pop} must occur in the same function, at the same +level of block nesting. Actually, @code{pthread_cleanup_push} and +@code{pthread_cleanup_pop} are macros, and the expansion of +@code{pthread_cleanup_push} introduces an open brace @code{@{} with the +matching closing brace @code{@}} being introduced by the expansion of the +matching @code{pthread_cleanup_pop}. + +@comment pthread.h +@comment GNU +@deftypefun void pthread_cleanup_push_defer_np (void (*@var{routine}) (void *), void *@var{arg}) +@code{pthread_cleanup_push_defer_np} is a non-portable extension that +combines @code{pthread_cleanup_push} and @code{pthread_setcanceltype}. +It pushes a cleanup handler just as @code{pthread_cleanup_push} does, +but also saves the current cancellation type and sets it to deferred +cancellation. This ensures that the cleanup mechanism is effective even +if the thread was initially in asynchronous cancellation mode. +@end deftypefun + +@comment pthread.h +@comment GNU +@deftypefun void pthread_cleanup_pop_restore_np (int @var{execute}) +@code{pthread_cleanup_pop_restore_np} pops a cleanup handler introduced +by @code{pthread_cleanup_push_defer_np}, and restores the cancellation +type to its value at the time @code{pthread_cleanup_push_defer_np} was +called. +@end deftypefun + +@code{pthread_cleanup_push_defer_np} and +@code{pthread_cleanup_pop_restore_np} must occur in matching pairs, at +the same level of block nesting. + +The sequence + +@smallexample +pthread_cleanup_push_defer_np(routine, arg); +... +pthread_cleanup_pop_restore_np(execute); +@end smallexample + +@noindent +is functionally equivalent to (but more compact and efficient than) + +@smallexample +@{ + int oldtype; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); + pthread_cleanup_push(routine, arg); + ... + pthread_cleanup_pop(execute); + pthread_setcanceltype(oldtype, NULL); +@} +@end smallexample + + +@node Mutexes +@section Mutexes + +A mutex is a MUTual EXclusion device, and is useful for protecting +shared data structures from concurrent modifications, and implementing +critical sections and monitors. + +A mutex has two possible states: unlocked (not owned by any thread), +and locked (owned by one thread). A mutex can never be owned by two +different threads simultaneously. A thread attempting to lock a mutex +that is already locked by another thread is suspended until the owning +thread unlocks the mutex first. + +None of the mutex functions is a cancellation point, not even +@code{pthread_mutex_lock}, in spite of the fact that it can suspend a +thread for arbitrary durations. This way, the status of mutexes at +cancellation points is predictable, allowing cancellation handlers to +unlock precisely those mutexes that need to be unlocked before the +thread stops executing. Consequently, threads using deferred +cancellation should never hold a mutex for extended periods of time. + +It is not safe to call mutex functions from a signal handler. In +particular, calling @code{pthread_mutex_lock} or +@code{pthread_mutex_unlock} from a signal handler may deadlock the +calling thread. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_init (pthread_mutex_t *@var{mutex}, const pthread_mutexattr_t *@var{mutexattr}) + +@code{pthread_mutex_init} initializes the mutex object pointed to by +@var{mutex} according to the mutex attributes specified in @var{mutexattr}. +If @var{mutexattr} is @code{NULL}, default attributes are used instead. + +The LinuxThreads implementation supports only one mutex attribute, +the @var{mutex type}, which is either ``fast'', ``recursive'', or +``error checking''. The type of a mutex determines whether +it can be locked again by a thread that already owns it. +The default type is ``fast''. + +Variables of type @code{pthread_mutex_t} can also be initialized +statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for +timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for +recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} +(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP} +(for error checking mutexes). + +@code{pthread_mutex_init} always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_lock (pthread_mutex_t *mutex)) +@code{pthread_mutex_lock} locks the given mutex. If the mutex is +currently unlocked, it becomes locked and owned by the calling thread, +and @code{pthread_mutex_lock} returns immediately. If the mutex is +already locked by another thread, @code{pthread_mutex_lock} suspends the +calling thread until the mutex is unlocked. + +If the mutex is already locked by the calling thread, the behavior of +@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex +is of the ``fast'' type, the calling thread is suspended. It will +remain suspended forever, because no other thread can unlock the mutex. +If the mutex is of the ``error checking'' type, @code{pthread_mutex_lock} +returns immediately with the error code @code{EDEADLK}. If the mutex is +of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and +returns immediately, recording the number of times the calling thread +has locked the mutex. An equal number of @code{pthread_mutex_unlock} +operations must be performed before the mutex returns to the unlocked +state. +@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_trylock (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_trylock} behaves identically to +@code{pthread_mutex_lock}, except that it does not block the calling +thread if the mutex is already locked by another thread (or by the +calling thread in the case of a ``fast'' mutex). Instead, +@code{pthread_mutex_trylock} returns immediately with the error code +@code{EBUSY}. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) +The @code{pthread_mutex_timedlock} is similar to the +@code{pthread_mutex_lock} function but instead of blocking for in +indefinite time if the mutex is locked by another thread, it returns +when the time specified in @var{abstime} is reached. + +This function can only be used on standard (``timed'') and ``error +checking'' mutexes. It behaves just like @code{pthread_mutex_lock} for +all other types. + +If the mutex is successfully locked, the function returns zero. If the +time specified in @var{abstime} is reached without the mutex being locked, +@code{ETIMEDOUT} is returned. + +This function was introduced in the POSIX.1d revision of the POSIX standard. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_unlock} unlocks the given mutex. The mutex is +assumed to be locked and owned by the calling thread on entrance to +@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type, +@code{pthread_mutex_unlock} always returns it to the unlocked state. If +it is of the ``recursive'' type, it decrements the locking count of the +mutex (number of @code{pthread_mutex_lock} operations performed on it by +the calling thread), and only when this count reaches zero is the mutex +actually unlocked. + +On ``error checking'' mutexes, @code{pthread_mutex_unlock} actually +checks at run-time that the mutex is locked on entrance, and that it was +locked by the same thread that is now calling +@code{pthread_mutex_unlock}. If these conditions are not met, +@code{pthread_mutex_unlock} returns @code{EPERM}, and the mutex remains +unchanged. ``Fast'' and ``recursive'' mutexes perform no such checks, +thus allowing a locked mutex to be unlocked by a thread other than its +owner. This is non-portable behavior and must not be relied upon. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_destroy (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_destroy} destroys a mutex object, freeing the +resources it might hold. The mutex must be unlocked on entrance. In the +LinuxThreads implementation, no resources are associated with mutex +objects, thus @code{pthread_mutex_destroy} actually does nothing except +checking that the mutex is unlocked. + +If the mutex is locked by some thread, @code{pthread_mutex_destroy} +returns @code{EBUSY}. Otherwise it returns 0. +@end deftypefun + +If any of the above functions (except @code{pthread_mutex_init}) +is applied to an uninitialized mutex, they will simply return +@code{EINVAL} and do nothing. + +A shared global variable @var{x} can be protected by a mutex as follows: + +@smallexample +int x; +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +@end smallexample + +All accesses and modifications to @var{x} should be bracketed by calls to +@code{pthread_mutex_lock} and @code{pthread_mutex_unlock} as follows: + +@smallexample +pthread_mutex_lock(&mut); +/* operate on x */ +pthread_mutex_unlock(&mut); +@end smallexample + +Mutex attributes can be specified at mutex creation time, by passing a +mutex attribute object as second argument to @code{pthread_mutex_init}. +Passing @code{NULL} is equivalent to passing a mutex attribute object +with all attributes set to their default values. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_init (pthread_mutexattr_t *@var{attr}) +@code{pthread_mutexattr_init} initializes the mutex attribute object +@var{attr} and fills it with default values for the attributes. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_destroy (pthread_mutexattr_t *@var{attr}) +@code{pthread_mutexattr_destroy} destroys a mutex attribute object, +which must not be reused until it is +reinitialized. @code{pthread_mutexattr_destroy} does nothing in the +LinuxThreads implementation. + +This function always returns 0. +@end deftypefun + +LinuxThreads supports only one mutex attribute: the mutex type, which is +either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes, +@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes, +@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or +@code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes. As +the @code{NP} suffix indicates, this is a non-portable extension to the +POSIX standard and should not be employed in portable programs. + +The mutex type determines what happens if a thread attempts to lock a +mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of +the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling +thread forever. If the mutex is of the ``error checking'' type, +@code{pthread_mutex_lock} returns immediately with the error code +@code{EDEADLK}. If the mutex is of the ``recursive'' type, the call to +@code{pthread_mutex_lock} returns immediately with a success return +code. The number of times the thread owning the mutex has locked it is +recorded in the mutex. The owning thread must call +@code{pthread_mutex_unlock} the same number of times before the mutex +returns to the unlocked state. + +The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}. +@c This doesn't describe how a ``timed'' mutex behaves. FIXME + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type}) +@code{pthread_mutexattr_settype} sets the mutex type attribute in +@var{attr} to the value specified by @var{type}. + +If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP}, +@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or +@code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return +@code{EINVAL} and leave @var{attr} unchanged. + +The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT}, +@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE}, +and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted. + +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type}) +@code{pthread_mutexattr_gettype} retrieves the current value of the +mutex type attribute in @var{attr} and stores it in the location pointed +to by @var{type}. + +This function always returns 0. +@end deftypefun + +@node Condition Variables +@section Condition Variables + +A condition (short for ``condition variable'') is a synchronization +device that allows threads to suspend execution until some predicate on +shared data is satisfied. The basic operations on conditions are: signal +the condition (when the predicate becomes true), and wait for the +condition, suspending the thread execution until another thread signals +the condition. + +A condition variable must always be associated with a mutex, to avoid +the race condition where a thread prepares to wait on a condition +variable and another thread signals the condition just before the first +thread actually waits on it. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_init (pthread_cond_t *@var{cond}, pthread_condattr_t *cond_@var{attr}) + +@code{pthread_cond_init} initializes the condition variable @var{cond}, +using the condition attributes specified in @var{cond_attr}, or default +attributes if @var{cond_attr} is @code{NULL}. The LinuxThreads +implementation supports no attributes for conditions, hence the +@var{cond_attr} parameter is actually ignored. + +Variables of type @code{pthread_cond_t} can also be initialized +statically, using the constant @code{PTHREAD_COND_INITIALIZER}. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_signal (pthread_cond_t *@var{cond}) +@code{pthread_cond_signal} restarts one of the threads that are waiting +on the condition variable @var{cond}. If no threads are waiting on +@var{cond}, nothing happens. If several threads are waiting on +@var{cond}, exactly one is restarted, but it is not specified which. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_broadcast (pthread_cond_t *@var{cond}) +@code{pthread_cond_broadcast} restarts all the threads that are waiting +on the condition variable @var{cond}. Nothing happens if no threads are +waiting on @var{cond}. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_wait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}) +@code{pthread_cond_wait} atomically unlocks the @var{mutex} (as per +@code{pthread_unlock_mutex}) and waits for the condition variable +@var{cond} to be signaled. The thread execution is suspended and does +not consume any CPU time until the condition variable is signaled. The +@var{mutex} must be locked by the calling thread on entrance to +@code{pthread_cond_wait}. Before returning to the calling thread, +@code{pthread_cond_wait} re-acquires @var{mutex} (as per +@code{pthread_lock_mutex}). + +Unlocking the mutex and suspending on the condition variable is done +atomically. Thus, if all threads always acquire the mutex before +signaling the condition, this guarantees that the condition cannot be +signaled (and thus ignored) between the time a thread locks the mutex +and the time it waits on the condition variable. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_timedwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) +@code{pthread_cond_timedwait} atomically unlocks @var{mutex} and waits +on @var{cond}, as @code{pthread_cond_wait} does, but it also bounds the +duration of the wait. If @var{cond} has not been signaled before time +@var{abstime}, the mutex @var{mutex} is re-acquired and +@code{pthread_cond_timedwait} returns the error code @code{ETIMEDOUT}. +The wait can also be interrupted by a signal; in that case +@code{pthread_cond_timedwait} returns @code{EINTR}. + +The @var{abstime} parameter specifies an absolute time, with the same +origin as @code{time} and @code{gettimeofday}: an @var{abstime} of 0 +corresponds to 00:00:00 GMT, January 1, 1970. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_destroy (pthread_cond_t *@var{cond}) +@code{pthread_cond_destroy} destroys the condition variable @var{cond}, +freeing the resources it might hold. If any threads are waiting on the +condition variable, @code{pthread_cond_destroy} leaves @var{cond} +untouched and returns @code{EBUSY}. Otherwise it returns 0, and +@var{cond} must not be used again until it is reinitialized. + +In the LinuxThreads implementation, no resources are associated with +condition variables, so @code{pthread_cond_destroy} actually does +nothing. +@end deftypefun + +@code{pthread_cond_wait} and @code{pthread_cond_timedwait} are +cancellation points. If a thread is canceled while suspended in one of +these functions, the thread immediately resumes execution, relocks the +mutex specified by @var{mutex}, and finally executes the cancellation. +Consequently, cleanup handlers are assured that @var{mutex} is locked +when they are called. + +It is not safe to call the condition variable functions from a signal +handler. In particular, calling @code{pthread_cond_signal} or +@code{pthread_cond_broadcast} from a signal handler may deadlock the +calling thread. + +Consider two shared variables @var{x} and @var{y}, protected by the +mutex @var{mut}, and a condition variable @var{cond} that is to be +signaled whenever @var{x} becomes greater than @var{y}. + +@smallexample +int x,y; +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +@end smallexample + +Waiting until @var{x} is greater than @var{y} is performed as follows: + +@smallexample +pthread_mutex_lock(&mut); +while (x <= y) @{ + pthread_cond_wait(&cond, &mut); +@} +/* operate on x and y */ +pthread_mutex_unlock(&mut); +@end smallexample + +Modifications on @var{x} and @var{y} that may cause @var{x} to become greater than +@var{y} should signal the condition if needed: + +@smallexample +pthread_mutex_lock(&mut); +/* modify x and y */ +if (x > y) pthread_cond_broadcast(&cond); +pthread_mutex_unlock(&mut); +@end smallexample + +If it can be proved that at most one waiting thread needs to be waken +up (for instance, if there are only two threads communicating through +@var{x} and @var{y}), @code{pthread_cond_signal} can be used as a slightly more +efficient alternative to @code{pthread_cond_broadcast}. In doubt, use +@code{pthread_cond_broadcast}. + +To wait for @var{x} to becomes greater than @var{y} with a timeout of 5 +seconds, do: + +@smallexample +struct timeval now; +struct timespec timeout; +int retcode; + +pthread_mutex_lock(&mut); +gettimeofday(&now); +timeout.tv_sec = now.tv_sec + 5; +timeout.tv_nsec = now.tv_usec * 1000; +retcode = 0; +while (x <= y && retcode != ETIMEDOUT) @{ + retcode = pthread_cond_timedwait(&cond, &mut, &timeout); +@} +if (retcode == ETIMEDOUT) @{ + /* timeout occurred */ +@} else @{ + /* operate on x and y */ +@} +pthread_mutex_unlock(&mut); +@end smallexample + +Condition attributes can be specified at condition creation time, by +passing a condition attribute object as second argument to +@code{pthread_cond_init}. Passing @code{NULL} is equivalent to passing +a condition attribute object with all attributes set to their default +values. + +The LinuxThreads implementation supports no attributes for +conditions. The functions on condition attributes are included only for +compliance with the POSIX standard. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_condattr_init (pthread_condattr_t *@var{attr}) +@deftypefunx int pthread_condattr_destroy (pthread_condattr_t *@var{attr}) +@code{pthread_condattr_init} initializes the condition attribute object +@var{attr} and fills it with default values for the attributes. +@code{pthread_condattr_destroy} destroys the condition attribute object +@var{attr}. + +Both functions do nothing in the LinuxThreads implementation. + +@code{pthread_condattr_init} and @code{pthread_condattr_destroy} always +return 0. +@end deftypefun + +@node POSIX Semaphores +@section POSIX Semaphores + +@vindex SEM_VALUE_MAX +Semaphores are counters for resources shared between threads. The +basic operations on semaphores are: increment the counter atomically, +and wait until the counter is non-null and decrement it atomically. + +Semaphores have a maximum value past which they cannot be incremented. +The macro @code{SEM_VALUE_MAX} is defined to be this maximum value. In +the GNU C library, @code{SEM_VALUE_MAX} is equal to @code{INT_MAX} +(@pxref{Range of Type}), but it may be much smaller on other systems. + +The pthreads library implements POSIX 1003.1b semaphores. These should +not be confused with System V semaphores (@code{ipc}, @code{semctl} and +@code{semop}). +@c !!! SysV IPC is not doc'd at all in our manual + +All the semaphore functions and macros are defined in @file{semaphore.h}. + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value}) +@code{sem_init} initializes the semaphore object pointed to by +@var{sem}. The count associated with the semaphore is set initially to +@var{value}. The @var{pshared} argument indicates whether the semaphore +is local to the current process (@var{pshared} is zero) or is to be +shared between several processes (@var{pshared} is not zero). + +On success @code{sem_init} returns 0. On failure it returns -1 and sets +@var{errno} to one of the following values: + +@table @code +@item EINVAL +@var{value} exceeds the maximal counter value @code{SEM_VALUE_MAX} + +@item ENOSYS +@var{pshared} is not zero. LinuxThreads currently does not support +process-shared semaphores. (This will eventually change.) +@end table +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_destroy (sem_t * @var{sem}) +@code{sem_destroy} destroys a semaphore object, freeing the resources it +might hold. If any threads are waiting on the semaphore when +@code{sem_destroy} is called, it fails and sets @var{errno} to +@code{EBUSY}. + +In the LinuxThreads implementation, no resources are associated with +semaphore objects, thus @code{sem_destroy} actually does nothing except +checking that no thread is waiting on the semaphore. This will change +when process-shared semaphores are implemented. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_wait (sem_t * @var{sem}) +@code{sem_wait} suspends the calling thread until the semaphore pointed +to by @var{sem} has non-zero count. It then atomically decreases the +semaphore count. + +@code{sem_wait} is a cancellation point. It always returns 0. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_trywait (sem_t * @var{sem}) +@code{sem_trywait} is a non-blocking variant of @code{sem_wait}. If the +semaphore pointed to by @var{sem} has non-zero count, the count is +atomically decreased and @code{sem_trywait} immediately returns 0. If +the semaphore count is zero, @code{sem_trywait} immediately returns -1 +and sets errno to @code{EAGAIN}. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_post (sem_t * @var{sem}) +@code{sem_post} atomically increases the count of the semaphore pointed to +by @var{sem}. This function never blocks. + +@c !!! This para appears not to agree with the code. +On processors supporting atomic compare-and-swap (Intel 486, Pentium and +later, Alpha, PowerPC, MIPS II, Motorola 68k, Ultrasparc), the +@code{sem_post} function is can safely be called from signal handlers. +This is the only thread synchronization function provided by POSIX +threads that is async-signal safe. On the Intel 386 and earlier Sparc +chips, the current LinuxThreads implementation of @code{sem_post} is not +async-signal safe, because the hardware does not support the required +atomic operations. + +@code{sem_post} always succeeds and returns 0, unless the semaphore +count would exceed @code{SEM_VALUE_MAX} after being incremented. In +that case @code{sem_post} returns -1 and sets @var{errno} to +@code{EINVAL}. The semaphore count is left unchanged. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_getvalue (sem_t * @var{sem}, int * @var{sval}) +@code{sem_getvalue} stores in the location pointed to by @var{sval} the +current count of the semaphore @var{sem}. It always returns 0. +@end deftypefun + +@node Thread-Specific Data +@section Thread-Specific Data + +Programs often need global or static variables that have different +values in different threads. Since threads share one memory space, this +cannot be achieved with regular variables. Thread-specific data is the +POSIX threads answer to this need. + +Each thread possesses a private memory block, the thread-specific data +area, or TSD area for short. This area is indexed by TSD keys. The TSD +area associates values of type @code{void *} to TSD keys. TSD keys are +common to all threads, but the value associated with a given TSD key can +be different in each thread. + +For concreteness, the TSD areas can be viewed as arrays of @code{void *} +pointers, TSD keys as integer indices into these arrays, and the value +of a TSD key as the value of the corresponding array element in the +calling thread. + +When a thread is created, its TSD area initially associates @code{NULL} +with all keys. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*destr_function) (void *)) +@code{pthread_key_create} allocates a new TSD key. The key is stored in +the location pointed to by @var{key}. There is a limit of +@code{PTHREAD_KEYS_MAX} on the number of keys allocated at a given +time. The value initially associated with the returned key is +@code{NULL} in all currently executing threads. + +The @var{destr_function} argument, if not @code{NULL}, specifies a +destructor function associated with the key. When a thread terminates +via @code{pthread_exit} or by cancellation, @var{destr_function} is +called on the value associated with the key in that thread. The +@var{destr_function} is not called if a key is deleted with +@code{pthread_key_delete} or a value is changed with +@code{pthread_setspecific}. The order in which destructor functions are +called at thread termination time is unspecified. + +Before the destructor function is called, the @code{NULL} value is +associated with the key in the current thread. A destructor function +might, however, re-associate non-@code{NULL} values to that key or some +other key. To deal with this, if after all the destructors have been +called for all non-@code{NULL} values, there are still some +non-@code{NULL} values with associated destructors, then the process is +repeated. The LinuxThreads implementation stops the process after +@code{PTHREAD_DESTRUCTOR_ITERATIONS} iterations, even if some +non-@code{NULL} values with associated descriptors remain. Other +implementations may loop indefinitely. + +@code{pthread_key_create} returns 0 unless @code{PTHREAD_KEYS_MAX} keys +have already been allocated, in which case it fails and returns +@code{EAGAIN}. +@end deftypefun + + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_key_delete (pthread_key_t @var{key}) +@code{pthread_key_delete} deallocates a TSD key. It does not check +whether non-@code{NULL} values are associated with that key in the +currently executing threads, nor call the destructor function associated +with the key. + +If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise +it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{pointer}) +@code{pthread_setspecific} changes the value associated with @var{key} +in the calling thread, storing the given @var{pointer} instead. + +If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise +it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun {void *} pthread_getspecific (pthread_key_t @var{key}) +@code{pthread_getspecific} returns the value currently associated with +@var{key} in the calling thread. + +If there is no such key @var{key}, it returns @code{NULL}. +@end deftypefun + +The following code fragment allocates a thread-specific array of 100 +characters, with automatic reclaimation at thread exit: + +@smallexample +/* Key for the thread-specific buffer */ +static pthread_key_t buffer_key; + +/* Once-only initialisation of the key */ +static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT; + +/* Allocate the thread-specific buffer */ +void buffer_alloc(void) +@{ + pthread_once(&buffer_key_once, buffer_key_alloc); + pthread_setspecific(buffer_key, malloc(100)); +@} + +/* Return the thread-specific buffer */ +char * get_buffer(void) +@{ + return (char *) pthread_getspecific(buffer_key); +@} + +/* Allocate the key */ +static void buffer_key_alloc() +@{ + pthread_key_create(&buffer_key, buffer_destroy); +@} + +/* Free the thread-specific buffer */ +static void buffer_destroy(void * buf) +@{ + free(buf); +@} +@end smallexample + +@node Threads and Signal Handling +@section Threads and Signal Handling + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_sigmask (int @var{how}, const sigset_t *@var{newmask}, sigset_t *@var{oldmask}) +@code{pthread_sigmask} changes the signal mask for the calling thread as +described by the @var{how} and @var{newmask} arguments. If @var{oldmask} +is not @code{NULL}, the previous signal mask is stored in the location +pointed to by @var{oldmask}. + +The meaning of the @var{how} and @var{newmask} arguments is the same as +for @code{sigprocmask}. If @var{how} is @code{SIG_SETMASK}, the signal +mask is set to @var{newmask}. If @var{how} is @code{SIG_BLOCK}, the +signals specified to @var{newmask} are added to the current signal mask. +If @var{how} is @code{SIG_UNBLOCK}, the signals specified to +@var{newmask} are removed from the current signal mask. + +Recall that signal masks are set on a per-thread basis, but signal +actions and signal handlers, as set with @code{sigaction}, are shared +between all threads. + +The @code{pthread_sigmask} function returns 0 on success, and one of the +following error codes on error: +@table @code +@item EINVAL +@var{how} is not one of @code{SIG_SETMASK}, @code{SIG_BLOCK}, or @code{SIG_UNBLOCK} + +@item EFAULT +@var{newmask} or @var{oldmask} point to invalid addresses +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_kill (pthread_t @var{thread}, int @var{signo}) +@code{pthread_kill} sends signal number @var{signo} to the thread +@var{thread}. The signal is delivered and handled as described in +@ref{Signal Handling}. + +@code{pthread_kill} returns 0 on success, one of the following error codes +on error: +@table @code +@item EINVAL +@var{signo} is not a valid signal number + +@item ESRCH +The thread @var{thread} does not exist (e.g. it has already terminated) +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int sigwait (const sigset_t *@var{set}, int *@var{sig}) +@code{sigwait} suspends the calling thread until one of the signals in +@var{set} is delivered to the calling thread. It then stores the number +of the signal received in the location pointed to by @var{sig} and +returns. The signals in @var{set} must be blocked and not ignored on +entrance to @code{sigwait}. If the delivered signal has a signal handler +function attached, that function is @emph{not} called. + +@code{sigwait} is a cancellation point. It always returns 0. +@end deftypefun + +For @code{sigwait} to work reliably, the signals being waited for must be +blocked in all threads, not only in the calling thread, since +otherwise the POSIX semantics for signal delivery do not guarantee +that it's the thread doing the @code{sigwait} that will receive the signal. +The best way to achieve this is block those signals before any threads +are created, and never unblock them in the program other than by +calling @code{sigwait}. + +Signal handling in LinuxThreads departs significantly from the POSIX +standard. According to the standard, ``asynchronous'' (external) signals +are addressed to the whole process (the collection of all threads), +which then delivers them to one particular thread. The thread that +actually receives the signal is any thread that does not currently block +the signal. + +In LinuxThreads, each thread is actually a kernel process with its own +PID, so external signals are always directed to one particular thread. +If, for instance, another thread is blocked in @code{sigwait} on that +signal, it will not be restarted. + +The LinuxThreads implementation of @code{sigwait} installs dummy signal +handlers for the signals in @var{set} for the duration of the +wait. Since signal handlers are shared between all threads, other +threads must not attach their own signal handlers to these signals, or +alternatively they should all block these signals (which is recommended +anyway). + +@node Threads and Fork +@section Threads and Fork + +It's not intuitively obvious what should happen when a multi-threaded POSIX +process calls @code{fork}. Not only are the semantics tricky, but you may +need to write code that does the right thing at fork time even if that code +doesn't use the @code{fork} function. Moreover, you need to be aware of +interaction between @code{fork} and some library features like +@code{pthread_once} and stdio streams. + +When @code{fork} is called by one of the threads of a process, it creates a new +process which is copy of the calling process. Effectively, in addition to +copying certain system objects, the function takes a snapshot of the memory +areas of the parent process, and creates identical areas in the child. +To make matters more complicated, with threads it's possible for two or more +threads to concurrently call fork to create two or more child processes. + +The child process has a copy of the address space of the parent, but it does +not inherit any of its threads. Execution of the child process is carried out +by a new thread which returns from @code{fork} function with a return value of +zero; it is the only thread in the child process. Because threads are not +inherited across fork, issues arise. At the time of the call to @code{fork}, +threads in the parent process other than the one calling @code{fork} may have +been executing critical regions of code. As a result, the child process may +get a copy of objects that are not in a well-defined state. This potential +problem affects all components of the program. + +Any program component which will continue being used in a child process must +correctly handle its state during @code{fork}. For this purpose, the POSIX +interface provides the special function @code{pthread_atfork} for installing +pointers to handler functions which are called from within @code{fork}. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void)) + +@code{pthread_atfork} registers handler functions to be called just +before and just after a new process is created with @code{fork}. The +@var{prepare} handler will be called from the parent process, just +before the new process is created. The @var{parent} handler will be +called from the parent process, just before @code{fork} returns. The +@var{child} handler will be called from the child process, just before +@code{fork} returns. + +@code{pthread_atfork} returns 0 on success and a non-zero error code on +error. + +One or more of the three handlers @var{prepare}, @var{parent} and +@var{child} can be given as @code{NULL}, meaning that no handler needs +to be called at the corresponding point. + +@code{pthread_atfork} can be called several times to install several +sets of handlers. At @code{fork} time, the @var{prepare} handlers are +called in LIFO order (last added with @code{pthread_atfork}, first +called before @code{fork}), while the @var{parent} and @var{child} +handlers are called in FIFO order (first added, first called). + +If there is insufficient memory available to register the handlers, +@code{pthread_atfork} fails and returns @code{ENOMEM}. Otherwise it +returns 0. + +The functions @code{fork} and @code{pthread_atfork} must not be regarded as +reentrant from the context of the handlers. That is to say, if a +@code{pthread_atfork} handler invoked from within @code{fork} calls +@code{pthread_atfork} or @code{fork}, the behavior is undefined. + +Registering a triplet of handlers is an atomic operation with respect to fork. +If new handlers are registered at about the same time as a fork occurs, either +all three handlers will be called, or none of them will be called. + +The handlers are inherited by the child process, and there is no +way to remove them, short of using @code{exec} to load a new +pocess image. + +@end deftypefun + +To understand the purpose of @code{pthread_atfork}, recall that +@code{fork} duplicates the whole memory space, including mutexes in +their current locking state, but only the calling thread: other threads +are not running in the child process. The mutexes are not usable after +the @code{fork} and must be initialized with @code{pthread_mutex_init} +in the child process. This is a limitation of the current +implementation and might or might not be present in future versions. + +To avoid this, install handlers with @code{pthread_atfork} as follows: have the +@var{prepare} handler lock the mutexes (in locking order), and the +@var{parent} handler unlock the mutexes. The @var{child} handler should reset +the mutexes using @code{pthread_mutex_init}, as well as any other +synchronization objects such as condition variables. + +Locking the global mutexes before the fork ensures that all other threads are +locked out of the critical regions of code protected by those mutexes. Thus +when @code{fork} takes a snapshot of the parent's address space, that snapshot +will copy valid, stable data. Resetting the synchronization objects in the +child process will ensure they are properly cleansed of any artifacts from the +threading subsystem of the parent process. For example, a mutex may inherit +a wait queue of threads waiting for the lock; this wait queue makes no sense +in the child process. Initializing the mutex takes care of this. + +@node Streams and Fork +@section Streams and Fork + +The GNU standard I/O library has an internal mutex which guards the internal +linked list of all standard C FILE objects. This mutex is properly taken care +of during @code{fork} so that the child receives an intact copy of the list. +This allows the @code{fopen} function, and related stream-creating functions, +to work correctly in the child process, since these functions need to insert +into the list. + +However, the individual stream locks are not completely taken care of. Thus +unless the multithreaded application takes special precautions in its use of +@code{fork}, the child process might not be able to safely use the streams that +it inherited from the parent. In general, for any given open stream in the +parent that is to be used by the child process, the application must ensure +that that stream is not in use by another thread when @code{fork} is called. +Otherwise an inconsistent copy of the stream object be produced. An easy way to +ensure this is to use @code{flockfile} to lock the stream prior to calling +@code{fork} and then unlock it with @code{funlockfile} inside the parent +process, provided that the parent's threads properly honor these locks. +Nothing special needs to be done in the child process, since the library +internally resets all stream locks. + +Note that the stream locks are not shared between the parent and child. +For example, even if you ensure that, say, the stream @code{stdout} is properly +treated and can be safely used in the child, the stream locks do not provide +an exclusion mechanism between the parent and child. If both processes write +to @code{stdout}, strangely interleaved output may result regardless of +the explicit use of @code{flockfile} or implicit locks. + +Also note that these provisions are a GNU extension; other systems might not +provide any way for streams to be used in the child of a multithreaded process. +POSIX requires that such a child process confines itself to calling only +asynchronous safe functions, which excludes much of the library, including +standard I/O. + +@node Miscellaneous Thread Functions +@section Miscellaneous Thread Functions + +@comment pthread.h +@comment POSIX +@deftypefun {pthread_t} pthread_self (@var{void}) +@code{pthread_self} returns the thread identifier for the calling thread. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2) +@code{pthread_equal} determines if two thread identifiers refer to the same +thread. + +A non-zero value is returned if @var{thread1} and @var{thread2} refer to +the same thread. Otherwise, 0 is returned. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_detach (pthread_t @var{th}) +@code{pthread_detach} puts the thread @var{th} in the detached +state. This guarantees that the memory resources consumed by @var{th} +will be freed immediately when @var{th} terminates. However, this +prevents other threads from synchronizing on the termination of @var{th} +using @code{pthread_join}. + +A thread can be created initially in the detached state, using the +@code{detachstate} attribute to @code{pthread_create}. In contrast, +@code{pthread_detach} applies to threads created in the joinable state, +and which need to be put in the detached state later. + +After @code{pthread_detach} completes, subsequent attempts to perform +@code{pthread_join} on @var{th} will fail. If another thread is already +joining the thread @var{th} at the time @code{pthread_detach} is called, +@code{pthread_detach} does nothing and leaves @var{th} in the joinable +state. + +On success, 0 is returned. On error, one of the following codes is +returned: +@table @code +@item ESRCH +No thread could be found corresponding to that specified by @var{th} +@item EINVAL +The thread @var{th} is already in the detached state +@end table +@end deftypefun + +@comment pthread.h +@comment GNU +@deftypefun void pthread_kill_other_threads_np (@var{void}) +@code{pthread_kill_other_threads_np} is a non-portable LinuxThreads extension. +It causes all threads in the program to terminate immediately, except +the calling thread which proceeds normally. It is intended to be +called just before a thread calls one of the @code{exec} functions, +e.g. @code{execve}. + +Termination of the other threads is not performed through +@code{pthread_cancel} and completely bypasses the cancellation +mechanism. Hence, the current settings for cancellation state and +cancellation type are ignored, and the cleanup handlers are not +executed in the terminated threads. + +According to POSIX 1003.1c, a successful @code{exec*} in one of the +threads should automatically terminate all other threads in the program. +This behavior is not yet implemented in LinuxThreads. Calling +@code{pthread_kill_other_threads_np} before @code{exec*} achieves much +of the same behavior, except that if @code{exec*} ultimately fails, then +all other threads are already killed. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_once (pthread_once_t *once_@var{control}, void (*@var{init_routine}) (void)) + +The purpose of @code{pthread_once} is to ensure that a piece of +initialization code is executed at most once. The @var{once_control} +argument points to a static or extern variable statically initialized +to @code{PTHREAD_ONCE_INIT}. + +The first time @code{pthread_once} is called with a given +@var{once_control} argument, it calls @var{init_routine} with no +argument and changes the value of the @var{once_control} variable to +record that initialization has been performed. Subsequent calls to +@code{pthread_once} with the same @code{once_control} argument do +nothing. + +If a thread is cancelled while executing @var{init_routine} +the state of the @var{once_control} variable is reset so that +a future call to @code{pthread_once} will call the routine again. + +If the process forks while one or more threads are executing +@code{pthread_once} initialization routines, the states of their respective +@var{once_control} variables will appear to be reset in the child process so +that if the child calls @code{pthread_once}, the routines will be executed. + +@code{pthread_once} always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setschedparam (pthread_t target_@var{thread}, int @var{policy}, const struct sched_param *@var{param}) + +@code{pthread_setschedparam} sets the scheduling parameters for the +thread @var{target_thread} as indicated by @var{policy} and +@var{param}. @var{policy} can be either @code{SCHED_OTHER} (regular, +non-realtime scheduling), @code{SCHED_RR} (realtime, round-robin) or +@code{SCHED_FIFO} (realtime, first-in first-out). @var{param} specifies +the scheduling priority for the two realtime policies. See +@code{sched_setpolicy} for more information on scheduling policies. + +The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} +are available only to processes with superuser privileges. + +On success, @code{pthread_setschedparam} returns 0. On error it returns +one of the following codes: +@table @code +@item EINVAL +@var{policy} is not one of @code{SCHED_OTHER}, @code{SCHED_RR}, +@code{SCHED_FIFO}, or the priority value specified by @var{param} is not +valid for the specified policy + +@item EPERM +Realtime scheduling was requested but the calling process does not have +sufficient privileges. + +@item ESRCH +The @var{target_thread} is invalid or has already terminated + +@item EFAULT +@var{param} points outside the process memory space +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_getschedparam (pthread_t target_@var{thread}, int *@var{policy}, struct sched_param *@var{param}) + +@code{pthread_getschedparam} retrieves the scheduling policy and +scheduling parameters for the thread @var{target_thread} and stores them +in the locations pointed to by @var{policy} and @var{param}, +respectively. + +@code{pthread_getschedparam} returns 0 on success, or one of the +following error codes on failure: +@table @code +@item ESRCH +The @var{target_thread} is invalid or has already terminated. + +@item EFAULT +@var{policy} or @var{param} point outside the process memory space. + +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setconcurrency (int @var{level}) +@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack +of a mapping of user threads to kernel threads. It exists for source +compatibility. It does store the value @var{level} so that it can be +returned by a subsequent call to @code{pthread_getconcurrency}. It takes +no other action however. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_getconcurrency () +@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack +of a mapping of user threads to kernel threads. It exists for source +compatibility. However, it will return the value that was set by the +last call to @code{pthread_setconcurrency}. +@end deftypefun diff --git a/libpthread/linuxthreads.old/locale.c b/libpthread/linuxthreads.old/locale.c new file mode 100644 index 0000000..c0879d0 --- /dev/null +++ b/libpthread/linuxthreads.old/locale.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "pthread.h" +#include "internals.h" +#include +#include +#include + +extern struct _pthread_descr_struct __pthread_initial_thread; + +__locale_t __curlocale(void) +{ + pthread_descr self = thread_self(); + +#ifdef NDEBUG + return THREAD_GETMEM (self, locale); +#else + { + __locale_t r = THREAD_GETMEM (self, locale); + + assert(r); + + return r; + } +#endif +} + +__locale_t __curlocale_set(__locale_t newloc) +{ + __locale_t oldloc; + pthread_descr self = thread_self(); + + oldloc = THREAD_GETMEM (self, locale); + + assert(newloc != LC_GLOBAL_LOCALE); + assert(oldloc); + + THREAD_SETMEM (self, locale, newloc); + + return oldloc; +} diff --git a/libpthread/linuxthreads.old/lockfile.c b/libpthread/linuxthreads.old/lockfile.c new file mode 100644 index 0000000..d054b62 --- /dev/null +++ b/libpthread/linuxthreads.old/lockfile.c @@ -0,0 +1,43 @@ +/* lockfile - Handle locking and unlocking of stream. + Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +extern __typeof(pthread_mutexattr_init) __pthread_mutexattr_init attribute_hidden; +extern __typeof(pthread_mutexattr_settype) __pthread_mutexattr_settype attribute_hidden; +extern __typeof(pthread_mutexattr_destroy) __pthread_mutexattr_destroy attribute_hidden; + +/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both + * libc and libpthread. In uClibc, they are now in libc only. */ + +void __fresetlockfiles (void); +void __fresetlockfiles (void) +{ + FILE *fp; + pthread_mutexattr_t attr; + + __pthread_mutexattr_init(&attr); + __pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + __pthread_mutex_init(&fp->__lock, &attr); + + __pthread_mutexattr_destroy(&attr); +} diff --git a/libpthread/linuxthreads.old/manager.c b/libpthread/linuxthreads.old/manager.c new file mode 100644 index 0000000..69fdd1c --- /dev/null +++ b/libpthread/linuxthreads.old/manager.c @@ -0,0 +1,928 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "thread manager" thread: manages creation and termination of threads */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for poll */ +#include /* for mmap */ +#include +#include +#include /* for waitpid macros */ + +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "semaphore.h" +#include "debug.h" /* PDEBUG, added by StS */ + + +/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is + * not available, we assume an old Linux kernel is in use and we will + * use select() instead. */ +#include +#ifndef __NR_poll +# define USE_SELECT +#endif + +libpthread_hidden_proto(waitpid) +libpthread_hidden_proto(raise) + +/* Array of active threads. Entry 0 is reserved for the initial thread. */ +struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] = +{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0}, + { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ }; + +/* For debugging purposes put the maximum number of threads in a variable. */ +const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or if all threads have stacks supplied by LinuxThreads (if 0). */ +int __pthread_nonstandard_stacks; + +/* Number of active entries in __pthread_handles (used by gdb) */ +volatile int __pthread_handles_num = 2; + +/* Whether to use debugger additional actions for thread creation + (set to 1 by gdb) */ +volatile int __pthread_threads_debug; + +/* Globally enabled events. */ +volatile td_thr_events_t __pthread_threads_events; + +/* Pointer to thread descriptor with last event. */ +volatile pthread_descr __pthread_last_event; + +/* Mapping from stack segment to thread descriptor. */ +/* Stack segment numbers are also indices into the __pthread_handles array. */ +/* Stack segment number 0 is reserved for the initial thread. */ + +static __inline__ pthread_descr thread_segment(int seg) +{ + return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE) + - 1; +} + +/* Flag set in signal handler to record child termination */ + +static volatile int terminated_children = 0; + +/* Flag set when the initial thread is blocked on pthread_exit waiting + for all other threads to terminate */ + +static int main_thread_exiting = 0; + +/* Counter used to generate unique thread identifier. + Thread identifier is pthread_threads_counter + segment. */ + +static pthread_t pthread_threads_counter = 0; + +/* Forward declarations */ + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t *mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp); +static void pthread_handle_free(pthread_t th_id); +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) attribute_noreturn; +static void pthread_reap_children(void); +static void pthread_kill_all_threads(int sig, int main_thread_also); + +/* The server thread managing requests for thread creation and termination */ + +int attribute_noreturn __pthread_manager(void *arg) +{ + int reqfd = (int) (long int) arg; +#ifdef USE_SELECT + struct timeval tv; + fd_set fd; +#else + struct pollfd ufd; +#endif + sigset_t manager_mask; + int n; + struct pthread_request request; + + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_manager_thread, 1); +#endif + /* Set the error variable. */ + __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno; + __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno; + +#ifdef __UCLIBC_HAS_XLOCALE__ + /* Initialize thread's locale to the global locale. */ + __pthread_manager_thread.locale = __global_locale; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + /* Block all signals except __pthread_sig_cancel and SIGTRAP */ + sigfillset(&manager_mask); + sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ + sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + sigdelset(&manager_mask, __pthread_sig_debug); + sigprocmask(SIG_SETMASK, &manager_mask, NULL); + /* Raise our priority to match that of main thread */ + __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); + /* Synchronize debugging of the thread manager */ + n = TEMP_FAILURE_RETRY(__libc_read(reqfd, (char *)&request, + sizeof(request))); +#ifndef USE_SELECT + ufd.fd = reqfd; + ufd.events = POLLIN; +#endif + /* Enter server loop */ + while(1) { +#ifdef USE_SELECT + tv.tv_sec = 2; + tv.tv_usec = 0; + FD_ZERO (&fd); + FD_SET (reqfd, &fd); + n = select (reqfd + 1, &fd, NULL, NULL, &tv); +#else + PDEBUG("before poll\n"); + n = poll(&ufd, 1, 2000); + PDEBUG("after poll\n"); +#endif + /* Check for termination of the main thread */ + if (getppid() == 1) { + pthread_kill_all_threads(SIGKILL, 0); + _exit(0); + } + /* Check for dead children */ + if (terminated_children) { + terminated_children = 0; + pthread_reap_children(); + } + /* Read and execute request */ +#ifdef USE_SELECT + if (n == 1) +#else + if (n == 1 && (ufd.revents & POLLIN)) +#endif + { + + PDEBUG("before __libc_read\n"); + n = __libc_read(reqfd, (char *)&request, sizeof(request)); + PDEBUG("after __libc_read, n=%d\n", n); + switch(request.req_kind) { + case REQ_CREATE: + PDEBUG("got REQ_CREATE\n"); + request.req_thread->p_retcode = + pthread_handle_create((pthread_t *) &request.req_thread->p_retval, + request.req_args.create.attr, + request.req_args.create.fn, + request.req_args.create.arg, + &request.req_args.create.mask, + request.req_thread->p_pid, + request.req_thread->p_report_events, + &request.req_thread->p_eventbuf.eventmask); + PDEBUG("restarting %d\n", request.req_thread); + restart(request.req_thread); + break; + case REQ_FREE: + PDEBUG("got REQ_FREE\n"); + pthread_handle_free(request.req_args.free.thread_id); + break; + case REQ_PROCESS_EXIT: + PDEBUG("got REQ_PROCESS_EXIT from %d, exit code = %d\n", + request.req_thread, request.req_args.exit.code); + pthread_handle_exit(request.req_thread, + request.req_args.exit.code); + break; + case REQ_MAIN_THREAD_EXIT: + PDEBUG("got REQ_MAIN_THREAD_EXIT\n"); + main_thread_exiting = 1; + /* Reap children in case all other threads died and the signal handler + went off before we set main_thread_exiting to 1, and therefore did + not do REQ_KICK. */ + pthread_reap_children(); + + if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* The main thread will now call exit() which will trigger an + __on_exit handler, which in turn will send REQ_PROCESS_EXIT + to the thread manager. In case you are wondering how the + manager terminates from its loop here. */ + } + break; + case REQ_POST: + PDEBUG("got REQ_POST\n"); + __new_sem_post(request.req_args.post); + break; + case REQ_DEBUG: + PDEBUG("got REQ_DEBUG\n"); + /* Make gdb aware of new thread and gdb will restart the + new thread when it is ready to handle the new thread. */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + PDEBUG("about to call raise(__pthread_sig_debug)\n"); + raise(__pthread_sig_debug); + } + case REQ_KICK: + /* This is just a prod to get the manager to reap some + threads right away, avoiding a potential delay at shutdown. */ + break; + } + } + } +} + +int __pthread_manager_event(void *arg) +{ + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_manager_thread, 1); +#endif + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock)); + + return __pthread_manager(arg); +} + +/* Process creation */ +static int +attribute_noreturn +pthread_start_thread(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + struct pthread_request request; + void * outcome; + /* Initialize special thread_self processing, if any. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + PDEBUG("\n"); + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Initial signal mask is that of the creating thread. (Otherwise, + we'd just inherit the mask of the thread manager.) */ + sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); + /* Set the scheduling policy and priority for the new thread, if needed */ + if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) + /* Explicit scheduling attributes were provided: apply them */ + sched_setscheduler(THREAD_GETMEM(self, p_pid), + THREAD_GETMEM(self, p_start_args.schedpolicy), + &self->p_start_args.schedparam); + else if (__pthread_manager_thread.p_priority > 0) + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + { + struct sched_param default_params; + default_params.sched_priority = 0; + sched_setscheduler(THREAD_GETMEM(self, p_pid), + SCHED_OTHER, &default_params); + } + /* Make gdb aware of new thread */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + request.req_thread = self; + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + /* Run the thread code */ + outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, + p_start_args.arg)); + /* Exit with the given return value */ + __pthread_do_exit(outcome, CURRENT_STACK_FRAME); +} + +static int +attribute_noreturn +pthread_start_thread_event(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + pthread_start_thread (arg); +} + +static int pthread_allocate_stack(const pthread_attr_t *attr, + pthread_descr default_new_thread, + int pagesize, + pthread_descr * out_new_thread, + char ** out_new_thread_bottom, + char ** out_guardaddr, + size_t * out_guardsize) +{ + pthread_descr new_thread; + char * new_thread_bottom; + char * guardaddr; + size_t stacksize, guardsize; + + if (attr != NULL && attr->__stackaddr_set) + { + /* The user provided a stack. */ + new_thread = + (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; + new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; + guardaddr = NULL; + guardsize = 0; + __pthread_nonstandard_stacks = 1; +#ifndef __ARCH_USE_MMU__ + /* check the initial thread stack boundaries so they don't overlap */ + NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); + + PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, + __pthread_initial_thread_tos); +#endif + } + else + { +#ifdef __ARCH_USE_MMU__ + stacksize = STACK_SIZE - pagesize; + if (attr != NULL) + stacksize = MIN (stacksize, roundup(attr->__stacksize, pagesize)); + /* Allocate space for stack and thread descriptor at default address */ + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize; + if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE), + INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, + -1, 0) == MAP_FAILED) + /* Bad luck, this segment is already mapped. */ + return -1; + /* We manage to get a stack. Now see whether we need a guard + and allocate it if necessary. Notice that the default + attributes (stack_size = STACK_SIZE - pagesize) do not need + a guard page, since the RLIMIT_STACK soft limit prevents stacks + from running into one another. */ + if (stacksize == (size_t) (STACK_SIZE - pagesize)) + { + /* We don't need a guard page. */ + guardaddr = NULL; + guardsize = 0; + } + else + { + /* Put a bad page at the bottom of the stack */ + guardsize = attr->__guardsize; + guardaddr = (void *)new_thread_bottom - guardsize; + if (mmap ((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0) + == MAP_FAILED) + { + /* We don't make this an error. */ + guardaddr = NULL; + guardsize = 0; + } + } +#else + /* We cannot mmap to this huge chunk of stack space when we don't have + * an MMU. Pretend we are using a user provided stack even if there was + * none provided by the user. Thus, we get around the mmap and reservation + * of a huge stack segment. -StS */ + + stacksize = INITIAL_STACK_SIZE; + /* The user may want to use a non-default stacksize */ + if (attr != NULL) + { + stacksize = attr->__stacksize; + } + + /* malloc a stack - memory from the bottom up */ + if ((new_thread_bottom = malloc(stacksize)) == NULL) + { + /* bad luck, we cannot malloc any more */ + return -1 ; + } + PDEBUG("malloced chunk: base=%p, size=0x%04x\n", new_thread_bottom, stacksize); + + /* Set up the pointers. new_thread marks the TOP of the stack frame and + * the address of the pthread_descr struct at the same time. Therefore we + * must account for its size and fit it in the malloc()'ed block. The + * value of `new_thread' is then passed to clone() as the stack argument. + * + * ^ +------------------------+ + * | | pthread_descr struct | + * | +------------------------+ <- new_thread + * malloc block | | | + * | | thread stack | + * | | | + * v +------------------------+ <- new_thread_bottom + * + * Note: The calculated value of new_thread must be word aligned otherwise + * the kernel chokes on a non-aligned stack frame. Choose the lower + * available word boundary. + */ + new_thread = ((pthread_descr) ((int)(new_thread_bottom + stacksize) & -sizeof(void*))) - 1; + guardaddr = NULL; + guardsize = 0; + + PDEBUG("thread stack: bos=%p, tos=%p\n", new_thread_bottom, new_thread); + + /* check the initial thread stack boundaries so they don't overlap */ + NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); + + PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, + __pthread_initial_thread_tos); + + /* on non-MMU systems we always have non-standard stack frames */ + __pthread_nonstandard_stacks = 1; + +#endif /* __ARCH_USE_MMU__ */ + } + + /* Clear the thread data structure. */ + memset (new_thread, '\0', sizeof (*new_thread)); + *out_new_thread = new_thread; + *out_new_thread_bottom = new_thread_bottom; + *out_guardaddr = guardaddr; + *out_guardsize = guardsize; + return 0; +} + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t * mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp) +{ + size_t sseg; + int pid; + pthread_descr new_thread; + char * new_thread_bottom; + pthread_t new_thread_id; + char *guardaddr = NULL; + size_t guardsize = 0; + int pagesize = getpagesize(); + int saved_errno = 0; + + /* First check whether we have to change the policy and if yes, whether + we can do this. Normally this should be done by examining the + return value of the sched_setscheduler call in pthread_start_thread + but this is hard to implement. FIXME */ + if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) + return EPERM; + /* Find a free segment for the thread, and allocate a stack if needed */ + for (sseg = 2; ; sseg++) + { + if (sseg >= PTHREAD_THREADS_MAX) + return EAGAIN; + if (__pthread_handles[sseg].h_descr != NULL) + continue; + if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize, + &new_thread, &new_thread_bottom, + &guardaddr, &guardsize) == 0) + break; +#ifndef __ARCH_USE_MMU__ + else + /* When there is MMU, mmap () is used to allocate the stack. If one + * segment is already mapped, we should continue to see if we can + * use the next one. However, when there is no MMU, malloc () is used. + * It's waste of CPU cycles to continue to try if it fails. */ + return EAGAIN; +#endif + } + __pthread_handles_num++; + /* Allocate new thread identifier */ + pthread_threads_counter += PTHREAD_THREADS_MAX; + new_thread_id = sseg + pthread_threads_counter; + /* Initialize the thread descriptor. Elements which have to be + initialized to zero already have this value. */ + new_thread->p_tid = new_thread_id; + new_thread->p_lock = &(__pthread_handles[sseg].h_lock); + new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; + new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; + new_thread->p_errnop = &new_thread->p_errno; + new_thread->p_h_errnop = &new_thread->p_h_errno; +#ifdef __UCLIBC_HAS_XLOCALE__ + /* Initialize thread's locale to the global locale. */ + new_thread->locale = __global_locale; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + new_thread->p_guardaddr = guardaddr; + new_thread->p_guardsize = guardsize; + new_thread->p_self = new_thread; + new_thread->p_nr = sseg; + /* Initialize the thread handle */ + __pthread_init_lock(&__pthread_handles[sseg].h_lock); + __pthread_handles[sseg].h_descr = new_thread; + __pthread_handles[sseg].h_bottom = new_thread_bottom; + /* Determine scheduling parameters for the thread */ + new_thread->p_start_args.schedpolicy = -1; + if (attr != NULL) { + new_thread->p_detached = attr->__detachstate; + new_thread->p_userstack = attr->__stackaddr_set; + + switch(attr->__inheritsched) { + case PTHREAD_EXPLICIT_SCHED: + new_thread->p_start_args.schedpolicy = attr->__schedpolicy; + memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam, + sizeof (struct sched_param)); + break; + case PTHREAD_INHERIT_SCHED: + new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid); + sched_getparam(father_pid, &new_thread->p_start_args.schedparam); + break; + } + new_thread->p_priority = + new_thread->p_start_args.schedparam.sched_priority; + } + /* Finish setting up arguments to pthread_start_thread */ + new_thread->p_start_args.start_routine = start_routine; + new_thread->p_start_args.arg = arg; + new_thread->p_start_args.mask = *mask; + /* Raise priority of thread manager if needed */ + __pthread_manager_adjust_prio(new_thread->p_priority); + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + pid = 0; /* Note that the thread never can have PID zero. */ + + + /* ******************************************************** */ + /* This code was moved from below to cope with running threads + * on uClinux systems. See comment below... + * Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /* ********************************************************* */ + + if (report_events) + { + /* See whether the TD_CREATE event bit is set in any of the + masks. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | event_maskp->event_bits[idx])) != 0) + { + /* Lock the mutex the child will use now so that it will stop. */ + __pthread_lock(new_thread->p_lock, NULL); + + /* We have to report this event. */ +#ifdef __ia64__ + pid = __clone2(pthread_start_thread_event, (void **) new_thread, + (char *)new_thread - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = clone(pthread_start_thread_event, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif + + saved_errno = errno; + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + new_thread->p_eventbuf.eventdata = new_thread; + new_thread->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = new_thread; + + /* We have to set the PID here since the callback function + in the debug library will need it and we cannot guarantee + the child got scheduled before the debugger. */ + new_thread->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + + /* Now restart the thread. */ + __pthread_unlock(new_thread->p_lock); + } + } + } + if (pid == 0) + { + PDEBUG("cloning new_thread = %p\n", new_thread); +#ifdef __ia64__ + pid = __clone2(pthread_start_thread, (void **) new_thread, + (char *)new_thread - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = clone(pthread_start_thread, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif + saved_errno = errno; + } + /* Check if cloning succeeded */ + if (pid == -1) { + /******************************************************** + * Code inserted to remove the thread from our list of active + * threads in case of failure (needed to cope with uClinux), + * See comment below. */ + new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive; + new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive; + /********************************************************/ + + /* Free the stack if we allocated it */ + if (attr == NULL || !attr->__stackaddr_set) + { +#ifdef __ARCH_USE_MMU__ + if (new_thread->p_guardsize != 0) + munmap(new_thread->p_guardaddr, new_thread->p_guardsize); + munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE), + INITIAL_STACK_SIZE); +#else + free(new_thread_bottom); +#endif /* __ARCH_USE_MMU__ */ + } + __pthread_handles[sseg].h_descr = NULL; + __pthread_handles[sseg].h_bottom = NULL; + __pthread_handles_num--; + return errno; + } + PDEBUG("new thread pid = %d\n", pid); + +#if 0 + /* *********************************************************** + This code has been moved before the call to clone(). In uClinux, + the use of wait on a semaphore is dependant upon that the child so + the child must be in the active threads list. This list is used in + pthread_find_self() to get the pthread_descr of self. So, if the + child calls sem_wait before this code is executed , it will hang + forever and initial_thread will instead be posted by a sem_post + call. */ + + /* Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /************************************************************/ +#endif + + /* Set pid field of the new thread, in case we get there before the + child starts. */ + new_thread->p_pid = pid; + /* We're all set */ + *thread = new_thread_id; + return 0; +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_free(pthread_descr th) +{ + pthread_handle handle; + pthread_readlock_info *iter, *next; + char *h_bottom_save; + + /* Make the handle invalid */ + handle = thread_handle(th->p_tid); + __pthread_lock(&handle->h_lock, NULL); + h_bottom_save = handle->h_bottom; + handle->h_descr = NULL; + handle->h_bottom = (char *)(-1L); + __pthread_unlock(&handle->h_lock); +#ifdef FREE_THREAD_SELF + FREE_THREAD_SELF(th, th->p_nr); +#endif + /* One fewer threads in __pthread_handles */ + __pthread_handles_num--; + + /* Destroy read lock list, and list of free read lock structures. + If the former is not empty, it means the thread exited while + holding read locks! */ + + for (iter = th->p_readlock_list; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + for (iter = th->p_readlock_free; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + /* If initial thread, nothing to free */ + if (th == &__pthread_initial_thread) return; +#ifdef __ARCH_USE_MMU__ + if (!th->p_userstack) + { + /* Free the stack and thread descriptor area */ + if (th->p_guardsize != 0) + munmap(th->p_guardaddr, th->p_guardsize); + munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE); + } +#else + /* For non-MMU systems we always malloc the stack, so free it here. -StS */ + if (!th->p_userstack) { + free(h_bottom_save); + } +#endif /* __ARCH_USE_MMU__ */ +} + +/* Handle threads that have exited */ + +static void pthread_exited(pid_t pid) +{ + pthread_descr th; + int detached; + /* Find thread with that pid */ + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + if (th->p_pid == pid) { + /* Remove thread from list of active threads */ + th->p_nextlive->p_prevlive = th->p_prevlive; + th->p_prevlive->p_nextlive = th->p_nextlive; + /* Mark thread as exited, and if detached, free its resources */ + __pthread_lock(th->p_lock, NULL); + th->p_exited = 1; + /* If we have to signal this event do it now. */ + if (th->p_report_events) + { + /* See whether TD_REAP is in any of the mask. */ + int idx = __td_eventword (TD_REAP); + uint32_t mask = __td_eventmask (TD_REAP); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | th->p_eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the reapage. */ + th->p_eventbuf.eventnum = TD_REAP; + th->p_eventbuf.eventdata = th; + __pthread_last_event = th; + + /* Now call the function to signal the event. */ + __linuxthreads_reap_event(); + } + } + detached = th->p_detached; + __pthread_unlock(th->p_lock); + if (detached) + pthread_free(th); + break; + } + } + /* If all threads have exited and the main thread is pending on a + pthread_exit, wake up the main thread and terminate ourselves. */ + if (main_thread_exiting && + __pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* Same logic as REQ_MAIN_THREAD_EXIT. */ + } +} + +static void pthread_reap_children(void) +{ + pid_t pid; + int status; + PDEBUG("\n"); + + while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) { + pthread_exited(pid); + if (WIFSIGNALED(status)) { + /* If a thread died due to a signal, send the same signal to + all other threads, including the main thread. */ + pthread_kill_all_threads(WTERMSIG(status), 1); + _exit(0); + } + } +} + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_handle_free(pthread_t th_id) +{ + pthread_handle handle = thread_handle(th_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, th_id)) { + /* pthread_reap_children has deallocated the thread already, + nothing needs to be done */ + __pthread_unlock(&handle->h_lock); + return; + } + th = handle->h_descr; + if (th->p_exited) { + __pthread_unlock(&handle->h_lock); + pthread_free(th); + } else { + /* The Unix process of the thread is still running. + Mark the thread as detached so that the thread manager will + deallocate its resources when the Unix process exits. */ + th->p_detached = 1; + __pthread_unlock(&handle->h_lock); + } +} + +/* Send a signal to all running threads */ + +static void pthread_kill_all_threads(int sig, int main_thread_also) +{ + pthread_descr th; + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + kill(th->p_pid, sig); + } + if (main_thread_also) { + kill(__pthread_main_thread->p_pid, sig); + } +} + +/* Process-wide exit() */ + +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) +{ + pthread_descr th; + __pthread_exit_requested = 1; + __pthread_exit_code = exitcode; + /* Send the CANCEL signal to all running threads, including the main + thread, but excluding the thread from which the exit request originated + (that thread must complete the exit, e.g. calling atexit functions + and flushing stdio buffers). */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies + and their times are properly added to the thread manager's times. */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + waitpid(th->p_pid, NULL, __WCLONE); + } + restart(issuing_thread); + _exit(0); +} + +/* Handler for __pthread_sig_cancel in thread manager thread */ + +void __pthread_manager_sighandler(int sig attribute_unused) +{ + int kick_manager = terminated_children == 0 && main_thread_exiting; + terminated_children = 1; + + /* If the main thread is terminating, kick the thread manager loop + each time some threads terminate. This eliminates a two second + shutdown delay caused by the thread manager sleeping in the + call to __poll(). Instead, the thread manager is kicked into + action, reaps the outstanding threads and resumes the main thread + so that it can complete the shutdown. */ + + if (kick_manager) { + struct pthread_request request; + request.req_thread = 0; + request.req_kind = REQ_KICK; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +} + +/* Adjust priority of thread manager so that it always run at a priority + higher than all threads */ + +void __pthread_manager_adjust_prio(int thread_prio) +{ + struct sched_param param; + + if (thread_prio <= __pthread_manager_thread.p_priority) return; + param.sched_priority = + thread_prio < sched_get_priority_max(SCHED_FIFO) + ? thread_prio + 1 : thread_prio; + sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, ¶m); + __pthread_manager_thread.p_priority = thread_prio; +} diff --git a/libpthread/linuxthreads.old/mutex.c b/libpthread/linuxthreads.old/mutex.c new file mode 100644 index 0000000..8908414 --- /dev/null +++ b/libpthread/linuxthreads.old/mutex.c @@ -0,0 +1,362 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Mutexes */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int attribute_hidden __pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + __pthread_init_lock(&mutex->__m_lock); + mutex->__m_kind = + mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; + mutex->__m_count = 0; + mutex->__m_owner = NULL; + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) + +int attribute_hidden __pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + if ((mutex->__m_lock.__status & 1) != 0) + return EBUSY; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + if (mutex->__m_lock.__status != 0) + return EBUSY; + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) + +int attribute_hidden __pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + pthread_descr self; + int retcode; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + retcode = __pthread_trylock(&mutex->__m_lock); + return retcode; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + retcode = __pthread_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = self; + mutex->__m_count = 0; + } + return retcode; + case PTHREAD_MUTEX_ERRORCHECK_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = thread_self(); + } + return retcode; + case PTHREAD_MUTEX_TIMED_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + return retcode; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) + +int attribute_hidden __pthread_mutex_lock(pthread_mutex_t * mutex) +{ + pthread_descr self; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + __pthread_alt_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_lock(&mutex->__m_lock, NULL); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) + +int pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_descr self; + int res; + + if (__builtin_expect (abstime->tv_nsec, 0) < 0 + || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) + return EINVAL; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); + if (res != 0) + { + mutex->__m_owner = self; + return 0; + } + return ETIMEDOUT; + case PTHREAD_MUTEX_TIMED_NP: + /* Only this type supports timed out lock. */ + return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) + ? 0 : ETIMEDOUT); + default: + return EINVAL; + } +} + +int attribute_hidden __pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + if (mutex->__m_owner != thread_self()) + return EPERM; + if (mutex->__m_count > 0) { + mutex->__m_count--; + return 0; + } + mutex->__m_owner = NULL; + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) + return EPERM; + mutex->__m_owner = NULL; + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) + +int attribute_hidden __pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; + return 0; +} +strong_alias(__pthread_mutexattr_init,pthread_mutexattr_init) + +int attribute_hidden __pthread_mutexattr_destroy(pthread_mutexattr_t *attr attribute_unused) +{ + return 0; +} +strong_alias(__pthread_mutexattr_destroy,pthread_mutexattr_destroy) + +int attribute_hidden __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (kind != PTHREAD_MUTEX_ADAPTIVE_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP + && kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_TIMED_NP) + return EINVAL; + attr->__mutexkind = kind; + return 0; +} +strong_alias(__pthread_mutexattr_settype,pthread_mutexattr_settype) +strong_alias (__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) +weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) + +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) attribute_hidden; +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + *kind = attr->__mutexkind; + return 0; +} +weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) +strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) +weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) + +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, + int *pshared) attribute_hidden; +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} +weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) + +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) attribute_hidden; +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} +weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) + +/* Once-only execution */ + +static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; +static int fork_generation = 0; /* Child process increments this after fork. */ + +enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; + +/* If a thread is canceled while calling the init_routine out of + pthread once, this handler will reset the once_control variable + to the NEVER state. */ + +static void pthread_once_cancelhandler(void *arg) +{ + pthread_once_t *once_control = arg; + + __pthread_mutex_lock(&once_masterlock); + *once_control = NEVER; + __pthread_mutex_unlock(&once_masterlock); + pthread_cond_broadcast(&once_finished); +} + +int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) +{ + /* flag for doing the condition broadcast outside of mutex */ + int state_changed; + + /* Test without locking first for speed */ + if (*once_control == DONE) { + READ_MEMORY_BARRIER(); + return 0; + } + /* Lock and test again */ + + state_changed = 0; + + __pthread_mutex_lock(&once_masterlock); + + /* If this object was left in an IN_PROGRESS state in a parent + process (indicated by stale generation field), reset it to NEVER. */ + if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) + *once_control = NEVER; + + /* If init_routine is being called from another routine, wait until + it completes. */ + while ((*once_control & 3) == IN_PROGRESS) { + pthread_cond_wait(&once_finished, &once_masterlock); + } + /* Here *once_control is stable and either NEVER or DONE. */ + if (*once_control == NEVER) { + *once_control = IN_PROGRESS | fork_generation; + __pthread_mutex_unlock(&once_masterlock); + pthread_cleanup_push(pthread_once_cancelhandler, once_control); + init_routine(); + pthread_cleanup_pop(0); + __pthread_mutex_lock(&once_masterlock); + WRITE_MEMORY_BARRIER(); + *once_control = DONE; + state_changed = 1; + } + __pthread_mutex_unlock(&once_masterlock); + + if (state_changed) + pthread_cond_broadcast(&once_finished); + + return 0; +} +strong_alias (__pthread_once, pthread_once) + +/* + * Handle the state of the pthread_once mechanism across forks. The + * once_masterlock is acquired in the parent process prior to a fork to ensure + * that no thread is in the critical region protected by the lock. After the + * fork, the lock is released. In the child, the lock and the condition + * variable are simply reset. The child also increments its generation + * counter which lets pthread_once calls detect stale IN_PROGRESS states + * and reset them back to NEVER. + */ + +void __pthread_once_fork_prepare(void); +void __pthread_once_fork_prepare(void) +{ + __pthread_mutex_lock(&once_masterlock); +} + +void __pthread_once_fork_parent(void); +void __pthread_once_fork_parent(void) +{ + __pthread_mutex_unlock(&once_masterlock); +} + +void __pthread_once_fork_child(void); +void __pthread_once_fork_child(void) +{ + __pthread_mutex_init(&once_masterlock, NULL); + pthread_cond_init(&once_finished, NULL); + if (fork_generation <= INT_MAX - 4) + fork_generation += 4; /* leave least significant two bits zero */ + else + fork_generation = 0; +} diff --git a/libpthread/linuxthreads.old/oldsemaphore.c b/libpthread/linuxthreads.old/oldsemaphore.c new file mode 100644 index 0000000..2a7b40a --- /dev/null +++ b/libpthread/linuxthreads.old/oldsemaphore.c @@ -0,0 +1,241 @@ +/* + * This file contains the old semaphore code that we need to + * preserve for glibc-2.0 backwards compatibility. Port to glibc 2.1 + * done by Cristian Gafton. + */ + +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" + +typedef struct { + long int sem_status; + int sem_spinlock; +} old_sem_t; + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) + +static __inline__ int sem_compare_and_swap(old_sem_t *sem, long oldval, long newval) +{ + return compare_and_swap(&sem->sem_status, oldval, newval, &sem->sem_spinlock); +} + +/* The state of a semaphore is represented by a long int encoding + either the semaphore count if >= 0 and no thread is waiting on it, + or the head of the list of threads waiting for the semaphore. + To distinguish the two cases, we encode the semaphore count N + as 2N+1, so that it has the lowest bit set. + + A sequence of sem_wait operations on a semaphore initialized to N + result in the following successive states: + 2N+1, 2N-1, ..., 3, 1, &first_waiting_thread, &second_waiting_thread, ... +*/ + +static void sem_restart_list(pthread_descr waiting); + +int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value); +int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + sem->sem_spinlock = 0; + sem->sem_status = ((long)value << 1) + 1; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside __old_sem_wait. Here we simply unconditionally + indicate that the thread is to be woken, by returning 1. */ + +static int old_sem_extricate_func(void *obj attribute_unused, pthread_descr th attribute_unused) +{ + return 1; +} + +int __old_sem_wait(old_sem_t * sem); +int __old_sem_wait(old_sem_t * sem) +{ + long oldstatus, newstatus; + volatile pthread_descr self = thread_self(); + pthread_descr * th; + pthread_extricate_if extr; + + /* Set up extrication interface */ + extr.pu_object = 0; + extr.pu_extricate_func = old_sem_extricate_func; + + while (1) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) && (oldstatus != 1)) + newstatus = oldstatus - 2; + else { + newstatus = (long) self; + self->p_nextwaiting = (pthread_descr) oldstatus; + } + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + if (newstatus & 1) { + /* We got the semaphore. */ + __pthread_set_own_extricate_if(self, 0); + return 0; + } + /* Wait for sem_post or cancellation */ + suspend(self); + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) { + /* Remove ourselves from the waiting list if we're still on it */ + /* First check if we're at the head of the list. */ + do { + oldstatus = sem->sem_status; + if (oldstatus != (long) self) break; + newstatus = (long) self->p_nextwaiting; + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + /* Now, check if we're somewhere in the list. + There's a race condition with sem_post here, but it does not matter: + the net result is that at the time pthread_exit is called, + self is no longer reachable from sem->sem_status. */ + if (oldstatus != (long) self && (oldstatus & 1) == 0) { + for (th = &(((pthread_descr) oldstatus)->p_nextwaiting); + *th != NULL && *th != (pthread_descr) 1; + th = &((*th)->p_nextwaiting)) { + if (*th == self) { + *th = self->p_nextwaiting; + break; + } + } + } + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + } +} + +int __old_sem_trywait(old_sem_t * sem); +int __old_sem_trywait(old_sem_t * sem) +{ + long oldstatus, newstatus; + + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) == 0 || (oldstatus == 1)) { + errno = EAGAIN; + return -1; + } + newstatus = oldstatus - 2; + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + return 0; +} + +int __old_sem_post(old_sem_t * sem); +int __old_sem_post(old_sem_t * sem) +{ + long oldstatus, newstatus; + + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) == 0) + newstatus = 3; + else { + if (oldstatus >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + return -1; + } + newstatus = oldstatus + 2; + } + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + if ((oldstatus & 1) == 0) + sem_restart_list((pthread_descr) oldstatus); + return 0; +} + +int __old_sem_getvalue(old_sem_t * sem, int * sval); +int __old_sem_getvalue(old_sem_t * sem, int * sval) +{ + long status = sem->sem_status; + if (status & 1) + *sval = (int)((unsigned long) status >> 1); + else + *sval = 0; + return 0; +} + +int __old_sem_destroy(old_sem_t * sem); +int __old_sem_destroy(old_sem_t * sem) +{ + if ((sem->sem_status & 1) == 0) { + errno = EBUSY; + return -1; + } + return 0; +} + +/* Auxiliary function for restarting all threads on a waiting list, + in priority order. */ + +static void sem_restart_list(pthread_descr waiting) +{ + pthread_descr th, towake, *p; + + /* Sort list of waiting threads by decreasing priority (insertion sort) */ + towake = NULL; + while (waiting != (pthread_descr) 1) { + th = waiting; + waiting = waiting->p_nextwaiting; + p = &towake; + while (*p != NULL && th->p_priority < (*p)->p_priority) + p = &((*p)->p_nextwaiting); + th->p_nextwaiting = *p; + *p = th; + } + /* Wake up threads in priority order */ + while (towake != NULL) { + th = towake; + towake = towake->p_nextwaiting; + th->p_nextwaiting = NULL; + restart(th); + } +} + +#if defined __PIC__ && defined DO_VERSIONING +symbol_version (__old_sem_init, sem_init, GLIBC_2.0); +symbol_version (__old_sem_wait, sem_wait, GLIBC_2.0); +symbol_version (__old_sem_trywait, sem_trywait, GLIBC_2.0); +symbol_version (__old_sem_post, sem_post, GLIBC_2.0); +symbol_version (__old_sem_getvalue, sem_getvalue, GLIBC_2.0); +symbol_version (__old_sem_destroy, sem_destroy, GLIBC_2.0); +#endif + diff --git a/libpthread/linuxthreads.old/pt-machine.c b/libpthread/linuxthreads.old/pt-machine.c new file mode 100644 index 0000000..438008d --- /dev/null +++ b/libpthread/linuxthreads.old/pt-machine.c @@ -0,0 +1,22 @@ +/* "Instantiation of machine-dependent pthreads inline functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define PT_EI + +#include diff --git a/libpthread/linuxthreads.old/ptfork.c b/libpthread/linuxthreads.old/ptfork.c new file mode 100644 index 0000000..7a5749e --- /dev/null +++ b/libpthread/linuxthreads.old/ptfork.c @@ -0,0 +1,174 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* mods for uClibc: removed strong alias and defined funcs properly */ + +/* The "atfork" stuff */ + +#include + +#ifdef __ARCH_USE_MMU__ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +struct handler_list { + void (*handler)(void); + struct handler_list * next; +}; + +static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER; +static struct handler_list * pthread_atfork_prepare = NULL; +static struct handler_list * pthread_atfork_parent = NULL; +static struct handler_list * pthread_atfork_child = NULL; + +#ifdef __MALLOC__ +__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock); +__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#endif + +static void pthread_insert_list(struct handler_list ** list, + void (*handler)(void), + struct handler_list * newlist, + int at_end) +{ + if (handler == NULL) return; + if (at_end) { + while(*list != NULL) list = &((*list)->next); + } + newlist->handler = handler; + newlist->next = *list; + *list = newlist; +} + +struct handler_list_block { + struct handler_list prepare, parent, child; +}; + +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + struct handler_list_block * block = + (struct handler_list_block *) malloc(sizeof(struct handler_list_block)); + if (block == NULL) return ENOMEM; + __pthread_mutex_lock(&pthread_atfork_lock); + /* "prepare" handlers are called in LIFO */ + pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0); + /* "parent" handlers are called in FIFO */ + pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1); + /* "child" handlers are called in FIFO */ + pthread_insert_list(&pthread_atfork_child, child, &block->child, 1); + __pthread_mutex_unlock(&pthread_atfork_lock); + return 0; +} +//strong_alias (__pthread_atfork, pthread_atfork) + +static __inline__ void pthread_call_handlers(struct handler_list * list) +{ + for (/*nothing*/; list != NULL; list = list->next) (list->handler)(); +} + +void __pthread_once_fork_prepare(void); +void __pthread_once_fork_child(void); +void __pthread_once_fork_parent(void); + +extern __typeof(fork) __libc_fork; + +pid_t __fork(void) attribute_hidden; +pid_t __fork(void) +{ + pid_t pid; + struct handler_list * prepare, * child, * parent; + + __pthread_mutex_lock(&pthread_atfork_lock); + prepare = pthread_atfork_prepare; + child = pthread_atfork_child; + parent = pthread_atfork_parent; + pthread_call_handlers(prepare); + + __pthread_once_fork_prepare(); +#ifdef __MALLOC__ + __pthread_mutex_lock(&__malloc_sbrk_lock); + __pthread_mutex_lock(&__malloc_heap_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_lock(&__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_lock(&__malloc_lock); +#endif + + pid = __libc_fork(); + if (pid == 0) { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __libc_lock_init_recursive(__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __libc_lock_init_adaptive(__malloc_mmb_heap_lock); +#endif + __libc_lock_init_adaptive(__malloc_heap_lock); + __libc_lock_init(__malloc_sbrk_lock); +#endif + __libc_lock_init_adaptive(pthread_atfork_lock); + __pthread_reset_main_thread(); + __fresetlockfiles(); + __pthread_once_fork_child(); + pthread_call_handlers(child); + } else { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_unlock(&__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_unlock(&__malloc_mmb_heap_lock); +#endif + __pthread_mutex_unlock(&__malloc_heap_lock); + __pthread_mutex_unlock(&__malloc_sbrk_lock); +#endif + __pthread_mutex_unlock(&pthread_atfork_lock); + __pthread_once_fork_parent(); + pthread_call_handlers(parent); + } + return pid; +} +strong_alias(__fork,fork) + +pid_t vfork(void) +{ + return __fork(); +} + +#else + +/* We can't support pthread_atfork without MMU, since we don't have + fork(), and we can't offer the correct semantics for vfork(). */ +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + /* ENOMEM is probably pushing it a little bit. + Take it as `no *virtual* memory' :-) */ + errno = ENOMEM; + return -1; +} + +#endif diff --git a/libpthread/linuxthreads.old/pthread.c b/libpthread/linuxthreads.old/pthread.c new file mode 100644 index 0000000..e96f3ab --- /dev/null +++ b/libpthread/linuxthreads.old/pthread.c @@ -0,0 +1,1166 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread creation, initialization, and basic low-level routines */ + +#define __FORCE_GLIBC +#include +#include +#include /* for h_errno */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "debug.h" /* added to linuxthreads -StS */ + + +/* Mods for uClibc: Some includes */ +#include +#include +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; +libpthread_hidden_proto(waitpid) +libpthread_hidden_proto(raise) + +/* These variables are used by the setup code. */ +extern int _errno; +extern int _h_errno; + + +/* Descriptor of the initial thread */ + +struct _pthread_descr_struct __pthread_initial_thread = { + &__pthread_initial_thread, /* pthread_descr p_nextlive */ + &__pthread_initial_thread, /* pthread_descr p_prevlive */ + NULL, /* pthread_descr p_nextwaiting */ + NULL, /* pthread_descr p_nextlock */ + PTHREAD_THREADS_MAX, /* pthread_t p_tid */ + 0, /* int p_pid */ + 0, /* int p_priority */ + &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */ + 0, /* int p_signal */ + NULL, /* sigjmp_buf * p_signal_buf */ + NULL, /* sigjmp_buf * p_cancel_buf */ + 0, /* char p_terminated */ + 0, /* char p_detached */ + 0, /* char p_exited */ + NULL, /* void * p_retval */ + 0, /* int p_retval */ + NULL, /* pthread_descr p_joining */ + NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ + 0, /* char p_cancelstate */ + 0, /* char p_canceltype */ + 0, /* char p_canceled */ + &_errno, /* int *p_errnop */ + 0, /* int p_errno */ + &_h_errno, /* int *p_h_errnop */ + 0, /* int p_h_errno */ + NULL, /* char * p_in_sighandler */ + 0, /* char p_sigwaiting */ + PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ + {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ + {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ + 0, /* int p_userstack */ + NULL, /* void * p_guardaddr */ + 0, /* size_t p_guardsize */ + &__pthread_initial_thread, /* pthread_descr p_self */ + 0, /* Always index 0 */ + 0, /* int p_report_events */ + {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ + __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ + 0, /* char p_woken_by_cancel */ + 0, /* char p_condvar_avail */ + 0, /* char p_sem_avail */ + NULL, /* struct pthread_extricate_if *p_extricate */ + NULL, /* pthread_readlock_info *p_readlock_list; */ + NULL, /* pthread_readlock_info *p_readlock_free; */ + 0 /* int p_untracked_readlock_count; */ +#ifdef __UCLIBC_HAS_XLOCALE__ + , + &__global_locale_data, /* __locale_t locale; */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +}; + +/* Descriptor of the manager thread; none of this is used but the error + variables, the p_pid and p_priority fields, + and the address for identification. */ +#define manager_thread (&__pthread_manager_thread) +struct _pthread_descr_struct __pthread_manager_thread = { + NULL, /* pthread_descr p_nextlive */ + NULL, /* pthread_descr p_prevlive */ + NULL, /* pthread_descr p_nextwaiting */ + NULL, /* pthread_descr p_nextlock */ + 0, /* int p_tid */ + 0, /* int p_pid */ + 0, /* int p_priority */ + &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */ + 0, /* int p_signal */ + NULL, /* sigjmp_buf * p_signal_buf */ + NULL, /* sigjmp_buf * p_cancel_buf */ + 0, /* char p_terminated */ + 0, /* char p_detached */ + 0, /* char p_exited */ + NULL, /* void * p_retval */ + 0, /* int p_retval */ + NULL, /* pthread_descr p_joining */ + NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ + 0, /* char p_cancelstate */ + 0, /* char p_canceltype */ + 0, /* char p_canceled */ + &__pthread_manager_thread.p_errno, /* int *p_errnop */ + 0, /* int p_errno */ + NULL, /* int *p_h_errnop */ + 0, /* int p_h_errno */ + NULL, /* char * p_in_sighandler */ + 0, /* char p_sigwaiting */ + PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ + {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ + {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ + 0, /* int p_userstack */ + NULL, /* void * p_guardaddr */ + 0, /* size_t p_guardsize */ + &__pthread_manager_thread, /* pthread_descr p_self */ + 1, /* Always index 1 */ + 0, /* int p_report_events */ + {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ + __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ + 0, /* char p_woken_by_cancel */ + 0, /* char p_condvar_avail */ + 0, /* char p_sem_avail */ + NULL, /* struct pthread_extricate_if *p_extricate */ + NULL, /* pthread_readlock_info *p_readlock_list; */ + NULL, /* pthread_readlock_info *p_readlock_free; */ + 0 /* int p_untracked_readlock_count; */ +#ifdef __UCLIBC_HAS_XLOCALE__ + , + &__global_locale_data, /* __locale_t locale; */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +}; + +/* Pointer to the main thread (the father of the thread manager thread) */ +/* Originally, this is the initial thread, but this changes after fork() */ + +pthread_descr __pthread_main_thread = &__pthread_initial_thread; + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ + +char *__pthread_initial_thread_bos = NULL; + +/* For non-MMU systems also remember to stack top of the initial thread. + * This is adapted when other stacks are malloc'ed since we don't know + * the bounds a-priori. -StS */ + +#ifndef __ARCH_USE_MMU__ +char *__pthread_initial_thread_tos = NULL; +#endif /* __ARCH_USE_MMU__ */ + +/* File descriptor for sending requests to the thread manager. */ +/* Initially -1, meaning that the thread manager is not running. */ + +int __pthread_manager_request = -1; + +/* Other end of the pipe for sending requests to the thread manager. */ + +int __pthread_manager_reader; + +/* Limits of the thread manager stack */ + +char *__pthread_manager_thread_bos = NULL; +char *__pthread_manager_thread_tos = NULL; + +/* For process-wide exit() */ + +int __pthread_exit_requested = 0; +int __pthread_exit_code = 0; + +/* Communicate relevant LinuxThreads constants to gdb */ + +const int __pthread_threads_max = PTHREAD_THREADS_MAX; +const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); +const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr); +const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, + p_pid); +const int __linuxthreads_pthread_sizeof_descr + = sizeof(struct _pthread_descr_struct); + +const int __linuxthreads_initial_report_events; + +const char __linuxthreads_version[] = VERSION; + +/* Forward declarations */ +static void pthread_onexit_process(int retcode, void *arg); +static void pthread_handle_sigcancel(int sig); +static void pthread_handle_sigrestart(int sig); +static void pthread_handle_sigdebug(int sig); +int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +/* Signal numbers used for the communication. + In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +#ifndef __NR_rt_sigaction +static int current_rtmin = -1; +static int current_rtmax = -1; +int __pthread_sig_restart = SIGUSR1; +int __pthread_sig_cancel = SIGUSR2; +int __pthread_sig_debug; +#else + +#if __SIGRTMAX - __SIGRTMIN >= 3 +static int current_rtmin = __SIGRTMIN + 3; +static int current_rtmax = __SIGRTMAX; +int __pthread_sig_restart = __SIGRTMIN; +int __pthread_sig_cancel = __SIGRTMIN + 1; +int __pthread_sig_debug = __SIGRTMIN + 2; +void (*__pthread_restart)(pthread_descr) = __pthread_restart_new; +void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new; +#else +static int current_rtmin = __SIGRTMIN; +static int current_rtmax = __SIGRTMAX; +int __pthread_sig_restart = SIGUSR1; +int __pthread_sig_cancel = SIGUSR2; +int __pthread_sig_debug; +void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; +void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; + +#endif + +/* Return number of available real-time signal with highest priority. */ +int __libc_current_sigrtmin (void) +{ + return current_rtmin; +} + +/* Return number of available real-time signal with lowest priority. */ +int __libc_current_sigrtmax (void) +{ + return current_rtmax; +} + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int __libc_allocate_rtsig (int high); +int __libc_allocate_rtsig (int high) +{ + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + return high ? current_rtmin++ : current_rtmax--; +} +#endif + +/* Initialize the pthread library. + Initialization is split in two functions: + - a constructor function that blocks the __pthread_sig_restart signal + (must do this very early, since the program could capture the signal + mask with e.g. sigsetjmp before creating the first thread); + - a regular function called from pthread_create when needed. */ + +static void pthread_initialize(void) __attribute__((constructor)); + +libpthread_hidden_proto(pthread_attr_destroy) +libpthread_hidden_proto(pthread_attr_init) +libpthread_hidden_proto(pthread_attr_getdetachstate) +libpthread_hidden_proto(pthread_attr_setdetachstate) +libpthread_hidden_proto(pthread_attr_getinheritsched) +libpthread_hidden_proto(pthread_attr_setinheritsched) +libpthread_hidden_proto(pthread_attr_setschedparam) +libpthread_hidden_proto(pthread_attr_getschedparam) +libpthread_hidden_proto(pthread_attr_getschedpolicy) +libpthread_hidden_proto(pthread_attr_setschedpolicy) +libpthread_hidden_proto(pthread_attr_getscope) +libpthread_hidden_proto(pthread_attr_setscope) + +libpthread_hidden_proto(pthread_exit) + +libpthread_hidden_proto(pthread_equal) +libpthread_hidden_proto(pthread_self) +libpthread_hidden_proto(pthread_getschedparam) +libpthread_hidden_proto(pthread_setschedparam) + +libpthread_hidden_proto(pthread_setcancelstate) +libpthread_hidden_proto(pthread_setcanceltype) +libpthread_hidden_proto(_pthread_cleanup_push_defer) +libpthread_hidden_proto(_pthread_cleanup_pop_restore) + +libpthread_hidden_proto(pthread_cond_broadcast) +libpthread_hidden_proto(pthread_cond_destroy) +libpthread_hidden_proto(pthread_cond_init) +libpthread_hidden_proto(pthread_cond_signal) +libpthread_hidden_proto(pthread_cond_wait) +libpthread_hidden_proto(pthread_cond_timedwait) + +libpthread_hidden_proto(pthread_condattr_destroy) +libpthread_hidden_proto(pthread_condattr_init) + +struct pthread_functions __pthread_functions = + { +#if !(USE_TLS && HAVE___THREAD) + .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, + .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, + .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, +#endif +/* + .ptr_pthread_fork = __pthread_fork, +*/ + .ptr_pthread_attr_destroy = pthread_attr_destroy, + .ptr_pthread_attr_init = pthread_attr_init, + .ptr_pthread_attr_getdetachstate = pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = pthread_attr_getscope, + .ptr_pthread_attr_setscope = pthread_attr_setscope, + .ptr_pthread_condattr_destroy = pthread_condattr_destroy, + .ptr_pthread_condattr_init = pthread_condattr_init, + .ptr_pthread_cond_broadcast = pthread_cond_broadcast, + .ptr_pthread_cond_destroy = pthread_cond_destroy, + .ptr_pthread_cond_init = pthread_cond_init, + .ptr_pthread_cond_signal = pthread_cond_signal, + .ptr_pthread_cond_wait = pthread_cond_wait, + .ptr_pthread_cond_timedwait = pthread_cond_timedwait, + .ptr_pthread_equal = pthread_equal, + .ptr___pthread_exit = pthread_exit, + .ptr_pthread_getschedparam = pthread_getschedparam, + .ptr_pthread_setschedparam = pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = pthread_self, + .ptr_pthread_setcancelstate = pthread_setcancelstate, + .ptr_pthread_setcanceltype = pthread_setcanceltype, +/* + .ptr_pthread_do_exit = pthread_do_exit, + .ptr_pthread_thread_self = pthread_thread_self, + .ptr_pthread_cleanup_upto = pthread_cleanup_upto, + .ptr_pthread_sigaction = pthread_sigaction, + .ptr_pthread_sigwait = pthread_sigwait, + .ptr_pthread_raise = pthread_raise, + .ptr__pthread_cleanup_push = _pthread_cleanup_push, + .ptr__pthread_cleanup_pop = _pthread_cleanup_pop +*/ + .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, + }; +#ifdef SHARED +# define ptr_pthread_functions &__pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; + + /* Do some minimal initialization which has to be done during the + startup of the C library. */ +void __pthread_initialize_minimal(void) +{ + /* If we have special thread_self processing, initialize + * that for the main thread now. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +#endif + + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); +} + + +static void pthread_initialize(void) +{ + struct sigaction sa; + sigset_t mask; +#ifdef __ARCH_USE_MMU__ + struct rlimit limit; + rlim_t max_stack; +#endif + + /* If already done (e.g. by a constructor called earlier!), bail out */ + if (__pthread_initial_thread_bos != NULL) return; +#ifdef TEST_FOR_COMPARE_AND_SWAP + /* Test if compare-and-swap is available */ + __pthread_has_cas = compare_and_swap_is_available(); +#endif + /* For the initial stack, reserve at least STACK_SIZE bytes of stack + below the current stack address, and align that on a + STACK_SIZE boundary. */ + __pthread_initial_thread_bos = + (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); + /* Update the descriptor for the initial thread. */ + __pthread_initial_thread.p_pid = getpid(); + /* If we have special thread_self processing, initialize that for the + main thread now. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +#endif + /* The errno/h_errno variable of the main thread are the global ones. */ + __pthread_initial_thread.p_errnop = &_errno; + __pthread_initial_thread.p_h_errnop = &_h_errno; + +#ifdef __UCLIBC_HAS_XLOCALE__ + /* The locale of the main thread is the current locale in use. */ + __pthread_initial_thread.locale = __curlocale_var; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + { /* uClibc-specific stdio initialization for threads. */ + FILE *fp; + + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } + + /* Play with the stack size limit to make sure that no stack ever grows + beyond STACK_SIZE minus two pages (one page for the thread descriptor + immediately beyond, and one page to act as a guard page). */ + +#ifdef __ARCH_USE_MMU__ + /* We cannot allocate a huge chunk of memory to mmap all thread stacks later + * on a non-MMU system. Thus, we don't need the rlimit either. -StS */ + getrlimit(RLIMIT_STACK, &limit); + max_stack = STACK_SIZE - 2 * getpagesize(); + if (limit.rlim_cur > max_stack) { + limit.rlim_cur = max_stack; + setrlimit(RLIMIT_STACK, &limit); + } +#else + /* For non-MMU assume __pthread_initial_thread_tos at upper page boundary, and + * __pthread_initial_thread_bos at address 0. These bounds are refined as we + * malloc other stack frames such that they don't overlap. -StS + */ + __pthread_initial_thread_tos = + (char *)(((long)CURRENT_STACK_FRAME + getpagesize()) & ~(getpagesize() - 1)); + __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */ + PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n", + __pthread_initial_thread_bos, __pthread_initial_thread_tos); +#endif /* __ARCH_USE_MMU__ */ + + /* Setup signal handlers for the initial thread. + Since signal handlers are shared between threads, these settings + will be inherited by all other threads. */ + sa.sa_handler = pthread_handle_sigrestart; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + sa.sa_handler = pthread_handle_sigcancel; + sigaddset(&sa.sa_mask, __pthread_sig_restart); + /* sa.sa_flags = 0; */ + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) { + sa.sa_handler = pthread_handle_sigdebug; + sigemptyset(&sa.sa_mask); + /* sa.sa_flags = 0; */ + __libc_sigaction(__pthread_sig_debug, &sa, NULL); + } + /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ + sigemptyset(&mask); + sigaddset(&mask, __pthread_sig_restart); + sigprocmask(SIG_BLOCK, &mask, NULL); + /* And unblock __pthread_sig_cancel if it has been blocked. */ + sigdelset(&mask, __pthread_sig_restart); + sigaddset(&mask, __pthread_sig_cancel); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Register an exit function to kill all other threads. */ + /* Do it early so that user-registered atexit functions are called + before pthread_onexit_process. */ + on_exit(pthread_onexit_process, NULL); +} + +void __pthread_initialize(void); +void __pthread_initialize(void) +{ + pthread_initialize(); +} + +int __pthread_initialize_manager(void) +{ + int manager_pipe[2]; + int pid; + int report_events; + struct pthread_request request; + + *__libc_multiple_threads_ptr = 1; + + /* If basic initialization not done yet (e.g. we're called from a + constructor run before our constructor), do it now */ + if (__pthread_initial_thread_bos == NULL) pthread_initialize(); + /* Setup stack for thread manager */ + __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); + if (__pthread_manager_thread_bos == NULL) return -1; + __pthread_manager_thread_tos = + __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; + + /* On non-MMU systems we make sure that the initial thread bounds don't overlap + * with the manager stack frame */ + NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos); + PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE, + __pthread_manager_thread_bos, __pthread_manager_thread_tos); +#if 0 + PDEBUG("initial stack: estimate bos=%p, tos=%p\n", + __pthread_initial_thread_bos, __pthread_initial_thread_tos); +#endif + + /* Setup pipe to communicate with thread manager */ + if (pipe(manager_pipe) == -1) { + free(__pthread_manager_thread_bos); + return -1; + } + /* Start the thread manager */ + pid = 0; +#ifdef USE_TLS + if (__linuxthreads_initial_report_events != 0) + THREAD_SETMEM (((pthread_descr) NULL), p_report_events, + __linuxthreads_initial_report_events); + report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); +#else + if (__linuxthreads_initial_report_events != 0) + __pthread_initial_thread.p_report_events + = __linuxthreads_initial_report_events; + report_events = __pthread_initial_thread.p_report_events; +#endif + if (__builtin_expect (report_events, 0)) + { + /* It's a bit more complicated. We have to report the creation of + the manager thread. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx])) + != 0) + { + + __pthread_lock(__pthread_manager_thread.p_lock, NULL); + +#ifdef __ia64__ + pid = __clone2(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#else + pid = clone(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#endif + + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + __pthread_manager_thread.p_eventbuf.eventdata = + &__pthread_manager_thread; + __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = &__pthread_manager_thread; + __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; + __pthread_manager_thread.p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + } + /* Now restart the thread. */ + __pthread_unlock(__pthread_manager_thread.p_lock); + } + } + + if (pid == 0) { +#ifdef __ia64__ + pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_tos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#else + pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#endif + } + if (pid == -1) { + free(__pthread_manager_thread_bos); + __libc_close(manager_pipe[0]); + __libc_close(manager_pipe[1]); + return -1; + } + __pthread_manager_request = manager_pipe[1]; /* writing end */ + __pthread_manager_reader = manager_pipe[0]; /* reading end */ + __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; + __pthread_manager_thread.p_pid = pid; + + /* Make gdb aware of new thread manager */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + { + raise(__pthread_sig_debug); + /* We suspend ourself and gdb will wake us up when it is + ready to handle us. */ + __pthread_wait_for_restart_signal(thread_self()); + } + /* Synchronize debugging of the thread manager */ + PDEBUG("send REQ_DEBUG to manager thread\n"); + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + return 0; +} + +/* Thread creation */ + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + pthread_descr self = thread_self(); + struct pthread_request request; + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) return EAGAIN; + } + request.req_thread = self; + request.req_kind = REQ_CREATE; + request.req_args.create.attr = attr; + request.req_args.create.fn = start_routine; + request.req_args.create.arg = arg; + sigprocmask(SIG_SETMASK, (const sigset_t *) NULL, + &request.req_args.create.mask); + PDEBUG("write REQ_CREATE to manager thread\n"); + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + PDEBUG("before suspend(self)\n"); + suspend(self); + PDEBUG("after suspend(self)\n"); + if (THREAD_GETMEM(self, p_retcode) == 0) + *thread = (pthread_t) THREAD_GETMEM(self, p_retval); + return THREAD_GETMEM(self, p_retcode); +} + +/* Simple operations on thread identifiers */ + +pthread_t pthread_self(void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM(self, p_tid); +} +libpthread_hidden_def (pthread_self) + +int pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +libpthread_hidden_def (pthread_equal) + +/* Helper function for thread_self in the case of user-provided stacks */ + +#ifndef THREAD_SELF + +pthread_descr __pthread_find_self(void) +{ + char * sp = CURRENT_STACK_FRAME; + pthread_handle h; + + /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is + the manager threads handled specially in thread_self(), so start at 2 */ + h = __pthread_handles + 2; + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; + +#ifdef DEBUG_PT + if (h->h_descr == NULL) { + printf("*** %s ERROR descriptor is NULL!!!!! ***\n\n", __FUNCTION__); + _exit(1); + } +#endif + + return h->h_descr; +} +#else + +static pthread_descr thread_self_stack(void) +{ + char *sp = CURRENT_STACK_FRAME; + pthread_handle h; + + if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) + return manager_thread; + h = __pthread_handles + 2; +# ifdef USE_TLS + while (h->h_descr == NULL + || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) + h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) + h++; +# endif + return h->h_descr; +} + +#endif + +/* Thread scheduling */ + +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (sched_setscheduler(th->p_pid, policy, param) == -1) { + __pthread_unlock(&handle->h_lock); + return errno; + } + th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; + __pthread_unlock(&handle->h_lock); + if (__pthread_manager_request >= 0) + __pthread_manager_adjust_prio(th->p_priority); + return 0; +} +libpthread_hidden_def(pthread_setschedparam) + +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + int pid, pol; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + pol = sched_getscheduler(pid); + if (pol == -1) return errno; + if (sched_getparam(pid, param) == -1) return errno; + *policy = pol; + return 0; +} +libpthread_hidden_def(pthread_getschedparam) + +/* Process-wide exit() request */ + +static void pthread_onexit_process(int retcode, void *arg attribute_unused) +{ + struct pthread_request request; + pthread_descr self = thread_self(); + + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_PROCESS_EXIT; + request.req_args.exit.code = retcode; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); + /* Since all threads have been asynchronously terminated + * (possibly holding locks), free cannot be used any more. */ + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } + } +} + +/* The handler for the RESTART signal just records the signal received + in the thread descriptor, and optionally performs a siglongjmp + (for pthread_cond_timedwait). */ + +static void pthread_handle_sigrestart(int sig) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_signal, sig); + if (THREAD_GETMEM(self, p_signal_jmp) != NULL) + siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); +} + +/* The handler for the CANCEL signal checks for cancellation + (in asynchronous mode), for process-wide exit and exec requests. + For the thread manager thread, redirect the signal to + __pthread_manager_sighandler. */ + +static void pthread_handle_sigcancel(int sig) +{ + pthread_descr self = thread_self(); + sigjmp_buf * jmpbuf; + + + if (self == &__pthread_manager_thread) + { +#ifdef THREAD_SELF + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + pthread_descr real_self = thread_self_stack(); + if (real_self == &__pthread_manager_thread) + { + __pthread_manager_sighandler(sig); + return; + } + /* Oops, thread_self() isn't working yet.. */ + self = real_self; +# ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +# endif +#else + __pthread_manager_sighandler(sig); + return; +#endif + } + if (__builtin_expect (__pthread_exit_requested, 0)) { + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#ifdef USE_TLS + waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + +/* Handler for the DEBUG signal. + The debugging strategy is as follows: + On reception of a REQ_DEBUG request (sent by new threads created to + the thread manager under debugging mode), the thread manager throws + __pthread_sig_debug to itself. The debugger (if active) intercepts + this signal, takes into account new threads and continue execution + of the thread manager by propagating the signal because it doesn't + know what it is specifically done for. In the current implementation, + the thread manager simply discards it. */ + +static void pthread_handle_sigdebug(int sig attribute_unused) +{ + /* Nothing */ +} + +/* Reset the state of the thread machinery after a fork(). + Close the pipe used for requests and set the main thread to the forked + thread. + Notice that we can't free the stack segments, as the forked thread + may hold pointers into them. */ + +void __pthread_reset_main_thread(void) +{ + pthread_descr self = thread_self(); + + if (__pthread_manager_request != -1) { + /* Free the thread manager stack */ + free(__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + /* Close the two ends of the pipe */ + __libc_close(__pthread_manager_request); + __libc_close(__pthread_manager_reader); + __pthread_manager_request = __pthread_manager_reader = -1; + } + + /* Update the pid of the main thread */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Make the forked thread the main thread */ + __pthread_main_thread = self; + THREAD_SETMEM(self, p_nextlive, self); + THREAD_SETMEM(self, p_prevlive, self); + /* Now this thread modifies the global variables. */ + THREAD_SETMEM(self, p_errnop, &_errno); + THREAD_SETMEM(self, p_h_errnop, &_h_errno); +} + +/* Process-wide exec() request */ + +void __pthread_kill_other_threads_np(void) +{ + struct sigaction sa; + /* Terminate all other threads and thread manager */ + pthread_onexit_process(0, NULL); + /* Make current thread the main thread in case the calling thread + changes its mind, does not exec(), and creates new threads instead. */ + __pthread_reset_main_thread(); + /* Reset the signal handlers behaviour for the signals the + implementation uses since this would be passed to the new + process. */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) + __libc_sigaction(__pthread_sig_debug, &sa, NULL); +} +weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) + +/* Concurrency symbol level. */ +static int current_level; + +int __pthread_setconcurrency(int level) +{ + /* We don't do anything unless we have found a useful interpretation. */ + current_level = level; + return 0; +} +weak_alias (__pthread_setconcurrency, pthread_setconcurrency) + +int __pthread_getconcurrency(void) +{ + return current_level; +} +weak_alias (__pthread_getconcurrency, pthread_getconcurrency) + + +/* Primitives for controlling thread execution */ + +void __pthread_wait_for_restart_signal(pthread_descr self) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ + sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ + THREAD_SETMEM(self, p_signal, 0); + do { + sigsuspend(&mask); /* Wait for signal */ + } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ +} + +#ifndef __NR_rt_sigaction +/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT + signals. + On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. + Since the restart signal does not queue, we use an atomic counter to create + queuing semantics. This is needed to resolve a rare race condition in + pthread_cond_timedwait_relative. */ + +void __pthread_restart_old(pthread_descr th) +{ + if (atomic_increment(&th->p_resume_count) == -1) + kill(th->p_pid, __pthread_sig_restart); +} + +void __pthread_suspend_old(pthread_descr self) +{ + if (atomic_decrement(&self->p_resume_count) <= 0) + __pthread_wait_for_restart_signal(self); +} + +int +__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (atomic_decrement(&self->p_resume_count) == 0) { + /* Set up a longjmp handler for the restart signal, unblock + the signal and sleep. */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + } + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + we know we have been dequeued and resumed and that the + resume count is balanced. Otherwise, there are some + cases to consider. First, try to bump up the resume count + back to zero. If it goes to 1, it means restart() was + invoked on this thread. The signal must be consumed + and the count bumped down and everything is cool. We + can return a 1 to the caller. + Otherwise, no restart was delivered yet, so a potential + race exists; we return a 0 to the caller which must deal + with this race in an appropriate way; for example by + atomically removing the thread from consideration for a + wakeup---if such a thing fails, it means a restart is + being delivered. */ + + if (!was_signalled) { + if (atomic_increment(&self->p_resume_count) != -1) { + __pthread_wait_for_restart_signal(self); + atomic_decrement(&self->p_resume_count); /* should be zero now! */ + /* woke spontaneously and consumed restart signal */ + return 1; + } + /* woke spontaneously but did not consume restart---caller must resolve */ + return 0; + } + /* woken due to restart signal */ + return 1; +} +#endif /* __NR_rt_sigaction */ + + +#ifdef __NR_rt_sigaction +void __pthread_restart_new(pthread_descr th) +{ + /* The barrier is proabably not needed, in which case it still documents + our assumptions. The intent is to commit previous writes to shared + memory so the woken thread will have a consistent view. Complementary + read barriers are present to the suspend functions. */ + WRITE_MEMORY_BARRIER(); + kill(th->p_pid, __pthread_sig_restart); +} + +int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + everything is cool. We have been removed from whatever + we were waiting on by the other thread, and consumed its signal. + + Otherwise we this thread woke up spontaneously, or due to a signal other + than restart. This is an ambiguous case that must be resolved by + the caller; the thread is still eligible for a restart wakeup + so there is a race. */ + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ + return was_signalled; +} +#endif + +/* Debugging aid */ + +#ifdef DEBUG_PT +#include + +void __pthread_message(char * fmt, ...) +{ + char buffer[1024]; + va_list args; + sprintf(buffer, "%05d : ", getpid()); + va_start(args, fmt); + vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); + va_end(args); + TEMP_FAILURE_RETRY(__libc_write(2, buffer, strlen(buffer))); +} + +#endif + + +#ifndef __PIC__ +/* We need a hook to force the cancelation wrappers to be linked in when + static libpthread is used. */ +extern const int __pthread_provide_wrappers; +static const int *const __pthread_require_wrappers = + &__pthread_provide_wrappers; +#endif diff --git a/libpthread/linuxthreads.old/ptlongjmp.c b/libpthread/linuxthreads.old/ptlongjmp.c new file mode 100644 index 0000000..b3ff274 --- /dev/null +++ b/libpthread/linuxthreads.old/ptlongjmp.c @@ -0,0 +1,71 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include +#include "pthread.h" +#include "internals.h" +#include + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern __typeof(siglongjmp) __libc_siglongjmp attribute_noreturn; +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; + +static void pthread_cleanup_upto(__jmp_buf target) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + char *currentframe = CURRENT_STACK_FRAME; + + for (c = THREAD_GETMEM(self, p_cleanup); + c != NULL && _JMPBUF_UNWINDS(target, c); + c = c->__prev) + { +#if _STACK_GROWS_DOWN + if ((char *) c <= currentframe) + { + c = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((char *) c >= currentframe) + { + c = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + THREAD_SETMEM(self, p_cleanup, c); + if (THREAD_GETMEM(self, p_in_sighandler) + && _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler))) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +void attribute_noreturn siglongjmp(sigjmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_siglongjmp(env, val); +} + +void attribute_noreturn longjmp(jmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_longjmp(env, val); +} diff --git a/libpthread/linuxthreads.old/queue.h b/libpthread/linuxthreads.old/queue.h new file mode 100644 index 0000000..01d18d1 --- /dev/null +++ b/libpthread/linuxthreads.old/queue.h @@ -0,0 +1,60 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Waiting queues */ + +/* Waiting queues are represented by lists of thread descriptors + linked through their p_nextwaiting field. The lists are kept + sorted by decreasing priority, and then decreasing waiting time. */ + +static __inline__ void enqueue(pthread_descr * q, pthread_descr th) +{ + int prio = th->p_priority; + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (prio > (*q)->p_priority) { + th->p_nextwaiting = *q; + *q = th; + return; + } + } + *q = th; +} + +static __inline__ pthread_descr dequeue(pthread_descr * q) +{ + pthread_descr th; + th = *q; + if (th != NULL) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + } + return th; +} + +static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) +{ + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (*q == th) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + return 1; + } + } + return 0; +} + +static __inline__ int queue_is_empty(pthread_descr * q) +{ + return *q == NULL; +} diff --git a/libpthread/linuxthreads.old/restart.h b/libpthread/linuxthreads.old/restart.h new file mode 100644 index 0000000..7d63a70 --- /dev/null +++ b/libpthread/linuxthreads.old/restart.h @@ -0,0 +1,50 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include +#include +#define __ASSUME_REALTIME_SIGNALS defined(__NR_rt_sigaction) + +/* Primitives for controlling thread execution */ + +static __inline__ void restart(pthread_descr th) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_restart_new(th); +#else + __pthread_restart(th); +#endif +} + +static __inline__ void suspend(pthread_descr self) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_wait_for_restart_signal(self); +#else + __pthread_suspend(self); +#endif +} + +static __inline__ int timedsuspend(pthread_descr self, + const struct timespec *abstime) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + return __pthread_timedsuspend_new(self, abstime); +#else + return __pthread_timedsuspend(self, abstime); +#endif +} diff --git a/libpthread/linuxthreads.old/rwlock.c b/libpthread/linuxthreads.old/rwlock.c new file mode 100644 index 0000000..eaf71e7 --- /dev/null +++ b/libpthread/linuxthreads.old/rwlock.c @@ -0,0 +1,486 @@ +/* Read-write lock implementation. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Xavier Leroy + and Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "queue.h" +#include "spinlock.h" +#include "restart.h" + +/* + * Check whether the calling thread already owns one or more read locks on the + * specified lock. If so, return a pointer to the read lock info structure + * corresponding to that lock. + */ + +static pthread_readlock_info * +rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info; + + for (info = self->p_readlock_list; info != NULL; info = info->pr_next) + { + if (info->pr_lock == rwlock) + return info; + } + + return NULL; +} + +/* + * Add a new lock to the thread's list of locks for which it has a read lock. + * A new info node must be allocated for this, which is taken from the thread's + * free list, or by calling malloc. If malloc fails, a null pointer is + * returned. Otherwise the lock info structure is initialized and pushed + * onto the thread's list. + */ + +static pthread_readlock_info * +rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info = self->p_readlock_free; + + if (info != NULL) + self->p_readlock_free = info->pr_next; + else + info = malloc(sizeof *info); + + if (info == NULL) + return NULL; + + info->pr_lock_count = 1; + info->pr_lock = rwlock; + info->pr_next = self->p_readlock_list; + self->p_readlock_list = info; + + return info; +} + +/* + * If the thread owns a read lock over the given pthread_rwlock_t, + * and this read lock is tracked in the thread's lock list, + * this function returns a pointer to the info node in that list. + * It also decrements the lock count within that node, and if + * it reaches zero, it removes the node from the list. + * If nothing is found, it returns a null pointer. + */ + +static pthread_readlock_info * +rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info **pinfo; + + for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) + { + if ((*pinfo)->pr_lock == rwlock) + { + pthread_readlock_info *info = *pinfo; + if (--info->pr_lock_count == 0) + *pinfo = info->pr_next; + return info; + } + } + + return NULL; +} + +/* + * This function checks whether the conditions are right to place a read lock. + * It returns 1 if so, otherwise zero. The rwlock's internal lock must be + * locked upon entry. + */ + +static int +rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) +{ + /* Can't readlock; it is write locked. */ + if (rwlock->__rw_writer != NULL) + return 0; + + /* Lock prefers readers; get it. */ + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) + return 1; + + /* Lock prefers writers, but none are waiting. */ + if (queue_is_empty(&rwlock->__rw_write_waiting)) + return 1; + + /* Writers are waiting, but this thread already has a read lock */ + if (have_lock_already) + return 1; + + /* Writers are waiting, and this is a new lock */ + return 0; +} + +/* + * This function helps support brain-damaged recursive read locking + * semantics required by Unix 98, while maintaining write priority. + * This basically determines whether this thread already holds a read lock + * already. It returns 1 if so, otherwise it returns 0. + * + * If the thread has any ``untracked read locks'' then it just assumes + * that this lock is among them, just to be safe, and returns 1. + * + * Also, if it finds the thread's lock in the list, it sets the pointer + * referenced by pexisting to refer to the list entry. + * + * If the thread has no untracked locks, and the lock is not found + * in its list, then it is added to the list. If this fails, + * then *pout_of_mem is set to 1. + */ + +static int +rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, + pthread_readlock_info **pexisting, int *pout_of_mem) +{ + pthread_readlock_info *existing = NULL; + int out_of_mem = 0, have_lock_already = 0; + pthread_descr self = *pself; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + if (!self) + self = thread_self(); + + existing = rwlock_is_in_list(self, rwlock); + + if (existing != NULL || self->p_untracked_readlock_count > 0) + have_lock_already = 1; + else + { + existing = rwlock_add_to_list(self, rwlock); + if (existing == NULL) + out_of_mem = 1; + } + } + + *pout_of_mem = out_of_mem; + *pexisting = existing; + *pself = self; + + return have_lock_already; +} + +int +pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + __pthread_init_lock(&rwlock->__rw_lock); + rwlock->__rw_readers = 0; + rwlock->__rw_writer = NULL; + rwlock->__rw_read_waiting = NULL; + rwlock->__rw_write_waiting = NULL; + + if (attr == NULL) + { + rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; + rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; + } + else + { + rwlock->__rw_kind = attr->__lockkind; + rwlock->__rw_pshared = attr->__pshared; + } + + return 0; +} + + +int +pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int readers; + _pthread_descr writer; + + __pthread_lock (&rwlock->__rw_lock, NULL); + readers = rwlock->__rw_readers; + writer = rwlock->__rw_writer; + __pthread_unlock (&rwlock->__rw_lock); + + if (readers > 0 || writer != NULL) + return EBUSY; + + return 0; +} + +int +pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + for (;;) + { + if (self == NULL) + self = thread_self (); + + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + existing->pr_lock_count++; + else + self->p_untracked_readlock_count++; + } + + return 0; +} + +int +pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self(); + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + int retval = EBUSY; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + __pthread_lock (&rwlock->__rw_lock, self); + + /* 0 is passed to here instead of have_lock_already. + This is to meet Single Unix Spec requirements: + if writers are waiting, pthread_rwlock_tryrdlock + does not acquire a read lock, even if the caller has + one or more read locks already. */ + + if (rwlock_can_rdlock(rwlock, 0)) + { + ++rwlock->__rw_readers; + retval = 0; + } + + __pthread_unlock (&rwlock->__rw_lock); + + if (retval == 0) + { + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + existing->pr_lock_count++; + else + self->p_untracked_readlock_count++; + } + } + + return retval; +} + + +int +pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self (); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} + + +int +pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = thread_self (); + result = 0; + } + __pthread_unlock (&rwlock->__rw_lock); + + return result; +} + + +int +pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + pthread_descr torestart; + pthread_descr th; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_writer != NULL) + { + /* Unlocking a write lock. */ + if (rwlock->__rw_writer != thread_self ()) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + rwlock->__rw_writer = NULL; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP + || (th = dequeue (&rwlock->__rw_write_waiting)) == NULL) + { + /* Restart all waiting readers. */ + torestart = rwlock->__rw_read_waiting; + rwlock->__rw_read_waiting = NULL; + __pthread_unlock (&rwlock->__rw_lock); + while ((th = dequeue (&torestart)) != NULL) + restart (th); + } + else + { + /* Restart one waiting writer. */ + __pthread_unlock (&rwlock->__rw_lock); + restart (th); + } + } + else + { + /* Unlocking a read lock. */ + if (rwlock->__rw_readers == 0) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + + --rwlock->__rw_readers; + if (rwlock->__rw_readers == 0) + /* Restart one waiting writer, if any. */ + th = dequeue (&rwlock->__rw_write_waiting); + else + th = NULL; + + __pthread_unlock (&rwlock->__rw_lock); + if (th != NULL) + restart (th); + + /* Recursive lock fixup */ + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + pthread_descr self = thread_self(); + pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); + + if (victim != NULL) + { + if (victim->pr_lock_count == 0) + { + victim->pr_next = self->p_readlock_free; + self->p_readlock_free = victim; + } + } + else + { + if (self->p_untracked_readlock_count > 0) + self->p_untracked_readlock_count--; + } + } + } + + return 0; +} + + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + attr->__lockkind = 0; + attr->__pshared = 0; + + return 0; +} + + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr attribute_unused) +{ + return 0; +} + + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) +{ + *pshared = attr->__pshared; + return 0; +} + + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + attr->__pshared = pshared; + + return 0; +} + + +int +pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) +{ + *pref = attr->__lockkind; + return 0; +} + + +int +pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) +{ + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP + && pref != PTHREAD_RWLOCK_DEFAULT_NP) + return EINVAL; + + attr->__lockkind = pref; + + return 0; +} diff --git a/libpthread/linuxthreads.old/semaphore.c b/libpthread/linuxthreads.old/semaphore.c new file mode 100644 index 0000000..7502b6e --- /dev/null +++ b/libpthread/linuxthreads.old/semaphore.c @@ -0,0 +1,313 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include +#include "pthread.h" +#include "semaphore.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" + +int __new_sem_init(sem_t *sem, int pshared, unsigned int value); +int __new_sem_init(sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + __pthread_init_lock(&sem->__sem_lock); + sem->__sem_value = value; + sem->__sem_waiting = NULL; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside __new_sem_wait. */ + +static int new_sem_extricate_func(void *obj, pthread_descr th) +{ + volatile pthread_descr self = thread_self(); + sem_t *sem = obj; + int did_remove = 0; + + __pthread_lock(&sem->__sem_lock, self); + did_remove = remove_from_queue(&sem->__sem_waiting, th); + __pthread_unlock(&sem->__sem_lock); + + return did_remove; +} + +int __new_sem_wait(sem_t * sem); +int __new_sem_wait(sem_t * sem) +{ + volatile pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + sem->__sem_value--; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Wait for sem_post or cancellation, or fall through if already canceled */ + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + +int __new_sem_trywait(sem_t * sem); +int __new_sem_trywait(sem_t * sem) +{ + int retval; + + __pthread_lock(&sem->__sem_lock, NULL); + if (sem->__sem_value == 0) { + errno = EAGAIN; + retval = -1; + } else { + sem->__sem_value--; + retval = 0; + } + __pthread_unlock(&sem->__sem_lock); + return retval; +} + +int __new_sem_post(sem_t * sem); +int __new_sem_post(sem_t * sem) +{ + pthread_descr self = thread_self(); + pthread_descr th; + struct pthread_request request; + + if (THREAD_GETMEM(self, p_in_sighandler) == NULL) { + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_waiting == NULL) { + if (sem->__sem_value >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + __pthread_unlock(&sem->__sem_lock); + return -1; + } + sem->__sem_value++; + __pthread_unlock(&sem->__sem_lock); + } else { + th = dequeue(&sem->__sem_waiting); + __pthread_unlock(&sem->__sem_lock); + th->p_sem_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + } else { + /* If we're in signal handler, delegate post operation to + the thread manager. */ + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) { + errno = EAGAIN; + return -1; + } + } + request.req_kind = REQ_POST; + request.req_args.post = sem; + TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int __new_sem_getvalue(sem_t * sem, int * sval); +int __new_sem_getvalue(sem_t * sem, int * sval) +{ + *sval = sem->__sem_value; + return 0; +} + +int __new_sem_destroy(sem_t * sem); +int __new_sem_destroy(sem_t * sem) +{ + if (sem->__sem_waiting != NULL) { + __set_errno (EBUSY); + return -1; + } + return 0; +} + +sem_t *sem_open(const char *name attribute_unused, int oflag attribute_unused, ...) +{ + __set_errno (ENOSYS); + return SEM_FAILED; +} + +int sem_close(sem_t *sem attribute_unused) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_unlink(const char *name attribute_unused) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abstime) +{ + pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + --sem->__sem_value; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { + /* The standard requires that if the function would block and the + time value is illegal, the function returns with an error. */ + __pthread_unlock(&sem->__sem_lock); + __set_errno (EINVAL); + return -1; + } + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + spurious_wakeup_count = 0; + while (1) + { + if (timedsuspend(self, abstime) == 0) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&sem->__sem_lock, self); + was_on_queue = remove_from_queue(&sem->__sem_waiting, self); + __pthread_unlock(&sem->__sem_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __set_errno (ETIMEDOUT); + return -1; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + + +weak_alias (__new_sem_init, sem_init) +weak_alias (__new_sem_wait, sem_wait) +weak_alias (__new_sem_trywait, sem_trywait) +weak_alias (__new_sem_post, sem_post) +weak_alias (__new_sem_getvalue, sem_getvalue) +weak_alias (__new_sem_destroy, sem_destroy) + diff --git a/libpthread/linuxthreads.old/semaphore.h b/libpthread/linuxthreads.old/semaphore.h new file mode 100644 index 0000000..fac2e59 --- /dev/null +++ b/libpthread/linuxthreads.old/semaphore.h @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors. Needed for `sem_t' definition. */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + +/* System specific semaphore definition. */ +typedef struct +{ + struct _pthread_fastlock __sem_lock; + int __sem_value; + _pthread_descr __sem_waiting; +} sem_t; + + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; + +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/libpthread/linuxthreads.old/signals.c b/libpthread/linuxthreads.old/signals.c new file mode 100644 index 0000000..23ba977 --- /dev/null +++ b/libpthread/linuxthreads.old/signals.c @@ -0,0 +1,251 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of signals */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) +{ + sigset_t mask; + + if (newmask != NULL) { + mask = *newmask; + /* Don't allow __pthread_sig_restart to be unmasked. + Don't allow __pthread_sig_cancel to be masked. */ + switch(how) { + case SIG_SETMASK: + sigaddset(&mask, __pthread_sig_restart); + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_BLOCK: + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_UNBLOCK: + sigdelset(&mask, __pthread_sig_restart); + break; + } + newmask = &mask; + } + if (sigprocmask(how, newmask, oldmask) == -1) + return errno; + else + return 0; +} + +int pthread_kill(pthread_t thread, int signo) +{ + pthread_handle handle = thread_handle(thread); + int pid; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + if (kill(pid, signo) == -1) + return errno; + else + return 0; +} + +/* User-provided signal handlers */ +typedef void (*arch_sighandler_t) __PMT ((int, SIGCONTEXT)); +static union +{ + arch_sighandler_t old; + void (*rt) (int, struct siginfo *, struct ucontext *); +} sighandler[NSIG]; + +/* The wrapper around user-provided signal handlers */ +static void pthread_sighandler(int signo, SIGCONTEXT ctx) +{ + pthread_descr self = thread_self(); + char * in_sighandler; + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The same, this time for real-time signals. */ +static void pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc) +{ + pthread_descr self = thread_self(); + char * in_sighandler; + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + sighandler[signo].rt(signo, si, uc); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The wrapper around sigaction. Install our own signal handler + around the signal. */ +libpthread_hidden_proto(sigaction) +int sigaction(int sig, const struct sigaction * act, + struct sigaction * oact) +{ + struct sigaction newact; + struct sigaction *newactp; + +#ifdef DEBUG_PT +printf(__FUNCTION__": pthreads wrapper!\n"); +#endif + if (sig == __pthread_sig_restart || + sig == __pthread_sig_cancel || + (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) + return EINVAL; + if (act) + { + newact = *act; + if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL + && sig > 0 && sig < NSIG) + { + if (act->sa_flags & SA_SIGINFO) + newact.sa_handler = (__sighandler_t) pthread_sighandler_rt; + else + newact.sa_handler = (__sighandler_t) pthread_sighandler; + } + newactp = &newact; + } + else + newactp = NULL; + if (__libc_sigaction(sig, newactp, oact) == -1) + return -1; +#ifdef DEBUG_PT +printf(__FUNCTION__": sighandler installed, sigaction successful\n"); +#endif + if (sig > 0 && sig < NSIG) + { + if (oact != NULL) + oact->sa_handler = (__sighandler_t) sighandler[sig].old; + if (act) + /* For the assignment is does not matter whether it's a normal + or real-time signal. */ + sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + return 0; +} +libpthread_hidden_def(sigaction) + +/* A signal handler that does nothing */ +static void pthread_null_sighandler(int sig attribute_unused) { } + +/* sigwait -- synchronously wait for a signal */ +int sigwait(const sigset_t * set, int * sig) +{ + volatile pthread_descr self = thread_self(); + sigset_t mask; + int s; + sigjmp_buf jmpbuf; + struct sigaction sa; + + /* Get ready to block all signals except those in set + and the cancellation signal. + Also check that handlers are installed on all signals in set, + and if not, install our dummy handler. This is conformant to + POSIX: "The effect of sigwait() on the signal actions for the + signals in set is unspecified." */ + sigfillset(&mask); + sigdelset(&mask, __pthread_sig_cancel); + for (s = 1; s <= NSIG; s++) { + if (sigismember(set, s) && + s != __pthread_sig_restart && + s != __pthread_sig_cancel && + s != __pthread_sig_debug) { + sigdelset(&mask, s); + if (sighandler[s].old == NULL || + sighandler[s].old == (arch_sighandler_t) SIG_DFL || + sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + sa.sa_handler = pthread_null_sighandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(s, &sa, NULL); + } + } + } + /* Test for cancellation */ + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf); + if (! (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) { + /* Reset the signal count */ + THREAD_SETMEM(self, p_signal, 0); + /* Say we're in sigwait */ + THREAD_SETMEM(self, p_sigwaiting, 1); + /* Unblock the signals and wait for them */ + sigsuspend(&mask); + } + } + THREAD_SETMEM(self, p_cancel_jmp, NULL); + /* The signals are now reblocked. Check for cancellation */ + pthread_testcancel(); + /* We should have self->p_signal != 0 and equal to the signal received */ + *sig = THREAD_GETMEM(self, p_signal); + return 0; +} + +/* Redefine raise() to send signal to calling thread only, + as per POSIX 1003.1c */ +libpthread_hidden_proto(raise) +int raise (int sig) +{ + int retcode = pthread_kill(pthread_self(), sig); + if (retcode == 0) + return 0; + else { + errno = retcode; + return -1; + } +} +libpthread_hidden_def(raise) diff --git a/libpthread/linuxthreads.old/specific.c b/libpthread/linuxthreads.old/specific.c new file mode 100644 index 0000000..dd86148 --- /dev/null +++ b/libpthread/linuxthreads.old/specific.c @@ -0,0 +1,198 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread-specific data */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +/* Table of keys. */ + +static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = + { { 0, NULL } }; + +/* For debugging purposes put the maximum number of keys in a variable. */ +const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; +const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; + +/* Mutex to protect access to pthread_keys */ + +static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Create a new key */ + +int pthread_key_create(pthread_key_t * key, destr_function destr) +{ + int i; + + __pthread_mutex_lock(&pthread_keys_mutex); + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (! pthread_keys[i].in_use) { + /* Mark key in use */ + pthread_keys[i].in_use = 1; + pthread_keys[i].destr = destr; + __pthread_mutex_unlock(&pthread_keys_mutex); + *key = i; + return 0; + } + } + __pthread_mutex_unlock(&pthread_keys_mutex); + return EAGAIN; +} + +/* Delete a key */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_descr self = thread_self(); + + __pthread_mutex_lock(&pthread_keys_mutex); + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { + __pthread_mutex_unlock(&pthread_keys_mutex); + return EINVAL; + } + pthread_keys[key].in_use = 0; + pthread_keys[key].destr = NULL; + + /* Set the value of the key to NULL in all running threads, so + that if the key is reallocated later by pthread_key_create, its + associated values will be NULL in all threads. + Do nothing if no threads have been created yet. */ + if (__pthread_manager_request != -1) + { + pthread_descr th; + unsigned int idx1st, idx2nd; + + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + th = self; + do { + /* If the thread already is terminated don't modify the memory. */ + if (!th->p_terminated && th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + th = th->p_nextlive; + } while (th != self); + } + + __pthread_mutex_unlock(&pthread_keys_mutex); + return 0; +} + +/* Set the value of a key */ + +int pthread_setspecific(pthread_key_t key, const void * pointer) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) + return EINVAL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) { + void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); + if (newp == NULL) + return ENOMEM; + THREAD_SETMEM_NC(self, p_specific[idx1st], newp); + } + THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer; + return 0; +} + +/* Get the value of a key */ + +void * pthread_getspecific(pthread_key_t key) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX) + return NULL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL + || !pthread_keys[key].in_use) + return NULL; + return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd]; +} + +/* Call the destruction routines on all keys */ + +void __pthread_destroy_specifics(void) +{ + pthread_descr self = thread_self(); + int i, j, round, found_nonzero; + destr_function destr; + void * data; + + for (round = 0, found_nonzero = 1; + found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; + round++) { + found_nonzero = 0; + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) + for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { + destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; + data = THREAD_GETMEM_NC(self, p_specific[i])[j]; + if (destr != NULL && data != NULL) { + THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL; + destr(data); + found_nonzero = 1; + } + } + } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { + free(THREAD_GETMEM_NC(self, p_specific[i])); + THREAD_SETMEM_NC(self, p_specific[i], NULL); + } + } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); +} + +#if !(USE_TLS && HAVE___THREAD) + +/* Thread-specific data for libc. */ + +int +__pthread_internal_tsd_set (int key, const void * pointer) +{ + pthread_descr self = thread_self(); + + THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer); + return 0; +} + +void * +__pthread_internal_tsd_get (int key) +{ + pthread_descr self = thread_self(); + + return THREAD_GETMEM_NC(self, p_libc_specific[key]); +} + +void ** __attribute__ ((__const__)) +__pthread_internal_tsd_address (int key) +{ + pthread_descr self = thread_self(); + return &self->p_libc_specific[key]; +} + +#endif diff --git a/libpthread/linuxthreads.old/spinlock.c b/libpthread/linuxthreads.old/spinlock.c new file mode 100644 index 0000000..24c81d4 --- /dev/null +++ b/libpthread/linuxthreads.old/spinlock.c @@ -0,0 +1,723 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Internal locks */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +libpthread_hidden_proto(nanosleep) + +static void __pthread_acquire(int * spinlock); + +static __inline__ void __pthread_release(int * spinlock) +{ + WRITE_MEMORY_BARRIER(); + *spinlock = __LT_SPINLOCK_INIT; + __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); +} + + +/* The status field of a spinlock is a pointer whose least significant + bit is a locked flag. + + Thus the field values have the following meanings: + + status == 0: spinlock is free + status == 1: spinlock is taken; no thread is waiting on it + + (status & 1) == 1: spinlock is taken and (status & ~1L) is a + pointer to the first waiting thread; other + waiting threads are linked via the p_nextlock + field. + (status & 1) == 0: same as above, but spinlock is not taken. + + The waiting list is not sorted by priority order. + Actually, we always insert at top of list (sole insertion mode + that can be performed without locking). + For __pthread_unlock, we perform a linear search in the list + to find the highest-priority, oldest waiting thread. + This is safe because there are no concurrent __pthread_unlock + operations -- only the thread that locked the mutex can unlock it. */ + + +void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; + int successful_seizure, spurious_wakeup_count; + int spin_count; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + /* First try it without preparation. Maybe it's a completely + uncontested lock. */ + if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) + return; + + spurious_wakeup_count = 0; + spin_count = 0; + + /* On SMP, try spinning to get the lock. */ +#if 0 + if (__pthread_smp_kernel) { + int max_count = lock->__spinlock * 2 + 10; + + if (max_count > MAX_ADAPTIVE_SPIN_COUNT) + max_count = MAX_ADAPTIVE_SPIN_COUNT; + + for (spin_count = 0; spin_count < max_count; spin_count++) { + if (((oldstatus = lock->__status) & 1) == 0) { + if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) + { + if (spin_count) + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + READ_MEMORY_BARRIER(); + return; + } + } +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); + } + + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + } +#endif + +again: + + /* No luck, try once more or suspend. */ + + do { + oldstatus = lock->__status; + successful_seizure = 0; + + if ((oldstatus & 1) == 0) { + newstatus = oldstatus | 1; + successful_seizure = 1; + } else { + if (self == NULL) + self = thread_self(); + newstatus = (long) self | 1; + } + + if (self != NULL) { + THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); + /* Make sure the store in p_nextlock completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend with guard against spurious wakeup. + This can happen in pthread_cond_timedwait_relative, when the thread + wakes up due to timeout and is still on the condvar queue, and then + locks the queue to remove itself. At that point it may still be on the + queue, and may be resumed by a condition signal. */ + + if (!successful_seizure) { + for (;;) { + suspend(self); + if (self->p_nextlock != NULL) { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + goto again; + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + READ_MEMORY_BARRIER(); +#endif +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus; + pthread_descr thr, * ptr, * maxptr; + int maxprio; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + return 0; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + WRITE_MEMORY_BARRIER(); + +again: + while ((oldstatus = lock->__status) == 1) { + if (__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, 0)) + return 0; + } + + /* Find thread in waiting queue with maximal priority */ + ptr = (pthread_descr *) &lock->__status; + thr = (pthread_descr) (oldstatus & ~1L); + maxprio = 0; + maxptr = ptr; + + /* Before we iterate over the wait queue, we need to execute + a read barrier, otherwise we may read stale contents of nodes that may + just have been inserted by other processors. One read barrier is enough to + ensure we have a stable list; we don't need one for each pointer chase + through the list, because we are the owner of the lock; other threads + can only add nodes at the front; if a front node is consistent, + the ones behind it must also be. */ + + READ_MEMORY_BARRIER(); + + while (thr != 0) { + if (thr->p_priority >= maxprio) { + maxptr = ptr; + maxprio = thr->p_priority; + } + ptr = &(thr->p_nextlock); + thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); + } + + /* Remove max prio thread from waiting list. */ + if (maxptr == (pthread_descr *) &lock->__status) { + /* If max prio thread is at head, remove it with compare-and-swap + to guard against concurrent lock operation. This removal + also has the side effect of marking the lock as released + because the new status comes from thr->p_nextlock whose + least significant bit is clear. */ + thr = (pthread_descr) (oldstatus & ~1L); + if (! __compare_and_swap_with_release_semantics + (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) + goto again; + } else { + /* No risk of concurrent access, remove max prio thread normally. + But in this case we must also flip the least significant bit + of the status to mark the lock as released. */ + thr = (pthread_descr)((long)*maxptr & ~1L); + *maxptr = thr->p_nextlock; + + /* Ensure deletion from linked list completes before we + release the lock. */ + WRITE_MEMORY_BARRIER(); + + do { + oldstatus = lock->__status; + } while (!__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, oldstatus & ~1L)); + } + + /* Wake up the selected waiting thread. Woken thread can check + its own p_nextlock field for NULL to detect that it has been removed. No + barrier is needed here, since restart() and suspend() take + care of memory synchronization. */ + + thr->p_nextlock = NULL; + restart(thr); + + return 0; +#endif +} + +/* + * Alternate fastlocks do not queue threads directly. Instead, they queue + * these wait queue node structures. When a timed wait wakes up due to + * a timeout, it can leave its wait node in the queue (because there + * is no safe way to remove from the quue). Some other thread will + * deallocate the abandoned node. + */ + + +struct wait_node { + struct wait_node *next; /* Next node in null terminated linked list */ + pthread_descr thr; /* The thread waiting with this node */ + int abandoned; /* Atomic flag */ +}; + +static long wait_node_free_list; +static int wait_node_free_list_spinlock; + +/* Allocate a new node from the head of the free list using an atomic + operation, or else using malloc if that list is empty. A fundamental + assumption here is that we can safely access wait_node_free_list->next. + That's because we never free nodes once we allocate them, so a pointer to a + node remains valid indefinitely. */ + +static struct wait_node *wait_node_alloc(void) +{ + struct wait_node *new_node = 0; + + __pthread_acquire(&wait_node_free_list_spinlock); + if (wait_node_free_list != 0) { + new_node = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) new_node->next; + } + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + + if (new_node == 0) + return malloc(sizeof *wait_node_alloc()); + + return new_node; +} + +/* Return a node to the head of the free list using an atomic + operation. */ + +static void wait_node_free(struct wait_node *wn) +{ + __pthread_acquire(&wait_node_free_list_spinlock); + wn->next = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) wn; + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + return; +} + +#if defined HAS_COMPARE_AND_SWAP + +/* Remove a wait node from the specified queue. It is assumed + that the removal takes place concurrently with only atomic insertions at the + head of the queue. */ + +static void wait_node_dequeue(struct wait_node **pp_head, + struct wait_node **pp_node, + struct wait_node *p_node) +{ + /* If the node is being deleted from the head of the + list, it must be deleted using atomic compare-and-swap. + Otherwise it can be deleted in the straightforward way. */ + + if (pp_node == pp_head) { + /* We don't need a read barrier between these next two loads, + because it is assumed that the caller has already ensured + the stability of *p_node with respect to p_node. */ + + long oldvalue = (long) p_node; + long newvalue = (long) p_node->next; + + if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) + return; + + /* Oops! Compare and swap failed, which means the node is + no longer first. We delete it using the ordinary method. But we don't + know the identity of the node which now holds the pointer to the node + being deleted, so we must search from the beginning. */ + + for (pp_node = pp_head; p_node != *pp_node; ) { + pp_node = &(*pp_node)->next; + READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ + } + } + + *pp_node = p_node->next; + return; +} + +#endif + +void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; +#endif + struct wait_node wait_node; + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int suspend_needed = 0; + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) lock->__status; + wait_node.thr = self; + lock->__status = (long) &wait_node; + suspend_needed = 1; + } + + __pthread_release(&lock->__spinlock); + + if (suspend_needed) + suspend (self); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + wait_node.thr = self; + newstatus = (long) &wait_node; + } + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend. Note that unlike in __pthread_lock, we don't worry + here about spurious wakeup. That's because this lock is not + used in situations where that can happen; the restart can + only come from the previous lock owner. */ + + if (oldstatus != 0) + suspend(self); + + READ_MEMORY_BARRIER(); +#endif +} + +/* Timed-out lock operation; returns 0 to indicate timeout. */ + +int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime) +{ + long oldstatus = 0; +#if defined HAS_COMPARE_AND_SWAP + long newstatus; +#endif + struct wait_node *p_wait_node = wait_node_alloc(); + + /* Out of memory, just give up and do ordinary lock. */ + if (p_wait_node == 0) { + __pthread_alt_lock(lock, self); + return 1; + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) lock->__status; + p_wait_node->thr = self; + lock->__status = (long) p_wait_node; + oldstatus = 1; /* force suspend */ + } + + __pthread_release(&lock->__spinlock); + goto suspend; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + p_wait_node->thr = self; + newstatus = (long) p_wait_node; + } + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + suspend: +#endif + + /* If we did not get the lock, do a timed suspend. If we wake up due + to a timeout, then there is a race; the old lock owner may try + to remove us from the queue. This race is resolved by us and the owner + doing an atomic testandset() to change the state of the wait node from 0 + to 1. If we succeed, then it's a timeout and we abandon the node in the + queue. If we fail, it means the owner gave us the lock. */ + + if (oldstatus != 0) { + if (timedsuspend(self, abstime) == 0) { + if (!testandset(&p_wait_node->abandoned)) + return 0; /* Timeout! */ + + /* Eat oustanding resume from owner, otherwise wait_node_free() below + will race with owner's wait_node_dequeue(). */ + suspend(self); + } + } + + wait_node_free(p_wait_node); + + READ_MEMORY_BARRIER(); + + return 1; /* Got the lock! */ +} + +void __pthread_alt_unlock(struct _pthread_fastlock *lock) +{ + struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; + struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; + int maxprio; + + WRITE_MEMORY_BARRIER(); + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + } +#endif + + while (1) { + + /* If no threads are waiting for this lock, try to just + atomically release it. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + if (lock->__status == 0 || lock->__status == 1) { + lock->__status = 0; + break; + } + } +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif + +#if defined HAS_COMPARE_AND_SWAP + { + long oldstatus = lock->__status; + if (oldstatus == 0 || oldstatus == 1) { + if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) + break; + else + continue; + } + } +#endif + + /* Process the entire queue of wait nodes. Remove all abandoned + wait nodes and put them into the global free queue, and + remember the one unabandoned node which refers to the thread + having the highest priority. */ + + pp_max_prio = pp_node = pp_head; + p_max_prio = p_node = *pp_head; + maxprio = INT_MIN; + + READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ + + while (p_node != (struct wait_node *) 1) { + int prio; + + if (p_node->abandoned) { + /* Remove abandoned node. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_node = p_node->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_node, p_node); +#endif + wait_node_free(p_node); + /* Note that the next assignment may take us to the beginning + of the queue, to newly inserted nodes, if pp_node == pp_head. + In that case we need a memory barrier to stabilize the first of + these new nodes. */ + p_node = *pp_node; + if (pp_node == pp_head) + READ_MEMORY_BARRIER(); /* No stale reads through p_node */ + continue; + } else if ((prio = p_node->thr->p_priority) >= maxprio) { + /* Otherwise remember it if its thread has a higher or equal priority + compared to that of any node seen thus far. */ + maxprio = prio; + pp_max_prio = pp_node; + p_max_prio = p_node; + } + + /* This canno6 jump backward in the list, so no further read + barrier is needed. */ + pp_node = &p_node->next; + p_node = *pp_node; + } + + /* If all threads abandoned, go back to top */ + if (maxprio == INT_MIN) + continue; + + /* Now we want to to remove the max priority thread's wait node from + the list. Before we can do this, we must atomically try to change the + node's abandon state from zero to nonzero. If we succeed, that means we + have the node that we will wake up. If we failed, then it means the + thread timed out and abandoned the node in which case we repeat the + whole unlock operation. */ + + if (!testandset(&p_max_prio->abandoned)) { +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_max_prio = p_max_prio->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); +#endif + restart(p_max_prio->thr); + break; + } + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif +} + + +/* Compare-and-swap emulation with a spinlock */ + +#ifdef TEST_FOR_COMPARE_AND_SWAP +int __pthread_has_cas = 0; +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + +int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + int res; + + __pthread_acquire(spinlock); + + if (*ptr == oldval) { + *ptr = newval; res = 1; + } else { + res = 0; + } + + __pthread_release(spinlock); + + return res; +} + +#endif + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + READ_MEMORY_BARRIER(); + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + nanosleep(&tm, NULL); + cnt = 0; + } + } +} diff --git a/libpthread/linuxthreads.old/spinlock.h b/libpthread/linuxthreads.old/spinlock.h new file mode 100644 index 0000000..7117898 --- /dev/null +++ b/libpthread/linuxthreads.old/spinlock.h @@ -0,0 +1,218 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include + + +/* There are 2 compare and swap synchronization primitives with + different semantics: + + 1. compare_and_swap, which has acquire semantics (i.e. it + completes befor subsequent writes.) + 2. compare_and_swap_with_release_semantics, which has release + semantics (it completes after previous writes.) + + For those platforms on which they are the same. HAS_COMPARE_AND_SWAP + should be defined. For those platforms on which they are different, + HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ + +#ifndef HAS_COMPARE_AND_SWAP +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define HAS_COMPARE_AND_SWAP +#endif +#endif + +#if defined(TEST_FOR_COMPARE_AND_SWAP) + +extern int __pthread_has_cas; +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + if (__builtin_expect (__pthread_has_cas, 1)) + return __compare_and_swap(ptr, oldval, newval); + else + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#elif defined(HAS_COMPARE_AND_SWAP) + +#ifdef IMPLEMENT_TAS_WITH_CAS +#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) +#endif + +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +static __inline__ int +compare_and_swap_with_release_semantics (long * ptr, long oldval, + long newval, int * spinlock) +{ + return __compare_and_swap_with_release_semantics (ptr, oldval, + newval); +} + +#endif + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __compare_and_swap(ptr, oldval, newval); +} + +#else + +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#endif + +#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define compare_and_swap_with_release_semantics compare_and_swap +#define __compare_and_swap_with_release_semantics __compare_and_swap +#endif + +/* Internal locks */ + +extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self); +extern int __pthread_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + return (testandset(&lock->__spinlock) ? EBUSY : 0); + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! __compare_and_swap(&lock->__status, 0, 1)); + return 0; +#endif +} + +/* Variation of internal lock used for pthread_mutex_t, supporting + timed-out waits. Warning: do not mix these operations with the above ones + over the same lock object! */ + +extern void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self); + +extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime); + +extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int res = EBUSY; + + if (testandset(&lock->__spinlock) == 0) + { + if (lock->__status == 0) + { + lock->__status = 1; + WRITE_MEMORY_BARRIER(); + res = 0; + } + lock->__spinlock = __LT_SPINLOCK_INIT; + } + return res; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); + return 0; +#endif +} + +/* Operations on pthread_atomic, which is defined in internals.h */ + +static __inline__ long atomic_increment(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ long atomic_decrement(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ void +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) +{ + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } +} diff --git a/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h new file mode 100644 index 0000000..97c3839 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h @@ -0,0 +1,127 @@ +/* Machine-dependent pthreads configuration and inline functions. + Alpha version. + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#ifdef __linux__ +# include +#else +# include +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__("$30"); + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret, temp; + + __asm__ __volatile__( + "/* Inline spinlock test & set */\n" + "1:\t" + "ldl_l %0,%3\n\t" + "bne %0,2f\n\t" + "or $31,1,%1\n\t" + "stl_c %1,%2\n\t" + "beq %1,1b\n" + "2:\tmb\n" + "/* End spinlock test & set */" + : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) + : "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Begin allocating thread stacks at this address. Default is to allocate + them just below the initial program stack. */ +#define THREAD_STACK_START_ADDRESS 0x40000000000 + + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self __asm__("$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ +{ \ + register pthread_descr __self __asm__("$16") = (descr); \ + __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ +} + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "/* Inline compare & swap */\n" + "1:\t" + "ldq_l %0,%4\n\t" + "cmpeq %0,%2,%0\n\t" + "beq %0,2f\n\t" + "mov %3,%0\n\t" + "stq_c %0,%1\n\t" + "beq %0,1b\n\t" + "2:\tmb\n" + "/* End compare & swap */" + : "=&r"(ret), "=m"(*p) + : "r"(oldval), "r"(newval), "m"(*p) + : "memory"); + + return ret; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h new file mode 100644 index 0000000..14eb6f6 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h @@ -0,0 +1,69 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + register unsigned int ret; + +#if defined(__thumb__) + void *pc; + __asm__ __volatile__( + ".align 0\n" + "\tbx pc\n" + "\tnop\n" + "\t.arm\n" + "\tswp %0, %2, [%3]\n" + "\torr %1, pc, #1\n" + "\tbx %1\n" + "\t.force_thumb" + : "=r"(ret), "=r"(pc) + : "0"(1), "r"(spinlock)); +#else + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); +#endif + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h new file mode 100644 index 0000000..5735d0e --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h @@ -0,0 +1,73 @@ +/* Machine-dependent pthreads configuration and inline functions. + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +static __inline__ int +_test_and_set (int *p, int v) +{ + int result; + + __asm__ __volatile__( + "/* Inline test and set */\n" + " xchg %[old], %[mem], %[new]" + : [old] "=&r"(result) + : [mem] "r"(p), [new] "r"(v) + : "memory"); + + return result; +} + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set(spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + long int result; + + __asm__ __volatile__( + "/* Inline compare and swap */\n" + "1: ssrf 5\n" + " ld.w %[result], %[mem]\n" + " eor %[result], %[old]\n" + " brne 2f\n" + " stcond %[mem], %[new]\n" + " brne 1b\n" + "2:" + : [result] "=&r"(result), [mem] "=m"(*p) + : "m"(*p), [new] "r"(newval), [old] "r"(oldval) + : "cc", "memory"); + + return result == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h new file mode 100644 index 0000000..e81ecff --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h @@ -0,0 +1,76 @@ +/* Machine-dependent pthreads configuration and inline functions. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#include + +/* Spinlock implementation; required. */ +/* The semantics of the TESTSET instruction cannot be guaranteed. We cannot + easily move all locks used by linux kernel to non-cacheable memory. + EXCPT 0x4 is used to trap into kernel to do the atomic testandset. + It's ugly. But it's the only thing we can do now. + The handler of EXCPT 0x4 expects the address of the lock is passed through + R0. And the result is returned by R0. */ +PT_EI long int +testandset (int *spinlock) +{ + long int res; + + __asm__ __volatile__ ( + "CALL (%4);" + : "=q0" (res), "=m" (*spinlock) + : "qA" (spinlock), "m" (*spinlock), "a" (ATOMIC_XCHG32), "q1" (1) + : "RETS", "cc", "memory"); + + return res; +} + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + __asm__ __volatile__ ( + "CALL (%5);" + : "=q0" (readval), "=m" (*p) + : "qA" (p), + "q1" (oldval), + "q2" (newval), + "a" (ATOMIC_CAS32), + "m" (*p) + : "RETS", "memory", "cc"); + return readval == oldval; +} + +#ifdef SHARED +# define PTHREAD_STATIC_FN_REQUIRE(name) +#else +# define PTHREAD_STATIC_FN_REQUIRE(name) __asm__ (".globl " "_"#name); +#endif + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h new file mode 100644 index 0000000..6d626fb --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h @@ -0,0 +1,70 @@ +/* Machine-dependent pthreads configuration and inline functions. + CRIS version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +PT_EI long int +testandset (int *spinlock) +{ + register unsigned long int ret; + + /* Note the use of a dummy output of *spinlock to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + +#ifdef __arch_v32 + __asm__ __volatile__("clearf p\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bcs 0b\n\t" + "clearf p" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "memory"); +#else /* not __arch_v32 */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "memory"); +#endif /* __arch_v32 */ + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + I don't trust register variables, so let's do this the safe way. */ +#define CURRENT_STACK_FRAME \ + ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h new file mode 100644 index 0000000..9c9d0d7 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h @@ -0,0 +1,70 @@ +/* Machine-dependent pthreads configuration and inline functions. + FR-V version. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Alexandre Oliva + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int i = 1; + __asm__ ("swap%I0 %M0, %1" : "+m"(*(volatile int *)spinlock), "+r"(i)); + return i; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* This symbol is defined by the ABI as the stack size requested by + the main program. */ +extern char __stacksize; +#define ARCH_STACK_MAX_SIZE ((unsigned long)&__stacksize) + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") + +/* Return the thread descriptor for the current thread. */ +register struct _pthread_descr_struct *THREAD_SELF __asm__ ("gr29"); +#define THREAD_SELF THREAD_SELF + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + (THREAD_SELF = descr) + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h new file mode 100644 index 0000000..121f496 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h @@ -0,0 +1,58 @@ +/* Machine-dependent pthreads configuration and inline functions. + H8/300 version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__( + "sub.w %0,%0\n\t" + "stc ccr,@-sp\n\t" + "orc #0x80,ccr\n\t" + "bld #0,@%2\n\t" + "bset #0,@%2\n\t" + "rotxl.w %0\n\t" + "ldc @sp+,ccr\n\t" + :"=r"(ret),"=m"(*spinlock) + :"g"(spinlock) + :"cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h new file mode 100644 index 0000000..a6256c5 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h @@ -0,0 +1,147 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline __attribute__((visibility("hidden"))) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* See if we can optimize for newer cpus... */ +#if defined __GNUC__ && __GNUC__ >= 2 && \ + (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \ + defined __athlon__ || defined __k8__) + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +#if defined(__ASSUME_LDT_WORKS) && __ASSUME_LDT_WORKS > 0 +#include "useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#else /* Generic i386 implementation */ + +extern int compare_and_swap_is_available (void); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +PT_EI int +compare_and_swap_is_available (void) +{ + int changed; + int oldflags; + /* get EFLAGS */ + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (oldflags) : ); + /* Flip AC bit in EFLAGS. */ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags ^ 0x40000) : "cc"); + /* reread EFLAGS */ + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (changed) : ); + /* See if bit changed. */ + changed = (changed ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags) : "cc"); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* Generic i386 implementation */ + +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/tls.h b/libpthread/linuxthreads.old/sysdeps/i386/tls.h new file mode 100644 index 0000000..8534cab --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/i386/tls.h @@ -0,0 +1,185 @@ +/* Definition for thread-local data handling. linuxthreads/i386 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ +} tcbhead_t; +#endif + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +# define TLS_DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result) \ + : "0" (__NR_modify_ldt), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ + "d" (sizeof (ldt_entry))); \ + __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \ +}) + +# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + if (secondcall) \ + ldt_entry.entry_number = ({ int _gs; \ + __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ + (_gs & 0xffff) >> 3; }); \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result), "=m" (ldt_entry.entry_number) \ + : "0" (__NR_set_thread_area), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ + __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_SET_THREAD_AREA (descr, firstcall) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \ + __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; }) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 0) +# endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + int __gs; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + if (__builtin_expect (__gs, 7) != -1) \ + { \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + __gs = 0; \ + } \ + __gs; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/useldt.h b/libpthread/linuxthreads.old/sysdeps/i386/useldt.h new file mode 100644 index 0000000..ca5677c --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/i386/useldt.h @@ -0,0 +1,307 @@ +/* Special definitions for ix86 machine using segment register based + thread descriptor. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __ASSEMBLER__ +#include /* For offsetof. */ +#include /* For abort(). */ + + +/* We don't want to include the kernel header. So duplicate the + information. */ + +/* Structure passed on `modify_ldt' call. */ +struct modify_ldt_ldt_s +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* System call to set LDT entry. */ +extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + + +/* Initialize the thread-unique value. Two possible ways to do it. */ + +#define DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ + abort (); \ + __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +#else +# define USETLS_EBX_ARG "b" +# define USETLS_LOAD_EBX +#endif + +/* When using the new set_thread_area call, we don't need to change %gs + because we inherited the value set up in the main thread by TLS setup. + We need to extract that value and set up the same segment in this + thread. */ +#if USE_TLS +# define DO_SET_THREAD_AREA_REUSE(nr) 1 +#else +/* Without TLS, we do the initialization of the main thread, where NR == 0. */ +# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) +#endif +#define DO_SET_THREAD_AREA(descr, nr) \ +({ \ + int __gs; \ + if (DO_SET_THREAD_AREA_REUSE (nr)) \ + { \ + __asm__ ("movw %%gs, %w0" : "=q" (__gs)); \ + struct modify_ldt_ldt_s ldt_entry = \ + { (__gs & 0xffff) >> 3, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ + if (__result == 0) \ + __asm__ ("movw %w0, %%gs" :: "q" (__gs)); \ + else \ + __gs = -1; \ + } \ + else \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ + if (__result == 0) \ + { \ + __gs = (ldt_entry.entry_number << 3) + 3; \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + } \ + else \ + __gs = -1; \ + } \ + __gs; \ +}) + +#if defined __ASSUME_SET_THREAD_AREA_SYSCALL +# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) +#elif defined __NR_set_thread_area +# define INIT_THREAD_SELF(descr, nr) \ +({ \ + if (__builtin_expect (__have_no_set_thread_area, 0) \ + || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ + && (__have_no_set_thread_area = 1))) \ + DO_MODIFY_LDT (descr, nr); \ +}) +/* Defined in pspinlock.c. */ +extern int __have_no_set_thread_area; +#else +# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) +#endif + +/* Free resources associated with thread descriptor. */ +#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +#define FREE_THREAD(descr, nr) do { } while (0) +#elif defined __NR_set_thread_area +#define FREE_THREAD(descr, nr) \ +{ \ + int __gs; \ + __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ + if (__builtin_expect (__gs & 4, 0)) \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ + } \ +} +#else +#define FREE_THREAD(descr, nr) \ +{ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ +} +#endif + +/* Read member of the thread descriptor directly. */ +#define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +#define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +#define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ +}) + +/* Set member of the thread descriptor directly. */ +#define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) +#endif + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 diff --git a/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h new file mode 100644 index 0000000..668057a --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h @@ -0,0 +1,135 @@ +/* Machine-dependent pthreads configuration and inline functions. + IA-64 version. + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#include +extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, void *__arg, ...); + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Make sure gcc doesn't try to be clever and move things around on + us. We need to use _exactly_ the address the user gave us, not some + alias that contains the same information. */ +#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) + +#ifndef ELF_MACHINE_NAME + +#define NEED_SEPARATE_REGISTER_STACK + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + r12 (sp) is the stack pointer. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__ ("sp"); + + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + + +/* Memory barrier */ +#define MEMORY_BARRIER() __sync_synchronize () + + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.acq %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, + long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.rel %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +#endif /* ELF_MACHINE_NAME */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchg4 %0=%1,%2" + : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) + : "r"(1), "m"(__atomic_fool_gcc (spinlock)) + : "memory"); + + return ret; +} + +/* Indicate that we are looping. */ +#define BUSY_WAIT_NOP __asm__ ("hint @pause") + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/ia64/tls.h b/libpthread/linuxthreads.old/sysdeps/ia64/tls.h new file mode 100644 index 0000000..81b41eb --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/ia64/tls.h @@ -0,0 +1,139 @@ +/* Definitions for thread-local data handling. linuxthreads/IA-64 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) +#else +# define INIT_SYSINFO 0 +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +# endif + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h new file mode 100644 index 0000000..295495b --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h @@ -0,0 +1,75 @@ +/* Machine-dependent pthreads configuration and inline functions. + m68k version. + Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__( +#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__m68000) + "tas %1; sne %0" +#else + "bset #7,%1; sne %0" +#endif + : "=dm"(ret), "=m"(*spinlock) + : "m"(*spinlock) + : "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + + +/* Compare-and-swap for semaphores. */ + +#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__mc68000) +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("casl %2, %3, %1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + + return ret; +} +#endif + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h new file mode 100644 index 0000000..fb1cc0e --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h @@ -0,0 +1,106 @@ +/* Machine-dependent pthreads configuration and inline functions. + + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + Based on the Alpha version by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. */ +static __inline__ int +__NTH (_test_and_set (int *p, int v)) +{ + int r, t; + + __asm__ __volatile__ + ("/* Inline test and set */\n" + "1:\n\t" + ".set push\n\t" + ".set mips2\n\t" + "ll %0,%3\n\t" + "move %1,%4\n\t" + "beq %0,%4,2f\n\t" + "sc %1,%2\n\t" + ".set pop\n\t" + "beqz %1,1b\n" + "2:\n\t" + "/* End test and set */" + : "=&r" (r), "=&r" (t), "=m" (*p) + : "m" (*p), "r" (v) + : "memory"); + + return r; +} + + +/* Spinlock implementation; required. */ + +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set (spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("$29"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret, temp; + + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" + ".set mips2\n\t" + "ll %1,%5\n\t" + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" + "sc %0,%2\n\t" + ".set pop\n\t" + "beqz %0,1b\n" + "2:\n\t" + "/* End compare & swap */" + : "=&r" (ret), "=&r" (temp), "=m" (*p) + : "r" (oldval), "r" (newval), "m" (*p) + : "memory"); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h new file mode 100644 index 0000000..1404550 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h @@ -0,0 +1,68 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +/* it is weird and dangerous to disable interrupt in userspace, but for nios + what else we can do before we have a swap like instruction? This is better + than nothing + */ +PT_EI long int +testandset (int *spinlock) +{ + unsigned int ret; + + __asm__ __volatile__("pfx 8\n\t" + "wrctl %1 ; disable interrupt\n\t" + "nop\n\t" + "nop\n\t" + "ld %0, [%2]\n\t" + "st [%2], %1\n\t" + "pfx 9\n\t" + "wrctl %1 ; enable interrupt\n\t" + "nop\n\t" + "nop\n\t" + : "=&r"(ret) + : "r"(1), "r"(spinlock) + : "memory"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +/* nios needs more because of reg windows */ +#define THREAD_MANAGER_STACK_SIZE (32*1024) +#define STACK_SIZE (32*1024) + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h new file mode 100644 index 0000000..061fa73 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h @@ -0,0 +1,58 @@ +/* Machine-dependent pthreads configuration and inline functions. + nios2 version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + unsigned int scratch; + long int ret=-2; + + __asm__ __volatile__( + "rdctl %0, status\n\t" + "and %0, %0, %1\n\t" + "wrctl status, %0 #disable interrupts\n\t" + "ldw %1, 0(%4)\n\t" + "stw %3, 0(%4)\n\t" + "ori %0, %0, 1\n\t" + "wrctl status, %0 #enable interrupts\n\t" + : "=&r"(scratch), "=r"(ret) + : "1"(ret), "r"(1), "r"(spinlock) + : "memory"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h new file mode 100644 index 0000000..561f895 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h @@ -0,0 +1,102 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 0000000..78593ac --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,416 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +#if defined _LIBC && !defined NOT_IN_libc +#include +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef pthread_mutex_t __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize an adaptive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_adaptive(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_ADAPTIVE_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_adaptive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_ADAPTIVE_NP); \ + __pthread_mutex_init (&(NAME), &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME), &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# define BP_SYM(sym) sym +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 0000000..2b889e6 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,73 @@ +/* libc-internal interface for thread-specific data. LinuxThreads version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include + +/* Fast thread-specific data internal to libc. */ +enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, + _LIBC_TSD_KEY_DL_ERROR, + _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, + _LIBC_TSD_KEY_N }; + +#include +#include + +#include + +#if defined(USE_TLS) && USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include + +#else + +# include + +# ifndef SHARED +extern void ** __pthread_internal_tsd_address (int); +extern void *__pthread_internal_tsd_get (int); +extern int __pthread_internal_tsd_set (int, const void *); + +weak_extern (__pthread_internal_tsd_address) +weak_extern (__pthread_internal_tsd_get) +weak_extern (__pthread_internal_tsd_set) +# endif + +#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; +#define __libc_tsd_address(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_address, \ + (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) +#define __libc_tsd_get(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_get, \ + (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) +#define __libc_tsd_set(KEY, VALUE) \ + __libc_maybe_call2 (pthread_internal_tsd_set, \ + (_LIBC_TSD_KEY_##KEY, (VALUE)), \ + (__libc_tsd_##KEY##_data = (VALUE), 0)) + +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h new file mode 100644 index 0000000..faec63b --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h @@ -0,0 +1,142 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __need_schedparam +#include + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef unsigned long int pthread_t; + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h b/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h new file mode 100644 index 0000000..ce6d10f --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); + int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h b/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h new file mode 100644 index 0000000..870e37f --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h @@ -0,0 +1,695 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#include + +#define __need_sigset_t +#include +#include +#include + + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_SIZE. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_SIZE + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on unitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; +extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + clockid_t *__clock_id) __THROW; +#endif +#endif + + +/* Functions for handling signals. */ +#include + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/tls.h b/libpthread/linuxthreads.old/sysdeps/pthread/tls.h new file mode 100644 index 0000000..6a23ec0 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/pthread/tls.h @@ -0,0 +1,81 @@ +/* Definition for thread-local data handling. Generic version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* By default no TLS support is available. This is signaled by the + absence of the symbol USE_TLS. */ +#undef USE_TLS + + +/* An architecture-specific version of this file has to defined a + number of symbols: + + TLS_TCB_AT_TP or TLS_DTV_AT_TP + + The presence of one of these symbols signals which variant of + the TLS ABI is used. There are in the moment two variants + available: + + * the thread pointer points to a thread control block + + * the thread pointer points to the dynamic thread vector + + + TLS_TCB_SIZE + + This is the size of the thread control block structure. How + this is actually defined depends on the ABI. The thread control + block could be internal descriptor of the thread library or + just a data structure which allows finding the DTV. + + TLS_INIT_TCB_SIZE + + Similarly, but this value is only used at startup and in the + dynamic linker itself. There are no threads in use at that time. + + + TLS_TCB_ALIGN + + Alignment requirements for the TCB structure. + + TLS_INIT_TCB_ALIGN + + Similarly, but for the structure used at startup time. + + + INSTALL_DTV(tcb, init_dtv) + + This macro must install the given initial DTV into the thread control + block TCB. The normal runtime functionality must then be able to + use the value. + + + TLS_INIT_TP(tcb, firstcall) + + This macro must initialize the thread pointer to enable normal TLS + operation. The first parameter is a pointer to the thread control + block. The second parameter specifies whether this is the first + call for the TCB. ld.so calls this macro more than once. + + + THREAD_DTV() + + This macro returns the address of the DTV of the current thread. + This normally is done using the the thread register which points + to the dtv or the TCB (from which the DTV can found). + */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h new file mode 100644 index 0000000..793f80b --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h @@ -0,0 +1,82 @@ +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +/* Return the thread descriptor for the current thread. */ +struct _pthread_descr_struct; +#define THREAD_SELF \ + ({ struct _pthread_descr_struct *self; \ + __asm__("stc gbr,%0" : "=r" (self)); self;}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh/tls.h b/libpthread/linuxthreads.old/sysdeps/sh/tls.h new file mode 100644 index 0000000..7bc2980 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sh/tls.h @@ -0,0 +1,117 @@ +/* Definition for thread-local data handling. linuxthreads/SH version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ +} tcbhead_t; + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Get system call information. */ +# include + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + int result; \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ ("ldc %0,gbr" : : "r" (_descr)); \ + \ + 0; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch b/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch new file mode 100644 index 0000000..bf57e80 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch @@ -0,0 +1,30 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_ARCH_DIR:=$(top_srcdir)libpthread/linuxthreads.old/sysdeps/sh64 +libpthread_ARCH_OUT:=$(top_builddir)libpthread/linuxthreads.old/sysdeps/sh64 + +libpthread_ARCH_SRC:=$(wildcard $(libpthread_ARCH_DIR)/*.c) +libpthread_ARCH_OBJ:=$(patsubst $(libpthread_ARCH_DIR)/%.c,$(libpthread_ARCH_OUT)/%.o,$(libpthread_ARCH_SRC)) + +libpthread-a-y+=$(libpthread_ARCH_OBJ) +libpthread-so-y+=$(libpthread_ARCH_OBJ:.o=.os) + +libpthread-multi-y+=$(libpthread_ARCH_SRC) + +objclean-y+=libpthread_arch_objclean + +# We need to build as SHcompact for tas.. +$(libpthread_ARCH_OBJ): %.o : %.c + $(compile.c:32media=compact) + +$(libpthread_ARCH_OBJ:.o=.os): %.os : %.c + $(compile.c:32media=compact) + +libpthread_arch_objclean: + $(do_rm) $(addprefix $(libpthread_ARCH_OUT)/*., o os) diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c new file mode 100644 index 0000000..bd2c401 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c @@ -0,0 +1,47 @@ +/* Cloned for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ + +/* Machine-dependent pthreads configuration and inline functions. + SH5 version. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "pt-machine.h" + +/* Spinlock implementation; required. */ + +/* The SH5 does not have a suitable test-and-set instruction (SWAP only + operates on an aligned quad word). So we use the SH4 version instead. + This must be seperately compiled in SHcompact mode, so it cannot be + inline. */ + +long int testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h new file mode 100644 index 0000000..b87448a --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h @@ -0,0 +1,39 @@ +/* Cloned for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ + +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h new file mode 100644 index 0000000..ab90810 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "sparc32/pt-machine.h" +#else +# include "sparc64/pt-machine.h" +#endif diff --git a/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 0000000..43c05f2 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,83 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 0000000..815d70e --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h new file mode 100644 index 0000000..34de63b --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h @@ -0,0 +1,52 @@ +/* + * sysdeps/v850/pt-machine.h -- v850-specific pthread definitions + * + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __stack_pointer +register char *__stack_pointer __asm__ ("sp"); + +#define HAS_COMPARE_AND_SWAP + +/* Atomically: If *PTR == OLD, set *PTR to NEW and return true, + otherwise do nothing and return false. */ +PT_EI int +__compare_and_swap (long *ptr, long old, long new) +{ + unsigned long psw; + + /* disable interrupts */ + __asm__ __volatile__ ("stsr psw, %0; di" : "=&r" (psw)); + + if (likely (*ptr == old)) + { + *ptr = new; + __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ + return 1; + } + else + { + __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ + return 0; + } +} +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h new file mode 100644 index 0000000..ce07bbb --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,85 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +# include /* For offsetof. */ +# include /* For abort(). */ +# include + + +# ifndef PT_EI +# define PT_EI __extern_always_inline +# endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *__spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*__spinlock) + : "0"(1), "m"(*__spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *__p, long int __oldval, long int __newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*__p), "=a" (readval) + : "r" (__newval), "m" (*__p), "a" (__oldval) + : "memory"); + return ret; +} + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h b/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h new file mode 100644 index 0000000..5e7239d --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/x86-64 version. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + long int _result; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_descr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h new file mode 100644 index 0000000..acd4d10 --- /dev/null +++ b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h @@ -0,0 +1,48 @@ +/* Machine-dependent pthreads configuration and inline functions. + Xtensa version. + + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Memory barrier. */ +#define MEMORY_BARRIER() __asm__ ("memw" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int unused = 0; + return INTERNAL_SYSCALL (xtensa, , 4, SYS_XTENSA_ATOMIC_SET, + spinlock, 1, unused); +} + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + +#endif /* _PT_MACHINE_H */ diff --git a/libpthread/linuxthreads.old/wrapsyscall.c b/libpthread/linuxthreads.old/wrapsyscall.c new file mode 100644 index 0000000..713e7e5 --- /dev/null +++ b/libpthread/linuxthreads.old/wrapsyscall.c @@ -0,0 +1,228 @@ +/* Wrapper arpund system calls to provide cancelation points. + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef __PIC__ +/* We need a hook to force this file to be linked in when static + libpthread is used. */ +const int __pthread_provide_wrappers = 0; +#endif + + +#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + result = __libc_##name params; \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + +#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + va_list ap; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + va_start (ap, last_arg); \ + result = __libc_##name params; \ + va_end (ap); \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + + +/* close(2). */ +CANCELABLE_SYSCALL (int, close, (int fd), (fd)) + + +/* fcntl(2). */ +CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), + (fd, cmd, va_arg (ap, long int)), cmd) + + +/* fsync(2). */ +CANCELABLE_SYSCALL (int, fsync, (int fd), (fd)) + + +/* lseek(2). */ +CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), + (fd, offset, whence)) + +#ifdef __UCLIBC_HAS_LFS__ +/* lseek64(2). */ +CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), + (fd, offset, whence)) +#endif + +#if defined(__NR_msync) && defined(__ARCH_USE_MMU__) + +/* msync(2). */ +CANCELABLE_SYSCALL (int, msync, (void *addr, size_t length, int flags), + (addr, length, flags)) +#endif + + +/* nanosleep(2). */ +libpthread_hidden_proto(nanosleep) +CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time, + struct timespec *remaining), + (requested_time, remaining)) +libpthread_hidden_def(nanosleep) + + +/* open(2). */ +CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), + (pathname, flags, va_arg (ap, mode_t)), flags) + + +#ifdef __UCLIBC_HAS_LFS__ +/* open64(3). */ +CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), + (pathname, flags, va_arg (ap, mode_t)), flags) +#endif + +/* pause(2). */ +CANCELABLE_SYSCALL (int, pause, (void), ()) + + +/* Enable this if enabling these in syscalls.c */ +/* pread(3). */ +CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, + off_t offset), + (fd, buf, count, offset)) + + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_pread64 +/* pread64(3). */ +CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, + off64_t offset), + (fd, buf, count, offset)) +#endif + +/* pwrite(3). */ +CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, + off_t offset), + (fd, buf, n, offset)) + + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_pwrited64 +/* pwrite64(3). */ +CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, + off64_t offset), + (fd, buf, n, offset)) +#endif + +/* read(2). */ +CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), + (fd, buf, count)) + + +/* system(3). */ +CANCELABLE_SYSCALL (int, system, (const char *line), (line)) + + +/* tcdrain(2). */ +CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd)) + + +/* wait(2). */ +CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) + + +/* waitpid(2). */ +libpthread_hidden_proto(waitpid) +CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, + int options), + (pid, stat_loc, options)) +libpthread_hidden_def(waitpid) + + +/* write(2). */ +CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), + (fd, buf, n)) + +#if defined __UCLIBC_HAS_SOCKET__ +/* The following system calls are thread cancellation points specified + in XNS. */ + +/* accept(2). */ +CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, + socklen_t *addr_len), + (fd, addr, addr_len)) + +/* connect(2). */ +CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, + socklen_t len), + (fd, addr, len)) + +/* recv(2). */ +CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), + (fd, buf, n, flags)) + +/* recvfrom(2). */ +CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, + __SOCKADDR_ARG addr, socklen_t *addr_len), + (fd, buf, n, flags, addr, addr_len)) + +/* recvmsg(2). */ +CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), + (fd, message, flags)) + +/* send(2). */ +CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, + int flags), + (fd, buf, n, flags)) + +/* sendmsg(2). */ +CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, + int flags), + (fd, message, flags)) + +/* sendto(2). */ +CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, + int flags, __CONST_SOCKADDR_ARG addr, + socklen_t addr_len), + (fd, buf, n, flags, addr, addr_len)) +#endif /* __UCLIBC_HAS_SOCKET__ */ diff --git a/libpthread/linuxthreads.old_db/Banner b/libpthread/linuxthreads.old_db/Banner new file mode 100644 index 0000000..6f4f3f8 --- /dev/null +++ b/libpthread/linuxthreads.old_db/Banner @@ -0,0 +1 @@ +libthread_db work sponsored by Alpha Processor Inc diff --git a/libpthread/linuxthreads.old_db/Makefile b/libpthread/linuxthreads.old_db/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/libpthread/linuxthreads.old_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/linuxthreads.old_db/Makefile.in b/libpthread/linuxthreads.old_db/Makefile.in new file mode 100644 index 0000000..1c89a9f --- /dev/null +++ b/libpthread/linuxthreads.old_db/Makefile.in @@ -0,0 +1,76 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# Get the thread include dependencies and shared object name +CFLAGS-linuxthreads.old_db := -DNOT_IN_libc -DLIBPTHREAD_SO="\"libpthread.so.$(MAJOR_VERSION)\"" + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols) +ifeq ($(DOSTRIP),y) +LDFLAGS-libthread_db.so += -Wl,-s +endif + +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/linuxthreads.old_db +libthread_db_OUT := $(top_builddir)libpthread/linuxthreads.old_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/*.c) + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.os) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so + +#ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) +#else +#$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db.oS | $(libc.depend) +# $(call linkm.so,$(libthread_db_FULL_NAME),1) +#endif + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libthread_db_OUT)/libthread_db.oS: $(libthread_db_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +include/thread_db.h: + $(do_ln) ../$(PTDIR)_db/$(@F) $(top_builddir)$@ + +linuxthreads_db_headers := include/thread_db.h +$(linuxthreads_db_headers): $(wildcard $(addprefix include/config/linuxthreads/,old.h new.h)) +headers-$(PTHREADS_DEBUG_SUPPORT) += $(linuxthreads_db_headers) + +objclean-y += libthread_db_clean +headers_clean-y += linuxthreads_db_headers_clean + +linuxthreads_db_headers_clean: + $(do_rm) $(top_builddir)include/thread_db.h + +libthread_db_clean: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o os oS a) diff --git a/libpthread/linuxthreads.old_db/Versions b/libpthread/linuxthreads.old_db/Versions new file mode 100644 index 0000000..063493c --- /dev/null +++ b/libpthread/linuxthreads.old_db/Versions @@ -0,0 +1,24 @@ +libthread_db { + GLIBC_2.1.3 { + # t* + td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; + td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; + td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; + td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; + td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; + td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; + td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; + td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; + td_thr_tsd; td_thr_validate; + } + GLIBC_2.2.3 { + td_symbol_list; + } + GLIBC_2.3 { + td_thr_tls_get_addr; + } + GLIBC_2.3.3 { + td_thr_tlsbase; + } +} diff --git a/libpthread/linuxthreads.old_db/proc_service.h b/libpthread/linuxthreads.old_db/proc_service.h new file mode 100644 index 0000000..74136c0 --- /dev/null +++ b/libpthread/linuxthreads.old_db/proc_service.h @@ -0,0 +1,70 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include + +typedef enum +{ + PS_OK, /* generic "call succeeded" */ + PS_ERR, /* generic. */ + PS_BADPID, /* bad process handle */ + PS_BADLID, /* bad lwp identifier */ + PS_BADADDR, /* bad address */ + PS_NOSYM, /* p_lookup() could not find given symbol */ + PS_NOFREGS + /* + * FPU register set not available for given + * lwp + */ +} ps_err_e; + + +struct ps_prochandle; /* user defined. */ + + +extern ps_err_e ps_pdread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); + +extern ps_err_e ps_pglobal_lookup(struct ps_prochandle *, + const char *object_name, const char *sym_name, psaddr_t *sym_addr); + + +extern ps_err_e ps_lgetregs(struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs(struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs(struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs(struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +extern pid_t ps_getpid (struct ps_prochandle *); + + +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/libpthread/linuxthreads.old_db/td_init.c b/libpthread/linuxthreads.old_db/td_init.c new file mode 100644 index 0000000..6f0e158 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_init.c @@ -0,0 +1,33 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +#ifndef NDEBUG +int __td_debug; +#endif + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_log.c b/libpthread/linuxthreads.old_db/td_log.c new file mode 100644 index 0000000..025273a --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_symbol_list.c b/libpthread/linuxthreads.old_db/td_symbol_list.c new file mode 100644 index 0000000..599c045 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_symbol_list.c @@ -0,0 +1,61 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ + [PTHREAD_THREADS_EVENTS] = "__pthread_threads_events", + [PTHREAD_LAST_EVENT] = "__pthread_last_event", + [PTHREAD_HANDLES_NUM] = "__pthread_handles_num", + [PTHREAD_HANDLES] = "__pthread_handles", + [PTHREAD_KEYS] = "pthread_keys", + [LINUXTHREADS_PTHREAD_THREADS_MAX] = "__linuxthreads_pthread_threads_max", + [LINUXTHREADS_PTHREAD_KEYS_MAX] = "__linuxthreads_pthread_keys_max", + [LINUXTHREADS_PTHREAD_SIZEOF_DESCR] = "__linuxthreads_pthread_sizeof_descr", + [LINUXTHREADS_CREATE_EVENT] = DOT "__linuxthreads_create_event", + [LINUXTHREADS_DEATH_EVENT] = DOT "__linuxthreads_death_event", + [LINUXTHREADS_REAP_EVENT] = DOT "__linuxthreads_reap_event", + [LINUXTHREADS_INITIAL_REPORT_EVENTS] = "__linuxthreads_initial_report_events", + [LINUXTHREADS_VERSION] = "__linuxthreads_version", + [NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +int +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + assert (idx >= 0 && idx < NUM_MESSAGES); + return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr); +} diff --git a/libpthread/linuxthreads.old_db/td_ta_clear_event.c b/libpthread/linuxthreads.old_db/td_ta_clear_event.c new file mode 100644 index 0000000..cbb7ddc --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_clear_event.c @@ -0,0 +1,53 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_delete.c b/libpthread/linuxthreads.old_db/td_ta_delete.c new file mode 100644 index 0000000..0e6ec17 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_delete.c @@ -0,0 +1,58 @@ +/* Detach to target process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. */ + if (ta == NULL || __td_agent_list == NULL) + return TD_BADTA; + + /* Remove the handle from the list. */ + if (ta == __td_agent_list->ta) + /* It's the first element of the list. */ + __td_agent_list = __td_agent_list->next; + else + { + /* We have to search for it. */ + struct agent_list *runp = __td_agent_list; + + while (runp->next != NULL && runp->next->ta != ta) + runp = runp->next; + + if (runp->next == NULL) + /* It's not a valid decriptor since it is not in the list. */ + return TD_BADTA; + + runp->next = runp->next->next; + } + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_enable_stats.c b/libpthread/linuxthreads.old_db/td_ta_enable_stats.c new file mode 100644 index 0000000..1d4c34a --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_event_addr.c b/libpthread/linuxthreads.old_db/td_ta_event_addr.c new file mode 100644 index 0000000..8bce35a --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_event_addr.c @@ -0,0 +1,73 @@ +/* Get event address. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) +{ + td_err_e res = TD_NOEVENT; + int idx = -1; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + idx = LINUXTHREADS_CREATE_EVENT; + break; + + case TD_DEATH: + idx = LINUXTHREADS_DEATH_EVENT; + break; + + case TD_REAP: + idx = LINUXTHREADS_REAP_EVENT; + break; + + default: + /* Event cannot be handled. */ + break; + } + + /* Now get the address. */ + if (idx != -1) + { + psaddr_t taddr; + + if (td_lookup (ta->ph, idx, &taddr) == PS_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + + res = TD_OK; + } + else + res = TD_ERR; + } + + return res; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c b/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c new file mode 100644 index 0000000..ba535da --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c @@ -0,0 +1,128 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg) +{ + /* XXX I cannot think of another way but using a static variable. */ + static td_thrhandle_t th; + td_eventbuf_t event; + psaddr_t addr; + + LOG ("td_ta_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + if (ps_pdread (ta->ph, ta->pthread_last_event, + &addr, sizeof (void *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* If the pointer is NULL no event occurred. */ + if (addr == 0) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + { + /* Oh well, this means the last event was already read. So + we have to look for any other event. */ + struct pthread_handle_struct handles[ta->pthread_threads_max]; + int num; + int i; + + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now read the handles. */ + if (ps_pdread (ta->ph, ta->handles, handles, + ta->pthread_threads_max * sizeof (handles[0])) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + for (i = 0; i < ta->pthread_threads_max && num > 0; ++i) + { + if (handles[i].h_descr == NULL) + /* No entry here. */ + continue; + + /* First count this active thread. */ + --num; + + if (handles[i].h_descr == addr) + /* We already handled this. */ + continue; + + /* Read the event data for this thread. */ + if (ps_pdread (ta->ph, + ((char *) handles[i].h_descr + + offsetof (struct _pthread_descr_struct, + p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; + + if (event.eventnum != TD_EVENT_NONE) + { + /* We found a thread with an unreported event. */ + addr = handles[i].h_descr; + break; + } + } + + /* If we haven't found any other event signal this to the user. */ + if (event.eventnum == TD_EVENT_NONE) + return TD_NOMSG; + } + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = &th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c b/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c new file mode 100644 index 0000000..839b56b --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta, int *np) +{ + psaddr_t addr; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable `__pthread_handles_num'. */ + if (td_lookup (ta->ph, PTHREAD_HANDLES_NUM, &addr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_get_ph.c b/libpthread/linuxthreads.old_db/td_ta_get_ph.c new file mode 100644 index 0000000..23d3285 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_get_stats.c b/libpthread/linuxthreads.old_db/td_ta_get_stats.c new file mode 100644 index 0000000..6bf2f53 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c b/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c new file mode 100644 index 0000000..c57f25a --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c @@ -0,0 +1,78 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + struct pthread_handle_struct phc; + struct _pthread_descr_struct pds; + int pthread_threads_max; + + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Make the following expression a bit smaller. */ + pthread_threads_max = ta->pthread_threads_max; + + /* We can compute the entry in the handle array we want. */ + if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Test whether this entry is in use. */ + if (phc.h_descr == NULL) + { + if (pt % pthread_threads_max == 0) + { + /* The initial thread always exists but the thread library + might not yet be initialized. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_BADTH; + } + + /* Next test: get the descriptor to see whether this is not an old + thread handle. */ + if (ps_pdread (ta->ph, phc.h_descr, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_tid != pt) + return TD_BADTH; + + if (pds.p_terminated != 0) + return TD_NOTHR; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc.h_descr; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c b/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c new file mode 100644 index 0000000..2be1e3d --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c @@ -0,0 +1,90 @@ +/* Which thread is running on an lwp? + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + int pthread_threads_max = ta->pthread_threads_max; + size_t sizeof_descr = ta->sizeof_descr; + struct pthread_handle_struct phc[pthread_threads_max]; + size_t cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * pthread_threads_max) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Get the entries one after the other and find out whether the ID + matches. */ + for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { + struct _pthread_descr_struct pds; + +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if ((pds.p_pid ?: ps_getpid (ta->ph)) == lwpid) + { + /* Found it. Now fill in the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc[cnt].h_descr; + + return TD_OK; + } + } + else if (cnt == 0) + { + /* The initial thread always exists. But it might not yet be + initialized. Construct a value. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_NOLWP; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_new.c b/libpthread/linuxthreads.old_db/td_ta_new.c new file mode 100644 index 0000000..2b0b68b --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_new.c @@ -0,0 +1,149 @@ +/* Attach to target process. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +struct agent_list *__td_agent_list; + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t addr; + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + struct agent_list *elemp; + + LOG ("td_ta_new"); + + /* Get the global event mask. This is one of the variables which + are new in the thread library to enable debugging. If it is + not available we cannot debug. */ + if (td_lookup (ps, PTHREAD_THREADS_EVENTS, &addr) != PS_OK) + return TD_NOLIBTHREAD; + + /* Check whether the versions match. */ + if (td_lookup (ps, LINUXTHREADS_VERSION, &versaddr) != PS_OK) + return TD_VERSION; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + versbuf[sizeof (versbuf) - 1] = '\0'; + if (strcmp (versbuf, VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Remember the address. */ + (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr; + + /* Get the pointer to the variable pointing to the thread descriptor + with the last event. */ + if (td_lookup (ps, PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event) != PS_OK) + { + free_return: + free (*ta); + return TD_ERR; + } + + /* Get the pointer to the variable containing the number of active + threads. */ + if (td_lookup (ps, PTHREAD_HANDLES_NUM, &(*ta)->pthread_handles_num) + != PS_OK) + goto free_return; + + /* See whether the library contains the necessary symbols. */ + if (td_lookup (ps, PTHREAD_HANDLES, &addr) != PS_OK) + goto free_return; + + (*ta)->handles = (struct pthread_handle_struct *) addr; + + + if (td_lookup (ps, PTHREAD_KEYS, &addr) != PS_OK) + goto free_return; + + /* Cast to the right type. */ + (*ta)->keys = (struct pthread_key_struct *) addr; + + /* Find out about the maximum number of threads. Old implementations + don't provide this information. In this case we assume that the + debug library is compiled with the same values. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_THREADS_MAX, &addr) != PS_OK) + (*ta)->pthread_threads_max = PTHREAD_THREADS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_threads_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* Similar for the maximum number of thread local data keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_KEYS_MAX, &addr) != PS_OK) + (*ta)->pthread_keys_max = PTHREAD_KEYS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* And for the size of the second level arrays for the keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + else + { + if (ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK) + goto free_return; + /* Don't let bogons in the inferior make us mess ourselves. */ + if ((*ta)->sizeof_descr > sizeof (struct _pthread_descr_struct)) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + } + + /* Now add the new agent descriptor to the list. */ + elemp = (struct agent_list *) malloc (sizeof (struct agent_list)); + if (elemp == NULL) + { + /* Argh, now that everything else worked... */ + free (*ta); + return TD_MALLOC; + } + + /* We don't care for thread-safety here. */ + elemp->ta = *ta; + elemp->next = __td_agent_list; + __td_agent_list = elemp; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_reset_stats.c b/libpthread/linuxthreads.old_db/td_ta_reset_stats.c new file mode 100644 index 0000000..b3ddbd0 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_set_event.c b/libpthread/linuxthreads.old_db/td_ta_set_event.c new file mode 100644 index 0000000..6edb38e --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_set_event.c @@ -0,0 +1,53 @@ +/* Globally enable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c b/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c new file mode 100644 index 0000000..408e763 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_thr_iter.c b/libpthread/linuxthreads.old_db/td_ta_thr_iter.c new file mode 100644 index 0000000..771a12d --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_thr_iter.c @@ -0,0 +1,173 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +static int +handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + size_t cnt, pthread_descr descr) +{ + struct _pthread_descr_struct pds; + size_t sizeof_descr = ta->sizeof_descr; + td_thrhandle_t th; + + if (descr == NULL) + { + /* No descriptor (yet). */ + if (cnt == 0) + { + /* This is the main thread. Create a fake descriptor. */ + memset (&pds, '\0', sizeof (pds)); + + /* Empty thread descriptor the thread library would create. */ + pds.p_self = &pds; + pds.p_nextlive = pds.p_prevlive = &pds; + pds.p_tid = PTHREAD_THREADS_MAX; + /* The init code also sets up p_lock, p_errnop, p_herrnop, and + p_userstack but this should not be necessary here. */ + + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = NULL; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; + } + else if (cnt == 1) + /* The manager is not yet started. No big deal. */ + return TD_OK; + else + /* For every other thread this should not happen. */ + return TD_ERR; + } + + if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* The manager thread must be handled special. The descriptor + exists but the thread only gets created when the first + `pthread_create' call is issued. A clear indication that this + happened is when the p_pid field is non-zero. */ + if (cnt == 1 && pds.p_pid == 0) + return TD_OK; + + /* Now test whether this thread matches the specified + conditions. */ + + /* Only if the priority level is as high or higher. */ + if (pds.p_priority < ti_pri) + return TD_OK; + + /* Test the state. + XXX This is incomplete. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + /* XXX For now we ignore threads which are not running anymore. + The reason is that gdb tries to get the registers and fails. + In future we should have a special mode of the thread library + in which we keep the process around until the actual join + operation happened. */ + if (pds.p_exited != 0) + return TD_OK; + + /* Yep, it matches. Call the callback function. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = descr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + int pthread_threads_max; + struct pthread_handle_struct *phc; + td_err_e result = TD_OK; + int cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_threads_max = ta->pthread_threads_max; + phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) + * pthread_threads_max); + + /* First read only the main thread and manager thread information. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * 2) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now handle these descriptors. */ + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0, + phc[0].h_descr); + if (result != TD_OK) + return result; + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1, + phc[1].h_descr); + if (result != TD_OK) + return result; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles + 2, &phc[2], + (sizeof (struct pthread_handle_struct) + * (pthread_threads_max - 2))) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Now get all descriptors, one after the other. */ + for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt, + phc[cnt].h_descr); + if (result != TD_OK) + break; + } + + return result; +} diff --git a/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c b/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c new file mode 100644 index 0000000..7ad98dd --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c @@ -0,0 +1,55 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback, + void *cbdata_p) +{ + struct pthread_key_struct *keys; + int pthread_keys_max; + int cnt; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_keys_max = ta->pthread_keys_max; + keys = (struct pthread_key_struct *) alloca (sizeof (keys[0]) + * pthread_keys_max); + + /* Read all the information about the keys. */ + if (ps_pdread (ta->ph, ta->keys, keys, + sizeof (keys[0]) * pthread_keys_max) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_keys_max; ++cnt) + if (keys[cnt].in_use + /* Return with an error if the callback returns a nonzero value. */ + && callback (cnt, keys[cnt].destr, cbdata_p) != 0) + return TD_DBERR; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_clear_event.c b/libpthread/linuxthreads.old_db/td_thr_clear_event.c new file mode 100644 index 0000000..147d180 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_clear_event.c @@ -0,0 +1,62 @@ +/* Disable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_clear_event"); + + /* If the thread descriptor has not yet been constructed do not do + anything. */ + if (th->th_unique == NULL) + return TD_OK; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_dbresume.c b/libpthread/linuxthreads.old_db/td_thr_dbresume.c new file mode 100644 index 0000000..7b7f6ee --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c b/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c new file mode 100644 index 0000000..ef66802 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_event_enable.c b/libpthread/linuxthreads.old_db/td_thr_event_enable.c new file mode 100644 index 0000000..407f3fc --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_event_enable.c @@ -0,0 +1,57 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + if (th->th_unique == NULL) + { + psaddr_t addr; + + if (td_lookup (th->th_ta_p->ph, LINUXTHREADS_INITIAL_REPORT_EVENTS, + &addr) != PS_OK) + /* Cannot read the symbol. This should not happen. */ + return TD_ERR; + + if (ps_pdwrite (th->th_ta_p->ph, addr, &onoff, sizeof (int)) != PS_OK) + return TD_ERR; + + return TD_OK; + } + + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_report_events)), + &onoff, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c b/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c new file mode 100644 index 0000000..bf4ddd4 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c @@ -0,0 +1,65 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_eventbuf_t event; + + LOG ("td_thr_event_getmsg"); + + /* If the thread descriptor has not yet been created there cannot be + any event. */ + if (th->th_unique == NULL) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_get_info.c b/libpthread/linuxthreads.old_db/td_thr_get_info.c new file mode 100644 index 0000000..4666bda --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_get_info.c @@ -0,0 +1,83 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_get_info"); + + /* Handle the case when the thread library is not yet initialized. */ + if (th->th_unique == NULL) + { + memset (&pds, '\0', sizeof (pds)); + pds.p_tid = PTHREAD_THREADS_MAX; + } + else + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + /* We have to handle the manager thread special since the thread + descriptor in older versions is not fully initialized. */ + if (pds.p_nr == 1) + { + infop->ti_tid = th->th_ta_p->pthread_threads_max * 2 + 1; + infop->ti_type = TD_THR_SYSTEM; + infop->ti_state = TD_THR_ACTIVE; + } + else + { + infop->ti_tid = pds.p_tid; + infop->ti_tls = (char *) pds.p_specific; + infop->ti_pri = pds.p_priority; + infop->ti_type = TD_THR_USER; + + if (! pds.p_terminated) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if (! pds.p_detached) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + } + + /* Initialization which are the same in both cases. */ + infop->ti_lid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + infop->ti_ta_p = th->th_ta_p; + infop->ti_startfunc = pds.p_start_args.start_routine; + memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask, + sizeof (td_thr_events_t)); + infop->ti_traceme = pds.p_report_events != 0; + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_getfpregs.c b/libpthread/linuxthreads.old_db/td_thr_getfpregs.c new file mode 100644 index 0000000..31c55c8 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_getfpregs.c @@ -0,0 +1,58 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getfpregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_getgregs.c b/libpthread/linuxthreads.old_db/td_thr_getgregs.c new file mode 100644 index 0000000..a9ec6a3 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_getgregs.c @@ -0,0 +1,58 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getgregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (gregs, '\0', sizeof (prgregset_t)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_getxregs.c b/libpthread/linuxthreads.old_db/td_thr_getxregs.c new file mode 100644 index 0000000..39cd73c --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_getxregsize.c b/libpthread/linuxthreads.old_db/td_thr_getxregsize.c new file mode 100644 index 0000000..5d8ac28 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_set_event.c b/libpthread/linuxthreads.old_db/td_thr_set_event.c new file mode 100644 index 0000000..1e1def5 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_set_event.c @@ -0,0 +1,62 @@ +/* Enable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_set_event"); + + /* What shall we do if no thread descriptor exists but the user + wants to set an event? */ + if (th->th_unique == NULL) + return TD_NOTALLOC; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_setfpregs.c b/libpthread/linuxthreads.old_db/td_thr_setfpregs.c new file mode 100644 index 0000000..e4d9ec6 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_setfpregs.c @@ -0,0 +1,47 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetfpregs (th->th_ta_p->ph, pid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_setgregs.c b/libpthread/linuxthreads.old_db/td_thr_setgregs.c new file mode 100644 index 0000000..8c021a4 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_setgregs.c @@ -0,0 +1,47 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_setprio.c b/libpthread/linuxthreads.old_db/td_thr_setprio.c new file mode 100644 index 0000000..98d202d --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_setsigpending.c b/libpthread/linuxthreads.old_db/td_thr_setsigpending.c new file mode 100644 index 0000000..98e3014 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_setxregs.c b/libpthread/linuxthreads.old_db/td_thr_setxregs.c new file mode 100644 index 0000000..da77ab3 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c b/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c new file mode 100644 index 0000000..8b0eb81 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c b/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c new file mode 100644 index 0000000..a28b074 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c @@ -0,0 +1,69 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th __attribute__ ((unused)), + void *map_address __attribute__ ((unused)), + size_t offset __attribute__ ((unused)), + void **address __attribute__ ((unused))) +{ +#if USE_TLS + size_t modid; + union dtv pdtv, *dtvp; + + LOG ("td_thr_tls_get_addr"); + + /* Get the DTV pointer from the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, + &((struct _pthread_descr_struct *) th->th_unique)->p_header.data.dtvp, + &dtvp, sizeof dtvp) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Read the module ID from the link_map. */ + if (ps_pdread (th->th_ta_p->ph, + &((struct link_map *) map_address)->l_tls_modid, + &modid, sizeof modid) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Get the corresponding entry in the DTV. */ + if (ps_pdread (th->th_ta_p->ph, dtvp + modid, + &pdtv, sizeof (union dtv)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if (pdtv.pointer == TLS_DTV_UNALLOCATED) + /* There is not much we can do. */ + return TD_NOTALLOC; + + *address = (char *) pdtv.pointer + offset; + + return TD_OK; +#else + return TD_ERR; +#endif +} diff --git a/libpthread/linuxthreads.old_db/td_thr_tsd.c b/libpthread/linuxthreads.old_db/td_thr_tsd.c new file mode 100644 index 0000000..2ab71c5 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_tsd.c @@ -0,0 +1,81 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + struct _pthread_descr_struct pds; + struct pthread_key_struct *keys = th->th_ta_p->keys; + struct pthread_key_struct key; + int pthread_keys_max = th->th_ta_p->pthread_keys_max; + int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size; + unsigned int idx1st; + unsigned int idx2nd; + void *p; + + LOG ("td_thr_tsd"); + + /* If there is no thread descriptor there cannot be any thread + specific data. */ + if (th->th_unique == NULL) + return TD_BADKEY; + + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check correct value of key. */ + if (tk >= pthread_keys_max) + return TD_BADKEY; + + /* Get the key entry. */ + if (ps_pdread (th->th_ta_p->ph, &keys[tk], &key, + sizeof (struct pthread_key_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fail if this key is not at all used. */ + if (! key.in_use) + return TD_BADKEY; + + /* Compute the indeces. */ + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Check the pointer to the second level array. */ + if (pds.p_specific[idx1st] == NULL) + return TD_NOTSD; + + /* Now get the real key. + XXX I don't know whether it's correct but there is currently no + easy way to determine whether a key was never set or the value + is NULL. We return an error whenever the value is NULL. */ + if (ps_pdread (th->th_ta_p->ph, &pds.p_specific[idx1st][idx2nd], &p, + sizeof (void *)) != PS_OK) + return TD_ERR; + + if (p != NULL) + *data = p; + + return p != NULL ? TD_OK : TD_NOTSD; +} diff --git a/libpthread/linuxthreads.old_db/td_thr_validate.c b/libpthread/linuxthreads.old_db/td_thr_validate.c new file mode 100644 index 0000000..2cf7727 --- /dev/null +++ b/libpthread/linuxthreads.old_db/td_thr_validate.c @@ -0,0 +1,69 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + struct pthread_handle_struct *handles = th->th_ta_p->handles; + int pthread_threads_max = th->th_ta_p->pthread_threads_max; + int cnt; + struct pthread_handle_struct phc; + + LOG ("td_thr_validate"); + + /* A special case: if the program just starts up the handle is + NULL. */ + if (th->th_unique == NULL) + { + /* Read the first handle. If the pointer to the thread + descriptor is not NULL this is an error. */ + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return phc.h_descr == NULL ? TD_OK : TD_NOTHR; + } + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles) + { + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (phc.h_descr != NULL && phc.h_descr == th->th_unique) + { + struct _pthread_descr_struct pds; + + if (ps_pdread (th->th_ta_p->ph, phc.h_descr, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* XXX There should be another test using the TID but this is + currently not available. */ + return pds.p_terminated != 0 ? TD_NOTHR : TD_OK; + } + } + + return TD_ERR; +} diff --git a/libpthread/linuxthreads.old_db/thread_db.h b/libpthread/linuxthreads.old_db/thread_db.h new file mode 100644 index 0000000..c115399 --- /dev/null +++ b/libpthread/linuxthreads.old_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the LinuxThreads library. It is + modelled closely after the interface with same names in Solaris with + the goal to share the same code in the debugger. */ +#include +#include +#include +#include + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Unused. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + void *__map_address, size_t __offset, + void **__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/libpthread/linuxthreads.old_db/thread_dbP.h b/libpthread/linuxthreads.old_db/thread_dbP.h new file mode 100644 index 0000000..b120c42 --- /dev/null +++ b/libpthread/linuxthreads.old_db/thread_dbP.h @@ -0,0 +1,110 @@ +/* Private header for thread debug library. */ +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#define __FORCE_GLIBC +#include +#include +#include +#include "proc_service.h" +#include "thread_db.h" +#include "internals.h" + + +/* Indices for the symbol names. */ +enum + { + PTHREAD_THREADS_EVENTS = 0, + PTHREAD_LAST_EVENT, + PTHREAD_HANDLES_NUM, + PTHREAD_HANDLES, + PTHREAD_KEYS, + LINUXTHREADS_PTHREAD_THREADS_MAX, + LINUXTHREADS_PTHREAD_KEYS_MAX, + LINUXTHREADS_PTHREAD_SIZEOF_DESCR, + LINUXTHREADS_CREATE_EVENT, + LINUXTHREADS_DEATH_EVENT, + LINUXTHREADS_REAP_EVENT, + LINUXTHREADS_INITIAL_REPORT_EVENTS, + LINUXTHREADS_VERSION, + NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Some cached information. */ + + /* Address of the `__pthread_handles' array. */ + struct pthread_handle_struct *handles; + + /* Address of the `pthread_kyes' array. */ + struct pthread_key_struct *keys; + + /* Maximum number of threads. */ + int pthread_threads_max; + + /* Maximum number of thread-local data keys. */ + int pthread_keys_max; + + /* Size of 2nd level array for thread-local data keys. */ + int pthread_key_2ndlevel_size; + + /* Sizeof struct _pthread_descr_struct. */ + int sizeof_descr; + + /* Pointer to the `__pthread_threads_events' variable in the target. */ + psaddr_t pthread_threads_eventsp; + + /* Pointer to the `__pthread_last_event' variable in the target. */ + psaddr_t pthread_last_event; + + /* Pointer to the `__pthread_handles_num' variable. */ + psaddr_t pthread_handles_num; +}; + + +/* Type used internally to keep track of thread agent descriptors. */ +struct agent_list +{ + td_thragent_t *ta; + struct agent_list *next; +}; + +/* List of all known descriptors. */ +extern struct agent_list *__td_agent_list attribute_hidden; + +/* Function used to test for correct thread agent pointer. */ +static __inline__ int +ta_ok (const td_thragent_t *ta) +{ + struct agent_list *runp = __td_agent_list; + + if (ta == NULL) + return 0; + + while (runp != NULL && runp->ta != ta) + runp = runp->next; + + return runp != NULL; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern int td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) attribute_hidden; + +#endif /* thread_dbP.h */ diff --git a/libpthread/linuxthreads/.cvsignore b/libpthread/linuxthreads/.cvsignore new file mode 100644 index 0000000..688daf4 --- /dev/null +++ b/libpthread/linuxthreads/.cvsignore @@ -0,0 +1,3 @@ +.cvsignore +*.os +Makefile.in diff --git a/libpthread/linuxthreads/Makefile b/libpthread/linuxthreads/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/libpthread/linuxthreads/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/linuxthreads/Makefile.in b/libpthread/linuxthreads/Makefile.in new file mode 100644 index 0000000..947dea9 --- /dev/null +++ b/libpthread/linuxthreads/Makefile.in @@ -0,0 +1,136 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-dir_linuxthreads := -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-linuxthreads := $(CFLAGS-dir_linuxthreads) $(SSP_ALL_CFLAGS) + +CFLAGS-libpthread/linuxthreads/sysdeps/$(TARGET_ARCH)/ := $(CFLAGS-linuxthreads) +CFLAGS-libpthread/linuxthreads/sysdeps/unix/sysv/linux/ := $(CFLAGS-linuxthreads) +CFLAGS-libpthread/linuxthreads/sysdeps/pthread/ := $(CFLAGS-linuxthreads) + +# This stuff will not compile without at least -O1 +# psm: can't handle this here, could maybe search for -O0 in CFLAGS +# and append -O1 if found +#CFLAGS:=$(CFLAGS:-O0=-O1) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LIBS-libpthread.so := $(LIBS) $(ldso) + +START_FILE-libpthread.so := $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) + +libpthread_FULL_NAME := libpthread-$(VERSION).so + +libpthread_DIR := $(top_srcdir)libpthread/linuxthreads +libpthread_OUT := $(top_builddir)libpthread/linuxthreads + +-include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch + +pthread_arch_SRC := pspinlock +pthread_arch_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/%.c,$(pthread_arch_SRC)) +pthread_linux_SRC := fork pt-sigsuspend register-atfork unregister-atfork +pthread_linux_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/unix/sysv/linux/%.c,$(pthread_linux_SRC)) +pthread_sysdep_SRC := errno-loc herrno-loc ptlongjmp +pthread_sysdep_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/pthread/%.c,$(pthread_sysdep_SRC)) +pthread_SRC := \ + attr barrier cancel condvar errno events join pthread \ + lockfile manager mutex pt-machine ptcleanup \ + ptclock_gettime ptclock_settime ptfork pthandles \ + pthread_setegid pthread_seteuid pthread_setgid pthread_setregid \ + pthread_setresgid pthread_setresuid pthread_setreuid pthread_setuid \ + rwlock semaphore sighandler signals specific spinlock +pthread_SRC := $(patsubst %,$(libpthread_DIR)/%.c,$(pthread_SRC)) + +libpthread_static_SRC := pthread_atfork +libpthread_SRC := $(pthread_arch_SRC) $(pthread_linux_SRC) $(pthread_sysdep_SRC) $(pthread_SRC) +libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC)) + +# +# Stuff that goes into libc.so, not libpthread.so +# +#CFLAGS-OMIT-alloca_cutoff.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-libc-cancellation.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads) +libpthread_libc_CSRC := \ + forward.c libc-cancellation.c libc_pthread_init.c # alloca_cutoff.c +libpthread_libc_OBJ := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC)) +libc-static-y += $(libpthread_OUT)/libc_pthread_init.o +libc-shared-y += $(libpthread_libc_OBJ:.o=.oS) + +libpthread-static-y += $(patsubst %,$(libpthread_OUT)/%.o,$(libpthread_static_SRC)) + +libpthread-nonshared-y += $(patsubst %,$(libpthread_OUT)/%.oS,$(libpthread_static_SRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(libpthread_OBJ:.o=.os) $(libpthread-static-y:.o=.os) +else +libpthread-a-y += $(libpthread_OBJ) $(libpthread-static-y) +endif +libpthread-so-y += $(libpthread_OBJ:.o=.oS) + +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +#ifeq ($(DOMULTI),n) +$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) $(top_builddir)lib/libpthread_nonshared.a + $(call link.so,$(libpthread_FULL_NAME),$(MAJOR_VERSION)) +#else +#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend) $(top_builddir)lib/libpthread_nonshared.a +# $(call linkm.so,$(libpthread_FULL_NAME),$(MAJOR_VERSION)) +#endif + $(Q)$(RM) $@ + $(Q)cp $(top_srcdir)extra/scripts/format.lds $@ + $(Q)echo "GROUP ( $(notdir $@).$(MAJOR_VERSION) libpthread_nonshared.a )" >> $@ + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ + $(do_ar) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC) + $(Q)$(RM) $@ + $(compile-m) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +include/pthread.h: + $(do_ln) ../$(PTDIR)/sysdeps/pthread/$(@F) $(top_builddir)$@ +include/semaphore.h: + $(do_ln) ../$(PTDIR)/$(@F) $(top_builddir)$@ +include/bits/pthreadtypes.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/pthread/bits/$(@F) $(top_builddir)$@ + +linuxthreads_headers := include/pthread.h include/semaphore.h \ + include/bits/pthreadtypes.h +$(linuxthreads_headers): $(wildcard $(addprefix include/config/linuxthreads/,old.h new.h)) +headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers) + +objclean-y += libpthread_clean +headers_clean-y += linuxthreads_headers_clean +linuxthreads_headers_clean: + $(do_rm) $(addprefix $(top_builddir),$(linuxthreads_headers)) + +libpthread_clean: + $(do_rm) $(addprefix $(libpthread_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*. */*/*. */*/*/*.,$(d)$(e)))) diff --git a/libpthread/linuxthreads/alloca_cutoff.c b/libpthread/linuxthreads/alloca_cutoff.c new file mode 100644 index 0000000..ca064b3 --- /dev/null +++ b/libpthread/linuxthreads/alloca_cutoff.c @@ -0,0 +1,36 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include + +int +__libc_alloca_cutoff (size_t size) +{ + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self (); + return size <= LIBC_THREAD_GETMEM (self, p_alloca_cutoff); + } + + return size <= __MAX_ALLOCA_CUTOFF; +} diff --git a/libpthread/linuxthreads/attr.c b/libpthread/linuxthreads/attr.c new file mode 100644 index 0000000..52e115c --- /dev/null +++ b/libpthread/linuxthreads/attr.c @@ -0,0 +1,469 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of thread attributes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + + +int __pthread_attr_init(pthread_attr_t *attr) +{ + size_t ps = __getpagesize (); + + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; +#ifdef NEED_SEPARATE_REGISTER_STACK + attr->__guardsize = ps + ps; +#else + attr->__guardsize = ps; +#endif + attr->__stackaddr = NULL; + attr->__stackaddr_set = 0; + attr->__stacksize = STACK_SIZE - ps; + return 0; +} +strong_alias (__pthread_attr_init, pthread_attr_init) + +int __pthread_attr_destroy(pthread_attr_t *attr) +{ + return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) + +int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + if (detachstate < PTHREAD_CREATE_JOINABLE || + detachstate > PTHREAD_CREATE_DETACHED) + return EINVAL; + attr->__detachstate = detachstate; + return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) + +int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + *detachstate = attr->__detachstate; + return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) + +int __pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + int max_prio = __sched_get_priority_max(attr->__schedpolicy); + int min_prio = __sched_get_priority_min(attr->__schedpolicy); + + if (param->sched_priority < min_prio || param->sched_priority > max_prio) + return EINVAL; + memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) + +int __pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) + +int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + attr->__schedpolicy = policy; + return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) + +int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + *policy = attr->__schedpolicy; + return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) + +int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + attr->__inheritsched = inherit; + return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) + +int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + *inherit = attr->__inheritsched; + return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) + +int __pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + switch (scope) { + case PTHREAD_SCOPE_SYSTEM: + attr->__scope = scope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) + +int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + *scope = attr->__scope; + return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) + +int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +{ + /* The guard size must not be larger than the stack itself */ + if (guardsize >= attr->__stacksize) return EINVAL; + + attr->__guardsize = guardsize; + + return 0; +} +weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) + +int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +{ + *guardsize = attr->__guardsize; + return 0; +} +weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) + +#if 0 /* uClibc: deprecated stuff disabled */ +int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + attr->__stackaddr_set = 1; + return 0; +} +weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, + "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") + +int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ + *stackaddr = attr->__stackaddr; + return 0; +} +weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, + "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") +#endif + + +int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ +#ifdef FLOATING_STACKS + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; +#else + /* We have a fixed size limit. */ + if (stacksize > STACK_SIZE) + return EINVAL; +#endif + + /* We don't accept value smaller than PTHREAD_STACK_MIN. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +versioned_symbol (libpthread, __pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_3_3); + +# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3) + +int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ +# ifdef FLOATING_STACKS + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; +# else + /* We have a fixed size limit. */ + if (stacksize > STACK_SIZE) + return EINVAL; +# endif + + /* We don't accept value smaller than old PTHREAD_STACK_MIN. */ + if (stacksize < 16384) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} +compat_symbol (libpthread, __old_pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_1); +# endif +#endif + + +int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +{ + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) + +int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +#ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +#else + attr->__stackaddr = stackaddr; +#endif + attr->__stackaddr_set = 1; + } + + return err; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstack, pthread_attr_setstack) +#else +versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_3_3); +# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3) +int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __old_pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +# else + attr->__stackaddr = stackaddr; +# endif + attr->__stackaddr_set = 1; + } + + return err; +} + +compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_2); + +# endif +#endif + +int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr, + size_t *stacksize) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ +#ifndef _STACK_GROWS_UP + *stackaddr = (char *) attr->__stackaddr - attr->__stacksize; +#else + *stackaddr = attr->__stackaddr; +#endif + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstack, pthread_attr_getstack) + +int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + pthread_handle handle = thread_handle (thread); + pthread_descr descr; + int ret = 0; + + if (handle == NULL) + return ENOENT; + + descr = handle->h_descr; + + attr->__detachstate = (descr->p_detached + ? PTHREAD_CREATE_DETACHED + : PTHREAD_CREATE_JOINABLE); + + attr->__schedpolicy = __sched_getscheduler (descr->p_pid); + if (attr->__schedpolicy == -1) + return errno; + + if (__sched_getparam (descr->p_pid, + (struct sched_param *) &attr->__schedparam) != 0) + return errno; + + attr->__inheritsched = descr->p_inheritsched; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + +#ifdef _STACK_GROWS_DOWN +# ifdef USE_TLS + attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr + - descr->p_guardsize; +# else + attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr + - descr->p_guardsize; +# endif +#else +# ifdef USE_TLS + attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr; +# else + attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr; +# endif +#endif + attr->__guardsize = descr->p_guardsize; + attr->__stackaddr_set = descr->p_userstack; +#ifdef NEED_SEPARATE_REGISTER_STACK + if (descr->p_userstack == 0) + attr->__stacksize *= 2; + /* XXX This is awkward. The guard pages are in the middle of the + two stacks. We must count the guard size in the stack size since + otherwise the range of the stack area cannot be computed. */ + attr->__stacksize += attr->__guardsize; +#endif +#ifdef USE_TLS + attr->__stackaddr = descr->p_stackaddr; +#else +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *)(descr + 1); +# else + attr->__stackaddr = (char *)descr; +# endif +#endif + +#ifdef USE_TLS + if (attr->__stackaddr == NULL) +#else + if (descr == &__pthread_initial_thread) +#endif + { + /* Stack size limit. */ + struct rlimit rl; + + /* The safest way to get the top of the stack is to read + /proc/self/maps and locate the line into which + __libc_stack_end falls. */ + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + ret = errno; + /* We need the limit of the stack in any case. */ + else if (getrlimit (RLIMIT_STACK, &rl) != 0) + ret = errno; + else + { + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Until we found an entry (which should always be the case) + mark the result as a failure. */ + ret = ENOENT; + + char *line = NULL; + size_t linelen = 0; + uintptr_t last_to = 0; + + while (! feof_unlocked (fp)) + { + if (getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + uintptr_t from; + uintptr_t to; + if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) + continue; + if (from <= (uintptr_t) __libc_stack_end + && (uintptr_t) __libc_stack_end < to) + { + /* Found the entry. Now we have the info we need. */ + attr->__stacksize = rl.rlim_cur; +#ifdef _STACK_GROWS_UP + /* Don't check to enforce a limit on the __stacksize */ + attr->__stackaddr = (void *) from; +#else + attr->__stackaddr = (void *) to; + + /* The limit might be too high. */ + if ((size_t) attr->__stacksize + > (size_t) attr->__stackaddr - last_to) + attr->__stacksize = (size_t) attr->__stackaddr - last_to; +#endif + + /* We succeed and no need to look further. */ + ret = 0; + break; + } + last_to = to; + } + + fclose (fp); + free (line); + } + } + + return 0; + +} diff --git a/libpthread/linuxthreads/barrier.c b/libpthread/linuxthreads/barrier.c new file mode 100644 index 0000000..37d997c --- /dev/null +++ b/libpthread/linuxthreads/barrier.c @@ -0,0 +1,128 @@ +/* POSIX barrier implementation for LinuxThreads. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_descr self = thread_self(); + pthread_descr temp_wake_queue, th; + int result = 0; + + __pthread_lock(&barrier->__ba_lock, self); + + /* If the required number of threads have achieved rendezvous... */ + if (barrier->__ba_present >= barrier->__ba_required - 1) + { + /* ... then this last caller shall be the serial thread */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + /* Copy and clear wait queue and reset barrier. */ + temp_wake_queue = barrier->__ba_waiting; + barrier->__ba_waiting = NULL; + barrier->__ba_present = 0; + } + else + { + result = 0; + barrier->__ba_present++; + enqueue(&barrier->__ba_waiting, self); + } + + __pthread_unlock(&barrier->__ba_lock); + + if (result == 0) + { + /* Non-serial threads have to suspend */ + suspend(self); + /* We don't bother dealing with cancellation because the POSIX + spec for barriers doesn't mention that pthread_barrier_wait + is a cancellation point. */ + } + else + { + /* Serial thread wakes up all others. */ + while ((th = dequeue(&temp_wake_queue)) != NULL) + restart(th); + } + + return result; +} + +int +pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + if (count == 0) + return EINVAL; + + __pthread_init_lock(&barrier->__ba_lock); + barrier->__ba_required = count; + barrier->__ba_present = 0; + barrier->__ba_waiting = NULL; + return 0; +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + if (barrier->__ba_waiting != NULL) return EBUSY; + return 0; +} + +int +pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_destroy(pthread_barrierattr_t *attr) +{ + return 0; +} + +int +__pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/libpthread/linuxthreads/cancel.c b/libpthread/linuxthreads/cancel.c new file mode 100644 index 0000000..3435680 --- /dev/null +++ b/libpthread/linuxthreads/cancel.c @@ -0,0 +1,238 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread cancellation */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + + +int __pthread_setcancelstate(int state, int * oldstate) +{ + pthread_descr self = thread_self(); + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); + THREAD_SETMEM(self, p_cancelstate, state); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) + +int __pthread_setcanceltype(int type, int * oldtype) +{ + pthread_descr self = thread_self(); + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, type); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return oldtype; +} + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_canceltype, oldtype); +} + + +int pthread_cancel(pthread_t thread) +{ + pthread_handle handle = thread_handle(thread); + int pid; + int dorestart = 0; + pthread_descr th; + pthread_extricate_if *pextricate; + int already_canceled; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + + th = handle->h_descr; + + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { + __pthread_unlock(&handle->h_lock); + return 0; + } + + pextricate = th->p_extricate; + pid = th->p_pid; + + /* If the thread has registered an extrication interface, then + invoke the interface. If it returns 1, then we succeeded in + dequeuing the thread from whatever waiting object it was enqueued + with. In that case, it is our responsibility to wake it up. + And also to set the p_woken_by_cancel flag so the woken thread + can tell that it was woken by cancellation. */ + + if (pextricate != NULL) { + dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); + th->p_woken_by_cancel = dorestart; + } + + __pthread_unlock(&handle->h_lock); + + /* If the thread has suspended or is about to, then we unblock it by + issuing a restart, instead of a cancel signal. Otherwise we send + the cancel signal to unblock the thread from a cancellation point, + or to initiate asynchronous cancellation. The restart is needed so + we have proper accounting of restarts; suspend decrements the thread's + resume count, and restart() increments it. This also means that suspend's + handling of the cancel signal is obsolete. */ + + if (dorestart) + restart(th); + else + kill(pid, __pthread_sig_cancel); + + return 0; +} + +void pthread_testcancel(void) +{ + pthread_descr self = thread_self(); + if (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); +} + +void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); + THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +extern void __rpc_thread_destroy(void); +void __pthread_perform_cleanup(char *currentframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer *c = THREAD_GETMEM(self, p_cleanup); + struct _pthread_cleanup_buffer *last; + + if (c != NULL) + while (FRAME_LEFT (currentframe, c)) + { + last = c; + c = c->__prev; + + if (c == NULL || FRAME_LEFT (last, c)) + { + c = NULL; + break; + } + } + + while (c != NULL) + { + c->__routine(c->__arg); + + last = c; + c = c->__prev; + + if (FRAME_LEFT (last, c)) + break; + } + +#ifdef __UCLIBC_HAS_RPC__ + /* And the TSD which needs special help. */ + if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) + __rpc_thread_destroy (); +#endif +} diff --git a/libpthread/linuxthreads/condvar.c b/libpthread/linuxthreads/condvar.c new file mode 100644 index 0000000..d7b2e98 --- /dev/null +++ b/libpthread/linuxthreads/condvar.c @@ -0,0 +1,304 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* and Pavel Krauz (krauz@fsid.cvut.cz). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Condition variables */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int __pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) +{ + __pthread_init_lock(&cond->__c_lock); + cond->__c_waiting = NULL; + return 0; +} +strong_alias (__pthread_cond_init, pthread_cond_init) + +int __pthread_cond_destroy(pthread_cond_t *cond) +{ + if (cond->__c_waiting != NULL) return EBUSY; + return 0; +} +strong_alias (__pthread_cond_destroy, pthread_cond_destroy) + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int cond_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_cond_t *cond = obj; + int did_remove = 0; + + __pthread_lock(&cond->__c_lock, self); + did_remove = remove_from_queue(&cond->__c_waiting, th); + __pthread_unlock(&cond->__c_lock); + + return did_remove; +} + +int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Atomically enqueue thread for waiting, but only if it is not + canceled. If the thread is canceled, then it will fall through the + suspend call below, and then call pthread_exit without + having to worry about whether it is still on the condition variable queue. + This depends on pthread_cancel setting p_canceled before calling the + extricate function. */ + + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Check for cancellation again, to provide correct cancellation + point behavior */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} +strong_alias (__pthread_cond_wait, pthread_cond_wait) + +static int +pthread_cond_timedwait_relative(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + __volatile__ pthread_descr self = thread_self(); + int already_canceled = 0; + pthread_extricate_if extr; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Enqueue to wait on the condition and check for cancellation. */ + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + if (!timedsuspend(self, abstime)) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&cond->__c_lock, self); + was_on_queue = remove_from_queue(&cond->__c_waiting, self); + __pthread_unlock(&cond->__c_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + pthread_mutex_lock(mutex); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* The remaining logic is the same as in other cancellable waits, + such as pthread_join sem_wait or pthread_cond wait. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} + +int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + /* Indirect call through pointer! */ + return pthread_cond_timedwait_relative(cond, mutex, abstime); +} +strong_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + +int __pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_descr th; + + __pthread_lock(&cond->__c_lock, NULL); + th = dequeue(&cond->__c_waiting); + __pthread_unlock(&cond->__c_lock); + if (th != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_signal, pthread_cond_signal) + +int __pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_descr tosignal, th; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ + tosignal = cond->__c_waiting; + cond->__c_waiting = NULL; + __pthread_unlock(&cond->__c_lock); + /* Now signal each process in the queue */ + while ((th = dequeue(&tosignal)) != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast) + +int __pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) + +int __pthread_condattr_destroy(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) + +int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/libpthread/linuxthreads/descr.h b/libpthread/linuxthreads/descr.h new file mode 100644 index 0000000..24ec30b --- /dev/null +++ b/libpthread/linuxthreads/descr.h @@ -0,0 +1,270 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _DESCR_H +#define _DESCR_H 1 + +#define __need_res_state +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_TLS +#include +#endif +#include "uClibc-glue.h" + +/* Fast thread-specific data internal to libc. */ +enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, + _LIBC_TSD_KEY_DL_ERROR, + _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, + _LIBC_TSD_KEY_N }; + +/* The type of thread descriptors */ +typedef struct _pthread_descr_struct *pthread_descr; + + +/* Some more includes. */ +#include +#include + + +/* Arguments passed to thread creation routine */ +struct pthread_start_args { + void *(*start_routine)(void *); /* function to run */ + void *arg; /* its argument */ + sigset_t mask; /* initial signal mask for thread */ + int schedpolicy; /* initial scheduling policy (if any) */ + struct sched_param schedparam; /* initial scheduling parameters (if any) */ +}; + + +/* Callback interface for removing the thread from waiting on an + object if it is cancelled while waiting or about to wait. + This hold a pointer to the object, and a pointer to a function + which ``extricates'' the thread from its enqueued state. + The function takes two arguments: pointer to the wait object, + and a pointer to the thread. It returns 1 if an extrication + actually occured, and hence the thread must also be signalled. + It returns 0 if the thread had already been extricated. */ +typedef struct _pthread_extricate_struct { + void *pu_object; + int (*pu_extricate_func)(void *, pthread_descr); +} pthread_extricate_if; + + +/* Atomic counter made possible by compare_and_swap */ +struct pthread_atomic { + long p_count; + int p_spinlock; +}; + + +/* Context info for read write locks. The pthread_rwlock_info structure + is information about a lock that has been read-locked by the thread + in whose list this structure appears. The pthread_rwlock_context + is embedded in the thread context and contains a pointer to the + head of the list of lock info structures, as well as a count of + read locks that are untracked, because no info structure could be + allocated for them. */ +struct _pthread_rwlock_t; +typedef struct _pthread_rwlock_info { + struct _pthread_rwlock_info *pr_next; + struct _pthread_rwlock_t *pr_lock; + int pr_lock_count; +} pthread_readlock_info; + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + + +union dtv; + +struct _pthread_descr_struct +{ +#if !defined USE_TLS || !TLS_DTV_AT_TP || INCLUDE_TLS_PADDING + /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads. */ + union + { + struct + { + void *tcb; /* Pointer to the TCB. This is not always + the address of this thread descriptor. */ + union dtv *dtvp; + pthread_descr self; /* Pointer to this structure */ + int multiple_threads; +# ifdef NEED_DL_SYSINFO + uintptr_t sysinfo; +# endif + } data; + void *__padding[16]; + } p_header; +# define p_multiple_threads p_header.data.multiple_threads +#elif defined TLS_MULTIPLE_THREADS_IN_TCB && TLS_MULTIPLE_THREADS_IN_TCB + int p_multiple_threads; +#endif + + pthread_descr p_nextlive, p_prevlive; + /* Double chaining of active threads */ + pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ + pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ + pthread_t p_tid; /* Thread identifier */ + int p_pid; /* PID of Unix process */ + int p_priority; /* Thread priority (== 0 if not realtime) */ + struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ + int p_signal; /* last signal received */ + sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */ + sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ + char p_terminated; /* true if terminated e.g. by pthread_exit */ + char p_detached; /* true if detached */ + char p_exited; /* true if the assoc. process terminated */ + void * p_retval; /* placeholder for return value */ + int p_retcode; /* placeholder for return code */ + pthread_descr p_joining; /* thread joining on that thread or NULL */ + struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ + char p_cancelstate; /* cancellation state */ + char p_canceltype; /* cancellation type (deferred/async) */ + char p_canceled; /* cancellation request pending */ + char * p_in_sighandler; /* stack address of sighandler, or NULL */ + char p_sigwaiting; /* true if a sigwait() is in progress */ + struct pthread_start_args p_start_args; /* arguments for thread creation */ + void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ +#if !(USE_TLS && HAVE___THREAD) + void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ + int * p_errnop; /* pointer to used errno variable */ + int p_errno; /* error returned by last system call */ + int * p_h_errnop; /* pointer to used h_errno variable */ + int p_h_errno; /* error returned by last netdb function */ + struct __res_state *p_resp; /* Pointer to resolver state */ +#endif + struct __res_state p_res; /* per-thread resolver state */ + int p_userstack; /* nonzero if the user provided the stack */ + void *p_guardaddr; /* address of guard area or NULL */ + size_t p_guardsize; /* size of guard area */ + int p_nr; /* Index of descriptor in __pthread_handles */ + int p_report_events; /* Nonzero if events must be reported. */ + td_eventbuf_t p_eventbuf; /* Data for event. */ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ + char p_condvar_avail; /* flag if conditional variable became avail */ + char p_sem_avail; /* flag if semaphore became available */ + pthread_extricate_if *p_extricate; /* See above */ + pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ + pthread_readlock_info *p_readlock_free; /* Free list of structs */ + int p_untracked_readlock_count; /* Readlocks not tracked by list */ + int p_inheritsched; /* copied from the thread attribute */ +#if HP_TIMING_AVAIL + hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ +#endif +#ifdef USE_TLS + char *p_stackaddr; /* Stack address. */ +#endif + size_t p_alloca_cutoff; /* Maximum size which should be allocated + using alloca() instead of malloc(). */ + /* New elements must be added at the end. */ +} __attribute__ ((aligned(32))); /* We need to align the structure so that + doubles are aligned properly. This is 8 + bytes on MIPS and 16 bytes on MIPS64. + 32 bytes might give better cache + utilization. */ + + + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. + Initially 0, meaning that the current thread is (by definition) + the initial thread. */ + +extern char *__pthread_initial_thread_bos; + +/* Descriptor of the initial thread */ + +extern struct _pthread_descr_struct __pthread_initial_thread; + +/* Limits of the thread manager stack. */ + +extern char *__pthread_manager_thread_bos; +extern char *__pthread_manager_thread_tos; + +/* Descriptor of the manager thread */ + +extern struct _pthread_descr_struct __pthread_manager_thread; +extern pthread_descr __pthread_manager_threadp attribute_hidden; + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or all threads have stacks supplied by LinuxThreads (if 0). */ + +extern int __pthread_nonstandard_stacks; + +/* The max size of the thread stack segments. If the default + THREAD_SELF implementation is used, this must be a power of two and + a multiple of PAGE_SIZE. */ +#ifndef STACK_SIZE +#define STACK_SIZE (2 * 1024 * 1024) +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* Recover thread descriptor for the current thread */ + +extern pthread_descr __pthread_find_self (void) __attribute__ ((pure)); + +static __inline__ pthread_descr thread_self (void) __attribute__ ((pure)); +static __inline__ pthread_descr thread_self (void) +{ +#ifdef THREAD_SELF + return THREAD_SELF; +#else + char *sp = CURRENT_STACK_FRAME; + if (sp >= __pthread_initial_thread_bos) + return &__pthread_initial_thread; + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) + return &__pthread_manager_thread; + else if (__pthread_nonstandard_stacks) + return __pthread_find_self(); + else +#ifdef _STACK_GROWS_DOWN + return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; +#else + return (pthread_descr)((unsigned long)sp &~ (STACK_SIZE-1)); +#endif +#endif +} + +#endif /* descr.h */ diff --git a/libpthread/linuxthreads/errno.c b/libpthread/linuxthreads/errno.c new file mode 100644 index 0000000..03c23f8 --- /dev/null +++ b/libpthread/linuxthreads/errno.c @@ -0,0 +1,48 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Define the location of errno for the remainder of the C library */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +#if !USE_TLS || !HAVE___THREAD +/* The definition in libc is sufficient if we use TLS. */ +int * +__errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_errnop); +} + +int * +__h_errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_h_errnop); +} + +#if 0 +/* Return thread specific resolver state. */ +struct __res_state * +__res_state (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_resp); +} +#endif +#endif diff --git a/libpthread/linuxthreads/events.c b/libpthread/linuxthreads/events.c new file mode 100644 index 0000000..b4ca384 --- /dev/null +++ b/libpthread/linuxthreads/events.c @@ -0,0 +1,37 @@ +/* Event functions used while debugging. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The functions contained here do nothing, they just return. */ + +#include "internals.h" + +void +__linuxthreads_create_event (void) +{ +} + +void +__linuxthreads_death_event (void) +{ +} + +void +__linuxthreads_reap_event (void) +{ +} diff --git a/libpthread/linuxthreads/forward.c b/libpthread/linuxthreads/forward.c new file mode 100644 index 0000000..2cd0196 --- /dev/null +++ b/libpthread/linuxthreads/forward.c @@ -0,0 +1,146 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* psm: keep this before internals.h */ +libc_hidden_proto(exit) + +#include "internals.h" + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +# define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) + +FORWARD (pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit) + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) +strong_alias(pthread_mutex_init, __pthread_mutex_init) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) +FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) + +FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) +FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h new file mode 100644 index 0000000..ecb7b03 --- /dev/null +++ b/libpthread/linuxthreads/internals.h @@ -0,0 +1,556 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _INTERNALS_H +#define _INTERNALS_H 1 + +#include "uClibc-glue.h" + +/* Internal data structures */ + +/* Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_TLS +#include +#endif +#include "descr.h" + +#include "semaphore.h" +#include + +#ifndef THREAD_GETMEM +# define THREAD_GETMEM(descr, member) descr->member +#endif +#ifndef THREAD_GETMEM_NC +# define THREAD_GETMEM_NC(descr, member) descr->member +#endif +#ifndef THREAD_SETMEM +# define THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif +#ifndef THREAD_SETMEM_NC +# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) +#endif + +#if !defined NOT_IN_libc && defined FLOATING_STACKS +# define LIBC_THREAD_GETMEM(descr, member) THREAD_GETMEM (descr, member) +# define LIBC_THREAD_SETMEM(descr, member, value) \ + THREAD_SETMEM (descr, member, value) +#else +# define LIBC_THREAD_GETMEM(descr, member) descr->member +# define LIBC_THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif + +typedef void (*destr_function)(void *); + +struct pthread_key_struct { + int in_use; /* already allocated? */ + destr_function destr; /* destruction routine */ +}; + + +#define PTHREAD_START_ARGS_INITIALIZER(fct) \ + { (void *(*) (void *)) fct, NULL, {{0, }}, 0, { 0 } } + + +/* The type of thread handles. */ + +typedef struct pthread_handle_struct * pthread_handle; + +struct pthread_handle_struct { + struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */ + pthread_descr h_descr; /* Thread descriptor or NULL if invalid */ + char * h_bottom; /* Lowest address in the stack thread */ +}; + +/* The type of messages sent to the thread manager thread */ + +struct pthread_request { + pthread_descr req_thread; /* Thread doing the request */ + enum { /* Request kind */ + REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, + REQ_POST, REQ_DEBUG, REQ_KICK, REQ_FOR_EACH_THREAD + } req_kind; + union { /* Arguments for request */ + struct { /* For REQ_CREATE: */ + const pthread_attr_t * attr; /* thread attributes */ + void * (*fn)(void *); /* start function */ + void * arg; /* argument to start function */ + sigset_t mask; /* signal mask */ + } create; + struct { /* For REQ_FREE: */ + pthread_t thread_id; /* identifier of thread to free */ + } free; + struct { /* For REQ_PROCESS_EXIT: */ + int code; /* exit status */ + } exit; + void * post; /* For REQ_POST: the semaphore */ + struct { /* For REQ_FOR_EACH_THREAD: callback */ + void (*fn)(void *, pthread_descr); + void *arg; + } for_each; + } req_args; +}; + + + +typedef void (*arch_sighandler_t) (int, SIGCONTEXT); +union sighandler +{ + arch_sighandler_t old; + void (*rt) (int, struct siginfo *, struct ucontext *); +}; +extern union sighandler __sighandler[NSIG]; + + +/* Signals used for suspend/restart and for cancellation notification. */ + +extern int __pthread_sig_restart; +extern int __pthread_sig_cancel; + +/* Signal used for interfacing with gdb */ + +extern int __pthread_sig_debug; + +/* Global array of thread handles, used for validating a thread id + and retrieving the corresponding thread descriptor. Also used for + mapping the available stack segments. */ + +extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; + +/* Descriptor of the main thread */ + +extern pthread_descr __pthread_main_thread; + +/* File descriptor for sending requests to the thread manager. + Initially -1, meaning that __pthread_initialize_manager must be called. */ + +extern int __pthread_manager_request; + +/* Other end of the pipe for sending requests to the thread manager. */ + +extern int __pthread_manager_reader; + +#ifdef FLOATING_STACKS +/* Maximum stack size. */ +extern size_t __pthread_max_stacksize; +#endif + +/* Pending request for a process-wide exit */ + +extern int __pthread_exit_requested, __pthread_exit_code; + +/* Set to 1 by gdb if we're debugging */ + +extern __volatile__ int __pthread_threads_debug; + +/* Globally enabled events. */ +extern __volatile__ td_thr_events_t __pthread_threads_events; + +/* Pointer to descriptor of thread with last event. */ +extern __volatile__ pthread_descr __pthread_last_event; + +/* Flag which tells whether we are executing on SMP kernel. */ +extern int __pthread_smp_kernel; + +/* Return the handle corresponding to a thread id */ + +static __inline__ pthread_handle thread_handle(pthread_t id) +{ + return &__pthread_handles[id % PTHREAD_THREADS_MAX]; +} + +/* Validate a thread handle. Must have acquired h->h_spinlock before. */ + +static __inline__ int invalid_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id || h->h_descr->p_terminated; +} + +static __inline__ int nonexisting_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id; +} + +/* Fill in defaults left unspecified by pt-machine.h. */ + +/* We round up a value with page size. */ +#ifndef page_roundup +#define page_roundup(v,p) ((((size_t) (v)) + (p) - 1) & ~((p) - 1)) +#endif + +/* The page size we can get from the system. This should likely not be + changed by the machine file but, you never know. */ +#ifndef PAGE_SIZE +#define PAGE_SIZE (sysconf (_SC_PAGE_SIZE)) +#endif + +/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE (4 * PAGE_SIZE) +#endif + +/* Size of the thread manager stack. The "- 32" avoids wasting space + with some malloc() implementations. */ +#ifndef THREAD_MANAGER_STACK_SIZE +#define THREAD_MANAGER_STACK_SIZE (2 * PAGE_SIZE - 32) +#endif + +/* The base of the "array" of thread stacks. The array will grow down from + here. Defaults to the calculated bottom of the initial application + stack. */ +#ifndef THREAD_STACK_START_ADDRESS +#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos +#endif + +/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the + architecture doesn't need a memory barrier instruction (e.g. Intel + x86). Still we need the compiler to respect the barrier and emit + all outstanding operations which modify memory. Some architectures + distinguish between full, read and write barriers. */ + +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER() __asm__ ("" : : : "memory") +#endif +#ifndef READ_MEMORY_BARRIER +#define READ_MEMORY_BARRIER() MEMORY_BARRIER() +#endif +#ifndef WRITE_MEMORY_BARRIER +#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() +#endif + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Max number of times the spinlock in the adaptive mutex implementation + spins actively on SMP systems. */ + +#ifndef MAX_ADAPTIVE_SPIN_COUNT +#define MAX_ADAPTIVE_SPIN_COUNT 100 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads attribute_hidden; +extern int __librt_multiple_threads; + +/* Debugging */ + +#ifdef DEBUG +#include +#define ASSERT assert +#define MSG __pthread_message +#else +#define ASSERT(x) +#define MSG(msg,arg...) +#endif + +/* Internal global functions */ + +extern void __pthread_do_exit (void *retval, char *currentframe) + __attribute__ ((__noreturn__)); +extern void __pthread_destroy_specifics (void); +extern void __pthread_perform_cleanup (char *currentframe); +extern void __pthread_init_max_stacksize (void); +extern int __pthread_initialize_manager (void); +extern void __pthread_message (const char * fmt, ...); +extern int __pthread_manager (void *reqfd); +extern int __pthread_manager_event (void *reqfd); +extern void __pthread_manager_sighandler (int sig); +extern void __pthread_reset_main_thread (void); +extern void __pthread_once_fork_prepare (void); +extern void __pthread_once_fork_parent (void); +extern void __pthread_once_fork_child (void); +extern void __flockfilelist (void); +extern void __funlockfilelist (void); +extern void __fresetlockfiles (void); +extern void __pthread_manager_adjust_prio (int thread_prio); +extern void __pthread_initialize_minimal (void); + +extern int __pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize); +extern int __pthread_attr_getguardsize (const pthread_attr_t *__attr, + size_t *__guardsize); +#if 0 /* uClibc: deprecated stuff disabled */ +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr); +extern int __pthread_attr_getstackaddr (const pthread_attr_t *__attr, + void **__stackaddr); +#endif +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); +extern int __pthread_attr_getstacksize (const pthread_attr_t *__attr, + size_t *__stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); +extern int __pthread_attr_getstack (const pthread_attr_t *__attr, void **__stackaddr, + size_t *__stacksize); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); + +extern int __pthread_getconcurrency (void); +extern int __pthread_setconcurrency (int __level); +extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex, + const struct timespec *__abstime); +extern int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *__attr, + int *__pshared); +extern int __pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared); +extern int __pthread_mutexattr_gettype (const pthread_mutexattr_t *__attr, + int *__kind); +extern void __pthread_kill_other_threads_np (void); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern pthread_t __pthread_self (void); +extern pthread_descr __pthread_thread_self (void); +extern pthread_descr __pthread_self_stack (void) attribute_hidden; +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern void __pthread_exit (void *retval) +#if defined NOT_IN_libc && defined IS_IN_libpthread + attribute_noreturn +#endif + ; +extern int __pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int * oldstate); +extern int __pthread_setcanceltype (int type, int * oldtype); + +extern void __pthread_restart_old(pthread_descr th); +extern void __pthread_suspend_old(pthread_descr self); +extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_restart_new(pthread_descr th); +extern void __pthread_suspend_new(pthread_descr self); +extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_wait_for_restart_signal(pthread_descr self); + +extern void __pthread_sigsuspend (const sigset_t *mask) attribute_hidden; + +extern int __pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr); + +extern int __pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared); + +extern int __pthread_spin_lock (pthread_spinlock_t *__lock); +extern int __pthread_spin_trylock (pthread_spinlock_t *__lock); +extern int __pthread_spin_unlock (pthread_spinlock_t *__lock); +extern int __pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); +extern int __pthread_spin_destroy (pthread_spinlock_t *__lock); + +/* Global pointers to old or new suspend functions */ + +extern void (*__pthread_restart)(pthread_descr); +extern void (*__pthread_suspend)(pthread_descr); +extern int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *); + +/* Prototypes for the function without cancelation support when the + normal version has it. */ +extern int __libc_close (int fd); +extern int __libc_nanosleep (const struct timespec *requested_time, + struct timespec *remaining); +/* Prototypes for some of the new semaphore functions. */ +extern int sem_post (sem_t * sem); +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value); +extern int sem_wait (sem_t *__sem); +extern int sem_trywait (sem_t *__sem); +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval); +extern int sem_destroy (sem_t *__sem); + +/* Prototypes for compatibility functions. */ +extern int __pthread_attr_init (pthread_attr_t *__attr); +extern int __pthread_create (pthread_t *__restrict __threadp, + const pthread_attr_t *__attr, + void *(*__start_routine) (void *), + void *__restrict __arg); + +/* The functions called the signal events. */ +extern void __linuxthreads_create_event (void); +extern void __linuxthreads_death_event (void); +extern void __linuxthreads_reap_event (void); + +/* This function is called to initialize the pthread library. */ +extern void __pthread_initialize (void); + +/* TSD. */ +extern int __pthread_internal_tsd_set (int key, const void * pointer); +extern void * __pthread_internal_tsd_get (int key); +extern void ** __attribute__ ((__const__)) + __pthread_internal_tsd_address (int key); + +/* Sighandler wrappers. */ +extern void __pthread_sighandler(int signo, SIGCONTEXT ctx); +extern void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc); +extern void __pthread_null_sighandler(int sig); +extern int __pthread_sigaction (int sig, const struct sigaction *act, + struct sigaction *oact); +extern int __pthread_sigwait (const sigset_t *set, int *sig); +extern int __pthread_raise (int sig); + +/* Cancellation. */ +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +/* The two functions are in libc.so and are exported. */ +extern int __librt_enable_asynccancel (void); +extern void __librt_disable_asynccancel (int oldtype) internal_function; + +extern void __pthread_cleanup_upto (__jmp_buf target, + char *targetframe) attribute_hidden; +extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden; + +#define asm_handle(name) _asm_handle(name) +#define _asm_handle(name) #name +#define ASM_GLOBAL asm_handle(ASM_GLOBAL_DIRECTIVE) +#define ASM_CANCEL(name) asm_handle(C_SYMBOL_NAME(name)) + +#if !defined NOT_IN_libc +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_disable_asynccancel)) +#elif defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_disable_asynccancel)) +#elif defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ + __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __librt_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_disable_asynccancel)) +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_HANDLED() /* Nothing. */ +#endif + +extern int * __libc_pthread_init (const struct pthread_functions *functions); + +#if !defined NOT_IN_libc && !defined FLOATING_STACKS +# ifdef SHARED +# define thread_self() \ + (*__libc_pthread_functions.ptr_pthread_thread_self) () +# else +weak_extern (__pthread_thread_self) +# define thread_self() __pthread_thread_self () +# endif +#endif + +#ifndef USE_TLS +# define __manager_thread (&__pthread_manager_thread) +#else +# define __manager_thread __pthread_manager_threadp +#endif + +static __always_inline pthread_descr +check_thread_self (void); +static __always_inline pthread_descr +check_thread_self (void) +{ + pthread_descr self = thread_self (); +#if defined THREAD_SELF && defined INIT_THREAD_SELF + if (self == __manager_thread) + { + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + self = __pthread_self_stack(); + if (self != __manager_thread) + /* Oops, thread_self() isn't working yet.. */ + INIT_THREAD_SELF(self, self->p_nr); + } +#endif + return self; +} + +#endif /* internals.h */ diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c new file mode 100644 index 0000000..57ea54e --- /dev/null +++ b/libpthread/linuxthreads/join.c @@ -0,0 +1,220 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread termination and joining */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include + +void __pthread_exit(void * retval) +{ + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} +strong_alias (__pthread_exit, pthread_exit) + +void __pthread_do_exit(void *retval, char *currentframe) +{ + pthread_descr self = thread_self(); + pthread_descr joining; + struct pthread_request request; + + /* Reset the cancellation flag to avoid looping if the cleanup handlers + contain cancellation points */ + THREAD_SETMEM(self, p_canceled, 0); + /* Call cleanup functions and destroy the thread-specific data */ + __pthread_perform_cleanup(currentframe); + __pthread_destroy_specifics(); + /* Store return value */ + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_retval, retval); + /* See whether we have to signal the death. */ + if (THREAD_GETMEM(self, p_report_events)) + { + /* See whether TD_DEATH is in any of the mask. */ + int idx = __td_eventword (TD_DEATH); + uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | THREAD_GETMEM_NC(self, + p_eventbuf.eventmask.event_bits[idx]))) + != 0) + { + /* Yep, we have to signal the death. */ + THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); + THREAD_SETMEM(self, p_eventbuf.eventdata, self); + __pthread_last_event = self; + + /* Now call the function to signal the event. */ + __linuxthreads_death_event(); + } + } + /* Say that we've terminated */ + THREAD_SETMEM(self, p_terminated, 1); + /* See if someone is joining on us */ + joining = THREAD_GETMEM(self, p_joining); + __pthread_unlock(THREAD_GETMEM(self, p_lock)); + /* Restart joining thread if any */ + if (joining != NULL) restart(joining); + /* If this is the initial thread, block until all threads have terminated. + If another thread calls exit, we'll be terminated from our signal + handler. */ + if (self == __pthread_main_thread && __pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_MAIN_THREAD_EXIT; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *)&request, sizeof(request))); + suspend(self); + /* Main thread flushes stdio streams and runs atexit functions. + It also calls a handler within LinuxThreads which sends a process exit + request to the thread manager. */ + exit(0); + } + /* Threads other than the main one terminate without flushing stdio streams + or running atexit functions. */ + _exit(0); +} + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int join_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_handle handle = obj; + pthread_descr jo; + int did_remove = 0; + + __pthread_lock(&handle->h_lock, self); + jo = handle->h_descr; + did_remove = jo->p_joining != NULL; + jo->p_joining = NULL; + __pthread_unlock(&handle->h_lock); + + return did_remove; +} + +int pthread_join(pthread_t thread_id, void ** thread_return) +{ + __volatile__ pthread_descr self = thread_self(); + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + pthread_extricate_if extr; + int already_canceled = 0; + + /* Set up extrication interface */ + extr.pu_object = handle; + extr.pu_extricate_func = join_extricate_func; + + __pthread_lock(&handle->h_lock, self); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (th == self) { + __pthread_unlock(&handle->h_lock); + return EDEADLK; + } + /* If detached or already joined, error */ + if (th->p_detached || th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If not terminated yet, suspend ourselves. */ + if (! th->p_terminated) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + th->p_joining = self; + else + already_canceled = 1; + __pthread_unlock(&handle->h_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + suspend(self); + /* Deregister extrication interface */ + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + __pthread_lock(&handle->h_lock, self); + } + /* Get return value */ + if (thread_return != NULL) *thread_return = th->p_retval; + __pthread_unlock(&handle->h_lock); + /* Send notification to thread manager */ + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int pthread_detach(pthread_t thread_id) +{ + int terminated; + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + /* If already detached, error */ + if (th->p_detached) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If already joining, don't do anything. */ + if (th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return 0; + } + /* Mark as detached */ + th->p_detached = 1; + terminated = th->p_terminated; + __pthread_unlock(&handle->h_lock); + /* If already terminated, notify thread manager to reclaim resources */ + if (terminated && __pthread_manager_request >= 0) { + request.req_thread = thread_self(); + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} diff --git a/libpthread/linuxthreads/libc-cancellation.c b/libpthread/linuxthreads/libc-cancellation.c new file mode 100644 index 0000000..d97359b --- /dev/null +++ b/libpthread/linuxthreads/libc-cancellation.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include + +#if !defined NOT_IN_libc + +# ifndef SHARED +weak_extern (__pthread_do_exit) +# endif + +int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); +strong_alias (__libc_multiple_threads, __librt_multiple_threads) + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__libc_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = LIBC_THREAD_GETMEM(self, p_canceltype); + LIBC_THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (LIBC_THREAD_GETMEM(self, p_canceled), 0) && + LIBC_THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __libc_maybe_call2 (pthread_do_exit, + (PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0); + return oldtype; +} +strong_alias (__libc_enable_asynccancel, __librt_enable_asynccancel) + +void +internal_function attribute_hidden +__libc_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + LIBC_THREAD_SETMEM(self, p_canceltype, oldtype); +} +strong_alias (__libc_disable_asynccancel, __librt_disable_asynccancel) + +#endif diff --git a/libpthread/linuxthreads/libc_pthread_init.c b/libpthread/linuxthreads/libc_pthread_init.c new file mode 100644 index 0000000..f89c287 --- /dev/null +++ b/libpthread/linuxthreads/libc_pthread_init.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifdef USE_TLS +#include +#endif +#include "internals.h" + +#ifdef SHARED +/* Experimentally off - libc_hidden_proto(memcpy) */ +#endif + +#if !(USE_TLS && HAVE___THREAD) && defined __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(uselocale) +#endif + +int * +__libc_pthread_init (functions) + const struct pthread_functions *functions; +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/libpthread/linuxthreads/lockfile.c b/libpthread/linuxthreads/lockfile.c new file mode 100644 index 0000000..5266b18 --- /dev/null +++ b/libpthread/linuxthreads/lockfile.c @@ -0,0 +1,52 @@ +/* lockfile - Handle locking and unlocking of stream. + Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" + +/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both + * libc and libpthread. In uClibc, they are now in libc only. */ + +void +__flockfilelist(void) +{ +} + +void +__funlockfilelist(void) +{ +} + +void +__fresetlockfiles (void) +{ + FILE *fp; + + pthread_mutexattr_t attr; + + __pthread_mutexattr_init (&attr); + __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + pthread_mutex_init (&fp->__lock, &attr); + + pthread_mutexattr_destroy(&attr); +} diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c new file mode 100644 index 0000000..b0a2a37 --- /dev/null +++ b/libpthread/linuxthreads/manager.c @@ -0,0 +1,1121 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "thread manager" thread: manages creation and termination of threads */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for poll */ +#include /* for mmap */ +#include +#include +#include /* for waitpid macros */ +#include /* for __uselocale */ +#include /* for __resp */ + +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "semaphore.h" +#include + +/* For debugging purposes put the maximum number of threads in a variable. */ +const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; + +#ifndef THREAD_SELF +/* Indicate whether at least one thread has a user-defined stack (if 1), + or if all threads have stacks supplied by LinuxThreads (if 0). */ +int __pthread_nonstandard_stacks; +#endif + +/* Number of active entries in __pthread_handles (used by gdb) */ +__volatile__ int __pthread_handles_num = 2; + +/* Whether to use debugger additional actions for thread creation + (set to 1 by gdb) */ +__volatile__ int __pthread_threads_debug; + +/* Globally enabled events. */ +__volatile__ td_thr_events_t __pthread_threads_events; + +/* Pointer to thread descriptor with last event. */ +__volatile__ pthread_descr __pthread_last_event; + +static pthread_descr manager_thread; + +/* Mapping from stack segment to thread descriptor. */ +/* Stack segment numbers are also indices into the __pthread_handles array. */ +/* Stack segment number 0 is reserved for the initial thread. */ + +#if FLOATING_STACKS +# define thread_segment(seq) NULL +#else +static __inline__ pthread_descr thread_segment(int seg) +{ +# ifdef _STACK_GROWS_UP + return (pthread_descr)(THREAD_STACK_START_ADDRESS + (seg - 1) * STACK_SIZE) + + 1; +# else + return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE) + - 1; +# endif +} +#endif + +/* Flag set in signal handler to record child termination */ + +static __volatile__ int terminated_children; + +/* Flag set when the initial thread is blocked on pthread_exit waiting + for all other threads to terminate */ + +static int main_thread_exiting; + +/* Counter used to generate unique thread identifier. + Thread identifier is pthread_threads_counter + segment. */ + +static pthread_t pthread_threads_counter; + +/* Forward declarations */ + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t *mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp); +static void pthread_handle_free(pthread_t th_id); +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) + __attribute__ ((noreturn)); +static void pthread_reap_children(void); +static void pthread_kill_all_threads(int sig, int main_thread_also); +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)); + +/* The server thread managing requests for thread creation and termination */ + +int +__attribute__ ((noreturn)) +__pthread_manager(void *arg) +{ + pthread_descr self = manager_thread = arg; + int reqfd = __pthread_manager_reader; + struct pollfd ufd; + sigset_t manager_mask; + int n; + struct pthread_request request; + + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif +#if !(USE_TLS && HAVE___THREAD) + /* Set the error variable. */ + self->p_errnop = &self->p_errno; + self->p_h_errnop = &self->p_h_errno; +#endif + /* Block all signals except __pthread_sig_cancel and SIGTRAP */ + sigfillset(&manager_mask); + sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ + sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + sigdelset(&manager_mask, __pthread_sig_debug); + sigprocmask(SIG_SETMASK, &manager_mask, NULL); + /* Raise our priority to match that of main thread */ + __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); + /* Synchronize debugging of the thread manager */ + n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, + sizeof(request))); + ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG); + ufd.fd = reqfd; + ufd.events = POLLIN; + /* Enter server loop */ + while(1) { + n = __poll(&ufd, 1, 2000); + + /* Check for termination of the main thread */ + if (getppid() == 1) { + pthread_kill_all_threads(SIGKILL, 0); + _exit(0); + } + /* Check for dead children */ + if (terminated_children) { + terminated_children = 0; + pthread_reap_children(); + } + /* Read and execute request */ + if (n == 1 && (ufd.revents & POLLIN)) { + n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, + sizeof(request))); +#ifdef DEBUG + if (n < 0) { + char d[64]; + write(STDERR_FILENO, d, snprintf(d, sizeof(d), "*** read err %m\n")); + } else if (n != sizeof(request)) { + write(STDERR_FILENO, "*** short read in manager\n", 26); + } +#endif + + switch(request.req_kind) { + case REQ_CREATE: + request.req_thread->p_retcode = + pthread_handle_create((pthread_t *) &request.req_thread->p_retval, + request.req_args.create.attr, + request.req_args.create.fn, + request.req_args.create.arg, + &request.req_args.create.mask, + request.req_thread->p_pid, + request.req_thread->p_report_events, + &request.req_thread->p_eventbuf.eventmask); + restart(request.req_thread); + break; + case REQ_FREE: + pthread_handle_free(request.req_args.free.thread_id); + break; + case REQ_PROCESS_EXIT: + pthread_handle_exit(request.req_thread, + request.req_args.exit.code); + /* NOTREACHED */ + break; + case REQ_MAIN_THREAD_EXIT: + main_thread_exiting = 1; + /* Reap children in case all other threads died and the signal handler + went off before we set main_thread_exiting to 1, and therefore did + not do REQ_KICK. */ + pthread_reap_children(); + + if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* The main thread will now call exit() which will trigger an + __on_exit handler, which in turn will send REQ_PROCESS_EXIT + to the thread manager. In case you are wondering how the + manager terminates from its loop here. */ + } + break; + case REQ_POST: + sem_post(request.req_args.post); + break; + case REQ_DEBUG: + /* Make gdb aware of new thread and gdb will restart the + new thread when it is ready to handle the new thread. */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + raise(__pthread_sig_debug); + break; + case REQ_KICK: + /* This is just a prod to get the manager to reap some + threads right away, avoiding a potential delay at shutdown. */ + break; + case REQ_FOR_EACH_THREAD: + pthread_for_each_thread(request.req_args.for_each.arg, + request.req_args.for_each.fn); + restart(request.req_thread); + break; + } + } + } +} + +int __pthread_manager_event(void *arg) +{ + pthread_descr self = arg; + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + return __pthread_manager(arg); +} + +/* Process creation */ + +static int +__attribute__ ((noreturn)) +pthread_start_thread(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + struct pthread_request request; + void * outcome; +#if HP_TIMING_AVAIL + hp_timing_t tmpclock; +#endif + /* Initialize special thread_self processing, if any. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif +#if HP_TIMING_AVAIL + HP_TIMING_NOW (tmpclock); + THREAD_SETMEM (self, p_cpuclock_offset, tmpclock); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Initial signal mask is that of the creating thread. (Otherwise, + we'd just inherit the mask of the thread manager.) */ + sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); + /* Set the scheduling policy and priority for the new thread, if needed */ + if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) + /* Explicit scheduling attributes were provided: apply them */ + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + THREAD_GETMEM(self, p_start_args.schedpolicy), + &self->p_start_args.schedparam); + else if (manager_thread->p_priority > 0) + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + { + struct sched_param default_params; + default_params.sched_priority = 0; + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + SCHED_OTHER, &default_params); + } +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#else + /* Initialize __resp. */ + __resp = &self->p_res; +#endif + /* Make gdb aware of new thread */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + request.req_thread = self; + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + /* Run the thread code */ + outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, + p_start_args.arg)); + /* Exit with the given return value */ + __pthread_do_exit(outcome, CURRENT_STACK_FRAME); +} + +static int +__attribute__ ((noreturn)) +pthread_start_thread_event(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + pthread_start_thread (arg); +} + +#if defined USE_TLS && !FLOATING_STACKS +# error "TLS can only work with floating stacks" +#endif + +static int pthread_allocate_stack(const pthread_attr_t *attr, + pthread_descr default_new_thread, + int pagesize, + char ** out_new_thread, + char ** out_new_thread_bottom, + char ** out_guardaddr, + size_t * out_guardsize, + size_t * out_stacksize) +{ + pthread_descr new_thread; + char * new_thread_bottom; + char * guardaddr; + size_t stacksize, guardsize; + +#ifdef USE_TLS + /* TLS cannot work with fixed thread descriptor addresses. */ + assert (default_new_thread == NULL); +#endif + + if (attr != NULL && attr->__stackaddr_set) + { +#ifdef _STACK_GROWS_UP + /* The user provided a stack. */ +# ifdef USE_TLS + /* This value is not needed. */ + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) new_thread; +# else + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) (new_thread + 1); +# endif + guardaddr = attr->__stackaddr + attr->__stacksize; + guardsize = 0; +#else + /* The user provided a stack. For now we interpret the supplied + address as 1 + the highest addr. in the stack segment. If a + separate register stack is needed, we place it at the low end + of the segment, relying on the associated stacksize to + determine the low end of the segment. This differs from many + (but not all) other pthreads implementations. The intent is + that on machines with a single stack growing toward higher + addresses, stackaddr would be the lowest address in the stack + segment, so that it is consistently close to the initial sp + value. */ +# ifdef USE_TLS + new_thread = (pthread_descr) attr->__stackaddr; +# else + new_thread = + (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; +# endif + new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; + guardaddr = new_thread_bottom; + guardsize = 0; +#endif +#ifndef THREAD_SELF + __pthread_nonstandard_stacks = 1; +#endif +#ifndef USE_TLS + /* Clear the thread data structure. */ + memset (new_thread, '\0', sizeof (*new_thread)); +#endif + stacksize = attr->__stacksize; + } + else + { +#ifdef NEED_SEPARATE_REGISTER_STACK + const size_t granularity = 2 * pagesize; + /* Try to make stacksize/2 a multiple of pagesize */ +#else + const size_t granularity = pagesize; +#endif + void *map_addr; + + /* Allocate space for stack and thread descriptor at default address */ +#if FLOATING_STACKS + if (attr != NULL) + { + guardsize = page_roundup (attr->__guardsize, granularity); + stacksize = __pthread_max_stacksize - guardsize; + stacksize = MIN (stacksize, + page_roundup (attr->__stacksize, granularity)); + } + else + { + guardsize = granularity; + stacksize = __pthread_max_stacksize - guardsize; + } + + map_addr = mmap(NULL, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_addr == MAP_FAILED) + /* No more memory available. */ + return -1; + +# ifdef NEED_SEPARATE_REGISTER_STACK + guardaddr = map_addr + stacksize / 2; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread_bottom = (char *) map_addr; +# ifdef USE_TLS + new_thread = ((pthread_descr) (new_thread_bottom + stacksize + + guardsize)); +# else + new_thread = ((pthread_descr) (new_thread_bottom + stacksize + + guardsize)) - 1; +# endif +# elif _STACK_GROWS_DOWN + guardaddr = map_addr; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread_bottom = (char *) map_addr + guardsize; +# ifdef USE_TLS + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)); +# else + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1; +# endif +# elif _STACK_GROWS_UP + guardaddr = map_addr + stacksize; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread = (pthread_descr) map_addr; +# ifdef USE_TLS + new_thread_bottom = (char *) new_thread; +# else + new_thread_bottom = (char *) (new_thread + 1); +# endif +# else +# error You must define a stack direction +# endif /* Stack direction */ +#else /* !FLOATING_STACKS */ +# if !defined NEED_SEPARATE_REGISTER_STACK && defined _STACK_GROWS_DOWN + void *res_addr; +# endif + + if (attr != NULL) + { + guardsize = page_roundup (attr->__guardsize, granularity); + stacksize = STACK_SIZE - guardsize; + stacksize = MIN (stacksize, + page_roundup (attr->__stacksize, granularity)); + } + else + { + guardsize = granularity; + stacksize = STACK_SIZE - granularity; + } + +# ifdef NEED_SEPARATE_REGISTER_STACK + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize - guardsize; + /* Includes guard area, unlike the normal case. Use the bottom + end of the segment as backing store for the register stack. + Needed on IA64. In this case, we also map the entire stack at + once. According to David Mosberger, that's cheaper. It also + avoids the risk of intermittent failures due to other mappings + in the same region. The cost is that we might be able to map + slightly fewer stacks. */ + + /* First the main stack: */ + map_addr = (caddr_t)((char *)(new_thread + 1) - stacksize / 2); + res_addr = mmap(map_addr, stacksize / 2, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + /* Bad luck, this segment is already mapped. */ + if (res_addr != MAP_FAILED) + munmap(res_addr, stacksize / 2); + return -1; + } + /* Then the register stack: */ + map_addr = (caddr_t)new_thread_bottom; + res_addr = mmap(map_addr, stacksize/2, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + if (res_addr != MAP_FAILED) + munmap(res_addr, stacksize / 2); + munmap((caddr_t)((char *)(new_thread + 1) - stacksize/2), + stacksize/2); + return -1; + } + + guardaddr = new_thread_bottom + stacksize/2; + /* We leave the guard area in the middle unmapped. */ +# else /* !NEED_SEPARATE_REGISTER_STACK */ +# ifdef _STACK_GROWS_DOWN + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize; + map_addr = new_thread_bottom - guardsize; + res_addr = mmap(map_addr, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + /* Bad luck, this segment is already mapped. */ + if (res_addr != MAP_FAILED) + munmap (res_addr, stacksize + guardsize); + return -1; + } + + /* We manage to get a stack. Protect the guard area pages if + necessary. */ + guardaddr = map_addr; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); +# else + /* The thread description goes at the bottom of this area, and + * the stack starts directly above it. + */ + new_thread = (pthread_descr)((unsigned long)default_new_thread &~ (STACK_SIZE - 1)); + map_addr = mmap(new_thread, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_addr == MAP_FAILED) + return -1; + + new_thread_bottom = map_addr + sizeof(*new_thread); + guardaddr = map_addr + stacksize; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + +# endif /* stack direction */ +# endif /* !NEED_SEPARATE_REGISTER_STACK */ +#endif /* !FLOATING_STACKS */ + } + *out_new_thread = (char *) new_thread; + *out_new_thread_bottom = new_thread_bottom; + *out_guardaddr = guardaddr; + *out_guardsize = guardsize; +#ifdef NEED_SEPARATE_REGISTER_STACK + *out_stacksize = stacksize / 2; +#else + *out_stacksize = stacksize; +#endif + return 0; +} + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t * mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp) +{ + size_t sseg; + int pid; + pthread_descr new_thread; + char *stack_addr; + char * new_thread_bottom; + pthread_t new_thread_id; + char *guardaddr = NULL; + size_t guardsize = 0, stksize = 0; + int pagesize = __getpagesize(); + int saved_errno = 0; + +#ifdef USE_TLS + new_thread = _dl_allocate_tls (NULL); + if (new_thread == NULL) + return EAGAIN; +# if TLS_DTV_AT_TP + /* pthread_descr is below TP. */ + new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE); +# endif +#else + /* Prevent warnings. */ + new_thread = NULL; +#endif + + /* First check whether we have to change the policy and if yes, whether + we can do this. Normally this should be done by examining the + return value of the __sched_setscheduler call in pthread_start_thread + but this is hard to implement. FIXME */ + if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) + return EPERM; + /* Find a free segment for the thread, and allocate a stack if needed */ + for (sseg = 2; ; sseg++) + { + if (sseg >= PTHREAD_THREADS_MAX) + { +#ifdef USE_TLS +# if TLS_DTV_AT_TP + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + return EAGAIN; + } + if (__pthread_handles[sseg].h_descr != NULL) + continue; + if (pthread_allocate_stack(attr, thread_segment(sseg), + pagesize, &stack_addr, &new_thread_bottom, + &guardaddr, &guardsize, &stksize) == 0) + { +#ifdef USE_TLS + new_thread->p_stackaddr = stack_addr; +#else + new_thread = (pthread_descr) stack_addr; +#endif + break; +#ifndef __ARCH_USE_MMU__ + } else { + /* When there is MMU, mmap () is used to allocate the stack. If one + * segment is already mapped, we should continue to see if we can + * use the next one. However, when there is no MMU, malloc () is used. + * It's waste of CPU cycles to continue to try if it fails. */ + return EAGAIN; +#endif + } + } + __pthread_handles_num++; + /* Allocate new thread identifier */ + pthread_threads_counter += PTHREAD_THREADS_MAX; + new_thread_id = sseg + pthread_threads_counter; + /* Initialize the thread descriptor. Elements which have to be + initialized to zero already have this value. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_header.data.tcb = new_thread; + new_thread->p_header.data.self = new_thread; +#endif +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_multiple_threads = 1; +#endif + new_thread->p_tid = new_thread_id; + new_thread->p_lock = &(__pthread_handles[sseg].h_lock); + new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; + new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; +#if !(USE_TLS && HAVE___THREAD) + new_thread->p_errnop = &new_thread->p_errno; + new_thread->p_h_errnop = &new_thread->p_h_errno; + new_thread->p_resp = &new_thread->p_res; +#endif + new_thread->p_guardaddr = guardaddr; + new_thread->p_guardsize = guardsize; + new_thread->p_nr = sseg; + new_thread->p_inheritsched = attr ? attr->__inheritsched : 0; + new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF + ? __MAX_ALLOCA_CUTOFF : stksize / 4; + /* Initialize the thread handle */ + __pthread_init_lock(&__pthread_handles[sseg].h_lock); + __pthread_handles[sseg].h_descr = new_thread; + __pthread_handles[sseg].h_bottom = new_thread_bottom; + /* Determine scheduling parameters for the thread */ + new_thread->p_start_args.schedpolicy = -1; + if (attr != NULL) { + new_thread->p_detached = attr->__detachstate; + new_thread->p_userstack = attr->__stackaddr_set; + + switch(attr->__inheritsched) { + case PTHREAD_EXPLICIT_SCHED: + new_thread->p_start_args.schedpolicy = attr->__schedpolicy; + memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam, + sizeof (struct sched_param)); + break; + case PTHREAD_INHERIT_SCHED: + new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid); + __sched_getparam(father_pid, &new_thread->p_start_args.schedparam); + break; + } + new_thread->p_priority = + new_thread->p_start_args.schedparam.sched_priority; + } + /* Finish setting up arguments to pthread_start_thread */ + new_thread->p_start_args.start_routine = start_routine; + new_thread->p_start_args.arg = arg; + new_thread->p_start_args.mask = *mask; + /* Make the new thread ID available already now. If any of the later + functions fail we return an error value and the caller must not use + the stored thread ID. */ + *thread = new_thread_id; + /* Raise priority of thread manager if needed */ + __pthread_manager_adjust_prio(new_thread->p_priority); + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + pid = 0; /* Note that the thread never can have PID zero. */ + if (report_events) + { + /* See whether the TD_CREATE event bit is set in any of the + masks. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | event_maskp->event_bits[idx])) != 0) + { + /* Lock the mutex the child will use now so that it will stop. */ + __pthread_lock(new_thread->p_lock, NULL); + + /* We have to report this event. */ +#ifdef NEED_SEPARATE_REGISTER_STACK + /* Perhaps this version should be used on all platforms. But + this requires that __clone2 be uniformly supported + everywhere. + + And there is some argument for changing the __clone2 + interface to pass sp and bsp instead, making it more IA64 + specific, but allowing stacks to grow outward from each + other, to get less paging and fewer mmaps. */ + pid = __clone2(pthread_start_thread_event, + (void **)new_thread_bottom, + (char *)stack_addr - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#elif _STACK_GROWS_UP + pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = __clone(pthread_start_thread_event, stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif + saved_errno = errno; + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + new_thread->p_eventbuf.eventdata = new_thread; + new_thread->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = new_thread; + + /* We have to set the PID here since the callback function + in the debug library will need it and we cannot guarantee + the child got scheduled before the debugger. */ + new_thread->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + + /* Now restart the thread. */ + __pthread_unlock(new_thread->p_lock); + } + } + } + if (pid == 0) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(pthread_start_thread, + (void **)new_thread_bottom, + (char *)stack_addr - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#elif _STACK_GROWS_UP + pid = __clone(pthread_start_thread, (void *) new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = __clone(pthread_start_thread, stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif /* !NEED_SEPARATE_REGISTER_STACK */ + saved_errno = errno; + } + /* Check if cloning succeeded */ + if (pid == -1) { + /* Free the stack if we allocated it */ + if (attr == NULL || !attr->__stackaddr_set) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + size_t stacksize = ((char *)(new_thread->p_guardaddr) + - new_thread_bottom); + munmap((caddr_t)new_thread_bottom, + 2 * stacksize + new_thread->p_guardsize); +#elif _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - stack_addr; + munmap(stack_addr, stacksize + guardsize); +# else + size_t stacksize = guardaddr - (char *)new_thread; + munmap(new_thread, stacksize + guardsize); +# endif +#else +# ifdef USE_TLS + size_t stacksize = stack_addr - new_thread_bottom; +# else + size_t stacksize = (char *)(new_thread+1) - new_thread_bottom; +# endif + munmap(new_thread_bottom - guardsize, guardsize + stacksize); +#endif + } +#ifdef USE_TLS +# if TLS_DTV_AT_TP + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + __pthread_handles[sseg].h_descr = NULL; + __pthread_handles[sseg].h_bottom = NULL; + __pthread_handles_num--; + return saved_errno; + } + /* Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /* Set pid field of the new thread, in case we get there before the + child starts. */ + new_thread->p_pid = pid; + return 0; +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_free(pthread_descr th) +{ + pthread_handle handle; + pthread_readlock_info *iter, *next; + + ASSERT(th->p_exited); + /* Make the handle invalid */ + handle = thread_handle(th->p_tid); + __pthread_lock(&handle->h_lock, NULL); + handle->h_descr = NULL; + handle->h_bottom = (char *)(-1L); + __pthread_unlock(&handle->h_lock); +#ifdef FREE_THREAD + FREE_THREAD(th, th->p_nr); +#endif + /* One fewer threads in __pthread_handles */ + __pthread_handles_num--; + + /* Destroy read lock list, and list of free read lock structures. + If the former is not empty, it means the thread exited while + holding read locks! */ + + for (iter = th->p_readlock_list; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + for (iter = th->p_readlock_free; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + /* If initial thread, nothing to free */ + if (!th->p_userstack) + { + size_t guardsize = th->p_guardsize; + /* Free the stack and thread descriptor area */ + char *guardaddr = th->p_guardaddr; +#ifdef _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - th->p_stackaddr; +# else + size_t stacksize = guardaddr - (char *)th; +# endif + guardaddr = (char *)th; +#else + /* Guardaddr is always set, even if guardsize is 0. This allows + us to compute everything else. */ +# ifdef USE_TLS + size_t stacksize = th->p_stackaddr - guardaddr - guardsize; +# else + size_t stacksize = (char *)(th+1) - guardaddr - guardsize; +# endif +# ifdef NEED_SEPARATE_REGISTER_STACK + /* Take account of the register stack, which is below guardaddr. */ + guardaddr -= stacksize; + stacksize *= 2; +# endif +#endif + /* Unmap the stack. */ + munmap(guardaddr, stacksize + guardsize); + + } + +#ifdef USE_TLS +# if TLS_DTV_AT_TP + th = (pthread_descr) ((char *) th + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (th, true); +#endif +} + +/* Handle threads that have exited */ + +static void pthread_exited(pid_t pid) +{ + pthread_descr th; + int detached; + /* Find thread with that pid */ + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + if (th->p_pid == pid) { + /* Remove thread from list of active threads */ + th->p_nextlive->p_prevlive = th->p_prevlive; + th->p_prevlive->p_nextlive = th->p_nextlive; + /* Mark thread as exited, and if detached, free its resources */ + __pthread_lock(th->p_lock, NULL); + th->p_exited = 1; + /* If we have to signal this event do it now. */ + if (th->p_report_events) + { + /* See whether TD_REAP is in any of the mask. */ + int idx = __td_eventword (TD_REAP); + uint32_t mask = __td_eventmask (TD_REAP); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | th->p_eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the reapage. */ + th->p_eventbuf.eventnum = TD_REAP; + th->p_eventbuf.eventdata = th; + __pthread_last_event = th; + + /* Now call the function to signal the event. */ + __linuxthreads_reap_event(); + } + } + detached = th->p_detached; + __pthread_unlock(th->p_lock); + if (detached) + pthread_free(th); + break; + } + } + /* If all threads have exited and the main thread is pending on a + pthread_exit, wake up the main thread and terminate ourselves. */ + if (main_thread_exiting && + __pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* Same logic as REQ_MAIN_THREAD_EXIT. */ + } +} + +static void pthread_reap_children(void) +{ + pid_t pid; + int status; + + while ((pid = waitpid_not_cancel(-1, &status, WNOHANG | __WCLONE)) > 0) { + pthread_exited(pid); + if (WIFSIGNALED(status)) { + /* If a thread died due to a signal, send the same signal to + all other threads, including the main thread. */ + pthread_kill_all_threads(WTERMSIG(status), 1); + _exit(0); + } + } +} + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_handle_free(pthread_t th_id) +{ + pthread_handle handle = thread_handle(th_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (nonexisting_handle(handle, th_id)) { + /* pthread_reap_children has deallocated the thread already, + nothing needs to be done */ + __pthread_unlock(&handle->h_lock); + return; + } + th = handle->h_descr; + if (th->p_exited) { + __pthread_unlock(&handle->h_lock); + pthread_free(th); + } else { + /* The Unix process of the thread is still running. + Mark the thread as detached so that the thread manager will + deallocate its resources when the Unix process exits. */ + th->p_detached = 1; + __pthread_unlock(&handle->h_lock); + } +} + +/* Send a signal to all running threads */ + +static void pthread_kill_all_threads(int sig, int main_thread_also) +{ + pthread_descr th; + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + kill(th->p_pid, sig); + } + if (main_thread_also) { + kill(__pthread_main_thread->p_pid, sig); + } +} + +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)) +{ + pthread_descr th; + + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + fn(arg, th); + } + + fn(arg, __pthread_main_thread); +} + +/* Process-wide exit() */ + +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) +{ + pthread_descr th; + __pthread_exit_requested = 1; + __pthread_exit_code = exitcode; + /* A forced asynchronous cancellation follows. Make sure we won't + get stuck later in the main thread with a system lock being held + by one of the cancelled threads. Ideally one would use the same + code as in pthread_atfork(), but we can't distinguish system and + user handlers there. */ + __flockfilelist(); + /* Send the CANCEL signal to all running threads, including the main + thread, but excluding the thread from which the exit request originated + (that thread must complete the exit, e.g. calling atexit functions + and flushing stdio buffers). */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies + and their times are properly added to the thread manager's times. */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + waitpid(th->p_pid, NULL, __WCLONE); + } + __fresetlockfiles(); + restart(issuing_thread); + _exit(0); +} + +/* Handler for __pthread_sig_cancel in thread manager thread */ + +void __pthread_manager_sighandler(int sig) +{ + int kick_manager = terminated_children == 0 && main_thread_exiting; + terminated_children = 1; + + /* If the main thread is terminating, kick the thread manager loop + each time some threads terminate. This eliminates a two second + shutdown delay caused by the thread manager sleeping in the + call to __poll(). Instead, the thread manager is kicked into + action, reaps the outstanding threads and resumes the main thread + so that it can complete the shutdown. */ + + if (kick_manager) { + struct pthread_request request; + request.req_thread = 0; + request.req_kind = REQ_KICK; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +} + +/* Adjust priority of thread manager so that it always run at a priority + higher than all threads */ + +void __pthread_manager_adjust_prio(int thread_prio) +{ + struct sched_param param; + + if (thread_prio <= manager_thread->p_priority) return; + param.sched_priority = + thread_prio < __sched_get_priority_max(SCHED_FIFO) + ? thread_prio + 1 : thread_prio; + __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, ¶m); + manager_thread->p_priority = thread_prio; +} diff --git a/libpthread/linuxthreads/mutex.c b/libpthread/linuxthreads/mutex.c new file mode 100644 index 0000000..3c97ea7 --- /dev/null +++ b/libpthread/linuxthreads/mutex.c @@ -0,0 +1,357 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Mutexes */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int __pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + __pthread_init_lock(&mutex->__m_lock); + mutex->__m_kind = + mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; + mutex->__m_count = 0; + mutex->__m_owner = NULL; + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) + +int __pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + if ((mutex->__m_lock.__status & 1) != 0) + return EBUSY; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + if (mutex->__m_lock.__status != 0) + return EBUSY; + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) + +int __pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + pthread_descr self; + int retcode; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + retcode = __pthread_trylock(&mutex->__m_lock); + return retcode; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + retcode = __pthread_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = self; + mutex->__m_count = 0; + } + return retcode; + case PTHREAD_MUTEX_ERRORCHECK_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = thread_self(); + } + return retcode; + case PTHREAD_MUTEX_TIMED_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + return retcode; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) + +int __pthread_mutex_lock(pthread_mutex_t * mutex) +{ + pthread_descr self; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + __pthread_alt_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_lock(&mutex->__m_lock, NULL); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) + +int __pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_descr self; + int res; + + if (__builtin_expect (abstime->tv_nsec, 0) < 0 + || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) + return EINVAL; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); + if (res != 0) + { + mutex->__m_owner = self; + return 0; + } + return ETIMEDOUT; + case PTHREAD_MUTEX_TIMED_NP: + /* Only this type supports timed out lock. */ + return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) + ? 0 : ETIMEDOUT); + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock) + +int __pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + if (mutex->__m_owner != thread_self()) + return EPERM; + if (mutex->__m_count > 0) { + mutex->__m_count--; + return 0; + } + mutex->__m_owner = NULL; + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) + return EPERM; + mutex->__m_owner = NULL; + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) + +int __pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; + return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) + +int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) + +int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (kind != PTHREAD_MUTEX_ADAPTIVE_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP + && kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_TIMED_NP) + return EINVAL; + attr->__mutexkind = kind; + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) +strong_alias ( __pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) +weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) + +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + *kind = attr->__mutexkind; + return 0; +} +weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) +strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) +weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) + +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} +weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) + +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} +weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) + +/* Once-only execution */ + +static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; +static int fork_generation = 0; /* Child process increments this after fork. */ + +enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; + +/* If a thread is canceled while calling the init_routine out of + pthread once, this handler will reset the once_control variable + to the NEVER state. */ + +static void pthread_once_cancelhandler(void *arg) +{ + pthread_once_t *once_control = arg; + + pthread_mutex_lock(&once_masterlock); + *once_control = NEVER; + pthread_mutex_unlock(&once_masterlock); + pthread_cond_broadcast(&once_finished); +} + +int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) +{ + /* flag for doing the condition broadcast outside of mutex */ + int state_changed; + + /* Test without locking first for speed */ + if (*once_control == DONE) { + READ_MEMORY_BARRIER(); + return 0; + } + /* Lock and test again */ + + state_changed = 0; + + pthread_mutex_lock(&once_masterlock); + + /* If this object was left in an IN_PROGRESS state in a parent + process (indicated by stale generation field), reset it to NEVER. */ + if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) + *once_control = NEVER; + + /* If init_routine is being called from another routine, wait until + it completes. */ + while ((*once_control & 3) == IN_PROGRESS) { + pthread_cond_wait(&once_finished, &once_masterlock); + } + /* Here *once_control is stable and either NEVER or DONE. */ + if (*once_control == NEVER) { + *once_control = IN_PROGRESS | fork_generation; + pthread_mutex_unlock(&once_masterlock); + pthread_cleanup_push(pthread_once_cancelhandler, once_control); + init_routine(); + pthread_cleanup_pop(0); + pthread_mutex_lock(&once_masterlock); + WRITE_MEMORY_BARRIER(); + *once_control = DONE; + state_changed = 1; + } + pthread_mutex_unlock(&once_masterlock); + + if (state_changed) + pthread_cond_broadcast(&once_finished); + + return 0; +} +strong_alias (__pthread_once, pthread_once) + +/* + * Handle the state of the pthread_once mechanism across forks. The + * once_masterlock is acquired in the parent process prior to a fork to ensure + * that no thread is in the critical region protected by the lock. After the + * fork, the lock is released. In the child, the lock and the condition + * variable are simply reset. The child also increments its generation + * counter which lets pthread_once calls detect stale IN_PROGRESS states + * and reset them back to NEVER. + */ + +void __pthread_once_fork_prepare(void) +{ + pthread_mutex_lock(&once_masterlock); +} + +void __pthread_once_fork_parent(void) +{ + pthread_mutex_unlock(&once_masterlock); +} + +void __pthread_once_fork_child(void) +{ + pthread_mutex_init(&once_masterlock, NULL); + pthread_cond_init(&once_finished, NULL); + if (fork_generation <= INT_MAX - 4) + fork_generation += 4; /* leave least significant two bits zero */ + else + fork_generation = 0; +} diff --git a/libpthread/linuxthreads/pt-machine.c b/libpthread/linuxthreads/pt-machine.c new file mode 100644 index 0000000..5cd477c --- /dev/null +++ b/libpthread/linuxthreads/pt-machine.c @@ -0,0 +1,25 @@ +/* "Instantiation of machine-dependent pthreads inline functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define PT_EI + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +#include diff --git a/libpthread/linuxthreads/ptcleanup.c b/libpthread/linuxthreads/ptcleanup.c new file mode 100644 index 0000000..6213b56 --- /dev/null +++ b/libpthread/linuxthreads/ptcleanup.c @@ -0,0 +1,74 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#define NO_PTR_DEMANGLE + +#include +#include "pthread.h" +#include "internals.h" +#ifndef NO_PTR_DEMANGLE +#include +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b,c) +#else +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b) +#endif + +#ifndef NO_PTR_DEMANGLE +static __inline__ uintptr_t +demangle_ptr (uintptr_t x) +{ +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (x); +#endif + return x; +} +#else +#define demangle_ptr(x) x +#endif + +void __pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = THREAD_GETMEM(self, p_cleanup); + c != NULL && __JMPBUF_UNWINDS(target, c, demangle_ptr); + c = c->__prev) + { +#if _STACK_GROWS_DOWN + if ((char *) c <= targetframe) + { + c = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((char *) c >= targetframe) + { + c = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + THREAD_SETMEM(self, p_cleanup, c); + if (THREAD_GETMEM(self, p_in_sighandler) + && __JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler), + demangle_ptr)) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} diff --git a/libpthread/linuxthreads/ptclock_gettime.c b/libpthread/linuxthreads/ptclock_gettime.c new file mode 100644 index 0000000..755f83d --- /dev/null +++ b/libpthread/linuxthreads/ptclock_gettime.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "spinlock.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) +{ + hp_timing_t tsc, cpuclock_offset; + pthread_descr self = thread_self (); + pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE; + + if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread) + cpuclock_offset = THREAD_GETMEM (self, p_cpuclock_offset); + else + { + pthread_descr th; + pthread_handle handle = thread_handle (thread); + __pthread_lock (&handle->h_lock, NULL); + th = handle->h_descr; + if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated) + { + __pthread_unlock (&handle->h_lock); + __set_errno (EINVAL); + return -1; + } + cpuclock_offset = th->p_cpuclock_offset; + __pthread_unlock (&handle->h_lock); + } + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Compute the offset since the start time of the process. */ + tsc -= cpuclock_offset; + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + + return 0; +} +#endif diff --git a/libpthread/linuxthreads/ptclock_settime.c b/libpthread/linuxthreads/ptclock_settime.c new file mode 100644 index 0000000..a4f218c --- /dev/null +++ b/libpthread/linuxthreads/ptclock_settime.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "spinlock.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +{ + pthread_descr self = thread_self (); + pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE; + + if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread) + /* Our own clock. */ + THREAD_SETMEM (self, p_cpuclock_offset, offset); + else + { + pthread_descr th; + pthread_handle handle = thread_handle (thread); + __pthread_lock (&handle->h_lock, NULL); + th = handle->h_descr; + if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated) + { + __pthread_unlock (&handle->h_lock); + __set_errno (EINVAL); + return -1; + } + th->p_cpuclock_offset = offset; + __pthread_unlock (&handle->h_lock); + } + + return 0; +} +#endif diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c new file mode 100644 index 0000000..853aeea --- /dev/null +++ b/libpthread/linuxthreads/ptfork.c @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "atfork" stuff */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include +#include "fork.h" + +extern int __libc_fork (void); + +pid_t __pthread_fork (struct fork_block *b) +{ + pid_t pid; + list_t *runp; + + __libc_lock_lock (b->lock); + + /* Run all the registered preparation handlers. In reverse order. */ + list_for_each_prev (runp, &b->prepare_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __pthread_once_fork_prepare(); + __flockfilelist(); + + pid = ARCH_FORK (); + + if (pid == 0) { + __pthread_reset_main_thread(); + + __fresetlockfiles(); + __pthread_once_fork_child(); + + /* Run the handlers registered for the child. */ + list_for_each (runp, &b->child_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_init (b->lock); + } else { + __funlockfilelist(); + __pthread_once_fork_parent(); + + /* Run the handlers registered for the parent. */ + list_for_each (runp, &b->parent_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_unlock (b->lock); + } + + return pid; +} + +/* psm: have no idea why these are here, sjhill? */ +#if 0 /*def SHARED*/ +pid_t __fork (void) +{ + return __libc_fork (); +} +weak_alias (__fork, fork) + +pid_t __vfork(void) +{ + return __libc_fork (); +} +weak_alias (__vfork, vfork) +#endif diff --git a/libpthread/linuxthreads/pthandles.c b/libpthread/linuxthreads/pthandles.c new file mode 100644 index 0000000..acc47e2 --- /dev/null +++ b/libpthread/linuxthreads/pthandles.c @@ -0,0 +1,5 @@ +#include "pthread.h" +#include "internals.h" + +/* Array of active threads. Entry 0 is reserved for the initial thread. */ +struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; diff --git a/libpthread/linuxthreads/pthread.c b/libpthread/linuxthreads/pthread.c new file mode 100644 index 0000000..36961a1 --- /dev/null +++ b/libpthread/linuxthreads/pthread.c @@ -0,0 +1,1382 @@ + +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread creation, initialization, and basic low-level routines */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "smp.h" +#include + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +#if !(USE_TLS && HAVE___THREAD) +/* These variables are used by the setup code. */ +extern int _errno; +extern int _h_errno; + +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ +/* We need the global/static resolver state here. */ +# include +# undef _res +extern struct __res_state _res; +# endif +#endif + +#ifdef USE_TLS + +/* We need only a few variables. */ +#define manager_thread __pthread_manager_threadp +pthread_descr __pthread_manager_threadp attribute_hidden; + +#else + +/* Descriptor of the initial thread */ + +struct _pthread_descr_struct __pthread_initial_thread = { + .p_header.data.self = &__pthread_initial_thread, + .p_nextlive = &__pthread_initial_thread, + .p_prevlive = &__pthread_initial_thread, + .p_tid = PTHREAD_THREADS_MAX, + .p_lock = &__pthread_handles[0].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(NULL), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &_errno, + .p_h_errnop = &_h_errno, +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + .p_resp = &_res, +# endif +#endif + .p_userstack = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = __MAX_ALLOCA_CUTOFF +}; + +/* Descriptor of the manager thread; none of this is used but the error + variables, the p_pid and p_priority fields, + and the address for identification. */ + +#define manager_thread (&__pthread_manager_thread) +struct _pthread_descr_struct __pthread_manager_thread = { + .p_header.data.self = &__pthread_manager_thread, + .p_header.data.multiple_threads = 1, + .p_lock = &__pthread_handles[1].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &__pthread_manager_thread.p_errno, +#endif + .p_nr = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = PTHREAD_STACK_MIN / 4 +}; +#endif + +/* Pointer to the main thread (the father of the thread manager thread) */ +/* Originally, this is the initial thread, but this changes after fork() */ + +#ifdef USE_TLS +pthread_descr __pthread_main_thread; +#else +pthread_descr __pthread_main_thread = &__pthread_initial_thread; +#endif + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ + +char *__pthread_initial_thread_bos; + +/* File descriptor for sending requests to the thread manager. */ +/* Initially -1, meaning that the thread manager is not running. */ + +int __pthread_manager_request = -1; + +int __pthread_multiple_threads attribute_hidden; + +/* Other end of the pipe for sending requests to the thread manager. */ + +int __pthread_manager_reader; + +/* Limits of the thread manager stack */ + +char *__pthread_manager_thread_bos; +char *__pthread_manager_thread_tos; + +/* For process-wide exit() */ + +int __pthread_exit_requested; +int __pthread_exit_code; + +/* Maximum stack size. */ +size_t __pthread_max_stacksize; + +/* Nozero if the machine has more than one processor. */ +int __pthread_smp_kernel; + + +#if !__ASSUME_REALTIME_SIGNALS +/* Pointers that select new or old suspend/resume functions + based on availability of rt signals. */ + +void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; +void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; +#endif /* __ASSUME_REALTIME_SIGNALS */ + +/* Communicate relevant LinuxThreads constants to gdb */ + +const int __pthread_threads_max = PTHREAD_THREADS_MAX; +const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); +const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, + h_descr); +const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, + p_pid); +const int __linuxthreads_pthread_sizeof_descr + = sizeof(struct _pthread_descr_struct); + +const int __linuxthreads_initial_report_events; + +const char __linuxthreads_version[] = VERSION; + +/* Forward declarations */ + +static void pthread_onexit_process(int retcode, void *arg); +#ifndef HAVE_Z_NODELETE +static void pthread_atexit_process(void *arg, int retcode); +static void pthread_atexit_retcode(void *arg, int retcode); +#endif +static void pthread_handle_sigcancel(int sig); +static void pthread_handle_sigrestart(int sig); +static void pthread_handle_sigdebug(int sig); + +/* Signal numbers used for the communication. + In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +int __pthread_sig_restart = __SIGRTMIN; +int __pthread_sig_cancel = __SIGRTMIN + 1; +int __pthread_sig_debug = __SIGRTMIN + 2; + +extern int __libc_current_sigrtmin_private (void); + +#if !__ASSUME_REALTIME_SIGNALS +static int rtsigs_initialized; + +static void +init_rtsigs (void) +{ + if (rtsigs_initialized) + return; + + if (__libc_current_sigrtmin_private () == -1) + { + __pthread_sig_restart = SIGUSR1; + __pthread_sig_cancel = SIGUSR2; + __pthread_sig_debug = 0; + } + else + { + __pthread_restart = __pthread_restart_new; + __pthread_suspend = __pthread_wait_for_restart_signal; + __pthread_timedsuspend = __pthread_timedsuspend_new; + } + + rtsigs_initialized = 1; +} +#endif + + +/* Initialize the pthread library. + Initialization is split in two functions: + - a constructor function that blocks the __pthread_sig_restart signal + (must do this very early, since the program could capture the signal + mask with e.g. sigsetjmp before creating the first thread); + - a regular function called from pthread_create when needed. */ + +static void pthread_initialize(void) __attribute__((constructor)); + +#ifndef HAVE_Z_NODELETE +extern void *__dso_handle __attribute__ ((weak)); +#endif + + +#if defined USE_TLS && !defined SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + +struct pthread_functions __pthread_functions = + { +#if !(USE_TLS && HAVE___THREAD) + .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, + .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, + .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, +#endif + .ptr_pthread_fork = __pthread_fork, + .ptr_pthread_attr_destroy = __pthread_attr_destroy, + .ptr_pthread_attr_init = __pthread_attr_init, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr_pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr_pthread_cond_destroy = __pthread_cond_destroy, + .ptr_pthread_cond_init = __pthread_cond_init, + .ptr_pthread_cond_signal = __pthread_cond_signal, + .ptr_pthread_cond_wait = __pthread_cond_wait, + .ptr_pthread_cond_timedwait = __pthread_cond_timedwait, + .ptr_pthread_equal = __pthread_equal, + .ptr___pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr_pthread_do_exit = __pthread_do_exit, + .ptr_pthread_thread_self = __pthread_thread_self, + .ptr_pthread_cleanup_upto = __pthread_cleanup_upto, + .ptr_pthread_sigaction = __pthread_sigaction, + .ptr_pthread_sigwait = __pthread_sigwait, + .ptr_pthread_raise = __pthread_raise, + .ptr__pthread_cleanup_push = _pthread_cleanup_push, + .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop = _pthread_cleanup_pop, + .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore, + }; +#ifdef SHARED +# define ptr_pthread_functions &__pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; + +/* Do some minimal initialization which has to be done during the + startup of the C library. */ +void +__pthread_initialize_minimal(void) +{ +#ifdef USE_TLS + pthread_descr self; + + /* First of all init __pthread_handles[0] and [1] if needed. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif +# ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not + taken care of initializing the TLS data structures. */ + __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); +# elif !USE___THREAD + if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0)) + { + tcbhead_t *tcbp; + + /* There is no actual TLS being used, so the thread register + was not initialized in the dynamic linker. */ + + /* We need to install special hooks so that the malloc and memalign + calls in _dl_tls_setup and _dl_allocate_tls won't cause full + malloc initialization that will try to set up its thread state. */ + + extern void __libc_malloc_pthread_startup (bool first_time); + __libc_malloc_pthread_startup (true); + + if (__builtin_expect (_dl_tls_setup (), 0) + || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0)) + { + static const char msg[] = "\ +cannot allocate TLS data structures for initial thread\n"; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + abort (); + } + const char *lossage = TLS_INIT_TP (tcbp, 0); + if (__builtin_expect (lossage != NULL, 0)) + { + static const char msg[] = "cannot set up thread-local storage: "; + const char nl = '\n'; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + lossage, strlen (lossage))); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1)); + } + + /* Though it was allocated with libc's malloc, that was done without + the user's __malloc_hook installed. A later realloc that uses + the hooks might not work with that block from the plain malloc. + So we record this block as unfreeable just as the dynamic linker + does when it allocates the DTV before the libc malloc exists. */ + GL(dl_initial_dtv) = GET_DTV (tcbp); + + __libc_malloc_pthread_startup (false); + } +# endif + + self = THREAD_SELF; + + /* The memory for the thread descriptor was allocated elsewhere as + part of the TLS allocation. We have to initialize the data + structure by hand. This initialization must mirror the struct + definition above. */ + self->p_nextlive = self->p_prevlive = self; + self->p_tid = PTHREAD_THREADS_MAX; + self->p_lock = &__pthread_handles[0].h_lock; +# ifndef HAVE___THREAD + self->p_errnop = &_errno; + self->p_h_errnop = &_h_errno; +# endif + /* self->p_start_args need not be initialized, it's all zero. */ + self->p_userstack = 1; +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF; + + /* Another variable which points to the thread descriptor. */ + __pthread_main_thread = self; + + /* And fill in the pointer the the thread __pthread_handles array. */ + __pthread_handles[0].h_descr = self; + +#else /* USE_TLS */ + + /* First of all init __pthread_handles[0] and [1]. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif + __pthread_handles[0].h_descr = &__pthread_initial_thread; + __pthread_handles[1].h_descr = &__pthread_manager_thread; + + /* If we have special thread_self processing, initialize that for the + main thread now. */ +# ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +# endif +#endif + +#if HP_TIMING_AVAIL +# ifdef USE_TLS + self->p_cpuclock_offset = GL(dl_cpuclock_offset); +# else + __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset); +# endif +#endif + + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); +} + + +void +__pthread_init_max_stacksize(void) +{ + struct rlimit limit; + size_t max_stack; + + getrlimit(RLIMIT_STACK, &limit); +#ifdef FLOATING_STACKS + if (limit.rlim_cur == RLIM_INFINITY) + limit.rlim_cur = ARCH_STACK_MAX_SIZE; +# ifdef NEED_SEPARATE_REGISTER_STACK + max_stack = limit.rlim_cur / 2; +# else + max_stack = limit.rlim_cur; +# endif +#else + /* Play with the stack size limit to make sure that no stack ever grows + beyond STACK_SIZE minus one page (to act as a guard page). */ +# ifdef NEED_SEPARATE_REGISTER_STACK + /* STACK_SIZE bytes hold both the main stack and register backing + store. The rlimit value applies to each individually. */ + max_stack = STACK_SIZE/2 - __getpagesize (); +# else + max_stack = STACK_SIZE - __getpagesize(); +# endif + if (limit.rlim_cur > max_stack) { + limit.rlim_cur = max_stack; + setrlimit(RLIMIT_STACK, &limit); + } +#endif + __pthread_max_stacksize = max_stack; + if (max_stack / 4 < __MAX_ALLOCA_CUTOFF) + { +#ifdef USE_TLS + pthread_descr self = THREAD_SELF; + self->p_alloca_cutoff = max_stack / 4; +#else + __pthread_initial_thread.p_alloca_cutoff = max_stack / 4; +#endif + } +} + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS +# if USE___THREAD +/* When using __thread for this, we do it in libc so as not + to give libpthread its own TLS segment just for this. */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); +# else +static void ** __attribute__ ((const)) +__libc_dl_error_tsd (void) +{ + return &thread_self ()->p_libc_specific[_LIBC_TSD_KEY_DL_ERROR]; +} +# endif +#endif + +#ifdef USE_TLS +static __inline__ void __attribute__((always_inline)) +init_one_static_tls (pthread_descr descr, struct link_map *map) +{ +# if TLS_TCB_AT_TP + dtv_t *dtv = GET_DTV (descr); + void *dest = (char *) descr - map->l_tls_offset; +# elif TLS_DTV_AT_TP + dtv_t *dtv = GET_DTV ((pthread_descr) ((char *) descr + TLS_PRE_TCB_SIZE)); + void *dest = (char *) descr + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +static void +__pthread_init_static_tls (struct link_map *map) +{ + size_t i; + + for (i = 0; i < PTHREAD_THREADS_MAX; ++i) + if (__pthread_handles[i].h_descr != NULL && i != 1) + { + __pthread_lock (&__pthread_handles[i].h_lock, NULL); + if (__pthread_handles[i].h_descr != NULL) + init_one_static_tls (__pthread_handles[i].h_descr, map); + __pthread_unlock (&__pthread_handles[i].h_lock); + } +} +#endif + +static void pthread_initialize(void) +{ + struct sigaction sa; + sigset_t mask; + + /* If already done (e.g. by a constructor called earlier!), bail out */ + if (__pthread_initial_thread_bos != NULL) return; +#ifdef TEST_FOR_COMPARE_AND_SWAP + /* Test if compare-and-swap is available */ + __pthread_has_cas = compare_and_swap_is_available(); +#endif +#ifdef FLOATING_STACKS + /* We don't need to know the bottom of the stack. Give the pointer some + value to signal that initialization happened. */ + __pthread_initial_thread_bos = (void *) -1l; +#else + /* Determine stack size limits . */ + __pthread_init_max_stacksize (); +# ifdef _STACK_GROWS_UP + /* The initial thread already has all the stack it needs */ + __pthread_initial_thread_bos = (char *) + ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1)); +# else + /* For the initial stack, reserve at least STACK_SIZE bytes of stack + below the current stack address, and align that on a + STACK_SIZE boundary. */ + __pthread_initial_thread_bos = + (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); +# endif +#endif +#ifdef USE_TLS + /* Update the descriptor for the initial thread. */ + THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid()); +# if !defined HAVE___THREAD && (defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__) + /* Likewise for the resolver state _res. */ + THREAD_SETMEM (((pthread_descr) NULL), p_resp, &_res); +# endif +#else + /* Update the descriptor for the initial thread. */ + __pthread_initial_thread.p_pid = __getpid(); +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + /* Likewise for the resolver state _res. */ + __pthread_initial_thread.p_resp = &_res; +# endif +#endif +#if !__ASSUME_REALTIME_SIGNALS + /* Initialize real-time signals. */ + init_rtsigs (); +#endif + /* Setup signal handlers for the initial thread. + Since signal handlers are shared between threads, these settings + will be inherited by all other threads. */ + sa.sa_handler = pthread_handle_sigrestart; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + sa.sa_handler = pthread_handle_sigcancel; + sigaddset(&sa.sa_mask, __pthread_sig_restart); + /* sa.sa_flags = 0; */ + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) { + sa.sa_handler = pthread_handle_sigdebug; + sigemptyset(&sa.sa_mask); + /* sa.sa_flags = 0; */ + __libc_sigaction(__pthread_sig_debug, &sa, NULL); + } + /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ + sigemptyset(&mask); + sigaddset(&mask, __pthread_sig_restart); + sigprocmask(SIG_BLOCK, &mask, NULL); + /* And unblock __pthread_sig_cancel if it has been blocked. */ + sigdelset(&mask, __pthread_sig_restart); + sigaddset(&mask, __pthread_sig_cancel); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Register an exit function to kill all other threads. */ + /* Do it early so that user-registered atexit functions are called + before pthread_*exit_process. */ +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL, + __dso_handle); + else +#endif + __on_exit (pthread_onexit_process, NULL); + /* How many processors. */ + __pthread_smp_kernel = is_smp_system (); + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + + /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock, + keep the lock count from the ld.so implementation. */ + GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock; + GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock; + unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__m_count; + GL(dl_load_lock).mutex.__m_count = 0; + while (rtld_lock_count-- > 0) + __pthread_mutex_lock (&GL(dl_load_lock).mutex); +#endif + +#ifdef USE_TLS + GL(dl_init_static_tls) = &__pthread_init_static_tls; +#endif +} + +void __pthread_initialize(void) +{ + pthread_initialize(); +} + +int __pthread_initialize_manager(void) +{ + int manager_pipe[2]; + int pid; + struct pthread_request request; + int report_events; + pthread_descr mgr; +#ifdef USE_TLS + tcbhead_t *tcbp; +#endif + + __pthread_multiple_threads = 1; +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + __pthread_main_thread->p_multiple_threads = 1; +#endif + *__libc_multiple_threads_ptr = 1; + +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL, + __dso_handle); +#endif + + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + /* If basic initialization not done yet (e.g. we're called from a + constructor run before our constructor), do it now */ + if (__pthread_initial_thread_bos == NULL) pthread_initialize(); + /* Setup stack for thread manager */ + __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); + if (__pthread_manager_thread_bos == NULL) return -1; + __pthread_manager_thread_tos = + __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; + /* Setup pipe to communicate with thread manager */ + if (pipe(manager_pipe) == -1) { + free(__pthread_manager_thread_bos); + return -1; + } + +#ifdef USE_TLS + /* Allocate memory for the thread descriptor and the dtv. */ + tcbp = _dl_allocate_tls (NULL); + if (tcbp == NULL) { + free(__pthread_manager_thread_bos); + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); + return -1; + } + +# if TLS_TCB_AT_TP + mgr = (pthread_descr) tcbp; +# elif TLS_DTV_AT_TP + /* pthread_descr is located right below tcbhead_t which _dl_allocate_tls + returns. */ + mgr = (pthread_descr) ((char *) tcbp - TLS_PRE_TCB_SIZE); +# endif + __pthread_handles[1].h_descr = manager_thread = mgr; + + /* Initialize the descriptor. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + mgr->p_header.data.tcb = tcbp; + mgr->p_header.data.self = mgr; + mgr->p_header.data.multiple_threads = 1; +#elif TLS_MULTIPLE_THREADS_IN_TCB + mgr->p_multiple_threads = 1; +#endif + mgr->p_lock = &__pthread_handles[1].h_lock; +# ifndef HAVE___THREAD + mgr->p_errnop = &mgr->p_errno; +# endif + mgr->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); + mgr->p_nr = 1; +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + mgr->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; +#else + mgr = &__pthread_manager_thread; +#endif + + __pthread_manager_request = manager_pipe[1]; /* writing end */ + __pthread_manager_reader = manager_pipe[0]; /* reading end */ + + /* Start the thread manager */ + pid = 0; +#ifdef USE_TLS + if (__linuxthreads_initial_report_events != 0) + THREAD_SETMEM (((pthread_descr) NULL), p_report_events, + __linuxthreads_initial_report_events); + report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); +#else + if (__linuxthreads_initial_report_events != 0) + __pthread_initial_thread.p_report_events + = __linuxthreads_initial_report_events; + report_events = __pthread_initial_thread.p_report_events; +#endif + if (__builtin_expect (report_events, 0)) + { + /* It's a bit more complicated. We have to report the creation of + the manager thread. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + uint32_t event_bits; + +#ifdef USE_TLS + event_bits = THREAD_GETMEM_NC (((pthread_descr) NULL), + p_eventbuf.eventmask.event_bits[idx]); +#else + event_bits = __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]; +#endif + + if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits)) + != 0) + { + __pthread_lock(mgr->p_lock, NULL); + +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + mgr); +#else + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + mgr); +#endif + + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + mgr->p_eventbuf.eventdata = mgr; + mgr->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = mgr; + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + } + + /* Now restart the thread. */ + __pthread_unlock(mgr->p_lock); + } + } + + if (__builtin_expect (pid, 0) == 0) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); +#else + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, mgr); +#endif + } + if (__builtin_expect (pid, 0) == -1) { +#ifdef USE_TLS + _dl_deallocate_tls (tcbp, true); +#endif + free(__pthread_manager_thread_bos); + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); + return -1; + } + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + /* Make gdb aware of new thread manager */ + if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) + { + raise(__pthread_sig_debug); + /* We suspend ourself and gdb will wake us up when it is + ready to handle us. */ + __pthread_wait_for_restart_signal(thread_self()); + } + /* Synchronize debugging of the thread manager */ + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + return 0; +} + +/* Thread creation */ + +int __pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + pthread_descr self = thread_self(); + struct pthread_request request; + int retval; + if (__builtin_expect (__pthread_manager_request, 0) < 0) { + if (__pthread_initialize_manager() < 0) return EAGAIN; + } + request.req_thread = self; + request.req_kind = REQ_CREATE; + request.req_args.create.attr = attr; + request.req_args.create.fn = start_routine; + request.req_args.create.arg = arg; + sigprocmask(SIG_SETMASK, (const sigset_t *) NULL, + &request.req_args.create.mask); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + retval = THREAD_GETMEM(self, p_retcode); + if (__builtin_expect (retval, 0) == 0) + *thread = (pthread_t) THREAD_GETMEM(self, p_retval); + return retval; +} +strong_alias (__pthread_create, pthread_create) + +/* Simple operations on thread identifiers */ + +pthread_descr __pthread_thread_self(void) +{ + return thread_self(); +} + +pthread_t __pthread_self(void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM(self, p_tid); +} +strong_alias (__pthread_self, pthread_self) + +int __pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) + +/* Helper function for thread_self in the case of user-provided stacks */ + +#ifndef THREAD_SELF + +pthread_descr __pthread_find_self(void) +{ + char * sp = CURRENT_STACK_FRAME; + pthread_handle h; + + /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is + the manager threads handled specially in thread_self(), so start at 2 */ + h = __pthread_handles + 2; +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < (char *) h->h_descr->p_guardaddr)) h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; +# endif + return h->h_descr; +} + +#else + +pthread_descr __pthread_self_stack(void) +{ + char *sp = CURRENT_STACK_FRAME; + pthread_handle h; + + if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) + return manager_thread; + h = __pthread_handles + 2; +# ifdef USE_TLS +# ifdef _STACK_GROWS_UP + while (h->h_descr == NULL + || ! (sp >= h->h_descr->p_stackaddr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (h->h_descr == NULL + || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) + h++; +# endif +# else +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) + h++; +# endif +# endif + return h->h_descr; +} + +#endif + +/* Thread scheduling */ + +int __pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1, + 0)) { + __pthread_unlock(&handle->h_lock); + return errno; + } + th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; + __pthread_unlock(&handle->h_lock); + if (__pthread_manager_request >= 0) + __pthread_manager_adjust_prio(th->p_priority); + return 0; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) + +int __pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + int pid, pol; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + pol = __sched_getscheduler(pid); + if (__builtin_expect (pol, 0) == -1) return errno; + if (__sched_getparam(pid, param) == -1) return errno; + *policy = pol; + return 0; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) + +/* Process-wide exit() request */ + +static void pthread_onexit_process(int retcode, void *arg) +{ + if (__builtin_expect (__pthread_manager_request, 0) >= 0) { + struct pthread_request request; + pthread_descr self = thread_self(); + + request.req_thread = self; + request.req_kind = REQ_PROCESS_EXIT; + request.req_args.exit.code = retcode; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) + { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + /* Since all threads have been asynchronously terminated + (possibly holding locks), free cannot be used any more. + For mtrace, we'd like to print something though. */ + /* #ifdef USE_TLS + tcbhead_t *tcbp = (tcbhead_t *) manager_thread; + # if TLS_DTV_AT_TP + tcbp = (tcbhead_t) ((char *) tcbp + TLS_PRE_TCB_SIZE); + # endif + _dl_deallocate_tls (tcbp, true); + #endif + free (__pthread_manager_thread_bos); */ + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } + } +} + +#ifndef HAVE_Z_NODELETE +static int __pthread_atexit_retcode; + +static void pthread_atexit_process(void *arg, int retcode) +{ + pthread_onexit_process (retcode ?: __pthread_atexit_retcode, arg); +} + +static void pthread_atexit_retcode(void *arg, int retcode) +{ + __pthread_atexit_retcode = retcode; +} +#endif + +/* The handler for the RESTART signal just records the signal received + in the thread descriptor, and optionally performs a siglongjmp + (for pthread_cond_timedwait). */ + +static void pthread_handle_sigrestart(int sig) +{ + pthread_descr self = check_thread_self(); + THREAD_SETMEM(self, p_signal, sig); + if (THREAD_GETMEM(self, p_signal_jmp) != NULL) + siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); +} + +/* The handler for the CANCEL signal checks for cancellation + (in asynchronous mode), for process-wide exit and exec requests. + For the thread manager thread, redirect the signal to + __pthread_manager_sighandler. */ + +static void pthread_handle_sigcancel(int sig) +{ + pthread_descr self = check_thread_self(); + sigjmp_buf * jmpbuf; + + if (self == manager_thread) + { + __pthread_manager_sighandler(sig); + return; + } + if (__builtin_expect (__pthread_exit_requested, 0)) { + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + +/* Handler for the DEBUG signal. + The debugging strategy is as follows: + On reception of a REQ_DEBUG request (sent by new threads created to + the thread manager under debugging mode), the thread manager throws + __pthread_sig_debug to itself. The debugger (if active) intercepts + this signal, takes into account new threads and continue execution + of the thread manager by propagating the signal because it doesn't + know what it is specifically done for. In the current implementation, + the thread manager simply discards it. */ + +static void pthread_handle_sigdebug(int sig) +{ + /* Nothing */ +} + +/* Reset the state of the thread machinery after a fork(). + Close the pipe used for requests and set the main thread to the forked + thread. + Notice that we can't free the stack segments, as the forked thread + may hold pointers into them. */ + +void __pthread_reset_main_thread(void) +{ + pthread_descr self = thread_self(); + + if (__pthread_manager_request != -1) { + /* Free the thread manager stack */ + free(__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + /* Close the two ends of the pipe */ + close_not_cancel(__pthread_manager_request); + close_not_cancel(__pthread_manager_reader); + __pthread_manager_request = __pthread_manager_reader = -1; + } + + /* Update the pid of the main thread */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Make the forked thread the main thread */ + __pthread_main_thread = self; + THREAD_SETMEM(self, p_nextlive, self); + THREAD_SETMEM(self, p_prevlive, self); +#if !(USE_TLS && HAVE___THREAD) + /* Now this thread modifies the global variables. */ + THREAD_SETMEM(self, p_errnop, &_errno); + THREAD_SETMEM(self, p_h_errnop, &_h_errno); +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + THREAD_SETMEM(self, p_resp, &_res); +# endif +#endif + +#ifndef FLOATING_STACKS + /* This is to undo the setrlimit call in __pthread_init_max_stacksize. + XXX This can be wrong if the user set the limit during the run. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_STACK, &limit) == 0 + && limit.rlim_cur != limit.rlim_max) + { + limit.rlim_cur = limit.rlim_max; + setrlimit(RLIMIT_STACK, &limit); + } + } +#endif +} + +/* Process-wide exec() request */ + +void __pthread_kill_other_threads_np(void) +{ + struct sigaction sa; + /* Terminate all other threads and thread manager */ + pthread_onexit_process(0, NULL); + /* Make current thread the main thread in case the calling thread + changes its mind, does not exec(), and creates new threads instead. */ + __pthread_reset_main_thread(); + + /* Reset the signal handlers behaviour for the signals the + implementation uses since this would be passed to the new + process. */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) + __libc_sigaction(__pthread_sig_debug, &sa, NULL); +} +weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) + +/* Concurrency symbol level. */ +static int current_level; + +int __pthread_setconcurrency(int level) +{ + /* We don't do anything unless we have found a useful interpretation. */ + current_level = level; + return 0; +} +weak_alias (__pthread_setconcurrency, pthread_setconcurrency) + +int __pthread_getconcurrency(void) +{ + return current_level; +} +weak_alias (__pthread_getconcurrency, pthread_getconcurrency) + +/* Primitives for controlling thread execution */ + +void __pthread_wait_for_restart_signal(pthread_descr self) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ + sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ + THREAD_SETMEM(self, p_signal, 0); + do { + __pthread_sigsuspend(&mask); /* Wait for signal. Must not be a + cancellation point. */ + } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ +} + +#if !__ASSUME_REALTIME_SIGNALS +/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT + signals. + On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. + Since the restart signal does not queue, we use an atomic counter to create + queuing semantics. This is needed to resolve a rare race condition in + pthread_cond_timedwait_relative. */ + +void __pthread_restart_old(pthread_descr th) +{ + if (atomic_increment(&th->p_resume_count) == -1) + kill(th->p_pid, __pthread_sig_restart); +} + +void __pthread_suspend_old(pthread_descr self) +{ + if (atomic_decrement(&self->p_resume_count) <= 0) + __pthread_wait_for_restart_signal(self); +} + +int +__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (atomic_decrement(&self->p_resume_count) == 0) { + /* Set up a longjmp handler for the restart signal, unblock + the signal and sleep. */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + } + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + we know we have been dequeued and resumed and that the + resume count is balanced. Otherwise, there are some + cases to consider. First, try to bump up the resume count + back to zero. If it goes to 1, it means restart() was + invoked on this thread. The signal must be consumed + and the count bumped down and everything is cool. We + can return a 1 to the caller. + Otherwise, no restart was delivered yet, so a potential + race exists; we return a 0 to the caller which must deal + with this race in an appropriate way; for example by + atomically removing the thread from consideration for a + wakeup---if such a thing fails, it means a restart is + being delivered. */ + + if (!was_signalled) { + if (atomic_increment(&self->p_resume_count) != -1) { + __pthread_wait_for_restart_signal(self); + atomic_decrement(&self->p_resume_count); /* should be zero now! */ + /* woke spontaneously and consumed restart signal */ + return 1; + } + /* woke spontaneously but did not consume restart---caller must resolve */ + return 0; + } + /* woken due to restart signal */ + return 1; +} +#endif /* __ASSUME_REALTIME_SIGNALS */ + +void __pthread_restart_new(pthread_descr th) +{ + /* The barrier is proabably not needed, in which case it still documents + our assumptions. The intent is to commit previous writes to shared + memory so the woken thread will have a consistent view. Complementary + read barriers are present to the suspend functions. */ + WRITE_MEMORY_BARRIER(); + kill(th->p_pid, __pthread_sig_restart); +} + +/* There is no __pthread_suspend_new because it would just + be a wasteful wrapper for __pthread_wait_for_restart_signal */ + +int +__pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + everything is cool. We have been removed from whatever + we were waiting on by the other thread, and consumed its signal. + + Otherwise we this thread woke up spontaneously, or due to a signal other + than restart. This is an ambiguous case that must be resolved by + the caller; the thread is still eligible for a restart wakeup + so there is a race. */ + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ + return was_signalled; +} + + +/* Debugging aid */ + +#ifdef DEBUG +#include + +void __pthread_message(const char * fmt, ...) +{ + char buffer[1024]; + va_list args; + sprintf(buffer, "%05d : ", __getpid()); + va_start(args, fmt); + vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); + va_end(args); + TEMP_FAILURE_RETRY(write_not_cancel(2, buffer, strlen(buffer))); +} + +#endif diff --git a/libpthread/linuxthreads/pthread_atfork.c b/libpthread/linuxthreads/pthread_atfork.c new file mode 100644 index 0000000..2464acb --- /dev/null +++ b/libpthread/linuxthreads/pthread_atfork.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "internals.h" +#include + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + + +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +int +#ifndef __pthread_atfork +/* Don't mark the compatibility function as hidden. */ +attribute_hidden +#endif +__pthread_atfork (prepare, parent, child) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); +{ + return __register_atfork (prepare, parent, child, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef __pthread_atfork +extern int pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)) attribute_hidden; +strong_alias (__pthread_atfork, pthread_atfork) +#endif diff --git a/libpthread/linuxthreads/pthread_setegid.c b/libpthread/linuxthreads/pthread_setegid.c new file mode 100644 index 0000000..e357bb9 --- /dev/null +++ b/libpthread/linuxthreads/pthread_setegid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setegid_np (gid_t gid); +int +pthread_setegid_np (gid_t gid) +{ + return setegid (gid); +} diff --git a/libpthread/linuxthreads/pthread_seteuid.c b/libpthread/linuxthreads/pthread_seteuid.c new file mode 100644 index 0000000..6a1464c --- /dev/null +++ b/libpthread/linuxthreads/pthread_seteuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_seteuid_np (uid_t uid); +int +pthread_seteuid_np (uid_t uid) +{ + return seteuid (uid); +} diff --git a/libpthread/linuxthreads/pthread_setgid.c b/libpthread/linuxthreads/pthread_setgid.c new file mode 100644 index 0000000..31b5a59 --- /dev/null +++ b/libpthread/linuxthreads/pthread_setgid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setgid_np (gid_t gid); +int +pthread_setgid_np (gid_t gid) +{ + return setgid (gid); +} diff --git a/libpthread/linuxthreads/pthread_setregid.c b/libpthread/linuxthreads/pthread_setregid.c new file mode 100644 index 0000000..8964eb7 --- /dev/null +++ b/libpthread/linuxthreads/pthread_setregid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setregid_np (gid_t rgid, gid_t egid); +int +pthread_setregid_np (gid_t rgid, gid_t egid) +{ + return setregid (rgid, egid); +} diff --git a/libpthread/linuxthreads/pthread_setresgid.c b/libpthread/linuxthreads/pthread_setresgid.c new file mode 100644 index 0000000..a330afc --- /dev/null +++ b/libpthread/linuxthreads/pthread_setresgid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid); +int +pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid) +{ + return setresgid (rgid, egid, sgid); +} diff --git a/libpthread/linuxthreads/pthread_setresuid.c b/libpthread/linuxthreads/pthread_setresuid.c new file mode 100644 index 0000000..0fa2895 --- /dev/null +++ b/libpthread/linuxthreads/pthread_setresuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid); +int +pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid) +{ + return setresuid (ruid, euid, suid); +} diff --git a/libpthread/linuxthreads/pthread_setreuid.c b/libpthread/linuxthreads/pthread_setreuid.c new file mode 100644 index 0000000..78738e3 --- /dev/null +++ b/libpthread/linuxthreads/pthread_setreuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setreuid_np (uid_t ruid, uid_t euid); +int +pthread_setreuid_np (uid_t ruid, uid_t euid) +{ + return setreuid (ruid, euid); +} diff --git a/libpthread/linuxthreads/pthread_setuid.c b/libpthread/linuxthreads/pthread_setuid.c new file mode 100644 index 0000000..107001e --- /dev/null +++ b/libpthread/linuxthreads/pthread_setuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setuid_np (uid_t uid); +int +pthread_setuid_np (uid_t uid) +{ + return setuid (uid); +} diff --git a/libpthread/linuxthreads/queue.h b/libpthread/linuxthreads/queue.h new file mode 100644 index 0000000..e50517f --- /dev/null +++ b/libpthread/linuxthreads/queue.h @@ -0,0 +1,61 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Waiting queues */ + +/* Waiting queues are represented by lists of thread descriptors + linked through their p_nextwaiting field. The lists are kept + sorted by decreasing priority, and then decreasing waiting time. */ + +static __inline__ void enqueue(pthread_descr * q, pthread_descr th) +{ + int prio = th->p_priority; + ASSERT(th->p_nextwaiting == NULL); + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (prio > (*q)->p_priority) { + th->p_nextwaiting = *q; + *q = th; + return; + } + } + *q = th; +} + +static __inline__ pthread_descr dequeue(pthread_descr * q) +{ + pthread_descr th; + th = *q; + if (th != NULL) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + } + return th; +} + +static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) +{ + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (*q == th) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + return 1; + } + } + return 0; +} + +static __inline__ int queue_is_empty(pthread_descr * q) +{ + return *q == NULL; +} diff --git a/libpthread/linuxthreads/restart.h b/libpthread/linuxthreads/restart.h new file mode 100644 index 0000000..f53642e --- /dev/null +++ b/libpthread/linuxthreads/restart.h @@ -0,0 +1,49 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include +#include + +/* Primitives for controlling thread execution */ + +static __inline__ void restart(pthread_descr th) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_restart_new(th); +#else + __pthread_restart(th); +#endif +} + +static __inline__ void suspend(pthread_descr self) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_wait_for_restart_signal(self); +#else + __pthread_suspend(self); +#endif +} + +static __inline__ int timedsuspend(pthread_descr self, + const struct timespec *abstime) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + return __pthread_timedsuspend_new(self, abstime); +#else + return __pthread_timedsuspend(self, abstime); +#endif +} diff --git a/libpthread/linuxthreads/rwlock.c b/libpthread/linuxthreads/rwlock.c new file mode 100644 index 0000000..f565f18 --- /dev/null +++ b/libpthread/linuxthreads/rwlock.c @@ -0,0 +1,658 @@ +/* Read-write lock implementation. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Xavier Leroy + and Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "internals.h" +#include "queue.h" +#include "spinlock.h" +#include "restart.h" + +/* Function called by pthread_cancel to remove the thread from + waiting inside pthread_rwlock_timedrdlock or pthread_rwlock_timedwrlock. */ + +static int rwlock_rd_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_read_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +static int rwlock_wr_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +/* + * Check whether the calling thread already owns one or more read locks on the + * specified lock. If so, return a pointer to the read lock info structure + * corresponding to that lock. + */ + +static pthread_readlock_info * +rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info; + + for (info = THREAD_GETMEM (self, p_readlock_list); info != NULL; + info = info->pr_next) + { + if (info->pr_lock == rwlock) + return info; + } + + return NULL; +} + +/* + * Add a new lock to the thread's list of locks for which it has a read lock. + * A new info node must be allocated for this, which is taken from the thread's + * free list, or by calling malloc. If malloc fails, a null pointer is + * returned. Otherwise the lock info structure is initialized and pushed + * onto the thread's list. + */ + +static pthread_readlock_info * +rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info = THREAD_GETMEM (self, p_readlock_free); + + if (info != NULL) + THREAD_SETMEM (self, p_readlock_free, info->pr_next); + else + info = malloc(sizeof *info); + + if (info == NULL) + return NULL; + + info->pr_lock_count = 1; + info->pr_lock = rwlock; + info->pr_next = THREAD_GETMEM (self, p_readlock_list); + THREAD_SETMEM (self, p_readlock_list, info); + + return info; +} + +/* + * If the thread owns a read lock over the given pthread_rwlock_t, + * and this read lock is tracked in the thread's lock list, + * this function returns a pointer to the info node in that list. + * It also decrements the lock count within that node, and if + * it reaches zero, it removes the node from the list. + * If nothing is found, it returns a null pointer. + */ + +static pthread_readlock_info * +rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info **pinfo; + + for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) + { + if ((*pinfo)->pr_lock == rwlock) + { + pthread_readlock_info *info = *pinfo; + if (--info->pr_lock_count == 0) + *pinfo = info->pr_next; + return info; + } + } + + return NULL; +} + +/* + * This function checks whether the conditions are right to place a read lock. + * It returns 1 if so, otherwise zero. The rwlock's internal lock must be + * locked upon entry. + */ + +static int +rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) +{ + /* Can't readlock; it is write locked. */ + if (rwlock->__rw_writer != NULL) + return 0; + + /* Lock prefers readers; get it. */ + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) + return 1; + + /* Lock prefers writers, but none are waiting. */ + if (queue_is_empty(&rwlock->__rw_write_waiting)) + return 1; + + /* Writers are waiting, but this thread already has a read lock */ + if (have_lock_already) + return 1; + + /* Writers are waiting, and this is a new lock */ + return 0; +} + +/* + * This function helps support brain-damaged recursive read locking + * semantics required by Unix 98, while maintaining write priority. + * This basically determines whether this thread already holds a read lock + * already. It returns 1 if so, otherwise it returns 0. + * + * If the thread has any ``untracked read locks'' then it just assumes + * that this lock is among them, just to be safe, and returns 1. + * + * Also, if it finds the thread's lock in the list, it sets the pointer + * referenced by pexisting to refer to the list entry. + * + * If the thread has no untracked locks, and the lock is not found + * in its list, then it is added to the list. If this fails, + * then *pout_of_mem is set to 1. + */ + +static int +rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, + pthread_readlock_info **pexisting, int *pout_of_mem) +{ + pthread_readlock_info *existing = NULL; + int out_of_mem = 0, have_lock_already = 0; + pthread_descr self = *pself; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + if (!self) + *pself = self = thread_self(); + + existing = rwlock_is_in_list(self, rwlock); + + if (existing != NULL + || THREAD_GETMEM (self, p_untracked_readlock_count) > 0) + have_lock_already = 1; + else + { + existing = rwlock_add_to_list(self, rwlock); + if (existing == NULL) + out_of_mem = 1; + } + } + + *pout_of_mem = out_of_mem; + *pexisting = existing; + + return have_lock_already; +} + +int +__pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + __pthread_init_lock(&rwlock->__rw_lock); + rwlock->__rw_readers = 0; + rwlock->__rw_writer = NULL; + rwlock->__rw_read_waiting = NULL; + rwlock->__rw_write_waiting = NULL; + + if (attr == NULL) + { + rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; + rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; + } + else + { + rwlock->__rw_kind = attr->__lockkind; + rwlock->__rw_pshared = attr->__pshared; + } + + return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) + + +int +__pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int readers; + _pthread_descr writer; + + __pthread_lock (&rwlock->__rw_lock, NULL); + readers = rwlock->__rw_readers; + writer = rwlock->__rw_writer; + __pthread_unlock (&rwlock->__rw_lock); + + if (readers > 0 || writer != NULL) + return EBUSY; + + return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) + +int +__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) + +int +__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_rd_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } + + __pthread_set_own_extricate_if (self, 0); + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock) + +int +__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self(); + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + int retval = EBUSY; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + __pthread_lock (&rwlock->__rw_lock, self); + + /* 0 is passed to here instead of have_lock_already. + This is to meet Single Unix Spec requirements: + if writers are waiting, pthread_rwlock_tryrdlock + does not acquire a read lock, even if the caller has + one or more read locks already. */ + + if (rwlock_can_rdlock(rwlock, 0)) + { + ++rwlock->__rw_readers; + retval = 0; + } + + __pthread_unlock (&rwlock->__rw_lock); + + if (retval == 0) + { + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + } + + return retval; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) + + +int +__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self (); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} +strong_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) + + +int +__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_wr_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_set_own_extricate_if (self, 0); + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } +} +strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock) + + +int +__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = thread_self (); + result = 0; + } + __pthread_unlock (&rwlock->__rw_lock); + + return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) + + +int +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + pthread_descr torestart; + pthread_descr th; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_writer != NULL) + { + /* Unlocking a write lock. */ + if (rwlock->__rw_writer != thread_self ()) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + rwlock->__rw_writer = NULL; + + if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP + && !queue_is_empty(&rwlock->__rw_read_waiting)) + || (th = dequeue(&rwlock->__rw_write_waiting)) == NULL) + { + /* Restart all waiting readers. */ + torestart = rwlock->__rw_read_waiting; + rwlock->__rw_read_waiting = NULL; + __pthread_unlock (&rwlock->__rw_lock); + while ((th = dequeue (&torestart)) != NULL) + restart (th); + } + else + { + /* Restart one waiting writer. */ + __pthread_unlock (&rwlock->__rw_lock); + restart (th); + } + } + else + { + /* Unlocking a read lock. */ + if (rwlock->__rw_readers == 0) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + + --rwlock->__rw_readers; + if (rwlock->__rw_readers == 0) + /* Restart one waiting writer, if any. */ + th = dequeue (&rwlock->__rw_write_waiting); + else + th = NULL; + + __pthread_unlock (&rwlock->__rw_lock); + if (th != NULL) + restart (th); + + /* Recursive lock fixup */ + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + pthread_descr self = thread_self(); + pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); + + if (victim != NULL) + { + if (victim->pr_lock_count == 0) + { + victim->pr_next = THREAD_GETMEM (self, p_readlock_free); + THREAD_SETMEM (self, p_readlock_free, victim); + } + } + else + { + int val = THREAD_GETMEM (self, p_untracked_readlock_count); + if (val > 0) + THREAD_SETMEM (self, p_untracked_readlock_count, val - 1); + } + } + } + + return 0; +} +strong_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) + + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + attr->__lockkind = 0; + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} + + +int +__pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy) + + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) +{ + *pshared = attr->__pshared; + return 0; +} + + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + attr->__pshared = pshared; + + return 0; +} + + +int +pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) +{ + *pref = attr->__lockkind; + return 0; +} + + +int +pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) +{ + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP + && pref != PTHREAD_RWLOCK_DEFAULT_NP) + return EINVAL; + + attr->__lockkind = pref; + + return 0; +} diff --git a/libpthread/linuxthreads/semaphore.c b/libpthread/linuxthreads/semaphore.c new file mode 100644 index 0000000..392c37b --- /dev/null +++ b/libpthread/linuxthreads/semaphore.c @@ -0,0 +1,298 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include "pthread.h" +#include "semaphore.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" +#include + +int sem_init(sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + __pthread_init_lock(&sem->__sem_lock); + sem->__sem_value = value; + sem->__sem_waiting = NULL; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside sem_wait. */ + +static int new_sem_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + sem_t *sem = obj; + int did_remove = 0; + + __pthread_lock(&sem->__sem_lock, self); + did_remove = remove_from_queue(&sem->__sem_waiting, th); + __pthread_unlock(&sem->__sem_lock); + + return did_remove; +} + +int sem_wait(sem_t * sem) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + sem->__sem_value--; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Wait for sem_post or cancellation, or fall through if already canceled */ + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + +int sem_trywait(sem_t * sem) +{ + int retval; + + __pthread_lock(&sem->__sem_lock, NULL); + if (sem->__sem_value == 0) { + errno = EAGAIN; + retval = -1; + } else { + sem->__sem_value--; + retval = 0; + } + __pthread_unlock(&sem->__sem_lock); + return retval; +} + +int sem_post(sem_t * sem) +{ + pthread_descr self = thread_self(); + pthread_descr th; + struct pthread_request request; + + if (THREAD_GETMEM(self, p_in_sighandler) == NULL) { + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_waiting == NULL) { + if (sem->__sem_value >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + __pthread_unlock(&sem->__sem_lock); + return -1; + } + sem->__sem_value++; + __pthread_unlock(&sem->__sem_lock); + } else { + th = dequeue(&sem->__sem_waiting); + __pthread_unlock(&sem->__sem_lock); + th->p_sem_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + } else { + /* If we're in signal handler, delegate post operation to + the thread manager. */ + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) { + errno = EAGAIN; + return -1; + } + } + request.req_kind = REQ_POST; + request.req_args.post = sem; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int sem_getvalue(sem_t * sem, int * sval) +{ + *sval = sem->__sem_value; + return 0; +} + +int sem_destroy(sem_t * sem) +{ + if (sem->__sem_waiting != NULL) { + __set_errno (EBUSY); + return -1; + } + return 0; +} + +sem_t *sem_open(const char *name, int oflag, ...) +{ + __set_errno (ENOSYS); + return SEM_FAILED; +} + +int sem_close(sem_t *sem) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_unlink(const char *name) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abstime) +{ + pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + --sem->__sem_value; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { + /* The standard requires that if the function would block and the + time value is illegal, the function returns with an error. */ + __pthread_unlock(&sem->__sem_lock); + __set_errno (EINVAL); + return -1; + } + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + spurious_wakeup_count = 0; + while (1) + { + if (timedsuspend(self, abstime) == 0) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&sem->__sem_lock, self); + was_on_queue = remove_from_queue(&sem->__sem_waiting, self); + __pthread_unlock(&sem->__sem_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __set_errno (ETIMEDOUT); + return -1; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} diff --git a/libpthread/linuxthreads/semaphore.h b/libpthread/linuxthreads/semaphore.h new file mode 100644 index 0000000..3084209 --- /dev/null +++ b/libpthread/linuxthreads/semaphore.h @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors. Needed for `sem_t' definition. */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + +/* System specific semaphore definition. */ +typedef struct +{ + struct _pthread_fastlock __sem_lock; + int __sem_value; + _pthread_descr __sem_waiting; +} sem_t; + + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; + +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/libpthread/linuxthreads/sighandler.c b/libpthread/linuxthreads/sighandler.c new file mode 100644 index 0000000..9dd3e22 --- /dev/null +++ b/libpthread/linuxthreads/sighandler.c @@ -0,0 +1,71 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Signal handlers */ + +#include "internals.h" + + +/* The wrapper around user-provided signal handlers */ +void __pthread_sighandler(int signo, SIGCONTEXT ctx) +{ + pthread_descr self; + char * in_sighandler; + self = check_thread_self(); + + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + CALL_SIGHANDLER(__sighandler[signo].old, signo, ctx); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The same, this time for real-time signals. */ +void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc) +{ + pthread_descr self; + char * in_sighandler; + self = check_thread_self(); + + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + __sighandler[signo].rt(signo, si, uc); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + + +/* A signal handler that does nothing */ +void __pthread_null_sighandler(int sig) { } diff --git a/libpthread/linuxthreads/signals.c b/libpthread/linuxthreads/signals.c new file mode 100644 index 0000000..62e8321 --- /dev/null +++ b/libpthread/linuxthreads/signals.c @@ -0,0 +1,215 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of signals */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) +{ + sigset_t mask; + + if (newmask != NULL) { + mask = *newmask; + /* Don't allow __pthread_sig_restart to be unmasked. + Don't allow __pthread_sig_cancel to be masked. */ + switch(how) { + case SIG_SETMASK: + sigaddset(&mask, __pthread_sig_restart); + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_BLOCK: + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_UNBLOCK: + sigdelset(&mask, __pthread_sig_restart); + break; + } + newmask = &mask; + } + if (sigprocmask(how, newmask, oldmask) == -1) + return errno; + else + return 0; +} + +int pthread_kill(pthread_t thread, int signo) +{ + pthread_handle handle = thread_handle(thread); + int pid; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + if (kill(pid, signo) == -1) + return errno; + else + return 0; +} + +union sighandler __sighandler[NSIG] = + { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } }; + +/* The wrapper around sigaction. Install our own signal handler + around the signal. */ +int __pthread_sigaction(int sig, const struct sigaction * act, + struct sigaction * oact) +{ + struct sigaction newact; + struct sigaction *newactp; + __sighandler_t old = SIG_DFL; + + if (sig == __pthread_sig_restart || + sig == __pthread_sig_cancel || + (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) + { + __set_errno (EINVAL); + return -1; + } + if (sig > 0 && sig < NSIG) + old = (__sighandler_t) __sighandler[sig].old; + if (act) + { + newact = *act; + if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL + && sig > 0 && sig < NSIG) + { + if (act->sa_flags & SA_SIGINFO) + newact.sa_handler = (__sighandler_t) __pthread_sighandler_rt; + else + newact.sa_handler = (__sighandler_t) __pthread_sighandler; + if (old == SIG_IGN || old == SIG_DFL || old == SIG_ERR) + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + newactp = &newact; + } + else + newactp = NULL; + if (__libc_sigaction(sig, newactp, oact) == -1) + { + if (act) + __sighandler[sig].old = (arch_sighandler_t) old; + return -1; + } + if (sig > 0 && sig < NSIG) + { + if (oact != NULL + /* We may have inherited SIG_IGN from the parent, so return the + kernel's idea of the signal handler the first time + through. */ + && old != SIG_ERR) + oact->sa_handler = old; + if (act) + /* For the assignment it does not matter whether it's a normal + or real-time signal. */ + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + return 0; +} +#ifdef SHARED +strong_alias(__pthread_sigaction, __sigaction) +strong_alias(__pthread_sigaction, sigaction) +#endif + +/* sigwait -- synchronously wait for a signal */ +int __pthread_sigwait(const sigset_t * set, int * sig) +{ + __volatile__ pthread_descr self = thread_self(); + sigset_t mask; + int s; + sigjmp_buf jmpbuf; + struct sigaction sa; + + /* Get ready to block all signals except those in set + and the cancellation signal. + Also check that handlers are installed on all signals in set, + and if not, install our dummy handler. This is conformant to + POSIX: "The effect of sigwait() on the signal actions for the + signals in set is unspecified." */ + sigfillset(&mask); + sigdelset(&mask, __pthread_sig_cancel); + for (s = 1; s < NSIG; s++) { + if (sigismember(set, s) && + s != __pthread_sig_restart && + s != __pthread_sig_cancel && + s != __pthread_sig_debug) { + sigdelset(&mask, s); + if (__sighandler[s].old == (arch_sighandler_t) SIG_ERR || + __sighandler[s].old == (arch_sighandler_t) SIG_DFL || + __sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + sa.sa_handler = __pthread_null_sighandler; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(s, &sa, NULL); + } + } + } + /* Test for cancellation */ + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf); + if (! (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) { + /* Reset the signal count */ + THREAD_SETMEM(self, p_signal, 0); + /* Say we're in sigwait */ + THREAD_SETMEM(self, p_sigwaiting, 1); + /* Unblock the signals and wait for them */ + sigsuspend(&mask); + } + } + THREAD_SETMEM(self, p_cancel_jmp, NULL); + /* The signals are now reblocked. Check for cancellation */ + pthread_testcancel(); + /* We should have self->p_signal != 0 and equal to the signal received */ + *sig = THREAD_GETMEM(self, p_signal); + return 0; +} +#ifdef SHARED +strong_alias (__pthread_sigwait, sigwait) +#endif + +/* Redefine raise() to send signal to calling thread only, + as per POSIX 1003.1c */ +int __pthread_raise (int sig) +{ + int retcode = pthread_kill(pthread_self(), sig); + if (retcode == 0) + return 0; + else { + errno = retcode; + return -1; + } +} +#ifdef SHARED +strong_alias (__pthread_raise, raise) +#endif + +/* This files handles cancellation internally. */ +LIBC_CANCEL_HANDLED (); diff --git a/libpthread/linuxthreads/specific.c b/libpthread/linuxthreads/specific.c new file mode 100644 index 0000000..92eec3d --- /dev/null +++ b/libpthread/linuxthreads/specific.c @@ -0,0 +1,241 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread-specific data */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include +#include + +/* Table of keys. */ + +static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = + { { 0, NULL } }; + +/* For debugging purposes put the maximum number of keys in a variable. */ +const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; +const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; + +/* Mutex to protect access to pthread_keys */ + +static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Create a new key */ + +int __pthread_key_create(pthread_key_t * key, destr_function destr) +{ + int i; + + pthread_mutex_lock(&pthread_keys_mutex); + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (! pthread_keys[i].in_use) { + /* Mark key in use */ + pthread_keys[i].in_use = 1; + pthread_keys[i].destr = destr; + pthread_mutex_unlock(&pthread_keys_mutex); + *key = i; + return 0; + } + } + pthread_mutex_unlock(&pthread_keys_mutex); + return EAGAIN; +} +strong_alias (__pthread_key_create, pthread_key_create) + +/* Reset deleted key's value to NULL in each live thread. + * NOTE: this executes in the context of the thread manager! */ + +struct pthread_key_delete_helper_args { + /* Damn, we need lexical closures in C! ;) */ + unsigned int idx1st, idx2nd; + pthread_descr self; +}; + +static void pthread_key_delete_helper(void *arg, pthread_descr th) +{ + struct pthread_key_delete_helper_args *args = arg; + unsigned int idx1st = args->idx1st; + unsigned int idx2nd = args->idx2nd; + pthread_descr self = args->self; + + if (self == 0) + self = args->self = thread_self(); + + if (!th->p_terminated) { + /* pthread_exit() may try to free th->p_specific[idx1st] concurrently. */ + __pthread_lock(th->p_lock, self); + if (th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + __pthread_unlock(th->p_lock); + } +} + +/* Delete a key */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_descr self = thread_self(); + + pthread_mutex_lock(&pthread_keys_mutex); + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { + pthread_mutex_unlock(&pthread_keys_mutex); + return EINVAL; + } + pthread_keys[key].in_use = 0; + pthread_keys[key].destr = NULL; + + /* Set the value of the key to NULL in all running threads, so + that if the key is reallocated later by pthread_key_create, its + associated values will be NULL in all threads. + + If no threads have been created yet, clear it just in the + current thread. */ + + struct pthread_key_delete_helper_args args; + args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (__pthread_manager_request != -1) + { + struct pthread_request request; + + args.self = 0; + + request.req_thread = self; + request.req_kind = REQ_FOR_EACH_THREAD; + request.req_args.for_each.arg = &args; + request.req_args.for_each.fn = pthread_key_delete_helper; + + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + else + { + if (self->p_specific[args.idx1st] != NULL) + self->p_specific[args.idx1st][args.idx2nd] = NULL; + } + + pthread_mutex_unlock(&pthread_keys_mutex); + return 0; +} + +/* Set the value of a key */ + +int __pthread_setspecific(pthread_key_t key, const void * pointer) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) + return EINVAL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) { + void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); + if (newp == NULL) + return ENOMEM; + THREAD_SETMEM_NC(self, p_specific[idx1st], newp); + } + THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer; + return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) + +/* Get the value of a key */ + +void * __pthread_getspecific(pthread_key_t key) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX) + return NULL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL + || !pthread_keys[key].in_use) + return NULL; + return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd]; +} +strong_alias (__pthread_getspecific, pthread_getspecific) + +/* Call the destruction routines on all keys */ + +void __pthread_destroy_specifics() +{ + pthread_descr self = thread_self(); + int i, j, round, found_nonzero; + destr_function destr; + void * data; + + for (round = 0, found_nonzero = 1; + found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; + round++) { + found_nonzero = 0; + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) + for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { + destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; + data = THREAD_GETMEM_NC(self, p_specific[i])[j]; + if (destr != NULL && data != NULL) { + THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL; + destr(data); + found_nonzero = 1; + } + } + } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { + free(THREAD_GETMEM_NC(self, p_specific[i])); + THREAD_SETMEM_NC(self, p_specific[i], NULL); + } + } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); +} + +#if !(USE_TLS && HAVE___THREAD) + +/* Thread-specific data for libc. */ + +int +__pthread_internal_tsd_set (int key, const void * pointer) +{ + pthread_descr self = thread_self(); + + THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer); + return 0; +} + +void * +__pthread_internal_tsd_get (int key) +{ + pthread_descr self = thread_self(); + + return THREAD_GETMEM_NC(self, p_libc_specific[key]); +} + +void ** __attribute__ ((__const__)) +__pthread_internal_tsd_address (int key) +{ + pthread_descr self = thread_self(); + return &self->p_libc_specific[key]; +} + +#endif diff --git a/libpthread/linuxthreads/spinlock.c b/libpthread/linuxthreads/spinlock.c new file mode 100644 index 0000000..f325402 --- /dev/null +++ b/libpthread/linuxthreads/spinlock.c @@ -0,0 +1,720 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Internal locks */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +static void __pthread_acquire(int * spinlock); + +static __inline__ void __pthread_release(int * spinlock) +{ + WRITE_MEMORY_BARRIER(); + *spinlock = __LT_SPINLOCK_INIT; + __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); +} + + +/* The status field of a spinlock is a pointer whose least significant + bit is a locked flag. + + Thus the field values have the following meanings: + + status == 0: spinlock is free + status == 1: spinlock is taken; no thread is waiting on it + + (status & 1) == 1: spinlock is taken and (status & ~1L) is a + pointer to the first waiting thread; other + waiting threads are linked via the p_nextlock + field. + (status & 1) == 0: same as above, but spinlock is not taken. + + The waiting list is not sorted by priority order. + Actually, we always insert at top of list (sole insertion mode + that can be performed without locking). + For __pthread_unlock, we perform a linear search in the list + to find the highest-priority, oldest waiting thread. + This is safe because there are no concurrent __pthread_unlock + operations -- only the thread that locked the mutex can unlock it. */ + + +void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; + int successful_seizure, spurious_wakeup_count; + int spin_count; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + /* First try it without preparation. Maybe it's a completely + uncontested lock. */ + if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) + return; + + spurious_wakeup_count = 0; + spin_count = 0; + + /* On SMP, try spinning to get the lock. */ + + if (__pthread_smp_kernel) { + int max_count = lock->__spinlock * 2 + 10; + + if (max_count > MAX_ADAPTIVE_SPIN_COUNT) + max_count = MAX_ADAPTIVE_SPIN_COUNT; + + for (spin_count = 0; spin_count < max_count; spin_count++) { + if (((oldstatus = lock->__status) & 1) == 0) { + if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) + { + if (spin_count) + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + READ_MEMORY_BARRIER(); + return; + } + } +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); + } + + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + } + +again: + + /* No luck, try once more or suspend. */ + + do { + oldstatus = lock->__status; + successful_seizure = 0; + + if ((oldstatus & 1) == 0) { + newstatus = oldstatus | 1; + successful_seizure = 1; + } else { + if (self == NULL) + self = thread_self(); + newstatus = (long) self | 1; + } + + if (self != NULL) { + THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); + /* Make sure the store in p_nextlock completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend with guard against spurious wakeup. + This can happen in pthread_cond_timedwait_relative, when the thread + wakes up due to timeout and is still on the condvar queue, and then + locks the queue to remove itself. At that point it may still be on the + queue, and may be resumed by a condition signal. */ + + if (!successful_seizure) { + for (;;) { + suspend(self); + if (self->p_nextlock != NULL) { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + goto again; + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + READ_MEMORY_BARRIER(); +#endif +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus; + pthread_descr thr, * ptr, * maxptr; + int maxprio; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + return 0; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + WRITE_MEMORY_BARRIER(); + +again: + while ((oldstatus = lock->__status) == 1) { + if (__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, 0)) + return 0; + } + + /* Find thread in waiting queue with maximal priority */ + ptr = (pthread_descr *) &lock->__status; + thr = (pthread_descr) (oldstatus & ~1L); + maxprio = 0; + maxptr = ptr; + + /* Before we iterate over the wait queue, we need to execute + a read barrier, otherwise we may read stale contents of nodes that may + just have been inserted by other processors. One read barrier is enough to + ensure we have a stable list; we don't need one for each pointer chase + through the list, because we are the owner of the lock; other threads + can only add nodes at the front; if a front node is consistent, + the ones behind it must also be. */ + + READ_MEMORY_BARRIER(); + + while (thr != 0) { + if (thr->p_priority >= maxprio) { + maxptr = ptr; + maxprio = thr->p_priority; + } + ptr = &(thr->p_nextlock); + thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); + } + + /* Remove max prio thread from waiting list. */ + if (maxptr == (pthread_descr *) &lock->__status) { + /* If max prio thread is at head, remove it with compare-and-swap + to guard against concurrent lock operation. This removal + also has the side effect of marking the lock as released + because the new status comes from thr->p_nextlock whose + least significant bit is clear. */ + thr = (pthread_descr) (oldstatus & ~1L); + if (! __compare_and_swap_with_release_semantics + (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) + goto again; + } else { + /* No risk of concurrent access, remove max prio thread normally. + But in this case we must also flip the least significant bit + of the status to mark the lock as released. */ + thr = (pthread_descr)((long)*maxptr & ~1L); + *maxptr = thr->p_nextlock; + + /* Ensure deletion from linked list completes before we + release the lock. */ + WRITE_MEMORY_BARRIER(); + + do { + oldstatus = lock->__status; + } while (!__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, oldstatus & ~1L)); + } + + /* Wake up the selected waiting thread. Woken thread can check + its own p_nextlock field for NULL to detect that it has been removed. No + barrier is needed here, since restart() and suspend() take + care of memory synchronization. */ + + thr->p_nextlock = NULL; + restart(thr); + + return 0; +#endif +} + +/* + * Alternate fastlocks do not queue threads directly. Instead, they queue + * these wait queue node structures. When a timed wait wakes up due to + * a timeout, it can leave its wait node in the queue (because there + * is no safe way to remove from the quue). Some other thread will + * deallocate the abandoned node. + */ + + +struct wait_node { + struct wait_node *next; /* Next node in null terminated linked list */ + pthread_descr thr; /* The thread waiting with this node */ + int abandoned; /* Atomic flag */ +}; + +static long wait_node_free_list; +static int wait_node_free_list_spinlock; + +/* Allocate a new node from the head of the free list using an atomic + operation, or else using malloc if that list is empty. A fundamental + assumption here is that we can safely access wait_node_free_list->next. + That's because we never free nodes once we allocate them, so a pointer to a + node remains valid indefinitely. */ + +static struct wait_node *wait_node_alloc(void) +{ + struct wait_node *new_node = 0; + + __pthread_acquire(&wait_node_free_list_spinlock); + if (wait_node_free_list != 0) { + new_node = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) new_node->next; + } + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + + if (new_node == 0) + return malloc(sizeof *wait_node_alloc()); + + return new_node; +} + +/* Return a node to the head of the free list using an atomic + operation. */ + +static void wait_node_free(struct wait_node *wn) +{ + __pthread_acquire(&wait_node_free_list_spinlock); + wn->next = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) wn; + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + return; +} + +#if defined HAS_COMPARE_AND_SWAP + +/* Remove a wait node from the specified queue. It is assumed + that the removal takes place concurrently with only atomic insertions at the + head of the queue. */ + +static void wait_node_dequeue(struct wait_node **pp_head, + struct wait_node **pp_node, + struct wait_node *p_node) +{ + /* If the node is being deleted from the head of the + list, it must be deleted using atomic compare-and-swap. + Otherwise it can be deleted in the straightforward way. */ + + if (pp_node == pp_head) { + /* We don't need a read barrier between these next two loads, + because it is assumed that the caller has already ensured + the stability of *p_node with respect to p_node. */ + + long oldvalue = (long) p_node; + long newvalue = (long) p_node->next; + + if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) + return; + + /* Oops! Compare and swap failed, which means the node is + no longer first. We delete it using the ordinary method. But we don't + know the identity of the node which now holds the pointer to the node + being deleted, so we must search from the beginning. */ + + for (pp_node = pp_head; p_node != *pp_node; ) { + pp_node = &(*pp_node)->next; + READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ + } + } + + *pp_node = p_node->next; + return; +} + +#endif + +void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; +#endif + struct wait_node wait_node; + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int suspend_needed = 0; + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) lock->__status; + wait_node.thr = self; + lock->__status = (long) &wait_node; + suspend_needed = 1; + } + + __pthread_release(&lock->__spinlock); + + if (suspend_needed) + suspend (self); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + wait_node.thr = self; + newstatus = (long) &wait_node; + } + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend. Note that unlike in __pthread_lock, we don't worry + here about spurious wakeup. That's because this lock is not + used in situations where that can happen; the restart can + only come from the previous lock owner. */ + + if (oldstatus != 0) + suspend(self); + + READ_MEMORY_BARRIER(); +#endif +} + +/* Timed-out lock operation; returns 0 to indicate timeout. */ + +int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime) +{ + long oldstatus = 0; +#if defined HAS_COMPARE_AND_SWAP + long newstatus; +#endif + struct wait_node *p_wait_node = wait_node_alloc(); + + /* Out of memory, just give up and do ordinary lock. */ + if (p_wait_node == 0) { + __pthread_alt_lock(lock, self); + return 1; + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) lock->__status; + p_wait_node->thr = self; + lock->__status = (long) p_wait_node; + oldstatus = 1; /* force suspend */ + } + + __pthread_release(&lock->__spinlock); + goto suspend; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + p_wait_node->thr = self; + newstatus = (long) p_wait_node; + } + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + suspend: +#endif + + /* If we did not get the lock, do a timed suspend. If we wake up due + to a timeout, then there is a race; the old lock owner may try + to remove us from the queue. This race is resolved by us and the owner + doing an atomic testandset() to change the state of the wait node from 0 + to 1. If we succeed, then it's a timeout and we abandon the node in the + queue. If we fail, it means the owner gave us the lock. */ + + if (oldstatus != 0) { + if (timedsuspend(self, abstime) == 0) { + if (!testandset(&p_wait_node->abandoned)) + return 0; /* Timeout! */ + + /* Eat oustanding resume from owner, otherwise wait_node_free() below + will race with owner's wait_node_dequeue(). */ + suspend(self); + } + } + + wait_node_free(p_wait_node); + + READ_MEMORY_BARRIER(); + + return 1; /* Got the lock! */ +} + +void __pthread_alt_unlock(struct _pthread_fastlock *lock) +{ + struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; + struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; + int maxprio; + + WRITE_MEMORY_BARRIER(); + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + } +#endif + + while (1) { + + /* If no threads are waiting for this lock, try to just + atomically release it. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + if (lock->__status == 0 || lock->__status == 1) { + lock->__status = 0; + break; + } + } +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif + +#if defined HAS_COMPARE_AND_SWAP + { + long oldstatus = lock->__status; + if (oldstatus == 0 || oldstatus == 1) { + if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) + break; + else + continue; + } + } +#endif + + /* Process the entire queue of wait nodes. Remove all abandoned + wait nodes and put them into the global free queue, and + remember the one unabandoned node which refers to the thread + having the highest priority. */ + + pp_max_prio = pp_node = pp_head; + p_max_prio = p_node = *pp_head; + maxprio = INT_MIN; + + READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ + + while (p_node != (struct wait_node *) 1) { + int prio; + + if (p_node->abandoned) { + /* Remove abandoned node. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_node = p_node->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_node, p_node); +#endif + wait_node_free(p_node); + /* Note that the next assignment may take us to the beginning + of the queue, to newly inserted nodes, if pp_node == pp_head. + In that case we need a memory barrier to stabilize the first of + these new nodes. */ + p_node = *pp_node; + if (pp_node == pp_head) + READ_MEMORY_BARRIER(); /* No stale reads through p_node */ + continue; + } else if ((prio = p_node->thr->p_priority) >= maxprio) { + /* Otherwise remember it if its thread has a higher or equal priority + compared to that of any node seen thus far. */ + maxprio = prio; + pp_max_prio = pp_node; + p_max_prio = p_node; + } + + /* This canno6 jump backward in the list, so no further read + barrier is needed. */ + pp_node = &p_node->next; + p_node = *pp_node; + } + + /* If all threads abandoned, go back to top */ + if (maxprio == INT_MIN) + continue; + + ASSERT (p_max_prio != (struct wait_node *) 1); + + /* Now we want to to remove the max priority thread's wait node from + the list. Before we can do this, we must atomically try to change the + node's abandon state from zero to nonzero. If we succeed, that means we + have the node that we will wake up. If we failed, then it means the + thread timed out and abandoned the node in which case we repeat the + whole unlock operation. */ + + if (!testandset(&p_max_prio->abandoned)) { +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_max_prio = p_max_prio->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); +#endif + restart(p_max_prio->thr); + break; + } + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif +} + + +/* Compare-and-swap emulation with a spinlock */ + +#ifdef TEST_FOR_COMPARE_AND_SWAP +int __pthread_has_cas = 0; +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + +int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + int res; + + __pthread_acquire(spinlock); + + if (*ptr == oldval) { + *ptr = newval; res = 1; + } else { + res = 0; + } + + __pthread_release(spinlock); + + return res; +} + +#endif + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + READ_MEMORY_BARRIER(); + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + nanosleep(&tm, NULL); + cnt = 0; + } + } +} diff --git a/libpthread/linuxthreads/spinlock.h b/libpthread/linuxthreads/spinlock.h new file mode 100644 index 0000000..210ead4 --- /dev/null +++ b/libpthread/linuxthreads/spinlock.h @@ -0,0 +1,218 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include + + +/* There are 2 compare and swap synchronization primitives with + different semantics: + + 1. compare_and_swap, which has acquire semantics (i.e. it + completes befor subsequent writes.) + 2. compare_and_swap_with_release_semantics, which has release + semantics (it completes after previous writes.) + + For those platforms on which they are the same. HAS_COMPARE_AND_SWAP + should be defined. For those platforms on which they are different, + HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ + +#ifndef HAS_COMPARE_AND_SWAP +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define HAS_COMPARE_AND_SWAP +#endif +#endif + +#if defined(TEST_FOR_COMPARE_AND_SWAP) + +extern int __pthread_has_cas; +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + if (__builtin_expect (__pthread_has_cas, 1)) + return __compare_and_swap(ptr, oldval, newval); + else + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#elif defined(HAS_COMPARE_AND_SWAP) + +#ifdef IMPLEMENT_TAS_WITH_CAS +#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) +#endif + +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +static __inline__ int +compare_and_swap_with_release_semantics (long * ptr, long oldval, + long newval, int * spinlock) +{ + return __compare_and_swap_with_release_semantics (ptr, oldval, + newval); +} + +#endif + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __compare_and_swap(ptr, oldval, newval); +} + +#else + +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#endif + +#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define compare_and_swap_with_release_semantics compare_and_swap +#define __compare_and_swap_with_release_semantics __compare_and_swap +#endif + +/* Internal locks */ + +extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self); +extern int __pthread_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + return (testandset(&lock->__spinlock) ? EBUSY : 0); + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! __compare_and_swap(&lock->__status, 0, 1)); + return 0; +#endif +} + +/* Variation of internal lock used for pthread_mutex_t, supporting + timed-out waits. Warning: do not mix these operations with the above ones + over the same lock object! */ + +extern void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self); + +extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime); + +extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int res = EBUSY; + + if (testandset(&lock->__spinlock) == 0) + { + if (lock->__status == 0) + { + lock->__status = 1; + WRITE_MEMORY_BARRIER(); + res = 0; + } + lock->__spinlock = __LT_SPINLOCK_INIT; + } + return res; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); + return 0; +#endif +} + +/* Operations on pthread_atomic, which is defined in internals.h */ + +static __inline__ long atomic_increment(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ long atomic_decrement(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ __attribute__((always_inline)) void +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) +{ + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } +} diff --git a/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c b/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 0000000..ee25582 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,90 @@ +/* Special .init and .fini section support for Alpha. Linuxthreads version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the .init and .fini + sections and defines global symbols for those addresses, so they can be + called as functions. + + * crtn.s puts the corresponding function epilogues in the .init and .fini + sections. + + This differs from what would be generated by the generic code in that + we save and restore the GP within the function. In order for linker + relaxation to work, the value in the GP register on exit from a function + must be valid for the function entry point. Normally, a function is + contained within one object file and this is not an issue, provided + that the function reloads the gp after making any function calls. + However, _init and _fini are constructed from pieces of many object + files, all of which may have different GP values. So we must reload + the GP value from crti.o in crtn.o. */ + +__asm__ (" \n\ +#include \"defs.h\" \n\ + \n\ +/*@HEADER_ENDS*/ \n\ + \n\ +/*@_init_PROLOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + .globl _init \n\ + .type _init,@function \n\ + .usepv _init,std \n\ +_init: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + jsr $26, __pthread_initialize_minimal \n\ + ldq $29, 8($30) \n\ + .align 3 \n\ +/*@_init_PROLOG_ENDS*/ \n\ + \n\ +/*@_init_EPILOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_init_EPILOG_ENDS*/ \n\ + \n\ +/*@_fini_PROLOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + .globl _fini \n\ + .type _fini,@function \n\ + .usepv _fini,std \n\ +_fini: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + .align 3 \n\ +/*@_fini_PROLOG_ENDS*/ \n\ + \n\ +/*@_fini_EPILOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_fini_EPILOG_ENDS*/ \n\ + \n\ +/*@TRAILER_BEGINS*/ \n\ +"); diff --git a/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c b/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c new file mode 100644 index 0000000..d54a2a9 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c @@ -0,0 +1,110 @@ +/* POSIX spinlock implementation. Alpha version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp; + __asm__ __volatile__ + ("1: ldl_l %0,%1\n" + " blbs %0,2f\n" + " or %0,1,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + " mb\n" + ".subsection 2\n" + "2: ldl %0,%1\n" + " blbs %0,2b\n" + " br 1b\n" + ".previous" + : "=r" (tmp), "=m" (lock) + : "m" (lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned long int oldval; + unsigned long int temp; + + __asm__ __volatile__ + ("1: ldl_l %0,%1\n" + " and %0,%3,%2\n" + " bne %2,2f\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" + " beq %0,3f\n" + " mb\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r" (temp), "=m" (*lock), "=&r" (oldval) + : "Ir" (1UL), "m" (*lock)); + + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ ("mb"); + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h b/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h new file mode 100644 index 0000000..97c3839 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h @@ -0,0 +1,127 @@ +/* Machine-dependent pthreads configuration and inline functions. + Alpha version. + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#ifdef __linux__ +# include +#else +# include +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__("$30"); + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret, temp; + + __asm__ __volatile__( + "/* Inline spinlock test & set */\n" + "1:\t" + "ldl_l %0,%3\n\t" + "bne %0,2f\n\t" + "or $31,1,%1\n\t" + "stl_c %1,%2\n\t" + "beq %1,1b\n" + "2:\tmb\n" + "/* End spinlock test & set */" + : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) + : "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Begin allocating thread stacks at this address. Default is to allocate + them just below the initial program stack. */ +#define THREAD_STACK_START_ADDRESS 0x40000000000 + + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self __asm__("$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ +{ \ + register pthread_descr __self __asm__("$16") = (descr); \ + __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ +} + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "/* Inline compare & swap */\n" + "1:\t" + "ldq_l %0,%4\n\t" + "cmpeq %0,%2,%0\n\t" + "beq %0,2f\n\t" + "mov %3,%0\n\t" + "stq_c %0,%1\n\t" + "beq %0,1b\n\t" + "2:\tmb\n" + "/* End compare & swap */" + : "=&r"(ret), "=m"(*p) + : "r"(oldval), "r"(newval), "m"(*p) + : "memory"); + + return ret; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/alpha/tls.h b/libpthread/linuxthreads/sysdeps/alpha/tls.h new file mode 100644 index 0000000..3eb9438 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/alpha/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/Alpha version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + dtv_t *dtv; + + /* Reserved for the thread implementation. Unused in LinuxThreads. */ + void *private; +} tcbhead_t; +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) \ + (((tcbhead_t *) (TCBP))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__builtin_set_thread_pointer (TCBP), 0) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr)__builtin_thread_pointer () - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + __builtin_set_thread_pointer ((struct _pthread_descr_struct *)(DESCR) + 1) + +/* Get the thread descriptor definition. */ +# include + +/* ??? Generic bits of LinuxThreads may call these macros with + DESCR set to NULL. We are expected to be able to reference + the "current" value. + + In our case, we'd really prefer to use DESCR, since lots of + PAL_code calls would be expensive. We can only trust that + the compiler does its job and unifies the multiple + __builtin_thread_pointer instances. */ + +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/arm/pspinlock.c b/libpthread/linuxthreads/sysdeps/arm/pspinlock.c new file mode 100644 index 0000000..9deb0b1 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/arm/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. Arm version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + while (val != 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h new file mode 100644 index 0000000..9ffc8bd --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/arm/pt-machine.h @@ -0,0 +1,54 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + register unsigned int ret; + + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/arm/tls.h b/libpthread/linuxthreads/sysdeps/arm/tls.h new file mode 100644 index 0000000..8057a54 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/arm/tls.h @@ -0,0 +1,172 @@ +/* Definitions for thread-local data handling. linuxthreads/ARM version. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + + /* Reserved for the thread implementation. Unused in LinuxThreads. */ + void *private; +} tcbhead_t; +#endif + + +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +/* LinuxThreads can only support TLS if both floating stacks and support + from the tools are available. + + We have to define USE_TLS consistently, or ldsodefs.h will lay out types + differently between an NPTL build and a LinuxThreads build. It can be set + for libc.so and not libpthread.so, but only if we provide appropriate padding + in the _pthread_descr_struct. + + Currently nothing defines FLOATING_STACKS. We could assume this based on + kernel version once the TLS patches are available in kernel.org. + + To avoid bothering with the TLS support code at all, use configure + --without-tls. */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) \ + (((tcbhead_t *) (TCBP))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (TCBP)); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr)__builtin_thread_pointer () - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + TLS_INIT_TP ((struct _pthread_descr_struct *)(DESCR) + 1, 0) + +/* Get the thread descriptor definition. */ +# include + +/* ??? Generic bits of LinuxThreads may call these macros with + DESCR set to NULL. We are expected to be able to reference + the "current" value. + + In our case, we'd really prefer to use DESCR, since lots of + PAL_code calls would be expensive. We can only trust that + the compiler does its job and unifies the multiple + __builtin_thread_pointer instances. */ + +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* Initializing the thread pointer will generate a SIGILL if the syscall + is not available. */ +#define TLS_INIT_TP_EXPENSIVE 1 + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h new file mode 100644 index 0000000..5735d0e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h @@ -0,0 +1,73 @@ +/* Machine-dependent pthreads configuration and inline functions. + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +static __inline__ int +_test_and_set (int *p, int v) +{ + int result; + + __asm__ __volatile__( + "/* Inline test and set */\n" + " xchg %[old], %[mem], %[new]" + : [old] "=&r"(result) + : [mem] "r"(p), [new] "r"(v) + : "memory"); + + return result; +} + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set(spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + long int result; + + __asm__ __volatile__( + "/* Inline compare and swap */\n" + "1: ssrf 5\n" + " ld.w %[result], %[mem]\n" + " eor %[result], %[old]\n" + " brne 2f\n" + " stcond %[mem], %[new]\n" + " brne 1b\n" + "2:" + : [result] "=&r"(result), [mem] "=m"(*p) + : "m"(*p), [new] "r"(newval), [old] "r"(oldval) + : "cc", "memory"); + + return result == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/cris/pspinlock.c b/libpthread/linuxthreads/sysdeps/cris/pspinlock.c new file mode 100644 index 0000000..402e838 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/cris/pspinlock.c @@ -0,0 +1,72 @@ +/* POSIX spinlock implementation. CRIS version. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* FIXME: These are just dummies. I don't know why or if they're needed; + configury should default to these definitions. We just follow the + crowd here. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (testandset (lock) != 0) + ; + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return testandset (lock) != 0 ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads/sysdeps/cris/pt-machine.h new file mode 100644 index 0000000..33cf579 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/cris/pt-machine.h @@ -0,0 +1,57 @@ +/* Machine-dependent pthreads configuration and inline functions. + CRIS version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +PT_EI long int +testandset (int *spinlock) +{ + register unsigned long int ret; + + /* Note the use of a dummy output of *spinlock to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1) + : "memory"); + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + I don't trust register variables, so let's do this the safe way. */ +#define CURRENT_STACK_FRAME \ + ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c b/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c new file mode 100644 index 0000000..71a537f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c @@ -0,0 +1,81 @@ +/* POSIX spinlock implementation. hppa version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + while (!val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h b/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h new file mode 100644 index 0000000..780af7b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h @@ -0,0 +1,60 @@ +/* Machine-dependent pthreads configuration and inline functions. + hppa version. + Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%r30"); + + +/* The hppa only has one atomic read and modify memory operation, + load and clear, so hppa spinlocks must use zero to signify that + someone is holding the lock. */ + +#define xstr(s) str(s) +#define str(s) #s +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "ldcw 0(%2),%0" + : "=r"(ret), "=m"(*spinlock) + : "r"(spinlock)); + + return ret == 0; +} +#undef str +#undef xstr + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h b/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h new file mode 100644 index 0000000..222d44a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h @@ -0,0 +1,79 @@ +/* Machine-dependent pthreads configuration and inline functions. + i686 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif +#include "kernel-features.h" + +#ifndef __ASSEMBLER__ +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} +#endif + +#if __ASSUME_LDT_WORKS > 0 +#include "../useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/pspinlock.c b/libpthread/linuxthreads/sysdeps/i386/pspinlock.c new file mode 100644 index 0000000..c9c6272 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/pspinlock.c @@ -0,0 +1,103 @@ +/* POSIX spinlock implementation. x86 version. + Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" +#include + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__ + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) + +#ifndef __ASSUME_SET_THREAD_AREA_SYSCALL +int __have_no_set_thread_area; +#endif diff --git a/libpthread/linuxthreads/sysdeps/i386/pt-machine.h b/libpthread/linuxthreads/sysdeps/i386/pt-machine.h new file mode 100644 index 0000000..a455789 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/pt-machine.h @@ -0,0 +1,118 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if defined __pentiumpro__ || defined __pentium4__ || defined __athlon__ || \ + defined __k8__ +# include "i686/pt-machine.h" +#else + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + + +PT_EI int get_eflags (void); +PT_EI int +get_eflags (void) +{ + int res; + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : ); + return res; +} + + +PT_EI void set_eflags (int newflags); +PT_EI void +set_eflags (int newflags) +{ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc"); +} + + +PT_EI int compare_and_swap_is_available (void); +PT_EI int +compare_and_swap_is_available (void) +{ + int oldflags = get_eflags (); + int changed; + /* Flip AC bit in EFLAGS. */ + set_eflags (oldflags ^ 0x40000); + /* See if bit changed. */ + changed = (get_eflags () ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + set_eflags (oldflags); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ + +#endif diff --git a/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 0000000..69a5018 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,7 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#ifdef NEED_DL_SYSINFO +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +#endif diff --git a/libpthread/linuxthreads/sysdeps/i386/tls.h b/libpthread/linuxthreads/sysdeps/i386/tls.h new file mode 100644 index 0000000..2abd3a0 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/tls.h @@ -0,0 +1,229 @@ +/* Definition for thread-local data handling. linuxthreads/i386 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +#ifdef NEED_DL_SYSINFO + uintptr_t sysinfo; +#endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +# if !defined IS_IN_libpthread && !defined DO_MODIFY_LDT +# include "useldt.h" /* For the structure. */ +# endif +# if __ASSUME_LDT_WORKS > 0 +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) (doit) /* Nothing to check. */ +# else +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) \ + (__builtin_expect (GLRO(dl_osversion) < 131939, 0) \ + ? "kernel too old for thread-local storage support\n" \ + : (doit)) +# endif + +# define TLS_DO_MODIFY_LDT(descr, nr) \ +TLS_DO_MODIFY_LDT_KERNEL_CHECK( \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result) \ + : "0" (__NR_modify_ldt), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ + "d" (sizeof (ldt_entry))); \ + __builtin_expect (result, 0) == 0 \ + ? ({ __asm__ ("movw %w0, %%gs" : : "q" ((nr) * 8 + 7)); NULL; }) \ + : "cannot set up LDT for thread-local storage\n"; \ +})) + +# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + if (secondcall) \ + ldt_entry.entry_number = ({ int _gs; \ + __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ + (_gs & 0xffff) >> 3; }); \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result), "=m" (ldt_entry.entry_number) \ + : "0" (__NR_set_thread_area), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ + if (__builtin_expect (result, 0) == 0) \ + __asm__ ("movw %w0, %%gs" : : "q" (ldt_entry.entry_number * 8 + 3)); \ + result; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? "set_thread_area failed when setting up thread-local storage\n" : NULL) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? TLS_DO_MODIFY_LDT (descr, 0) : NULL) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 0) +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + INIT_SYSINFO; \ + TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/i386/useldt.h b/libpthread/linuxthreads/sysdeps/i386/useldt.h new file mode 100644 index 0000000..fa9a2a5 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/i386/useldt.h @@ -0,0 +1,314 @@ +/* Special definitions for ix86 machine using segment register based + thread descriptor. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __ASSEMBLER__ +#include /* For offsetof. */ +#include /* For abort(). */ +#include + + +/* We don't want to include the kernel header. So duplicate the + information. */ + +/* Structure passed on `modify_ldt' call. */ +struct modify_ldt_ldt_s +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* System call to set LDT entry. */ +extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + + +/* Initialize the thread-unique value. Two possible ways to do it. */ + +#define DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ + abort (); \ + __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %1, %%ebx\n\t" +#else +# define USETLS_EBX_ARG "b" +# define USETLS_LOAD_EBX +#endif + +/* When using the new set_thread_area call, we don't need to change %gs + because we inherited the value set up in the main thread by TLS setup. + We need to extract that value and set up the same segment in this + thread. */ +#if defined (USE_TLS) && USE_TLS +# define DO_SET_THREAD_AREA_REUSE(nr) 1 +#else +/* Without TLS, we do the initialization of the main thread, where NR == 0. */ +# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) +#endif +#define DO_SET_THREAD_AREA(descr, nr) \ +({ \ + int __gs; \ + if (DO_SET_THREAD_AREA_REUSE (nr)) \ + { \ + __asm__ ("movw %%gs, %w0" : "=q" (__gs)); \ + struct modify_ldt_ldt_s ldt_entry = \ + { (__gs & 0xffff) >> 3, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + __asm__ ("movw %w0, %%gs" :: "q" (__gs)); \ + else \ + __gs = -1; \ + } \ + else \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + { \ + __gs = (ldt_entry.entry_number << 3) + 3; \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + } \ + else \ + __gs = -1; \ + } \ + __gs; \ +}) + +#if defined __ASSUME_SET_THREAD_AREA_SYSCALL +# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) +#elif defined __NR_set_thread_area +# define INIT_THREAD_SELF(descr, nr) \ +({ \ + if (__builtin_expect (__have_no_set_thread_area, 0) \ + || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ + && (__have_no_set_thread_area = 1))) \ + DO_MODIFY_LDT (descr, nr); \ +}) +/* Defined in pspinlock.c. */ +extern int __have_no_set_thread_area; +#else +# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) +#endif + +/* Free resources associated with thread descriptor. */ +#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +#define FREE_THREAD(descr, nr) do { } while (0) +#elif defined __NR_set_thread_area +#define FREE_THREAD(descr, nr) \ +{ \ + int __gs; \ + __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ + if (__builtin_expect (__gs & 4, 0)) \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ + } \ +} +#else +#define FREE_THREAD(descr, nr) \ +{ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ +} +#endif + +/* Read member of the thread descriptor directly. */ +#define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +#define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +#define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ +}) + +/* Set member of the thread descriptor directly. */ +#define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) +#endif + +#if __ASSUME_LDT_WORKS > 0 +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 +#endif diff --git a/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c b/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c new file mode 100644 index 0000000..fa10c7b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c @@ -0,0 +1,79 @@ +/* POSIX spinlock implementation. ia64 version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" +#include + +/* This implementation is inspired by the implementation used in the + Linux kernel. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + int *p = (int *) lock; + + while (__builtin_expect (__sync_val_compare_and_swap (p, 0, 1), 0)) + { + /* Spin without using the atomic instruction. */ + do + __asm__ __volatile__ ("" : : : "memory"); + while (*p); + } + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __sync_val_compare_and_swap ((int *) lock, 0, 1) == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h b/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h new file mode 100644 index 0000000..e36468a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h @@ -0,0 +1,131 @@ +/* Machine-dependent pthreads configuration and inline functions. + IA-64 version. + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Make sure gcc doesn't try to be clever and move things around on + us. We need to use _exactly_ the address the user gave us, not some + alias that contains the same information. */ +#define __atomic_fool_gcc(x) (*(__volatile__ struct { int a[100]; } *)x) + +#ifndef ELF_MACHINE_NAME + +#define NEED_SEPARATE_REGISTER_STACK + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + r12 (sp) is the stack pointer. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__ ("sp"); + + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + + +/* Memory barrier */ +#define MEMORY_BARRIER() __sync_synchronize () + + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.acq %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, + long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.rel %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +#endif /* ELF_MACHINE_NAME */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchg4 %0=%1,%2" + : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) + : "r"(1), "m"(__atomic_fool_gcc (spinlock)) + : "memory"); + + return ret; +} + +/* Indicate that we are looping. */ +#define BUSY_WAIT_NOP __asm__ ("hint @pause") + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym new file mode 100644 index 0000000..f7793f7 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym @@ -0,0 +1,9 @@ +#include +#include + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/libpthread/linuxthreads/sysdeps/ia64/tls.h b/libpthread/linuxthreads/sysdeps/ia64/tls.h new file mode 100644 index 0000000..0311a9c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/ia64/tls.h @@ -0,0 +1,145 @@ +/* Definitions for thread-local data handling. linuxthreads/IA-64 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) +#else +# define INIT_SYSINFO 0 +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include + +# endif + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c b/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c new file mode 100644 index 0000000..35b851f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. M68k version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + while (val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h b/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h new file mode 100644 index 0000000..a13c069 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h @@ -0,0 +1,68 @@ +/* Machine-dependent pthreads configuration and inline functions. + m68k version. + Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__("tas %1; sne %0" + : "=dm"(ret), "=m"(*spinlock) + : "m"(*spinlock) + : "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("casl %2, %3, %1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/mips/pspinlock.c b/libpthread/linuxthreads/sysdeps/mips/pspinlock.c new file mode 100644 index 0000000..4d6617e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/mips/pspinlock.c @@ -0,0 +1,96 @@ +/* POSIX spinlock implementation. MIPS version. + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp1, tmp2; + + __asm__ __volatile__ + ("\t\t\t# spin_lock\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif + "ll %1,%3\n\t" + "li %2,1\n\t" + "bnez %1,1b\n\t" + "sc %2,%0\n\t" + ".set pop\n\t" + "beqz %2,1b" + : "=m" (*lock), "=&r" (tmp1), "=&r" (tmp2) + : "m" (*lock) + : "memory"); + + return 0; +} + +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + /* To be done. */ + return 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\t\t\t# spin_unlock\n\t" + "sw $0,%0" + : "=m" (*lock) + : + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/mips/pt-machine.h b/libpthread/linuxthreads/sysdeps/mips/pt-machine.h new file mode 100644 index 0000000..0ab7ac1 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/mips/pt-machine.h @@ -0,0 +1,89 @@ +/* Machine-dependent pthreads configuration and inline functions. + + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + Based on the Alpha version by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ + +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set (spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("$29"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret, temp; + + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif +#if _MIPS_SIM == _ABI64 + "lld %1,%5\n\t" +#else + "ll %1,%5\n\t" +#endif + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" +#if _MIPS_SIM == _ABI64 + "scd %0,%2\n\t" +#else + "sc %0,%2\n\t" +#endif + ".set pop\n\t" + "beqz %0,1b\n" + "2:\n\t" + "/* End compare & swap */" + : "=&r" (ret), "=&r" (temp), "=m" (*p) + : "r" (oldval), "r" (newval), "m" (*p) + : "memory"); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/mips/tls.h b/libpthread/linuxthreads/sysdeps/mips/tls.h new file mode 100644 index 0000000..15dda69 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/mips/tls.h @@ -0,0 +1,170 @@ +/* Definitions for thread-local data handling. linuxthreads/MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +# define READ_THREAD_POINTER() \ + ({ void *__result; \ + __asm__ __volatile__ (".set\tpush\n\t.set\tmips32r2\n\t" \ + "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \ + __result; }) + +#else /* __ASSEMBLER__ */ +# include + +/* Note: rd must be $v1 to be ABI-conformant. */ +# define READ_THREAD_POINTER(rd) \ + .set push; \ + .set mips32r2; \ + rdhwr rd, $29; \ + .set pop +#endif /* __ASSEMBLER__ */ + +/* LinuxThreads can only use TLS if both floating stacks (in the MIPS case, + that means support for "rdhwr") and support from the tools are available. + + We have to define USE_TLS consistently, or ldsodefs.h will lay out types + differently between an NPTL build and a LinuxThreads build. It can be set + for libc.so and not libpthread.so, but only if we provide appropriate padding + in the _pthread_descr_struct. + + Currently nothing defines FLOATING_STACKS. We could assume this based on + kernel version once the TLS patches are available in kernel.org, but + it hardly seems worth it. Use NPTL if you can. + + To avoid bothering with the TLS support code at all, use configure + --without-tls. */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ + +/* This layout is actually wholly private and not affected by the ABI. + Nor does it overlap the pthread data structure, so we need nothing + extra here at all. */ +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is + immediately in front of the TCB. */ +#define TLS_TCB_OFFSET 0x7000 + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +/* This is not really true for powerpc64. We are following alpha + where the DTV pointer is first doubleword in the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) (((tcbhead_t *) (TCBP))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \ + (char *) (tcbp) + TLS_TCB_OFFSET); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr) (READ_THREAD_POINTER () \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Get the thread descriptor definition. */ +# include + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Initializing the thread pointer requires a syscall which may not be + available, so don't do it if we don't need to. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c b/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c new file mode 100644 index 0000000..15fd545 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap ((long int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap ((long int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h b/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h new file mode 100644 index 0000000..bfb13df --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c b/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c new file mode 100644 index 0000000..19161c6 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap32 ((int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap32 ((int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h b/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h new file mode 100644 index 0000000..d7ed841 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h @@ -0,0 +1,185 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); +extern int __compare_and_swap32 (int *p, int oldval, int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 16*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32 (int *p, int oldval, int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI long int +testandset (int *p) +{ + long int ret, val = 1; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " cmpwi 0,%0,0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r" (val) + : "cr0", "memory"); + MEMORY_BARRIER (); + return ret != 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c b/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c new file mode 100644 index 0000000..bb88a06 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "powerpc32/pspinlock.c" +#else +# include "powerpc64/pspinlock.c" +#endif diff --git a/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h b/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h new file mode 100644 index 0000000..55e922e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "powerpc32/pt-machine.h" +#else +# include "powerpc64/pt-machine.h" +#endif diff --git a/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 0000000..7c5cca0 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,19 @@ +#include +#include + +-- This line separates the #include lines from conditionals. + +# ifdef USE_TLS + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct _pthread_descr_struct, p_##mem)) + +# else + +# define thread_offsetof(mem) offsetof (tcbhead_t, mem) + +# endif + +MULTIPLE_THREADS_OFFSET thread_offsetof (multiple_threads) diff --git a/libpthread/linuxthreads/sysdeps/powerpc/tls.h b/libpthread/linuxthreads/sysdeps/powerpc/tls.h new file mode 100644 index 0000000..1ae0b60 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/powerpc/tls.h @@ -0,0 +1,165 @@ +/* Definitions for thread-local data handling. linuxthreads/PPC version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +/* This layout is actually wholly private and not affected by the ABI. + Nor does it overlap the pthread data structure, so we need nothing + extra here at all. */ +typedef struct +{ + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The following assumes that TP (R2 or R13) is points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread_descr is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +#define TLS_TCB_OFFSET 0x7000 + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +/* This is not really true for powerpc64. We are following alpha + where the DTV pointer is first doubleword in the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) (((tcbhead_t *) (TCBP))[-1].dtv) + +/* We still need this define so that tcb-offsets.sym can override it and + use THREAD_SELF to generate MULTIPLE_THREADS_OFFSET. */ +# define __thread_register ((void *) __thread_self) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The global register variable is declared in pt-machine.h with the + wrong type, so we need some extra casts to get the desired result. + This avoids a lvalue cast that gcc-3.4 does not like. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__thread_self = (struct _pthread_descr_struct *) \ + ((void *) (TCBP) + TLS_TCB_OFFSET), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) ((void *) __thread_self - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + (__thread_self = (struct _pthread_descr_struct *)((void *) (DESCR) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)) + +/* Make sure we have the p_multiple_threads member in the thread structure. + See below. */ +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +# endif /* __ASSEMBLER__ */ + +#elif !defined __ASSEMBLER__ + +/* This overlaps the start of the pthread_descr. System calls + and such use this to find the multiple_threads flag and need + to use the same offset relative to the thread register in both + single-threaded and multi-threaded code. */ +typedef struct +{ + void *tcb; /* Never used. */ + dtv_t *dtv; /* Never used. */ + void *self; /* Used only if multithreaded, and rarely. */ + int multiple_threads; /* Only this member is really used. */ +} tcbhead_t; + +#define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/.cvsignore b/libpthread/linuxthreads/sysdeps/pthread/.cvsignore new file mode 100644 index 0000000..7ee8f59 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/.cvsignore @@ -0,0 +1,2 @@ +.cvsignore +*.os diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h b/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h new file mode 100644 index 0000000..a19ec07 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 0000000..2299b3a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,409 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +#if defined _LIBC && !defined NOT_IN_libc +#include +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).mutex.__m_count = 0; \ + (NAME).mutex.__m_owner = NULL; \ + (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).mutex.__m_lock.__status = 0; \ + (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME) +#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = 2; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# define BP_SYM(sym) sym +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 0000000..fa6eb4b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,59 @@ +/* libc-internal interface for thread-specific data. LinuxThreads version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include +#include + +#if USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include + +#else + +# include + +# ifndef SHARED +extern void ** __pthread_internal_tsd_address (int); +extern void *__pthread_internal_tsd_get (int); +extern int __pthread_internal_tsd_set (int, const void *); + +weak_extern (__pthread_internal_tsd_address) +weak_extern (__pthread_internal_tsd_get) +weak_extern (__pthread_internal_tsd_set) +# endif + +#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; +#define __libc_tsd_address(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_address, \ + (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) +#define __libc_tsd_get(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_get, \ + (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) +#define __libc_tsd_set(KEY, VALUE) \ + __libc_maybe_call2 (pthread_internal_tsd_set, \ + (_LIBC_TSD_KEY_##KEY, (VALUE)), \ + (__libc_tsd_##KEY##_data = (VALUE), 0)) + +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h new file mode 100644 index 0000000..4ea6d8a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h @@ -0,0 +1,152 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __need_schedparam +#include + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ + +#ifdef __GLIBC_HAVE_LONG_LONG +__extension__ typedef long long __pthread_cond_align_t; +#else +typedef long __pthread_cond_align_t; +#endif + +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ + char __padding[48 - sizeof (struct _pthread_fastlock) + - sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)]; + __pthread_cond_align_t __align; +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef __volatile__ int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef unsigned long int pthread_t; + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h b/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h new file mode 100644 index 0000000..45264ac --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c b/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c new file mode 100644 index 0000000..c3b3087 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c @@ -0,0 +1,45 @@ +/* MT support function to get address of `errno' variable, linuxthreads + version. + Copyright (C) 1996, 1998, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO +#undef errno +extern int errno; +#endif + +int * +#if ! USE___THREAD +weak_const_function +#endif +__errno_location (void) +{ +#if ! USE___THREAD && !defined NOT_IN_libc + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_errnop); + } +#endif + return &errno; +} +libc_hidden_def (__errno_location) diff --git a/libpthread/linuxthreads/sysdeps/pthread/flockfile.c b/libpthread/linuxthreads/sysdeps/pthread/flockfile.c new file mode 100644 index 0000000..918cb84 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/flockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +void +__flockfile (stream) + FILE *stream; +{ + _IO_lock_lock (*stream->_lock); +} +strong_alias (__flockfile, _IO_flockfile) +weak_alias (__flockfile, flockfile) diff --git a/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c b/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c new file mode 100644 index 0000000..21c1ea0 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +int +__ftrylockfile (stream) + FILE *stream; +{ + return _IO_lock_trylock (*stream->_lock); +} +strong_alias (__ftrylockfile, _IO_ftrylockfile) +weak_alias (__ftrylockfile, ftrylockfile) diff --git a/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c b/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c new file mode 100644 index 0000000..f941fc9 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +void +__funlockfile (stream) + FILE *stream; +{ + _IO_lock_unlock (*stream->_lock); +} +strong_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile) diff --git a/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c b/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c new file mode 100644 index 0000000..1c64e6c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c @@ -0,0 +1,117 @@ +/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version + Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !(__ASSUME_POSIX_CPU_TIMERS > 0) +int __libc_missing_posix_cpu_timers attribute_hidden; +#endif +#if !(__ASSUME_POSIX_TIMERS > 0) +int __libc_missing_posix_timers attribute_hidden; +#endif + +int +pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id) +{ +#ifdef __NR_clock_getres + pthread_handle handle = thread_handle(thread_id); + int pid; + + __pthread_lock (&handle->h_lock, NULL); + if (nonexisting_handle (handle, thread_id)) + { + __pthread_unlock (&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock (&handle->h_lock); + + /* The clockid_t value is a simple computation from the PID. + But we do a clock_getres call to validate it if we aren't + yet sure we have the kernel support. */ + + const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED); + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +# if !(__ASSUME_POSIX_TIMERS > 0) + if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers) + __libc_missing_posix_cpu_timers = 1; +# endif + if (!__libc_missing_posix_cpu_timers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) +# endif + { + *clock_id = pidclock; + return 0; + } + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +# if !(__ASSUME_POSIX_TIMERS > 0) + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + { + /* The kernel doesn't support these calls at all. */ + __libc_missing_posix_timers = 1; + __libc_missing_posix_cpu_timers = 1; + } + else +# endif + if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) + { + /* The kernel doesn't support these clocks at all. */ + __libc_missing_posix_cpu_timers = 1; + } + else + return INTERNAL_SYSCALL_ERRNO (r, err); + } +# endif +#endif + +#ifdef CLOCK_THREAD_CPUTIME_ID + /* We need to store the thread ID in the CLOCKID variable together + with a number identifying the clock. We reserve the low 3 bits + for the clock ID and the rest for the thread ID. This is + problematic if the thread ID is too large. But 29 bits should be + fine. + + If some day more clock IDs are needed the ID part can be + enlarged. The IDs are entirely internal. */ + if (2 * PTHREAD_THREADS_MAX + >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE)) + return ERANGE; + + /* Store the number. */ + *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE); + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c b/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c new file mode 100644 index 0000000..fbc5576 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996, 97, 98, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if ! USE___THREAD +# undef h_errno +extern int h_errno; +#endif + +/* When threaded, h_errno may be a per-thread variable. */ +int * +weak_const_function +__h_errno_location (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_h_errnop); + } +#endif + return &h_errno; +} +libc_hidden_def (__h_errno_location) diff --git a/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h b/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h new file mode 100644 index 0000000..88a7182 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h @@ -0,0 +1,80 @@ +/* Set flags signalling availability of kernel features based on given + kernel version number. + Copyright (C) 1999-2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file must not contain any C code. At least it must be protected + to allow using the file also in assembler files. */ + +#if defined __mips__ +# include +#endif + +#include +#define __LINUX_KERNEL_VERSION LINUX_VERSION_CODE + +/* Real-time signal became usable in 2.1.70. */ +#if __LINUX_KERNEL_VERSION >= 131398 +# define __ASSUME_REALTIME_SIGNALS 1 +#endif + +/* Beginning with 2.5.63 support for realtime and monotonic clocks and + timers based on them is available. */ +#if __LINUX_KERNEL_VERSION >= 132415 +# define __ASSUME_POSIX_TIMERS 1 +#endif + +/* On x86, the set_thread_area syscall was introduced in 2.5.29, but its + semantics was changed in 2.5.30, and again after 2.5.31. */ +#if __LINUX_KERNEL_VERSION >= 132384 && defined __i386__ +# define __ASSUME_SET_THREAD_AREA_SYSCALL 1 +#endif + +/* We can use the LDTs for threading with Linux 2.3.99 and newer. */ +#if __LINUX_KERNEL_VERSION >= 131939 +# define __ASSUME_LDT_WORKS 1 +#endif + +/* Starting with 2.4.5 kernels PPC passes the AUXV in the standard way + and the vfork syscall made it into the official kernel. */ +#if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__ +# define __ASSUME_STD_AUXV 1 +# define __ASSUME_VFORK_SYSCALL 1 +#endif + +/* The vfork syscall on x86 and arm was definitely available in 2.4. */ +#if __LINUX_KERNEL_VERSION >= 132097 && (defined __i386__ || defined __arm__) +# define __ASSUME_VFORK_SYSCALL 1 +#endif + +/* Starting with version 2.6.4-rc1 the getdents syscall returns d_type + * information as well and in between 2.6.5 and 2.6.8 most compat wrappers + * were fixed too. Except s390{,x} which was fixed in 2.6.11. */ +#if (__LINUX_KERNEL_VERSION >= 0x020608 && !defined __s390__) \ + || (__LINUX_KERNEL_VERSION >= 0x02060b && defined __s390__) +# define __ASSUME_GETDENTS32_D_TYPE 1 +#endif + +/* These features were surely available with 2.4.12. */ +#if __LINUX_KERNEL_VERSION >= 132108 && defined __mc68000__ +# define __ASSUME_MMAP2_SYSCALL 1 +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +# define __ASSUME_FCNTL64 1 +# define __ASSUME_VFORK_SYSCALL 1 +#endif diff --git a/libpthread/linuxthreads/sysdeps/pthread/list.h b/libpthread/linuxthreads/sysdeps/pthread/list.h new file mode 100644 index 0000000..75decfb --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/list.h @@ -0,0 +1,114 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIST_H +#define _LIST_H 1 + +/* The definitions of this file are adopted from those which can be + found in the Linux kernel headers to enable people familiar with + the latter find their way in these sources as well. */ + + +/* Basic type for the double-link list. */ +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_t; + + +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) \ + list_t name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) \ + (ptr)->next = (ptr)->prev = (ptr) + + +/* Add new element at the head of the list. */ +static __inline__ void +list_add (list_t *newp, list_t *head) +{ + head->next->prev = newp; + newp->next = head->next; + newp->prev = head; + head->next = newp; +} + + +/* Add new element at the tail of the list. */ +static __inline__ void +list_add_tail (list_t *newp, list_t *head) +{ + head->prev->next = newp; + newp->next = head; + newp->prev = head->prev; + head->prev = newp; +} + + +/* Remove element from list. */ +static __inline__ void +list_del (list_t *elem) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + + +/* Join two lists. */ +static __inline__ void +list_splice (list_t *add, list_t *head) +{ + /* Do nothing if the list which gets added is empty. */ + if (add != add->next) + { + add->next->prev = head; + add->prev->next = head->next; + head->next->prev = add->prev; + head->next = add->next; + } +} + + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ + ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) + + + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/* Iterate forward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + + +/* Iterate backwards over the elements list. The list elements can be + removed from the list while doing this. */ +#define list_for_each_prev_safe(pos, p, head) \ + for (pos = (head)->prev, p = pos->prev; \ + pos != (head); \ + pos = p, p = pos->prev) + +#endif /* list.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h b/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h new file mode 100644 index 0000000..5191f8c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,67 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include +#include + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m) \ + __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0)) +#define mutex_lock(m) \ + __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0)) +#define mutex_trylock(m) \ + __libc_maybe_call2 (pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0))) +#define mutex_unlock(m) \ + __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0)) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h b/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h new file mode 100644 index 0000000..4373917 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h @@ -0,0 +1,62 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(func, numargs, args...) syscall(__NR_ ## func, args) + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h b/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h new file mode 100644 index 0000000..5486f7d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h @@ -0,0 +1,204 @@ +/* Definitions for POSIX timer implementation on top of LinuxThreads. + Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Double linked list. */ +struct list_links +{ + struct list_links *next; + struct list_links *prev; +}; + + +/* Forward declaration. */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation. */ +struct thread_node +{ + struct list_links links; + pthread_attr_t attr; + pthread_t id; + unsigned int exists; + struct list_links timer_queue; + pthread_cond_t cond; + struct timer_node *current_timer; + pthread_t captured; + clockid_t clock_id; +}; + + +/* Internal representation of a timer. */ +struct timer_node +{ + struct list_links links; + struct sigevent event; + clockid_t clock; + struct itimerspec value; + struct timespec expirytime; + pthread_attr_t attr; + unsigned int abstime; + unsigned int armed; + enum { + TIMER_FREE, TIMER_INUSE, TIMER_DELETED + } inuse; + struct thread_node *thread; + pid_t creator_pid; + int refcount; + int overrun_count; +}; + + +/* Static array with the structures for all the timers. */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization. */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed. */ +extern int __timer_init_failed; + +/* Nodes for the threads used to deliver signals. */ +/* A distinct thread is used for each clock type. */ + +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID. */ +static __inline__ struct timer_node * +timer_id2ptr (timer_t timerid) +{ + if (timerid >= 0 && timerid < TIMER_MAX) + return &__timer_array[timerid]; + + return NULL; +} + +/* Return ID of TIMER. */ +static __inline__ int +timer_ptr2id (struct timer_node *timer) +{ + return timer - __timer_array; +} + +/* Check whether timer is valid; global mutex must be held. */ +static __inline__ int +timer_valid (struct timer_node *timer) +{ + return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static __inline__ void +timer_addref (struct timer_node *timer) +{ + timer->refcount++; +} + +static __inline__ void +timer_delref (struct timer_node *timer) +{ + if (--timer->refcount == 0) + __timer_dealloc (timer); +} + +/* Timespec helper routines. */ +static __inline__ int +timespec_compare (const struct timespec *left, const struct timespec *right) +{ + if (left->tv_sec < right->tv_sec) + return -1; + if (left->tv_sec > right->tv_sec) + return 1; + + if (left->tv_nsec < right->tv_nsec) + return -1; + if (left->tv_nsec > right->tv_nsec) + return 1; + + return 0; +} + +static __inline__ void +timespec_add (struct timespec *sum, const struct timespec *left, + const struct timespec *right) +{ + sum->tv_sec = left->tv_sec + right->tv_sec; + sum->tv_nsec = left->tv_nsec + right->tv_nsec; + + if (sum->tv_nsec >= 1000000000) + { + ++sum->tv_sec; + sum->tv_nsec -= 1000000000; + } +} + +static __inline__ void +timespec_sub (struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + + +/* We need one of the list functions in the other modules. */ +static __inline__ void +list_unlink_ip (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; + + /* The suffix ip means idempotent; list_unlink_ip can be called + * two or more times on the same node. + */ + + list->next = list; + list->prev = list; +} + + +/* Functions in the helper file. */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c b/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c new file mode 100644 index 0000000..15aeb21 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,124 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) __asm__ (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +__asm__ ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +__asm__ ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +__asm__ ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +__asm__ ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +__asm__ ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal (void); + + __pthread_initialize_minimal (); +} + +SECTION (".init"); +extern void _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + __asm__ ("ALIGN"); + __asm__("END_INIT"); + /* Now the epilog. */ + __asm__ ("\n/*@_init_PROLOG_ENDS*/"); + __asm__ ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +__asm__ ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +__asm__ ("\n/*@_init_EPILOG_ENDS*/"); +__asm__ ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + __asm__ ("ALIGN"); + __asm__ ("END_FINI"); + __asm__ ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + __asm__ ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +__asm__ ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +__asm__ ("\n/*@_fini_EPILOG_ENDS*/"); +__asm__ ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h b/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h new file mode 100644 index 0000000..258e1fc --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); + int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread.h b/libpthread/linuxthreads/sysdeps/pthread/pthread.h new file mode 100644 index 0000000..0fa3be1 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/pthread.h @@ -0,0 +1,678 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#include + +#define __need_sigset_t +#include +#include +#include + + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_TIMED_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0, "", 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on unitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) __THROW; +#endif + + +/* Functions for handling signals. */ +#include + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c b/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c new file mode 100644 index 0000000..a2a56b8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c @@ -0,0 +1,39 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include +#include "pthread.h" +#include "internals.h" + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +#ifdef SHARED +void siglongjmp (sigjmp_buf env, int val) +{ + __libc_siglongjmp (env, val); +} + +void longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} +#endif diff --git a/libpthread/linuxthreads/sysdeps/pthread/res-state.c b/libpthread/linuxthreads/sysdeps/pthread/res-state.c new file mode 100644 index 0000000..016e20b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/res-state.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1996, 97, 98, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if ! USE___THREAD +# undef _res +extern struct __res_state _res; +#endif + +/* When threaded, _res may be a per-thread variable. */ +struct __res_state * +#if ! USE___THREAD +weak_const_function +#endif +__res_state (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_resp); + } + return &_res; +#else + return __resp; +#endif +} +libc_hidden_def (__res_state) diff --git a/libpthread/linuxthreads/sysdeps/pthread/semaphore.h b/libpthread/linuxthreads/sysdeps/pthread/semaphore.h new file mode 100644 index 0000000..8793768 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/semaphore.h @@ -0,0 +1 @@ +#include diff --git a/libpthread/linuxthreads/sysdeps/pthread/sigaction.c b/libpthread/linuxthreads/sysdeps/pthread/sigaction.c new file mode 100644 index 0000000..0a0a9e2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/sigaction.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is tricky. GCC doesn't like #include_next in the primary + source file and even if it did, the first #include_next is this + exact file anyway. */ +#ifndef LIBC_SIGACTION + +# include + +# define LIBC_SIGACTION 1 + +# include "sigaction.c" + +# ifndef NOT_IN_libc +# ifndef SHARED +weak_extern (__pthread_sigaction) +# endif + +int +__sigaction (sig, act, oact) + int sig; + const struct sigaction *act; + struct sigaction *oact; +{ + return __libc_maybe_call2 (pthread_sigaction, (sig, act, oact), + __libc_sigaction (sig, act, oact)); +} +# else +weak_alias (__libc_sigaction, __sigaction) +# endif +libc_hidden_weak (__sigaction) +weak_alias (__sigaction, sigaction) + +#else + +# include_next + +#endif /* LIBC_SIGACTION */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h b/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h new file mode 100644 index 0000000..3fe1370 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h @@ -0,0 +1 @@ +/* This is overridden by generated tcb-offsets.h on arches which need it. */ diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_create.c b/libpthread/linuxthreads/sysdeps/pthread/timer_create.c new file mode 100644 index 0000000..7f7e886 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK. */ +int +timer_create (clock_id, evp, timerid) + clockid_t clock_id; + struct sigevent *evp; + timer_t *timerid; +{ + int retval = -1; + struct timer_node *newtimer = NULL; + struct thread_node *thread = NULL; + + if (0 +#ifdef _POSIX_CPUTIME + || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#ifdef _POSIX_THREAD_CPUTIME + || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif + ) + { + /* We don't allow timers for CPU clocks. At least not in the + moment. */ + __set_errno (ENOTSUP); + return -1; + } + + if (clock_id != CLOCK_REALTIME) + { + __set_errno (EINVAL); + return -1; + } + + pthread_once (&__timer_init_once_control, __timer_init_once); + + if (__timer_init_failed) + { + __set_errno (ENOMEM); + return -1; + } + + pthread_mutex_lock (&__timer_mutex); + + newtimer = __timer_alloc (); + if (__builtin_expect (newtimer == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + if (evp != NULL) + newtimer->event = *evp; + else + { + newtimer->event.sigev_notify = SIGEV_SIGNAL; + newtimer->event.sigev_signo = SIGALRM; + newtimer->event.sigev_value.sival_int = timer_ptr2id (newtimer); + newtimer->event.sigev_notify_function = 0; + } + + newtimer->event.sigev_notify_attributes = &newtimer->attr; + newtimer->creator_pid = getpid (); + + switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + case SIGEV_SIGNAL: + /* We have a global thread for delivering timed signals. + If it is not running, try to start it up. */ + thread = &__timer_signal_thread_rclk; + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), + 1) < 0) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + } + break; + + case SIGEV_THREAD: + /* Copy over thread attributes or set up default ones. */ + if (evp->sigev_notify_attributes) + newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; + else + pthread_attr_init (&newtimer->attr); + + /* Ensure thread attributes call for deatched thread. */ + pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + + /* Try to find existing thread having the right attributes. */ + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + + /* If no existing thread has these attributes, try to allocate one. */ + if (thread == NULL) + thread = __timer_thread_alloc (&newtimer->attr, clock_id); + + /* Out of luck; no threads are available. */ + if (__builtin_expect (thread == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + /* If the thread is not running already, try to start it. */ + if (! thread->exists + && __builtin_expect (! __timer_thread_start (thread), 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + break; + + default: + __set_errno (EINVAL); + goto unlock_bail; + } + + newtimer->clock = clock_id; + newtimer->abstime = 0; + newtimer->armed = 0; + newtimer->thread = thread; + + *timerid = timer_ptr2id (newtimer); + retval = 0; + + if (__builtin_expect (retval, 0) == -1) + { + unlock_bail: + if (thread != NULL) + __timer_thread_dealloc (thread); + if (newtimer != NULL) + { + timer_delref (newtimer); + __timer_dealloc (newtimer); + } + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c b/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c new file mode 100644 index 0000000..48ba1f2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Delete timer TIMERID. */ +int +timer_delete (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + if (! timer_valid (timer)) + /* Invalid timer ID or the timer is not in use. */ + __set_errno (EINVAL); + else + { + if (timer->armed && timer->thread != NULL) + { + struct thread_node *thread = timer->thread; + assert (thread != NULL); + + /* If thread is cancelled while waiting for handler to terminate, + the mutex is unlocked and timer_delete is aborted. */ + pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + + /* If timer is currently being serviced, wait for it to finish. */ + while (thread->current_timer == timer) + pthread_cond_wait (&thread->cond, &__timer_mutex); + + pthread_cleanup_pop (0); + } + + /* Remove timer from whatever queue it may be on and deallocate it. */ + timer->inuse = TIMER_DELETED; + list_unlink_ip (&timer->links); + timer_delref (timer); + retval = 0; + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c b/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 0000000..f3e2221 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID. */ +int +timer_getoverrun (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + if (! timer_valid (timer = timer_id2ptr (timerid))) + __set_errno (EINVAL); + else + retval = timer->overrun_count; + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c b/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c new file mode 100644 index 0000000..723a616 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE. */ +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ + struct timer_node *timer; + struct timespec now, expiry; + int retval = -1, armed = 0, valid; + clock_t clock = 0; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + valid = timer_valid (timer); + + if (valid) { + armed = timer->armed; + expiry = timer->expirytime; + clock = timer->clock; + value->it_interval = timer->value.it_interval; + } + + pthread_mutex_unlock (&__timer_mutex); + + if (valid) + { + if (armed) + { + clock_gettime (clock, &now); + if (timespec_compare (&now, &expiry) < 0) + timespec_sub (&value->it_value, &expiry, &now); + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + } + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + + retval = 0; + } + else + __set_errno (EINVAL); + + return retval; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c b/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c new file mode 100644 index 0000000..25b4630 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c @@ -0,0 +1,573 @@ +/* Helper code for POSIX timer implementation on LinuxThreads. + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Number of threads used. */ +#define THREAD_MAXNODES 16 + +/* Array containing the descriptors for the used threads. */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers. */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization. */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed. */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads. */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions. */ +static __inline__ void +list_init (struct list_links *list) +{ + list->next = list->prev = list; +} + +static __inline__ void +list_append (struct list_links *list, struct list_links *newp) +{ + newp->prev = list->prev; + newp->next = list; + list->prev->next = newp; + list->prev = newp; +} + +static __inline__ void +list_insbefore (struct list_links *list, struct list_links *newp) +{ + list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static __inline__ void +list_unlink (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; +} + +static __inline__ struct list_links * +list_first (struct list_links *list) +{ + return list->next; +} + +static __inline__ struct list_links * +list_null (struct list_links *list) +{ + return list; +} + +static __inline__ struct list_links * +list_next (struct list_links *list) +{ + return list->next; +} + +static __inline__ int +list_isempty (struct list_links *list) +{ + return list->next == list; +} + + +/* Functions build on top of the list functions. */ +static __inline__ struct thread_node * +thread_links2ptr (struct list_links *list) +{ + return (struct thread_node *) ((char *) list + - offsetof (struct thread_node, links)); +} + +static __inline__ struct timer_node * +timer_links2ptr (struct list_links *list) +{ + return (struct timer_node *) ((char *) list + - offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure. */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ + if (attr != NULL) + thread->attr = *attr; + else + { + pthread_attr_init (&thread->attr); + pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); + } + + thread->exists = 0; + list_init (&thread->timer_queue); + pthread_cond_init (&thread->cond, 0); + thread->current_timer = 0; + thread->captured = pthread_self (); + thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources. Error + reporting is done by storing a non-zero value to the global variable + timer_init_failed. */ +static void +init_module (void) +{ + int i; + + list_init (&timer_free_list); + list_init (&thread_free_list); + list_init (&thread_active_list); + + for (i = 0; i < TIMER_MAX; ++i) + { + list_append (&timer_free_list, &__timer_array[i].links); + __timer_array[i].inuse = TIMER_FREE; + } + + for (i = 0; i < THREAD_MAXNODES; ++i) + list_append (&thread_free_list, &thread_array[i].links); + + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() + occurs. It reinitializes the module, resetting all of the data + structures to their initial state. The mutex is initialized in + case it was locked in the parent process. */ +static void +reinit_after_fork (void) +{ + init_module (); + pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the + module and ensures that reinit_after_fork will be executed in any + child process. */ +void +__timer_init_once (void) +{ + init_module (); + pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated. */ +static void +thread_deinit (struct thread_node *thread) +{ + assert (list_isempty (&thread->timer_queue)); + pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list. Global + mutex lock must be held by caller. The thread is moved to + the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ + struct list_links *node = list_first (&thread_free_list); + + if (node != list_null (&thread_free_list)) + { + struct thread_node *thread = thread_links2ptr (node); + list_unlink (node); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); + return thread; + } + + return 0; +} + + +/* Return a thread structure to the global free list. Global lock + must be held by caller. */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ + thread_deinit (thread); + list_unlink (&thread->links); + list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup + handler. We never terminate threads ourselves; if a thread gets here + it means that the evil application has killed it. If the thread has + timers, these require servicing and so we must hire a replacement + thread right away. We must also unblock another thread that may + have been waiting for this thread to finish servicing a timer (see + timer_delete()). */ + +static void +thread_cleanup (void *val) +{ + if (val != NULL) + { + struct thread_node *thread = val; + + /* How did the signal thread get killed? */ + assert (thread != &__timer_signal_thread_rclk); + + pthread_mutex_lock (&__timer_mutex); + + thread->exists = 0; + + /* We are no longer processing a timer event. */ + thread->current_timer = 0; + + if (list_isempty (&thread->timer_queue)) + __timer_thread_dealloc (thread); + else + (void) __timer_thread_start (thread); + + pthread_mutex_unlock (&__timer_mutex); + + /* Unblock potentially blocked timer_delete(). */ + pthread_cond_broadcast (&thread->cond); + } +} + + +/* Handle a timer which is supposed to go off now. */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ + self->current_timer = timer; /* Lets timer_delete know timer is running. */ + + pthread_mutex_unlock (&__timer_mutex); + + switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + break; + + case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo + { + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t + value. */ + info.si_signo = timer->event.sigev_signo; + info.si_code = SI_TIMER; + info.si_pid = timer->creator_pid; + info.si_uid = getuid (); + info.si_value = timer->event.sigev_value; + + INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); + } +#else + if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) + { + if (pthread_kill (self->id, timer->event.sigev_signo) != 0) + abort (); + } +#endif + break; + + case SIGEV_THREAD: + timer->event.sigev_notify_function (timer->event.sigev_value); + break; + + default: + assert (! "unknown event"); + break; + } + + pthread_mutex_lock (&__timer_mutex); + + self->current_timer = 0; + + pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this + function is to wait on the thread's timer queue and expire the + timers in chronological order as close to their scheduled time as + possible. */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ + struct thread_node *self = arg; + + /* Register cleanup handler, in case rogue application terminates + this thread. (This cannot happen to __timer_signal_thread, which + doesn't invoke application callbacks). */ + + pthread_cleanup_push (thread_cleanup, self); + + pthread_mutex_lock (&__timer_mutex); + + while (1) + { + struct list_links *first; + struct timer_node *timer = NULL; + + /* While the timer queue is not empty, inspect the first node. */ + first = list_first (&self->timer_queue); + if (first != list_null (&self->timer_queue)) + { + struct timespec now; + + timer = timer_links2ptr (first); + + /* This assumes that the elements of the list of one thread + are all for the same clock. */ + clock_gettime (timer->clock, &now); + + while (1) + { + /* If the timer is due or overdue, remove it from the queue. + If it's a periodic timer, re-compute its new time and + requeue it. Either way, perform the timer expiry. */ + if (timespec_compare (&now, &timer->expirytime) < 0) + break; + + list_unlink_ip (first); + + if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 + || timer->value.it_interval.tv_nsec != 0) + { + timer->overrun_count = 0; + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + while (timespec_compare (&timer->expirytime, &now) < 0) + { + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + if (timer->overrun_count < DELAYTIMER_MAX) + ++timer->overrun_count; + } + __timer_thread_queue_timer (self, timer); + } + + thread_expire_timer (self, timer); + + first = list_first (&self->timer_queue); + if (first == list_null (&self->timer_queue)) + break; + + timer = timer_links2ptr (first); + } + } + + /* If the queue is not empty, wait until the expiry time of the + first node. Otherwise wait indefinitely. Insertions at the + head of the queue must wake up the thread by broadcasting + this condition variable. */ + if (timer != NULL) + pthread_cond_timedwait (&self->cond, &__timer_mutex, + &timer->expirytime); + else + pthread_cond_wait (&self->cond, &__timer_mutex); + } + /* This macro will never be executed since the while loop loops + forever - but we have to add it for proper nesting. */ + pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. + Returns 1 if the timer was inserted at the head of the queue, + causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert) +{ + struct list_links *iter; + int athead = 1; + + for (iter = list_first (&thread->timer_queue); + iter != list_null (&thread->timer_queue); + iter = list_next (iter)) + { + struct timer_node *timer = timer_links2ptr (iter); + + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; + athead = 0; + } + + list_insbefore (iter, &insert->links); + return athead; +} + + +/* Start a thread and associate it with the given thread node. Global + lock must be held by caller. */ +int +__timer_thread_start (struct thread_node *thread) +{ + int retval = 1; + + assert (!thread->exists); + thread->exists = 1; + + if (pthread_create (&thread->id, &thread->attr, + (void *(*) (void *)) thread_func, thread) != 0) + { + thread->exists = 0; + retval = -1; + } + + return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ + pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. + Returns 1 if they are equal, otherwise zero if they are not equal or + contain illegal values. This version is LinuxThreads-specific for + performance reason. One could use the access functions to get the + values of all the fields of the attribute structure. */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ + return (left->__detachstate == right->__detachstate + && left->__schedpolicy == right->__schedpolicy + && left->__guardsize == right->__guardsize + && (left->__schedparam.sched_priority + == right->__schedparam.sched_priority) + && left->__inheritsched == right->__inheritsched + && left->__scope == right->__scope + && left->__stacksize == right->__stacksize + && left->__stackaddr_set == right->__stackaddr_set + && (left->__stackaddr_set + || left->__stackaddr == right->__stackaddr)); +} + + +/* Search the list of active threads and find one which has matching + attributes. Global mutex lock must be held by caller. */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) +{ + struct list_links *iter = list_first (&thread_active_list); + + while (iter != list_null (&thread_active_list)) + { + struct thread_node *candidate = thread_links2ptr (iter); + + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) + return candidate; + + iter = list_next (iter); + } + + return NULL; +} + + +/* Grab a free timer structure from the global free list. The global + lock must be held by the caller. */ +struct timer_node * +__timer_alloc (void) +{ + struct list_links *node = list_first (&timer_free_list); + + if (node != list_null (&timer_free_list)) + { + struct timer_node *timer = timer_links2ptr (node); + list_unlink_ip (node); + timer->inuse = TIMER_INUSE; + timer->refcount = 1; + return timer; + } + + return NULL; +} + + +/* Return a timer structure to the global free list. The global lock + must be held by the caller. */ +void +__timer_dealloc (struct timer_node *timer) +{ + assert (timer->refcount == 0); + timer->thread = NULL; /* Break association between timer and thread. */ + timer->inuse = TIMER_FREE; + list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex. */ +void +__timer_mutex_cancel_handler (void *arg) +{ + pthread_mutex_unlock (arg); +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c b/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c new file mode 100644 index 0000000..592b527 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ + struct timer_node *timer; + struct thread_node *thread = NULL; + struct timespec now; + int have_now = 0, need_wakeup = 0; + int retval = -1; + + timer = timer_id2ptr (timerid); + if (timer == NULL) + { + __set_errno (EINVAL); + goto bail; + } + + if (value->it_interval.tv_nsec < 0 + || value->it_interval.tv_nsec >= 1000000000 + || value->it_value.tv_nsec < 0 + || value->it_value.tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + goto bail; + } + + /* Will need to know current time since this is a relative timer; + might as well make the system call outside of the lock now! */ + + if ((flags & TIMER_ABSTIME) == 0) + { + clock_gettime (timer->clock, &now); + have_now = 1; + } + + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + + /* One final check of timer validity; this one is possible only + until we have the mutex, because it accesses the inuse flag. */ + + if (! timer_valid(timer)) + { + __set_errno (EINVAL); + goto unlock_bail; + } + + if (ovalue != NULL) + { + ovalue->it_interval = timer->value.it_interval; + + if (timer->armed) + { + if (! have_now) + { + pthread_mutex_unlock (&__timer_mutex); + clock_gettime (timer->clock, &now); + have_now = 1; + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + } + + timespec_sub (&ovalue->it_value, &timer->expirytime, &now); + } + else + { + ovalue->it_value.tv_sec = 0; + ovalue->it_value.tv_nsec = 0; + } + } + + timer->value = *value; + + list_unlink_ip (&timer->links); + timer->armed = 0; + + thread = timer->thread; + + /* A value of { 0, 0 } causes the timer to be stopped. */ + if (value->it_value.tv_sec != 0 + || __builtin_expect (value->it_value.tv_nsec != 0, 1)) + { + if ((flags & TIMER_ABSTIME) != 0) + /* The user specified the expiration time. */ + timer->expirytime = value->it_value; + else + timespec_add (&timer->expirytime, &now, &value->it_value); + + /* Only need to wake up the thread if timer is inserted + at the head of the queue. */ + if (thread != NULL) + need_wakeup = __timer_thread_queue_timer (thread, timer); + timer->armed = 1; + } + + retval = 0; + +unlock_bail: + timer_delref (timer); + pthread_mutex_unlock (&__timer_mutex); + +bail: + if (thread != NULL && need_wakeup) + __timer_thread_wakeup (thread); + + return retval; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c b/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c new file mode 100644 index 0000000..7417bcd --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c @@ -0,0 +1,114 @@ +/* Tests for POSIX timer implementation. + Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + + +static void +notify_func (union sigval sigval) +{ + puts ("notify_func"); +} + + +static void +signal_func (int sig) +{ + static const char text[] = "signal_func\n"; + signal (sig, signal_func); + write (STDOUT_FILENO, text, sizeof text - 1); +} + +static void +intr_sleep (int sec) +{ + struct timespec ts; + + ts.tv_sec = sec; + ts.tv_nsec = 0; + + while (nanosleep (&ts, &ts) == -1 && errno == EINTR) + ; +} + +#define ZSIGALRM 14 + + +int +main (void) +{ + struct timespec ts; + timer_t timer_sig, timer_thr1, timer_thr2; + int retval; + struct sigevent sigev1 = + { + .sigev_notify = SIGEV_SIGNAL, + .sigev_signo = ZSIGALRM + }; + struct sigevent sigev2; + struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; + struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; + struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; + struct itimerspec old; + + retval = clock_gettime (CLOCK_REALTIME, &ts); + + sigev2.sigev_notify = SIGEV_THREAD; + sigev2.sigev_notify_function = notify_func; + sigev2.sigev_notify_attributes = NULL; + + setvbuf (stdout, 0, _IOLBF, 0); + + printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + retval = clock_getres (CLOCK_REALTIME, &ts); + + printf ("clock_getres returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + timer_create (CLOCK_REALTIME, &sigev1, &timer_sig); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2); + + timer_settime (timer_thr1, 0, &itimer2, &old); + timer_settime (timer_thr2, 0, &itimer3, &old); + + signal (ZSIGALRM, signal_func); + + timer_settime (timer_sig, 0, &itimer1, &old); + + timer_delete (-1); + + intr_sleep (3); + + timer_delete (timer_sig); + timer_delete (timer_thr1); + + intr_sleep (3); + + timer_delete (timer_thr2); + + return 0; +} diff --git a/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h b/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h new file mode 100644 index 0000000..e5c577f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h @@ -0,0 +1,47 @@ +#ifndef _UCLIBC_GLUE_H +#define _UCLIBC_GLUE_H 1 + +#include +#include +#include + +#ifdef IS_IN_libpthread +#include "kernel-features.h" + +#ifndef __GLIBC_HAVE_LONG_LONG +# define __GLIBC_HAVE_LONG_LONG +#endif + +#define __getpagesize getpagesize +#define __sched_get_priority_max sched_get_priority_max +#define __sched_get_priority_min sched_get_priority_min +#define __sched_getscheduler sched_getscheduler +#define __sched_setscheduler sched_setscheduler +#define __sched_getparam sched_getparam +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __poll poll +#define __sysctl sysctl +#define __open open +#define __read read +#define __close close +#define __on_exit on_exit +#define __libc_current_sigrtmin_private __libc_current_sigrtmin +#define __clone clone + +extern void *__libc_stack_end; +extern int __cxa_atexit (void (*func) (void *), void *arg, void *d); + +#endif /* IS_IN_libpthread */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define __uselocale(x) uselocale(x) +#else +# define __uselocale(x) ((void)0) +#endif + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/s390/pspinlock.c b/libpthread/linuxthreads/sysdeps/s390/pspinlock.c new file mode 100644 index 0000000..98be504 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/s390/pspinlock.c @@ -0,0 +1,91 @@ +/* POSIX spinlock implementation. S/390 version. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__(" basr 1,0\n" + "0: slr 0,0\n" + " cs 0,1,%1\n" + " jl 0b\n" + : "=m" (*lock) + : "m" (*lock) : "0", "1", "cc" ); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__(" slr %1,%1\n" + " basr 1,0\n" + "0: cs %1,1,%0" + : "=m" (*lock), "=&d" (oldval) + : "m" (*lock) : "1", "cc" ); + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__(" xc 0(4,%0),0(%0)\n" + " bcr 15,0" + : : "a" (lock) : "memory" ); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h b/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h new file mode 100644 index 0000000..d52d600 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + S390 version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + S/390 registers uses access register 0 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ ("ear %0,%%a0" : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ ("sar %%a0,%0" : : "d" (descr) ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " la 1,%1\n" + " lr 0,%2\n" + " cs 0,%3,0(1)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0", "1" ); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h b/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h new file mode 100644 index 0000000..187e1f8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h @@ -0,0 +1,125 @@ +/* Machine-dependent pthreads configuration and inline functions. + 64 bit S/390 version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + 64 bit S/390 uses access register 0 and 1 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ (" ear %0,%%a0\n" \ + " sllg %0,%0,32\n" \ + " ear %0,%%a1\n" \ + : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ (" sar %%a1,%0\n" \ + " srlg 0,%0,32\n" \ + " sar %%a0,0\n" \ + : : "d" (descr) : "0" ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " lgr 0,%2\n" + " csg 0,%3,%1\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0"); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym new file mode 100644 index 0000000..aee6be2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/libpthread/linuxthreads/sysdeps/s390/tls.h b/libpthread/linuxthreads/sysdeps/s390/tls.h new file mode 100644 index 0000000..f750f2d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/s390/tls.h @@ -0,0 +1,145 @@ +/* Definitions for thread-local data handling. linuxthreads/s390 version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* TLS is always supported if the tools support it. There are no + kernel dependencies. To avoid bothering with the TLS support code + at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h + conditionals. */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __builtin_set_thread_pointer (_descr); \ + NULL; \ + }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +# endif /* __ASSEMBLER__ */ + +#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +# ifndef __ASSEMBLER__ + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + INIT_THREAD_SELF (&nontls_init_tp, 0); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/sh/pspinlock.c b/libpthread/linuxthreads/sysdeps/sh/pspinlock.c new file mode 100644 index 0000000..c4e333a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/pspinlock.c @@ -0,0 +1,80 @@ +/* POSIX spinlock implementation. SH version. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/sh/pt-machine.h b/libpthread/linuxthreads/sysdeps/sh/pt-machine.h new file mode 100644 index 0000000..793f80b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/pt-machine.h @@ -0,0 +1,82 @@ +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +/* Return the thread descriptor for the current thread. */ +struct _pthread_descr_struct; +#define THREAD_SELF \ + ({ struct _pthread_descr_struct *self; \ + __asm__("stc gbr,%0" : "=r" (self)); self;}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 0000000..328eb05 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,10 @@ +#include +#include + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/libpthread/linuxthreads/sysdeps/sh/tls.h b/libpthread/linuxthreads/sysdeps/sh/tls.h new file mode 100644 index 0000000..350d129 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sh/tls.h @@ -0,0 +1,159 @@ +/* Definition for thread-local data handling. linuxthreads/SH version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm__ __volatile__ ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ({ struct _pthread_descr_struct *__self; \ + __asm__ ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + ({ struct _pthread_descr_struct *__self = (void *) descr; \ + __asm__ __volatile__ ("ldc %0,gbr" : : "r" (__self + 1)); \ + 0; }) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. This must be after the + the definition of THREAD_SELF for TLS. */ +# include + +# endif /* __ASSEMBLER__ */ + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __asm__ __volatile__ ("ldc %0,gbr" : : "r" (&nontls_init_tp)); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c b/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c new file mode 100644 index 0000000..72a9af5 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c @@ -0,0 +1,14 @@ +#include +#include + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/pspinlock.c" +# else +# include "sparc32/pspinlock.c" +# endif + +#else +# include "sparc64/pspinlock.c" +#endif diff --git a/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h new file mode 100644 index 0000000..ab90810 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "sparc32/pt-machine.h" +#else +# include "sparc64/pt-machine.h" +#endif diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c b/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c new file mode 100644 index 0000000..812c7ff --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c @@ -0,0 +1,88 @@ +/* POSIX spinlock implementation. SPARC32 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g2\n" + " orcc %%g2, 0x0, %%g0\n" + " bne,a 2f\n" + " ldub [%0], %%g2\n" + ".subsection 2\n" + "2: orcc %%g2, 0x0, %%g0\n" + " bne,a 2b\n" + " ldub [%0], %%g2\n" + " b,a 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory", "cc"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 0000000..43c05f2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,83 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c b/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c new file mode 100644 index 0000000..7e55df4 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c @@ -0,0 +1,94 @@ +/* POSIX spinlock implementation. SPARC v9 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g2\n" + " brnz,pn %%g2, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g2\n" + " brnz,pt %%g2, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c b/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c new file mode 100644 index 0000000..e0c350e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c @@ -0,0 +1,93 @@ +/* POSIX spinlock implementation. SPARC64 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g5\n" + " brnz,pn %%g5, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g5\n" + " brnz,pt %%g5, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g5", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h b/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 0000000..815d70e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 0000000..aee6be2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/libpthread/linuxthreads/sysdeps/sparc/tls.h b/libpthread/linuxthreads/sysdeps/sparc/tls.h new file mode 100644 index 0000000..2df97d6 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/sparc/tls.h @@ -0,0 +1,115 @@ +/* Definitions for thread-local data handling. linuxthreads/sparc version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +# endif + +#else + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore new file mode 100644 index 0000000..7ee8f59 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore @@ -0,0 +1,2 @@ +.cvsignore +*.os diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h new file mode 100644 index 0000000..a3f303c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h @@ -0,0 +1,26 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +__extern_always_inline int __libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 0000000..b9ada64 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,87 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +static int current_rtmin; +static int current_rtmax; + +static int initialized; + +#include + +static void +init (void) +{ + if (!kernel_has_rtsig ()) + { + current_rtmin = -1; + current_rtmax = -1; + } + else + { + current_rtmin = __SIGRTMIN + 3; + current_rtmax = __SIGRTMAX; + } + initialized = 1; +} + +/* Return number of available real-time signal with highest priority. */ +int +__libc_current_sigrtmin (void) +{ + if (!initialized) + init (); + return current_rtmin; +} +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private) +libc_hidden_def (__libc_current_sigrtmin) + +/* Return number of available real-time signal with lowest priority. */ +int +__libc_current_sigrtmax (void) +{ + if (!initialized) + init (); + return current_rtmax; +} +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private) +libc_hidden_def (__libc_current_sigrtmax) + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int +__libc_allocate_rtsig (int high) +{ + if (!initialized) + init (); + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} +strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c new file mode 100644 index 0000000..0d6da82 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 0000000..96893c5 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h new file mode 100644 index 0000000..a272488 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/Alpha version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U64_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __U32_TYPE +#define __INO64_T_TYPE __U64_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __S64_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __U64_TYPE +#define __BLKCNT_T_TYPE __U32_TYPE +#define __BLKCNT64_T_TYPE __U64_TYPE +#define __FSBLKCNT_T_TYPE __S32_TYPE +#define __FSBLKCNT64_T_TYPE __S64_TYPE +#define __FSFILCNT_T_TYPE __U32_TYPE +#define __FSFILCNT64_T_TYPE __U64_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S64_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __U32_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S new file mode 100644 index 0000000..91e5c86 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S @@ -0,0 +1,28 @@ +/* Internal sigsuspend system call for LinuxThreads. Alpha version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS ldq a0, 0(a0); + + .hidden __pthread_sigsuspend +PSEUDO_NOERRNO(__pthread_sigsuspend, sigsuspend, 1) + ret +PSEUDO_END_NOERRNO(__pthread_sigsuspend) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 0000000..9ea779e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,146 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + lda AT, _mcount; \ + jsr AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END + besides "ret". */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .type name, @function; \ + .usepv name, std; \ + cfi_startproc; \ +__LABEL(name) \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + PSEUDO_PREPARE_ARGS \ + SINGLE_THREAD_P(t0); \ + bne t0, $pseudo_cancel; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + bne a3, SYSCALL_ERROR_LABEL; \ +__LABEL($pseudo_ret) \ + .subsection 2; \ +__LABEL($pseudo_cancel) \ + subq sp, 64, sp; \ + cfi_def_cfa_offset(64); \ + stq ra, 0(sp); \ + cfi_offset(ra, -64); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + stq v0, 8(sp); \ + bne a3, $multi_error; \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_remember_state; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ + ret; \ + cfi_restore_state; \ +__LABEL($multi_error) \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ +__LABEL($syscall_error) \ + SYSCALL_ERROR_HANDLER; \ + .previous + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + .subsection 2; \ + cfi_endproc; \ + .size sym, .-sym + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifdef PIC +# define CENABLE bsr ra, __local_enable_asynccancel !samegp +# define CDISABLE bsr ra, __local_disable_asynccancel !samegp +# else +# define CENABLE jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +# define CDISABLE jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# elif defined(PIC) +# define SINGLE_THREAD_P(reg) ldl reg, __local_multiple_threads(gp) !gprel +# else +# define SINGLE_THREAD_P(reg) \ + ldah reg, __local_multiple_threads(gp) !gprelhigh; \ + ldl reg, __local_multiple_threads(reg) !gprellow +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 0000000..cfaae10 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,70 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include + + .align 4 + .globl __vfork + .type __vfork, @function + .usepv __vfork, std + cfi_startproc +__vfork: + ldgp gp, 0(pv) + PSEUDO_PROF + +#ifdef SHARED + ldq t0, __libc_pthread_functions(gp) !gprel + bne t0, HIDDEN_JUMPTARGET (__fork) !samegp +#else + .weak pthread_create + ldq t0, pthread_create(gp) !literal + bne t0, $do_fork +#endif + + lda v0, SYS_ify(vfork) + call_pal PAL_callsys + bne a3, SYSCALL_ERROR_LABEL + ret + +#ifndef SHARED + /* Can't tail-call due to possible mismatch between GP in + fork and vfork object files. */ +$do_fork: + subq sp, 16, sp + cfi_adjust_cfa_offset(16) + stq ra, 0(sp) + cfi_offset(ra, -16) + jsr ra, HIDDEN_JUMPTARGET (__fork) + ldgp gp, 0(ra) + ldq ra, 0(sp) + addq sp, 16, sp + cfi_restore(ra) + cfi_adjust_cfa_offset(-16) + ret + +$syscall_error: + SYSCALL_ERROR_HANDLER +#endif + + cfi_endproc + .size __vfork, .-__vfork + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c new file mode 100644 index 0000000..9fa912b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include +#include +#include + +extern int __syscall_execve (const char *__unbounded file, + char *__unbounded const *__unbounded argv, + char *__unbounded const *__unbounded envp); +extern void __pthread_kill_other_threads_np (void); +weak_extern (__pthread_kill_other_threads_np) + + +int +__execve (file, argv, envp) + const char *file; + char *const argv[]; + char *const envp[]; +{ + /* If this is a threaded application kill all other threads. */ + if (__pthread_kill_other_threads_np) + __pthread_kill_other_threads_np (); +#if __BOUNDED_POINTERS__ + { + char *const *v; + int i; + char *__unbounded *__unbounded ubp_argv; + char *__unbounded *__unbounded ubp_envp; + char *__unbounded *__unbounded ubp_v; + + for (v = argv; *v; v++) + ; + i = v - argv + 1; + ubp_argv = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_argv) * i); + for (v = argv, ubp_v = ubp_argv; --i; v++, ubp_v++) + *ubp_v = CHECK_STRING (*v); + *ubp_v = 0; + + for (v = envp; *v; v++) + ; + i = v - envp + 1; + ubp_envp = (char *__unbounded *__unbounded) alloca (sizeof (*ubp_envp) * i); + for (v = envp, ubp_v = ubp_envp; --i; v++, ubp_v++) + *ubp_v = CHECK_STRING (*v); + *ubp_v = 0; + + return INLINE_SYSCALL (execve, 3, CHECK_STRING (file), ubp_argv, ubp_envp); + } +#else + return INLINE_SYSCALL (execve, 3, file, argv, envp); +#endif +} +weak_alias (__execve, execve) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 0000000..e15b99b --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +struct fork_block __fork_block = +{ + .lock = PTHREAD_MUTEX_INITIALIZER, + .prepare_list = { &__fork_block.prepare_list, &__fork_block.prepare_list }, + .parent_list = { &__fork_block.parent_list, &__fork_block.parent_list }, + .child_list = { &__fork_block.child_list, &__fork_block.child_list } +}; diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 0000000..85477eb --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +struct fork_block +{ + /* Lock to protect handling of fork handlers. */ + __libc_lock_define (, lock); + + /* Lists of registered fork handlers. */ + list_t prepare_list; + list_t parent_list; + list_t child_list; +}; + +extern struct fork_block __fork_block attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + list_t list; + void (*handler) (void); + void *dso_handle; +}; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); + +#ifndef ARCH_FORK +# define ARCH_FORK() __libc_fork() +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c new file mode 100644 index 0000000..0d6da82 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h new file mode 100644 index 0000000..9b13400 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h @@ -0,0 +1,27 @@ +/* PA-RISC specific definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. PA-RISC only implements atomic load + and clear so this must be non-zero. */ +#define __LT_SPINLOCK_INIT 1 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h new file mode 100644 index 0000000..6a53da2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h @@ -0,0 +1,73 @@ +/* HP-PARISC macro definitions for mutexes, thread-specific data + and parameters for malloc. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include +#include + +__libc_lock_define (typedef, mutex_t) + +/* Since our lock structure does not tolerate being initialized to zero, we must + modify the standard function calls made by malloc */ +# define mutex_init(m) \ + __libc_maybe_call (__pthread_mutex_init, (m, NULL), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT),(*(int *)(m))) ) +# define mutex_lock(m) \ + __libc_maybe_call (__pthread_mutex_lock, (m), \ + (__load_and_clear(&((m)->__m_lock.__spinlock)), 0)) +# define mutex_trylock(m) \ + __libc_maybe_call (__pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : (__load_and_clear(&((m)->__m_lock.__spinlock)), 0))) +# define mutex_unlock(m) \ + __libc_maybe_call (__pthread_mutex_unlock, (m), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT), (*(int *)(m))) ) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c new file mode 100644 index 0000000..27f850c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c @@ -0,0 +1,109 @@ +/* Special .init and .fini section support for HPPA. Linuxthreads version. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +/* If we use the standard C version, the linkage table pointer won't + be properly preserved due to the splitting up of function prologues + and epilogues. Therefore we write these in assembly to make sure + they do the right thing. */ + +__asm__ ( +"#include \"defs.h\"\n" +"\n" +"/*@HEADER_ENDS*/\n" +"\n" +"/*@_init_PROLOG_BEGINS*/\n" +" .section .init\n" +" .align 4\n" +" .globl _init\n" +" .type _init,@function\n" +"_init:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" bl __pthread_initialize_minimal,%rp\n" +" copy %r19,%r4 /* delay slot */\n" +" copy %r4,%r19\n" +"/*@_init_PROLOG_ENDS*/\n" +"\n" +"/*@_init_EPILOG_BEGINS*/\n" +"/* Here is the tail end of _init. */\n" +" .section .init\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_init:\n" +" ldwm -64(%sp),%r4\n" +"\n" +"/* Our very own unwind info, because the assembler can't handle\n" +" functions split into two or more pieces. */\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _init\n" +" .word _init, _end_init\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_init_EPILOG_ENDS*/\n" +"\n" +"/*@_fini_PROLOG_BEGINS*/\n" +" .section .fini\n" +" .align 4\n" +" .globl _fini\n" +" .type _fini,@function\n" +"_fini:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" copy %r19,%r4\n" +"/*@_fini_PROLOG_ENDS*/\n" +"\n" +"/*@_fini_EPILOG_BEGINS*/\n" +" .section .fini\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_fini:\n" +" ldwm -64(%sp),%r4\n" +"\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _fini\n" +" .word _fini, _end_fini\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_fini_EPILOG_ENDS*/\n" +"\n" +"/*@TRAILER_BEGINS*/\n" +); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h new file mode 100644 index 0000000..134977e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h @@ -0,0 +1,189 @@ +/* cancellable system calls for Linux/HPPA. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifndef NO_ERROR +# define NO_ERROR -0x1000 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + ENTRY (name) \ + SINGLE_THREAD_P ASM_LINE_SEP \ + cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + DO_CALL(syscall_name, args) ASM_LINE_SEP \ + /* DONE! */ ASM_LINE_SEP \ + bv 0(2) ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + Lpseudo_cancel: ASM_LINE_SEP \ + /* store return ptr */ ASM_LINE_SEP \ + stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ + /* save syscall args */ ASM_LINE_SEP \ + PUSHARGS_##args /* MACRO */ ASM_LINE_SEP \ + STW_PIC ASM_LINE_SEP \ + CENABLE /* FUNC CALL */ ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* restore syscall args */ ASM_LINE_SEP \ + POPARGS_##args ASM_LINE_SEP \ + /* save r4 in arg0 stack slot */ ASM_LINE_SEP \ + stw %r4, -36(%sr0,%sp) ASM_LINE_SEP \ + /* save mask from cenable */ ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + ble 0x100(%sr2,%r0) ASM_LINE_SEP \ + ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \ + copy %r4, %r26 ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + CDISABLE ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* compare error */ ASM_LINE_SEP \ + ldi NO_ERROR,%r1 ASM_LINE_SEP \ + /* branch if no error */ ASM_LINE_SEP \ + cmpb,>>=,n %r1,%r4,Lpre_end ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + /* make syscall res value positive */ ASM_LINE_SEP \ + sub %r0, %r4, %r4 ASM_LINE_SEP \ + /* store into errno location */ ASM_LINE_SEP \ + stw %r4, 0(%sr0,%ret0) ASM_LINE_SEP \ + /* return -1 */ ASM_LINE_SEP \ + ldo -1(%r0), %ret0 ASM_LINE_SEP \ + Lpre_end: ASM_LINE_SEP \ + ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + ldw -36(%sr0,%sp), %r4 ASM_LINE_SEP + +/* Save arguments into our frame */ +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_5 PUSHARGS_4 /* Args are on the stack... */ +# define PUSHARGS_6 PUSHARGS_5 + +/* Bring them back from the stack */ +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP +# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP +# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP +# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP +# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP +# define POPARGS_6 POPARGS_5 ldw -54(%sr0,%sp), %r21 ASM_LINE_SEP + +# ifdef IS_IN_libpthread +# ifdef PIC +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# elif !defined NOT_IN_libc +# ifdef PIC +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# else +# ifdef PIC +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# endif + +/* p_header.multiple_threads is +12 from the pthread_descr struct start, + We could have called __get_cr27() but we really want less overhead */ +# define MULTIPLE_THREADS_OFFSET 0xC + +/* cr27 has been initialized to 0x0 by kernel */ +# define NO_THREAD_CR27 0x0 + +# ifdef IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ + extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +/* This ALT version requires newer kernel support */ +# define SINGLE_THREAD_P_MFCTL \ + mfctl %cr27, %ret0 ASM_LINE_SEP \ + cmpib,= NO_THREAD_CR27,%ret0,Lstp ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \ + Lstp: ASM_LINE_SEP +# ifdef PIC +/* Slower version uses GOT to get value of __local_multiple_threads */ +# define SINGLE_THREAD_P \ + addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \ + ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \ + ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP +# else + /* Slow non-pic version using DP */ +# define SINGLE_THREAD_P \ + addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \ + ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP +# endif +# endif +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif +/* !defined NOT_IN_libc || defined IS_IN_libpthread */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 0000000..a5dbeff --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,187 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + int $0x80 \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 + +# define PUSHCARGS_0 /* No arguments to push. */ +# define DOCARGS_0 /* No arguments to frob. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (edi); + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# elif defined IS_IN_librt +# ifdef PIC +# define CENABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_enable_asynccancel@PLT; \ + popl %ebx; +# define CDISABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_disable_asynccancel@PLT; \ + popl %ebx; +# else +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# endif +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); +# define POPSTATE_3 POPSTATE_2 +# define POPSTATE_4 POPSTATE_3 +# define POPSTATE_5 POPSTATE_4 + +#if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +#elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +#else +# define __local_multiple_threads __librt_multiple_threads +#endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined PIC +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined PIC +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define __SINGLE_THREAD_CMP cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# else +# define __SINGLE_THREAD_CMP \ + movl __local_multiple_threads@GOT(%ecx), %ecx;\ + cmpl $0, (%ecx) +# endif +# if !defined HAVE_HIDDEN || !USE___THREAD +# define SINGLE_THREAD_P \ + SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# else +# define SINGLE_THREAD_P \ + call __i686.get_pc_thunk.cx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 0000000..c7a120d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,95 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED +# if !defined HAVE_HIDDEN || !USE___THREAD + SETUP_PIC_REG (cx) +# else + call __i686.get_pc_thunk.cx +# endif + addl $_GLOBAL_OFFSET_TABLE_, %ecx + cmpl $0, __libc_pthread_functions@GOTOFF(%ecx) +# else + .weak pthread_create + movl $pthread_create, %eax + testl %eax, %eax +# endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into ECX. */ + popl %ecx + + /* Stuff the syscall number in EAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + int $0x80 + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + + cmpl $-4095, %eax + /* Branch forward if it failed. */ +# ifdef __ASSUME_VFORK_SYSCALL + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: +# else + jae .Lerror +# endif + + ret + +# ifndef __ASSUME_VFORK_SYSCALL +.Lerror: + /* Check if vfork syscall is known at all. */ + cmpl $-ENOSYS, %eax + jne SYSCALL_ERROR_LABEL +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movl $SYS_ify (fork), %eax + int $0x80 + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: + ret +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h new file mode 100644 index 0000000..629b1f8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 196608 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h new file mode 100644 index 0000000..30a0cc1 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define ARCH_FORK() INLINE_SYSCALL (clone, 2, SIGCHLD, 0) + +#include_next diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c new file mode 100644 index 0000000..af8a63c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c @@ -0,0 +1,142 @@ +/* Special .init and .fini section support for ia64. LinuxThreads version. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +#ifdef HAVE_INITFINI_ARRAY + +# define INIT_NEW_WAY \ + ".xdata8 \".init_array\", @fptr(__pthread_initialize_minimal)\n" +# define INIT_OLD_WAY "" +#else +# define INIT_NEW_WAY "" +# define INIT_OLD_WAY \ + "\n\ + st8 [r12] = gp, -16\n\ + br.call.sptk.many b0 = __pthread_initialize_minimal# ;;\n\ + ;;\n\ + adds r12 = 16, r12\n\ + ;;\n\ + ld8 gp = [r12]\n\ + ;;\n" +#endif + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n" + INIT_NEW_WAY + ".section .init\n\ + .align 16\n\ + .global _init#\n\ + .proc _init#\n\ +_init:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n" + INIT_OLD_WAY + ".endp _init#\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + .proc _init#\n\ +_init:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _init#\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 16\n\ + .global _fini#\n\ + .proc _fini#\n\ +_fini:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n\ + .endp _fini#\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + .proc _fini#\n\ +_fini:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _fini#\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + .weak __gmon_start__#\n\ +"); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c new file mode 100644 index 0000000..0b96e3d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. IA64 version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include +#include + +void +__pthread_sigsuspend (const sigset_t *set) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h new file mode 100644 index 0000000..dd9637d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef IS_IN_librt +# define PSEUDO_NLOCAL 6 +# define PSEUDO_SAVE_GP mov loc5 = gp +# define PSEUDO_RESTORE_GP mov gp = loc5 +# define PSEUDO_SAVE_GP_1 +# define PSEUDO_RESTORE_GP_1 mov gp = loc5 +# else +# define PSEUDO_NLOCAL 5 +# define PSEUDO_SAVE_GP +# define PSEUDO_RESTORE_GP +# define PSEUDO_SAVE_GP_1 mov loc4 = gp;; +# define PSEUDO_RESTORE_GP_1 mov gp = loc4 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +.text; \ +ENTRY (name) \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13;; \ + ld4 r14 = [r14]; \ + mov r15 = SYS_ify(syscall_name);; \ + cmp4.ne p6, p7 = 0, r14; \ +(p6) br.cond.spnt .Lpseudo_cancel;; \ + break __BREAK_SYSCALL;; \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; \ + ret;; \ + .endp name; \ + .proc __GC_##name; \ + .globl __GC_##name; \ + .hidden __GC_##name; \ +__GC_##name: \ +.Lpseudo_cancel: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + alloc loc0 = ar.pfs, args, PSEUDO_NLOCAL, args, 0; \ + .save rp, loc1; \ + mov loc1 = rp; \ + PSEUDO_SAVE_GP;; \ + .body; \ + CENABLE;; \ + PSEUDO_RESTORE_GP; \ + mov loc2 = r8; \ + COPY_ARGS_##args \ + mov r15 = SYS_ify(syscall_name); \ + break __BREAK_SYSCALL;; \ + mov loc3 = r8; \ + mov loc4 = r10; \ + mov out0 = loc2; \ + CDISABLE;; \ + PSEUDO_RESTORE_GP; \ + cmp.eq p6,p0=-1,loc4; \ +(p6) br.cond.spnt.few __syscall_error_##args; \ + mov r8 = loc3; \ + mov rp = loc1; \ + mov ar.pfs = loc0; \ +.Lpseudo_end: \ + ret; \ + .endp __GC_##name; \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax"; \ + .align 32; \ + .proc __syscall_error_##args; \ + .global __syscall_error_##args; \ + .hidden __syscall_error_##args; \ + .size __syscall_error_##args, 64; \ +__syscall_error_##args: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + .save rp, loc1; \ + .body; \ + PSEUDO_SAVE_GP_1; \ + br.call.sptk.many b0 = __errno_location;; \ + st4 [r8] = loc3; \ + PSEUDO_RESTORE_GP_1; \ + mov rp = loc1; \ + mov r8 = -1; \ + mov ar.pfs = loc0 + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp + +# ifdef IS_IN_libpthread +# define CENABLE br.call.sptk.many b0 = __pthread_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE br.call.sptk.many b0 = __libc_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __libc_disable_asynccancel +# else +# define CENABLE br.call.sptk.many b0 = __librt_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov out0 = in0; +#define COPY_ARGS_2 COPY_ARGS_1 mov out1 = in1; +#define COPY_ARGS_3 COPY_ARGS_2 mov out2 = in2; +#define COPY_ARGS_4 COPY_ARGS_3 mov out3 = in3; +#define COPY_ARGS_5 COPY_ARGS_4 mov out4 = in4; +#define COPY_ARGS_6 COPY_ARGS_5 mov out5 = in5; +#define COPY_ARGS_7 COPY_ARGS_6 mov out6 = in6; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S new file mode 100644 index 0000000..54aceda --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#define _SIGNAL_H +#include + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) +#ifdef SHARED + addl r14 = @gprel(__libc_pthread_functions#), gp;; +#else + .weak pthread_create + addl r14 = @ltoff(@fptr(pthread_create#)), gp;; +#endif + ld8 r14 = [r14];; + cmp.ne p6, p7 = 0, r14 +(p6) br.cond.spnt.few HIDDEN_JUMPTARGET (__fork);; + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 + ;; +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 0000000..4b90315 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,34 @@ +/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifndef SHARED +weak_extern (__pthread_cleanup_upto); +#endif + +void +_longjmp_unwind (jmp_buf env, int val) +{ + __libc_maybe_call2 (pthread_cleanup_upto, + (env->__jmpbuf, __builtin_frame_address (0)), + (void) 0); +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h new file mode 100644 index 0000000..bb798e4 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL; \ + rts; \ + .Lpseudo_cancel: \ + CENABLE; \ + DOCARGS_##args \ + move.l %d0, -(%sp); \ + move.l &SYS_ify (syscall_name), %d0; \ + trap &0; \ + move.l %d0, %d2; \ + CDISABLE; \ + addq.l &4, %sp; \ + move.l %d2, %d0; \ + UNDOCARGS_##args \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL + +# define DOCARGS_0 move.l %d2, -(%sp); +# define _DOCARGS_0(n) +# define UNDOCARGS_0 move.l (%sp)+, %d2; + +# define DOCARGS_1 _DOCARGS_1 (4); DOCARGS_0 +# define _DOCARGS_1(n) move.l n(%sp), %d1; _DOARGS_0 (n) +# define UNDOCARGS_1 UNDOCARGS_0 + +# define DOCARGS_2 _DOCARGS_2 (8) +# define _DOCARGS_2(n) move.l %d2, -(%sp); move.l n+4(%sp), %d2; \ + _DOCARGS_1 (n) +# define UNDOCARGS_2 UNDOCARGS_1 + +# define DOCARGS_3 _DOCARGS_3 (12) +# define _DOCARGS_3(n) move.l %d3, -(%sp); move.l n+4(%sp), %d3; \ + _DOCARGS_2 (n) +# define UNDOCARGS_3 UNDOCARGS_2; move.l (%sp)+, %d3; + +# define DOCARGS_4 _DOCARGS_4 (16) +# define _DOCARGS_4(n) move.l %d4, -(%sp); move.l n+4(%sp), %d4; \ + _DOCARGS_3 (n) +# define UNDOCARGS_4 UNDOCARGS_3; move.l (%sp)+, %d4; + +# define DOCARGS_5 _DOCARGS_5 (20) +# define _DOCARGS_5(n) move.l %d5, -(%sp); move.l n+4(%sp), %d5; \ + _DOCARGS_4 (n) +# define UNDOCARGS_5 UNDOCARGS_4; move.l (%sp)+, %d5; + +# ifdef IS_IN_libpthread +# ifdef PIC +# define CENABLE jbsr __pthread_enable_asynccancel@PLTPC +# define CDISABLE jbsr __pthread_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __pthread_enable_asynccancel +# define CDISABLE jbsr __pthread_disable_asynccancel +# endif +# elif !defined NOT_IN_libc +# ifdef PIC +# define CENABLE jbsr __libc_enable_asynccancel@PLTPC +# define CDISABLE jbsr __libc_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __libc_enable_asynccancel +# define CDISABLE jbsr __libc_disable_asynccancel +# endif +# else +# ifdef PIC +# define CENABLE jbsr __librt_enable_asynccancel@PLTPC +# define CDISABLE jbsr __librt_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __librt_enable_asynccancel +# define CDISABLE jbsr __librt_disable_asynccancel +# endif +# endif + +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined PIC +# define SINGLE_THREAD_P tst.l __local_multiple_threads +# else +# define SINGLE_THREAD_P tst.l (__local_multiple_threads, %pc) +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S new file mode 100644 index 0000000..49b8a3c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S @@ -0,0 +1,84 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + tstl (__libc_pthread_functions@GOTPC, %pc) +#else + .weak pthread_create + movel #pthread_create, %d0 +#endif + jbne HIDDEN_JUMPTARGET (__fork) + +#ifdef __NR_vfork + + /* Pop the return PC value into A0. */ + movel %sp@+, %a0 + + /* Stuff the syscall number in D0 and trap into the kernel. */ + movel #SYS_ify (vfork), %d0 + trap #0 + tstl %d0 + jmi .Lerror /* Branch forward if it failed. */ + + /* Jump to the return PC. */ + jmp %a0@ + +.Lerror: + /* Push back the return PC. */ + movel %a0,%sp@- + +# ifdef __ASSUME_VFORK_SYSCALL +# ifndef PIC + jbra SYSCALL_ERROR_LABEL +# endif +# else + /* Check if vfork syscall is known at all. */ + movel #-ENOSYS,%d1 + cmpl %d0,%d1 + jne SYSCALL_ERROR_LABEL + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movel #SYS_ify (fork), %d0 + trap #0 + tstl %d0 + jmi SYSCALL_ERROR_LABEL + rts +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h new file mode 100644 index 0000000..fc51774 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* system call stubs with cancellation handling. Linux/MIPS version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Demetriou of Broadcom Corporation, + based on work by Guido Guenther . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif +#include + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: \ + PTR_LA t9,__syscall_error; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + jr t9; \ + ENTRY (name) \ + SAVESTK ; \ + .cpsetup t9, STKOFF_GP, name ; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + ret; \ + L(pseudo_cancel): \ + REG_S ra, STKOFF_RA(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + REG_S v0, STKOFF_SVMSK(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + REG_S v0, STKOFF_SC_V0(sp); /* save syscall result */ \ + REG_S a3, STKOFF_SC_ERR(sp); /* save syscall error flag */ \ + REG_L a0, STKOFF_SVMSK(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + REG_L a3, STKOFF_SC_ERR(sp); /* restore syscall error flag */ \ + REG_L ra, STKOFF_RA(sp); /* restore return address */ \ + REG_L v0, STKOFF_SC_V0(sp); /* restore syscall result */ \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 REG_S a0, STKOFF_A0(sp); +# define PUSHARGS_2 PUSHARGS_1 REG_S a1, STKOFF_A1(sp); +# define PUSHARGS_3 PUSHARGS_2 REG_S a2, STKOFF_A2(sp); +# define PUSHARGS_4 PUSHARGS_3 REG_S a3, STKOFF_A3(sp); +# define PUSHARGS_5 PUSHARGS_4 REG_S a4, STKOFF_A4(sp); +# define PUSHARGS_6 PUSHARGS_5 REG_S a5, STKOFF_A5(sp); + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 REG_L a0, STKOFF_A0(sp); +# define POPARGS_2 POPARGS_1 REG_L a1, STKOFF_A1(sp); +# define POPARGS_3 POPARGS_2 REG_L a2, STKOFF_A2(sp); +# define POPARGS_4 POPARGS_3 REG_L a3, STKOFF_A3(sp); +# define POPARGS_5 POPARGS_4 REG_L a4, STKOFF_A4(sp); +# define POPARGS_6 POPARGS_5 REG_L a5, STKOFF_A5(sp); + +/* Save an even number of slots. Should be 0 if an even number of slots + are used below, or SZREG if an odd number are used. */ +# define STK_PAD SZREG + +/* Place values that we are more likely to use later in this sequence, i.e. + closer to the SP at function entry. If you do that, the are more + likely to already be in your d-cache. */ +# define STKOFF_A5 (STK_PAD) +# define STKOFF_A4 (STKOFF_A5 + SZREG) +# define STKOFF_A3 (STKOFF_A4 + SZREG) +# define STKOFF_A2 (STKOFF_A3 + SZREG) /* MT and more args. */ +# define STKOFF_A1 (STKOFF_A2 + SZREG) /* MT and 2 args. */ +# define STKOFF_A0 (STKOFF_A1 + SZREG) /* MT and 1 arg. */ +# define STKOFF_RA (STKOFF_A0 + SZREG) /* Used if MT. */ +# define STKOFF_SC_V0 (STKOFF_RA + SZREG) /* Used if MT. */ +# define STKOFF_SC_ERR (STKOFF_SC_V0 + SZREG) /* Used if MT. */ +# define STKOFF_SVMSK (STKOFF_SC_ERR + SZREG) /* Used if MT. */ +# define STKOFF_GP (STKOFF_SVMSK + SZREG) /* Always used. */ + +# define STKSPACE (STKOFF_GP + SZREG) +# define SAVESTK PTR_SUBU sp, STKSPACE +# define RESTORESTK PTR_ADDU sp, STKSPACE + +# ifdef IS_IN_libpthread +# define CENABLE PTR_LA t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE PTR_LA t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE PTR_LA t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 0000000..1fff782 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Guido Guenther , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: la t9,__syscall_error; \ + jr t9; \ + ENTRY (name) \ + .set noreorder; \ + .cpload t9; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args; \ + sw ra, 28(sp); \ + sw gp, 32(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + lw gp, 32(sp); \ + sw v0, 44(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + sw v0, 36(sp); /* save syscall result */ \ + sw a3, 40(sp); /* save syscall error flag */ \ + lw a0, 44(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + lw gp, 32(sp); \ + lw v0, 36(sp); /* restore syscall result */ \ + lw a3, 40(sp); /* restore syscall error flag */ \ + lw ra, 28(sp); /* restore return address */ \ + RESTORESTK; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp); +# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp); +# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp); +# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp); +# define PUSHARGS_5 PUSHARGS_4 /* handeld by SAVESTK_## */ +# define PUSHARGS_6 PUSHARGS_5 +# define PUSHARGS_7 PUSHARGS_6 + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 lw a0, 0(sp); +# define POPARGS_2 POPARGS_1 lw a1, 4(sp); +# define POPARGS_3 POPARGS_2 lw a2, 8(sp); +# define POPARGS_4 POPARGS_3 lw a3, 12(sp); +# define POPARGS_5 POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6 POPARGS_5 +# define POPARGS_7 POPARGS_6 + + +# define STKSPACE 48 +# define SAVESTK_0 subu sp, STKSPACE +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 SAVESTK_2 +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 lw t0, 16(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp) + +# define SAVESTK_6 lw t0, 16(sp); \ + lw t1, 20(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp) + +# define SAVESTK_7 lw t0, 16(sp); \ + lw t1, 20(sp); \ + lw t2, 24(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp); \ + sw t2, 24(sp) + +# define RESTORESTK addu sp, STKSPACE + + +# ifdef IS_IN_libpthread +# define CENABLE la t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE la t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE la t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S new file mode 100644 index 0000000..7bbab5c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S @@ -0,0 +1,104 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* vfork() is just a special case of clone(). */ + +#include +#include +#include + +/* int vfork() */ + + .text +LOCALSZ= 1 +FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK +GPOFF= FRAMESZ-(1*SZREG) +NESTED(__vfork,FRAMESZ,sp) +#ifdef __PIC__ + SETUP_GP +#endif + PTR_SUBU sp, FRAMESZ + SETUP_GP64 (a5, __vfork) +#ifdef __PIC__ + SAVE_GP (GPOFF) +#endif +#ifdef PROF +# if (_MIPS_SIM != _ABIO32) + PTR_S a5, GPOFF(sp) +# endif + .set noat + move $1, ra +# if (_MIPS_SIM == _ABIO32) + subu sp,sp,8 +# endif + jal _mcount + .set at +# if (_MIPS_SIM != _ABIO32) + PTR_L a5, GPOFF(sp) +# endif +#endif + + /* If libpthread is loaded, we need to call fork instead. */ +#ifdef SHARED + PTR_L a0, __libc_pthread_functions +#else + .weak pthread_create + PTR_LA a0, pthread_create +#endif + + PTR_ADDU sp, FRAMESZ + + bnez a0, L(call_fork) + + li a0, 0x4112 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ + move a1, sp + + /* Do the system call */ + li v0,__NR_clone + syscall + + bnez a3,L(error) + + /* Successful return from the parent or child. */ + RESTORE_GP64 + ret + + /* Something bad happened -- no child created. */ +L(error): +#ifdef __PIC__ + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + RESTORE_GP64 + j __syscall_error +#endif + +L(call_fork): +#ifdef __PIC__ + PTR_LA t9, fork + RESTORE_GP64 + jr t9 +#else + RESTORE_GP64 + j fork +#endif + END(__vfork) + +libc_hidden_def(__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 0000000..6cd0f09 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,287 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + __volatile__ union notify_data *data = (__volatile__ union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + + /* Make sure the descriptor is closed on exec. */ + if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0) + goto errout; + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static smallint added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + errout: + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + +/* Register notification upon message arrival to an empty message queue + MQDES. */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__builtin_expect (netlink_socket == -1, 0)) + { + __set_errno (ENOSYS); + return -1; + } + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__builtin_expect (retval != 0, 0)) + free (data.attr); + + return retval; +} + +#else +# include +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 0000000..865da8e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,159 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stwu 1,-48(1); \ + mflr 9; \ + stw 9,52(1); \ + CGOTSETUP; \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + stw 3,16(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + stw 3,8(1); \ + stw 0,12(1); \ + lwz 3,16(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + lwz 4,52(1); \ + lwz 0,12(1); /* restore CR/R3. */ \ + lwz 3,8(1); \ + CGOTRESTORE; \ + mtlr 4; \ + mtcr 0; \ + addi 1,1,48; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2 stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3 stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4 stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5 stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6 stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5 + +# define CGOTSETUP +# define CGOTRESTORE + +# ifdef IS_IN_libpthread +# define CENABLE bl __pthread_enable_asynccancel@local +# define CDISABLE bl __pthread_disable_asynccancel@local +# elif !defined NOT_IN_libc +# define CENABLE bl __libc_enable_asynccancel@local +# define CDISABLE bl __libc_disable_asynccancel@local +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# if defined HAVE_AS_REL16 && defined PIC +# undef CGOTSETUP +# define CGOTSETUP \ + bcl 20,31,1f; \ + 1: stw 30,44(1); \ + mflr 30; \ + addis 30,30,_GLOBAL_OFFSET_TABLE-1b@ha; \ + addi 30,30,_GLOBAL_OFFSET_TABLE-1b@l +# undef CGOTRESTORE +# define CGOTRESTORE \ + lwz 30,44(1) +# endif +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(2); \ + cmpwi 10,0 +# endif +# else +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined PIC +# define SINGLE_THREAD_P \ + lis 10,__local_multiple_threads@ha; \ + lwz 10,__local_multiple_threads@l(10); \ + cmpwi 10,0 +# else +# ifdef HAVE_ASM_PPC_REL16 +# define SINGLE_THREAD_P \ + mflr 9; \ + bcl 20,31,1f; \ +1:mflr 10; \ + addis 10,10,__local_multiple_threads-1b@ha; \ + lwz 10,__local_multiple_threads-1b@l(10); \ + mtlr 9; \ + cmpwi 10,0 +# else +# define SINGLE_THREAD_P \ + mflr 9; \ + bl _GLOBAL_OFFSET_TABLE_@local-4; \ + mflr 10; \ + mtlr 9; \ + lwz 10,__local_multiple_threads@got(10); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 0000000..724d4cc --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,86 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork +# ifdef SHARED + mflr 9 +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr 10 + addis 10,10,__libc_pthread_functions-1b@ha + lwz 10,__libc_pthread_functions-1b@l(10) + mtlr 9 +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr 10 + mtlr 9 + lwz 10,__libc_pthread_functions@got(10) + lwz 10,0(10) +# endif +# else + .weak pthread_create + lis 10,pthread_create@ha + la 10,pthread_create@l(10) +# endif + + cmpwi 10,0 + bne- .Lhidden_fork + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpwi r3,ENOSYS + bne- .Lsyscall_error + +# endif + +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) + +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + bnslr+ + +.Lsyscall_error: + b __syscall_error@local +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 0000000..0c74676 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + mflr 9; \ + std 9,128+16(1); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ + cmpwi 10,0 +# endif +# else /* !HAVE_TLS_SUPPORT */ +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + .section ".toc","aw"; \ +.LC__local_multiple_threads:; \ + .tc __local_multiple_threads[TC],__local_multiple_threads; \ + .previous; \ + ld 10,.LC__local_multiple_threads@toc(2); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 0000000..b408e31 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,91 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +#ifdef SHARED + .section ".toc","aw" +.LC0: + .tc __libc_pthread_functions[TC],__libc_pthread_functions + .section ".text" + .align 2 +#endif + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED + ld 10,.LC0@toc(2) + ld 10,0(10) + cmpwi 10,0 + bne- HIDDEN_JUMPTARGET(__fork) +# else + .weak pthread_create + lis 10,pthread_create@highest + ori 10,10,pthread_create@higher + sldi 10,10,32 + oris 10,10,pthread_create@h + ori 10,10,pthread_create@l + cmpwi 10,0 + bne- .Lhidden_fork +# endif + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpdi r3,ENOSYS +# ifdef SHARED + bne JUMPTARGET(__syscall_error) +# else + bne- .Lsyscall_error +# endif + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + PSEUDO_RET +#endif + +# ifndef SHARED +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) +.Lsyscall_error: + b JUMPTARGET(__syscall_error) +# endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c new file mode 100644 index 0000000..177256c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c @@ -0,0 +1,70 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ +/* Derived from linuxthreads/ptlongjmp.c & added AltiVec/VMX versioning. */ +#include "pthread.h" +#include +#include +#include +#if defined SHARED +# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __novmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __novmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + + +void __novmx_siglongjmp (sigjmp_buf env, int val) +{ + __novmx__libc_siglongjmp (env, val); +} + +void __novmx_longjmp (jmp_buf env, int val) +{ + __novmx__libc_longjmp (env, val); +} + +# if __WORDSIZE == 64 +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3); +# else +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0); +# endif +# endif /* SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) ) */ + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __vmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __vmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +void __vmx_siglongjmp (sigjmp_buf env, int val) +{ + __vmx__libc_siglongjmp (env, val); +} + +void __vmx_longjmp (jmp_buf env, int val) +{ + __vmx__libc_longjmp (env, val); +} +default_symbol_version (__vmx_longjmp,longjmp,GLIBC_2.3.4); +default_symbol_version (__vmx_siglongjmp,siglongjmp,GLIBC_2.3.4); +#endif /* SHARED */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c new file mode 100644 index 0000000..7c9fe36 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. Generic Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include + +#include + +void +__pthread_sigsuspend (const sigset_t *set) +{ + sigsuspend(set); +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 0000000..61209cf --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1996, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef IS_IN_rtld +# include + +# ifndef SHARED +weak_extern (__pthread_raise) +# endif +#endif + +/* Raise the signal SIG. */ +int +raise (sig) + int sig; +{ +#ifdef IS_IN_rtld + return __kill (__getpid (), sig); +#else + return __libc_maybe_call2 (pthread_raise, (sig), + __kill (__getpid (), sig)); +#endif +} +libc_hidden_def (raise) +weak_alias (raise, gsignal) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 0000000..2dce262 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "fork.h" + + +int +__register_atfork (prepare, parent, child, dso_handle) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); + void *dso_handle; +{ + struct fork_handler *new_prepare = NULL; + struct fork_handler *new_parent = NULL; + struct fork_handler *new_child = NULL; + + if (prepare != NULL) + { + new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare)); + if (new_prepare == NULL) + goto out1; + + new_prepare->handler = prepare; + new_prepare->dso_handle = dso_handle; + } + + if (parent != NULL) + { + new_parent = (struct fork_handler *) malloc (sizeof (*new_parent)); + if (new_parent == NULL) + goto out2; + + new_parent->handler = parent; + new_parent->dso_handle = dso_handle; + } + + if (child != NULL) + { + new_child = (struct fork_handler *) malloc (sizeof (*new_child)); + if (new_child == NULL) + { + free (new_parent); + out2: + free (new_prepare); + out1: + return errno; + } + + new_child->handler = child; + new_child->dso_handle = dso_handle; + } + + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + /* Now that we have all the handlers allocate enqueue them. */ + if (new_prepare != NULL) + list_add_tail (&new_prepare->list, &__fork_block.prepare_list); + if (new_parent != NULL) + list_add_tail (&new_parent->list, &__fork_block.parent_list); + if (new_child != NULL) + list_add_tail (&new_child->list, &__fork_block.child_list); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); + + return 0; +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h new file mode 100644 index 0000000..bee7639 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h @@ -0,0 +1,72 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/s390 version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#if defined __GNUC__ && __GNUC__ <= 2 +/* Compatibility with g++ 2.95.x. */ +#define __SSIZE_T_TYPE __SWORD_TYPE +#else +/* size_t is unsigned long int on s390 -m31. */ +#define __SSIZE_T_TYPE __SLONGWORD_TYPE +#endif + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c new file mode 100644 index 0000000..b7d901c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c @@ -0,0 +1,154 @@ +/* Special .init and .fini section support for S/390. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN1_0\n\ +.LT1_0:\n\ +.LC13:\n\ + .long __pthread_initialize_minimal@PLT-.LT1_0\n\ +.LC14:\n\ + .long __gmon_start__@GOT\n\ +.LC15:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT1_0\n\ +.LTN1_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC15-.LT1_0(13)\n\ + AR 12,13\n\ + L 1,.LC13-.LT1_0(13)\n\ + LA 1,0(1,13)\n\ + BASR 14,1\n\ + L 1,.LC14-.LT1_0(13)\n\ + L 1,0(1,12)\n\ + LTR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN2_0\n\ +.LT2_0:\n\ +.LC17:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT2_0\n\ +.LTN2_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC17-.LT2_0(13)\n\ + AR 12,13\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\ +"); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h new file mode 100644 index 0000000..06f7aed --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# if !defined NOT_IN_libc || defined IS_IN_libpthread + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r12,%r15,48(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r1,1f-0b(%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r12,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r12; \ + lm %r12,%r15,48+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE-0b; \ +2: .long CDISABLE-0b; + +# else /* !libc.so && !libpthread.so */ + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r11,%r15,44(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r12,3f-0b(%r13); \ + l %r1,1f-0b(%r13); \ + la %r12,0(%r12,%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r11,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r11; \ + lm %r11,%r15,44+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE@PLT-0b; \ +2: .long CDISABLE@PLT-0b; \ +3: .long _GLOBAL_OFFSET_TABLE_-0b; + +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +PSEUDO_CANCEL(name, syscall_name, args) \ +ENTRY(name) \ + SINGLE_THREAD_P(%r1) \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lhi %r4,-4095; \ + clr %r2,%r4; \ + jnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# else +# define CENABLE __librt_enable_asynccancel +# define CDISABLE __librt_disable_asynccancel +# endif + +#define STM_0 /* Nothing */ +#define STM_1 st %r2,8(%r15); +#define STM_2 stm %r2,%r3,8(%r15); +#define STM_3 stm %r2,%r4,8(%r15); +#define STM_4 stm %r2,%r5,8(%r15); +#define STM_5 stm %r2,%r5,8(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 l %r2,8+96(%r15); +#define LM_2 lm %r2,%r3,8+96(%r15); +#define LM_3 lm %r2,%r4,8+96(%r15); +#define LM_4 lm %r2,%r5,8+96(%r15); +#define LM_5 lm %r2,%r5,8+96(%r15); + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + ear reg,%a0; \ + icm reg,15,MULTIPLE_THREADS_OFFSET(reg); +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S new file mode 100644 index 0000000..6dfeca8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S @@ -0,0 +1,69 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + basr %r1,0 +0: +#ifdef SHARED + al %r1,4f-0b(%r1) + l %r1,0(%r1) + ltr %r1,%r1 +#else + icm %r1,15,4f-0b(%r1) +#endif + jne 1f + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lhi %r4,-4095 + clr %r2,%r4 + jnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +1: + basr %r1,0 +2: + al %r1,3f-2b(%r1) + br %r1 +3: + .long HIDDEN_JUMPTARGET(__fork)-2b +4: +#ifdef SHARED + .long __libc_pthread_functions-0b +#else + .weak pthread_create + .long pthread_create +#endif +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c new file mode 100644 index 0000000..540443e --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c @@ -0,0 +1,137 @@ +/* Special .init and .fini section support for 64 bit S/390. + Copyright (C) 2001 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ + BRASL 14,__pthread_initialize_minimal@PLT\n\ + LARL 1,__gmon_start__@GOTENT\n\ + LG 1,0(1)\n\ + LTGR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + "); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c new file mode 100644 index 0000000..d57283a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h new file mode 100644 index 0000000..f71ef3f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +L(pseudo_cancel): \ + STM_##args \ + stmg %r13,%r15,104(%r15); \ + lgr %r14,%r15; \ + aghi %r15,-160; \ + stg %r14,0(%r15); \ + brasl %r14,CENABLE; \ + lgr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + lgr %r13,%r2; \ + lgr %r2,%r0; \ + brasl %r14,CDISABLE; \ + lgr %r2,%r13; \ + lmg %r13,%r15,104+160(%r15); \ + j L(pseudo_check); \ +ENTRY(name) \ + SINGLE_THREAD_P \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lghi %r4,-4095; \ + clgr %r2,%r4; \ + jgnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE __librt_enable_asynccancel@PLT +# define CDISABLE __librt_disable_asynccancel@PLT +# endif + +#define STM_0 /* Nothing */ +#define STM_1 stg %r2,16(%r15); +#define STM_2 stmg %r2,%r3,16(%r15); +#define STM_3 stmg %r2,%r4,16(%r15); +#define STM_4 stmg %r2,%r5,16(%r15); +#define STM_5 stmg %r2,%r5,16(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 lg %r2,16+160(%r15); +#define LM_2 lmg %r2,%r3,16+160(%r15); +#define LM_3 lmg %r2,%r4,16+160(%r15); +#define LM_4 lmg %r2,%r5,16+160(%r15); +#define LM_5 lmg %r2,%r5,16+160(%r15); + +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + larl %r1,__local_multiple_threads; \ + icm %r0,15,0(%r1); +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + ear %r1,%a0; \ + sllg %r1,%r1,32; \ + ear %r1,%a1; \ + icm %r1,15,MULTIPLE_THREADS_OFFSET(%r1); +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S new file mode 100644 index 0000000..199f001 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + larl %r1,__libc_pthread_functions + lg %r1,0(%r1) +#else + .weak pthread_create + larl %r1,pthread_create +#endif + ltgr %r1,%r1 + jgne HIDDEN_JUMPTARGET(__fork) + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lghi %r4,-4095 + clgr %r2,%r4 + jgnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 0000000..1cdb98f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for SH. Linuxthread version. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 5\n\ + .global _init\n\ + .type _init,@function\n\ +_init:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L22,r0\n\ + mov.l .L22,r12\n\ + add r0,r12\n\ + mova .L24,r0\n\ + mov.l .L24,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + nop\n\ + mova .L23,r0\n\ + mov.l .L23,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + mov r15,r14\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L22:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +.L23:\n\ + .long __gmon_start__@PLT\n\ +.L24:\n\ + .long __pthread_initialize_minimal@PLT\n\ +1:\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ + END_INIT\n\ + .section .text\n\ + .align 5\n\ + .weak __gmon_start__\n\ + .type __gmon_start__,@function\n\ +__gmon_start__:\n\ + mov.l r14,@-r15\n\ + mov r15,r14\n\ + mov r14,r15\n\ + rts \n\ + mov.l @r15+,r14\n\ + \n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 5\n\ + .global _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L27,r0\n\ + mov.l .L27,r12\n\ + add r0,r12\n\ + mov r15,r14\n\ + ALIGN\n\ + END_FINI\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L27:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ +\n\ + END_FINI\n\ + \n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 0000000..5e2f43c --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +static __inline__ int +is_smp_system (void) +{ + return 0; +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 0000000..03c6fed --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,227 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bt .Lsyscall_error; \ + bra .Lpseudo_end; \ + nop; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + add _IMM16,r15; \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + lds.l @r15+,pr; \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + mov.l r0,@-r15; \ + CDISABLE; \ + mov.l @r15+,r0; \ + lds.l @r15+,pr; \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + .Lsyscall_error: \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + END (sym) + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; mov.l r4,@(0,r15) +# define SAVE_ARGS_2 SAVE_ARGS_1; mov.l r5,@(4,r15) +# define SAVE_ARGS_3 SAVE_ARGS_2; mov.l r6,@(8,r15) +# define SAVE_ARGS_4 SAVE_ARGS_3; mov.l r7,@(12,r15) +# define SAVE_ARGS_5 SAVE_ARGS_4 +# define SAVE_ARGS_6 SAVE_ARGS_5 + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2 LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3 LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4 LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5 LOAD_ARGS_4 +# define LOAD_ARGS_6 LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# define __local_multiple_threads __librt_multiple_threads +# endif + +# if defined IS_IN_librt && defined PIC +# define CENABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 3f; \ + mov r0,r2; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_enable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 + +# define CDISABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 3f; \ + nop; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_disable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 +# else +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + mov r0,r2; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_disable_asynccancel - 0b; \ + 2: +# endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined PIC +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined PIC +# define SINGLE_THREAD_P \ + mov.l 1f,r0; \ + mov.l @r0,r0; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 1: .long __local_multiple_threads; \ + 2: +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P \ + stc gbr,r0; \ + mov.w 0f,r1; \ + sub r1,r0; \ + mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ + bra 1f; \ + tst r0,r0; \ + 0: .word TLS_PRE_TCB_SIZE; \ + 1: + +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOTOFF; \ + 2: +# else +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov.l @r0,r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOT; \ + 2: +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 0000000..e933eef --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,78 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + mov.l .Lgot, r1 + mova .Lgot, r0 + add r0, r1 + mov.l .Lpthread_func, r0 + mov.l @(r0,r1), r0 +#else + mov.l .Lpthread_create, r0 +#endif + tst r0, r0 + bf .Lhidden_fork + + mov.w .L1, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: .word __NR_vfork + .align 2 +#ifdef SHARED +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lpthread_func: + .long __libc_pthread_functions@GOTOFF +#else +.Lpthread_create: + .weak pthread_create + .long pthread_create +#endif + +.Lhidden_fork: + mov.l .L2, r1 + braf r1 + nop +1: + .align 2 +.L2: .long HIDDEN_JUMPTARGET(__fork)-1b + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 0000000..3432125 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +#include +#include +#include +#include + +extern int __syscall_rt_sigtimedwait (const sigset_t *__unbounded, siginfo_t *__unbounded, + const struct timespec *__unbounded, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +static __inline__ int +do_sigwait (const sigset_t *set, int *sig) +{ + int ret; + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (! INTERNAL_SYSCALL_ERROR_P (ret, err)) + { + *sig = ret; + ret = 0; + } + else + ret = INTERNAL_SYSCALL_ERRNO (ret, err); +#else + ret = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set), + NULL, NULL, _NSIG / 8); + if (ret != -1) + { + *sig = ret; + ret = 0; + } + else + ret = errno; +#endif + + return ret; +} + +#ifndef SHARED +weak_extern (__pthread_sigwait) +#endif + +int +__sigwait (set, sig) + const sigset_t *set; + int *sig; +{ +#ifndef NOT_IN_libc + return __libc_maybe_call2 (pthread_sigwait, (set, sig), + do_sigwait (set, sig)); +#else + return do_sigwait (set, sig); +#endif +} +libc_hidden_def (__sigwait) +weak_alias (__sigwait, sigwait) +strong_alias (__sigwait, __libc_sigwait) + +/* Cancellation is handled in __pthread_sigwait. */ +LIBC_CANCEL_HANDLED (); diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 0000000..9ab75e8 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,48 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static __inline__ int +is_smp_system (void) +{ + static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; + char buf[512]; + size_t reslen = sizeof (buf); + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = __open ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + buf[0] = '\0'; + + __close (fd); + } + + return strstr (buf, "SMP") != NULL; +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c new file mode 100644 index 0000000..0d6da82 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 0000000..27ffa66 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/SPARC version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h new file mode 100644 index 0000000..7e42537 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/SPARC version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S32_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h new file mode 100644 index 0000000..b736526 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define ARCH_FORK() \ +({ \ + register long __o0 __asm__ ("o0"); \ + register long __o1 __asm__ ("o1"); \ + register long __g1 __asm__ ("g1") = __NR_fork; \ + __asm__ __volatile__ (__SYSCALL_STRING \ + : "=r" (__g1), "=r" (__o0), "=r" (__o1) \ + : "0" (__g1) \ + : __SYSCALL_CLOBBERS); \ + __o0 == -1 ? __o0 : (__o0 & (__o1 - 1)); \ +}) + +#include_next diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 0000000..dd3f52a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + cmp %g1, 0; \ + bne 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -96, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 0000000..132da67 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ld [%o0 + %o2], %o2 + ld [%o2], %o2 + cmp %o2, 0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + orcc %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + bne HIDDEN_JUMPTARGET(__fork) +#else + bne 1f +#endif + mov __NR_vfork, %g1 + ta 0x10 + bcs __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c new file mode 100644 index 0000000..d57283a --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 0000000..8083429 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + brnz,pn %g1, 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -192, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 0000000..8a6d277 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ldx [%o0 + %o2], %o2 + ldx [%o2], %o0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + or %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + cmp %o0, 0 + bne HIDDEN_JUMPTARGET(__fork) +#else + brnz,pn %o0, 1f +#endif + mov __NR_vfork, %g1 + ta 0x6d + bcs,pn %xcc, __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 0000000..dad273f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "fork.h" + + +void +__unregister_atfork (dso_handle) + void *dso_handle; +{ + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + list_t *runp; + list_t *prevp; + + list_for_each_prev_safe (runp, prevp, &__fork_block.prepare_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.parent_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.child_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); +} diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c new file mode 100644 index 0000000..3a0c2af --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../ia64/pt-sigsuspend.c" diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 0000000..e82e6df --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + /* Save registers that might get destroyed. */ \ + SAVESTK_##args \ + PUSHARGS_##args \ + CENABLE \ + /* Restore registers. */ \ + POPARGS_##args \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + movl $SYS_ify (syscall_name), %eax; \ + syscall; \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, 8(%rsp); \ + CDISABLE \ + movq 8(%rsp), %rax; \ + RESTSTK_##args \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define PUSHARGS_0 /* Nothing. */ +# define PUSHARGS_1 PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2 PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3 PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4 PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5 PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6 PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0 /* Nothing. */ +# define POPARGS_1 POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2 POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3 POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4 POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5 POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6 POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function. */ +# define SAVESTK_0 subq $24, %rsp;cfi_adjust_cfa_offset(24); +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 subq $40, %rsp;cfi_adjust_cfa_offset(40); +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 subq $56, %rsp;cfi_adjust_cfa_offset(56); +# define SAVESTK_6 SAVESTK_5 + +# define RESTSTK_0 addq $24,%rsp;cfi_adjust_cfa_offset(-24); +# define RESTSTK_1 RESTSTK_0 +# define RESTSTK_2 RESTSTK_1 +# define RESTSTK_3 addq $40, %rsp;cfi_adjust_cfa_offset(-40); +# define RESTSTK_4 RESTSTK_3 +# define RESTSTK_5 addq $56, %rsp;cfi_adjust_cfa_offset(-56); +# define RESTSTK_6 RESTSTK_5 + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE call __librt_enable_asynccancel@plt; +# define CDISABLE call __librt_disable_asynccancel@plt; +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 0000000..25d1d3f --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,62 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + cmpq $0, __libc_pthread_functions(%rip) +#else + .weak pthread_create + movq $pthread_create, %rax + testq %rax, %rax +#endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into RDI. We need a register that + is preserved by the syscall and that we're allowed to destroy. */ + popq %rdi + cfi_adjust_cfa_offset(-8) + + /* Stuff the syscall number in RAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + syscall + + /* Push back the return PC. */ + pushq %rdi + cfi_adjust_cfa_offset(8) + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ + + /* Normal return. */ +.Lpseudo_end: + ret + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c b/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c new file mode 100644 index 0000000..b43d4ac --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c @@ -0,0 +1,97 @@ +/* POSIX spinlock implementation. x86-64 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__ + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h b/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h new file mode 100644 index 0000000..23615db --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,224 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +# include + +#ifndef __ASSEMBLER__ +# include /* For offsetof. */ +# include /* For abort(). */ +# include + + +# ifndef PT_EI +# define PT_EI __extern_always_inline +# endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + +/* Prototype for the system call. */ +extern int arch_prctl (int __code, unsigned long __addr); + +/* Initialize the thread-unique value. */ +# define INIT_THREAD_SELF(descr, nr) \ +{ \ + if (arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \ + abort (); \ +} + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P2,%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:(%2),%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym b/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 0000000..aee6be2 --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/libpthread/linuxthreads/sysdeps/x86_64/tls.h b/libpthread/linuxthreads/sysdeps/x86_64/tls.h new file mode 100644 index 0000000..5e7239d --- /dev/null +++ b/libpthread/linuxthreads/sysdeps/x86_64/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/x86-64 version. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + long int _result; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_descr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/linuxthreads_db/.cvsignore b/libpthread/linuxthreads_db/.cvsignore new file mode 100644 index 0000000..e60a14b --- /dev/null +++ b/libpthread/linuxthreads_db/.cvsignore @@ -0,0 +1,5 @@ +.cvsignore +.svn +*.os +Makefile +Makefile.in diff --git a/libpthread/linuxthreads_db/Banner b/libpthread/linuxthreads_db/Banner new file mode 100644 index 0000000..6f4f3f8 --- /dev/null +++ b/libpthread/linuxthreads_db/Banner @@ -0,0 +1 @@ +libthread_db work sponsored by Alpha Processor Inc diff --git a/libpthread/linuxthreads_db/ChangeLog b/libpthread/linuxthreads_db/ChangeLog new file mode 100644 index 0000000..9964b4d --- /dev/null +++ b/libpthread/linuxthreads_db/ChangeLog @@ -0,0 +1,467 @@ +2006-04-25 Bernhard Fischer + + * td_init.c (__td_debug): Only declare when NDEBUG is undefined. + +2006-04-25 Bernhard Fischer + + * thread_dbP.h: Fix Indices typo in comment. + +2005-11-02 Daniel Jacobowitz + + * td_ta_clear_event.c (td_ta_clear_event): Correct arguments to + sizeof. + * td_ta_set_event.c (td_ta_set_event): Likewise. + * td_thr_clear_event.c (td_thr_clear_event): Likewise. + * td_thr_set_event.c (td_thr_set_event): Likewise. + +2005-01-09 Andreas Jaeger + + * td_thr_tlsbase.c (td_thr_tlsbase): Adjust for dtv change. + +2004-05-01 Jakub Jelinek + + * thread_dbP.h (LOG): Use write instead of __libc_write. + +2004-03-13 Jakub Jelinek + + * td_thr_tlsbase.c: Remove dl-tls.h include. Don't use + TLS_TP_OFFSET in the #if, but TLS_TCB_SIZE == 0 ?:. + +2004-03-12 Roland McGrath + + * td_thr_tlsbase.c [TLS_DTV_AT_TP && TLS_TP_OFFSET > 0]: Handle this + case (PowerPC) differently. + +2003-11-25 Roland McGrath + + * td_symbol_list.c (symbol_list_arr) [HAVE_ASM_GLOBAL_DOT_NAME]: + Prepend "." to symbol names for functions. + +2003-08-18 Daniel Jacobowitz + + * td_thr_getfpregs.c (td_thr_getfpregs): Use the main thread if + the descriptor is uninitialized. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + +2003-03-15 Roland McGrath + + * thread_db.h (td_err_e): Add TD_NOTLS and TD_TLSDEFER. + (td_thr_tlsbase): Declare it. + * td_thr_tlsbase.c: New file. + * Makefile (libthread_db-routines): Add it. + * Versions (libthread_db: GLIBC_2.3.3): New set, add td_thr_tlsbase. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use td_thr_tlsbase. + +2003-02-27 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Handle TLS_DTV_AT_TP. + + * td_ta_thr_iter.c (handle_descr) [!defined USE_TLS || !TLS_DTV_AT_TP]: + Conditionalize p_header use on this. + +2003-01-29 Roland McGrath + + * td_ta_new.c (td_ta_new): Cap the `sizeof_descr' value read from the + inferior at `sizeof (struct _pthread_descr_struct)', since we use it + as a length in copies to our own structures. + +2003-01-05 Ulrich Drepper + + * Makefile (libthread_db.so-no-z-defs): Define. + +2002-09-29 Ulrich Drepper + + * td_thr_tsd.c (td_thr_tsd): Read correct entry from pthread_keys + array. + +2002-09-28 Andreas Jaeger + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Fix reference to dtv. + +2002-09-24 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Fetch just the + individual members we need, not the whole structures. + +2002-09-24 Ulrich Drepper + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Change second + parameter to be the address of the link map in the inferior process. + * thread_db.h: Update prototype for td_thr_tls_get_addr. + +2002-08-23 Ulrich Drepper + + * thread_dbP.h: Define LINUXTHREADS_VERSION. + * td_symbol_list.c (symbol_list_arr): Add LINUXTHREADS_VERSION string. + * td_ta_new.c (td_ta_new): After verifying the thread library is + there check version. + * thread_db.h: Add new error TD_VERSION. + +2002-08-21 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): __attribute_used__ -> + __attribute__ ((unused)) for arguments. + +2002-08-07 Ulrich Drepper + + * thread_dbP.h: Define LINUXTHREADS_INITIAL_REPORT_EVENTS. + * td_thr_event_enable.c (td_thr_event_enable): If th->th_unique is + null write to __linuxthreads_initial_report_events. + * td_symbol_list.c (symbol_list_arr): Add + __linuxthreads_initial_report_events. + +2002-07-16 Ulrich Drepper + + * td_thr_clear_event.c: Yet more changes to help with TLS-enabled + libpthread. + * td_thr_event_enable.c: Likewise. + * td_thr_event_getmsg.c: Likewise. + * td_thr_set_event.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + * td_thr_tsd.c: Likewise. + * td_thr_validate.c: Likewise. + +2002-07-15 Ulrich Drepper + + * td_ta_thr_iter.c: Some more changes to enable using TLS-enabled + libpthread. + * td_thr_event_enable.c: Likewise. + * td_thr_getfpregs.c: Likewise. + * td_thr_getgregs.c: Likewise. + +2002-07-14 Ulrich Drepper + + * td_ta_map_id2thr.c: Begin fixing implementation for libpthread with + TLS support. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_thr_iter.c: Likewise. + * td_thr_get_info.c: Likewise. + +2002-07-10 Ulrich Drepper + + * Versions [libthread_db] (GLIBC_2.3): Add td_thr_tls_get_addr. + +2002-06-14 H.J. Lu + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Don't include + "tls.h". Return TD_ERR if USE_TLS is not defined. + +2002-06-12 Ulrich Drepper + + * td_thr_tls_get_addr.c: New file. + * thread_db.h: Add prototype for td_thr_tls_get_addr. + * Makefile (libthread_db-routines): Add td_thr_tls_get_addr. + +2002-03-03 Andreas Jaeger + + * thread_dbP.h: Include for prototypes of __libc_write. + +2002-02-04 Ulrich Drepper + + * thread_dbP.h: Include descr.h instead of internals.h. + * td_ta_event_getmsg.c: Also include . + * td_ta_map_id2thr.c: Likewise. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_thr_iter.c: Likewise. + * td_ta_tsd_iter.c: Likewise. + * td_thr_tsd.c: Likewise. + * td_thr_validate.c: Likewise. + +2001-12-28 Andreas Jaeger + + * td_init.c (td_init): Don't use __FUNCTION__ as literal. + * td_log.c (td_log): Likewise. + * td_ta_delete.c (td_ta_delete): Likewise. + * td_ta_get_nthreads.c (td_ta_get_nthreads): Likewise. + * td_ta_get_ph.c (td_ta_get_ph): Likewise. + * td_ta_map_id2thr.c (td_ta_map_id2thr): Likewise. + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Likewise. + * td_ta_new.c (td_ta_new): Likewise. + * td_ta_clear_event.c (td_ta_clear_event): Likewise. + * td_ta_enable_stats.c (td_ta_enable_stats): Likewise. + * td_ta_event_addr.c (td_ta_event_addr): Likewise. + * td_ta_event_getmsg.c (td_ta_event_getmsg): Likewise. + * td_ta_get_stats.c (td_ta_get_stats): Likewise. + * td_ta_reset_stats.c (td_ta_reset_stats): Likewise. + * td_ta_set_event.c (td_ta_set_event): Likewise. + * td_ta_setconcurrency.c (td_ta_setconcurrency): Likewise. + * td_ta_thr_iter.c (td_ta_thr_iter): Likewise. + * td_ta_tsd_iter.c (td_ta_tsd_iter): Likewise. + * td_thr_clear_event.c (td_thr_clear_event): Likewise. + * td_thr_dbresume.c (td_thr_dbresume): Likewise. + * td_thr_dbsuspend.c (td_thr_dbsuspend): Likewise. + * td_thr_event_enable.c (td_thr_event_enable): Likewise. + * td_thr_event_getmsg.c (td_thr_event_getmsg): Likewise. + * td_thr_get_info.c (td_thr_get_info): Likewise. + * td_thr_getfpregs.c (td_thr_getfpregs): Likewise. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + * td_thr_getxregs.c (td_thr_getxregs): Likewise. + * td_thr_getxregsize.c (td_thr_getxregsize): Likewise. + * td_thr_set_event.c (td_thr_set_event): Likewise. + * td_thr_setfpregs.c (td_thr_setfpregs): Likewise. + * td_thr_setgregs.c (td_thr_setgregs): Likewise. + * td_thr_setprio.c (td_thr_setprio): Likewise. + * td_thr_setsigpending.c (td_thr_setsigpending): Likewise. + * td_thr_setxregs.c (td_thr_setxregs): Likewise. + * td_thr_sigsetmask.c (td_thr_sigsetmask): Likewise. + * td_thr_tsd.c (td_thr_tsd): Likewise. + * td_thr_validate.c (td_thr_validate): Likewise. + +2001-04-12 Ulrich Drepper + + * td_ta_map_id2thr.c: If thread terminated return TD_NOTHR. + * td_thr_validate.c: Likewise. + +2001-04-04 Ulrich Drepper + + * td_thr_getfpregs.c: If p_pid is zero use ps_getpid(). + * td_thr_getgregs.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + +2001-03-20 Ulrich Drepper + + * Makefile (libthread_db-routines): Add td_symbol_list. + * Versions [libthread_db] (GLIBC_2.2.3): Add td_symbol_list. + * td_symbol_list.c: New file. + * thread_db.h: Add prototype for td_symbol_list. + * thread_dbP.h: Define symbol name indices. + Add prototype for td_lookup. + * td_ta_event_addr.c: Use td_lookup instead of directly using + ps_pglobal_lookup to find symbol address. + * td_ta_get_nthreads.c: Likewise. + * td_ta_new.c: Likewise. + +2001-03-18 Ulrich Drepper + + * Makefile: When generating DSO link with libc_nonshared.a. + +2000-08-01 Andreas Jaeger + + * Makefile (distribute): Add missing files. + +2000-04-24 Mark Kettenis + + * td_thr_get_info.c (td_thr_get_info): Set ti_state to + TD_THR_ACTIVE instead of TD_THR_RUN. If the thread is no longer + running but is still joinable, set it to TD_THR_ZOMBIE. Otherwise + set it to TD_THR_UNKNOWN. + +2000-02-25 Andreas Jaeger + + * td_ta_thr_iter.c: Include for prototype declaration. + * td_ta_tsd_iter.c: Likewise. + +2000-01-20 Andreas Jaeger + + * td_thr_getgregs.c (td_thr_getgregs): Fix typo. + +2000-01-19 Ulrich Drepper + + * td_thr_getgregs.c: Correct size parameter of memset call. + +1999-12-02 Ulrich Drepper + + * proc_service.h: Fix typos in last added declaractions. + +1999-12-01 Ulrich Drepper + + * proc_service.h: Add ps_pstop, ps_pcontinue, ps_lstop, and + ps_lcontinue prototypes. + +1999-11-23 Ulrich Drepper + + * Makefile: Correct dependency for shared object. + +1999-11-22 Ulrich Drepper + + * td_ta_map_lwp2thr.c: Add missing brace in comparison. + + * thread_dbP.h (LOG): Only print message if __td_debug is nonzero. + * td_init.c: Add __td_debug. + +1999-11-12 Ulrich Drepper + + * td_ta_thr_iter.c: Start copying list of descriptors from right + position in target process. + + * td_ta_thr_iter.c: Fix loop starting point over all but main and + manager thread. + + * td_ta_thr_iter.c: Read descriptors for main and manager thread + special since after this we can assume that no new threads will be + created anymore (at least in the gdb implementation). + + * Makefile: Define version correctly. + +1999-11-10 Ulrich Drepper + + * td_ta_map_lwp2thr.c: If p_pid field is zero, this is before the + thread library is initialized and we get the PID from the + debugger. + +1999-11-08 Ulrich Drepper + + * td_thr_get_info.c: Make sure ti_lid is never zero. + + * proc_service.h: Add ps_getpid prototype. + +1999-11-03 Ulrich Drepper + + * thread_dbP.h (ta_ok): New function. + * td_ta_new.c: Add new handle to list. + * td_ta_delete.c: Remove handle from list. + * td_ta_clear_event.c: Use ta_ok to check for correct ta parameter. + * td_ta_enable_stats.c: Likewise. + * td_ta_event_addr.c: Likewise. + * td_ta_event_getmsg.c: Likewise. + * td_ta_get_nthreads.c: Likewise. + * td_ta_get_ph.c: Likewise. + * td_ta_get_stats.c: Likewise. + * td_ta_map_id2thr.c: Likewise. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_reset_stats.c: Likewise. + * td_ta_set_event.c: Likewise. + * td_ta_setconcurrency.c: Likewise. + * td_ta_thr_iter.c: Likewise. + + * td_ta_tsd_iter.c: Optimize memory retrieving. + + * Versions: New file. + + * td_thr_get_info.c (td_thr_get_info): Initialize ti_traceme. + +1999-11-02 Ulrich Drepper + + * td_ta_thr_iter.c (td_ta_thr_iter): Optimize a bit. Read all + handles at once. + + * thread_dbP.h (struct th_thragent): Add pthread_handle_num. + * td_ta_new.c: Initialize pthread_handle_num. + * td_ta_event_getmsg.c: If last event was already reported search + for another unreported event. + + * td_thr_get_info.c (td_thr_get_info): Initialize ti_events. + + * Makefile (libthread_db-routines): Add td_ta_set_event, + td_ta_event_getmsg, and td_ta_clear_event. + * td_ta_clear_event.c: New file. + * td_ta_event_getmsg.c: New file. + * td_ta_new.c: Get address of __pthread_last_event in target. + * td_ta_set_event.c: Don't overwrite old mask, set additional bits. + * td_thr_set_event.c: Likewise. + * td_thr_clear_event.c: Implement. + * thread_db.h: Declare td_ta_clear_event and td_ta_event_getmsg. + * thread_dbP.h (struct td_thragent): Add pthread_last_event. + + * td_ta_new.c: Don't test for __pthread_threads_debug. Get address + of __pthread_threads_events and fail if this is not possible. + * td_ta_event_addr.c: Implement. + * td_thr_event_enable.c: Implement. + * td_thr_event_getmsg.c: Implement. + * td_thr_set_event.c: Implement. + * td_ta_set_event.c: New file. + * thread_db.h (td_eventbuf_t): Define. + Declare td_ta_set_event. + * thread_dbP.h (struct td_thragent): Add pthread_threads_eventsp. + + * td_thr_getfpregs.c: For terminated threads return empty structure. + * td_thr_getgregs.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + +1999-11-01 Ulrich Drepper + + * thread_db.h: Shuffle types around to make things work for gdb. + * thread_dbP.h: Include proc_service.h before thread_db.h. + + * thread_db.h: It's TD_NOLIBTHREAD, not TD_LIBTHREAD. + * td_ta_new.c: Likewise. + +1999-10-14 Ulrich Drepper + + * td_ta_new.c: p_startfct does not exist anymore. + + * td_thr_get_info.c: Always initialize start function. + + * td_ta_thr_iter.c: Don't return threads which exited (but are not + joined). + + * td_thr_validate.c: Don't skip manager thread. + +1999-10-13 Ulrich Drepper + + * td_ta_thr_iter.c: Use size of descriptor from *TA. + Don't return manager thread before it's actually running. + Actually use state parameter to distingusih at least a few states. + + * td_thr_get_info.c: Handle manager thread special. Fill in ti_lid, + ti_state, and ti_startfunc fields. + +1999-10-12 Andreas Jaeger + + * thread_dbP.h: Include for strlen declaration. Remove + __libc_write prototype since this is already declared in + linuxthreads/internals.h. + +1999-10-11 Ulrich Drepper + + * thread_db.h: Fix comment for ti_type. + + * td_thr_get_info.c: Initialize ti_type field. + + * td_ta_thr_iter.c: Also report the manager thread. + +1999-10-08 Andreas Jaeger + + * thread_db.h: Fix typos in comments. + + * td_ta_get_nthreads.c (td_ta_get_nthreads): Don't hardcode + libpthread library name, get it from instead. + * td_ta_new.c (td_ta_new): Likewise. + +1999-10-08 Ulrich Drepper + + * shlib-versions: New file. + +1999-10-07 Ulrich Drepper + + * Makefile: New file. + * proc_service.h: New file. + * td_init.c: New file. + * td_log.c: New file. + * td_ta_delete.c: New file. + * td_ta_enable_stats.c: New file. + * td_ta_event_addr.c: New file. + * td_ta_get_nthreads.c: New file. + * td_ta_get_ph.c: New file. + * td_ta_get_stats.c: New file. + * td_ta_map_id2thr.c: New file. + * td_ta_map_lwp2thr.c: New file. + * td_ta_new.c: New file. + * td_ta_reset_stats.c: New file. + * td_ta_setconcurrency.c: New file. + * td_ta_thr_iter.c: New file. + * td_ta_tsd_iter.c: New file. + * td_thr_clear_event.c: New file. + * td_thr_dbresume.c: New file. + * td_thr_dbsuspend.c: New file. + * td_thr_event_enable.c: New file. + * td_thr_event_getmsg.c: New file. + * td_thr_get_info.c: New file. + * td_thr_getfpregs.c: New file. + * td_thr_getgregs.c: New file. + * td_thr_getxregs.c: New file. + * td_thr_getxregsize.c: New file. + * td_thr_set_event.c: New file. + * td_thr_setfpregs.c: New file. + * td_thr_setgregs.c: New file. + * td_thr_setprio.c: New file. + * td_thr_setsigpending.c: New file. + * td_thr_setxregs.c: New file. + * td_thr_sigsetmask.c: New file. + * td_thr_tsd.c: New file. + * td_thr_validate.c: New file. + * thread_db.h: New file. + * thread_dbP.h: New file. diff --git a/libpthread/linuxthreads_db/Makefile b/libpthread/linuxthreads_db/Makefile new file mode 100644 index 0000000..f910021 --- /dev/null +++ b/libpthread/linuxthreads_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/linuxthreads_db/Makefile.in b/libpthread/linuxthreads_db/Makefile.in new file mode 100644 index 0000000..a57cb84 --- /dev/null +++ b/libpthread/linuxthreads_db/Makefile.in @@ -0,0 +1,76 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# Get the thread include dependencies and shared object name +CFLAGS-linuxthreads_db := -DNOT_IN_libc -DLIBPTHREAD_SO="\"libpthread.so.$(MAJOR_VERSION)\"" + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols) +ifeq ($(DOSTRIP),y) +LDFLAGS-libthread_db.so += -Wl,-s +endif + +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/linuxthreads_db +libthread_db_OUT := $(top_builddir)libpthread/linuxthreads_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/*.c) + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.os) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so + +#ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) +#else +#$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db.oS | $(libc.depend) +# $(call linkm.so,$(libthread_db_FULL_NAME),1) +#endif + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libthread_db_OUT)/libthread_db.oS: $(libthread_db_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +include/thread_db.h: + $(do_ln) ../$(PTDIR)_db/$(@F) $(top_builddir)$@ + +linuxthreads_db_headers := include/thread_db.h +$(linuxthreads_db_headers): $(wildcard $(addprefix include/config/linuxthreads/,old.h new.h)) +headers-$(PTHREADS_DEBUG_SUPPORT) += $(linuxthreads_db_headers) + +objclean-y += libthread_db_clean +headers_clean-y += linuxthreads_db_headers_clean + +linuxthreads_db_headers_clean: + $(do_rm) $(top_builddir)include/thread_db.h + +libthread_db_clean: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o os oS a) diff --git a/libpthread/linuxthreads_db/Makefile.old b/libpthread/linuxthreads_db/Makefile.old new file mode 100644 index 0000000..53e46f7 --- /dev/null +++ b/libpthread/linuxthreads_db/Makefile.old @@ -0,0 +1,57 @@ +# Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C 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. + +# The GNU C 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 the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# Makefile for linuxthreads debug library subdirectory of GNU C Library. + +subdir := linuxthreads_db + +linuxthreads_db-version = 1.0 + +extra-libs = libthread_db +extra-libs-others := $(extra-libs) + +headers = thread_db.h +libthread_db-routines = td_init td_log td_ta_delete td_ta_get_nthreads \ + td_ta_get_ph td_ta_map_id2thr td_ta_map_lwp2thr \ + td_ta_new td_ta_thr_iter td_ta_tsd_iter \ + td_thr_get_info td_thr_getfpregs td_thr_getgregs \ + td_thr_getxregs td_thr_getxregsize td_thr_setfpregs \ + td_thr_setgregs td_thr_setprio td_thr_setsigpending \ + td_thr_setxregs td_thr_sigsetmask td_thr_tsd \ + td_thr_validate td_thr_dbsuspend td_thr_dbresume \ + td_ta_setconcurrency td_ta_enable_stats \ + td_ta_reset_stats td_ta_get_stats td_ta_event_addr \ + td_thr_event_enable td_thr_set_event \ + td_thr_clear_event td_thr_event_getmsg \ + td_ta_set_event td_ta_event_getmsg \ + td_ta_clear_event td_symbol_list \ + td_thr_tlsbase td_thr_tls_get_addr + +libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes)) + +# The ps_* callback functions are not defined. +libthread_db.so-no-z-defs = yes + +distribute = thread_dbP.h shlib-versions proc_service.h +include ../Rules + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +$(objpfx)libthread_db.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a diff --git a/libpthread/linuxthreads_db/Versions b/libpthread/linuxthreads_db/Versions new file mode 100644 index 0000000..063493c --- /dev/null +++ b/libpthread/linuxthreads_db/Versions @@ -0,0 +1,24 @@ +libthread_db { + GLIBC_2.1.3 { + # t* + td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; + td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; + td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; + td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; + td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; + td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; + td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; + td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; + td_thr_tsd; td_thr_validate; + } + GLIBC_2.2.3 { + td_symbol_list; + } + GLIBC_2.3 { + td_thr_tls_get_addr; + } + GLIBC_2.3.3 { + td_thr_tlsbase; + } +} diff --git a/libpthread/linuxthreads_db/proc_service.h b/libpthread/linuxthreads_db/proc_service.h new file mode 100644 index 0000000..74136c0 --- /dev/null +++ b/libpthread/linuxthreads_db/proc_service.h @@ -0,0 +1,70 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include + +typedef enum +{ + PS_OK, /* generic "call succeeded" */ + PS_ERR, /* generic. */ + PS_BADPID, /* bad process handle */ + PS_BADLID, /* bad lwp identifier */ + PS_BADADDR, /* bad address */ + PS_NOSYM, /* p_lookup() could not find given symbol */ + PS_NOFREGS + /* + * FPU register set not available for given + * lwp + */ +} ps_err_e; + + +struct ps_prochandle; /* user defined. */ + + +extern ps_err_e ps_pdread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); + +extern ps_err_e ps_pglobal_lookup(struct ps_prochandle *, + const char *object_name, const char *sym_name, psaddr_t *sym_addr); + + +extern ps_err_e ps_lgetregs(struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs(struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs(struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs(struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +extern pid_t ps_getpid (struct ps_prochandle *); + + +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/libpthread/linuxthreads_db/shlib-versions b/libpthread/linuxthreads_db/shlib-versions new file mode 100644 index 0000000..592f7fa --- /dev/null +++ b/libpthread/linuxthreads_db/shlib-versions @@ -0,0 +1,2 @@ +# The thread debug library +.*-.*-linux.* libthread_db=1 diff --git a/libpthread/linuxthreads_db/td_init.c b/libpthread/linuxthreads_db/td_init.c new file mode 100644 index 0000000..66e9849 --- /dev/null +++ b/libpthread/linuxthreads_db/td_init.c @@ -0,0 +1,34 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +#ifndef NDEBUG +int __td_debug; +#endif + + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_log.c b/libpthread/linuxthreads_db/td_log.c new file mode 100644 index 0000000..025273a --- /dev/null +++ b/libpthread/linuxthreads_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_symbol_list.c b/libpthread/linuxthreads_db/td_symbol_list.c new file mode 100644 index 0000000..599c045 --- /dev/null +++ b/libpthread/linuxthreads_db/td_symbol_list.c @@ -0,0 +1,61 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ + [PTHREAD_THREADS_EVENTS] = "__pthread_threads_events", + [PTHREAD_LAST_EVENT] = "__pthread_last_event", + [PTHREAD_HANDLES_NUM] = "__pthread_handles_num", + [PTHREAD_HANDLES] = "__pthread_handles", + [PTHREAD_KEYS] = "pthread_keys", + [LINUXTHREADS_PTHREAD_THREADS_MAX] = "__linuxthreads_pthread_threads_max", + [LINUXTHREADS_PTHREAD_KEYS_MAX] = "__linuxthreads_pthread_keys_max", + [LINUXTHREADS_PTHREAD_SIZEOF_DESCR] = "__linuxthreads_pthread_sizeof_descr", + [LINUXTHREADS_CREATE_EVENT] = DOT "__linuxthreads_create_event", + [LINUXTHREADS_DEATH_EVENT] = DOT "__linuxthreads_death_event", + [LINUXTHREADS_REAP_EVENT] = DOT "__linuxthreads_reap_event", + [LINUXTHREADS_INITIAL_REPORT_EVENTS] = "__linuxthreads_initial_report_events", + [LINUXTHREADS_VERSION] = "__linuxthreads_version", + [NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +int +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + assert (idx >= 0 && idx < NUM_MESSAGES); + return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr); +} diff --git a/libpthread/linuxthreads_db/td_ta_clear_event.c b/libpthread/linuxthreads_db/td_ta_clear_event.c new file mode 100644 index 0000000..cbb7ddc --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_clear_event.c @@ -0,0 +1,53 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_delete.c b/libpthread/linuxthreads_db/td_ta_delete.c new file mode 100644 index 0000000..0e6ec17 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_delete.c @@ -0,0 +1,58 @@ +/* Detach to target process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. */ + if (ta == NULL || __td_agent_list == NULL) + return TD_BADTA; + + /* Remove the handle from the list. */ + if (ta == __td_agent_list->ta) + /* It's the first element of the list. */ + __td_agent_list = __td_agent_list->next; + else + { + /* We have to search for it. */ + struct agent_list *runp = __td_agent_list; + + while (runp->next != NULL && runp->next->ta != ta) + runp = runp->next; + + if (runp->next == NULL) + /* It's not a valid decriptor since it is not in the list. */ + return TD_BADTA; + + runp->next = runp->next->next; + } + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_enable_stats.c b/libpthread/linuxthreads_db/td_ta_enable_stats.c new file mode 100644 index 0000000..1d4c34a --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_event_addr.c b/libpthread/linuxthreads_db/td_ta_event_addr.c new file mode 100644 index 0000000..8bce35a --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_event_addr.c @@ -0,0 +1,73 @@ +/* Get event address. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) +{ + td_err_e res = TD_NOEVENT; + int idx = -1; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + idx = LINUXTHREADS_CREATE_EVENT; + break; + + case TD_DEATH: + idx = LINUXTHREADS_DEATH_EVENT; + break; + + case TD_REAP: + idx = LINUXTHREADS_REAP_EVENT; + break; + + default: + /* Event cannot be handled. */ + break; + } + + /* Now get the address. */ + if (idx != -1) + { + psaddr_t taddr; + + if (td_lookup (ta->ph, idx, &taddr) == PS_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + + res = TD_OK; + } + else + res = TD_ERR; + } + + return res; +} diff --git a/libpthread/linuxthreads_db/td_ta_event_getmsg.c b/libpthread/linuxthreads_db/td_ta_event_getmsg.c new file mode 100644 index 0000000..c3a4492 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_event_getmsg.c @@ -0,0 +1,129 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg) +{ + /* XXX I cannot think of another way but using a static variable. */ + static td_thrhandle_t th; + td_eventbuf_t event; + psaddr_t addr; + + LOG ("td_ta_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + if (ps_pdread (ta->ph, ta->pthread_last_event, + &addr, sizeof (void *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* If the pointer is NULL no event occurred. */ + if (addr == 0) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + { + /* Oh well, this means the last event was already read. So + we have to look for any other event. */ + struct pthread_handle_struct handles[ta->pthread_threads_max]; + int num; + int i; + + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now read the handles. */ + if (ps_pdread (ta->ph, ta->handles, handles, + ta->pthread_threads_max * sizeof (handles[0])) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + for (i = 0; i < ta->pthread_threads_max && num > 0; ++i) + { + if (handles[i].h_descr == NULL) + /* No entry here. */ + continue; + + /* First count this active thread. */ + --num; + + if (handles[i].h_descr == addr) + /* We already handled this. */ + continue; + + /* Read the event data for this thread. */ + if (ps_pdread (ta->ph, + ((char *) handles[i].h_descr + + offsetof (struct _pthread_descr_struct, + p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; + + if (event.eventnum != TD_EVENT_NONE) + { + /* We found a thread with an unreported event. */ + addr = handles[i].h_descr; + break; + } + } + + /* If we haven't found any other event signal this to the user. */ + if (event.eventnum == TD_EVENT_NONE) + return TD_NOMSG; + } + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = &th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_get_nthreads.c b/libpthread/linuxthreads_db/td_ta_get_nthreads.c new file mode 100644 index 0000000..839b56b --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta, int *np) +{ + psaddr_t addr; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable `__pthread_handles_num'. */ + if (td_lookup (ta->ph, PTHREAD_HANDLES_NUM, &addr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_get_ph.c b/libpthread/linuxthreads_db/td_ta_get_ph.c new file mode 100644 index 0000000..23d3285 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_get_stats.c b/libpthread/linuxthreads_db/td_ta_get_stats.c new file mode 100644 index 0000000..6bf2f53 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_map_id2thr.c b/libpthread/linuxthreads_db/td_ta_map_id2thr.c new file mode 100644 index 0000000..ddeb2d3 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_map_id2thr.c @@ -0,0 +1,79 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + struct pthread_handle_struct phc; + struct _pthread_descr_struct pds; + int pthread_threads_max; + + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Make the following expression a bit smaller. */ + pthread_threads_max = ta->pthread_threads_max; + + /* We can compute the entry in the handle array we want. */ + if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Test whether this entry is in use. */ + if (phc.h_descr == NULL) + { + if (pt % pthread_threads_max == 0) + { + /* The initial thread always exists but the thread library + might not yet be initialized. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_BADTH; + } + + /* Next test: get the descriptor to see whether this is not an old + thread handle. */ + if (ps_pdread (ta->ph, phc.h_descr, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_tid != pt) + return TD_BADTH; + + if (pds.p_terminated != 0) + return TD_NOTHR; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc.h_descr; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c b/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c new file mode 100644 index 0000000..dd2fcbf --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c @@ -0,0 +1,91 @@ +/* Which thread is running on an lwp? + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + int pthread_threads_max = ta->pthread_threads_max; + size_t sizeof_descr = ta->sizeof_descr; + struct pthread_handle_struct phc[pthread_threads_max]; + size_t cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * pthread_threads_max) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Get the entries one after the other and find out whether the ID + matches. */ + for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { + struct _pthread_descr_struct pds; + +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if ((pds.p_pid ?: ps_getpid (ta->ph)) == lwpid) + { + /* Found it. Now fill in the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc[cnt].h_descr; + + return TD_OK; + } + } + else if (cnt == 0) + { + /* The initial thread always exists. But it might not yet be + initialized. Construct a value. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_NOLWP; +} diff --git a/libpthread/linuxthreads_db/td_ta_new.c b/libpthread/linuxthreads_db/td_ta_new.c new file mode 100644 index 0000000..2b0b68b --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_new.c @@ -0,0 +1,149 @@ +/* Attach to target process. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +struct agent_list *__td_agent_list; + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t addr; + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + struct agent_list *elemp; + + LOG ("td_ta_new"); + + /* Get the global event mask. This is one of the variables which + are new in the thread library to enable debugging. If it is + not available we cannot debug. */ + if (td_lookup (ps, PTHREAD_THREADS_EVENTS, &addr) != PS_OK) + return TD_NOLIBTHREAD; + + /* Check whether the versions match. */ + if (td_lookup (ps, LINUXTHREADS_VERSION, &versaddr) != PS_OK) + return TD_VERSION; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + versbuf[sizeof (versbuf) - 1] = '\0'; + if (strcmp (versbuf, VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Remember the address. */ + (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr; + + /* Get the pointer to the variable pointing to the thread descriptor + with the last event. */ + if (td_lookup (ps, PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event) != PS_OK) + { + free_return: + free (*ta); + return TD_ERR; + } + + /* Get the pointer to the variable containing the number of active + threads. */ + if (td_lookup (ps, PTHREAD_HANDLES_NUM, &(*ta)->pthread_handles_num) + != PS_OK) + goto free_return; + + /* See whether the library contains the necessary symbols. */ + if (td_lookup (ps, PTHREAD_HANDLES, &addr) != PS_OK) + goto free_return; + + (*ta)->handles = (struct pthread_handle_struct *) addr; + + + if (td_lookup (ps, PTHREAD_KEYS, &addr) != PS_OK) + goto free_return; + + /* Cast to the right type. */ + (*ta)->keys = (struct pthread_key_struct *) addr; + + /* Find out about the maximum number of threads. Old implementations + don't provide this information. In this case we assume that the + debug library is compiled with the same values. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_THREADS_MAX, &addr) != PS_OK) + (*ta)->pthread_threads_max = PTHREAD_THREADS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_threads_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* Similar for the maximum number of thread local data keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_KEYS_MAX, &addr) != PS_OK) + (*ta)->pthread_keys_max = PTHREAD_KEYS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* And for the size of the second level arrays for the keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + else + { + if (ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK) + goto free_return; + /* Don't let bogons in the inferior make us mess ourselves. */ + if ((*ta)->sizeof_descr > sizeof (struct _pthread_descr_struct)) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + } + + /* Now add the new agent descriptor to the list. */ + elemp = (struct agent_list *) malloc (sizeof (struct agent_list)); + if (elemp == NULL) + { + /* Argh, now that everything else worked... */ + free (*ta); + return TD_MALLOC; + } + + /* We don't care for thread-safety here. */ + elemp->ta = *ta; + elemp->next = __td_agent_list; + __td_agent_list = elemp; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_reset_stats.c b/libpthread/linuxthreads_db/td_ta_reset_stats.c new file mode 100644 index 0000000..b3ddbd0 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_set_event.c b/libpthread/linuxthreads_db/td_ta_set_event.c new file mode 100644 index 0000000..6edb38e --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_set_event.c @@ -0,0 +1,53 @@ +/* Globally enable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_ta_setconcurrency.c b/libpthread/linuxthreads_db/td_ta_setconcurrency.c new file mode 100644 index 0000000..408e763 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads_db/td_ta_thr_iter.c b/libpthread/linuxthreads_db/td_ta_thr_iter.c new file mode 100644 index 0000000..9ab04e1 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_thr_iter.c @@ -0,0 +1,176 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include + +static int +handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + size_t cnt, pthread_descr descr) +{ + struct _pthread_descr_struct pds; + size_t sizeof_descr = ta->sizeof_descr; + td_thrhandle_t th; + + if (descr == NULL) + { + /* No descriptor (yet). */ + if (cnt == 0) + { + /* This is the main thread. Create a fake descriptor. */ + memset (&pds, '\0', sizeof (pds)); + + /* Empty thread descriptor the thread library would create. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + pds.p_header.data.self = &pds; +#endif + pds.p_nextlive = pds.p_prevlive = &pds; + pds.p_tid = PTHREAD_THREADS_MAX; + /* The init code also sets up p_lock, p_errnop, p_herrnop, and + p_userstack but this should not be necessary here. */ + + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = NULL; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; + } + else if (cnt == 1) + /* The manager is not yet started. No big deal. */ + return TD_OK; + else + /* For every other thread this should not happen. */ + return TD_ERR; + } + + if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* The manager thread must be handled special. The descriptor + exists but the thread only gets created when the first + `pthread_create' call is issued. A clear indication that this + happened is when the p_pid field is non-zero. */ + if (cnt == 1 && pds.p_pid == 0) + return TD_OK; + + /* Now test whether this thread matches the specified + conditions. */ + + /* Only if the priority level is as high or higher. */ + if (pds.p_priority < ti_pri) + return TD_OK; + + /* Test the state. + XXX This is incomplete. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + /* XXX For now we ignore threads which are not running anymore. + The reason is that gdb tries to get the registers and fails. + In future we should have a special mode of the thread library + in which we keep the process around until the actual join + operation happened. */ + if (pds.p_exited != 0) + return TD_OK; + + /* Yep, it matches. Call the callback function. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = descr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + int pthread_threads_max; + struct pthread_handle_struct *phc; + td_err_e result = TD_OK; + int cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_threads_max = ta->pthread_threads_max; + phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) + * pthread_threads_max); + + /* First read only the main thread and manager thread information. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * 2) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now handle these descriptors. */ + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0, + phc[0].h_descr); + if (result != TD_OK) + return result; + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1, + phc[1].h_descr); + if (result != TD_OK) + return result; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles + 2, &phc[2], + (sizeof (struct pthread_handle_struct) + * (pthread_threads_max - 2))) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Now get all descriptors, one after the other. */ + for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt, + phc[cnt].h_descr); + if (result != TD_OK) + break; + } + + return result; +} diff --git a/libpthread/linuxthreads_db/td_ta_tsd_iter.c b/libpthread/linuxthreads_db/td_ta_tsd_iter.c new file mode 100644 index 0000000..2eb41f6 --- /dev/null +++ b/libpthread/linuxthreads_db/td_ta_tsd_iter.c @@ -0,0 +1,56 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback, + void *cbdata_p) +{ + struct pthread_key_struct *keys; + int pthread_keys_max; + int cnt; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_keys_max = ta->pthread_keys_max; + keys = (struct pthread_key_struct *) alloca (sizeof (keys[0]) + * pthread_keys_max); + + /* Read all the information about the keys. */ + if (ps_pdread (ta->ph, ta->keys, keys, + sizeof (keys[0]) * pthread_keys_max) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_keys_max; ++cnt) + if (keys[cnt].in_use + /* Return with an error if the callback returns a nonzero value. */ + && callback (cnt, keys[cnt].destr, cbdata_p) != 0) + return TD_DBERR; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_clear_event.c b/libpthread/linuxthreads_db/td_thr_clear_event.c new file mode 100644 index 0000000..147d180 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_clear_event.c @@ -0,0 +1,62 @@ +/* Disable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_clear_event"); + + /* If the thread descriptor has not yet been constructed do not do + anything. */ + if (th->th_unique == NULL) + return TD_OK; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_dbresume.c b/libpthread/linuxthreads_db/td_thr_dbresume.c new file mode 100644 index 0000000..7b7f6ee --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads_db/td_thr_dbsuspend.c b/libpthread/linuxthreads_db/td_thr_dbsuspend.c new file mode 100644 index 0000000..ef66802 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/libpthread/linuxthreads_db/td_thr_event_enable.c b/libpthread/linuxthreads_db/td_thr_event_enable.c new file mode 100644 index 0000000..407f3fc --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_event_enable.c @@ -0,0 +1,57 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + if (th->th_unique == NULL) + { + psaddr_t addr; + + if (td_lookup (th->th_ta_p->ph, LINUXTHREADS_INITIAL_REPORT_EVENTS, + &addr) != PS_OK) + /* Cannot read the symbol. This should not happen. */ + return TD_ERR; + + if (ps_pdwrite (th->th_ta_p->ph, addr, &onoff, sizeof (int)) != PS_OK) + return TD_ERR; + + return TD_OK; + } + + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_report_events)), + &onoff, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_event_getmsg.c b/libpthread/linuxthreads_db/td_thr_event_getmsg.c new file mode 100644 index 0000000..bf4ddd4 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_event_getmsg.c @@ -0,0 +1,65 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_eventbuf_t event; + + LOG ("td_thr_event_getmsg"); + + /* If the thread descriptor has not yet been created there cannot be + any event. */ + if (th->th_unique == NULL) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_get_info.c b/libpthread/linuxthreads_db/td_thr_get_info.c new file mode 100644 index 0000000..4666bda --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_get_info.c @@ -0,0 +1,83 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_get_info"); + + /* Handle the case when the thread library is not yet initialized. */ + if (th->th_unique == NULL) + { + memset (&pds, '\0', sizeof (pds)); + pds.p_tid = PTHREAD_THREADS_MAX; + } + else + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + /* We have to handle the manager thread special since the thread + descriptor in older versions is not fully initialized. */ + if (pds.p_nr == 1) + { + infop->ti_tid = th->th_ta_p->pthread_threads_max * 2 + 1; + infop->ti_type = TD_THR_SYSTEM; + infop->ti_state = TD_THR_ACTIVE; + } + else + { + infop->ti_tid = pds.p_tid; + infop->ti_tls = (char *) pds.p_specific; + infop->ti_pri = pds.p_priority; + infop->ti_type = TD_THR_USER; + + if (! pds.p_terminated) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if (! pds.p_detached) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + } + + /* Initialization which are the same in both cases. */ + infop->ti_lid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + infop->ti_ta_p = th->th_ta_p; + infop->ti_startfunc = pds.p_start_args.start_routine; + memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask, + sizeof (td_thr_events_t)); + infop->ti_traceme = pds.p_report_events != 0; + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_getfpregs.c b/libpthread/linuxthreads_db/td_thr_getfpregs.c new file mode 100644 index 0000000..31c55c8 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_getfpregs.c @@ -0,0 +1,58 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getfpregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_getgregs.c b/libpthread/linuxthreads_db/td_thr_getgregs.c new file mode 100644 index 0000000..a9ec6a3 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_getgregs.c @@ -0,0 +1,58 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getgregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (gregs, '\0', sizeof (prgregset_t)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_getxregs.c b/libpthread/linuxthreads_db/td_thr_getxregs.c new file mode 100644 index 0000000..39cd73c --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads_db/td_thr_getxregsize.c b/libpthread/linuxthreads_db/td_thr_getxregsize.c new file mode 100644 index 0000000..5d8ac28 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads_db/td_thr_set_event.c b/libpthread/linuxthreads_db/td_thr_set_event.c new file mode 100644 index 0000000..1e1def5 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_set_event.c @@ -0,0 +1,62 @@ +/* Enable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_set_event"); + + /* What shall we do if no thread descriptor exists but the user + wants to set an event? */ + if (th->th_unique == NULL) + return TD_NOTALLOC; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_setfpregs.c b/libpthread/linuxthreads_db/td_thr_setfpregs.c new file mode 100644 index 0000000..e4d9ec6 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_setfpregs.c @@ -0,0 +1,47 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetfpregs (th->th_ta_p->ph, pid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_setgregs.c b/libpthread/linuxthreads_db/td_thr_setgregs.c new file mode 100644 index 0000000..8c021a4 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_setgregs.c @@ -0,0 +1,47 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_setprio.c b/libpthread/linuxthreads_db/td_thr_setprio.c new file mode 100644 index 0000000..98d202d --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_setsigpending.c b/libpthread/linuxthreads_db/td_thr_setsigpending.c new file mode 100644 index 0000000..98e3014 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_setxregs.c b/libpthread/linuxthreads_db/td_thr_setxregs.c new file mode 100644 index 0000000..da77ab3 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/linuxthreads_db/td_thr_sigsetmask.c b/libpthread/linuxthreads_db/td_thr_sigsetmask.c new file mode 100644 index 0000000..8b0eb81 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/libpthread/linuxthreads_db/td_thr_tls_get_addr.c b/libpthread/linuxthreads_db/td_thr_tls_get_addr.c new file mode 100644 index 0000000..c900cac --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_tls_get_addr.c @@ -0,0 +1,45 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th __attribute__ ((unused)), + void *map_address __attribute__ ((unused)), + size_t offset __attribute__ ((unused)), + void **address __attribute__ ((unused))) +{ +#if USE_TLS + /* Read the module ID from the link_map. */ + size_t modid; + if (ps_pdread (th->th_ta_p->ph, + &((struct link_map *) map_address)->l_tls_modid, + &modid, sizeof modid) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + td_err_e result = td_thr_tlsbase (th, modid, address); + if (result == TD_OK) + *address += offset; + return result; +#else + return TD_ERR; +#endif +} diff --git a/libpthread/linuxthreads_db/td_thr_tlsbase.c b/libpthread/linuxthreads_db/td_thr_tlsbase.c new file mode 100644 index 0000000..5a7e31b --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_tlsbase.c @@ -0,0 +1,71 @@ +/* Locate TLS data for a thread. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + +td_err_e +td_thr_tlsbase (const td_thrhandle_t *th, + unsigned long int modid, + psaddr_t *base) +{ + if (modid < 1) + return TD_NOTLS; + +#if USE_TLS + union dtv pdtv, *dtvp; + + LOG ("td_thr_tlsbase"); + + psaddr_t dtvpp = th->th_unique; +#if TLS_TCB_AT_TP + dtvpp += offsetof (struct _pthread_descr_struct, p_header.data.dtvp); +#elif TLS_DTV_AT_TP +/* Special case hack. If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB + containing the DTV at the TP, but actually the TCB lies behind the TP, + i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE. */ + dtvpp += TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv) + - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0); +#else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined." +#endif + + /* Get the DTV pointer from the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, dtvpp, &dtvp, sizeof dtvp) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Get the corresponding entry in the DTV. */ + if (ps_pdread (th->th_ta_p->ph, dtvp + modid, + &pdtv, sizeof (union dtv)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if (pdtv.pointer.val == TLS_DTV_UNALLOCATED) + return TD_TLSDEFER; + + *base = (char *) pdtv.pointer.val; + + return TD_OK; +#else + return TD_ERR; +#endif +} diff --git a/libpthread/linuxthreads_db/td_thr_tsd.c b/libpthread/linuxthreads_db/td_thr_tsd.c new file mode 100644 index 0000000..978dc5e --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_tsd.c @@ -0,0 +1,82 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + struct _pthread_descr_struct pds; + struct pthread_key_struct *keys = th->th_ta_p->keys; + struct pthread_key_struct key; + int pthread_keys_max = th->th_ta_p->pthread_keys_max; + int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size; + unsigned int idx1st; + unsigned int idx2nd; + void *p; + + LOG ("td_thr_tsd"); + + /* If there is no thread descriptor there cannot be any thread + specific data. */ + if (th->th_unique == NULL) + return TD_BADKEY; + + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check correct value of key. */ + if (tk >= pthread_keys_max) + return TD_BADKEY; + + /* Get the key entry. */ + if (ps_pdread (th->th_ta_p->ph, &keys[tk], &key, + sizeof (struct pthread_key_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fail if this key is not at all used. */ + if (! key.in_use) + return TD_BADKEY; + + /* Compute the indeces. */ + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Check the pointer to the second level array. */ + if (pds.p_specific[idx1st] == NULL) + return TD_NOTSD; + + /* Now get the real key. + XXX I don't know whether it's correct but there is currently no + easy way to determine whether a key was never set or the value + is NULL. We return an error whenever the value is NULL. */ + if (ps_pdread (th->th_ta_p->ph, &pds.p_specific[idx1st][idx2nd], &p, + sizeof (void *)) != PS_OK) + return TD_ERR; + + if (p != NULL) + *data = p; + + return p != NULL ? TD_OK : TD_NOTSD; +} diff --git a/libpthread/linuxthreads_db/td_thr_validate.c b/libpthread/linuxthreads_db/td_thr_validate.c new file mode 100644 index 0000000..6f893d3 --- /dev/null +++ b/libpthread/linuxthreads_db/td_thr_validate.c @@ -0,0 +1,70 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + struct pthread_handle_struct *handles = th->th_ta_p->handles; + int pthread_threads_max = th->th_ta_p->pthread_threads_max; + int cnt; + struct pthread_handle_struct phc; + + LOG ("td_thr_validate"); + + /* A special case: if the program just starts up the handle is + NULL. */ + if (th->th_unique == NULL) + { + /* Read the first handle. If the pointer to the thread + descriptor is not NULL this is an error. */ + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return phc.h_descr == NULL ? TD_OK : TD_NOTHR; + } + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles) + { + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (phc.h_descr != NULL && phc.h_descr == th->th_unique) + { + struct _pthread_descr_struct pds; + + if (ps_pdread (th->th_ta_p->ph, phc.h_descr, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* XXX There should be another test using the TID but this is + currently not available. */ + return pds.p_terminated != 0 ? TD_NOTHR : TD_OK; + } + } + + return TD_ERR; +} diff --git a/libpthread/linuxthreads_db/thread_db.h b/libpthread/linuxthreads_db/thread_db.h new file mode 100644 index 0000000..c115399 --- /dev/null +++ b/libpthread/linuxthreads_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the LinuxThreads library. It is + modelled closely after the interface with same names in Solaris with + the goal to share the same code in the debugger. */ +#include +#include +#include +#include + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Unused. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + void *__map_address, size_t __offset, + void **__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/libpthread/linuxthreads_db/thread_dbP.h b/libpthread/linuxthreads_db/thread_dbP.h new file mode 100644 index 0000000..407f306 --- /dev/null +++ b/libpthread/linuxthreads_db/thread_dbP.h @@ -0,0 +1,108 @@ +/* Private header for thread debug library. */ +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#include +#include +#include "proc_service.h" +#include "thread_db.h" +#include "../linuxthreads/descr.h" + + +/* Indices for the symbol names. */ +enum + { + PTHREAD_THREADS_EVENTS = 0, + PTHREAD_LAST_EVENT, + PTHREAD_HANDLES_NUM, + PTHREAD_HANDLES, + PTHREAD_KEYS, + LINUXTHREADS_PTHREAD_THREADS_MAX, + LINUXTHREADS_PTHREAD_KEYS_MAX, + LINUXTHREADS_PTHREAD_SIZEOF_DESCR, + LINUXTHREADS_CREATE_EVENT, + LINUXTHREADS_DEATH_EVENT, + LINUXTHREADS_REAP_EVENT, + LINUXTHREADS_INITIAL_REPORT_EVENTS, + LINUXTHREADS_VERSION, + NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Some cached information. */ + + /* Address of the `__pthread_handles' array. */ + struct pthread_handle_struct *handles; + + /* Address of the `pthread_kyes' array. */ + struct pthread_key_struct *keys; + + /* Maximum number of threads. */ + int pthread_threads_max; + + /* Maximum number of thread-local data keys. */ + int pthread_keys_max; + + /* Size of 2nd level array for thread-local data keys. */ + int pthread_key_2ndlevel_size; + + /* Sizeof struct _pthread_descr_struct. */ + int sizeof_descr; + + /* Pointer to the `__pthread_threads_events' variable in the target. */ + psaddr_t pthread_threads_eventsp; + + /* Pointer to the `__pthread_last_event' variable in the target. */ + psaddr_t pthread_last_event; + + /* Pointer to the `__pthread_handles_num' variable. */ + psaddr_t pthread_handles_num; +}; + + +/* Type used internally to keep track of thread agent descriptors. */ +struct agent_list +{ + td_thragent_t *ta; + struct agent_list *next; +}; + +/* List of all known descriptors. */ +extern struct agent_list *__td_agent_list attribute_hidden; + +/* Function used to test for correct thread agent pointer. */ +static __inline__ int +ta_ok (const td_thragent_t *ta) +{ + struct agent_list *runp = __td_agent_list; + + if (ta == NULL) + return 0; + + while (runp != NULL && runp->ta != ta) + runp = runp->next; + + return runp != NULL; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern int td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) attribute_hidden; + +#endif /* thread_dbP.h */ diff --git a/libresolv/Makefile b/libresolv/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libresolv/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libresolv/Makefile.in b/libresolv/Makefile.in new file mode 100644 index 0000000..f006fe1 --- /dev/null +++ b/libresolv/Makefile.in @@ -0,0 +1,50 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libresolv := -DNOT_IN_libc -DIS_IN_libresolv $(SSP_ALL_CFLAGS) + +LDFLAGS-libresolv.so := $(LDFLAGS) + +LIBS-libresolv.so := $(LIBS) + +libresolv_FULL_NAME := libresolv-$(VERSION).so + +libresolv_DIR := $(top_srcdir)libresolv +libresolv_OUT := $(top_builddir)libresolv + +libresolv_SRC := $(libresolv_DIR)/resolv.c +libresolv_OBJ := $(patsubst $(libresolv_DIR)/%.c,$(libresolv_OUT)/%.o,$(libresolv_SRC)) + +ifeq ($(DOPIC),y) +libresolv-a-y := $(libresolv_OBJ:.o=.os) +else +libresolv-a-y := $(libresolv_OBJ) +endif +libresolv-so-y := $(libresolv_OBJ:.o=.os) + +lib-a-y += $(top_builddir)lib/libresolv.a +lib-so-y += $(top_builddir)lib/libresolv.so +objclean-y += libresolv_clean + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libresolv.so: $(top_builddir)lib/libresolv.a $(libc.depend) +else +$(top_builddir)lib/libresolv.so: $(libresolv_OUT)/libresolv_so.a $(libc.depend) +endif + $(call link.so,$(libresolv_FULL_NAME),$(MAJOR_VERSION)) + +$(libresolv_OUT)/libresolv_so.a: $(libresolv-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libresolv.a: $(libresolv-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +libresolv_clean: + $(do_rm) $(addprefix $(libresolv_OUT)/*., o os a) diff --git a/libresolv/resolv.c b/libresolv/resolv.c new file mode 100644 index 0000000..38b10ff --- /dev/null +++ b/libresolv/resolv.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * libresolv for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +void __stub1(void); +void __stub1(void) +{ + return; +} +link_warning (__stub1, "the `libresolv' library is a stub. Do you really need it?") + diff --git a/librt/Makefile b/librt/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/librt/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/librt/Makefile.in b/librt/Makefile.in new file mode 100644 index 0000000..2902006 --- /dev/null +++ b/librt/Makefile.in @@ -0,0 +1,53 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-librt := -DNOT_IN_libc -DIS_IN_librt $(SSP_ALL_CFLAGS) + +LDFLAGS-librt.so := $(LDFLAGS) + +LIBS-librt.so := $(LIBS) + +librt_FULL_NAME := librt-$(VERSION).so + +librt_DIR := $(top_srcdir)librt +librt_OUT := $(top_builddir)librt + +ifeq ($(UCLIBC_HAS_REALTIME),y) +librt_SRC := $(wildcard $(librt_DIR)/*.c) +librt_OBJ := $(patsubst $(librt_DIR)/%.c,$(librt_OUT)/%.o,$(librt_SRC)) + +ifeq ($(DOPIC),y) +librt-a-y += $(librt_OBJ:.o=.os) +else +librt-a-y += $(librt_OBJ) +endif +librt-so-y += $(librt_OBJ:.o=.os) + +lib-a-y += $(top_builddir)lib/librt.a +lib-so-y += $(top_builddir)lib/librt.so +endif + +ifeq ($(DOPIC),y) +$(top_builddir)lib/librt.so: $(top_builddir)lib/librt.a $(libc.depend) +else +$(top_builddir)lib/librt.so: $(librt_OUT)/librt_so.a $(libc.depend) +endif + $(call link.so,$(librt_FULL_NAME),$(MAJOR_VERSION)) + +$(librt_OUT)/librt_so.a: $(librt-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/librt.a: $(librt-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +objclean-y += librt_clean + +librt_clean: + $(do_rm) $(addprefix $(librt_OUT)/*., o os a) diff --git a/librt/kernel-posix-timers.h b/librt/kernel-posix-timers.h new file mode 100644 index 0000000..bf246c9 --- /dev/null +++ b/librt/kernel-posix-timers.h @@ -0,0 +1,36 @@ +/* + * kernel-posix-timers.h - kernel-dependent definitions for POSIX timers. + */ + +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +/* Type of timers in the kernel */ +typedef int kernel_timer_t; + +/* Internal representation of timer */ +struct timer { + /* Notification mechanism */ + int sigev_notify; + + /* Timer ID returned by the kernel */ + kernel_timer_t ktimerid; + + /* + * All new elements must be added after ktimerid. And if the thrfunc + * element is not the third element anymore the memory allocation in + * timer_create needs to be changed. + */ + + /* Parameters for the thread to be started for SIGEV_THREAD */ + void (*thrfunc) (sigval_t); + sigval_t sival; +#ifdef __UCLIBC_HAS_THREADS__ + pthread_attr_t attr; +#endif +}; diff --git a/librt/mq_close.c b/librt/mq_close.c new file mode 100644 index 0000000..cf04044 --- /dev/null +++ b/librt/mq_close.c @@ -0,0 +1,22 @@ +/* + * mq_close.c - close a message queue. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_open + +/* + * Remove the association between message queue descriptor and its + * message queue. + */ +int mq_close(mqd_t mqdes) +{ + return close(mqdes); +} + +#endif diff --git a/librt/mq_getsetattr.c b/librt/mq_getsetattr.c new file mode 100644 index 0000000..b50d9a9 --- /dev/null +++ b/librt/mq_getsetattr.c @@ -0,0 +1,36 @@ +/* + * mq_getattr.c - get message queue attributes. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_getsetattr + +librt_hidden_proto(mq_setattr) +#define __NR___syscall_mq_getsetattr __NR_mq_getsetattr +static __inline__ _syscall3(int, __syscall_mq_getsetattr, int, mqdes, + const void *, mqstat, void *, omqstat); + +/* + * Set attributes associated with message queue (and possibly also get + * its old attributes) + */ +int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, + struct mq_attr *omqstat) +{ + return __syscall_mq_getsetattr(mqdes, mqstat, omqstat); +} + +librt_hidden_def(mq_setattr) + +/* Query status and attributes of message queue */ +int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat) +{ + return mq_setattr(mqdes, NULL, mqstat); +} + +#endif diff --git a/librt/mq_notify.c b/librt/mq_notify.c new file mode 100644 index 0000000..2556669 --- /dev/null +++ b/librt/mq_notify.c @@ -0,0 +1,28 @@ +/* + * mq_notify.c - notify process that a message is available. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_notify + +#define __NR___syscall_mq_notify __NR_mq_notify +static __inline__ _syscall2(int, __syscall_mq_notify, int, mqdes, + const void *, notification); + +/* Register notification upon message arrival to an empty message queue */ +int mq_notify(mqd_t mqdes, const struct sigevent *notification) +{ + /* We don't support SIGEV_THREAD notification yet */ + if (notification != NULL && notification->sigev_notify == SIGEV_THREAD) { + __set_errno(ENOSYS); + return -1; + } + return __syscall_mq_notify(mqdes, notification); +} + +#endif diff --git a/librt/mq_open.c b/librt/mq_open.c new file mode 100644 index 0000000..62c8310 --- /dev/null +++ b/librt/mq_open.c @@ -0,0 +1,52 @@ +/* + * mq_open.c - open a message queue. + */ + +#include +#include +#include +#include + +#include + +#ifdef __NR_mq_open + +#define __NR___syscall_mq_open __NR_mq_open +static __inline__ _syscall4(int, __syscall_mq_open, const char *, name, + int, oflag, __kernel_mode_t, mode, void *, attr); +/* + * Establish connection between a process and a message queue and + * return message queue descriptor or (mqd_t) -1 on error. + * oflag determines the type of access used. If O_CREAT is on oflag, the + * third argument is taken as a `mode_t', the mode of the created + * message queue, and the fourth argument is taken as `struct mq_attr *', + * pointer to message queue attributes. + * If the fourth argument is NULL, default attributes are used. + */ +mqd_t mq_open(const char *name, int oflag, ...) +{ + mode_t mode; + struct mq_attr *attr; + + if (name[0] != '/') { + __set_errno(EINVAL); + return -1; + } + + mode = 0; + attr = NULL; + + if (oflag & O_CREAT) { + va_list ap; + + va_start(ap, oflag); + mode = va_arg(ap, mode_t); + attr = va_arg(ap, struct mq_attr *); + + va_end(ap); + } + + return __syscall_mq_open(name + 1, oflag, mode, attr); +} + +#endif diff --git a/librt/mq_receive.c b/librt/mq_receive.c new file mode 100644 index 0000000..c0392b0 --- /dev/null +++ b/librt/mq_receive.c @@ -0,0 +1,51 @@ +/* + * mq_receive.c - functions for receiving from message queue. + */ + +#include +#include +#include +#include + +#ifdef __NR_mq_timedreceive +#define __NR___syscall_mq_timedreceive __NR_mq_timedreceive +static _syscall5(int, __syscall_mq_timedreceive, int, mqdes, + char *, msg_ptr, size_t, msg_len, unsigned int *, + msg_prio, const void *, abs_timeout) +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* + * Receive the oldest from highest priority messages. + * Stop waiting if abs_timeout expires. + */ +ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio, + const struct timespec *abs_timeout) +{ + return __syscall_mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout); +} +# endif + +/* Receive the oldest from highest priority messages */ +ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio) +{ + return __syscall_mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, NULL); +} +#elif defined __UCLIBC_HAS_STUBS__ +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +ssize_t mq_timedreceive(mqd_t mqdes attribute_unused, char *msg_ptr attribute_unused, + size_t msg_len attribute_unused, unsigned int *msg_prio attribute_unused, + const struct timespec *abs_timeout attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +# endif +ssize_t mq_receive(mqd_t mqdes attribute_unused, char *msg_ptr attribute_unused, + size_t msg_len attribute_unused, unsigned int *msg_prio attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/librt/mq_send.c b/librt/mq_send.c new file mode 100644 index 0000000..4c1a492 --- /dev/null +++ b/librt/mq_send.c @@ -0,0 +1,51 @@ +/* + * mq_send.c - functions for sending to message queue. + */ + +#include +#include +#include +#include + +#ifdef __NR_mq_timedsend +#define __NR___syscall_mq_timedsend __NR_mq_timedsend +static _syscall5(int, __syscall_mq_timedsend, int, mqdes, + const char *, msg_ptr, size_t, msg_len, unsigned int, + msg_prio, const void *, abs_timeout); + +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* + * Add a message to queue. If O_NONBLOCK is set and queue is full, wait + * for sufficient room in the queue until abs_timeout expires. + */ +int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio, const struct timespec *abs_timeout) +{ + return __syscall_mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout); +} +# endif + +/* Add a message to queue */ +int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio) +{ + return __syscall_mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, NULL); +} +#elif defined __UCLIBC_HAS_STUBS__ +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +int mq_timedsend(mqd_t mqdes attribute_unused, const char *msg_ptr attribute_unused, + size_t msg_len attribute_unused, unsigned int msg_prio attribute_unused, + const struct timespec *abs_timeout attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +# endif +int mq_send(mqd_t mqdes attribute_unused, const char *msg_ptr attribute_unused, + size_t msg_len attribute_unused, unsigned int msg_prio attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/librt/mq_unlink.c b/librt/mq_unlink.c new file mode 100644 index 0000000..3c490e0 --- /dev/null +++ b/librt/mq_unlink.c @@ -0,0 +1,39 @@ +/* + * mq_unlink.c - remove a message queue. + */ + +#include +#include + +#include + +#ifdef __NR_mq_unlink + +#define __NR___syscall_mq_unlink __NR_mq_unlink +static __inline__ _syscall1(int, __syscall_mq_unlink, const char *, name); + +/* Remove message queue */ +int mq_unlink(const char *name) +{ + int ret; + + if (name[0] != '/') { + __set_errno(EINVAL); + return -1; + } + + ret = __syscall_mq_unlink(name + 1); + + /* While unlink can return either EPERM or EACCES, mq_unlink should return just EACCES. */ + if (ret < 0) { + ret = errno; + if (ret == EPERM) + ret = EACCES; + __set_errno(ret); + ret = -1; + } + + return ret; +} + +#endif diff --git a/librt/timer_create.c b/librt/timer_create.c new file mode 100644 index 0000000..9298a37 --- /dev/null +++ b/librt/timer_create.c @@ -0,0 +1,71 @@ +/* + * timer_create.c - create a per-process timer. + */ + +#include +#include +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_create + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define __NR___syscall_timer_create __NR_timer_create +static __inline__ _syscall3(int, __syscall_timer_create, clockid_t, clock_id, + struct sigevent *, evp, kernel_timer_t *, ktimerid); + +/* Create a per-process timer */ +int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t * timerid) +{ + int retval; + kernel_timer_t ktimerid; + struct sigevent default_evp; + struct timer *newp; + + if (evp == NULL) { + /* + * The kernel has to pass up the timer ID which is a userlevel object. + * Therefore we cannot leave it up to the kernel to determine it. + */ + default_evp.sigev_notify = SIGEV_SIGNAL; + default_evp.sigev_signo = SIGALRM; + evp = &default_evp; + } + + /* Notification via a thread is not supported yet */ + if (__builtin_expect(evp->sigev_notify == SIGEV_THREAD, 1)) + return -1; + + /* + * We avoid allocating too much memory by basically using + * struct timer as a derived class with the first two elements + * being in the superclass. We only need these two elements here. + */ + newp = malloc(offsetof(struct timer, thrfunc)); + if (newp == NULL) + return -1; /* No memory */ + default_evp.sigev_value.sival_ptr = newp; + + retval = __syscall_timer_create(clock_id, evp, &ktimerid); + if (retval != -1) { + newp->sigev_notify = evp->sigev_notify; + newp->ktimerid = ktimerid; + + *timerid = (timer_t) newp; + } else { + /* Cannot allocate the timer, fail */ + free(newp); + retval = -1; + } + + return retval; +} + +#endif diff --git a/librt/timer_delete.c b/librt/timer_delete.c new file mode 100644 index 0000000..af6b34f --- /dev/null +++ b/librt/timer_delete.c @@ -0,0 +1,33 @@ +/* + * timer_delete.c - delete a per-process timer. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_delete + +#define __NR___syscall_timer_delete __NR_timer_delete +static __inline__ _syscall1(int, __syscall_timer_delete, kernel_timer_t, ktimerid); + +/* Delete a per-process timer */ +int timer_delete(timer_t timerid) +{ + int res; + struct timer *kt = (struct timer *)timerid; + + /* Delete the kernel timer object */ + res = __syscall_timer_delete(kt->ktimerid); + if (res == 0) { + free(kt); /* Free the memory */ + return 0; + } + + return -1; +} + +#endif diff --git a/librt/timer_getoverr.c b/librt/timer_getoverr.c new file mode 100644 index 0000000..0e85516 --- /dev/null +++ b/librt/timer_getoverr.c @@ -0,0 +1,26 @@ +/* + * timer-getoverr.c - get the timer overrun count. + */ + +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_getoverrun + +#define __NR___syscall_timer_getoverrun __NR_timer_getoverrun +static __inline__ _syscall1(int, __syscall_timer_getoverrun, kernel_timer_t, + ktimerid); + +/* Get the timer overrun count */ +int timer_getoverrun(timer_t timerid) +{ + struct timer *kt = (struct timer *)timerid; + + /* Get the information from the kernel */ + return __syscall_timer_getoverrun(kt->ktimerid); +} + +#endif diff --git a/librt/timer_gettime.c b/librt/timer_gettime.c new file mode 100644 index 0000000..e13f446 --- /dev/null +++ b/librt/timer_gettime.c @@ -0,0 +1,27 @@ +/* + * timer_gettime.c - get the timer value. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_gettime + +#define __NR___syscall_timer_gettime __NR_timer_gettime +static __inline__ _syscall2(int, __syscall_timer_gettime, kernel_timer_t, ktimerid, + void *, value); + +/* Get the amount of time left on a timer */ +int timer_gettime(timer_t timerid, struct itimerspec *value) +{ + struct timer *kt = (struct timer *)timerid; + + /* Get timeout from the kernel */ + return __syscall_timer_gettime(kt->ktimerid, value); +} + +#endif diff --git a/librt/timer_settime.c b/librt/timer_settime.c new file mode 100644 index 0000000..2703fa9 --- /dev/null +++ b/librt/timer_settime.c @@ -0,0 +1,28 @@ +/* + * timer_settime.c - set the timer. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_settime + +#define __NR___syscall_timer_settime __NR_timer_settime +static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid, + int, flags, const void *, value, void *, ovalue); + +/* Set the expiration time for a timer */ +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue) +{ + struct timer *kt = (struct timer *)timerid; + + /* Set timeout */ + return __syscall_timer_settime(kt->ktimerid, flags, value, ovalue); +} + +#endif diff --git a/libutil/Makefile b/libutil/Makefile new file mode 100644 index 0000000..c8dc9b4 --- /dev/null +++ b/libutil/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libutil/Makefile.in b/libutil/Makefile.in new file mode 100644 index 0000000..67d9738 --- /dev/null +++ b/libutil/Makefile.in @@ -0,0 +1,66 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-libutil := -DNOT_IN_libc -DIS_IN_libutil $(SSP_ALL_CFLAGS) + +LDFLAGS-libutil.so := $(LDFLAGS) + +LIBS-libutil.so := $(LIBS) + +libutil_FULL_NAME := libutil-$(VERSION).so + +libutil_DIR := $(top_srcdir)libutil +libutil_OUT := $(top_builddir)libutil + +libutil_SRC := $(wildcard $(libutil_DIR)/*.c) +ifneq ($(ARCH_USE_MMU),y) +libutil_SRC := $(filter-out $(libutil_DIR)/forkpty.c,$(libutil_SRC)) +endif +ifneq ($(UCLIBC_HAS_PTY),y) +libutil_SRC := $(filter-out $(libutil_DIR)/openpty.c $(libutil_DIR)/forkpty.c \ + ,$(libutil_SRC)) +endif +libutil_OBJ := $(patsubst $(libutil_DIR)/%.c,$(libutil_OUT)/%.o,$(libutil_SRC)) + +ifeq ($(DOPIC),y) +libutil-a-y := $(libutil_OBJ:.o=.os) +else +libutil-a-y := $(libutil_OBJ) +endif +libutil-so-y := $(libutil_OBJ:.o=.os) + +lib-a-y += $(top_builddir)lib/libutil.a +lib-so-y += $(top_builddir)lib/libutil.so +objclean-y += libutil_clean + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libutil.so: $(top_builddir)lib/libutil.a $(libc.depend) +else +$(top_builddir)lib/libutil.so: $(libutil_OUT)/libutil_so.a $(libc.depend) +endif + $(call link.so,$(libutil_FULL_NAME),$(MAJOR_VERSION)) +else +$(top_builddir)lib/libutil.so: $(libutil_OUT)/libutil.oS | $(libc.depend) + $(call linkm.so,$(libutil_FULL_NAME),$(MAJOR_VERSION)) +endif + +$(libutil_OUT)/libutil_so.a: $(libutil-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libutil_OUT)/libutil.oS: $(libutil_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libutil.a: $(libutil-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +libutil_clean: + $(do_rm) $(addprefix $(libutil_OUT)/*., o os oS a) diff --git a/libutil/forkpty.c b/libutil/forkpty.c new file mode 100644 index 0000000..61e8592 --- /dev/null +++ b/libutil/forkpty.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +libutil_hidden_proto(openpty) +libutil_hidden_proto(login_tty) + +int +forkpty (int *amaster, char *name, struct termios *termp, struct winsize *winp) +{ + int master, slave, pid; + + if (openpty (&master, &slave, name, termp, winp) == -1) + return -1; + + switch (pid = fork ()) + { + case -1: + return -1; + case 0: + /* Child. */ + close (master); + if (login_tty (slave)) + _exit (1); + + return 0; + default: + /* Parent. */ + *amaster = master; + close (slave); + + return pid; + } +} diff --git a/libutil/login.c b/libutil/login.c new file mode 100644 index 0000000..bd1dd29 --- /dev/null +++ b/libutil/login.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include + +/* Write the given entry into utmp and wtmp. */ +void login (const struct utmp *entry) +{ + struct utmp copy = *entry; + + utmpname(_PATH_UTMP); + setutent(); +#if _HAVE_UT_TYPE - 0 + copy.ut_type = USER_PROCESS; +#endif +#if _HAVE_UT_PID - 0 + copy.ut_pid = getpid(); +#endif + strncpy (copy.ut_line, entry->ut_line, UT_LINESIZE); + pututline(entry); + endutent(); +} + diff --git a/libutil/login_tty.c b/libutil/login_tty.c new file mode 100644 index 0000000..3979adc --- /dev/null +++ b/libutil/login_tty.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Make FD be the controlling terminal, stdin, stdout, and stderr; + then close FD. Returns 0 on success, nonzero on error. */ + +#include +#include +#include +#include +#include + +libutil_hidden_proto(login_tty) +int login_tty(int fd) +{ + (void) setsid(); +#ifdef TIOCSCTTY + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) + return (-1); +#else + { + /* This might work. */ + char *fdname = ttyname (fd); + int newfd; + if (fdname) + { + if (fd != 0) + (void) close (0); + if (fd != 1) + (void) close (1); + if (fd != 2) + (void) close (2); + newfd = open (fdname, O_RDWR); + (void) close (newfd); + } + } +#endif + (void) dup2(fd, 0); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + if (fd > 2) + (void) close(fd); + return (0); +} +libutil_hidden_def(login_tty) diff --git a/libutil/logout.c b/libutil/logout.c new file mode 100644 index 0000000..e6d9565 --- /dev/null +++ b/libutil/logout.c @@ -0,0 +1,79 @@ +/* Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +logout (const char *line) +{ + struct utmp tmp; + struct utmp *ut; + int result = 0; + + /* Tell that we want to use the UTMP file. */ + if (utmpname (_PATH_UTMP) == -1) + return 0; + + /* Open UTMP file. */ + setutent (); + + /* Fill in search information. */ +#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +#endif + strncpy (tmp.ut_line, line, sizeof tmp.ut_line); + + /* Read the record. */ + if( (ut = getutline(&tmp)) ) + { + /* Clear information about who & from where. */ + memset (ut->ut_name, 0, sizeof ut->ut_name); +#if _HAVE_UT_HOST - 0 + memset (ut->ut_host, 0, sizeof ut->ut_host); +#endif +#if _HAVE_UT_TV - 0 +# if !defined __WORDSIZE_COMPAT32 || __WORDSIZE_COMPAT32 == 0 + gettimeofday (&ut->ut_tv, NULL); +# else + { + struct timeval tv; + gettimeofday (&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; + } +# endif +#else + time (&ut->ut_time); +#endif +#if _HAVE_UT_TYPE - 0 + ut->ut_type = DEAD_PROCESS; +#endif + + if (pututline (ut) != NULL) + result = 1; + } + + /* Close UTMP file. */ + endutent (); + + return result; +} diff --git a/libutil/logwtmp.c b/libutil/logwtmp.c new file mode 100644 index 0000000..0845b50 --- /dev/null +++ b/libutil/logwtmp.c @@ -0,0 +1,56 @@ +/* vi: set sw=4 ts=4: */ +/* + * wtmp support rubbish (i.e. complete crap) + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include + + +void logwtmp (const char *line, const char *name, const char *host) +{ + struct utmp lutmp; + memset (&(lutmp), 0, sizeof (struct utmp)); + + lutmp.ut_type = (name && *name)? USER_PROCESS : DEAD_PROCESS; + lutmp.ut_pid = getpid(); + strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); + strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); + strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); +#if !defined __WORDSIZE_COMPAT32 || __WORDSIZE_COMPAT32 == 0 + gettimeofday(&(lutmp.ut_tv), NULL); +#else + { + struct timeval tv; + gettimeofday (&tv, NULL); + lutmp.ut_tv.tv_sec = tv.tv_sec; + lutmp.ut_tv.tv_usec = tv.tv_usec; + } +#endif + + updwtmp(_PATH_WTMP, &(lutmp)); +} + +#if 0 +/* This is enabled in uClibc/libc/misc/utmp/wtent.c */ +extern void updwtmp(const char *wtmp_file, const struct utmp *lutmp) +{ + int fd; + + fd = open(wtmp_file, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0)==0) { + write(fd, (const char *) lutmp, sizeof(struct utmp)); + lockf(fd, F_ULOCK, 0); + close(fd); + } + } +} +#endif diff --git a/libutil/openpty.c b/libutil/openpty.c new file mode 100644 index 0000000..5f58476 --- /dev/null +++ b/libutil/openpty.c @@ -0,0 +1,157 @@ +/* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BCS: the following function is, IMO, overkill */ +#if 0 +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_r (fd, buf, buf_len); + + if (rv != 0 || memchr (buf, '\0', buf_len)) + /* We either got an error, or we succeeded and the + returned name fit in the buffer. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + __set_errno (ENOMEM); + break; + } + buf = new_buf; + } + + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} +#endif + +/* Create pseudo tty master slave pair and set terminal attributes + according to TERMP and WINP. Return handles for both ends in + AMASTER and ASLAVE, and return the name of the slave end in NAME. */ +libutil_hidden_proto(openpty) +int +openpty (int *amaster, int *aslave, char *name, struct termios *termp, + struct winsize *winp) +{ +#if 0 +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; +#else +#ifdef PATH_MAX + char buf[PATH_MAX]; +#else + char buf[512]; +#endif +#endif + int master, slave; + + master = posix_openpt (O_RDWR); + if (master == -1) + return -1; + + if (grantpt (master)) + goto fail; + + if (unlockpt (master)) + goto fail; + +#if 0 + if (pts_name (master, &buf, sizeof (_buf))) +#else + if (ptsname_r (master, buf, sizeof buf)) +#endif + goto fail; + + slave = open (buf, O_RDWR | O_NOCTTY); + if (slave == -1) + { +#if 0 + if (buf != _buf) + free (buf); +#endif + goto fail; + } + + /* XXX Should we ignore errors here? */ + if(termp) + tcsetattr (slave, TCSAFLUSH, termp); + if (winp) + ioctl (slave, TIOCSWINSZ, winp); + + *amaster = master; + *aslave = slave; + if (name != NULL) + strcpy (name, buf); + +#if 0 + if (buf != _buf) + free (buf); +#endif + return 0; + + fail: + close (master); + return -1; +} +libutil_hidden_def(openpty) diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..f38427e --- /dev/null +++ b/test/Makefile @@ -0,0 +1,71 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_builddir=../ +include Rules.mak + +ALL_SUBDIRS := $(patsubst %/Makefile,%,$(wildcard */Makefile)) + +DIRS := $(ALL_SUBDIRS) +ifneq ($(HAVE_SHARED)$(UCLIBC_HAS_THREADS),yy) + DIRS := $(filter-out dlopen,$(DIRS)) +endif +ifneq ($(findstring -static,$(LDFLAGS)),) + DIRS := $(filter-out dlopen,$(DIRS)) +endif +ifneq ($(UCLIBC_HAS_THREADS),y) + DIRS := $(filter-out pthread,$(DIRS)) +endif +ifneq ($(UCLIBC_HAS_FULL_RPC),y) + DIRS := $(filter-out rpc,$(DIRS)) +endif +ifneq ($(UCLIBC_HAS_REGEX),y) + DIRS := $(filter-out regex,$(DIRS)) +endif +ifneq ($(UCLIBC_HAS_WCHAR),y) + DIRS := $(filter-out locale-mbwc,$(DIRS)) +endif +ifneq ($(UCLIBC_HAS_LOCALE),y) + DIRS := $(filter-out locale,$(DIRS)) +endif +ifeq ($(UCLIBC_HAS_CRYPT_STUB),y) + DIRS := $(filter-out crypt,$(DIRS)) +endif +ifeq ($(HAS_NO_THREADS),y) + DIRS := $(filter-out pthread,$(DIRS)) +endif +DIRS := $(filter-out math,$(DIRS)) + +test check all: run + +run: subdirs_run + +compile: subdirs_compile + +tags: + ctags -R + +clean: subdirs_clean + +subdirs: $(patsubst %, _dir_%, $(DIRS)) +subdirs_compile: $(patsubst %, _dircompile_%, $(DIRS)) +subdirs_run: $(patsubst %, _dirrun_%, $(DIRS)) +subdirs_clean: $(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) + +$(patsubst %, _dir_%, $(DIRS)) : dummy + $(Q)$(MAKE) -C $(patsubst _dir_%, %, $@) + +$(patsubst %, _dirrun_%, $(DIRS)) : dummy + $(Q)$(MAKE) -C $(patsubst _dirrun_%, %, $@) run + +$(patsubst %, _dircompile_%, $(DIRS)) : dummy + $(Q)$(MAKE) -C $(patsubst _dircompile_%, %, $@) compile + +$(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) : dummy + $(Q)$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean + +.PHONY: all check clean dummy subdirs_compile subdirs_run subdirs subdirs_clean test run compile diff --git a/test/README b/test/README new file mode 100644 index 0000000..2bc92ab --- /dev/null +++ b/test/README @@ -0,0 +1,68 @@ +----------- + For: User +----------- +Following make targets are avaialable + +make compile + +This will compile and link the tests + +make run + +This will check for binaries if they are not there it +will call 'compile' target then it will execute all the +tests. + +make check +make all + +This will build and run tests. + +The following make variables may help you in testing: + - UCLIBC_ONLY - only run tests against uClibc + - GLIBC_ONLY - only run tests against glibc + - V / VERBOSE - run tests with a lot of output + - TEST_INSTALLED_UCLIBC - Test installed libraries + under /lib and /usr/lib. +So, to just run the uClibc tests, try this: +make check UCLIBC_ONLY=1 + +---------------- + For: Developer +---------------- + +The structure of this test system is: + test/ toplevel dir containing common test code + test/Rules.mak Common build code + test/Test.mak Runtime test make code + test/subdir/ code specific to a subsystem is stored in a subdir + test/subdir/Makefile describe the tests to run + test/subdir/*.c the tests + +Each subdir Makefile must include the toplevel Test.mak file. Before doing so, +you may define the TESTS and TESTS_DISABLED variables. If you do not, TESTS +is built automatically based upon all the .c files in the subdir. +TESTS := foo +TESTS_DISABLED := bar +include ../Test.mak +Each test must use a similar .c name; so the "foo" test needs a "foo.c". + +Additionally, the following options further control specific test behavior: +CFLAGS_foo := extra cflags to use to compile test +DODIFF_foo := compare the output of the glibc and uClibc tests (see below) +LDFLAGS_foo := extra ldflags to use to link test +OPTS_foo := extra options to pass to test +RET_foo := expected exit code of test; default is 0 +WRAPPER_foo := execute stuff just before test + +Or to control all tests in a subdir: +EXTRA_CLEAN := extra files to remove in the clean target +EXTRA_DIRS := extra directories to remove in the clean target +EXTRA_CFLAGS := -DFOO +EXTRA_LDFLAGS := -lpthread +OPTS := +WRAPPER := + +If you want to compare the output of a test with known good output, then just +create a local file named "foo.out.good" and the output generated by the test +"foo" will be automatically stored in "foo.out" and compared to "foo.out.good". diff --git a/test/Rules.mak b/test/Rules.mak new file mode 100644 index 0000000..d188a91 --- /dev/null +++ b/test/Rules.mak @@ -0,0 +1,161 @@ +# Rules.mak for uClibc test subdirs +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# +# Note: This does not read the top level Rules.mak file +# + +top_builddir ?= ../ + +TESTDIR=$(top_builddir)test/ + +include $(top_builddir)/Rules.mak +ifndef TEST_INSTALLED_UCLIBC +ifdef UCLIBC_LDSO +ifeq (,$(findstring /,$(UCLIBC_LDSO))) +UCLIBC_LDSO := $(top_builddir)lib/$(UCLIBC_LDSO) +endif +else +UCLIBC_LDSO := $(firstword $(wildcard $(top_builddir)lib/ld*)) +endif +endif +#-------------------------------------------------------- +# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc. +LC_ALL:= C +export LC_ALL + +ifeq ($(strip $(TARGET_ARCH)),) +TARGET_ARCH:=$(shell $(CC) -dumpmachine | sed -e s'/-.*//' \ + -e 's/i.86/i386/' \ + -e 's/sparc.*/sparc/' \ + -e 's/arm.*/arm/g' \ + -e 's/m68k.*/m68k/' \ + -e 's/ppc/powerpc/g' \ + -e 's/v850.*/v850/g' \ + -e 's/sh[234]/sh/' \ + -e 's/mips.*/mips/' \ + -e 's/cris.*/cris/' \ + -e 's/xtensa.*/xtensa/' \ + ) +endif +export TARGET_ARCH + + +#-------------------------------------------------------- +# If you are running a cross compiler, you will want to set 'CROSS' +# to something more interesting... Target architecture is determined +# by asking the CC compiler what arch it compiles things for, so unless +# your compiler is broken, you should not need to specify TARGET_ARCH +# +# Most people will set this stuff on the command line, i.e. +# make CROSS=mipsel-linux- +# will build uClibc for 'mipsel'. + +CROSS = $(subst ",, $(strip $(CROSS_COMPILER_PREFIX))) +CC = $(CROSS)gcc +RM = rm -f +RM_R = $(RM) -r + +# Select the compiler needed to build binaries for your development system +HOSTCC = gcc + + +#-------------------------------------------------------- +# A nifty macro to make testing gcc features easier +check_gcc=$(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then echo "$(1)"; else echo "$(2)"; fi) + +# use '-Os' optimization if available, else use -O2, allow Config to override +# Override optimization settings when debugging +ifeq ($(DODEBUG),y) +OPTIMIZATION = -O0 +else +OPTIMIZATION += $(call check_gcc,-Os,-O2) +endif + +XWARNINGS := $(subst ",, $(strip $(WARNINGS))) -Wstrict-prototypes +XARCH_CFLAGS := $(subst ",, $(strip $(ARCH_CFLAGS))) $(CPU_CFLAGS) +XCOMMON_CFLAGS := -D_GNU_SOURCE -I$(top_builddir)test +CFLAGS := $(XWARNINGS) $(OPTIMIZATION) $(XCOMMON_CFLAGS) $(XARCH_CFLAGS) -nostdinc -I$(top_builddir)$(LOCAL_INSTALL_PATH)/usr/include + +CC_IPREFIX:=$(shell $(CC) --print-file-name=include) +CFLAGS += -I$(dir $(CC_IPREFIX))/include-fixed -I$(CC_IPREFIX) + +HOST_CFLAGS += $(XWARNINGS) $(OPTIMIZATION) $(XCOMMON_CFLAGS) + +LDFLAGS := $(CPU_LDFLAGS) +ifeq ($(DODEBUG),y) + CFLAGS += -g + HOST_CFLAGS += -g + LDFLAGS += -g + HOST_LDFLAGS += -g +else + LDFLAGS += -s + HOST_LDFLAGS += -s +endif + +ifneq ($(strip $(HAVE_SHARED)),y) + LDFLAGS += -static + HOST_LDFLAGS += -static +endif + +LDFLAGS += -B$(top_builddir)lib -Wl,-rpath,$(top_builddir)lib -Wl,-rpath-link,$(top_builddir)lib +UCLIBC_LDSO_ABSPATH=$(shell pwd) +ifdef TEST_INSTALLED_UCLIBC +LDFLAGS += -Wl,-rpath,./ +UCLIBC_LDSO_ABSPATH=$(SHARED_LIB_LOADER_PREFIX) +endif + +ifeq ($(findstring -static,$(LDFLAGS)),) + LDFLAGS += -Wl,--dynamic-linker,$(UCLIBC_LDSO_ABSPATH)/$(UCLIBC_LDSO) +endif + +ifeq ($(LDSO_GNU_HASH_SUPPORT),y) +# Check for binutils support is done on root Rules.mak +LDFLAGS += -Wl,${LDFLAGS_GNUHASH} +endif + + +# Filter output +MAKEFLAGS += --no-print-directory +ifneq ($(findstring s,$(MAKEFLAGS)),) +DISP := sil +Q := @ +SCAT := -@true +else +ifneq ($(V)$(VERBOSE),) +DISP := ver +Q := +SCAT := cat +else +DISP := pur +Q := @ +SCAT := -@true +endif +endif + +banner := --------------------------------- +pur_showclean = echo " "CLEAN $(notdir $(CURDIR)) +pur_showdiff = echo " "TEST_DIFF $(notdir $(CURDIR))/ +pur_showlink = echo " "TEST_LINK $(notdir $(CURDIR))/ $@ +pur_showtest = echo " "TEST_EXEC $(notdir $(CURDIR))/ $(patsubst %.exe,%,$@) +sil_showclean = +sil_showdiff = true +sil_showlink = true +sil_showtest = true +ver_showclean = +ver_showdiff = true echo +ver_showlink = true echo +ver_showtest = printf "\n$(banner)\nTEST $(notdir $(PWD))/ $(patsubst %.exe,%,$@)\n$(banner)\n" +do_showclean = $($(DISP)_showclean) +do_showdiff = $($(DISP)_showdiff) +do_showlink = $($(DISP)_showlink) +do_showtest = $($(DISP)_showtest) +showclean = @$(do_showclean) +showdiff = @$(do_showdiff) +showlink = @$(do_showlink) +showtest = @$(do_showtest) diff --git a/test/Test.mak b/test/Test.mak new file mode 100644 index 0000000..43c35d2 --- /dev/null +++ b/test/Test.mak @@ -0,0 +1,117 @@ +# Common makefile rules for tests +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +ifeq ($(TESTS),) +TESTS := $(patsubst %.c,%,$(wildcard *.c)) +endif +ifneq ($(TESTS_DISABLED),) +TESTS := $(filter-out $(TESTS_DISABLED),$(TESTS)) +endif +ifeq ($(SHELL_TESTS),) +SHELL_TESTS := $(patsubst %.sh,shell_%,$(wildcard *.sh)) +endif + +ifneq ($(filter-out test,$(TESTS)),$(TESTS)) +$(error Sanity check: cannot have a test named "test.c") +endif + +top_builddir = ../../ +include ../Rules.mak + +U_TARGETS := $(TESTS) +G_TARGETS := $(patsubst %,%_glibc,$(U_TARGETS)) + +ifeq ($(GLIBC_ONLY),) +TARGETS += $(U_TARGETS) +endif +ifeq ($(UCLIBC_ONLY),) +TARGETS += $(G_TARGETS) +endif + +CLEAN_TARGETS := $(U_TARGETS) $(G_TARGETS) +COMPILE_TARGETS := $(TARGETS) +RUN_TARGETS := $(patsubst %,%.exe,$(TARGETS)) +TARGETS += $(SHELL_TESTS) + +define binary_name +$(patsubst %.exe,%,$@) +endef + +define diff_test + $(Q)\ + for x in "$(binary_name).out" "$(patsubst %_glibc,%,$(binary_name)).out" ; do \ + test -e "$$x.good" && $(do_showdiff) "$(binary_name).out" "$$x.good" && exec diff -u "$(binary_name).out" "$$x.good" ; \ + done ; \ + true +endef +define uclibc_glibc_diff_test + $(Q)\ + test -z "$(DODIFF_$(patsubst %_glibc,%,$(binary_name)))" && exec true ; \ + uclibc_out="$(binary_name).out" ; \ + glibc_out="$(patsubst %_glibc,%,$(binary_name)).out" ; \ + $(do_showdiff) $$uclibc_out $$glibc_out ; \ + exec diff -u "$$uclibc_out" "$$glibc_out" +endef +define exec_test + $(showtest) + $(Q)\ + $(WRAPPER) $(WRAPPER_$(patsubst %_glibc,%,$(binary_name))) \ + ./$(binary_name) $(OPTS) $(OPTS_$(patsubst %_glibc,%,$(binary_name))) > "$(binary_name).out" 2>&1 ; \ + ret=$$? ; \ + expected_ret="$(RET_$(patsubst %_glibc,%,$(binary_name)))" ; \ + test -z "$$expected_ret" && export expected_ret=0 ; \ + if ! test $$ret -eq $$expected_ret ; then \ + echo "ret == $$ret ; expected_ret == $$expected_ret" ; \ + exit 1 ; \ + fi + $(SCAT) "$(binary_name).out" +endef + +test check all: run +run: $(RUN_TARGETS) compile + +$(RUN_TARGETS): $(TARGETS) + $(exec_test) + $(diff_test) +ifeq ($(UCLIBC_ONLY),) + $(uclibc_glibc_diff_test) +endif + +compile: $(COMPILE_TARGETS) + +G_TARGET_SRCS := $(patsubst %,%.c,$(G_TARGETS)) +U_TARGET_SRCS := $(patsubst %,%.c,$(U_TARGETS)) + +$(MAKE_SRCS): Makefile $(TESTDIR)Makefile $(TESTDIR)Rules.mak $(TESTDIR)Test.mak + +$(U_TARGETS): $(U_TARGET_SRCS) $(MAKE_SRCS) + $(showlink) + $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -c $@.c -o $@.o + $(Q)$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LDFLAGS) $(LDFLAGS_$@) + +$(G_TARGETS): $(U_TARGET_SRCS) $(MAKE_SRCS) + $(showlink) + $(Q)$(HOSTCC) $(HOST_CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(patsubst %_glibc,%,$@)) -c $(patsubst %_glibc,%,$@).c -o $@.o + $(Q)$(HOSTCC) $(HOST_LDFLAGS) $@.o -o $@ $(EXTRA_LDFLAGS) $(LDFLAGS_$(patsubst %_glibc,%,$@)) + + +shell_%: + $(showtest) + $(Q)$(SHELL) $(patsubst shell_%,%.sh,$(binary_name)) + +%.so: %.c + $(showlink) + $(Q)$(CC) \ + $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(patsubst %_glibc,%,$@)) \ + -fPIC -shared $< -o $@ -Wl,-soname,$@ \ + $(LDFLAGS) $(EXTRA_LIBS) $(LDFLAGS_$(patsubst %_glibc,%,$@)) + +clean: + $(showclean) + $(Q)$(RM) *.a *.o *.so *~ core *.out *.gdb $(CLEAN_TARGETS) $(EXTRA_CLEAN) + $(Q)$(RM_R) $(EXTRA_DIRS) + +.PHONY: all check clean test run compile diff --git a/test/args/Makefile b/test/args/Makefile new file mode 100644 index 0000000..7ba8a31 --- /dev/null +++ b/test/args/Makefile @@ -0,0 +1,11 @@ +# uClibc args tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +OPTS_arg_test = a b c d e f g h +WRAPPER_arg_test = \ + env -i \ + ENVVAR=123 \ + SOMETHING=sldajfasdf \ + BLAHBLAH=" hi hi " diff --git a/test/args/arg_test.c b/test/args/arg_test.c new file mode 100644 index 0000000..86f3157 --- /dev/null +++ b/test/args/arg_test.c @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * Test application for argc and argv handling + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +int main(int argc, char **argv) +{ + int i=0; + char** index=__environ; + +#ifdef __powerpc__ + { + unsigned long sp; + sp = (unsigned long) __builtin_frame_address(0); + if(sp&0xf){ + printf("stack pointer is unaligned! (%08lx)\n", sp); + } + } +#endif + + printf("argc=%d\n", argc); + + for(i=0;i + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#undef NDEBUG + +#include +#include +#include +#include +#include "../testsuite.h" + +int got_abort; + +static void aborthandler(int junk) +{ + got_abort = 1; +} + +int main(int argc, char *argv[]) +{ + signal(SIGABRT, aborthandler); + + init_testsuite("Testing functions defined in assert.h:\n\t"); + + got_abort=0; + assert(0 == 0); + TEST_NUMERIC(got_abort, 0); + +#define NDEBUG + got_abort = 0; + printf("Don't worry -- This next test is supposed to print an assert message:\n"); + fprintf(stderr, "\t"); + assert(0 == 1); + TEST_NUMERIC(got_abort, 0); + +#undef NDEBUG + got_abort = 0; + assert(0 == 1); + TEST_NUMERIC(got_abort, 1); + + exit(0); +} diff --git a/test/build/Makefile b/test/build/Makefile new file mode 100644 index 0000000..eb65c2a --- /dev/null +++ b/test/build/Makefile @@ -0,0 +1,4 @@ +# uClibc build tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak diff --git a/test/build/check_config_options.sh b/test/build/check_config_options.sh new file mode 100644 index 0000000..086131f --- /dev/null +++ b/test/build/check_config_options.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +ret=0 + +# Make sure nothing uses the ARCH_HAS_MMU option anymore +result=$( +find ../.. \ + | grep -v \ + -e include/bits/uClibc_config.h \ + -e /test/ \ + -e /.svn/ \ + | xargs grep -sHI \ + __ARCH_HAS_MMU__ +) +if [ -n "$result" ] ; then + echo "The build system is incorrectly using ARCH_HAS_MMU:" + echo "$result" + ret=1 +fi + +exit $ret diff --git a/test/crypt/Makefile b/test/crypt/Makefile new file mode 100644 index 0000000..11d420d --- /dev/null +++ b/test/crypt/Makefile @@ -0,0 +1,8 @@ +# uClibc crypt tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +EXTRA_LDFLAGS := -lcrypt + +OPTS_crypt = < crypt.input diff --git a/test/crypt/crypt.c b/test/crypt/crypt.c new file mode 100644 index 0000000..34d7e41 --- /dev/null +++ b/test/crypt/crypt.c @@ -0,0 +1,113 @@ + +/* + * This crypt(3) validation program shipped with UFC-crypt + * is derived from one distributed with Phil Karns PD DES package. + * + * @(#)cert.c 1.8 11 Aug 1996 + */ + +#include +#include +#include "crypt.h" + +int totfails = 0; + +#if __STDC__ - 0 +int main (int argc, char *argv[]); +void get8 (char *cp); +void put8 (char *cp); +void good_bye (void) __attribute__ ((noreturn)); +#else +void get8(), put8(); +#endif + +void good_bye () +{ + if(totfails == 0) { + printf("Passed DES validation suite\n"); + exit(0); + } else { + printf("%d failures during DES validation suite!!!\n", totfails); + exit(1); + } +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char key[64],plain[64],cipher[64],answer[64]; + int i; + int test; + int fail; + + for(test=0;!feof(stdin);test++){ + + get8(key); + printf(" K: "); put8(key); + setkey(key); + + get8(plain); + printf(" P: "); put8(plain); + + get8(answer); + printf(" C: "); put8(answer); + + for(i=0;i<64;i++) + cipher[i] = plain[i]; + encrypt(cipher, 0); + + for(i=0;i<64;i++) + if(cipher[i] != answer[i]) + break; + fail = 0; + if(i != 64){ + printf(" Encrypt FAIL"); + fail++; totfails++; + } + + encrypt(cipher, 1); + + for(i=0;i<64;i++) + if(cipher[i] != plain[i]) + break; + if(i != 64){ + printf(" Decrypt FAIL"); + fail++; totfails++; + } + + if(fail == 0) + printf(" OK"); + printf("\n"); + } + good_bye(); +} +void +get8(cp) +char *cp; +{ + int i,j,t; + + for(i=0;i<8;i++){ + scanf("%2x",&t); + if(feof(stdin)) + good_bye(); + for(j=0; j<8 ; j++) { + *cp++ = (t & (0x01 << (7-j))) != 0; + } + } +} +void +put8(cp) +char *cp; +{ + int i,j,t; + + for(i=0;i<8;i++){ + t = 0; + for(j = 0; j<8; j++) + t = (t<<1) | *cp++; + printf("%02x", t); + } +} diff --git a/test/crypt/crypt.input b/test/crypt/crypt.input new file mode 100644 index 0000000..d843fa8 --- /dev/null +++ b/test/crypt/crypt.input @@ -0,0 +1,171 @@ +0101010101010101 95f8a5e5dd31d900 8000000000000000 +0101010101010101 dd7f121ca5015619 4000000000000000 +0101010101010101 2e8653104f3834ea 2000000000000000 +0101010101010101 4bd388ff6cd81d4f 1000000000000000 +0101010101010101 20b9e767b2fb1456 0800000000000000 +0101010101010101 55579380d77138ef 0400000000000000 +0101010101010101 6cc5defaaf04512f 0200000000000000 +0101010101010101 0d9f279ba5d87260 0100000000000000 +0101010101010101 d9031b0271bd5a0a 0080000000000000 +0101010101010101 424250b37c3dd951 0040000000000000 +0101010101010101 b8061b7ecd9a21e5 0020000000000000 +0101010101010101 f15d0f286b65bd28 0010000000000000 +0101010101010101 add0cc8d6e5deba1 0008000000000000 +0101010101010101 e6d5f82752ad63d1 0004000000000000 +0101010101010101 ecbfe3bd3f591a5e 0002000000000000 +0101010101010101 f356834379d165cd 0001000000000000 +0101010101010101 2b9f982f20037fa9 0000800000000000 +0101010101010101 889de068a16f0be6 0000400000000000 +0101010101010101 e19e275d846a1298 0000200000000000 +0101010101010101 329a8ed523d71aec 0000100000000000 +0101010101010101 e7fce22557d23c97 0000080000000000 +0101010101010101 12a9f5817ff2d65d 0000040000000000 +0101010101010101 a484c3ad38dc9c19 0000020000000000 +0101010101010101 fbe00a8a1ef8ad72 0000010000000000 +0101010101010101 750d079407521363 0000008000000000 +0101010101010101 64feed9c724c2faf 0000004000000000 +0101010101010101 f02b263b328e2b60 0000002000000000 +0101010101010101 9d64555a9a10b852 0000001000000000 +0101010101010101 d106ff0bed5255d7 0000000800000000 +0101010101010101 e1652c6b138c64a5 0000000400000000 +0101010101010101 e428581186ec8f46 0000000200000000 +0101010101010101 aeb5f5ede22d1a36 0000000100000000 +0101010101010101 e943d7568aec0c5c 0000000080000000 +0101010101010101 df98c8276f54b04b 0000000040000000 +0101010101010101 b160e4680f6c696f 0000000020000000 +0101010101010101 fa0752b07d9c4ab8 0000000010000000 +0101010101010101 ca3a2b036dbc8502 0000000008000000 +0101010101010101 5e0905517bb59bcf 0000000004000000 +0101010101010101 814eeb3b91d90726 0000000002000000 +0101010101010101 4d49db1532919c9f 0000000001000000 +0101010101010101 25eb5fc3f8cf0621 0000000000800000 +0101010101010101 ab6a20c0620d1c6f 0000000000400000 +0101010101010101 79e90dbc98f92cca 0000000000200000 +0101010101010101 866ecedd8072bb0e 0000000000100000 +0101010101010101 8b54536f2f3e64a8 0000000000080000 +0101010101010101 ea51d3975595b86b 0000000000040000 +0101010101010101 caffc6ac4542de31 0000000000020000 +0101010101010101 8dd45a2ddf90796c 0000000000010000 +0101010101010101 1029d55e880ec2d0 0000000000008000 +0101010101010101 5d86cb23639dbea9 0000000000004000 +0101010101010101 1d1ca853ae7c0c5f 0000000000002000 +0101010101010101 ce332329248f3228 0000000000001000 +0101010101010101 8405d1abe24fb942 0000000000000800 +0101010101010101 e643d78090ca4207 0000000000000400 +0101010101010101 48221b9937748a23 0000000000000200 +0101010101010101 dd7c0bbd61fafd54 0000000000000100 +0101010101010101 2fbc291a570db5c4 0000000000000080 +0101010101010101 e07c30d7e4e26e12 0000000000000040 +0101010101010101 0953e2258e8e90a1 0000000000000020 +0101010101010101 5b711bc4ceebf2ee 0000000000000010 +0101010101010101 cc083f1e6d9e85f6 0000000000000008 +0101010101010101 d2fd8867d50d2dfe 0000000000000004 +0101010101010101 06e7ea22ce92708f 0000000000000002 +0101010101010101 166b40b44aba4bd6 0000000000000001 +8001010101010101 0000000000000000 95a8d72813daa94d +4001010101010101 0000000000000000 0eec1487dd8c26d5 +2001010101010101 0000000000000000 7ad16ffb79c45926 +1001010101010101 0000000000000000 d3746294ca6a6cf3 +0801010101010101 0000000000000000 809f5f873c1fd761 +0401010101010101 0000000000000000 c02faffec989d1fc +0201010101010101 0000000000000000 4615aa1d33e72f10 +0180010101010101 0000000000000000 2055123350c00858 +0140010101010101 0000000000000000 df3b99d6577397c8 +0120010101010101 0000000000000000 31fe17369b5288c9 +0110010101010101 0000000000000000 dfdd3cc64dae1642 +0108010101010101 0000000000000000 178c83ce2b399d94 +0104010101010101 0000000000000000 50f636324a9b7f80 +0102010101010101 0000000000000000 a8468ee3bc18f06d +0101800101010101 0000000000000000 a2dc9e92fd3cde92 +0101400101010101 0000000000000000 cac09f797d031287 +0101200101010101 0000000000000000 90ba680b22aeb525 +0101100101010101 0000000000000000 ce7a24f350e280b6 +0101080101010101 0000000000000000 882bff0aa01a0b87 +0101040101010101 0000000000000000 25610288924511c2 +0101020101010101 0000000000000000 c71516c29c75d170 +0101018001010101 0000000000000000 5199c29a52c9f059 +0101014001010101 0000000000000000 c22f0a294a71f29f +0101012001010101 0000000000000000 ee371483714c02ea +0101011001010101 0000000000000000 a81fbd448f9e522f +0101010801010101 0000000000000000 4f644c92e192dfed +0101010401010101 0000000000000000 1afa9a66a6df92ae +0101010201010101 0000000000000000 b3c1cc715cb879d8 +0101010180010101 0000000000000000 19d032e64ab0bd8b +0101010140010101 0000000000000000 3cfaa7a7dc8720dc +0101010120010101 0000000000000000 b7265f7f447ac6f3 +0101010110010101 0000000000000000 9db73b3c0d163f54 +0101010108010101 0000000000000000 8181b65babf4a975 +0101010104010101 0000000000000000 93c9b64042eaa240 +0101010102010101 0000000000000000 5570530829705592 +0101010101800101 0000000000000000 8638809e878787a0 +0101010101400101 0000000000000000 41b9a79af79ac208 +0101010101200101 0000000000000000 7a9be42f2009a892 +0101010101100101 0000000000000000 29038d56ba6d2745 +0101010101080101 0000000000000000 5495c6abf1e5df51 +0101010101040101 0000000000000000 ae13dbd561488933 +0101010101020101 0000000000000000 024d1ffa8904e389 +0101010101018001 0000000000000000 d1399712f99bf02e +0101010101014001 0000000000000000 14c1d7c1cffec79e +0101010101012001 0000000000000000 1de5279dae3bed6f +0101010101011001 0000000000000000 e941a33f85501303 +0101010101010801 0000000000000000 da99dbbc9a03f379 +0101010101010401 0000000000000000 b7fc92f91d8e92e9 +0101010101010201 0000000000000000 ae8e5caa3ca04e85 +0101010101010180 0000000000000000 9cc62df43b6eed74 +0101010101010140 0000000000000000 d863dbb5c59a91a0 +0101010101010120 0000000000000000 a1ab2190545b91d7 +0101010101010110 0000000000000000 0875041e64c570f7 +0101010101010108 0000000000000000 5a594528bebef1cc +0101010101010104 0000000000000000 fcdb3291de21f0c0 +0101010101010102 0000000000000000 869efd7f9f265a09 +1046913489980131 0000000000000000 88d55e54f54c97b4 +1007103489988020 0000000000000000 0c0cc00c83ea48fd +10071034c8980120 0000000000000000 83bc8ef3a6570183 +1046103489988020 0000000000000000 df725dcad94ea2e9 +1086911519190101 0000000000000000 e652b53b550be8b0 +1086911519580101 0000000000000000 af527120c485cbb0 +5107b01519580101 0000000000000000 0f04ce393db926d5 +1007b01519190101 0000000000000000 c9f00ffc74079067 +3107915498080101 0000000000000000 7cfd82a593252b4e +3107919498080101 0000000000000000 cb49a2f9e91363e3 +10079115b9080140 0000000000000000 00b588be70d23f56 +3107911598080140 0000000000000000 406a9a6ab43399ae +1007d01589980101 0000000000000000 6cb773611dca9ada +9107911589980101 0000000000000000 67fd21c17dbb5d70 +9107d01589190101 0000000000000000 9592cb4110430787 +1007d01598980120 0000000000000000 a6b7ff68a318ddd3 +1007940498190101 0000000000000000 4d102196c914ca16 +0107910491190401 0000000000000000 2dfa9f4573594965 +0107910491190101 0000000000000000 b46604816c0e0774 +0107940491190401 0000000000000000 6e7e6221a4f34e87 +19079210981a0101 0000000000000000 aa85e74643233199 +1007911998190801 0000000000000000 2e5a19db4d1962d6 +10079119981a0801 0000000000000000 23a866a809d30894 +1007921098190101 0000000000000000 d812d961f017d320 +100791159819010b 0000000000000000 055605816e58608f +1004801598190101 0000000000000000 abd88e8b1b7716f1 +1004801598190102 0000000000000000 537ac95be69da1e1 +1004801598190108 0000000000000000 aed0f6ae3c25cdd8 +1002911598100104 0000000000000000 b3e35a5ee53e7b8d +1002911598190104 0000000000000000 61c79c71921a2ef8 +1002911598100201 0000000000000000 e2f5728f0995013c +1002911698100101 0000000000000000 1aeac39a61f0a464 +7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b +0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271 +07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a +3849674c2602319e 51454b582ddf440a 7178876e01f19b2a +04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095 +0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b +0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09 +43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a +07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f +04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088 +37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77 +1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a +584023641aba6176 004bd6ef09176062 88bf0db6d70dee56 +025816164629b007 480d39006ee762f2 a1f9915541020b56 +49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556 +4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac +49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a +018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41 +1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793 diff --git a/test/crypt/crypt.out.good b/test/crypt/crypt.out.good new file mode 100644 index 0000000..073ab2b --- /dev/null +++ b/test/crypt/crypt.out.good @@ -0,0 +1,172 @@ + K: 0101010101010101 P: 95f8a5e5dd31d900 C: 8000000000000000 OK + K: 0101010101010101 P: dd7f121ca5015619 C: 4000000000000000 OK + K: 0101010101010101 P: 2e8653104f3834ea C: 2000000000000000 OK + K: 0101010101010101 P: 4bd388ff6cd81d4f C: 1000000000000000 OK + K: 0101010101010101 P: 20b9e767b2fb1456 C: 0800000000000000 OK + K: 0101010101010101 P: 55579380d77138ef C: 0400000000000000 OK + K: 0101010101010101 P: 6cc5defaaf04512f C: 0200000000000000 OK + K: 0101010101010101 P: 0d9f279ba5d87260 C: 0100000000000000 OK + K: 0101010101010101 P: d9031b0271bd5a0a C: 0080000000000000 OK + K: 0101010101010101 P: 424250b37c3dd951 C: 0040000000000000 OK + K: 0101010101010101 P: b8061b7ecd9a21e5 C: 0020000000000000 OK + K: 0101010101010101 P: f15d0f286b65bd28 C: 0010000000000000 OK + K: 0101010101010101 P: add0cc8d6e5deba1 C: 0008000000000000 OK + K: 0101010101010101 P: e6d5f82752ad63d1 C: 0004000000000000 OK + K: 0101010101010101 P: ecbfe3bd3f591a5e C: 0002000000000000 OK + K: 0101010101010101 P: f356834379d165cd C: 0001000000000000 OK + K: 0101010101010101 P: 2b9f982f20037fa9 C: 0000800000000000 OK + K: 0101010101010101 P: 889de068a16f0be6 C: 0000400000000000 OK + K: 0101010101010101 P: e19e275d846a1298 C: 0000200000000000 OK + K: 0101010101010101 P: 329a8ed523d71aec C: 0000100000000000 OK + K: 0101010101010101 P: e7fce22557d23c97 C: 0000080000000000 OK + K: 0101010101010101 P: 12a9f5817ff2d65d C: 0000040000000000 OK + K: 0101010101010101 P: a484c3ad38dc9c19 C: 0000020000000000 OK + K: 0101010101010101 P: fbe00a8a1ef8ad72 C: 0000010000000000 OK + K: 0101010101010101 P: 750d079407521363 C: 0000008000000000 OK + K: 0101010101010101 P: 64feed9c724c2faf C: 0000004000000000 OK + K: 0101010101010101 P: f02b263b328e2b60 C: 0000002000000000 OK + K: 0101010101010101 P: 9d64555a9a10b852 C: 0000001000000000 OK + K: 0101010101010101 P: d106ff0bed5255d7 C: 0000000800000000 OK + K: 0101010101010101 P: e1652c6b138c64a5 C: 0000000400000000 OK + K: 0101010101010101 P: e428581186ec8f46 C: 0000000200000000 OK + K: 0101010101010101 P: aeb5f5ede22d1a36 C: 0000000100000000 OK + K: 0101010101010101 P: e943d7568aec0c5c C: 0000000080000000 OK + K: 0101010101010101 P: df98c8276f54b04b C: 0000000040000000 OK + K: 0101010101010101 P: b160e4680f6c696f C: 0000000020000000 OK + K: 0101010101010101 P: fa0752b07d9c4ab8 C: 0000000010000000 OK + K: 0101010101010101 P: ca3a2b036dbc8502 C: 0000000008000000 OK + K: 0101010101010101 P: 5e0905517bb59bcf C: 0000000004000000 OK + K: 0101010101010101 P: 814eeb3b91d90726 C: 0000000002000000 OK + K: 0101010101010101 P: 4d49db1532919c9f C: 0000000001000000 OK + K: 0101010101010101 P: 25eb5fc3f8cf0621 C: 0000000000800000 OK + K: 0101010101010101 P: ab6a20c0620d1c6f C: 0000000000400000 OK + K: 0101010101010101 P: 79e90dbc98f92cca C: 0000000000200000 OK + K: 0101010101010101 P: 866ecedd8072bb0e C: 0000000000100000 OK + K: 0101010101010101 P: 8b54536f2f3e64a8 C: 0000000000080000 OK + K: 0101010101010101 P: ea51d3975595b86b C: 0000000000040000 OK + K: 0101010101010101 P: caffc6ac4542de31 C: 0000000000020000 OK + K: 0101010101010101 P: 8dd45a2ddf90796c C: 0000000000010000 OK + K: 0101010101010101 P: 1029d55e880ec2d0 C: 0000000000008000 OK + K: 0101010101010101 P: 5d86cb23639dbea9 C: 0000000000004000 OK + K: 0101010101010101 P: 1d1ca853ae7c0c5f C: 0000000000002000 OK + K: 0101010101010101 P: ce332329248f3228 C: 0000000000001000 OK + K: 0101010101010101 P: 8405d1abe24fb942 C: 0000000000000800 OK + K: 0101010101010101 P: e643d78090ca4207 C: 0000000000000400 OK + K: 0101010101010101 P: 48221b9937748a23 C: 0000000000000200 OK + K: 0101010101010101 P: dd7c0bbd61fafd54 C: 0000000000000100 OK + K: 0101010101010101 P: 2fbc291a570db5c4 C: 0000000000000080 OK + K: 0101010101010101 P: e07c30d7e4e26e12 C: 0000000000000040 OK + K: 0101010101010101 P: 0953e2258e8e90a1 C: 0000000000000020 OK + K: 0101010101010101 P: 5b711bc4ceebf2ee C: 0000000000000010 OK + K: 0101010101010101 P: cc083f1e6d9e85f6 C: 0000000000000008 OK + K: 0101010101010101 P: d2fd8867d50d2dfe C: 0000000000000004 OK + K: 0101010101010101 P: 06e7ea22ce92708f C: 0000000000000002 OK + K: 0101010101010101 P: 166b40b44aba4bd6 C: 0000000000000001 OK + K: 8001010101010101 P: 0000000000000000 C: 95a8d72813daa94d OK + K: 4001010101010101 P: 0000000000000000 C: 0eec1487dd8c26d5 OK + K: 2001010101010101 P: 0000000000000000 C: 7ad16ffb79c45926 OK + K: 1001010101010101 P: 0000000000000000 C: d3746294ca6a6cf3 OK + K: 0801010101010101 P: 0000000000000000 C: 809f5f873c1fd761 OK + K: 0401010101010101 P: 0000000000000000 C: c02faffec989d1fc OK + K: 0201010101010101 P: 0000000000000000 C: 4615aa1d33e72f10 OK + K: 0180010101010101 P: 0000000000000000 C: 2055123350c00858 OK + K: 0140010101010101 P: 0000000000000000 C: df3b99d6577397c8 OK + K: 0120010101010101 P: 0000000000000000 C: 31fe17369b5288c9 OK + K: 0110010101010101 P: 0000000000000000 C: dfdd3cc64dae1642 OK + K: 0108010101010101 P: 0000000000000000 C: 178c83ce2b399d94 OK + K: 0104010101010101 P: 0000000000000000 C: 50f636324a9b7f80 OK + K: 0102010101010101 P: 0000000000000000 C: a8468ee3bc18f06d OK + K: 0101800101010101 P: 0000000000000000 C: a2dc9e92fd3cde92 OK + K: 0101400101010101 P: 0000000000000000 C: cac09f797d031287 OK + K: 0101200101010101 P: 0000000000000000 C: 90ba680b22aeb525 OK + K: 0101100101010101 P: 0000000000000000 C: ce7a24f350e280b6 OK + K: 0101080101010101 P: 0000000000000000 C: 882bff0aa01a0b87 OK + K: 0101040101010101 P: 0000000000000000 C: 25610288924511c2 OK + K: 0101020101010101 P: 0000000000000000 C: c71516c29c75d170 OK + K: 0101018001010101 P: 0000000000000000 C: 5199c29a52c9f059 OK + K: 0101014001010101 P: 0000000000000000 C: c22f0a294a71f29f OK + K: 0101012001010101 P: 0000000000000000 C: ee371483714c02ea OK + K: 0101011001010101 P: 0000000000000000 C: a81fbd448f9e522f OK + K: 0101010801010101 P: 0000000000000000 C: 4f644c92e192dfed OK + K: 0101010401010101 P: 0000000000000000 C: 1afa9a66a6df92ae OK + K: 0101010201010101 P: 0000000000000000 C: b3c1cc715cb879d8 OK + K: 0101010180010101 P: 0000000000000000 C: 19d032e64ab0bd8b OK + K: 0101010140010101 P: 0000000000000000 C: 3cfaa7a7dc8720dc OK + K: 0101010120010101 P: 0000000000000000 C: b7265f7f447ac6f3 OK + K: 0101010110010101 P: 0000000000000000 C: 9db73b3c0d163f54 OK + K: 0101010108010101 P: 0000000000000000 C: 8181b65babf4a975 OK + K: 0101010104010101 P: 0000000000000000 C: 93c9b64042eaa240 OK + K: 0101010102010101 P: 0000000000000000 C: 5570530829705592 OK + K: 0101010101800101 P: 0000000000000000 C: 8638809e878787a0 OK + K: 0101010101400101 P: 0000000000000000 C: 41b9a79af79ac208 OK + K: 0101010101200101 P: 0000000000000000 C: 7a9be42f2009a892 OK + K: 0101010101100101 P: 0000000000000000 C: 29038d56ba6d2745 OK + K: 0101010101080101 P: 0000000000000000 C: 5495c6abf1e5df51 OK + K: 0101010101040101 P: 0000000000000000 C: ae13dbd561488933 OK + K: 0101010101020101 P: 0000000000000000 C: 024d1ffa8904e389 OK + K: 0101010101018001 P: 0000000000000000 C: d1399712f99bf02e OK + K: 0101010101014001 P: 0000000000000000 C: 14c1d7c1cffec79e OK + K: 0101010101012001 P: 0000000000000000 C: 1de5279dae3bed6f OK + K: 0101010101011001 P: 0000000000000000 C: e941a33f85501303 OK + K: 0101010101010801 P: 0000000000000000 C: da99dbbc9a03f379 OK + K: 0101010101010401 P: 0000000000000000 C: b7fc92f91d8e92e9 OK + K: 0101010101010201 P: 0000000000000000 C: ae8e5caa3ca04e85 OK + K: 0101010101010180 P: 0000000000000000 C: 9cc62df43b6eed74 OK + K: 0101010101010140 P: 0000000000000000 C: d863dbb5c59a91a0 OK + K: 0101010101010120 P: 0000000000000000 C: a1ab2190545b91d7 OK + K: 0101010101010110 P: 0000000000000000 C: 0875041e64c570f7 OK + K: 0101010101010108 P: 0000000000000000 C: 5a594528bebef1cc OK + K: 0101010101010104 P: 0000000000000000 C: fcdb3291de21f0c0 OK + K: 0101010101010102 P: 0000000000000000 C: 869efd7f9f265a09 OK + K: 1046913489980131 P: 0000000000000000 C: 88d55e54f54c97b4 OK + K: 1007103489988020 P: 0000000000000000 C: 0c0cc00c83ea48fd OK + K: 10071034c8980120 P: 0000000000000000 C: 83bc8ef3a6570183 OK + K: 1046103489988020 P: 0000000000000000 C: df725dcad94ea2e9 OK + K: 1086911519190101 P: 0000000000000000 C: e652b53b550be8b0 OK + K: 1086911519580101 P: 0000000000000000 C: af527120c485cbb0 OK + K: 5107b01519580101 P: 0000000000000000 C: 0f04ce393db926d5 OK + K: 1007b01519190101 P: 0000000000000000 C: c9f00ffc74079067 OK + K: 3107915498080101 P: 0000000000000000 C: 7cfd82a593252b4e OK + K: 3107919498080101 P: 0000000000000000 C: cb49a2f9e91363e3 OK + K: 10079115b9080140 P: 0000000000000000 C: 00b588be70d23f56 OK + K: 3107911598080140 P: 0000000000000000 C: 406a9a6ab43399ae OK + K: 1007d01589980101 P: 0000000000000000 C: 6cb773611dca9ada OK + K: 9107911589980101 P: 0000000000000000 C: 67fd21c17dbb5d70 OK + K: 9107d01589190101 P: 0000000000000000 C: 9592cb4110430787 OK + K: 1007d01598980120 P: 0000000000000000 C: a6b7ff68a318ddd3 OK + K: 1007940498190101 P: 0000000000000000 C: 4d102196c914ca16 OK + K: 0107910491190401 P: 0000000000000000 C: 2dfa9f4573594965 OK + K: 0107910491190101 P: 0000000000000000 C: b46604816c0e0774 OK + K: 0107940491190401 P: 0000000000000000 C: 6e7e6221a4f34e87 OK + K: 19079210981a0101 P: 0000000000000000 C: aa85e74643233199 OK + K: 1007911998190801 P: 0000000000000000 C: 2e5a19db4d1962d6 OK + K: 10079119981a0801 P: 0000000000000000 C: 23a866a809d30894 OK + K: 1007921098190101 P: 0000000000000000 C: d812d961f017d320 OK + K: 100791159819010b P: 0000000000000000 C: 055605816e58608f OK + K: 1004801598190101 P: 0000000000000000 C: abd88e8b1b7716f1 OK + K: 1004801598190102 P: 0000000000000000 C: 537ac95be69da1e1 OK + K: 1004801598190108 P: 0000000000000000 C: aed0f6ae3c25cdd8 OK + K: 1002911598100104 P: 0000000000000000 C: b3e35a5ee53e7b8d OK + K: 1002911598190104 P: 0000000000000000 C: 61c79c71921a2ef8 OK + K: 1002911598100201 P: 0000000000000000 C: e2f5728f0995013c OK + K: 1002911698100101 P: 0000000000000000 C: 1aeac39a61f0a464 OK + K: 7ca110454a1a6e57 P: 01a1d6d039776742 C: 690f5b0d9a26939b OK + K: 0131d9619dc1376e P: 5cd54ca83def57da C: 7a389d10354bd271 OK + K: 07a1133e4a0b2686 P: 0248d43806f67172 C: 868ebb51cab4599a OK + K: 3849674c2602319e P: 51454b582ddf440a C: 7178876e01f19b2a OK + K: 04b915ba43feb5b6 P: 42fd443059577fa2 C: af37fb421f8c4095 OK + K: 0113b970fd34f2ce P: 059b5e0851cf143a C: 86a560f10ec6d85b OK + K: 0170f175468fb5e6 P: 0756d8e0774761d2 C: 0cd3da020021dc09 OK + K: 43297fad38e373fe P: 762514b829bf486a C: ea676b2cb7db2b7a OK + K: 07a7137045da2a16 P: 3bdd119049372802 C: dfd64a815caf1a0f OK + K: 04689104c2fd3b2f P: 26955f6835af609a C: 5c513c9c4886c088 OK + K: 37d06bb516cb7546 P: 164d5e404f275232 C: 0a2aeeae3ff4ab77 OK + K: 1f08260d1ac2465e P: 6b056e18759f5cca C: ef1bf03e5dfa575a OK + K: 584023641aba6176 P: 004bd6ef09176062 C: 88bf0db6d70dee56 OK + K: 025816164629b007 P: 480d39006ee762f2 C: a1f9915541020b56 OK + K: 49793ebc79b3258f P: 437540c8698f3cfa C: 6fbf1cafcffd0556 OK + K: 4fb05e1515ab73a7 P: 072d43a077075292 C: 2f22e49bab7ca1ac OK + K: 49e95d6d4ca229bf P: 02fe55778117f12a C: 5a6b612cc26cce4a OK + K: 018310dc409b26d6 P: 1d9d5c5018f728c2 C: 5f4c038ed12b2e41 OK + K: 1c587f1c13924fef P: 305532286d6f295a C: 63fac0d034d9f793 OK +Passed DES validation suite diff --git a/test/crypt/md5c-test.c b/test/crypt/md5c-test.c new file mode 100644 index 0000000..3c61540 --- /dev/null +++ b/test/crypt/md5c-test.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + const char salt[] = "$1$saltstring"; + char *cp; + + cp = crypt ("Hello world!", salt); + if (strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp)) { + fprintf(stderr, "Failed md5 crypt test!\n"); + return EXIT_FAILURE; + } + fprintf(stderr, "Passed md5 crypt test!\n"); + return EXIT_SUCCESS; +} diff --git a/test/ctype/Makefile b/test/ctype/Makefile new file mode 100644 index 0000000..d2b7bc5 --- /dev/null +++ b/test/ctype/Makefile @@ -0,0 +1,6 @@ +# uClibc ctype tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS := ctype + +include ../Test.mak diff --git a/test/ctype/ctype.c b/test/ctype/ctype.c new file mode 100644 index 0000000..352b2d2 --- /dev/null +++ b/test/ctype/ctype.c @@ -0,0 +1,248 @@ +/* vi: set sw=4 ts=4: */ +/* + * Test application for functions defined in ctype.h + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include "../testsuite.h" + + +int main( int argc, char **argv) +{ + int i, c; + + + init_testsuite("Testing functions defined in ctype.h\n"); + + /* isalnum() */ + { + int buffer[]={ '1', '4', 'a', 'z', 'A', 'Z', '5', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isalnum(c)!=0); + } + } + { + int buffer[]={ 2, 128, 254, '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isalnum(c)==0); + } + } + + + + /* isalpha() */ + { + int buffer[]={ 'a', 'z', 'A', 'Z', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isalpha(c)!=0); + } + } + { + int buffer[]={ 2, 63, 128, 254, '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isalpha(c)==0); + } + } + + + + /* isascii() */ + { + int buffer[]={ 'a', 'z', 'A', 'Z', '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isascii(c)!=0); + } + } + { + int buffer[]={ 128, 254, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isascii(c)==0); + } + } + + + /* iscntrl() */ + { + int buffer[]={ 0x7F, 6, '\t', '\n', 0x7F, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( iscntrl(c)!=0); + } + } + { + int buffer[]={ 63, 128, 254, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( iscntrl(c)==0); + } + } + + + /* isdigit() */ + { + int buffer[]={ '1', '5', '7', '9', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isdigit(c)!=0); + } + } + { + int buffer[]={ 2, 'a', 'z', 'A', 'Z', 63, 128, 254, '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isdigit(c)==0); + } + } + + + + /* isgraph() */ + { + int buffer[]={ ')', '~', '9', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isgraph(c)!=0); + } + } + { + int buffer[]={ 9, ' ', '\t', '\n', 200, 0x7F, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isgraph(c)==0); + } + } + + + /* islower() */ + { + int buffer[]={ 'a', 'g', 'z', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( islower(c)!=0); + } + } + { + int buffer[]={ 9, 'A', 'Z', 128, 254, ' ', '\t', '\n', 0x7F, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( islower(c)==0); + } + } + + + /* isprint() */ + { + int buffer[]={ ' ', ')', '~', '9', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isprint(c)!=0); + } + } + { + int buffer[]={ '\b', '\t', '\n', 9, 128, 254, 200, 0x7F, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isprint(c)==0); + } + } + + + /* ispunct() */ + { + int buffer[]={ '.', '#', '@', ';', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( ispunct(c)!=0); + } + } + { + int buffer[]={ 2, 'a', 'Z', '1', 128, 254, '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( ispunct(c)==0); + } + } + + + /* isspace() */ + { + int buffer[]={ ' ', '\t', '\r', '\v', '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isspace(c)!=0); + } + } + { + int buffer[]={ 2, 'a', 'Z', '1', 128, 254, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isspace(c)==0); + } + } + + + /* isupper() */ + { + int buffer[]={ 'A', 'G', 'Z', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isupper(c)!=0); + } + } + { + int buffer[]={ 2, 'a', 'z', '1', 128, 254, -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isupper(c)==0); + } + } + + + + /* isxdigit() */ + { + int buffer[]={ 'f', 'A', '1', '8', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isxdigit(c)!=0); + } + } + { + int buffer[]={ 2, 'g', 'G', 'x', '\n', -1}; + for(i=0; buffer[i]!=-1; i++) { + c = buffer[i]; + TEST( isxdigit(c)==0); + } + } + + + /* tolower() */ + c='A'; + TEST_NUMERIC( tolower(c), 'a'); + c='a'; + TEST_NUMERIC( tolower(c), 'a'); + c='#'; + TEST_NUMERIC( tolower(c), c); + + /* toupper() */ + c='a'; + TEST_NUMERIC( toupper(c), 'A'); + c='A'; + TEST_NUMERIC( toupper(c), 'A'); + c='#'; + TEST_NUMERIC( toupper(c), c); + + exit(0); +} diff --git a/test/dlopen/Makefile b/test/dlopen/Makefile new file mode 100644 index 0000000..b59c3e2 --- /dev/null +++ b/test/dlopen/Makefile @@ -0,0 +1,40 @@ +# uClibc dlopen tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +# rules need a little love to work with glibc ... +export UCLIBC_ONLY := 1 + +TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr + +include ../Test.mak + +CFLAGS_dltest := -DLIBNAME="\"./libtest.so\"" +CFLAGS_dltest2 := -DLIBNAME="\"./libtest3.so\"" + +LDFLAGS_dlstatic := -ldl +LDFLAGS_dltest := -ldl -lpthread +LDFLAGS_dltest2 := -ldl -lpthread +LDFLAGS_dlundef := -ldl +LDFLAGS_dlafk := -ldl ./libafk.so -Wl,-rpath,. +LDFLAGS_test1 := -ldl +LDFLAGS_test2 := -ldl +LDFLAGS_test3 := -ldl ./libtest1.so ./libtest2.so -Wl,-rpath,. +LDFLAGS_dladdr := -ldl + +DEBUG_LIBS := X +WRAPPER := env $(DEBUG_LIBS)=all LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" + +dltest: libtest.so +dltest2: libtest3.so +dlstatic: libstatic.so +dlundef: libundef.so +dlafk: libafk.so +libafk.so: libafk-temp.so +LDFLAGS_libafk.so := ./libafk-temp.so -Wl,-rpath,. +test1: libtest1.so +test2: libtest1.so libtest2.so +test3: libtest1.so libtest2.so +libtest1.so: libtest2.so +LDFLAGS_libtest1.so := ./libtest2.so -Wl,-rpath,. +LDFLAGS_libtest2.so := -Wl,-rpath,. +LDFLAGS_libtest3.so := -lpthread -Wl,-rpath,. diff --git a/test/dlopen/dladdr.c b/test/dlopen/dladdr.c new file mode 100644 index 0000000..b64c000 --- /dev/null +++ b/test/dlopen/dladdr.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + Dl_info info; + int res = 0; + + memset(&info, '\0', sizeof(Dl_info)); + res = dladdr((void *)1, &info); + if (res != 0) { + fprintf(stderr, "dladdr() should fail\n"); + fprintf(stderr, "dli_fname = %s\n", info.dli_fname); + fprintf(stderr, "dli_fbase = 0x%08x\n", (unsigned int)info.dli_fbase); + fprintf(stderr, "dli_sname = %s\n", info.dli_sname); + fprintf(stderr, "dli_saddr = 0x%08x\n", (unsigned int)info.dli_saddr); + exit(1); + } + + fprintf(stderr, "dladdr() failed as expected\n"); + return EXIT_SUCCESS; +} + diff --git a/test/dlopen/dlafk.c b/test/dlopen/dlafk.c new file mode 100644 index 0000000..2eac4af --- /dev/null +++ b/test/dlopen/dlafk.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define LIBNAME "libafk.so" + +#define LIBAFK "libafk-temp.so" +#define LIBAFK_BAK ".libafk-temp.so.temp" + +int main(int argc, char **argv) +{ + void *handle; + + if (rename(LIBAFK, LIBAFK_BAK)) { + fprintf(stderr, "Unable to rename %s: %s\n", LIBAFK, strerror(errno)); + return EXIT_FAILURE; + } + + handle = dlopen(LIBNAME, RTLD_NOW); + if (!handle) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + return EXIT_FAILURE; + } + + if (rename(LIBAFK_BAK, LIBAFK)) { + fprintf(stderr, "Unable to rename %s: %s\n", LIBAFK_BAK, strerror(errno)); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/test/dlopen/dlstatic.c b/test/dlopen/dlstatic.c new file mode 100644 index 0000000..57c8c5d --- /dev/null +++ b/test/dlopen/dlstatic.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +#define LIBNAME "libstatic.so" + +int load_and_test(void) +{ + void *handle; + int (*mystatic)(void); + + handle = dlopen(LIBNAME, RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + return 1; + } + + mystatic = dlsym(handle, "static_test"); + if (mystatic == NULL) { + fprintf(stderr, "Could not locate symbol 'static_test': %s\n", dlerror()); + return 1; + } + + if (!mystatic()) { + fprintf(stderr, "mystatic() failed: static vars were not setup properly\n"); + return 1; + } + + dlclose(handle); + + return 0; +} + +int main(int argc, char **argv) +{ + int count = 5; + while (count-- > 0) + if (load_and_test()) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} diff --git a/test/dlopen/dltest.c b/test/dlopen/dltest.c new file mode 100644 index 0000000..6bec6e0 --- /dev/null +++ b/test/dlopen/dltest.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int ret = EXIT_SUCCESS; + void *handle; + void (*mydltest)(void *value1, void *value2); + char *error; + uint32_t *value1, *value2; + + handle = dlopen (LIBNAME, RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + exit(1); + } + + mydltest = dlsym(handle, "dltest"); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error); + exit(1); + } + + mydltest(&value1, &value2); + printf("dltest: __pthread_once=%p\n", value1); + printf("dltest: pthread_self=%p\n", value2); + if (value1 == value2) { + ret = EXIT_FAILURE; + printf("dltest: values should NOT be equal Weak values resolved incorrectly!\n"); + } else { + printf("dltest: weak symbols resoved correctly.\n"); + } + + dlclose(handle); + + return ret; +} + diff --git a/test/dlopen/dltest2.c b/test/dlopen/dltest2.c new file mode 100644 index 0000000..127b3b5 --- /dev/null +++ b/test/dlopen/dltest2.c @@ -0,0 +1 @@ +#include "dltest.c" diff --git a/test/dlopen/dlundef.c b/test/dlopen/dlundef.c new file mode 100644 index 0000000..cefd933 --- /dev/null +++ b/test/dlopen/dlundef.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +#define LIBNAME "libundef.so" + +int main(int argc, char **argv) +{ + void *handle; + int (*myundefined)(void); + + handle = dlopen(LIBNAME, RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror()); + return EXIT_FAILURE; + } + + myundefined = dlsym(handle, "__booga_booga_you_cant_touch_this__"); + if (myundefined != NULL) { + fprintf(stderr, "dlsym() found a symbol that does not exist!\n"); + return EXIT_FAILURE; + } + + dlclose(handle); + + return EXIT_SUCCESS; +} diff --git a/test/dlopen/libafk-temp.c b/test/dlopen/libafk-temp.c new file mode 100644 index 0000000..39b58df --- /dev/null +++ b/test/dlopen/libafk-temp.c @@ -0,0 +1 @@ +/* the actual contents doesnt matter */ diff --git a/test/dlopen/libafk.c b/test/dlopen/libafk.c new file mode 100644 index 0000000..39b58df --- /dev/null +++ b/test/dlopen/libafk.c @@ -0,0 +1 @@ +/* the actual contents doesnt matter */ diff --git a/test/dlopen/libstatic.c b/test/dlopen/libstatic.c new file mode 100644 index 0000000..bf44c3c --- /dev/null +++ b/test/dlopen/libstatic.c @@ -0,0 +1,15 @@ +#include + +static int global_static = -1; + +int static_test(void) +{ + static int local_static = -2; + + if (global_static != -1) + printf("FAIL: global_static is not -1\n"); + if (local_static != -2) + printf("FAIL: local_static is not -2\n"); + + return (global_static == -1 && local_static == -2); +} diff --git a/test/dlopen/libtest.c b/test/dlopen/libtest.c new file mode 100644 index 0000000..a306e4b --- /dev/null +++ b/test/dlopen/libtest.c @@ -0,0 +1,13 @@ +#include +#include +#include + +extern int __pthread_once(void); + +void dltest(uint32_t **value1, uint32_t **value2); +void dltest(uint32_t **value1, uint32_t **value2) +{ + *value1 = (uint32_t *) __pthread_once; + *value2 = (uint32_t *) pthread_self; +} + diff --git a/test/dlopen/libtest1.c b/test/dlopen/libtest1.c new file mode 100644 index 0000000..a2f7dcd --- /dev/null +++ b/test/dlopen/libtest1.c @@ -0,0 +1,40 @@ +#include + +extern int libtest2_func(const char *s); + +void __attribute__((constructor)) libtest1_ctor(void); +void libtest1_ctor(void) +{ + printf("libtest1: constructor!\n"); +} + +void __attribute__((destructor)) libtest1_dtor(void); +void libtest1_dtor(void) +{ + printf("libtest1: destructor!\n"); +} + +void __attribute__((weak)) function1(void); +void function1(void) +{ + printf("libtest1: I am weak function1!\n"); +} + +void function2(void); +void function2(void) +{ + printf("libtest1: I am function2!\n"); +} + +int dltest(const char *s); +int dltest(const char *s) +{ + printf( "libtest1: function1 = %p\n" + "libtest1: function2 = %p\n", + function1, function2); + function1(); + function2(); + return(libtest2_func(s)); +} + + diff --git a/test/dlopen/libtest2.c b/test/dlopen/libtest2.c new file mode 100644 index 0000000..5261506 --- /dev/null +++ b/test/dlopen/libtest2.c @@ -0,0 +1,38 @@ +#include +#include + +void __attribute__((constructor)) libtest2_ctor(void); +void libtest2_ctor(void) +{ + printf("libtest2: constructor!\n"); +} + +void __attribute__((destructor)) libtest2_dtor(void); +void libtest2_dtor(void) +{ + printf("libtest2: destructor!\n"); +} + +void function1(void); +void function1(void) +{ + printf("libtest2: I am function1!\n"); +} + +void __attribute__((weak)) function2(void); +void function2(void) +{ + printf("libtest2: I am weak function2!\n"); +} + + +int libtest2_func(const char *s); +int libtest2_func(const char *s) +{ + printf( "libtest2: function1 = %p\n" + "libtest2: function2 = %p\n", + function1, function2); + function1(); + function2(); + return 0; +} diff --git a/test/dlopen/libtest3.c b/test/dlopen/libtest3.c new file mode 100644 index 0000000..1d4bd7e --- /dev/null +++ b/test/dlopen/libtest3.c @@ -0,0 +1 @@ +#include "libtest.c" diff --git a/test/dlopen/libundef.c b/test/dlopen/libundef.c new file mode 100644 index 0000000..39b58df --- /dev/null +++ b/test/dlopen/libundef.c @@ -0,0 +1 @@ +/* the actual contents doesnt matter */ diff --git a/test/dlopen/test1.c b/test/dlopen/test1.c new file mode 100644 index 0000000..c13eb30 --- /dev/null +++ b/test/dlopen/test1.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#ifdef __UCLIBC__ +extern void _dlinfo(void); +#endif + +int main(int argc, char **argv) { + void *handle; + int (*mydltest)(const char *s); + char *error; + + handle = dlopen ("./libtest1.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./libtest1.so: %s\n", dlerror()); + exit(1); + } + + mydltest = dlsym(handle, "dltest"); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error); + exit(1); + } + + mydltest("hello world!"); + + dlclose(handle); + + return EXIT_SUCCESS; +} + diff --git a/test/dlopen/test2.c b/test/dlopen/test2.c new file mode 100644 index 0000000..d8428f7 --- /dev/null +++ b/test/dlopen/test2.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#ifdef __UCLIBC__ +extern void _dlinfo(void); +#endif + +int main(int argc, char **argv) { + void *handle; + int (*mydltest)(const char *s); + char *error; + + handle = dlopen ("./libtest2.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./libtest2.so: %s\n", dlerror()); + exit(1); + } + + handle = dlopen ("./libtest1.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "Could not open ./libtest1.so: %s\n", dlerror()); + exit(1); + } + + mydltest = dlsym(handle, "dltest"); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error); + exit(1); + } + + mydltest("hello world!"); + + dlclose(handle); + + return EXIT_SUCCESS; +} + diff --git a/test/dlopen/test3.c b/test/dlopen/test3.c new file mode 100644 index 0000000..2f2dfc6 --- /dev/null +++ b/test/dlopen/test3.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +extern int dltest(const char *s); + +int main(int argc, char **argv) +{ + dltest("hello world!"); + return EXIT_SUCCESS; +} + diff --git a/test/inet/Makefile b/test/inet/Makefile new file mode 100644 index 0000000..91927e4 --- /dev/null +++ b/test/inet/Makefile @@ -0,0 +1,4 @@ +# uClibc inet tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak diff --git a/test/inet/bug-if1.c b/test/inet/bug-if1.c new file mode 100644 index 0000000..6bcd175 --- /dev/null +++ b/test/inet/bug-if1.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2004. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +static int +do_test (void) +{ + char buf[IF_NAMESIZE]; + /* Index 0 is always invalid (see RFC 3493). */ + char *cp = if_indextoname (0, buf); + if (cp != NULL) + { + printf ("invalid index returned result \"%s\"\n", cp); + return 1; + } + else if (errno != ENXIO) + { + int err = errno; + char errbuf1[256]; + char errbuf2[256]; + + printf ("errno = %d (%s), expected %d (%s)\n", + err, strerror_r (err, errbuf1, sizeof (errbuf1)), + ENXIO, strerror_r (ENXIO, errbuf2, sizeof (errbuf2))); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/inet/gethost_r-align.c b/test/inet/gethost_r-align.c new file mode 100644 index 0000000..53ce93a --- /dev/null +++ b/test/inet/gethost_r-align.c @@ -0,0 +1,50 @@ +/* Since the reentrant gethost functions take a char * buffer, + * we have to make sure they internally do not assume alignment. + * The actual return values are not relevant. If the test fails, + * it'll be due to an alignment exception which means the test + * app is killed by the kernel. + */ + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + size_t i; + char buf[1024]; + in_addr_t addr; + + addr = inet_addr("127.0.0.1"); + + for (i = 0; i < sizeof(size_t) * 2; ++i) { + struct hostent hent, *hentres; + int ret, herr; + + printf("Testing misalignment of %2zi bytes: ", i); + + memset(&hent, 0x00, sizeof(hent)); + ret = gethostent_r(&hent, buf + i, sizeof(buf) - i, &hentres, &herr); + printf("%sgethostent_r() ", (ret ? "!!!" : "")); + + memset(&hent, 0x00, sizeof(hent)); + ret = gethostbyname_r("localhost", &hent, buf + i, sizeof(buf) - i, &hentres, &herr); + printf("%sgethostbyname_r() ", (ret ? "!!!" : "")); + + memset(&hent, 0x00, sizeof(hent)); + ret = gethostbyname2_r("localhost", AF_INET, &hent, buf + i, sizeof(buf) - i, &hentres, &herr); + printf("%sgethostbyname2_r() ", (ret ? "!!!" : "")); + + memset(&hent, 0x00, sizeof(hent)); + ret = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf + i, sizeof(buf) - i, &hentres, &herr); + printf("%sgethostbyaddr_r() ", (ret ? "!!!" : "")); + + puts("OK!"); + } + + return 0; +} diff --git a/test/inet/if_nameindex.c b/test/inet/if_nameindex.c new file mode 100644 index 0000000..126c5ba --- /dev/null +++ b/test/inet/if_nameindex.c @@ -0,0 +1,61 @@ +/* if_nameindex.c: test the if_nameindex() function + * + * Copyright (C) 2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +static char ifname[IF_NAMESIZE]; + +static void test_if_nameindex(void) +{ + size_t i; + struct if_nameindex *ret; + + ret = if_nameindex(); + + if (ret == NULL) { + perror("if_nameindex()"); + exit(1); + } + + printf("--- if_nameindex()\n"); + for (i=0; ret[i].if_name; ++i) + printf("%i: %s\n", ret[i].if_index, ret[i].if_name); + + if_freenameindex(ret); +} + +static void test_if_indextoname(void) +{ + if (if_indextoname(1, ifname) == NULL) { + perror("if_nameindex()"); + exit(1); + } + + printf("if_indextoname(1) = %s\n", ifname); +} + +static void test_if_nametoindex(void) +{ + int ifindex = if_nametoindex(ifname); + + if (ifindex == 0) { + perror("if_nametoindex()"); + exit(1); + } + + printf("if_nametoindex(%s) = %i\n", ifname, ifindex); +} + +int main(void) +{ + test_if_nameindex(); + test_if_indextoname(); + test_if_nametoindex(); + return 0; +} diff --git a/test/inet/tst-aton.c b/test/inet/tst-aton.c new file mode 100644 index 0000000..3e945f1 --- /dev/null +++ b/test/inet/tst-aton.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +/* Note: uClibc only supports the standard notation 'a.b.c.d' */ + +static struct tests +{ + const char *input; + int valid; + uint32_t result; +} tests[] = +{ + { "", 0, 0 }, + { "-1", 0, 0 }, +/* + { "256", 1, 0x00000100 }, +*/ + { "256.", 0, 0 }, + { "256a", 0, 0 }, +/* + { "0x100", 1, 0x00000100 }, + { "0200.0x123456", 1, 0x80123456 }, + { "0300.0x89123456.", 0 ,0 }, + { "0100.-0xffff0000", 0, 0 }, + { "0.0xffffff", 1, 0x00ffffff }, + { "0.0x1000000", 0, 0 }, + { "0377.16777215", 1, 0xffffffff }, + { "0377.16777216", 0, 0 }, + { "0x87.077777777", 1, 0x87ffffff }, + { "0x87.0100000000", 0, 0 }, + { "0.1.3", 1, 0x00010003 }, +*/ + { "0.256.3", 0, 0 }, + { "256.1.3", 0, 0 }, +/* + { "0.1.0x10000", 0, 0 }, + { "0.1.0xffff", 1, 0x0001ffff }, +*/ + { "0.1a.3", 0, 0 }, + { "0.1.a3", 0, 0 }, + { "1.2.3.4", 1, 0x01020304 }, + { "0400.2.3.4", 0, 0 }, + { "1.0x100.3.4", 0, 0 }, + { "1.2.256.4", 0, 0 }, + { "1.2.3.0x100", 0, 0 }, + { "323543357756889", 0, 0 }, + { "10.1.2.3.4", 0, 0}, +}; + + +int +main (int argc, char *argv[]) +{ + int result = 0; + size_t cnt; + + for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) + { + struct in_addr addr; + + if ((int) inet_aton (tests[cnt].input, &addr) != tests[cnt].valid) + { + if (tests[cnt].valid) + printf ("\"%s\" not seen as valid IP address\n", tests[cnt].input); + else + printf ("\"%s\" seen as valid IP address\n", tests[cnt].input); + result = 1; + } + else if (tests[cnt].valid && addr.s_addr != ntohl (tests[cnt].result)) + { + printf ("\"%s\" not converted correctly: is %08x, should be %08x\n", + tests[cnt].input, addr.s_addr, tests[cnt].result); + result = 1; + } + } + + return result; +} diff --git a/test/inet/tst-ethers-line.c b/test/inet/tst-ethers-line.c new file mode 100644 index 0000000..19cf2fb --- /dev/null +++ b/test/inet/tst-ethers-line.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +/* glibc 2.4 has no ETHER_FILE_NAME, host compile fails without this */ +#ifndef ETHER_FILE_NAME +#define ETHER_FILE_NAME "/etc/ethers" +#endif + +#define ETHER_LINE_LEN 256 + +/* This test requires /etc/ethers to exist + * and to have nonzero length + */ + +int main(void) +{ + struct ether_addr addr; + char hostname[ETHER_LINE_LEN]; + int fd, i; + const char *ethers; + struct stat statb; + + if ((fd = open(ETHER_FILE_NAME, O_RDONLY)) == -1) { + perror ("Cannot open file"); + exit(1); + } + + if (fstat(fd, &statb)) { + perror("Stat failed"); + exit(1); + } + ethers = mmap(NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0); + + if (ethers == MAP_FAILED) { + perror("File mapping failed"); + exit(1); + } + + ether_line(ethers, &addr, hostname); + + for (i = 0; i < 6; i++) { + printf("%02x", addr.ether_addr_octet[i]); + if (i < 5) + printf(":"); + } + printf(" %s\n", hostname); + + return 0; +} diff --git a/test/inet/tst-ethers.c b/test/inet/tst-ethers.c new file mode 100644 index 0000000..6b6e10c --- /dev/null +++ b/test/inet/tst-ethers.c @@ -0,0 +1,33 @@ +#include +#include + +#define ETHER_LINE_LEN 256 + +/* This test requires /etc/ethers to exist + * and to have host "teeth". For example: + * 00:11:22:33:44:55 teeth + */ + +int main(void) +{ + struct ether_addr addr; + char host[ETHER_LINE_LEN]; + int i; + int res = ether_hostton("teeth", &addr); + + if (res) + return 1; + + for (i = 0; i < 6; i++) { + printf("%02x", addr.ether_addr_octet[i]); + if (i < 5) + printf(":"); + } + + res = ether_ntohost(host, &addr); + if (res) + return 1; + printf(" %s\n", host); + + return 0; +} diff --git a/test/inet/tst-network.c b/test/inet/tst-network.c new file mode 100644 index 0000000..2598637 --- /dev/null +++ b/test/inet/tst-network.c @@ -0,0 +1,105 @@ +/* Test for inet_network. + Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +struct +{ + const char *network; + uint32_t number; +} tests [] = +{ + {"1.0.0.0", 0x1000000}, + {"1.0.0", 0x10000}, + {"1.0", 0x100}, + {"1", 0x1}, + {"192.168.0.0", 0xC0A80000}, + /* Now some invalid addresses. */ + {"141.30.225.2800", INADDR_NONE}, + {"141.76.1.1.1", INADDR_NONE}, + {"141.76.1.11.", INADDR_NONE}, + {"1410", INADDR_NONE}, + {"1.1410", INADDR_NONE}, + {"1.1410.", INADDR_NONE}, + {"1.1410", INADDR_NONE}, + {"141.76.1111", INADDR_NONE}, + {"141.76.1111.", INADDR_NONE}, + {"1.1.1.257", INADDR_NONE}, + /* Now some from BSD */ + {"0x12", 0x00000012}, + {"127.1", 0x00007f01}, + {"127.1.2.3", 0x7f010203}, + {"0x123456", INADDR_NONE}, + {"0x12.0x34", 0x00001234}, + {"0x12.0x345", INADDR_NONE}, + {"1.2.3.4.5", INADDR_NONE}, + {"1..3.4", INADDR_NONE}, + {".", INADDR_NONE}, + {"1.", INADDR_NONE}, + {".1", INADDR_NONE}, + {"x", INADDR_NONE}, + {"0x", INADDR_NONE}, + {"0", 0x00000000}, + {"0x0", 0x00000000}, + {"01.02.07.077", 0x0102073f}, + {"0x1.23.045.0", 0x01172500}, + {"", INADDR_NONE}, + {" ", INADDR_NONE}, + {"bar", INADDR_NONE}, + {"1.2bar", INADDR_NONE}, + {"1.", INADDR_NONE}, + {"ÊÃÕËÅÎ", INADDR_NONE}, + {"255.255.255.255", INADDR_NONE}, + {"x", INADDR_NONE}, + {"0X12", 0x00000012}, + {"078", INADDR_NONE}, + {"1 bar", INADDR_NONE}, + {"127.0xfff", INADDR_NONE}, +}; + + +int +main (void) +{ + int errors = 0; + size_t i; + uint32_t res; + + for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + { + printf ("Testing: %s\n", tests[i].network); + res = inet_network (tests[i].network); + + if (res != tests[i].number) + { + ++errors; + printf ("Test failed for inet_network (\"%s\"):\n", + tests[i].network); + printf ("Expected return value %u (0x%x) but got %u (0x%x).\n", + tests[i].number, tests[i].number, res, res); + } + + } + + return errors != 0; +} diff --git a/test/inet/tst-ntoa.c b/test/inet/tst-ntoa.c new file mode 100644 index 0000000..9be91eb --- /dev/null +++ b/test/inet/tst-ntoa.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + + +static int +test (unsigned int inaddr, const char *expected) +{ + struct in_addr addr; + char *res; + int fail; + + addr.s_addr = htonl (inaddr); + res = inet_ntoa (addr); + fail = strcmp (res, expected); + + printf ("%#010x -> \"%s\" -> %s%s\n", inaddr, res, + fail ? "fail, expected" : "ok", fail ? expected : ""); + + return fail; +} + + +int +main (void) +{ + int result = 0; + + result |= test (INADDR_LOOPBACK, "127.0.0.1"); + result |= test (INADDR_BROADCAST, "255.255.255.255"); + result |= test (INADDR_ANY, "0.0.0.0"); + result |= test (0xc0060746, "192.6.7.70"); + + return result; +} diff --git a/test/locale-mbwc/Makefile b/test/locale-mbwc/Makefile new file mode 100644 index 0000000..8f5a2db --- /dev/null +++ b/test/locale-mbwc/Makefile @@ -0,0 +1,29 @@ +# uClibc locale tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# tst_mbtowc tst_strcoll tst_strfmon tst_strxfrm \ + +TESTS := tst_iswalnum tst_iswalpha tst_iswcntrl \ + tst_iswctype tst_iswdigit tst_iswgraph \ + tst_iswlower tst_iswprint tst_iswpunct \ + tst_iswspace tst_iswupper tst_iswxdigit \ + tst_mblen tst_mbrlen tst_mbrtowc tst_mbsrtowcs \ + tst_mbstowcs tst_mbtowc tst_strcoll tst_strxfrm \ + tst_swscanf tst_towctrans tst_towlower \ + tst_towupper tst_wcrtomb tst_wcscat tst_wcschr \ + tst_wcscmp tst_wcscoll tst_wcscpy tst_wcscspn \ + tst_wcslen tst_wcsncat tst_wcsncmp tst_wcsncpy \ + tst_wcspbrk tst_wcsrtombs tst_wcsspn tst_wcsstr \ + tst_wcstod tst_wcstok tst_wcstombs tst_wcswidth \ + tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \ + tst_wctype tst_wcwidth tst_strfmon + + +# NOTE: For now disabled tst_strfmon to avoid build failure. +TESTS_DISABLED := tst_strfmon + +include ../Test.mak + +DODIFF_rint := 1 + +EXTRA_CFLAGS := -D__USE_GNU -fno-builtin + diff --git a/test/locale-mbwc/dat_isw-funcs.h b/test/locale-mbwc/dat_isw-funcs.h new file mode 100644 index 0000000..70aecb0 --- /dev/null +++ b/test/locale-mbwc/dat_isw-funcs.h @@ -0,0 +1,37 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_isw-funcs.h + * + * ISW*: int isw* (wint_t wc); + */ + +#include +#include +#include +#include "tst_types.h" +#include "tgn_locdef.h" + +#define TST_ISW_LOC(FUNC, func) \ + TST_ISW## FUNC tst_isw## func ##_loc [] + +#define TST_ISW_REC(locale, func) \ + { Tisw## func, TST_LOC_## locale }, + +/* + * NOTE: + * Set ret_flg = 1, when a return value is expected to be 0 (FALSE). + * Set ret_flg = 0, when a return value is expected to be non-zero (TRUE). + * + * Since the functions return *non*-zero value for TRUE, can't + * compare an actual return value with an expected return value. + * Set the ret_flg=0 for TRUE cases and the tst_isw*() will check + * the non-zero value. + * + * { { WEOF }, { 0,1,0 } }, + * | | + * | ret_val: an expected return value + * ret_flg: if 1, compare an actual return value with the + * ret_val; if 0, the test program + * checks the actual return value. + */ diff --git a/test/locale-mbwc/dat_iswalnum.c b/test/locale-mbwc/dat_iswalnum.c new file mode 100644 index 0000000..5093703 --- /dev/null +++ b/test/locale-mbwc/dat_iswalnum.c @@ -0,0 +1,196 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswalnum.c + * + * ISW*: int iswalnum (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (ALNUM, alnum) = { + + { TST_ISW_REC (de, alnum) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* last element */ + } + }, + { TST_ISW_REC (de_UTF8, alnum) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* last element */ + } + }, + { TST_ISW_REC (enUS, alnum) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,0,0 } }, + { { 0x0039 }, { 0,0,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,0,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,0,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* last element */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, alnum) +#else + { TST_ISW_REC (ja_UTF8, alnum) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ +#else + { { 0x3029 }, { 0,0,0 } }, /* Hangzhou NUM9 */ +#endif + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ +#else + { { 0x3041 }, { 0,0,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,0,0 } }, /* HIRAGANA u" */ +#endif + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ +#ifdef SHOJI_IS_RIGHT + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ +#else + { { 0x309E }, { 0,0,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,0,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,0,0 } }, /* KATAKANA wo" */ +#endif + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ +#ifdef SHOJI_IS_RIGHT + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ +#else + { { 0x30FE }, { 0,0,0 } }, /* KATAKANA ITERATION */ +#endif + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#else + { { 0x4E00 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#endif + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,0,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,0,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ +#else + { { 0xFF66 }, { 0,0,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,0,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,0,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,0,0 } }, /* HALF KATA MI */ +#endif + { .is_last = 1 } /* last element */ + } + }, + { TST_ISW_REC (end, alnum) } +}; diff --git a/test/locale-mbwc/dat_iswalpha.c b/test/locale-mbwc/dat_iswalpha.c new file mode 100644 index 0000000..c2b59fb --- /dev/null +++ b/test/locale-mbwc/dat_iswalpha.c @@ -0,0 +1,169 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswalpha.c + * + * ISW*: int iswalpha (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (ALPHA, alpha) = { + + { TST_ISW_REC (de, alpha) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* last element */ + } + }, + { TST_ISW_REC (enUS, alpha) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,0,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,0,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, /* 20 */ + { .is_last = 1 } /* last element */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, alpha) +#else + { TST_ISW_REC (ja_UTF8, alpha) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ +#else + { { 0x3029 }, { 0,0,0 } }, /* Hangzhou NUM9 */ +#endif + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ +#else + { { 0x3041 }, { 0,0,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,0,0 } }, /* HIRAGANA u" */ +#endif + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ +#ifdef SHOJI_IS_RIGHT + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ +#else + { { 0x309E }, { 0,0,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,0,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,0,0 } }, /* KATAKANA wo" */ +#endif + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ +#ifdef SHOJI_IS_RIGHT + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ +#else + { { 0x30FE }, { 0,0,0 } }, /* KATAKANA ITERATION */ +#endif + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#else + { { 0x4E00 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#endif + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ +#else + { { 0xFF19 }, { 0,0,0 } }, /* FULL 9 */ +#endif + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,0,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ +#else + { { 0xFF66 }, { 0,0,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,0,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,0,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,0,0 } }, /* HALF KATA MI */ +#endif + { .is_last = 1 } /* last element */ + } + }, + { TST_ISW_REC (end, alpha) } +}; diff --git a/test/locale-mbwc/dat_iswcntrl.c b/test/locale-mbwc/dat_iswcntrl.c new file mode 100644 index 0000000..e6ec685 --- /dev/null +++ b/test/locale-mbwc/dat_iswcntrl.c @@ -0,0 +1,125 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswcntrl.c + * + * ISW*: int iswcntrl (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (CNTRL, cntrl) = { + + { TST_ISW_REC (de, cntrl) + { + { { 0x0080 }, { 0,0,0 } }, /* CTRL */ + { { 0x009F }, { 0,0,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, cntrl) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,0,0 } }, + { { 0x001F }, { 0,0,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,1,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,1,0 } }, + { { 0x007A }, { 0,1,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,0,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, cntrl) +#else + { TST_ISW_REC (ja_UTF8, cntrl) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC(end, cntrl) } +}; diff --git a/test/locale-mbwc/dat_iswctype.c b/test/locale-mbwc/dat_iswctype.c new file mode 100644 index 0000000..6448b32 --- /dev/null +++ b/test/locale-mbwc/dat_iswctype.c @@ -0,0 +1,667 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswctype.c + * + * ISWCTYPE: int iswctype( wint_t wc, wctype_t charclass ); + */ + +#include +#include +#include +#include "tst_types.h" +#include "tgn_locdef.h" + +/* + * NOTE: + * Set ret_flg = 1, when a return value is expected to be 0 (FALSE). + * Set ret_flg = 0, when a return value is expected to be non-zero (TRUE). + * + * Since the functions return *non*-zero value for TRUE, can't + * compare an actual return value with an expected return value. + * Set the ret_flg=0 for TRUE cases and the tst_isw*() will check + * the non-zero value. + * + * { { WEOF }, { 0,1,0 } }, + * | | + * | ret_val: an expected return value + * ret_flg: if 1, compare an actual return value with the + * ret_val; if 0, the test program checks + * the actual return value. + */ + +TST_ISWCTYPE tst_iswctype_loc [] = { + { + { Tiswctype, TST_LOC_de }, + { + { { 0x009F, "alnum" }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0, "alnum" }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1, "alnum" }, { 0,1,0 } }, /* UD ! */ + { { 0x00B1, "alnum" }, { 0,1,0 } }, /* +- sign */ + { { 0x00B3, "alnum" }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4, "alnum" }, { 0,1,0 } }, /* ACUTE */ + { { 0x00BB, "alnum" }, { 0,1,0 } }, /* >> */ + { { 0x00BE, "alnum" }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF, "alnum" }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0, "alnum" }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6, "alnum" }, { 0,0,0 } }, /* O dia */ + { { 0x00D7, "alnum" }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8, "alnum" }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF, "alnum" }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0, "alnum" }, { 0,0,0 } }, /* a grave */ + { { 0x00F6, "alnum" }, { 0,0,0 } }, /* o dia */ + { { 0x00F7, "alnum" }, { 0,1,0 } }, /* division */ + { { 0x00F8, "alnum" }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF, "alnum" }, { 0,0,0 } }, /* y dia */ + { { 0x0080, "alpha" }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0, "alpha" }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1, "alpha" }, { 0,1,0 } }, /* UD ! */ + { { 0x00B1, "alpha" }, { 0,1,0 } }, /* +- sign */ + { { 0x00B4, "alpha" }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8, "alpha" }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9, "alpha" }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB, "alpha" }, { 0,1,0 } }, /* >> */ + { { 0x00BE, "alpha" }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF, "alpha" }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0, "alpha" }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6, "alpha" }, { 0,0,0 } }, /* O dia */ + { { 0x00D7, "alpha" }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8, "alpha" }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF, "alpha" }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0, "alpha" }, { 0,0,0 } }, /* a grave */ + { { 0x00F6, "alpha" }, { 0,0,0 } }, /* o dia */ + { { 0x00F7, "alpha" }, { 0,1,0 } }, /* division */ + { { 0x00F8, "alpha" }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF, "alpha" }, { 0,0,0 } }, /* y dia */ + { { 0x0080, "cntrl" }, { 0,0,0 } }, /* CTRL */ + { { 0x009F, "cntrl" }, { 0,0,0 } }, /* CTRL */ + { { 0x00A0, "cntrl" }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00F6, "cntrl" }, { 0,1,0 } }, /* o dia */ + { { 0x00FF, "cntrl" }, { 0,1,0 } }, /* y dia */ + { { 0x00B9, "digit" }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BE, "digit" }, { 0,1,0 } }, /* 3/4 */ + { { 0x009F, "graph" }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0, "graph" }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0, "graph" }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1, "graph" }, { 0,0,0 } }, /* UD ! */ + { { 0x00B1, "graph" }, { 0,0,0 } }, /* +- sign */ + { { 0x00B3, "graph" }, { 0,0,0 } }, /* SUP 3 */ + { { 0x00B4, "graph" }, { 0,0,0 } }, /* ACUTE */ + { { 0x00BB, "graph" }, { 0,0,0 } }, /* >> */ + { { 0x00BE, "graph" }, { 0,0,0 } }, /* 3/4 */ + { { 0x00C0, "graph" }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6, "graph" }, { 0,0,0 } }, /* O dia */ + { { 0x00D7, "graph" }, { 0,0,0 } }, /* multipl. */ + { { 0x00D8, "graph" }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF, "graph" }, { 0,0,0 } }, /* small Sh */ + { { 0x00F7, "graph" }, { 0,0,0 } }, /* division */ + { { 0x00F8, "graph" }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF, "graph" }, { 0,0,0 } }, /* y dia */ + { { 0x009F, "print" }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0, "print" }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0, "print" }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1, "print" }, { 0,0,0 } }, /* UD ! */ + { { 0x00B1, "print" }, { 0,0,0 } }, /* +- sign */ + { { 0x00B4, "print" }, { 0,0,0 } }, /* ACUTE */ + { { 0x00B8, "print" }, { 0,0,0 } }, /* CEDILLA */ + { { 0x00B9, "print" }, { 0,0,0 } }, /* SUP 1 */ + { { 0x00BB, "print" }, { 0,0,0 } }, /* >> */ + { { 0x00BE, "print" }, { 0,0,0 } }, /* 3/4 */ + { { 0x00C0, "print" }, { 0,0,0 } }, /* A Grave */ + { { 0x00DF, "print" }, { 0,0,0 } }, /* small Sh */ + { { 0x00F6, "print" }, { 0,0,0 } }, /* o dia */ + { { 0x00F7, "print" }, { 0,0,0 } }, /* division */ + { { 0x00F8, "print" }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF, "print" }, { 0,0,0 } }, /* y dia */ + { { 0x009F, "punct" }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0, "punct" }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0, "punct" }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1, "punct" }, { 0,0,0 } }, /* UD ! */ + { { 0x00B0, "punct" }, { 0,0,0 } }, /* Degree */ + { { 0x00B1, "punct" }, { 0,0,0 } }, /* +- sign */ + { { 0x00B2, "punct" }, { 0,0,0 } }, /* SUP 2 */ + { { 0x00B3, "punct" }, { 0,0,0 } }, /* SUP 3 */ + { { 0x00B4, "punct" }, { 0,0,0 } }, /* ACUTE */ + { { 0x00B8, "punct" }, { 0,0,0 } }, /* CEDILLA */ + { { 0x00B9, "punct" }, { 0,0,0 } }, /* SUP 1 */ + { { 0x00BB, "punct" }, { 0,0,0 } }, /* >> */ + { { 0x00BC, "punct" }, { 0,0,0 } }, /* 1/4 */ + { { 0x00BD, "punct" }, { 0,0,0 } }, /* 1/2 */ + { { 0x00BE, "punct" }, { 0,0,0 } }, /* 3/4 */ + { { 0x00BF, "punct" }, { 0,0,0 } }, /* UD ? */ + { { 0x00C0, "punct" }, { 0,1,0 } }, /* A Grave */ + { { 0x00D7, "punct" }, { 0,0,0 } }, /* multipl. */ + { { 0x00DF, "punct" }, { 0,1,0 } }, /* small Sh */ + { { 0x00F6, "punct" }, { 0,1,0 } }, /* o dia */ + { { 0x00F7, "punct" }, { 0,0,0 } }, /* division */ + { { 0x00FF, "punct" }, { 0,1,0 } }, /* y dia */ + { { 0x009F, "space" }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0, "space" }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1, "space" }, { 0,1,0 } }, /* UD ! */ + { { 0x00B1, "space" }, { 0,1,0 } }, /* +- sign */ + { { 0x00F8, "space" }, { 0,1,0 } }, /* o stroke */ + { { 0x00B3, "lower" }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B8, "lower" }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00BE, "lower" }, { 0,1,0 } }, /* 3/4 */ + { { 0x00C0, "lower" }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6, "lower" }, { 0,1,0 } }, /* O dia */ + { { 0x00D8, "lower" }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF, "lower" }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0, "lower" }, { 0,0,0 } }, /* a grave */ + { { 0x00F6, "lower" }, { 0,0,0 } }, /* o dia */ + { { 0x00F7, "lower" }, { 0,1,0 } }, /* division */ + { { 0x00F8, "lower" }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF, "lower" }, { 0,0,0 } }, /* y dia */ + { { 0x00B4, "upper" }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8, "upper" }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9, "upper" }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BE, "upper" }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF, "upper" }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0, "upper" }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6, "upper" }, { 0,0,0 } }, /* O dia */ + { { 0x00D7, "upper" }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8, "upper" }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF, "upper" }, { 0,1,0 } }, /* small Sh */ + { { 0x00FF, "upper" }, { 0,1,0 } }, /* y dia */ + { { 0x00B9, "xdigit" }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BC, "xdigit" }, { 0,1,0 } }, /* 1/4 */ + { .is_last = 1 } + } + }, + { + { Tiswctype, TST_LOC_enUS }, + { + { { WEOF, "alnum" }, { 0,1,0 } }, + { { 0x0000, "alnum" }, { 0,1,0 } }, + { { 0x001F, "alnum" }, { 0,1,0 } }, + { { 0x0020, "alnum" }, { 0,1,0 } }, + { { 0x0021, "alnum" }, { 0,1,0 } }, + { { 0x002F, "alnum" }, { 0,1,0 } }, + { { 0x0030, "alnum" }, { 0,0,0 } }, + { { 0x0039, "alnum" }, { 0,0,0 } }, + { { 0x003A, "alnum" }, { 0,1,0 } }, + { { 0x0040, "alnum" }, { 0,1,0 } }, + { { 0x0041, "alnum" }, { 0,0,0 } }, + { { 0x005A, "alnum" }, { 0,0,0 } }, + { { 0x005B, "alnum" }, { 0,1,0 } }, + { { 0x0060, "alnum" }, { 0,1,0 } }, + { { 0x0061, "alnum" }, { 0,0,0 } }, + { { 0x007A, "alnum" }, { 0,0,0 } }, + { { 0x007B, "alnum" }, { 0,1,0 } }, + { { 0x007E, "alnum" }, { 0,1,0 } }, + { { 0x007F, "alnum" }, { 0,1,0 } }, + { { 0x0080, "alnum" }, { 0,1,0 } }, + { { 0x0000, "alpha" }, { 0,1,0 } }, + { { 0x001F, "alpha" }, { 0,1,0 } }, + { { 0x0020, "alpha" }, { 0,1,0 } }, + { { 0x0021, "alpha" }, { 0,1,0 } }, + { { 0x002F, "alpha" }, { 0,1,0 } }, + { { 0x0030, "alpha" }, { 0,1,0 } }, + { { 0x0039, "alpha" }, { 0,1,0 } }, + { { 0x003A, "alpha" }, { 0,1,0 } }, + { { 0x0040, "alpha" }, { 0,1,0 } }, + { { 0x0041, "alpha" }, { 0,0,0 } }, + { { 0x005A, "alpha" }, { 0,0,0 } }, + { { 0x005B, "alpha" }, { 0,1,0 } }, + { { 0x0060, "alpha" }, { 0,1,0 } }, + { { 0x0061, "alpha" }, { 0,0,0 } }, + { { 0x007A, "alpha" }, { 0,0,0 } }, + { { 0x007B, "alpha" }, { 0,1,0 } }, + { { 0x007E, "alpha" }, { 0,1,0 } }, + { { 0x007F, "alpha" }, { 0,1,0 } }, + { { 0x0080, "alpha" }, { 0,1,0 } }, + { { 0x0009, "blank" }, { 0,0,0 } }, + { { 0x000B, "blank" }, { 0,1,0 } }, + { { 0x0020, "blank" }, { 0,0,0 } }, + { { 0x0000, "cntrl" }, { 0,0,0 } }, + { { 0x001F, "cntrl" }, { 0,0,0 } }, + { { 0x0020, "cntrl" }, { 0,1,0 } }, + { { 0x0021, "cntrl" }, { 0,1,0 } }, + { { 0x002F, "cntrl" }, { 0,1,0 } }, + { { 0x0030, "cntrl" }, { 0,1,0 } }, + { { 0x0039, "cntrl" }, { 0,1,0 } }, + { { 0x003A, "cntrl" }, { 0,1,0 } }, + { { 0x0040, "cntrl" }, { 0,1,0 } }, + { { 0x0041, "cntrl" }, { 0,1,0 } }, + { { 0x005A, "cntrl" }, { 0,1,0 } }, + { { 0x005B, "cntrl" }, { 0,1,0 } }, + { { 0x0060, "cntrl" }, { 0,1,0 } }, + { { 0x0061, "cntrl" }, { 0,1,0 } }, + { { 0x007A, "cntrl" }, { 0,1,0 } }, + { { 0x007B, "cntrl" }, { 0,1,0 } }, + { { 0x007E, "cntrl" }, { 0,1,0 } }, + { { 0x007F, "cntrl" }, { 0,0,0 } }, + { { 0x0080, "cntrl" }, { 0,0,0 } }, + { { 0x0000, "digit" }, { 0,1,0 } }, + { { 0x001F, "digit" }, { 0,1,0 } }, + { { 0x0020, "digit" }, { 0,1,0 } }, + { { 0x0021, "digit" }, { 0,1,0 } }, + { { 0x002F, "digit" }, { 0,1,0 } }, + { { 0x0030, "digit" }, { 0,0,0 } }, + { { 0x0039, "digit" }, { 0,0,0 } }, + { { 0x003A, "digit" }, { 0,1,0 } }, + { { 0x0040, "digit" }, { 0,1,0 } }, + { { 0x0041, "digit" }, { 0,1,0 } }, + { { 0x005A, "digit" }, { 0,1,0 } }, + { { 0x005B, "digit" }, { 0,1,0 } }, + { { 0x0060, "digit" }, { 0,1,0 } }, + { { 0x0061, "digit" }, { 0,1,0 } }, + { { 0x007A, "digit" }, { 0,1,0 } }, + { { 0x007B, "digit" }, { 0,1,0 } }, + { { 0x007E, "digit" }, { 0,1,0 } }, + { { 0x007F, "digit" }, { 0,1,0 } }, + { { 0x0080, "digit" }, { 0,1,0 } }, + { { 0x0000, "graph" }, { 0,1,0 } }, + { { 0x001F, "graph" }, { 0,1,0 } }, + { { 0x0020, "graph" }, { 0,1,0 } }, + { { 0x0021, "graph" }, { 0,0,0 } }, + { { 0x002F, "graph" }, { 0,0,0 } }, + { { 0x0030, "graph" }, { 0,0,0 } }, + { { 0x0039, "graph" }, { 0,0,0 } }, + { { 0x003A, "graph" }, { 0,0,0 } }, + { { 0x0040, "graph" }, { 0,0,0 } }, + { { 0x0041, "graph" }, { 0,0,0 } }, + { { 0x005A, "graph" }, { 0,0,0 } }, + { { 0x005B, "graph" }, { 0,0,0 } }, + { { 0x0060, "graph" }, { 0,0,0 } }, + { { 0x0061, "graph" }, { 0,0,0 } }, + { { 0x007A, "graph" }, { 0,0,0 } }, + { { 0x007B, "graph" }, { 0,0,0 } }, + { { 0x007E, "graph" }, { 0,0,0 } }, + { { 0x007F, "graph" }, { 0,1,0 } }, + { { 0x0080, "graph" }, { 0,1,0 } }, + { { 0x0000, "print" }, { 0,1,0 } }, + { { 0x001F, "print" }, { 0,1,0 } }, + { { 0x0020, "print" }, { 0,0,0 } }, + { { 0x0021, "print" }, { 0,0,0 } }, + { { 0x002F, "print" }, { 0,0,0 } }, + { { 0x0030, "print" }, { 0,0,0 } }, + { { 0x0039, "print" }, { 0,0,0 } }, + { { 0x003A, "print" }, { 0,0,0 } }, + { { 0x0040, "print" }, { 0,0,0 } }, + { { 0x0041, "print" }, { 0,0,0 } }, + { { 0x005A, "print" }, { 0,0,0 } }, + { { 0x005B, "print" }, { 0,0,0 } }, + { { 0x0060, "print" }, { 0,0,0 } }, + { { 0x0061, "print" }, { 0,0,0 } }, + { { 0x007A, "print" }, { 0,0,0 } }, + { { 0x007B, "print" }, { 0,0,0 } }, + { { 0x007E, "print" }, { 0,0,0 } }, + { { 0x007F, "print" }, { 0,1,0 } }, + { { 0x0080, "print" }, { 0,1,0 } }, + { { 0x0000, "punct" }, { 0,1,0 } }, + { { 0x001F, "punct" }, { 0,1,0 } }, + { { 0x0020, "punct" }, { 0,1,0 } }, + { { 0x0021, "punct" }, { 0,0,0 } }, + { { 0x002F, "punct" }, { 0,0,0 } }, + { { 0x0030, "punct" }, { 0,1,0 } }, + { { 0x0039, "punct" }, { 0,1,0 } }, + { { 0x003A, "punct" }, { 0,0,0 } }, + { { 0x0040, "punct" }, { 0,0,0 } }, + { { 0x0041, "punct" }, { 0,1,0 } }, + { { 0x005A, "punct" }, { 0,1,0 } }, + { { 0x005B, "punct" }, { 0,0,0 } }, + { { 0x0060, "punct" }, { 0,0,0 } }, + { { 0x0061, "punct" }, { 0,1,0 } }, + { { 0x007A, "punct" }, { 0,1,0 } }, + { { 0x007B, "punct" }, { 0,0,0 } }, + { { 0x007E, "punct" }, { 0,0,0 } }, + { { 0x007F, "punct" }, { 0,1,0 } }, + { { 0x0080, "punct" }, { 0,1,0 } }, + { { 0x0000, "space" }, { 0,1,0 } }, + { { 0x001F, "space" }, { 0,1,0 } }, + { { 0x0020, "space" }, { 0,0,0 } }, + { { 0x0021, "space" }, { 0,1,0 } }, + { { 0x002F, "space" }, { 0,1,0 } }, + { { 0x007E, "space" }, { 0,1,0 } }, + { { 0x007F, "space" }, { 0,1,0 } }, + { { 0x0080, "space" }, { 0,1,0 } }, + { { 0x0000, "lower" }, { 0,1,0 } }, + { { 0x001F, "lower" }, { 0,1,0 } }, + { { 0x0020, "lower" }, { 0,1,0 } }, + { { 0x0021, "lower" }, { 0,1,0 } }, + { { 0x002F, "lower" }, { 0,1,0 } }, + { { 0x0030, "lower" }, { 0,1,0 } }, + { { 0x0039, "lower" }, { 0,1,0 } }, + { { 0x003A, "lower" }, { 0,1,0 } }, + { { 0x0040, "lower" }, { 0,1,0 } }, + { { 0x0041, "lower" }, { 0,1,0 } }, + { { 0x005A, "lower" }, { 0,1,0 } }, + { { 0x005B, "lower" }, { 0,1,0 } }, + { { 0x0060, "lower" }, { 0,1,0 } }, + { { 0x0061, "lower" }, { 0,0,0 } }, + { { 0x007A, "lower" }, { 0,0,0 } }, + { { 0x007B, "lower" }, { 0,1,0 } }, + { { 0x007E, "lower" }, { 0,1,0 } }, + { { 0x007F, "lower" }, { 0,1,0 } }, + { { 0x0080, "lower" }, { 0,1,0 } }, + { { 0x0000, "upper" }, { 0,1,0 } }, + { { 0x001F, "upper" }, { 0,1,0 } }, + { { 0x0020, "upper" }, { 0,1,0 } }, + { { 0x0021, "upper" }, { 0,1,0 } }, + { { 0x002F, "upper" }, { 0,1,0 } }, + { { 0x0030, "upper" }, { 0,1,0 } }, + { { 0x0039, "upper" }, { 0,1,0 } }, + { { 0x003A, "upper" }, { 0,1,0 } }, + { { 0x0040, "upper" }, { 0,1,0 } }, + { { 0x0041, "upper" }, { 0,0,0 } }, + { { 0x005A, "upper" }, { 0,0,0 } }, + { { 0x005B, "upper" }, { 0,1,0 } }, + { { 0x0060, "upper" }, { 0,1,0 } }, + { { 0x0061, "upper" }, { 0,1,0 } }, + { { 0x007A, "upper" }, { 0,1,0 } }, + { { 0x007B, "upper" }, { 0,1,0 } }, + { { 0x007E, "upper" }, { 0,1,0 } }, + { { 0x007F, "upper" }, { 0,1,0 } }, + { { 0x0080, "upper" }, { 0,1,0 } }, + { { 0x0000, "xdigit" }, { 0,1,0 } }, + { { 0x001F, "xdigit" }, { 0,1,0 } }, + { { 0x0020, "xdigit" }, { 0,1,0 } }, + { { 0x0021, "xdigit" }, { 0,1,0 } }, + { { 0x002F, "xdigit" }, { 0,1,0 } }, + { { 0x0030, "xdigit" }, { 0,0,0 } }, + { { 0x0039, "xdigit" }, { 0,0,0 } }, + { { 0x003A, "xdigit" }, { 0,1,0 } }, + { { 0x0040, "xdigit" }, { 0,1,0 } }, + { { 0x0041, "xdigit" }, { 0,0,0 } }, + { { 0x005A, "xdigit" }, { 0,1,0 } }, + { { 0x005B, "xdigit" }, { 0,1,0 } }, + { { 0x0060, "xdigit" }, { 0,1,0 } }, + { { 0x0061, "xdigit" }, { 0,0,0 } }, + { { 0x007A, "xdigit" }, { 0,1,0 } }, + { { 0x007B, "xdigit" }, { 0,1,0 } }, + { { 0x007E, "xdigit" }, { 0,1,0 } }, + { { 0x007F, "xdigit" }, { 0,1,0 } }, + { { 0x0080, "xdigit" }, { 0,1,0 } }, + { { 0x0061, "xxxxxx" }, { 0,1,0 } }, + { .is_last = 1 } + } + }, + { +#if 0 + { Tiswctype, TST_LOC_eucJP }, +#else + { Tiswctype, TST_LOC_ja_UTF8 }, +#endif + { +#ifdef SHOJI_IS_RIGHT + { { 0x3029, "alnum" }, { 0,1,0 } }, /* Hangzhou NUM9 */ +#else + { { 0x3029, "alnum" }, { 0,0,0 } }, /* Hangzhou NUM9 */ +#endif + { { 0xFE4F, "alnum" }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF19, "alnum" }, { 0,0,0 } }, /* FULL 9 */ + { { 0xFF20, "alnum" }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A, "alnum" }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40, "alnum" }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A, "alnum" }, { 0,0,0 } }, /* FULL z */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF71, "alnum" }, { 0,1,0 } }, /* HALF KATA A */ +#else + { { 0xFF71, "alnum" }, { 0,0,0 } }, /* HALF KATA A */ +#endif +#ifdef SHOJI_IS_RIGHT + { { 0x3029, "alpha" }, { 0,1,0 } }, /* Hangzhou NUM9 */ +#else + { { 0x3029, "alpha" }, { 0,0,0 } }, /* Hangzhou NUM9 */ +#endif + { { 0xFE4F, "alpha" }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF19, "alpha" }, { 0,1,0 } }, /* FULL 9 */ +#else + { { 0xFF19, "alpha" }, { 0,0,0 } }, /* FULL 9 */ +#endif + { { 0xFF20, "alpha" }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A, "alpha" }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40, "alpha" }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A, "alpha" }, { 0,0,0 } }, /* FULL z */ +#ifdef SHOJI_IS_RIGHT + { { 0xFF71, "alpha" }, { 0,1,0 } }, /* HALF KATA A */ +#else + { { 0xFF71, "alpha" }, { 0,0,0 } }, /* HALF KATA A */ +#endif + { { 0x0080, "cntrl" }, { 0,0,0 } }, /* CNTRL */ + { { 0x3000, "cntrl" }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3029, "digit" }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x32CB, "digit" }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + /* 21: */ + { { 0x33FE, "digit" }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ + { { 0xFF19, "digit" }, { 0,1,0 } }, /* FULL 9 */ + { { 0x3000, "graph" }, { 0,1,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020, "graph" }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029, "graph" }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F, "graph" }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "graph" }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F, "graph" }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#else + { { 0x3020, "graph" }, { 0,0,0 } }, /* POSTAL MARK FACE */ + { { 0x3029, "graph" }, { 0,0,0 } }, /* Hangzhou NUM9 */ + { { 0x302F, "graph" }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "graph" }, { 0,0,0 } }, /* Separator Symbol */ + { { 0x303F, "graph" }, { 0,0,0 } }, /* IDEO. HALF SPACE */ +#endif + /* 29: */ + { { 0x3041, "graph" }, { 0,0,0 } }, /* HIRAGANA a */ + /* Non jis: */ +#ifdef SHOJI_IS_RIGHT + { { 0x3094, "graph" }, { 0,1,0 } }, /* HIRAGANA u" */ +#else + { { 0x3094, "graph" }, { 0,0,0 } }, /* HIRAGANA u" */ +#endif + /* Non jis: */ +#ifdef SHOJI_IS_RIGHT + { { 0x3099, "graph" }, { 0,1,0 } }, /* SOUND MARK */ +#else + { { 0x3099, "graph" }, { 0,0,0 } }, /* SOUND MARK */ +#endif + { { 0x309E, "graph" }, { 0,0,0 } }, /* ITERATION MARK */ + /* 33: */ + { { 0x30A1, "graph" }, { 0,0,0 } }, /* KATAKANA a */ + /* Non jis: */ +#ifdef SHOJI_IS_RIGHT + { { 0x30FA, "graph" }, { 0,1,0 } }, /* KATAKANA wo" */ +#else + { { 0x30FA, "graph" }, { 0,0,0 } }, /* KATAKANA wo" */ +#endif + { { 0x30FB, "graph" }, { 0,0,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE, "graph" }, { 0,0,0 } }, /* KATAKANA ITERATION */ +#ifdef SHOJI_IS_RIGHT + { { 0x3191, "graph" }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243, "graph" }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB, "graph" }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE, "graph" }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE, "graph" }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#else + { { 0x3191, "graph" }, { 0,0,0 } }, /* KANBUN REV.MARK */ + { { 0x3243, "graph" }, { 0,0,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB, "graph" }, { 0,0,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE, "graph" }, { 0,0,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE, "graph" }, { 0,0,0 } }, /* CJK IDEO.TEL.31th */ +#endif + { { 0x4E00, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E06, "graph" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x4E06, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x4E07, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x9007, "graph" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4, "graph" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x9007, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + /* 51 */ + { { 0x9FA5, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + /* Non jis: */ +#ifdef SHOJI_IS_RIGHT + { { 0xFE4F, "graph" }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#else + { { 0xFE4F, "graph" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#endif + { { 0xFF0F, "graph" }, { 0,0,0 } }, /* FULL SLASH */ + { { 0xFF19, "graph" }, { 0,0,0 } }, /* FULL 9 */ + { { 0xFF20, "graph" }, { 0,0,0 } }, /* FULL @ */ + { { 0xFF3A, "graph" }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40, "graph" }, { 0,0,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A, "graph" }, { 0,0,0 } }, /* FULL z */ + { { 0xFF5E, "graph" }, { 0,0,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61, "graph" }, { 0,0,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65, "graph" }, { 0,0,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66, "graph" }, { 0,0,0 } }, /* HALF KATA WO */ + { { 0xFF6F, "graph" }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0xFF70, "graph" }, { 0,0,0 } }, /* HALF KATA PL - */ + { { 0xFF71, "graph" }, { 0,0,0 } }, /* HALF KATA A */ + { { 0xFF9E, "graph" }, { 0,0,0 } }, /* HALF KATA MI */ + { { 0x3000, "print" }, { 0,0,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020, "print" }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029, "print" }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F, "print" }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "print" }, { 0,1,0 } }, /* Separator Symbol */ +#else + { { 0x3020, "print" }, { 0,0,0 } }, /* POSTAL MARK FACE */ + { { 0x3029, "print" }, { 0,0,0 } }, /* Hangzhou NUM9 */ + { { 0x302F, "print" }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "print" }, { 0,0,0 } }, /* Separator Symbol */ +#endif + { { 0x4E00, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E06, "print" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x4E06, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x4E07, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x9007, "print" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4, "print" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x9007, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + /* 81: */ + { { 0x9FA5, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + /* Non jis: */ +#ifdef SHOJI_IS_RIGHT + { { 0xFE4F, "print" }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#else + { { 0xFE4F, "print" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#endif + { { 0x3000, "punct" }, { 0,1,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020, "punct" }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x302F, "punct" }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "punct" }, { 0,1,0 } }, /* FEED Separator */ + { { 0x303F, "punct" }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#else + { { 0x3020, "punct" }, { 0,0,0 } }, /* POSTAL MARK FACE */ + { { 0x302F, "punct" }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037, "punct" }, { 0,0,0 } }, /* FEED Separator */ + { { 0x303F, "punct" }, { 0,0,0 } }, /* IDEO. HALF SPACE */ +#endif + { { 0x3041, "punct" }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094, "punct" }, { 0,1,0 } }, /* HIRAGANA u" */ + /* 90: */ +#ifdef SHOJI_IS_RIGHT + { { 0x3099, "punct" }, { 0,1,0 } }, /* SOUND MARK */ +#else + { { 0x3099, "punct" }, { 0,0,0 } }, /* SOUND MARK */ +#endif + { { 0x309E, "punct" }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1, "punct" }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA, "punct" }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB, "punct" }, { 0,0,0 } }, /* KATAKANA MID.DOT */ + /* 95: */ + { { 0x30FE, "punct" }, { 0,1,0 } }, /* KATAKANA ITERATION */ +#ifdef SHOJI_IS_RIGHT + { { 0x3191, "punct" }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243, "punct" }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB, "punct" }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE, "punct" }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE, "punct" }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#else + { { 0x3191, "punct" }, { 0,0,0 } }, /* KANBUN REV.MARK */ + { { 0x3243, "punct" }, { 0,0,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB, "punct" }, { 0,0,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE, "punct" }, { 0,0,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE, "punct" }, { 0,0,0 } }, /* CJK IDEO.TEL.31th */ +#endif + { { 0x9007, "punct" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4, "punct" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5, "punct" }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F, "punct" }, { 0,0,0 } }, /* FULL SLASH */ + /* 105: */ + { { 0xFF19, "punct" }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20, "punct" }, { 0,0,0 } }, /* FULL @ */ + { { 0xFF3A, "punct" }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40, "punct" }, { 0,0,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A, "punct" }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E, "punct" }, { 0,0,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61, "punct" }, { 0,0,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65, "punct" }, { 0,0,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF70, "punct" }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF9E, "punct" }, { 0,1,0 } }, /* HALF KATA MI */ + /* 115: */ + { { 0x3000, "space" }, { 0,0,0 } }, /* IDEO. SPACE */ + { { 0x303F, "space" }, { 0,1,0 } }, /* IDEO. HALF SPACE */ + { { 0x3041, "lower" }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094, "lower" }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x30A1, "lower" }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA, "lower" }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0xFF66, "lower" }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F, "lower" }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70, "lower" }, { 0,1,0 } }, /* HALF KATA PL - */ + /* 124: */ + { { 0xFF71, "lower" }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E, "lower" }, { 0,1,0 } }, /* HALF KATA MI */ + { { 0xFF71, "upper" }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF19, "xdigit" }, { 0,1,0 } }, /* FULL 9 */ + { { 0x3000, "jspace" }, { 0,0,0 } }, /* IDEO. SPACE */ + /* Non jis? */ + { { 0x303F, "jspace" }, { 0,1,0 } }, /* IDEO.HALF SPACE */ + { { 0xFF19, "jdigit" }, { 0,0,0 } }, /* FULL 9 */ + { { 0x3041, "jhira" }, { 0,0,0 } }, /* HIRAGANA a */ + { { 0x3094, "jhira" }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x30A1, "jkata" }, { 0,0,0 } }, /* KATAKANA a */ + /* Non jis: */ + { { 0x30FA, "jkata" }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0xFF66, "jkata" }, { 0,0,0 } }, /* HALF KATA WO */ + { { 0xFF6F, "jkata" }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0x4E05, "jkanji" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + /* : */ + { { 0x4E06, "jkanji" }, { 0,1,1 } }, /* CJK UNI.IDEO.NON-J */ +#else + /* XXX This character does not exist in EUC-JP. */ + { { 0x4E06, "jkanji" }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x4E07, "jkanji" }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { .is_last = 1 } + } + }, + { + { Tiswctype, TST_LOC_end } + } +}; + + +/* dat_isw-funcs.c */ diff --git a/test/locale-mbwc/dat_iswdigit.c b/test/locale-mbwc/dat_iswdigit.c new file mode 100644 index 0000000..70ca544 --- /dev/null +++ b/test/locale-mbwc/dat_iswdigit.c @@ -0,0 +1,125 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswdigit.c + * + * ISW*: int iswdigit (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (DIGIT, digit) = { + + { TST_ISW_REC (de, digit) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, digit) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,0,0 } }, + { { 0x0039 }, { 0,0,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,1,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,1,0 } }, + { { 0x007A }, { 0,1,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, digit) +#else + { TST_ISW_REC (ja_UTF8, digit) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, digit) } +}; diff --git a/test/locale-mbwc/dat_iswgraph.c b/test/locale-mbwc/dat_iswgraph.c new file mode 100644 index 0000000..80cacb2 --- /dev/null +++ b/test/locale-mbwc/dat_iswgraph.c @@ -0,0 +1,167 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswgraph.c + * + * ISW*: int iswgraph (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (GRAPH, graph) = { + + { TST_ISW_REC (de, graph) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0 }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1 }, { 0,0,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,0,0 } }, /* Degree */ + { { 0x00B1 }, { 0,0,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,0,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,0,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,0,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,0,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,0,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,0,0 } }, /* >> */ + { { 0x00BC }, { 0,0,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,0,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,0,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,0,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,0,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,0,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, graph) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,0,0 } }, + { { 0x002F }, { 0,0,0 } }, + { { 0x0030 }, { 0,0,0 } }, + { { 0x0039 }, { 0,0,0 } }, + { { 0x003A }, { 0,0,0 } }, + { { 0x0040 }, { 0,0,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,0,0 } }, + { { 0x005B }, { 0,0,0 } }, + { { 0x0060 }, { 0,0,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,0,0 } }, + { { 0x007B }, { 0,0,0 } }, + { { 0x007E }, { 0,0,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, /* 20 */ + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC( eucJP, graph ) +#else + { TST_ISW_REC( ja_UTF8, graph ) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#else + { { 0x3020 }, { 0,0,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,0,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,0,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,0,0 } }, /* IDEO. HALF SPACE */ +#endif + { { 0x3041 }, { 0,0,0 } }, /* HIRAGANA a */ +#ifdef SHOJI_IS_RIGHT + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ /* non jis */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ +#else + { { 0x3094 }, { 0,0,0 } }, /* HIRAGANA u" */ /* non jis */ + { { 0x3099 }, { 0,0,0 } }, /* SOUND MARK */ +#endif + { { 0x309E }, { 0,0,0 } }, /* ITERATION MARK */ /* 10 */ + { { 0x30A1 }, { 0,0,0 } }, /* KATAKANA a */ +#ifdef SHOJI_IS_RIGHT + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ /* non jis */ +#else + { { 0x30FA }, { 0,0,0 } }, /* KATAKANA wo" */ /* non jis */ +#endif + { { 0x30FB }, { 0,0,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,0,0 } }, /* KATAKANA ITERATION */ +#ifdef SHOJI_IS_RIGHT + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#else + { { 0x3191 }, { 0,0,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,0,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,0,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,0,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,0,0 } }, /* CJK IDEO.TEL.31th */ +#endif + { { 0x4E00 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ /* 20 */ + { { 0x4E05 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x4E06 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x4E07 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x9007 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x9FA5 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0xFE4F }, { 0,1,0 } }, /* CJK Wave Low Line */ /* 30 */ +#else + { { 0xFE4F }, { 0,0,0 } }, /* CJK Wave Low Line */ /* 30 */ +#endif + { { 0xFF0F }, { 0,0,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,0,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,0,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,0,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,0,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,0,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,0,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,0,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,0,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,0,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,0,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,0,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, graph) } +}; diff --git a/test/locale-mbwc/dat_iswlower.c b/test/locale-mbwc/dat_iswlower.c new file mode 100644 index 0000000..58ec08e --- /dev/null +++ b/test/locale-mbwc/dat_iswlower.c @@ -0,0 +1,96 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswlower.c + * + * ISW*: int iswlower (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (LOWER, lower) = { + + { TST_ISW_REC (de, lower) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, lower) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,1,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,0,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, lower) +#else + { TST_ISW_REC (ja_UTF8, lower) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,0,0 } }, /* FULL z */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, lower) } + +}; diff --git a/test/locale-mbwc/dat_iswprint.c b/test/locale-mbwc/dat_iswprint.c new file mode 100644 index 0000000..bcd96d0 --- /dev/null +++ b/test/locale-mbwc/dat_iswprint.c @@ -0,0 +1,170 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswprint.c + * + * ISW*: int iswprint (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (PRINT, print) = { + + { TST_ISW_REC (de, print) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0 }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1 }, { 0,0,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,0,0 } }, /* Degree */ + { { 0x00B1 }, { 0,0,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,0,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,0,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,0,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,0,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,0,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,0,0 } }, /* >> */ + { { 0x00BC }, { 0,0,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,0,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,0,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,0,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,0,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,0,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,0,0 } }, /* a grave */ + { { 0x00F6 }, { 0,0,0 } }, /* o dia */ + { { 0x00F7 }, { 0,0,0 } }, /* division */ + { { 0x00F8 }, { 0,0,0 } }, /* o stroke */ + { { 0x00FF }, { 0,0,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, print) + { + { { WEOF }, { 0,1,0 } }, /* 01 */ + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,0,0 } }, + { { 0x0021 }, { 0,0,0 } }, + { { 0x002F }, { 0,0,0 } }, + { { 0x0030 }, { 0,0,0 } }, + { { 0x0039 }, { 0,0,0 } }, + { { 0x003A }, { 0,0,0 } }, + { { 0x0040 }, { 0,0,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,0,0 } }, + { { 0x005B }, { 0,0,0 } }, + { { 0x0060 }, { 0,0,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,0,0 } }, + { { 0x007B }, { 0,0,0 } }, + { { 0x007E }, { 0,0,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, /* 20 */ +#ifdef NO_WAIVER + { { 0x3042 }, { 0,1,0 } }, /* */ +#endif + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, print) +#else + { TST_ISW_REC (ja_UTF8, print) +#endif + { + { { 0x3000 }, { 0,0,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#else + { { 0x3020 }, { 0,0,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,0,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,0,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,0,0 } }, /* IDEO. HALF SPACE */ +#endif + { { 0x3041 }, { 0,0,0 } }, /* HIRAGANA a */ +#ifdef SHOJI_IS_RIGHT + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ /* non jis */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ +#else + { { 0x3094 }, { 0,0,0 } }, /* HIRAGANA u" */ /* non jis */ + { { 0x3099 }, { 0,0,0 } }, /* SOUND MARK */ +#endif + { { 0x309E }, { 0,0,0 } }, /* ITERATION MARK */ /* 10 */ + { { 0x30A1 }, { 0,0,0 } }, /* KATAKANA a */ +#ifdef SHOJI_IS_RIGHT + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ /* non jis */ +#else + { { 0x30FA }, { 0,0,0 } }, /* KATAKANA wo" */ /* non jis */ +#endif + { { 0x30FB }, { 0,0,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,0,0 } }, /* KATAKANA ITERATION */ +#ifdef SHOJI_IS_RIGHT + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#else + { { 0x3191 }, { 0,0,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,0,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,0,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,0,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,0,0 } }, /* CJK IDEO.TEL.31th */ +#endif + { { 0x4E00 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ /* 20 */ + { { 0x4E05 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x4E06 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x4E07 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ +#else + { { 0x9007 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,0,0 } }, /* CJK UNI.IDEO.NON-J */ +#endif + { { 0x9FA5 }, { 0,0,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0xFE4F }, { 0,1,0 } }, /* WAVE LOW LINE */ /* 30 */ +#else + { { 0xFE4F }, { 0,0,0 } }, /* WAVE LOW LINE */ /* 30 */ +#endif + { { 0xFF0F }, { 0,0,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,0,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,0,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,0,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,0,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,0,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,0,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,0,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,0,0 } }, /* HALF KATA WO */ /* 40 */ + { { 0xFF6F }, { 0,0,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,0,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,0,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,0,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, print) } +}; diff --git a/test/locale-mbwc/dat_iswpunct.c b/test/locale-mbwc/dat_iswpunct.c new file mode 100644 index 0000000..2b3612f --- /dev/null +++ b/test/locale-mbwc/dat_iswpunct.c @@ -0,0 +1,155 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswpunct.c + * + * ISW*: int iswpunct (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (PUNCT, punct) = { + + { TST_ISW_REC (de, punct) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ +#ifdef SHOJI_IS_RIGHT + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ +#else + { { 0x00A0 }, { 0,0,0 } }, /* NB SPACE */ +#endif + { { 0x00A1 }, { 0,0,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,0,0 } }, /* Degree */ + { { 0x00B1 }, { 0,0,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,0,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,0,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,0,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,0,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,0,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,0,0 } }, /* >> */ + { { 0x00BC }, { 0,0,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,0,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,0,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,0,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,0,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,0,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, punct) + { + { { WEOF }, { 0,1,0 } }, /* 01 */ + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,0,0 } }, + { { 0x002F }, { 0,0,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,0,0 } }, + { { 0x0040 }, { 0,0,0 } }, + { { 0x0041 }, { 0,1,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,0,0 } }, + { { 0x0060 }, { 0,0,0 } }, + { { 0x0061 }, { 0,1,0 } }, + { { 0x007A }, { 0,1,0 } }, + { { 0x007B }, { 0,0,0 } }, + { { 0x007E }, { 0,0,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, /* 20 */ + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, punct) +#else + { TST_ISW_REC (ja_UTF8, punct) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ +#ifdef SHOJI_IS_RIGHT + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ +#else + { { 0x3020 }, { 0,0,0 } }, /* POSTAL MARK FACE */ +#endif + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ +#ifdef SHOJI_IS_RIGHT + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ +#else + { { 0x302F }, { 0,0,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,0,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,0,0 } }, /* IDEO. HALF SPACE */ +#endif + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ +#ifdef SHOJI_IS_RIGHT + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ +#else + { { 0x3099 }, { 0,0,0 } }, /* SOUND MARK */ +#endif + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ /* 10 */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB }, { 0,0,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ +#ifdef SHOJI_IS_RIGHT + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ +#else + { { 0x3191 }, { 0,0,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,0,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,0,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,0,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,0,0 } }, /* CJK IDEO.TEL.31th */ +#endif + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ /* 20 */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ +#ifdef SHOJI_IS_RIGHT + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ /* 30 */ +#else + { { 0xFE4F }, { 0,0,0 } }, /* CJK UNI.IDEO. */ /* 30 */ +#endif + { { 0xFF0F }, { 0,0,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,0,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,0,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,0,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,0,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,0,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ /* 40 */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, punct) } +}; diff --git a/test/locale-mbwc/dat_iswspace.c b/test/locale-mbwc/dat_iswspace.c new file mode 100644 index 0000000..2131b87 --- /dev/null +++ b/test/locale-mbwc/dat_iswspace.c @@ -0,0 +1,129 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswspace.c + * + * ISW*: int iswspace (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (SPACE, space) = { + + { TST_ISW_REC (de, space) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (enUS, space) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x0008 }, { 0,1,0 } }, + { { 0x0009 }, { 0,0,0 } }, + { { 0x000D }, { 0,0,0 } }, + { { 0x000E }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,0,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,1,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,1,0 } }, + { { 0x007A }, { 0,1,0 } }, /* 20 */ + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, space) +#else + { TST_ISW_REC (ja_UTF8, space) +#endif + { + { { 0x3000 }, { 0,0,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ /* No JIS */ + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, space) } +}; diff --git a/test/locale-mbwc/dat_iswupper.c b/test/locale-mbwc/dat_iswupper.c new file mode 100644 index 0000000..865f42f --- /dev/null +++ b/test/locale-mbwc/dat_iswupper.c @@ -0,0 +1,94 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswupper.c + * + * ISW*: int iswupper (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (UPPER, upper) = { + + { TST_ISW_REC (de, upper) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,0,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,0,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,0,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last entry. */ + } + }, + { TST_ISW_REC (enUS, upper) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,1,0 } }, + { { 0x0039 }, { 0,1,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,0,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,1,0 } }, + { { 0x007A }, { 0,1,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last entry. */ + } + }, +#if 0 + { TST_ISW_REC (eucJP, upper) +#else + { TST_ISW_REC (ja_UTF8, upper) +#endif + { + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,0,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last entry. */ + } + }, + { TST_ISW_REC (end, upper) } +}; diff --git a/test/locale-mbwc/dat_iswxdigit.c b/test/locale-mbwc/dat_iswxdigit.c new file mode 100644 index 0000000..5d6c652 --- /dev/null +++ b/test/locale-mbwc/dat_iswxdigit.c @@ -0,0 +1,125 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_iswxdigit.c + * + * ISW*: int iswxdigit (wint_t wc); + */ + + +#include "dat_isw-funcs.h" + + +TST_ISW_LOC (XDIGIT, xdigit) = { + + { TST_ISW_REC (de, xdigit) + { + { { 0x0080 }, { 0,1,0 } }, /* CTRL */ + { { 0x009F }, { 0,1,0 } }, /* CTRL */ + { { 0x00A0 }, { 0,1,0 } }, /* NB SPACE */ + { { 0x00A1 }, { 0,1,0 } }, /* UD ! */ + { { 0x00B0 }, { 0,1,0 } }, /* Degree */ + { { 0x00B1 }, { 0,1,0 } }, /* +- sign */ + { { 0x00B2 }, { 0,1,0 } }, /* SUP 2 */ + { { 0x00B3 }, { 0,1,0 } }, /* SUP 3 */ + { { 0x00B4 }, { 0,1,0 } }, /* ACUTE */ + { { 0x00B8 }, { 0,1,0 } }, /* CEDILLA */ + { { 0x00B9 }, { 0,1,0 } }, /* SUP 1 */ + { { 0x00BB }, { 0,1,0 } }, /* >> */ + { { 0x00BC }, { 0,1,0 } }, /* 1/4 */ + { { 0x00BD }, { 0,1,0 } }, /* 1/2 */ + { { 0x00BE }, { 0,1,0 } }, /* 3/4 */ + { { 0x00BF }, { 0,1,0 } }, /* UD ? */ + { { 0x00C0 }, { 0,1,0 } }, /* A Grave */ + { { 0x00D6 }, { 0,1,0 } }, /* O dia */ + { { 0x00D7 }, { 0,1,0 } }, /* multipl. */ + { { 0x00D8 }, { 0,1,0 } }, /* O stroke */ + { { 0x00DF }, { 0,1,0 } }, /* small Sh */ + { { 0x00E0 }, { 0,1,0 } }, /* a grave */ + { { 0x00F6 }, { 0,1,0 } }, /* o dia */ + { { 0x00F7 }, { 0,1,0 } }, /* division */ + { { 0x00F8 }, { 0,1,0 } }, /* o stroke */ + { { 0x00FF }, { 0,1,0 } }, /* y dia */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC( enUS, xdigit ) + { + { { WEOF }, { 0,1,0 } }, + { { 0x0000 }, { 0,1,0 } }, + { { 0x001F }, { 0,1,0 } }, + { { 0x0020 }, { 0,1,0 } }, + { { 0x0021 }, { 0,1,0 } }, + { { 0x002F }, { 0,1,0 } }, + { { 0x0030 }, { 0,0,0 } }, + { { 0x0039 }, { 0,0,0 } }, + { { 0x003A }, { 0,1,0 } }, + { { 0x0040 }, { 0,1,0 } }, + { { 0x0041 }, { 0,0,0 } }, + { { 0x005A }, { 0,1,0 } }, + { { 0x005B }, { 0,1,0 } }, + { { 0x0060 }, { 0,1,0 } }, + { { 0x0061 }, { 0,0,0 } }, + { { 0x007A }, { 0,1,0 } }, + { { 0x007B }, { 0,1,0 } }, + { { 0x007E }, { 0,1,0 } }, + { { 0x007F }, { 0,1,0 } }, + { { 0x0080 }, { 0,1,0 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_ISW_REC( eucJP, xdigit ) +#else + { TST_ISW_REC( ja_UTF8, xdigit ) +#endif + { + { { 0x3000 }, { 0,1,0 } }, /* IDEO. SPACE */ + { { 0x3020 }, { 0,1,0 } }, /* POSTAL MARK FACE */ + { { 0x3029 }, { 0,1,0 } }, /* Hangzhou NUM9 */ + { { 0x302F }, { 0,1,0 } }, /* Diacritics(Hangul) */ + { { 0x3037 }, { 0,1,0 } }, /* Separator Symbol */ + { { 0x303F }, { 0,1,0 } }, /* IDEO. HALF SPACE */ + { { 0x3041 }, { 0,1,0 } }, /* HIRAGANA a */ + { { 0x3094 }, { 0,1,0 } }, /* HIRAGANA u" */ + { { 0x3099 }, { 0,1,0 } }, /* SOUND MARK */ + { { 0x309E }, { 0,1,0 } }, /* ITERATION MARK */ + { { 0x30A1 }, { 0,1,0 } }, /* KATAKANA a */ + { { 0x30FA }, { 0,1,0 } }, /* KATAKANA wo" */ + { { 0x30FB }, { 0,1,0 } }, /* KATAKANA MID.DOT */ + { { 0x30FE }, { 0,1,0 } }, /* KATAKANA ITERATION */ + { { 0x3191 }, { 0,1,0 } }, /* KANBUN REV.MARK */ + { { 0x3243 }, { 0,1,0 } }, /* IDEO. MARK (reach) */ + { { 0x32CB }, { 0,1,0 } }, /* IDEO.TEL.SYM.DEC12 */ + { { 0x32FE }, { 0,1,0 } }, /* MARU KATAKANA wo */ + { { 0x33FE }, { 0,1,0 } }, /* CJK IDEO.TEL.31th */ + { { 0x4E00 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E05 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4E06 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x4E07 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x4FFF }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9000 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9006 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0x9007 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA4 }, { 0,1,0 } }, /* CJK UNI.IDEO.NON-J */ + { { 0x9FA5 }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFE4F }, { 0,1,0 } }, /* CJK UNI.IDEO. */ + { { 0xFF0F }, { 0,1,0 } }, /* FULL SLASH */ + { { 0xFF19 }, { 0,1,0 } }, /* FULL 9 */ + { { 0xFF20 }, { 0,1,0 } }, /* FULL @ */ + { { 0xFF3A }, { 0,1,0 } }, /* FULL Z */ + { { 0xFF40 }, { 0,1,0 } }, /* FULL GRAVE ACC. */ + { { 0xFF5A }, { 0,1,0 } }, /* FULL z */ + { { 0xFF5E }, { 0,1,0 } }, /* FULL ~ (tilde) */ + { { 0xFF61 }, { 0,1,0 } }, /* HALF IDEO.STOP. . */ + { { 0xFF65 }, { 0,1,0 } }, /* HALF KATA MID.DOT */ + { { 0xFF66 }, { 0,1,0 } }, /* HALF KATA WO */ + { { 0xFF6F }, { 0,1,0 } }, /* HALF KATA tu */ + { { 0xFF70 }, { 0,1,0 } }, /* HALF KATA PL - */ + { { 0xFF71 }, { 0,1,0 } }, /* HALF KATA A */ + { { 0xFF9E }, { 0,1,0 } }, /* HALF KATA MI */ + { .is_last = 1 } /* Last element. */ + } + }, + { TST_ISW_REC (end, xdigit) } +}; diff --git a/test/locale-mbwc/dat_mblen.c b/test/locale-mbwc/dat_mblen.c new file mode 100644 index 0000000..8da038c --- /dev/null +++ b/test/locale-mbwc/dat_mblen.c @@ -0,0 +1,137 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mblen.c + * + * MBLEN: int mblen (char *s, size_t n); + */ + + +/* + * NOTE: + * int mblen (char *s, size_t n); + * + * where n: a maximum number of bytes + * + * return - the number of bytes + * + * CAUTION: + * + * o When you feed a null pointer for a string (s) to the function, + * set s_flg=0 instead of putting just a 'NULL' there. + * Even if you set a 'NULL', it doens't mean a NULL pointer. + * + * o When s is a null pointer, the function checks state dependency. + * + * state-dependent encoding - return NON-zero + * state-independent encoding - return 0 + * + * If state-dependent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = +1 + * + * If state-independent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = 0 + * + * + * When you set ret_flg=1, the test program simply compares an + * actual return value with an expected value. You can check + * state-independent case (return value is 0) in that way, but + * you can not check state-dependent case. So when you check + * state- dependency in this test function: tst_mblen(), set + * ret_flg=0 always. It's a special case, and the test + * function takes care of it. + * + * s_flg=0 ret_flg=0 + * | | + * { 0, 0 }, { 0, 0, 0, x } + * | | + * not used ret_val: 0/+1 + * (expected val) */ + + +TST_MBLEN tst_mblen_loc [] = { + { + { Tmblen, TST_LOC_de }, + { + /* 01: a character. */ + { { 1, "\300", USE_MBCURMAX }, { 0, 1, 1 } }, + /* 02: a character. */ + { { 1, "\309", USE_MBCURMAX }, { 0, 1, 1 } }, + /* 03: a character + an invalid byte. */ + { { 1, "Z\204", USE_MBCURMAX }, { 0, 1, +1 } }, + /* 04: control/invalid characters. */ + { { 1, "\177\000", USE_MBCURMAX }, { 0, 1, +1 } }, + /* 05: a null string. */ + { { 1, "", USE_MBCURMAX }, { 0, 1, 0 } }, + /* 06: a null pointer. */ + { { 0, "", USE_MBCURMAX }, { 0, 0, 0 } }, + /* Last element. */ + { .is_last = 1 } + } + }, + { + { Tmblen, TST_LOC_enUS }, + { + /* 01: a character. */ + { { 1, "A", USE_MBCURMAX }, { 0, 1, 1 } }, + /* 02: a character. */ + { { 1, "a", USE_MBCURMAX }, { 0, 1, 1 } }, + /* 03: a character + an invalid byte. */ + { { 1, "Z\204", USE_MBCURMAX }, { 0, 1, +1 } }, + /* 04: control/invalid characters. */ + { { 1, "\177\000", USE_MBCURMAX }, { 0, 1, +1 } }, + /* 05: a null string. */ + { { 1, "", USE_MBCURMAX }, { 0, 1, 0 } }, + /* 06: a null pointer. */ + { { 0, "", USE_MBCURMAX }, { 0, 0, 0 } }, + /* Last element. */ + { .is_last = 1 } + } + }, +#if 0 + { + { Tmblen, TST_LOC_eucJP }, + { + /* 01: a character. */ + { { 1, "\264\301", USE_MBCURMAX }, { 0, 1, 2 } }, + /* 02: a character. */ + { { 1, "\216\261", USE_MBCURMAX }, { 0, 1, 2 } }, + /* 03: a character + an invalid byte. */ + { { 1, "\260\241\200", USE_MBCURMAX }, { 0, 1, 2 } }, + /* 04: control/invalid characters. */ + { { 1, "\377\202", USE_MBCURMAX }, { EILSEQ, 1, -1 } }, + /* 05: a null string. */ + { { 1, "", USE_MBCURMAX }, { 0, 1, 0 } }, + /* 06: a null pointer. */ + { { 0, "", USE_MBCURMAX }, { 0, 0, 0 } }, + /* Last element. */ + { .is_last = 1 } + } + }, +#else + { + { Tmblen, TST_LOC_ja_UTF8 }, + { + /* 01: a character. */ + { { 1, "\346\274\242", USE_MBCURMAX }, { 0, 1, 3 } }, + /* 02: a character. */ + { { 1, "\357\275\261", USE_MBCURMAX }, { 0, 1, 3 } }, + /* 03: a character + an invalid byte. */ + { { 1, "\345\272\234\200", USE_MBCURMAX }, { 0, 1, 3 } }, + /* 04: control/invalid characters. */ + { { 1, "\377\202", USE_MBCURMAX }, { EILSEQ, 1, -1 } }, + /* 05: a null string. */ + { { 1, "", USE_MBCURMAX }, { 0, 1, 0 } }, + /* 06: a null pointer. */ + { { 0, "", USE_MBCURMAX }, { 0, 0, 0 } }, + /* Last element. */ + { .is_last = 1 } + } + }, +#endif + { + { Tmblen, TST_LOC_end} + } +}; diff --git a/test/locale-mbwc/dat_mbrlen.c b/test/locale-mbwc/dat_mbrlen.c new file mode 100644 index 0000000..63ae19f --- /dev/null +++ b/test/locale-mbwc/dat_mbrlen.c @@ -0,0 +1,222 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mbrlen.c + * + * MBRLEN: size_t mbrlen (const char *s, size_t n, mbstate_t *ps); + */ + +/* + * NOTE: + * (1) A mbstate object is initialized for + * every new data record by the test program. + * + * (2) USE_MBCURMAX is defined as a value of 99. + * + */ + + +TST_MBRLEN tst_mbrlen_loc [] = { + { + { Tmbrlen, TST_LOC_de }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "", 0, 0, 0 }, + { 1, "", 1, 0, 0 }, + { 1, "\300", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { 0, 1, 0, }, + { 0, 1, 1, }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\300\001", 0, 0, 0 }, + { 1, "\300\001", 1, 0, 0 }, + { 1, "\317\001", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { 0, 1, 1, }, + { 0, 1, 1, }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Tmbrlen, TST_LOC_enUS }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "A", 0, 0, 0 }, + { 1, "A", 1, 0, 0 }, + { 1, "A", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { 0, 1, 1, }, + { 0, 1, 1, }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\317\001", 0, 1, 0 }, + { 1, "\317\001", 1, 1, 0 }, + { 1, "\317\001", USE_MBCURMAX, 1, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { EILSEQ, 1, -1, }, + { EILSEQ, 1, -1, }, + } + } + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Tmbrlen, TST_LOC_eucJP }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "\317\302", 1, 1, 1 }, + { 0, "", 0, 1, 0 }, + { 1, "\317\302", USE_MBCURMAX, 1, 1 }, + } + }, + { + { + { 0, 1, -2, }, + { 0, 1, -1, }, + { 0, 1, 2, }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\317", 1, 1, 0 }, + { 1, "\302", 1, 1, 0 }, + { 1, "\317\302", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, -2, }, +#ifdef SHOJI_IS_RIGHT + { 0, 1, +2, }, +#else + /* XXX ISO C explicitly says that the return value does not + XXX reflect the bytes contained in the state. */ + { 0, 1, +1, }, +#endif + { 0, 1, 2, }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, "\216\217", 0, 0, 0 }, + { 1, "\216\217", 1, 0, 0 }, + { 1, "\216\217", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { 0, 1, -2, }, + { EILSEQ, 1, -1, }, + } + } + }, + { .is_last = 1 } + } + }, +#else + { + { Tmbrlen, TST_LOC_ja_UTF8 }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "\345\222\214", 1, 1, 1 }, + { 0, "", 0, 1, 0 }, + { 1, "\345\222\214", USE_MBCURMAX, 1, 1 }, + } + }, + { + { + { 0, 1, -2, }, + { 0, 1, -1, }, + { 0, 1, 3, }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\317", 1, 1, 0 }, + { 1, "\266", 1, 1, 0 }, + { 1, "\345\222\214", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, -2, }, +#ifdef SHOJI_IS_RIGHT + { 0, 1, +2, }, +#else + /* XXX ISO C explicitly says that the return value does not + XXX reflect the bytes contained in the state. */ + { 0, 1, +1, }, +#endif + { 0, 1, 3, }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, "\302\303", 0, 0, 0 }, + { 1, "\302\303", 1, 0, 0 }, + { 1, "\302\303", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 0, }, + { 0, 1, -2, }, + { EILSEQ, 1, -1, }, + } + } + }, + { .is_last = 1 } + } + }, +#endif + { + { Tmbrlen, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_mbrtowc.c b/test/locale-mbwc/dat_mbrtowc.c new file mode 100644 index 0000000..b8eb3dd --- /dev/null +++ b/test/locale-mbwc/dat_mbrtowc.c @@ -0,0 +1,140 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mbrtowc.c + * + * MBTOWC: size_t mbrtowc (wchar_t *pwc, char *s, size_t n, + * mbstate_t *ps); + */ + +#include + +/* Note: + assumes en_US = en_US.ascii +*/ + + + + +TST_MBRTOWC tst_mbrtowc_loc [] = { + { + { Tmbrtowc, TST_LOC_de }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { .is_last = 1 } + } + }, +#if 0 + /* XXX: These tests don't make sense to me. */ + { + { Tmbrtowc, TST_LOC_enUS }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Tmbrtowc, TST_LOC_eucJP }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "ÄÖÜ", 1, 0, 0 }, + { 1, 1, "ÄÖÜ", 2, 0, 0 }, + { 1, 1, "ÄÖÜ", USE_MBCURMAX, 0, 0 }, + } + }, + { + { + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + { 0, 1, 1, 0x00C4 }, + } + } + }, + { .is_last = 1 } + } + }, +#endif + { + { Tmbrtowc, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_mbsrtowcs.c b/test/locale-mbwc/dat_mbsrtowcs.c new file mode 100644 index 0000000..30a0a6c --- /dev/null +++ b/test/locale-mbwc/dat_mbsrtowcs.c @@ -0,0 +1,180 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mbsrtowcs.c + * + * MBSRTOWCS: size_t mbsrtowcs (wchar_t *ws, char **s, size_t n, + * mbstate_t *ps); + */ + + +TST_MBSRTOWCS tst_mbsrtowcs_loc [] = { + { + { Tmbsrtowcs, TST_LOC_de }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "üäö", 4, 0,0 }, + { 1, "üäö", 3, 0,0 }, + { 1, "üäö", 2, 0,0 }, + } + }, + { + { + { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 } }, + { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 } }, + { 0,1,2, { 0x00FC,0x00E4,0x00F6,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "üäö", 4, 0,0 }, + { 1, "", 1, 0,0 }, + { 0, "üäö", 4, 0,0 }, + } + }, + { + { + { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,3, { 0x0000 } }, + } + } + }, + { /*----------------- END -----------------*/ + .is_last = 1 + } + } + }, + + { + { Tmbsrtowcs, TST_LOC_enUS }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "ABC", 4, 0,0 }, + { 1, "ABC", 3, 0,0 }, + { 1, "ABC", 2, 0,0 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "ABC", 4, 0,0 }, + { 1, "", 1, 0,0 }, + { 0, "ABC", 4, 0,0 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,3, { 0x0000 } }, + } + } + }, + { /*----------------- END -----------------*/ + .is_last = 1 + } + } + }, + +#if 0 + { + { Tmbsrtowcs, TST_LOC_eucJP }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "\244\242\244\244\244\246ABC", 7, 0,0 }, + { 1, "\244\242\244\244\244\246ABC", 6, 0,0 }, + { 1, "\244\242\244\244\244\246ABC", 4, 0,0 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\244\242\244\244\244\246ABC", 7, 0,0 }, + { 1, "", 1, 0,0 }, + { 0, "\244\242\244\244\244\246ABC", 7, 0,0 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,0, { 0x0000 } }, + { 0,1,6, { 0x0000 } }, + } + } + }, + { /*----------------- END -----------------*/ + .is_last = 1 + } + } + }, +#else + { + { Tmbsrtowcs, TST_LOC_ja_UTF8 }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, "\343\201\202\343\201\204\343\201\206ABC", 7, 0,0 }, + { 1, "\343\201\202\343\201\204\343\201\206ABC", 6, 0,0 }, + { 1, "\343\201\202\343\201\204\343\201\206ABC", 4, 0,0 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, "\343\201\202\343\201\204\343\201\206ABC", 7, 0,0 }, + { 1, "", 1, 0,0 }, + { 0, "\343\201\202\343\201\204\343\201\206ABC", 7, 0,0 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,0, { 0x0000 } }, + { 0,1,6, { 0x0000 } }, + } + } + }, + { /*----------------- END -----------------*/ + .is_last = 1 + } + } + }, +#endif + { + { Tmbsrtowcs, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_mbstowcs.c b/test/locale-mbwc/dat_mbstowcs.c new file mode 100644 index 0000000..3b8ce65 --- /dev/null +++ b/test/locale-mbwc/dat_mbstowcs.c @@ -0,0 +1,190 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mbstowcs.c + * + * MBSTOWCS: size_t mbstowcs (wchar_t *ws, char *s, size_t n); + */ + +#include + +TST_MBSTOWCS tst_mbstowcs_loc [] = { + { + { Tmbstowcs, TST_LOC_de }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ABC", 4 }, + { 1, 1, "ABC", 3 }, + { 1, 1, "ABC", 2 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "ABC", 4 }, + { 1, 1, "", 1 }, + { 0, 1, "ABC", 4 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,3, { 0x0000 } }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Tmbstowcs, TST_LOC_enUS }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ABC", 4 }, + { 1, 1, "ABC", 3 }, + { 1, 1, "ABC", 2 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "ABC", 4 }, + { 1, 1, "", 1 }, + { 0, 1, "ABC", 4 }, + } + }, + { + { + { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,3, { 0x0000 } }, + } + } + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Tmbstowcs, TST_LOC_eucJP }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "\244\242\244\244\244\246ABC", 7 }, + { 1, 1, "\244\242\244\244\244\246ABC", 6 }, + { 1, 1, "\244\242\244\244\244\246ABC", 4 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { +#ifdef SHOJI_IS_RIGHT + /* XXX I really don't understand the first and third line. + the result of the first line is the same as the first + in the last test (i.e., returns 6). Also, the third + test will simply convert everything. */ + { 1, 1, "\244\242\244\244\244\246ABC", 7 }, + { 1, 1, "", 1 }, + { 0, 1, "\244\242\244\244\244\246ABC", 7 }, +#else + { 1, 1, "\244\242\244\244\244\246ABC", 4 }, + { 1, 1, "", 1 }, + { 0, 1, "\244\242\244\244\244\246ABC", 0 }, +#endif + } + }, + { + { + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,6, { 0x0000 } }, + } + } + }, + { .is_last = 1 } + } + }, +#else + { + { Tmbstowcs, TST_LOC_ja_UTF8 }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "\343\201\202\343\201\204\343\201\206ABC", 7 }, + { 1, 1, "\343\201\202\343\201\204\343\201\206ABC", 6 }, + { 1, 1, "\343\201\202\343\201\204\343\201\206ABC", 4 }, + } + }, + { + { + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }}, + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { +#ifdef SHOJI_IS_RIGHT + /* XXX I really don't understand the first and third line. + the result of the first line is the same as the first + in the last test (i.e., returns 6). Also, the third + test will simply convert everything. */ + { 1, 1, "\244\242\244\244\244\246ABC", 7 }, + { 1, 1, "", 1 }, + { 0, 1, "\244\242\244\244\244\246ABC", 7 }, +#else + { 1, 1, "\343\201\202\343\201\204\343\201\206ABC", 4 }, + { 1, 1, "", 1 }, + { 0, 1, "\343\201\202\343\201\204\343\201\206ABC", 7 }, +#endif + } + }, + { + { + { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 } }, + { 0,1,0, { 0x0000 } }, + { 0,1,6, { 0x0000 } }, + } + } + }, + { .is_last = 1 } + } + }, +#endif + { + { Tmbstowcs, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_mbtowc.c b/test/locale-mbwc/dat_mbtowc.c new file mode 100644 index 0000000..6527dfc --- /dev/null +++ b/test/locale-mbwc/dat_mbtowc.c @@ -0,0 +1,444 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_mbtowc.c + * + * MBTOWC: int mbtowc (wchar_t *wp, char *s, size_t n); + */ + +/* NOTE: + * + * int mbtowc (wchar_t *wp, char *s, size_t n); + * + * where n: a maximum number of bytes + * return: the number of bytes + * + * + * o When you feed a null pointer for a string (s) to the function, + * set s_flg=0 instead of putting just a 'NULL' there. + * Even if you put a 'NULL', it means a null string as well as "". + * + * o When s is a null pointer, the function checks state dependency. + * + * state-dependent encoding - return NON-zero + * state-independent encoding - return 0 + * + * If state-dependent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = +1 + * + * If state-independent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = 0 + * + * + * When you set ret_flg=1, the test program simply compares + * an actual return value with an expected value. You can + * check state-independent case (return value is 0) in that + * way, but you can not check state-dependent case. So when + * you check state- dependency in this test function: + * tst_mbtowc(), set ret_flg=0 always. It's a special case + * and the test function takes care of it. + * + * w_flg + * | s: (a null string; can't be (char *)NULL) + * | | + * input. { 1, 0, (char)NULL, MB_LEN_MAX }, + * | + * s_flg=0: makes _s_ a null pointer. + * + * expect { 0,0,0,x, 0x0000 }, + * | | + * | ret_val: 0/+1 + * ret_flg=0 + * + * + * Test data for State dependent encodings: + * + * mbtowc( NULL, NULL, 0 ); ... first data + * mbtowc( &wc, s1, n1 ); ... second data + * mbtowc( &wc, s2, n2 ); ... third data + * */ + +#include + +TST_MBTOWC tst_mbtowc_loc [] = { + { + { Tmbtowc, TST_LOC_de }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "\xfc\xe4\xf6", 1 }, + { 1, 1, "\xfc\xe4\xf6", 2 }, + { 1, 1, "\xfc\xe4\xf6", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x00FC }, + { 0, 1, 1, 0x00FC }, + { 0, 1, 1, 0x00FC }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "\177", MB_LEN_MAX }, + { 1, 1, "\200", MB_LEN_MAX }, + { 1, 1, "\201", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x007F }, + { 0, 1, 1, 0x0080 }, + { 0, 1, 1, 0x0081 }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, 1, "", MB_LEN_MAX }, + { 0, 1, "\xfc\xe4\xf6", 1 }, + { 0, 1, "\xfc\xe4\xf6", 2 }, + } + }, + { + { + { 0, 1, 0, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + } + } + }, + { /*----------------- #04 -----------------*/ + { + { + { 0, 1, "\xfc\xe4\xf6", MB_LEN_MAX }, + { 0, 1, "\177", MB_LEN_MAX }, + { 0, 1, "", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 1, 0, 0x0000 }, + } + } + }, + { /*----------------- #05 -----------------*/ + { + { + { 0, 1, "\xfc\xe4\xf6", MB_LEN_MAX }, + { 0, 1, "\177", MB_LEN_MAX }, + { 0, 0, (char)NULL, MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 0, 0, 0x0000 }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Tmbtowc, TST_LOC_enUS }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "ABC", 1 }, + { 1, 1, "ABC", 2 }, + { 1, 1, "ABC", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x0041 }, + { 0, 1, 1, 0x0041 }, + { 0, 1, 1, 0x0041 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "\177", MB_LEN_MAX }, + { 1, 1, "\200", MB_LEN_MAX }, + { 1, 1, "\201", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x007F }, + { EILSEQ, 1, -1, 0x0000 }, + { EILSEQ, 1, -1, 0x0000 }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, 1, "", MB_LEN_MAX }, + { 0, 1, "ABC", 1 }, + { 0, 1, "ABC", 2 }, + } + }, + { + { + { 0, 1, 0, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + } + } + }, + { /*----------------- #04 -----------------*/ + { + { + { 0, 1, "ABC", MB_LEN_MAX }, + { 0, 1, "\177", MB_LEN_MAX }, + { 0, 1, "", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 1, 0, 0x0000 }, + } + } + }, + { /*----------------- #05 -----------------*/ + { + { + { 0, 1, "ABC", MB_LEN_MAX }, + { 0, 1, "\177", MB_LEN_MAX }, + { 0, 0, (char)NULL, MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 1, 0x0000 }, + { 0, 1, 1, 0x0000 }, + { 0, 0, 0, 0x0000 }, + } + } + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Tmbtowc, TST_LOC_eucJP }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "\244\242A", 1 }, + { 1, 1, "\244\242A", 2 }, + { 1, 1, "\244\242A", MB_LEN_MAX }, + } + }, + { + { +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + /* XXX EILSEQ was introduced in ISO C99. */ + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, 2, 0x3042 }, + { 0, 1, 2, 0x3042 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "\177\244\242", MB_LEN_MAX }, + { 1, 1, "\377\244\242", MB_LEN_MAX }, + { 1, 1, "\201\244\242", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, +1, 0x007F }, +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, +1, 0x0081 }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, 1, "", MB_LEN_MAX }, + { 0, 1, "\244\242A", 1 }, + { 0, 1, "\244\242A", 2 }, + } + }, + { + { + { 0, 1, 0, 0x0000 }, +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + /* XXX EILSEQ was introduced in ISO C99. */ + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, 2, 0x0000 }, + } + } + }, + { /*----------------- #04 -----------------*/ + { + { + { 0, 1, "\244\242A", MB_LEN_MAX }, + { 0, 1, "\177\244\242", MB_LEN_MAX }, + { 0, 1, "", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 2, 0x0000 }, + { 0, 1, +1, 0x0000 }, + { 0, 1, 0, 0x0000 }, + } + } + }, + { /*----------------- #05 -----------------*/ + { + { + { 0, 1, "\244\242A", MB_LEN_MAX }, + { 0, 1, "\177\244\242", MB_LEN_MAX }, + { 0, 0, (char)NULL, MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 2, 0x0000 }, + { 0, 1, +1, 0x0000 }, + { 0, 0, 0, 0x0000 }, + } + } + }, + { .is_last = 1 } + } + }, +#else + { + { Tmbtowc, TST_LOC_ja_UTF8 }, + { + { /*----------------- #01 -----------------*/ + { + { + { 1, 1, "\343\201\202A", 1 }, + { 1, 1, "\343\201\202A", 3 }, + { 1, 1, "\343\201\202A", MB_LEN_MAX }, + } + }, + { + { +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + /* XXX EILSEQ was introduced in ISO C99. */ + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, 3, 0x3042 }, + { 0, 1, 3, 0x3042 }, + } + } + }, + { /*----------------- #02 -----------------*/ + { + { + { 1, 1, "\177\343\201\202", MB_LEN_MAX }, + { 1, 1, "\377\343\201\202", MB_LEN_MAX }, + { 1, 1, "\302\201\343\201\202", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, +1, 0x007F }, +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, +2, 0x0081 }, + } + } + }, + { /*----------------- #03 -----------------*/ + { + { + { 1, 1, "", MB_LEN_MAX }, + { 0, 1, "\343\201\202A", 1 }, + { 0, 1, "\343\201\202A", 3 }, + } + }, + { + { + { 0, 1, 0, 0x0000 }, +#ifdef SHOJI_IS_RIGHT + { EILSEQ, 1, -1, 0x0000 }, +#else + /* XXX EILSEQ was introduced in ISO C99. */ + { 0, 1, -1, 0x0000 }, +#endif + { 0, 1, 3, 0x0000 }, + } + } + }, + { /*----------------- #04 -----------------*/ + { + { + { 0, 1, "\343\201\202A", MB_LEN_MAX }, + { 0, 1, "\177\343\201\202", MB_LEN_MAX }, + { 0, 1, "", MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 3, 0x0000 }, + { 0, 1, +1, 0x0000 }, + { 0, 1, 0, 0x0000 }, + } + } + }, + { /*----------------- #05 -----------------*/ + { + { + { 0, 1, "\343\201\202A", MB_LEN_MAX }, + { 0, 1, "\177\343\201\202", MB_LEN_MAX }, + { 0, 0, (char)NULL, MB_LEN_MAX }, + } + }, + { + { + { 0, 1, 3, 0x0000 }, + { 0, 1, +1, 0x0000 }, + { 0, 0, 0, 0x0000 }, + } + } + }, + { .is_last = 1 } + } + }, +#endif + { + { Tmbtowc, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_strcoll.c b/test/locale-mbwc/dat_strcoll.c new file mode 100644 index 0000000..e12037c --- /dev/null +++ b/test/locale-mbwc/dat_strcoll.c @@ -0,0 +1,209 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_strcoll.c + * + * STRCOLL: int strcoll (const char *s1, const char *s2); + */ + +/* + NOTE: + + If a return value is expected to be 0, set ret_flg=1 and the + expected value = 0. If a return value is expected to be a + positive/negative value, set ret_flg=0, and set the expected value + = +1/-1. + There is inconsistensy between tst_strcoll() and tst_wcscoll()(it + has cmp_flg) for input data. I'll fix it. + + Assuming en_US to be en_US.ascii. (maybe, should be iso8859-1). + + + + ASCII CODE : A,B,C, ... , a, b, c, ... B,a:-1 a,B:+1 + DICTIONARY : A,a,B,b,C,c,.... a,B:-1 B,a:+1 */ + +TST_STRCOLL tst_strcoll_loc [] = { + { + { Tstrcoll, TST_LOC_de }, + { + { /*input.*/ { "ÄBCDEFG", "ÄBCDEFG" }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { "XX Ä XX", "XX B XX" }, /* #2 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "XX B XX", "XX Ä XX" }, /* #3 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "B", "a" }, /* #4 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "a", "B" }, /* #5 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "b", "A" }, /* #6 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "A", "b" }, /* #7 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "ä", "B" }, /* #8 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "B", "ä" }, /* #9 */ + /*expect*/ { 0,0,+1, }, + }, + { .is_last = 1 } /* Last element. */ + } + }, + { + { Tstrcoll, TST_LOC_en }, + { + { /*input.*/ { "ABCDEFG", "ABCDEFG" }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { "XX a XX", "XX B XX" }, /* #2 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "XX B XX", "XX a XX" }, /* #3 */ + /*expect*/ { 0,0,+1, }, + }, + { + /* */ + /*input.*/ { "B", "a" }, /* #4 */ +#ifdef SHOJI_IS_RIGHT + /*expect*/ { 0,0,-1, }, +#else + /* XXX We are not testing the C locale. */ + /*expect*/ { 0,0,+1, }, +#endif + }, + { + /* */ + /*input.*/ { "a", "B" }, /* #5 */ +#ifdef SHOJI_IS_RIGHT + /*expect*/ { 0,0,+1, }, +#else + /* XXX We are not testing the C locale. */ + /*expect*/ { 0,0,-1, }, +#endif + }, + { /*input.*/ { "b", "A" }, /* #6 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "A", "b" }, /* #7 */ + /*expect*/ { 0,0,-1, }, + }, +#ifdef NO_WAIVER + /* XXX I do not yet know whether strcoll really should reject + characters outside the multibyte character range. */ + { + /* #8 */ /* */ + /*input.*/ { "\244\242\244\244\244\246\244\250\244\252", "ABCDEFG" }, + /*expect*/ { EINVAL,0,0, }, + }, + { + /* #9 */ /* */ + /*input.*/ { "ABCZEFG", "\244\242\244\244\244\246\244\250\244\252" }, + /*expect*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { + { Tstrcoll, TST_LOC_eucJP }, + { + { /*input.*/ { "\244\242\244\244\244\246\244\250\244\252", + "\244\242\244\244\244\246\244\250\244\252" }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { "\244\242\244\244\244\246\244\250\244\252", + "\244\242\244\244\244\363\244\250\244\252" }, /* #2 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "\244\242\244\244\244\363\244\250\244\252", + "\244\242\244\244\244\246\244\250\244\252" }, /* #3 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "B", "a" }, /* #4 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "a", "B" }, /* #5 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "b", "A" }, /* #6 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "A", "b" }, /* #7 */ + /*expect*/ { 0,0,-1, }, + }, +#ifdef NO_WAIVER + /* XXX I do not yet know whether strcoll really should reject + characters outside the multibyte character range. */ + { + /* */ + /*input.*/ { "\200\216\217", "ABCDEFG" }, /* #8 */ + /*expect*/ { EINVAL,0,0, }, + }, + { + /* */ + /*input.*/ { "ABCZEFG", "\200\216\217" }, /* #9 */ + /*expect*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } /* Last element. */ + } + }, +#else + { + { Tstrcoll, TST_LOC_ja_UTF8 }, + { + { /*input.*/ { "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212", + "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212" }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212", + "\343\201\202\343\201\204\343\202\223\343\201\210\343\201\212" }, /* #2 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "\343\201\202\343\201\204\343\202\223\343\201\210\343\201\212", + "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212" }, /* #3 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "B", "a" }, /* #4 */ + /*expect*/ { 0,0,-1, }, + }, + { /*input.*/ { "a", "B" }, /* #5 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "b", "A" }, /* #6 */ + /*expect*/ { 0,0,+1, }, + }, + { /*input.*/ { "A", "b" }, /* #7 */ + /*expect*/ { 0,0,-1, }, + }, +#ifdef NO_WAIVER + /* XXX I do not yet know whether strcoll really should reject + characters outside the multibyte character range. */ + { + /* */ + /*input.*/ { "\200\216\217", "ABCDEFG" }, /* #8 */ + /*expect*/ { EINVAL,0,0, }, + }, + { + /* */ + /*input.*/ { "ABCZEFG", "\200\216\217" }, /* #9 */ + /*expect*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } /* Last element. */ + } + }, +#endif + { + { Tstrcoll, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_strfmon.c b/test/locale-mbwc/dat_strfmon.c new file mode 100644 index 0000000..8c28bba --- /dev/null +++ b/test/locale-mbwc/dat_strfmon.c @@ -0,0 +1,268 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_strfmon.c + * + * STRFMON: size_t strfmon (char *buf, size_t nbyte, char *fmt, ... ); + */ + +/* + * NOTE: + * + * The buffer size should be enough to contain a string including a + * null char. + * Returns the number of bytes of the string (NOT including a null char). + */ + +TST_STRFMON tst_strfmon_loc [] = { + { + { Tstrfmon, TST_LOC_de }, + { + { + /* #01 */ + /*inp*/ { 24, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,23, "123,00 EUR % 123,00 EUR" }, + }, + { + /* #02 */ + /*inp*/ { 24, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,23, "123,00 EUR % 123,00 EUR" }, + }, + { + /* #03 */ + /*inp*/ { 23, "%n %% %i", 123.00 }, + /*exp*/ { E2BIG,1,-1, "" }, + }, + { + /* #04 */ + /*inp*/ { 31, "%n|%i", 1234.561 }, + /*exp*/ { 0,1,25, "1.234,56 EUR|1.234,56 EUR"}, + }, + { + /* #05 */ + /*inp*/ { 33, "%n|%i", -1234.561 }, + /*exp*/ { 0,1,27, "-1.234,56 EUR|-1.234,56 EUR"}, + }, + { + /* #06 */ + /*inp*/ { 33, "%13n|%12i", 1234.561 }, + /*exp*/ { 0,1,26, " 1.234,56 EUR|1.234,56 EUR"}, + }, + { + /* #07 */ + /*inp*/ { 33, "%12n|%12i", -1234.561 }, + /*exp*/ { 0,1,27, "-1.234,56 EUR|-1.234,56 EUR"}, + }, + { + /* #08 */ + /*inp*/ { 33, "%#5n|%#5i", 1234.561 }, + /*exp*/ { 0,1,29, " 1.234,56 EUR| 1.234,56 EUR"}, + }, + { + /* #09 */ + /*inp*/ { 33, "%#5n|%#5i", -1234.561 }, + /*exp*/ { 0,1,29, "- 1.234,56 EUR|- 1.234,56 EUR"}, + }, + { + /* #10 */ + /*inp*/ { 33, "%=*#5n|%=*#5i", 1234.561 }, + /*exp*/ { 0,1,29, " *1.234,56 EUR| *1.234,56 EUR"}, + }, + { + /* #11 */ + /*inp*/ { 33, "%=0#5n|%=0#5i", -1234.561 }, + /*exp*/ { 0,1,29, "-01.234,56 EUR|-01.234,56 EUR"}, + }, + { + /* #12 */ + /*inp*/ { 33, "%^#5n|%^#5i", -1234.561 }, + /*exp*/ { 0,1,27, "- 1234,56 EUR|- 1234,56 EUR"}, + }, + { + /* #13 */ + /*inp*/ { 33, "%#5.0n|%#5.0i", 1234.444 }, + /*exp*/ { 0,1,23, " 1.234 EUR| 1.234 EUR" }, + }, + { + /* #14 */ + /*inp*/ { 33, "%#5.0n|%#5.4i", -1234.555 }, + /*exp*/ { 0,1,28, "- 1.235 EUR|- 1.234,5550 EUR"}, + }, + { + /* #15 */ + /*inp*/ { 33, "%(#5n|%!(#5i", -1234.561 }, + /*exp*/ { 0,1,27, "( 1.234,56 EUR)|( 1.234,56)"}, + }, + { .is_last = 1 } + } + }, + { + { Tstrfmon, TST_LOC_enUS }, + { + { + /* #01 */ + /*inp*/ { 22, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,20, "$123.00 % USD 123.00" }, + }, + { + /* #02 */ + /*inp*/ { 21, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,20, "$123.00 % USD 123.00" }, + }, + { + /* #03 */ + /*inp*/ { 20, "%n %% %i", 123.00 }, + /*exp*/ { E2BIG,1,-1, "" }, + }, + { + /* #04 */ + /*inp*/ { 30, "%n|%i", 1234.561 }, + /*exp*/ { 0,1,22, "$1,234.56|USD 1,234.56" }, + }, + { + /* #05 */ + /*inp*/ { 32, "%n|%i", -1234.561 }, + /*exp*/ { 0,1,24, "-$1,234.56|-USD 1,234.56" }, + }, + { + /* #06 */ + /*inp*/ { 30, "%12n|%12i", 1234.561 }, + /*exp*/ { 0,1,25, " $1,234.56|USD 1,234.56"}, + }, + { + /* #07 */ + /*inp*/ { 32, "%12n|%12i", -1234.561 }, + /*exp*/ { 0,1,26, " -$1,234.56|-USD 1,234.56"}, + }, + { + /* #08 */ + /*inp*/ { 32, "%#5n|%#5i", 1234.561 }, + /*exp*/ { 0,1,26, " $ 1,234.56| USD 1,234.56"}, + }, + { + /* #09 */ + /*inp*/ { 32, "%#5n|%#5i", -1234.561 }, + /*exp*/ { 0,1,26, "-$ 1,234.56|-USD 1,234.56"}, + }, + { + /* #10 */ + /*inp*/ { 32, "%=*#5n|%=*#5i", 1234.561 }, + /*exp*/ { 0,1,26, " $*1,234.56| USD *1,234.56"}, + }, + { + /* #11 */ + /*inp*/ { 32, "%=0#5n|%=0#5i", -1234.561 }, + /*exp*/ { 0,1,26, "-$01,234.56|-USD 01,234.56"}, + }, + { + /* #12 */ + /*inp*/ { 32, "%^#5n|%^#5i", -1234.561 }, + /*exp*/ { 0,1,24, "-$ 1234.56|-USD 1234.56" }, + }, + { + /* #13 */ + /*inp*/ { 32, "%#5.0n|%#5.0i", 1234.444 }, + /*exp*/ { 0,1,20, " $ 1,234| USD 1,234" }, + }, + { + /* #14 */ + /*inp*/ { 32, "%#5.0n|%#5.4i", -1234.555 }, + /*exp*/ { 0,1,25, "-$ 1,235|-USD 1,234.5550"}, + }, + { + /* #15 */ + /*inp*/ { 32, "%(#5n|%!(#5i", -1234.561 }, + /*exp*/ { 0,1,24, "($ 1,234.56)|( 1,234.56)" }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Tstrfmon, TST_LOC_eucJP }, +#else + { Tstrfmon, TST_LOC_ja_UTF8 }, +#endif + { + { + /* #01 */ + /*inp*/ { 17, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,15, "\241\357123 % JPY 123" }, + }, + { + /* #02 */ + /*inp*/ { 16, "%n %% %i", 123.00 }, + /*exp*/ { 0,1,15, "\241\357123 % JPY 123" }, + }, + { + /* #03 */ + /*inp*/ { 15, "%n %% %i", 123.00 }, + /*exp*/ { E2BIG,1,-1, "" }, + }, + { + /* #04 */ + /*inp*/ { 30, "%n|%i", 1234.561 }, + /*exp*/ { 0,1,17, "\241\3571,235|JPY 1,235" }, + }, + { + /* #05 */ + /*inp*/ { 32, "%n|%i", -1234.561 }, + /*exp*/ { 0,1,19, "\241\357-1,235|JPY -1,235" }, + }, + { + /* #06 */ + /*inp*/ { 32, "%12n|%12i", 1234.561 }, + /*exp*/ { 0,1,25, " \241\3571,235| JPY 1,235" }, + }, + { + /* #07 */ + /*inp*/ { 32, "%12n|%12i", -1234.561 }, + /*exp*/ { 0,1,25, " \241\357-1,235| JPY -1,235" }, + }, + { + /* #08 */ + /*inp*/ { 32, "%#5n|%#5i", 1234.561 }, + /*exp*/ { 0,1,21, " \241\357 1,235| JPY 1,235" }, + }, + { + /* #09 */ + /*inp*/ { 32, "%#5n|%#5i", -1234.561 }, + /*exp*/ { 0,1,21, "\241\357- 1,235|JPY - 1,235" }, + }, + { + /* #10 */ + /*inp*/ { 32, "%=*#5n|%=*#5i", 1234.561 }, + /*exp*/ { 0,1,21, " \241\357*1,235| JPY *1,235" }, + }, + { + /* #11 */ + /*inp*/ { 32, "%=0#5n|%=0#5i", -1234.561 }, + /*exp*/ { 0,1,21, "\241\357-01,235|JPY -01,235" }, + }, + { + /* #12 */ + /*inp*/ { 32, "%^#5n|%^#5i", -1234.561 }, + /*exp*/ { 0,1,19, "\241\357- 1235|JPY - 1235" }, + }, + { + /* #13 */ + /*inp*/ { 32, "%#5.0n|%#5.0i", 1234.444 }, + /*exp*/ { 0,1,21, " \241\357 1,234| JPY 1,234" }, + }, + { + /* #14 */ + /*inp*/ { 32, "%#5.0n|%#5.4i", -1234.555 }, + /*exp*/ { 0,1,26, "\241\357- 1,235|JPY - 1,234.5550"}, + }, + { + /* #15 */ + /*inp*/ { 32, "%(#5n|%!(#5i", -1234.561 }, + /*exp*/ { 0,1,19, "(\241\357 1,235)|( 1,235)" }, + }, + { .is_last = 1 } + } + }, + { + { Tstrfmon, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_strxfrm.c b/test/locale-mbwc/dat_strxfrm.c new file mode 100644 index 0000000..0c672d3 --- /dev/null +++ b/test/locale-mbwc/dat_strxfrm.c @@ -0,0 +1,147 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_strxfrm.c + * + * STRXFRM: size_t strxfrm (char *s1, const char s2, size_t n); + */ + + +/* + * NOTE: + * + * Return value and errno value are checked only for 2nd string: + * org2[]; n1 and n2 don't mean bytes to be translated. + * It means a buffer size including a null character. + * Results of this test depens on results of strcoll(). + * If you got errors, check both test results. + * + * The buffer size should be enough to contain a string including a + * null char. Returns the number of bytes of the string (NOT + * including a null char). + */ + + + +TST_STRXFRM tst_strxfrm_loc [] = { + { + { Tstrxfrm, TST_LOC_de }, + { + { /*inp*/ { "\xf6\xc4\xe4\xfc", "\xf6\xc4\xe4\xfc", 17, 17 }, /* #01 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "aA", "Aa", 10, 10 }, /* #02 */ + /*exp*/ { 0,0,0 , }, + }, + { /*inp*/ { "Aa", "aA", 10, 10 }, /* #03 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "abc", "", 13, 13 }, /* #04 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "a", "B", 7, 7 }, /* #05 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "B", "a", 7, 7 }, /* #06 */ + /*exp*/ { 0,0,0, }, + }, + { + /* hiragana == latin1 */ + /*inp*/ { "abc", "\244\241\244\242", 13, 9 }, /* #07 */ + /*exp*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { + { Tstrxfrm, TST_LOC_enUS }, + { + { /*inp*/ { "abcd", "abcd", 17, 17 }, /* #01 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "aA", "Aa", 10, 10 }, /* #02 */ + /*exp*/ { 0,0,0 , }, + }, + { /*inp*/ { "Aa", "aA", 10, 10 }, /* #03 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "abc", "", 13, 13 }, /* #04 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "a", "B", 7, 7 }, /* #05 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "B", "a", 7, 7 }, /* #06 */ + /*exp*/ { 0,0,0, }, + }, +#ifdef NO_WAIVER + { + /* */ + /*inp*/ { "abc", "\244\241\244\242", 13, 9 }, /* #07 */ + /*exp*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } + } + }, +#if 0 + { + { Tstrxfrm, TST_LOC_eucJP }, /* ??? */ + { + { + /* #01 */ + /*inp*/ { "\244\242\244\241", "\244\241\244\242", 5, 5 }, + /*exp*/ { 0,0,0, }, + }, + { + /* #02 */ + /*inp*/ { "\244\241\244\242", "\244\242\244\241", 5, 5 }, + /*exp*/ { 0,0,0, }, + }, + { + /* #03 */ + /*inp*/ { "\244\242\216\261", "\216\261\244\242", 5, 5 }, + /*exp*/ { 0,0,0, }, + }, +#ifdef NO_WAIVER + { + /*inp*/ { "AAA", "\216\217", 5, 5 }, /* #04 */ /* */ + /*exp*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } + } + }, +#else + { + { Tstrxfrm, TST_LOC_ja_UTF8 }, /* ??? */ + { + { + /* #01 */ + /*inp*/ { "\343\201\202\343\201\201", "\343\201\201\343\201\202", 7, 7 }, + /*exp*/ { 0,0,0, }, + }, + { + /* #02 */ + /*inp*/ { "\343\201\201\343\201\202", "\343\201\202\343\201\201", 7, 7 }, + /*exp*/ { 0,0,0, }, + }, + { + /* #03 */ + /*inp*/ { "\343\201\202\357\275\261", "\357\275\261343\201\202", 7, 7 }, + /*exp*/ { 0,0,0, }, + }, +#ifdef NO_WAIVER + { + /*inp*/ { "AAA", "\340\277\220", 5, 5 }, /* #04 */ /* */ + /*exp*/ { EINVAL,0,0, }, + }, +#endif + { .is_last = 1 } + } + }, +#endif + { + { Tstrxfrm, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_swscanf.c b/test/locale-mbwc/dat_swscanf.c new file mode 100644 index 0000000..088f165 --- /dev/null +++ b/test/locale-mbwc/dat_swscanf.c @@ -0,0 +1,185 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_swscanf.c + * + * SWSCANF: int swscanf (const wchar_t *s, const wchar_t *fmt, ...); + */ + + +#include +#include +#include "tst_types.h" +#include "tgn_locdef.h" + + +TST_SWSCANF tst_swscanf_loc [] = +{ + { + { Tswscanf, TST_LOC_de }, + { + /*------------------------ 01 -----------------------*/ + { { { + 0x002D, 0x0031, 0x003A, /* %d: -1 */ + 0x0032, 0x003A, /* %u: 2 */ + 0x0033, 0x002C, 0x0033, 0x003A, /* %f: 3.3 */ + 0x00E4, 0x003A, /* %c: 'ä' */ + 0x00C4, 0x00DC, 0x0000, 0x0000, /* %s: "ÄÜ" */ + }, + L"%d:%u:%f:%c:%s", 0 + }, + { /* The fields are: err_val, ret_flag, ret_val, + val_int, val_uns, val_flt, val_c, val_s, val_S. */ + 0,1,5, + -1, 2, 3.3, 'ä', "ÄÜ", { 0x0000, }, + }, + }, + /*------------------------ 02 -----------------------*/ + { { { + 0x00E4, 0x00C4, 0x0000 /* "äÄ" */ + }, + L"%lc", 'C' + }, + { 0,1,1, + 0,0,0,0,"", { 0x00E4, 0x0000 }, + }, + }, + /*------------------------ 03 -----------------------*/ + { { { + 0x00E4, 0x00C4, 0x0000 /* "äÄ" */ + }, + L"%ls", 'S' + }, + { 0,1,1, + 0,0,0,0,"", { 0x00E4, 0x00C4, 0x0000 }, + }, + }, + /*------------------------ 04 -----------------------*/ + /* x 2 */ + { { { + 0x00E4, 0x00C4, 0x0000 /* "äÄ" */ + }, + L"1%d:2%d:3%d:4%d:5%d:6%d:7%d:8%d:9%d", 0 + }, +#ifdef SHOJI_IS_RIGHT + { 1,EINVAL,1,WEOF, + 0,0,0,0,"", { 0x0000 }, +#else + { 0,1,0, + 0,0,0,0,"", { 0x0000 }, +#endif + }, + }, + /*---------------------------------------------------*/ + { .is_last = 1} /* Last element. */ + } + }, + { + { Tswscanf, TST_LOC_enUS }, + { + /*------------------------ 01 -----------------------*/ + { { { 0x002D, 0x0031, 0x003A, + 0x0032, 0x003A, + 0x0035, 0x0034, 0x002E, 0x0033, 0x0045, 0x002D, 0x0031, 0x003A, + 0x0041, 0x003A, + 0x0061, 0x0062, 0x0000, 0x0000, + }, + L"%d:%u:%f:%c:%s", 0 + }, + { 0,1,5, + -1, 2, 5.43, 'A', "ab", { 0x0000 }, + }, + }, + /*------------------------ 02 -----------------------*/ + /* x 2 */ + { { { + 0x0063, 0x0064, 0x0000 + }, + L"%C", 'C' + }, + { 0,1,1, + 0,0,0,0,"", { 0x0063, 0x0000 }, + }, + }, + /*------------------------ 03 -----------------------*/ + { { { + 0x0063, 0x0064, 0x0000 + }, + L"%S", 'S' + }, + { 0,1,1, + 0,0,0,0,"", { 0x0063, 0x0064, 0x0000 }, + }, + }, + /*---------------------------------------------------*/ + { .is_last = 1} /* Last element. */ + } + }, + { +#if 0 + { Tswscanf, TST_LOC_eucJP }, +#else + { Tswscanf, TST_LOC_ja_UTF8 }, +#endif + { + /*------------------------ 01 -----------------------*/ + { { { 0x002D, 0x0031, 0x003A, + 0x0032, 0x003A, + 0x0033, 0x002E, 0x0033, 0x003A, + 0x0062, 0x003A, + 0x0061, 0x0062, 0x0000, 0x0000, + }, + L"%d:%u:%f:%c:%s", 0 + }, + { 0,1,5, + -1, 2, 3.3, 'b', "ab", { 0x0000 } + }, + }, + /*------------------------ 02 -----------------------*/ + { { { + 0x30A2, 0x30A4, 0x0000 + }, + L"%ls", 'S' + }, + { 0,1,1, + 0,0,0,0,"", { 0x30A2, 0x30A4, 0x0000 } + }, + }, + /*------------------------ 03 -----------------------*/ + { { { + 0x0031, 0x003A, + 0x0030, 0x003A, + 0x0033, 0x002E, 0x0039, 0x003A, + 0x0061, 0x003A, + 0x0063, 0x0064, 0x0000, 0x0000, + }, + L"%2$d:%1$u:%3$f:%4$c:%5$s", 0 + }, + { 0,1,5, + 0, 1, 3.9, 'a', "cd", { 0x0000 } + }, + }, +#ifdef SHOJI_IS_RIGHT + /* XXX This test does not make sense. The format string is + L"\x1\x2\x25\x53" and it is supposed to match the words + 0x30A2, 0x30A4, 0x0001. */ + /*------------------------ 04 -----------------------*/ + /* x 2 */ + { { { + 0x30A2, 0x30A4, 0x0001, 0x0000 + }, + { 0x0001,0x0002,0x0025,0x0053,0x0000 }, 'S' + }, + { EILSEQ,1,EOF, + 0,0,0,0,"", { 0x0000 } + }, + }, +#endif + /*---------------------------------------------------*/ + { .is_last = 1} /* Last element. */ + } + }, + { + { Tswscanf, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_tow-funcs.h b/test/locale-mbwc/dat_tow-funcs.h new file mode 100644 index 0000000..4456437 --- /dev/null +++ b/test/locale-mbwc/dat_tow-funcs.h @@ -0,0 +1,24 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_tow-funcs.h + * + * ISW*: int tow*( wint_t wc ); + */ + +#include +#include +#include +#include "tst_types.h" +#include "tgn_locdef.h" + +#define TST_TOW_LOC(FUNC, func) \ + TST_TOW## FUNC tst_tow## func ##_loc[] + +#define TST_TOW_REC(locale, func) \ + { Ttow## func, TST_LOC_## locale }, + +/* + * NOTE: + * need more test data! + */ diff --git a/test/locale-mbwc/dat_towctrans.c b/test/locale-mbwc/dat_towctrans.c new file mode 100644 index 0000000..cf3712a --- /dev/null +++ b/test/locale-mbwc/dat_towctrans.c @@ -0,0 +1,97 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_towctrans.c + * + * TOWCTRANS: wint_t towctrans (wint_t wc, wctrans_t charclass); + */ + +#include +#include +#include +#include "tst_types.h" +#include "tgn_locdef.h" + +/* + * NOTE: + * Set ret_flg = 1, when a return value is expected to be 0 (FALSE). + * Set ret_flg = 0, when a return value is expected to be non-zero (TRUE). + * + * Since the functions return *non*-zero value for TRUE, can't + * compare an actual return value with an expected return value. + * Set the ret_flg=0 for TRUE cases and the tst_isw*() will check + * the non-zero value. + * + * { { WEOF }, { 0,0,1,0 } }, + * | | + * | ret_val: an expected return value + * ret_flg: if 1, compare an actual return value with the + * ret_val; if 0, the test program checks + * the actual return value. + * + * CAUTION: if a charclass is invalid, the test function gives + * towctrans() an invalid wctrans object instead of a return value + * from wctrans() which is supposed to be 0. + */ + +TST_TOWCTRANS tst_towctrans_loc [] = { + { + { Ttowctrans, TST_LOC_C }, + { +#ifdef SHOJI_IS_RIGHT + { { 0x0010, "xxxxxxx" }, { EINVAL,1,0x0010 } }, +#else + { { 0x0010, "xxxxxxx" }, { 0, 1,0x0010 } }, +#endif + { { 0x007F, "tolower" }, { 0, 1,0x007F } }, + { { 0x0061, "toupper" }, { 0, 1,0x0041 } }, + { { 0x0041, "tolower" }, { 0, 1,0x0061 } }, + { .is_last = 1 } + } + }, + { + { Ttowctrans, TST_LOC_de }, + { +#ifdef SHOJI_IS_RIGHT + { { 0x0010, "tojkata" }, { EINVAL,1,0x0010 } }, +#else + { { 0x0010, "tojkata" }, { 0, 1,0x0010 } }, +#endif + { { 0x0080, "tolower" }, { 0, 1,0x0080 } }, + { { 0x00EC, "toupper" }, { 0, 1,0x00CC } }, + { { 0x00CC, "tolower" }, { 0, 1,0x00EC } }, + { .is_last = 1 } + } + }, + { + { Ttowctrans, TST_LOC_enUS }, + { +#ifdef SHOJI_IS_RIGHT + { { 0x0010, "xxxxxxx" }, { EINVAL,1,0x0010 } }, +#else + { { 0x0010, "xxxxxxx" }, { 0, 1,0x0010 } }, +#endif + { { 0x007F, "tolower" }, { 0, 1,0x007F } }, + { { 0x0061, "toupper" }, { 0, 1,0x0041 } }, + { { 0x0041, "tolower" }, { 0, 1,0x0061 } }, + { .is_last = 1 } + } + }, + { +#if 0 + { Ttowctrans, TST_LOC_eucJP }, +#else + { Ttowctrans, TST_LOC_ja_UTF8 }, +#endif + { + { { 0xFF21, "tolower" }, { 0, 1,0xFF41 } }, + { { 0xFF41, "toupper" }, { 0, 1,0xFF21 } }, + { { 0x30A1, "tojhira" }, { 0, 1,0x3041 } }, + { { 0x3041, "tojkata" }, { 0, 1,0x30A1 } }, + { .is_last = 1 } + } + }, + { + { Ttowctrans, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_towlower.c b/test/locale-mbwc/dat_towlower.c new file mode 100644 index 0000000..b6dd275 --- /dev/null +++ b/test/locale-mbwc/dat_towlower.c @@ -0,0 +1,47 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_towlower.c + * + * ISW*: int towlower (wint_t wc); + */ + + +#include "dat_tow-funcs.h" + + +TST_TOW_LOC (LOWER, lower) = { + + { TST_TOW_REC (de, lower) + { + { { WEOF }, { 0, 1, (wint_t)-1 } }, + { { 0x0080 }, { 0, 1, 0x0080 } }, + { { 0x00CC }, { 0, 1, 0x00EC } }, + { { 0x00EC }, { 0, 1, 0x00EC } }, + { .is_last = 1 } /* Last element. */ + } + }, + { TST_TOW_REC (enUS, lower) + { + { { WEOF }, { 0, 1, (wint_t)-1 } }, + { { 0x007F }, { 0, 1, 0x007F } }, + { { 0x0041 }, { 0, 1, 0x0061 } }, + { { 0x0061 }, { 0, 1, 0x0061 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_TOW_REC (eucJP, lower) +#else + { TST_TOW_REC (ja_UTF8, lower) +#endif + { + { { 0x007F }, { 0, 1, 0x007F } }, + { { 0x0080 }, { 0, 1, 0x0080 } }, + { { 0xFF21 }, { 0, 1, 0xFF41 } }, + { { 0xFF41 }, { 0, 1, 0xFF41 } }, + { .is_last = 1 } /* Last element. */ + } + }, + { TST_TOW_REC (end, lower) } +}; diff --git a/test/locale-mbwc/dat_towupper.c b/test/locale-mbwc/dat_towupper.c new file mode 100644 index 0000000..704ad44 --- /dev/null +++ b/test/locale-mbwc/dat_towupper.c @@ -0,0 +1,47 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_towupper.c + * + * ISW*: int towupper (wint_t wc); + */ + + +#include "dat_tow-funcs.h" + + +TST_TOW_LOC (UPPER, upper) = { + + { TST_TOW_REC (de, upper) + { + { { WEOF }, { 0, 1, (wint_t)-1 } }, + { { 0x0080 }, { 0, 1, 0x0080 } }, + { { 0x00EC }, { 0, 1, 0x00CC } }, + { { 0x00CC }, { 0, 1, 0x00CC } }, + { .is_last = 1 } /* Last element. */ + } + }, + { TST_TOW_REC (enUS, upper) + { + { { WEOF }, { 0, 1, (wint_t)-1 } }, + { { 0x0080 }, { 0, 1, 0x0080 } }, + { { 0x0041 }, { 0, 1, 0x0041 } }, + { { 0x0061 }, { 0, 1, 0x0041 } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { TST_TOW_REC (eucJP, upper) +#else + { TST_TOW_REC (ja_UTF8, upper) +#endif + { + { { WEOF }, { 0, 1, (wint_t)-1 } }, + { { 0x007F }, { 0, 1, 0x007F } }, + { { 0xFF41 }, { 0, 1, 0xFF21 } }, + { { 0xFF21 }, { 0, 1, 0xFF21 } }, + { .is_last = 1 } /* Last element. */ + } + }, + { TST_TOW_REC (end, upper) } +}; diff --git a/test/locale-mbwc/dat_wcrtomb.c b/test/locale-mbwc/dat_wcrtomb.c new file mode 100644 index 0000000..055f7b0 --- /dev/null +++ b/test/locale-mbwc/dat_wcrtomb.c @@ -0,0 +1,122 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcrtomb.c + * + * WCRTOMB: intwcrtomb (char *s, wchar_t wc, mbstate_t *ps); + * + */ + +TST_WCRTOMB tst_wcrtomb_loc [] = { + { + { Twcrtomb, TST_LOC_de }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x00FC, 0,0 }, + /*expect*/ { 0, 1,1, "ü" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x00D6, 0,0 }, + /*expect*/ { 0, 1,1, "Ö" }, + }, + /* #03 : error case */ + { /*input.*/ { 1, 0xFFA1, 0,0 }, + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #04 : */ + { /*input.*/ { 0, 0x0041, 0,0 }, + /*expect*/ { 0, 1,1, "" }, + }, + /* #05 : */ + { /*input.*/ { 0, 0x0092, 0,0 }, + /*expect*/ { 0, 1,1, "" }, + }, + { .is_last = 1 } + } + }, + { + { Twcrtomb, TST_LOC_enUS }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x0041, 0,0 }, + /*expect*/ { 0, 1,1, "A" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x0042, 0,0 }, + /*expect*/ { 0, 1,1, "B" }, + }, + /* #03 : error case */ + /* x 2 */ + { /*input.*/ { 1, 0x0092, 0,0 }, /* assume ascii */ + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #04 : */ + { /*input.*/ { 0, 0x0041, 0,0 }, + /*expect*/ { 0, 1,1, "" }, + }, + /* #05 : */ + { /*input.*/ { 0, 0x0092, 0,0 }, + /*expect*/ { 0, 1,1, "" }, + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Twcrtomb, TST_LOC_eucJP }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x3042, 0,0 }, + /*expect*/ { 0, 1,2, "\244\242" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x3044, 0,0 }, + /*expect*/ { 0, 1,2, "\244\244" }, + }, + /* #03 : normal case */ + { /*input.*/ { 1, 0x008E, 0,0 }, + /*expect*/ { EILSEQ, 1,-1, "" }, + }, + /* #04 : */ + { /*input.*/ { 0, 0x3042, 0,0 }, + /*expect*/ { 0, 0,0, "" }, + }, + /* #05 : */ + { /*input.*/ { 0, 0x008E, 0,0 }, + /*expect*/ { 0, 0,0, "" }, + }, + { .is_last = 1 } + } + }, +#else + { + { Twcrtomb, TST_LOC_ja_UTF8 }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x3042, 0,0 }, + /*expect*/ { 0, 1,3, "\343\201\202" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x3044, 0,0 }, + /*expect*/ { 0, 1,3, "\343\201\204" }, + }, + /* #03 : normal case */ + { /*input.*/ { 1, 0x008E, 0,0 }, + /*expect*/ { EILSEQ, 1,-1, "" }, + }, + /* #04 : */ + { /*input.*/ { 0, 0x3042, 0,0 }, + /*expect*/ { 0, 0,0, "" }, + }, + /* #05 : */ + { /*input.*/ { 0, 0x008E, 0,0 }, + /*expect*/ { 0, 0,0, "" }, + }, + { .is_last = 1 } + } + }, +#endif + { + { Twcrtomb, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcscat.c b/test/locale-mbwc/dat_wcscat.c new file mode 100644 index 0000000..f54e72d --- /dev/null +++ b/test/locale-mbwc/dat_wcscat.c @@ -0,0 +1,116 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcscat.c + * + * WCSCAT: wchar_t *wcscat (wchar_t *ws1, wchar_t *ws2) + */ + +/* NOTE: + Since this is not a locale sensitive function, + it doesn't make sense to test the function on some + locales. Better make different test cases for each locale ... + (Also some wc* functions are not locale sensitive.) +*/ + + +TST_WCSCAT tst_wcscat_loc [] = { + + { + {Twcscat, TST_LOC_de}, + { + /* 1 */ + {{{ 0x00C1,0x00C2,0x0000 }, + { 0x00C3,0x00C4,0x0000 }, }, + { 0, 0, 0, + { 0x00C1,0x00C2,0x00C3,0x00C4,0x0000 } }, + }, + /* 2 */ + {{{ 0x0001,0x0002,0x0000 }, + { 0x0003,0x0004,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0x0002,0x0003,0x0004,0x0000 } }, + }, + /* 3 */ + {{{ 0x0000 }, + { 0x00C3,0x00C4,0x0000 }, }, + { 0, 0, 0, + { 0x00C3,0x00C4,0x0000 } }, + }, + /* 4 */ + {{{ 0x0001,0xFFFF,0x0000 }, + { 0x0080,0x0090,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0xFFFF,0x0080,0x0090,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcscat, TST_LOC_enUS}, + { + /* 1 */ + {{{ 0x0041,0x0042,0x0000 }, + { 0x0043,0x0044,0x0000 }, }, + { 0, 0, 0, + { 0x0041,0x0042,0x0043,0x0044,0x0000 } }, + }, + /* 2 */ + {{{ 0x0001,0x0002,0x0000 }, + { 0x0003,0x0004,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0x0002,0x0003,0x0004,0x0000 } }, + }, + /* 3 */ + {{{ 0x0000 }, + { 0x0043,0x0044,0x0000 }, }, + { 0, 0, 0, + { 0x0043,0x0044,0x0000 } }, + }, + /* 4 */ + {{{ 0x0001,0xFFFF,0x0000 }, + { 0x0080,0x0090,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0xFFFF,0x0080,0x0090,0x0000 } }, + }, + {.is_last = 1} + } + }, + { +#if 0 + {Twcscat, TST_LOC_eucJP}, +#else + {Twcscat, TST_LOC_ja_UTF8}, +#endif + { + /* 1 */ + {{{ 0x30A2,0x74E0,0x0000 }, + { 0xFF71,0x0041,0x0000 }, }, + { 0, 0, 0, + { 0x30A2,0x74E0,0xFF71,0x0041,0x0000 } }, + }, + /* 2 */ + {{{ 0x0001,0x0002,0x0000 }, + { 0x0003,0x0004,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0x0002,0x0003,0x0004,0x0000 } }, + }, + /* 3 */ + {{{ 0x30A2,0xFF71,0x0000 }, + { 0x0000 }, }, + { 0, 0, 0, + { 0x30A2,0xFF71,0x0000 } }, + }, + /* 4 */ + {{{ 0x0001,0xFFFF,0x0000 }, + { 0x0080,0x0090,0x0000 }, }, + { 0, 0, 0, + { 0x0001,0xFFFF,0x0080,0x0090,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcscat, TST_LOC_end} + } +}; diff --git a/test/locale-mbwc/dat_wcschr.c b/test/locale-mbwc/dat_wcschr.c new file mode 100644 index 0000000..aa355e9 --- /dev/null +++ b/test/locale-mbwc/dat_wcschr.c @@ -0,0 +1,94 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcschr.c + * + * WCSCHR: wchar_t *wcschr (const wchar_t *ws, wchar_t wc); + */ + +TST_WCSCHR tst_wcschr_loc [] = { + + { { Twcschr, TST_LOC_de }, + { + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C0 }, /* #1 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C1 }, /* #2 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C2 }, /* #3 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C3 }, /* #4 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x0000 }, /* #5 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0000,0x00C2,0x00C3,0x0000 }, 0x00C1 }, /* #6 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x0000,0x00C2,0x00C3,0x0000 }, 0x0000 }, /* #7 */ + /*expect*/ { 0,0,0 }, + }, + { .is_last = 1 } + } + }, + { { Twcschr, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0040 }, /* #1 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0041 }, /* #2 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0042 }, /* #3 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0043 }, /* #4 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0000 }, /* #5 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, 0x0041 }, /* #6 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, 0x0000 }, /* #7 */ + /*expect*/ { 0,0,0 }, + }, + { .is_last = 1 } + } + }, +#if 0 + { { Twcschr, TST_LOC_eucJP }, +#else + { { Twcschr, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3040 }, /* #1 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3041 }, /* #2 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3042 }, /* #3 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3043 }, /* #4 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x0000 }, /* #5 */ + /*expect*/ { 0,0,0 }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, 0x3041 }, /* #6 */ + /*expect*/ { 0,1,(wchar_t *)NULL }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, 0x0000 }, /* #7 */ + /*expect*/ { 0,0,0 }, + }, + { .is_last = 1 } + } + }, + { { Twcschr, TST_LOC_end } } +}; diff --git a/test/locale-mbwc/dat_wcscmp.c b/test/locale-mbwc/dat_wcscmp.c new file mode 100644 index 0000000..a2da551 --- /dev/null +++ b/test/locale-mbwc/dat_wcscmp.c @@ -0,0 +1,137 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcscmp.c + * + * WCSCMP: int wcscmp (const wchar_t *ws1, const wchar_t *ws2); + */ + +/* NOTE: + This is not a locale sensitive function and + it may not make sence testing it for each locale ... +*/ + + +TST_WCSCMP tst_wcscmp_loc [] = { + { + { Twcscmp, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x00D1,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x00D3,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D1,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x00D3,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D1,0x00D3,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x00D1,0x00D5,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D9,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x0000 }, + { 0x00D1,0x00D2,0x00D9,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D9,0x0000 }, + { 0x00D1,0x00D2,0x0000 }, }, /* #8 */ + /*expect*/ { 0,1,1, }, + }, + { .is_last = 1 } + } + }, + { + { Twcscmp, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x0041,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0041,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0041,0x0041,0x0043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x0041,0x0045,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0049,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0000 }, + { 0x0041,0x0042,0x0049,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0049,0x0000 }, + { 0x0041,0x0042,0x0000 }, }, /* #8 */ + /*expect*/ { 0,1,1, }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcscmp, TST_LOC_eucJP}, +#else + { Twcscmp, TST_LOC_ja_UTF8}, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x3041,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3041,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3041,0x3041,0x3043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x3041,0x3045,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3049,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x0000 }, + { 0x3041,0x3042,0x3049,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,-1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3049,0x0000 }, + { 0x3041,0x3042,0x0000 }, }, /* #8 */ + /*expect*/ { 0,1,1, }, + }, + { .is_last = 1 } + } + }, + { + { Twcschr, TST_LOC_end} + } +}; diff --git a/test/locale-mbwc/dat_wcscoll.c b/test/locale-mbwc/dat_wcscoll.c new file mode 100644 index 0000000..a9733ad --- /dev/null +++ b/test/locale-mbwc/dat_wcscoll.c @@ -0,0 +1,210 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcscoll.c + * + * WCSCOLL: int wcscoll (const wchar_t *ws1, const wchar_t *ws2); + */ + +/* + * CAUTION: + * When LC_COLLATE (or LC_ALL) is set for ja_JP.EUC, + * wcscoll() core-dumps for big values such as 0x3041 + * (0x0041 is okay) in glibc 2.1.2. + * + * NOTE: + * a) When 0 is expected as a return value, set ret_flg=1. + * - the return value is compared with an expected value: ret_val. + * b) When a positive value is expected as a return value, + * set ret_flg=0 and set cmp_flg=+1. + * - the return value is not compared with the expected value + * (can not be compared); instead, the test program checks + * if the return value is positive when cmp_flg=+1. + * c) When a negative value is expected as a return value, + * ...... + * d) When data contains invalid values, set err_val to the expected errno. + * Set ret_flg=0 and cmp_flg=0 so that it doesn't compare + * the return value with an expected value or doesn't check + * the sign of the return value. + * + * + * ------------------------------------------- + * CASE err_val ret_flg ret_val cmp_flg + * ------------------------------------------- + * a) 0 1 0 0 + * b) 0 0 0 +1 + * c) 0 0 0 -1 + * d) EINVAL 0 0 0 + * ------------------------------------------- + */ + + +TST_WCSCOLL tst_wcscoll_loc [] = { + + { { Twcscoll, TST_LOC_de }, + { + { /*input.*/ { { 0x00E1,0x00E2,0x00E3,0x0000 }, + { 0x00E1,0x00E2,0x00E3,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x0000,0x00E1,0x00E3,0x0000 }, + { 0x0000,0x00E2,0x00E3,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x00E1,0x00E1,0x00E3,0x0000 }, + { 0x0000,0x00E2,0x00E3,0x0000 }, }, /* #3 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x0000,0x00E2,0x00E3,0x0000 }, + { 0x00E1,0x00E1,0x00E3,0x0000 }, }, /* #4 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x00E1,0x0042,0x00E3,0x0000 }, + { 0x00E1,0x0061,0x00E3,0x0000 }, }, /* #5 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x00E1,0x0061,0x00E3,0x0000 }, + { 0x00E1,0x0042,0x00E3,0x0000 }, }, /* #6 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x00E1,0x00E2,0x0000 }, + { 0x00E1,0x00E2,0x00E9,0x0000 }, }, /* #7 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x00E1,0x00E2,0x00E9,0x0000 }, + { 0x00E1,0x00E2,0x0000 }, }, /* #8 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x00E1,0x0092,0x00E9,0x0000 }, + { 0x00E1,0x008E,0x00E9,0x0000 }, }, /* #9 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x00E1,0x008E,0x00E9,0x0000 }, + { 0x00E1,0x0092,0x00E9,0x0000 }, }, /* #10 */ + /*expect*/ { 0,0,0, -1, }, + }, + { .is_last = 1 } + } + }, + { { Twcscoll, TST_LOC_en }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x0000,0x0041,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x0041,0x0041,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0041,0x0041,0x0043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,0,0, -1, }, + }, +#ifdef SHOJI_IS_RIGHT + /* */ /* assume ascii */ + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0061,0x0043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,0,0, -1, }, + }, + /* */ /* assume ascii */ + { /*input.*/ { { 0x0041,0x0061,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #6 */ + /*expect*/ { 0,0,0, +1, }, + }, +#else + /* XXX Correct order is lowercase before uppercase. */ + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0061,0x0043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x0041,0x0061,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #6 */ + /*expect*/ { 0,0,0, -1, }, + }, +#endif + { /*input.*/ { { 0x0041,0x0042,0x0000 }, + { 0x0041,0x0042,0x0049,0x0000 }, }, /* #7 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0049,0x0000 }, + { 0x0041,0x0042,0x0000 }, }, /* #8 */ + /*expect*/ { 0,0,0, +1, }, + }, +#ifdef SHOJI_IS_RIGHT + { /*input.*/ { { 0x0041,0x0092,0x0049,0x0000 }, + { 0x0041,0x008E,0x0049,0x0000 }, }, /* #9 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x0041,0x008E,0x0049,0x0000 }, + { 0x0041,0x0092,0x0049,0x0000 }, }, /* #10 */ + /*expect*/ { 0,0,0, -1, }, + }, +#else + /* Do not assume position of character out of range. */ + { /*input.*/ { { 0x0041,0x0092,0x0049,0x0000 }, + { 0x0041,0x008E,0x0049,0x0000 }, }, /* #9 */ + /*expect*/ { 0,0,0, 0, }, + }, + { /*input.*/ { { 0x0041,0x008E,0x0049,0x0000 }, + { 0x0041,0x0092,0x0049,0x0000 }, }, /* #10 */ + /*expect*/ { 0,0,0, 0, }, + }, +#endif + { .is_last = 1 } + } + }, +#if 0 + { { Twcscoll, TST_LOC_eucJP }, +#else + { { Twcscoll, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x0000,0x3041,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, 0, }, + }, + { /*input.*/ { { 0x3041,0x3041,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3041,0x3041,0x3043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x3041,0x0042,0x3043,0x0000 }, + { 0x3041,0x0061,0x3043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x3041,0x0061,0x3043,0x0000 }, + { 0x3041,0x0042,0x3043,0x0000 }, }, /* #6 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0xFF71,0x0000 }, + { 0x3041,0x3042,0x30A2,0x0000 }, }, /* #7 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x30A2,0x0000 }, + { 0x3041,0x3042,0xFF71,0x0000 }, }, /* #8 */ + /*expect*/ { 0,0,0, +1, }, + }, + { /*input.*/ { { 0x30FF,0x3092,0x3049,0x0000 }, + { 0x3041,0x308E,0x3049,0x0000 }, }, /* #9 */ + /*expect*/ { 0,0,0, -1, }, + }, + { /*input.*/ { { 0x3041,0x308E,0x3049,0x0000 }, + { 0x30FF,0x3092,0x3049,0x0000 }, }, /* #10 */ + /*expect*/ { 0,0,0, +1, }, + }, + { .is_last = 1 } + } + }, + { { Twcscoll, TST_LOC_end } } +}; diff --git a/test/locale-mbwc/dat_wcscpy.c b/test/locale-mbwc/dat_wcscpy.c new file mode 100644 index 0000000..b376bfc --- /dev/null +++ b/test/locale-mbwc/dat_wcscpy.c @@ -0,0 +1,44 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcscpy.c + * + * WCSCPY: wchar_t *wcscpy (wchar_t *ws1, const wchar_t *ws2); + */ + +TST_WCSCPY tst_wcscpy_loc [] = { + + { { Twcscpy, TST_LOC_de }, + { + { { { 0x00F1,0x00F2,0x00F3,0x0000 }, }, /* 1 */ + { 0,0,0, { 0x00F1,0x00F2,0x00F3,0x0000, } }, }, + { { { 0x0000,0x00F2,0x00F3,0x0000 }, }, /* 2 */ + { 0,0,0, { 0x0000, } }, }, + { .is_last = 1 } + } + }, + { { Twcscpy, TST_LOC_enUS }, + { + { { { 0x0041,0x0082,0x0043,0x0000 }, }, /* 1 */ + { 0,0,0, { 0x0041,0x0082,0x0043,0x0000, } }, }, + { { { 0x0000,0x0082,0x0043,0x0000 }, }, /* 2 */ + { 0,0,0, { 0x0000, } }, }, + { .is_last = 1 } + } + }, +#if 0 + { { Twcscpy, TST_LOC_eucJP }, +#else + { { Twcscpy, TST_LOC_ja_UTF8 }, +#endif + { + { { { 0x3041,0x0092,0x3043,0x0000 }, }, /* 1 */ + { 0,0,0, { 0x3041,0x0092,0x3043,0x0000, } }, }, + { { { 0x0000,0x0092,0x3043,0x0000 }, }, /* 2 */ + { 0,0,0, { 0x0000, } }, }, + { .is_last = 1 } + } + }, + { { Twcscpy, TST_LOC_end }} + +}; diff --git a/test/locale-mbwc/dat_wcscspn.c b/test/locale-mbwc/dat_wcscspn.c new file mode 100644 index 0000000..f6eb0c3 --- /dev/null +++ b/test/locale-mbwc/dat_wcscspn.c @@ -0,0 +1,164 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcscspn.c + * + * WCSCSPN: size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2); + */ + + +TST_WCSCSPN tst_wcscspn_loc [] = { + + { { Twcscspn, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x00D4,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x00D4,0x00D5,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x000 }, }, /* #8 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x00D3,0x0000 }, }, /* #9 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x0000 }, + { 0x00D1,0x00D3,0x00D4,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twcscspn, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0044,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0044,0x0045,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0042,0x000 }, }, /* #8 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, }, /* #9 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0000 }, + { 0x0041,0x0043,0x0044,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, +#if 0 + { { Twcscspn, TST_LOC_eucJP }, +#else + { { Twcscspn, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x0043,0x0000 }, + { 0x3041,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x0043,0x0000 }, + { 0x3042,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x3044,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x3044,0x3045,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3042,0x0000 }, }, /* #8 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, }, /* #9 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x0000 }, + { 0x3041,0x3043,0x3044,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twcscspn, TST_LOC_end }} +}; diff --git a/test/locale-mbwc/dat_wcslen.c b/test/locale-mbwc/dat_wcslen.c new file mode 100644 index 0000000..7bb2c89 --- /dev/null +++ b/test/locale-mbwc/dat_wcslen.c @@ -0,0 +1,62 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wcslen.c + * + * WCSLEN: size_t wcslen (const wchar_t *ws); + */ + + +/* + * NOTE: + * + * a header in each expected data: + * + * int err_val; ... expected value for errno + * ret_flg; ... set ret_flg=1 to compare an expected + * value with an actual value + * ret_val; ... expected value for return + */ + + +TST_WCSLEN tst_wcslen_loc [] = { + + { { Twcslen, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 } }, /* #01 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x0000 } }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twcslen, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 } }, /* #01 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x0000 } }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, +#if 0 + { { Twcslen, TST_LOC_eucJP }, +#else + { { Twcslen, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 } }, /* #01 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x0000 } }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twcslen, TST_LOC_end }} +}; diff --git a/test/locale-mbwc/dat_wcsncat.c b/test/locale-mbwc/dat_wcsncat.c new file mode 100644 index 0000000..9d1e46b --- /dev/null +++ b/test/locale-mbwc/dat_wcsncat.c @@ -0,0 +1,158 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsncat.c + * + * WCSNCAT: wchar_t *wcsncat (wchar_t *ws1, wchar_t *ws2, size_t n); + */ + + +/* + * Note: + * A terminating null wide chararacter is always appended to + * the result: ws1. + * + */ + + +TST_WCSNCAT tst_wcsncat_loc [] = { + { + {Twcsncat, TST_LOC_de}, + { + /* 1 */ + { + /* Input: */ + {{ 0x00D1,0x00D2,0x0000 }, + { 0x00D3,0x00D4,0x0000 }, 3 }, + /* Expect: */ + { 0, 0, 0, + { 0x00D1,0x00D2,0x00D3,0x00D4,0x0000 } }, + }, + /* 2 */ + {{{ 0x00D1,0x00D2,0x0000 }, + { 0x00D3,0x00D4,0x0000 }, 2 }, + { 0, 0, 0, + { 0x00D1,0x00D2,0x00D3,0x00D4,0x0000 } }, + }, + /* 3 */ + {{{ 0x00E1,0x00E2,0x0000 }, + { 0x00E3,0x00E4,0x0000 }, 1 }, + { 0, 0, 0, + { 0x00E1,0x00E2,0x00E3,0x0000 } }, + }, + /* 4 */ + {{{ 0x00E1,0x00E2,0x0000 }, + { 0x00E3,0x00E4,0x0000 }, 0 }, + { 0, 0, 0, + { 0x00E1,0x00E2,0x0000 } }, + }, + /* 5 */ + {{{ 0x0000 }, + { 0x00D3,0x00D4,0x0000 }, 3 }, + { 0, 0, 0, + { 0x00D3,0x00D4,0x0000 } }, + }, + /* 6 */ + {{{ 0x00E1,0x00E2,0x0000 }, + { 0x0000 }, 3 }, + { 0, 0, 0, + { 0x00E1,0x00E2,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcsncat, TST_LOC_enUS}, + { + /* 1 */ + { + /* Input: */ + {{ 0x0041,0x0042,0x0000 }, + { 0x0043,0x0044,0x0000 }, 3 }, + /* Expect: */ + { 0, 0, 0, + { 0x0041,0x0042,0x0043,0x0044,0x0000 } }, + }, + /* 2 */ + {{{ 0x0041,0x0042,0x0000 }, + { 0x0043,0x0044,0x0000 }, 2 }, + { 0, 0, 0, + { 0x0041,0x0042,0x0043,0x0044,0x0000 } }, + }, + /* 3 */ + {{{ 0x0051,0x0052,0x0000 }, + { 0x0053,0x0054,0x0000 }, 1 }, + { 0, 0, 0, + { 0x0051,0x0052,0x0053,0x0000 } }, + }, + /* 4 */ + {{{ 0x0051,0x0052,0x0000 }, + { 0x0053,0x0054,0x0000 }, 0 }, + { 0, 0, 0, + { 0x0051,0x0052,0x0000 } }, + }, + /* 5 */ + {{{ 0x0000 }, + { 0x0043,0x0044,0x0000 }, 3 }, + { 0, 0, 0, + { 0x0043,0x0044,0x0000 } }, + }, + /* 6 */ + {{{ 0x0051,0x0052,0x0000 }, + { 0x0000 }, 3 }, + { 0, 0, 0, + { 0x0051,0x0052,0x0000 } }, + }, + {.is_last = 1} + } + }, + { +#if 0 + {Twcsncat, TST_LOC_eucJP}, +#else + {Twcsncat, TST_LOC_ja_UTF8}, +#endif + { + /* 1 */ + {{{ 0x3041,0x3042,0x0000 }, + { 0x3043,0x3044,0x0000 }, 3 }, + { 0, 0, 0, + { 0x3041,0x3042,0x3043,0x3044,0x0000 } }, + }, + /* 2 */ + {{{ 0x30A2,0x30A3,0x0000 }, + { 0xFF71,0xFF72,0x0000 }, 2 }, + { 0, 0, 0, + { 0x30A2,0x30A3,0xFF71,0xFF72,0x0000 } }, + }, + /* 3 */ + {{{ 0x3051,0x3052,0x0000 }, + { 0x3053,0x3054,0x0000 }, 1 }, + { 0, 0, 0, + { 0x3051,0x3052,0x3053,0x0000 } }, + }, + /* 4 */ + {{{ 0x3051,0x3052,0x0000 }, + { 0x3053,0x3054,0x0000 }, 0 }, + { 0, 0, 0, + { 0x3051,0x3052,0x0000 } }, + }, + /* 5 */ + {{{ 0x0000 }, + { 0x3043,0x3044,0x0000 }, 3 }, + { 0, 0, 0, + { 0x3043,0x3044,0x0000 } }, + }, + /* 6 */ + {{{ 0x3051,0x3052,0x0000 }, + { 0x0000 }, 3 }, + { 0, 0, 0, + { 0x3051,0x3052,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcsncat, TST_LOC_end} + } +}; diff --git a/test/locale-mbwc/dat_wcsncmp.c b/test/locale-mbwc/dat_wcsncmp.c new file mode 100644 index 0000000..5c59631 --- /dev/null +++ b/test/locale-mbwc/dat_wcsncmp.c @@ -0,0 +1,144 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsncmp.c + * + * WCSNCMP: int wcsncmp (const wchar_t *ws1, const wchar_t *ws2, + * size_t n); + */ + +TST_WCSNCMP tst_wcsncmp_loc [] = { + { + { Twcsncmp, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, 4 }, /* #01 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, 3 }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D1,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, 2 }, /* #03 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D0,0x00D2,0x00D3,0x0000 }, 0 }, /* #04 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x00D1,0x0000 }, 3 }, /* #05 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x00D3,0x0000 }, 3 }, /* #06 */ + /*expect*/ { 0,1,0x00D1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D9,0x0000 }, 2 }, /* #07 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D9,0x0000 }, 3 }, /* #08 */ + /*expect*/ { 0,1,-0x0006, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x0000 }, 4 }, /* #09 */ + /*expect*/ { 0,1,0x00D3, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsncmp, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, 4 }, /* #01 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, 3 }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0041,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, 2 }, /* #03 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0040,0x0042,0x0043,0x0000 }, 0 }, /* #04 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0000,0x0042,0x0041,0x0000 }, 3 }, /* #05 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0000,0x0042,0x0043,0x0000 }, 3 }, /* #06 */ + /*expect*/ { 0,1,0x0041, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0049,0x0000 }, 2 }, /* #07 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0049,0x0000 }, 3 }, /* #08 */ + /*expect*/ { 0,1,-0x0006, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0000 }, 4 }, /* #09 */ + /*expect*/ { 0,1,0x0043, }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcsncmp, TST_LOC_eucJP }, +#else + { Twcsncmp, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, 4 }, /* #01 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, 3 }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3041,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, 2 }, /* #03 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3040,0x3042,0x3043,0x0000 }, 0 }, /* #04 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x0000,0x3042,0x3041,0x0000 }, 3 }, /* #05 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x0000,0x3042,0x3043,0x0000 }, 3 }, /* #06 */ + /*expect*/ { 0,1,0x3041, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3049,0x0000 }, 2 }, /* #07 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3049,0x0000 }, 3 }, /* #08 */ + /*expect*/ { 0,1,-0x0006, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x0000 }, 4 }, /* #09 */ + /*expect*/ { 0,1,0x3043, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsncmp, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcsncpy.c b/test/locale-mbwc/dat_wcsncpy.c new file mode 100644 index 0000000..7a65783 --- /dev/null +++ b/test/locale-mbwc/dat_wcsncpy.c @@ -0,0 +1,119 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsncpy.c + * + * WCSNCPY: wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2, + * size_t n); + */ + + +/* Note: + * + * An initial value of ws1 in the test program is defined as: + * + * #define WCSNUM_NCPY 7 + * wchar_t ws1 [WCSSIZE] = { 0x9999, 0x9999, 0x9999, 0x9999, + * 0x9999, 0x9999, 0x0000 }; + * */ + + +TST_WCSNCPY tst_wcsncpy_loc [] = { + { + {Twcsncpy, TST_LOC_de}, + { + /* 1 */ + {{ { 0x00D1,0x00D2,0x00D3,0x0000 }, 6 }, + { 0,0,0, { 0x00D1,0x00D2,0x00D3,0x0000,0x0000,0x0000,0x0000 } }, + }, + /* 2 */ + {{ { 0x00D1,0x00D2,0x00D3,0x0000 }, 5 }, + { 0,0,0, { 0x00D1,0x00D2,0x00D3,0x0000,0x0000,0x9999,0x0000 } }, + }, + /* 3 */ + {{ { 0x00D1,0x00D2,0x00D3,0x0000 }, 3 }, + { 0,0,0, { 0x00D1,0x00D2,0x00D3,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 4 */ + {{ { 0x00D1,0x00D2,0x00D3,0x0000 }, 2 }, + { 0,0,0, { 0x00D1,0x00D2,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 5 */ + {{ { 0x00D1,0x00D2,0x00D3,0x0000 }, 0 }, + { 0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 6 */ + {{ { 0x0000,0x00D2,0x00D3,0x0000 }, 3 }, + { 0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcsncpy, TST_LOC_enUS}, + { + /* 1 */ + {{ { 0x0041,0x0042,0x0043,0x0000 }, 6 }, + { 0,0,0, { 0x0041,0x0042,0x0043,0x0000,0x0000,0x0000,0x0000 } }, + }, + /* 2 */ + {{ { 0x0041,0x0042,0x0043,0x0000 }, 5 }, + { 0,0,0, { 0x0041,0x0042,0x0043,0x0000,0x0000,0x9999,0x0000 } }, + }, + /* 3 */ + {{ { 0x0041,0x0042,0x0043,0x0000 }, 3 }, + { 0,0,0, { 0x0041,0x0042,0x0043,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 4 */ + {{ { 0x0041,0x0042,0x0043,0x0000 }, 2 }, + { 0,0,0, { 0x0041,0x0042,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 5 */ + {{ { 0x0041,0x0042,0x0043,0x0000 }, 0 }, + { 0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 6 */ + {{ { 0x0000,0x0042,0x0043,0x0000 }, 3 }, + { 0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 } }, + }, + {.is_last = 1} + } + }, + { +#if 0 + {Twcsncpy, TST_LOC_eucJP}, +#else + {Twcsncpy, TST_LOC_ja_UTF8}, +#endif + { + /* 1 */ + {{ { 0x3041,0x3042,0x3043,0x0000 }, 6 }, + { 0,0,0, { 0x3041,0x3042,0x3043,0x0000,0x0000,0x0000,0x0000 } }, + }, + /* 2 */ + {{ { 0x3041,0x3042,0x3043,0x0000 }, 5 }, + { 0,0,0, { 0x3041,0x3042,0x3043,0x0000,0x0000,0x9999,0x0000 } }, + }, + /* 3 */ + {{ { 0x3041,0x3042,0x3043,0x0000 }, 3 }, + { 0,0,0, { 0x3041,0x3042,0x3043,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 4 */ + {{ { 0x3041,0x3042,0x3043,0x0000 }, 2 }, + { 0,0,0, { 0x3041,0x3042,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 5 */ + {{ { 0x3041,0x3042,0x3043,0x0000 }, 0 }, + { 0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 } }, + }, + /* 6 */ + {{ { 0x0000,0x3042,0x3043,0x0000 }, 3 }, + { 0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 } }, + }, + {.is_last = 1} + } + }, + { + {Twcsncpy, TST_LOC_end} + } +}; diff --git a/test/locale-mbwc/dat_wcspbrk.c b/test/locale-mbwc/dat_wcspbrk.c new file mode 100644 index 0000000..471515e --- /dev/null +++ b/test/locale-mbwc/dat_wcspbrk.c @@ -0,0 +1,176 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcspbrk.c + * + * WCSSTR: wchar_t *wcspbrk (const wchar_t *ws1, const wchar_t *ws2); + */ + + +/* + * NOTE: + * This is not a locale sensitive function. + * So those data in each locale doesn't make sense + * ... (redundant test cases) + */ + + +TST_WCSPBRK tst_wcspbrk_loc [] = { + { + { Twcspbrk, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, 0x00D1 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, 0x00D2 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, 0x00D3 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, 0x00D1 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, 0x00D2 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, 0x00D1 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D0,0x00D4,0x00D5,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D5,0x00D0,0x00D4,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { .is_last = 1 } + } + }, + { + { Twcspbrk, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, 0x0041 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, 0x0042 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, 0x0043 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, 0x0041 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, 0x0042 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, 0x0041 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0040,0x0044,0x0045,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0045,0x0040,0x0044,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcspbrk, TST_LOC_eucJP }, +#else + { Twcspbrk, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, 0x3041 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, 0x3042 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, 0x3043 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, 0x3041 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, 0x3042 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, 0x3041 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x3044,0x0000 }, }, /* #07 */ + /*expect*/ { 0,0,0, 0x3042 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3040,0x3041,0x3042,0x0000 }, }, /* #08 */ + /*expect*/ { 0,0,0, 0x3041 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3041,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,(wchar_t *)NULL, 0x0000 }, + }, + { .is_last = 1 } + } + }, + { + { Twcspbrk, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcsrtombs.c b/test/locale-mbwc/dat_wcsrtombs.c new file mode 100644 index 0000000..f8adc6c --- /dev/null +++ b/test/locale-mbwc/dat_wcsrtombs.c @@ -0,0 +1,272 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsrtombs.c + * + * WCSTOMBS: size_t wcsrtombs (char *s, const wchar_t **ws, + * size_t n, mbstate *ps) + */ + + +/* + * CAUTION: + * Do not use a value 0x01 for string data. The test program + * uses it. + * + */ + + +TST_WCSRTOMBS tst_wcsrtombs_loc [] = { + { + { Twcsrtombs, TST_LOC_de }, + { + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 0, 0, 0}, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,1, "Ä" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 2, 0, 0 }, + /*expect*/ { 0,1,2, "ÄÖ" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 3, 0, 0 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 4, 0, 0 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, + { + { Twcsrtombs, TST_LOC_enUS }, + { + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,1, "A" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 2, 0, 0 }, + /*expect*/ { 0,1,2, "AB" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 3, 0, 0 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 4, 0, 0 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Twcsrtombs, TST_LOC_eucJP }, + { + + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 2, 0, 0 }, + /*expect*/ { 0,1,2, "\244\242" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 4, 0, 0 }, + /*expect*/ { 0,1,4, "\244\242\244\244" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 6, 0, 0 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 7, 0, 0 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 }, + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#else + { + { Twcsrtombs, TST_LOC_ja_UTF8 }, + { + + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 3, 0, 0 }, + /*expect*/ { 0,1,3, "\343\201\202" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 6, 0, 0 }, + /*expect*/ { 0,1,6, "\343\201\202\343\201\204" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 9, 0, 0 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 10, 0, 0 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 11, 0, 0 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 }, + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 1, 0, 0 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5, 0, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#endif + { + { Twcsrtombs, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcsspn.c b/test/locale-mbwc/dat_wcsspn.c new file mode 100644 index 0000000..06af2d6 --- /dev/null +++ b/test/locale-mbwc/dat_wcsspn.c @@ -0,0 +1,179 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsspn.c + * + * WCSSPN: size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2); + */ + +TST_WCSSPN tst_wcsspn_loc [] = { + { + { Twcsspn, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #01 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x0000 }, }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x0000 }, }, /* #03 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D4,0x0000 }, }, /* #04 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x0000 }, }, /* #05 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x00D4,0x0000 }, }, /* #06 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x0000 }, }, /* #09 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x0000,0x00D2,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D1,0x0000 }, }, /* #12 */ + /*expect*/ { 0,1,2, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsspn, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #01 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0000 }, }, /* #02 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0000 }, }, /* #03 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0044,0x0000 }, }, /* #04 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0000 }, }, /* #05 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0044,0x0000 }, }, /* #06 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0042,0x0000 }, }, /* #09 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0000,0x0042,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0000,0x0042,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0041,0x0000 }, }, /* #12 */ + /*expect*/ { 0,1,2, }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcsspn, TST_LOC_eucJP }, +#else + { Twcsspn, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x0000 }, }, /* #1 */ + /*expect*/ { 0,1,1, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x0000 }, }, /* #2 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x0000 }, }, /* #3 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3044,0x0000 }, }, /* #4 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x0000 }, }, /* #5 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x3044,0x0000 }, }, /* #6 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #7 */ + /*expect*/ { 0,1,3, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #8 */ + /*expect*/ { 0,1,2, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3042,0x0000 }, }, /* #9 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x0000,0x3042,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x0000,0x3042,0x0000 }, }, /* #11 */ + /*expect*/ { 0,1,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3041,0x0000 }, }, /* #12 */ + /*expect*/ { 0,1,2, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsspn, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcsstr.c b/test/locale-mbwc/dat_wcsstr.c new file mode 100644 index 0000000..f999dc5 --- /dev/null +++ b/test/locale-mbwc/dat_wcsstr.c @@ -0,0 +1,175 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcsstr.c + * + * WCSSTR: wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2); + */ + +/* + * NOTE: + * This is not a locale sensitive function. + * So those data in each locale doesn't make sense ... + * (redundant test cases) + */ + + +TST_WCSSTR tst_wcsstr_loc [] = { + { + { Twcsstr, TST_LOC_de }, + { + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D3,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x00D2,0x00D3,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D2,0x00D3,0x00D4,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x00D0,0x00D1,0x00D2,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x00D1,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsstr, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0043,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0041,0x0042,0x0043,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0042,0x0043,0x0044,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0040,0x0041,0x0042,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0041,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcsstr, TST_LOC_eucJP }, +#else + { Twcsstr, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x0000 }, }, /* #01 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x0000 }, }, /* #02 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3043,0x0000 }, }, /* #03 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x0000 }, }, /* #04 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x0000 }, }, /* #05 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3041,0x3042,0x3043,0x0000 }, }, /* #06 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3042,0x3043,0x3044,0x0000 }, }, /* #07 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x3040,0x3041,0x3042,0x0000 }, }, /* #08 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, + { 0x0000 }, }, /* #09 */ + /*expect*/ { 0,0,0, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x3041,0x0000 }, }, /* #10 */ + /*expect*/ { 0,1,(wchar_t *)NULL, }, + }, + { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, + { 0x0000 }, }, /* #11 */ + /*expect*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsstr, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcstod.c b/test/locale-mbwc/dat_wcstod.c new file mode 100644 index 0000000..c7b4018 --- /dev/null +++ b/test/locale-mbwc/dat_wcstod.c @@ -0,0 +1,78 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wcstod.c + * + * WCSTOD: double wcstod (const wchar_t *np, wchar_t **endp); + */ + + +/* + * NOTE: + * need more test data! + * + */ + + +TST_WCSTOD tst_wcstod_loc [] = { + { + { Twcstod, TST_LOC_de }, + { + { + /*01*/ + /*I*/ + {{ 0x0030,0x0030,0x0030,0x002C,0x0030,0x0030,0x0030,0x0030,0x0000 }}, + /*E*/ + { 0,1,0.0, 0.0, 0x0000 } + }, + { + /*02*/ + /*I*/ + {{ 0x0031,0x0032,0x0033,0x002C,0x0034,0x0035,0x0036,0x0040,0x0000 }}, + /*E*/ + { 0,1,123.456, 123.456, 0x0040 } + }, + { .is_last = 1 } + } + }, + { + { Twcstod, TST_LOC_enUS }, + { + { + /*01*/ + /*I*/ + {{ 0x0030,0x0030,0x0030,0x002E,0x0030,0x0030,0x0030,0x0030,0x0000 }}, + /*E*/ + { 0,1,0.0, 0.0, 0x0000 } + }, + { + /*02*/ + /*I*/ + {{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0040,0x0000 }}, + /*E*/ + { 0,1,123.456, 123.456, 0x0040 } + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcstod, TST_LOC_eucJP }, +#else + { Twcstod, TST_LOC_ja_UTF8 }, +#endif + { + { + /*01*/ + /*I*/ + {{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0040,0x0000 }}, + /*E*/ + { 0,1,123.456, 123.456, 0x0040 } + }, + { .is_last = 1 } + } + }, + { + { Twcstod, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcstok.c b/test/locale-mbwc/dat_wcstok.c new file mode 100644 index 0000000..559b401 --- /dev/null +++ b/test/locale-mbwc/dat_wcstok.c @@ -0,0 +1,138 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wcstok.c + * + * WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm, + * wchar_t **pt); + */ + +/* + * NOTE: + * need more test data! + * locale insensitive function... + */ + + + + +TST_WCSTOK tst_wcstok_loc [] = { + { + { Twcstok, TST_LOC_de }, + { + { + { + { + { 1, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8, + 0x00D9,0x0000 }, + { 0x00D3,0x00D2, 0x00D5 } + }, + { 0, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8, + 0x00D9,0x0000 }, + { 0x00D3,0x00D2, 0x00D5 } + }, + { 0, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8, + 0x00D9,0x0000 }, + { 0x00D3,0x00D2, 0x00D5 } + }, + } + }, + { + { + { 0, 0,0, + { 0x00D1,0x0000 } + }, + { 0, 0,0, + { 0x00D4,0x0000 } + }, + { 0, 0,0, + { 0x00D6,0x00D7,0x00D8,0x00D9,0x0000 } + }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Twcstok, TST_LOC_enUS }, + { + { + { + { + { 1, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + } + }, + { + { + { 0, 0,0, + { 0x0041,0x0000 } + }, + { 0, 0,0, + { 0x0044,0x0000 } + }, + { 0, 0,0, + { 0x0046,0x0047,0x0048,0x0049,0x0000 } + }, + } + } + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcstok, TST_LOC_eucJP }, +#else + { Twcstok, TST_LOC_ja_UTF8 }, +#endif + { + { + { + { + { 1, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048, + 0x0049,0x0000 }, + { 0x0043,0x0042, 0x0045 } + }, + } + }, + { + { + { 0, 0,0, + { 0x0041,0x0000 } + }, + { 0, 0,0, + { 0x0044,0x0000 } + }, + { 0, 0,0, + { 0x0046,0x0047,0x0048,0x0049,0x0000 } + }, + } + } + }, + { .is_last = 1 } + } + }, + { + { Twcstok, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcstombs.c b/test/locale-mbwc/dat_wcstombs.c new file mode 100644 index 0000000..ffeb0ef --- /dev/null +++ b/test/locale-mbwc/dat_wcstombs.c @@ -0,0 +1,271 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcstombs.c + * + * WCSTOMBS: size_t wcstombs (char *s, const wchar_t *ws, size_t n) + */ + + +/* + * CAUTION: + * Do not use a value 0x01 for string data. The test program + * uses it. + * + */ + + +TST_WCSTOMBS tst_wcstombs_loc [] = { + { + { Twcstombs, TST_LOC_de }, + { + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 1 }, + /*expect*/ { 0,1,1, "Ä" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 2 }, + /*expect*/ { 0,1,2, "ÄÖ" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 3 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 4 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 5 }, + /*expect*/ { 0,1,3, "ÄÖÜ" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 1 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x00C4,0x00D6,0x00DC,0x0000 }, 5 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, + { + { Twcstombs, TST_LOC_enUS }, + { + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x00C4,0x0042,0x0043,0x0000 }, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 1 }, + /*expect*/ { 0,1,1, "A" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 2 }, + /*expect*/ { 0,1,2, "AB" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 3 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 4 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x0041,0x0042,0x0043,0x0000 }, 5 }, + /*expect*/ { 0,1,3, "ABC" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 0 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 1 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0041,0x0042,0x0043,0x0000 }, 5 }, + /*expect*/ { 0,1,3, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5, }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Twcstombs, TST_LOC_eucJP }, + { + + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 2 }, + /*expect*/ { 0,1,2, "\244\242" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 4 }, + /*expect*/ { 0,1,4, "\244\242\244\244" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 6 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 7 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8 }, + /*expect*/ { 0,1,6, "\244\242\244\244\216\263" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2 }, + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 1 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8 }, + /*expect*/ { 0,1,6, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#else + { + { Twcstombs, TST_LOC_ja_UTF8 }, + { + + /* #01 : Any chars including a null char should not be stored in s. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #02 : Only one chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 3 }, + /*expect*/ { 0,1,3, "\343\201\202" }, + }, + /* #03 : Only two chars should be stored in s. No null termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 6 }, + /*expect*/ { 0,1,6, "\343\201\202\343\201\204" }, + }, + /* #04 : Only three chars should be stored in s. No null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 9 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #05 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 10 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #06 : Only three chars should be stored in s with a null + termination. */ + { /*input.*/ { 1,1, { 0x3042,0x3044,0xFF73,0x0000 }, 11 }, + /*expect*/ { 0,1,9, "\343\201\202\343\201\204\357\275\263" }, + }, + /* #07 : Invalid mb sequence. No chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0201,0x0221,0x0000,0x0000 }, 2 }, + /*expect*/ { EILSEQ,1,-1, "" }, + }, + /* #08 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 0 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #09 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 1 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #10 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x3042,0x3044,0xFF73,0x0000 }, 8 }, + /*expect*/ { 0,1,9, "" }, + }, + /* #11 : s is a null pointer. No chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0201,0x0221,0x0000,0x0000 }, 5 }, + /*expect*/ { EILSEQ,1,(size_t)-1, "" }, + }, + /* #12 : ws is a null wc string, no chars should be stored in s. */ + { /*input.*/ { 1,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + /* #13 : s is a null pointer, no chars should be stored in s. */ + { /*input.*/ { 0,1, { 0x0000 }, 5 }, + /*expect*/ { 0,1,0, "" }, + }, + { .is_last = 1 } + } + }, +#endif + { + { Twcstombs, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcswidth.c b/test/locale-mbwc/dat_wcswidth.c new file mode 100644 index 0000000..6d2f98e --- /dev/null +++ b/test/locale-mbwc/dat_wcswidth.c @@ -0,0 +1,263 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcswidth.c + * + * WCSWIDTH: int wcswidth (const wchar_t *ws, size_t n); + */ + +TST_WCSWIDTH tst_wcswidth_loc [] = { + { + { Twcswidth, TST_LOC_de }, + { + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0 }, /* 01 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 1 }, /* 02 */ + /*expect*/ { 0,1,1 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 2 }, /* 03 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 3 }, /* 04 */ + /*expect*/ { 0,1,3 }, + }, + { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 4 }, /* 05 */ + /*expect*/ { 0,1,3 }, + }, + { /*input.*/ { { 0x0000 }, 1 }, /* 06 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x00C1,0x0001,0x0000 }, 2 }, /* 07 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x0001,0x0000 }, 1 }, /* 08 */ + /*expect*/ { 0,1,1 }, + }, + { /*input.*/ { { 0x00C1,0x0001,0x0000 }, 2 }, /* 09 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x0092,0x0000 }, 2 }, /* 10 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x0020,0x0000 }, 2 }, /* 11 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x0021,0x0000 }, 2 }, /* 12 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x007E,0x0000 }, 2 }, /* 13 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x007F,0x0000 }, 2 }, /* 14 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x0080,0x0000 }, 2 }, /* 15 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x00A0,0x0000 }, 2 }, /* 16 */ +#ifdef SHOJI_IS_RIGHT + /*expect*/ { 0,1,-1 }, +#else + /*expect*/ { 0,1,2 }, +#endif + }, + { /*input.*/ { { 0x00C1,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x00FF,0x0000 }, 2 }, /* 18 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x00C1,0x3042,0x0000 }, 2 }, /* 19 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x00C1,0x3044,0x0000 }, 2 }, /* 20 */ + /*expect*/ { 0,1,-1 }, + }, + { .is_last = 1 } + } + }, + { + { Twcswidth, TST_LOC_enUS }, + { + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 0 }, /* 01 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 1 }, /* 02 */ + /*expect*/ { 0,1,1 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 2 }, /* 03 */ + /*expect*/ { 0,1,2 }, + }, +#ifdef SHOJI_IS_RIGHT + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 3 }, /* 04 */ + /*expect*/ { 0,1,3 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 4 }, /* 05 */ + /*expect*/ { 0,1,3 }, + }, +#else + { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 }, 3 }, /* 04 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 4 }, /* 05 */ + /*expect*/ { 0,1,3 }, + }, +#endif + { /*input.*/ { { 0x0000 }, 1 }, /* 06 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x0041,0x0001,0x0000 }, 2 }, /* 07 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0001,0x0000 }, 1 }, /* 08 */ + /*expect*/ { 0,1,1 }, + }, + { /*input.*/ { { 0x0041,0x0001,0x0000 }, 2 }, /* 09 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0092,0x0000 }, 2 }, /* 10 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0020,0x0000 }, 2 }, /* 11 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x0021,0x0000 }, 2 }, /* 12 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x007E,0x0000 }, 2 }, /* 13 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x007F,0x0000 }, 2 }, /* 14 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0080,0x0000 }, 2 }, /* 15 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x00A0,0x0000 }, 2 }, /* 16 */ + /*expect*/ { 0,1,-1 }, + }, +#ifdef SHOJI_IS_RIGHT + { /*input.*/ { { 0x0041,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x00FF,0x0000 }, 2 }, /* 18 */ + /*expect*/ { 0,1,2 }, + }, +#else + { /*input.*/ { { 0x0041,0x007E,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x0020,0x0000 }, 2 }, /* 18 */ + /*expect*/ { 0,1,2 }, + }, +#endif + { /*input.*/ { { 0x0041,0x3042,0x0000 }, 2 }, /* 19 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x3044,0x0000 }, 2 }, /* 20 */ + /*expect*/ { 0,1,-1 }, + }, + { .is_last = 1 } + } + }, + { +#if 0 + { Twcswidth, TST_LOC_eucJP }, +#else + { Twcswidth, TST_LOC_ja_UTF8 }, +#endif + { + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0 }, /* 01 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 1 }, /* 02 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 2 }, /* 03 */ + /*expect*/ { 0,1,4 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 3 }, /* 04 */ + /*expect*/ { 0,1,6 }, + }, + { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 4 }, /* 05 */ + /*expect*/ { 0,1,6 }, + }, + { /*input.*/ { { 0x0000 }, 1 }, /* 06 */ + /*expect*/ { 0,1,0 }, + }, + { /*input.*/ { { 0x008E,0x0001,0x0000 }, 2 }, /* 07 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x3041,0x008E,0x0000 }, 1 }, /* 08 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x3041,0x008E,0x0000 }, 2 }, /* 09 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x3041,0x0001,0x0000 }, 2 }, /* 10 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x3041,0x3000,0x0000 }, 2 }, /* 11 */ + /*expect*/ { 0,1,4 }, + }, + { /*input.*/ { { 0x0041,0x0021,0x0000 }, 2 }, /* 12 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x007E,0x0000 }, 2 }, /* 13 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x007F,0x0000 }, 2 }, /* 14 */ + /*expect*/ { 0,1,-1 }, + }, + { /*input.*/ { { 0x0041,0x0080,0x0000 }, 2 }, /* 15 */ + /*expect*/ { 0,1,-1 }, + }, +#if 0 + { /*input.*/ { { 0x0041,0x00A0,0x0000 }, 2 }, /* 16 */ + /*expect*/ { 0,1,-1 }, + }, +#ifdef NO_WAIVER + /* */ /* returns 3 */ + { /*input.*/ { { 0x0041,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,-1 }, + }, +#else + /* XXX U00A1 is valid -> /x8f/xa2/xc4 in JIS X 0212 */ + { /*input.*/ { { 0x0041,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,3 }, + }, +#endif +#else + /* XXX U00A0 i UTF8 is valid -> /xc2/xa0 */ + { /*input.*/ { { 0x0041,0x00A0,0x0000 }, 2 }, /* 16 */ + /*expect*/ { 0,1,2 }, + }, +#ifdef NO_WAIVER + /* */ /* returns 3 */ + { /*input.*/ { { 0x0041,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,-1 }, + }, +#else + /* XXX U00A1 in UTF-8 is valid -> /xc2/xa1 */ + { /*input.*/ { { 0x0041,0x00A1,0x0000 }, 2 }, /* 17 */ + /*expect*/ { 0,1,2 }, + }, +#endif +#endif + { /*input.*/ { { 0x0041,0xFF71,0x0000 }, 2 }, /* 18 */ + /*expect*/ { 0,1,2 }, + }, + { /*input.*/ { { 0x0041,0x3042,0x0000 }, 2 }, /* 19 */ + /*expect*/ { 0,1,3 }, + }, + { /*input.*/ { { 0x0041,0x3044,0x0000 }, 2 }, /* 20 */ + /*expect*/ { 0,1,3 }, + }, + { .is_last = 1 } + } + }, + { + { Twcswidth, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wcsxfrm.c b/test/locale-mbwc/dat_wcsxfrm.c new file mode 100644 index 0000000..acb6727 --- /dev/null +++ b/test/locale-mbwc/dat_wcsxfrm.c @@ -0,0 +1,102 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wcsxfrm.c + * + * WCSXFRM: size_t wcsxfrm (char *s1, const char s2, size_t n); + */ + +/* + * NOTE: + * + * Return value and errno value are checked only for 2nd string: + * org2[]; n1 and n2 don't mean bytes to be translated. + * It means a buffer size including a null character. + * Results of this test depens on results of wcscoll(). + * If you got errors, check both test results. + */ + + +TST_WCSXFRM tst_wcsxfrm_loc [] = { + + { + { Twcsxfrm, TST_LOC_de }, + { + { /*inp*/ { { 0x00C1,0x0000 }, { 0x00C1,0x0000 }, 7, 7 }, /* #01 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 }, /* #02 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 }, /* #03 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x00E4,0x0000 }, { 0x00DC,0x0000 }, 7, 7 }, /* #04 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x00DC,0x0000 }, { 0x00E4,0x0000 }, 7, 7 }, /* #05 */ + /*exp*/ { 0, 0,0, }, + }, + { .is_last = 1 } + } + }, + { + { Twcsxfrm, TST_LOC_enUS }, + { + { /*inp*/ { { 0x0041,0x0000 }, { 0x0041,0x0000 }, 7, 7 }, /* #01 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 }, /* #02 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 }, /* #03 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0000,0x0000 }, { 0x0000,0x0000 }, 7, 7 }, /* #04 */ + /*exp*/ { 0, 0,0, }, + }, +#ifdef NO_WAIVER + { /* x 2 */ + /*inp*/ { { 0x3061,0x0000 }, { 0xFF42,0x0000 }, 7, 7 }, /* #05 */ + /* */ + /*exp*/ { EINVAL, 1,(size_t)-1, }, + }, +#endif + { .is_last = 1 } + } + }, + { +#if 0 + { Twcsxfrm, TST_LOC_eucJP }, /* need more test data ! */ +#else + { Twcsxfrm, TST_LOC_ja_UTF8 }, /* need more test data ! */ +#endif + { + { /*inp*/ { { 0x3041,0x0000 }, { 0x3041,0x0000 }, 7, 7 }, /* #01 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 }, /* #02 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 }, /* #03 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0x30A2,0x0000 }, { 0xFF71,0x0000 }, 7, 7 }, /* #04 */ + /*exp*/ { 0, 0,0, }, + }, + { /*inp*/ { { 0xFF71,0x0000 }, { 0x30A2,0x0000 }, 7, 7 }, /* #05 */ + /*exp*/ { 0, 0,0, }, + }, +#ifdef NO_WAIVER + /* x 2 */ + { /*inp*/ { { 0x008E,0x0000 }, { 0x008F,0x0000 }, 7, 7 }, /* #06 */ + /*exp*/ { EINVAL, 1,(size_t)-1, }, + }, +#endif + { .is_last = 1 } + } + }, + { + { Twcsxfrm, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wctob.c b/test/locale-mbwc/dat_wctob.c new file mode 100644 index 0000000..dfd344e --- /dev/null +++ b/test/locale-mbwc/dat_wctob.c @@ -0,0 +1,61 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wctob.c + * + * ISW*: int wctob( wint_t wc ); + */ + + +TST_WCTOB tst_wctob_loc [] = { + + { { Twctob, TST_LOC_de }, + { + { { WEOF }, { 0, 1, EOF } }, + { { 0x0020 }, { 0, 1, 0x20 } }, + { { 0x0061 }, { 0, 1, 0x61 } }, + { { 0x0080 }, { 0, 1, 0x80 } }, + { { 0x00C4 }, { 0, 1, 0xC4 } }, + { { 0x30C4 }, { 0, 1, EOF } }, + { .is_last = 1 } /* Last element. */ + } + }, + { { Twctob, TST_LOC_enUS }, + { + { { WEOF }, { 0, 1, EOF } }, + { { 0x0020 }, { 0, 1, 0x20 } }, + { { 0x0061 }, { 0, 1, 0x61 } }, +#ifdef SHOJI_IS_RIGHT + { { 0x0080 }, { 0, 1, 0x80 } }, + { { 0x00C4 }, { 0, 1, 0xC4 } }, +#else + /* XXX These are no valid characters. */ + { { 0x0080 }, { 0, 1, EOF } }, + { { 0x00C4 }, { 0, 1, EOF } }, +#endif + { { 0x30C4 }, { 0, 1, EOF } }, + { .is_last = 1 } /* Last element. */ + } + }, +#if 0 + { { Twctob, TST_LOC_eucJP }, +#else + { { Twctob, TST_LOC_ja_UTF8 }, +#endif + { + { { WEOF }, { 0, 1, EOF } }, + { { 0x0020 }, { 0, 1, 0x20 } }, + { { 0x0061 }, { 0, 1, 0x61 } }, +#if 0 + { { 0x0080 }, { 0, 1, 0x80 } }, +#else + { { 0x0080 }, { 0, 1, EOF } }, +#endif + { { 0x00FF }, { 0, 1, EOF } }, + { { 0x00C4 }, { 0, 1, EOF } }, + { { 0x30C4 }, { 0, 1, EOF } }, + { .is_last = 1 } /* Last element. */ + } + }, + { { Twctob, TST_LOC_end } } +}; diff --git a/test/locale-mbwc/dat_wctomb.c b/test/locale-mbwc/dat_wctomb.c new file mode 100644 index 0000000..0ec3a9c --- /dev/null +++ b/test/locale-mbwc/dat_wctomb.c @@ -0,0 +1,168 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wctomb.c + * + * WCTOMB: int wctomb (char *s, wchar_t wc) + */ + + +/* + * FUNCTION: + * + * int wctomb (char *s, wchar_t wc); + * + * return: the number of bytes + * + * NOTE: + * + * o When you feed a null pointer for a string (s) to the function, + * set s_flg=0 instead of putting just a 'NULL' there. + * Even if you put a 'NULL', it means a null string as well as "". + * + * o When s is a null pointer, the function checks state dependency. + * + * state-dependent encoding - return NON-zero + * state-independent encoding - return 0 + * + * If state-dependent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = +1 + * + * If state-independent encoding is expected, set + * + * s_flg = 0, ret_flg = 0, ret_val = 0 + * + * + * When you set ret_flg=1, the test program simply compares an + * actual return value with an expected value. You can check + * state-independent case (return value is 0) in that way, but + * you can not check state-dependent case. So when you check + * state- dependency in this test function: tst_wctomb(), set + * ret_flg=0 always. It's a special case, and the test + * function takes care of it. + * + * Input Expect + * + * s_flg=0 ret_flg=0 + * | | + * { 0, 0 }, { 0, 0, 0, x, "" } + * | | + * not used ret_val: 0/+1 + * (expected val) + */ + + +TST_WCTOMB tst_wctomb_loc [] = { + { + { Twctomb, TST_LOC_de }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x00C4 }, + /*expect*/ { 0,1,1, "Ä" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x00DC }, + /*expect*/ { 0,1,1, "Ü" }, + }, + /* #03 : normal case */ + { /*input.*/ { 1, 0x0092 }, + /*expect*/ { 0,1,1, "\222" }, + }, + /* #04 : error case */ + { /*input.*/ { 1, 0x3041 }, + /*expect*/ { 0,1,-1, "" }, + }, + /* #05 : state dependency */ + { /*input.*/ { 0, 0x0000 }, + /*expect*/ { 0,0,0, "" }, + }, + { .is_last = 1 } + } + }, + { + { Twctomb, TST_LOC_enUS }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x0041 }, + /*expect*/ { 0,1,1, "A" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x0042 }, + /*expect*/ { 0,1,1, "B" }, + }, + /* #03 : error case */ + /* */ + { /*input.*/ { 1, 0x00C4 }, + /*expect*/ { 0,1,-1, "" }, + }, + /* #04 : error case */ + { /*input.*/ { 1, 0x30A4 }, + /*expect*/ { 0,1,-1, "" }, + }, + /* #05 : state dependency */ + { /*input.*/ { 0, 0x0000 }, + /*expect*/ { 0,0,0, "" }, + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Twctomb, TST_LOC_eucJP }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x3042 }, + /*expect*/ { 0,1,2, "\244\242" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x3044 }, + /*expect*/ { 0,1,2, "\244\244" }, + }, + /* #03 : normal case */ + { /*input.*/ { 1, 0x008E }, + /*expect*/ { 0,1,-1, "" }, + }, + /* #04 : jisX0212 */ + { /*input.*/ { 1, 0x00C4 }, + /*expect*/ { 0,1,3, "\217\252\243" }, /* jisx0210 returns 3 */ + }, + /* #05 : state dependency */ + { /*input.*/ { 0, 0x008E }, + /*expect*/ { 0,0,0, "" }, + }, + { .is_last = 1 } + } + }, +#else + { + { Twctomb, TST_LOC_ja_UTF8 }, + { + /* #01 : normal case */ + { /*input.*/ { 1, 0x3042 }, + /*expect*/ { 0,1,3, "\343\201\202" }, + }, + /* #02 : normal case */ + { /*input.*/ { 1, 0x3044 }, + /*expect*/ { 0,1,3, "\343\201\204" }, + }, + /* #03 : normal case */ + { /*input.*/ { 1, 0x008E }, + /*expect*/ { 0,1,2, "\302\216" }, + }, + /* #04 : jisX0212 */ + { /*input.*/ { 1, 0x00C4 }, + /*expect*/ { 0,1,2, "\303\204" }, /* jisx0210 returns 3 */ + }, + /* #05 : state dependency */ + { /*input.*/ { 0, 0x008E }, + /*expect*/ { 0,0,0, "" }, + }, + { .is_last = 1 } + } + }, +#endif + { + { Twctomb, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/dat_wctrans.c b/test/locale-mbwc/dat_wctrans.c new file mode 100644 index 0000000..df4d3ad --- /dev/null +++ b/test/locale-mbwc/dat_wctrans.c @@ -0,0 +1,99 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wctrans.c + * + * WCTRANS: wctrans_t wctrans( const char *charclass ); + */ + +/* + * NOTE: + * When a return value is expected to be 0 (false), + * set ret_flg=1 and set ret_val=0. + * Otherwise just set ret_flg=0. + */ + + +TST_WCTRANS tst_wctrans_loc [] = { + + { { Twctrans, TST_LOC_de }, + { + { /*inp*/ { "" }, /* #1 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "upper" }, /* #2 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "lower" }, /* #3 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "toupper" }, /* #4 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "tolower" }, /* #5 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xxxxx" }, /* #6 */ + /*exp*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twctrans, TST_LOC_enUS }, + { + { /*inp*/ { "" }, /* #1 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "upper" }, /* #2 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "lower" }, /* #3 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "toupper" }, /* #4 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "tolower" }, /* #5 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xxxxx" }, /* #6 */ + /*exp*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, +#if 0 + { { Twctrans, TST_LOC_eucJP }, +#else + { { Twctrans, TST_LOC_ja_UTF8 }, +#endif + { + { /*inp*/ { "" }, /* #1 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "upper" }, /* #2 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "lower" }, /* #3 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "toupper" }, /* #4 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "tolower" }, /* #5 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xxxxx" }, /* #6 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "tojhira" }, /* #7 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "tojkata" }, /* #8 */ + /*exp*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { { Twctrans, TST_LOC_end }} +}; diff --git a/test/locale-mbwc/dat_wctype.c b/test/locale-mbwc/dat_wctype.c new file mode 100644 index 0000000..db3bf33 --- /dev/null +++ b/test/locale-mbwc/dat_wctype.c @@ -0,0 +1,189 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY + * + * FILE: dat_wctype.c + * + * WCTYPE: wctype_t wctype( const char *class ); + */ + +/* + * NOTE: + * When a return value is expected to be 0 (false), + * set ret_flg=1 and set ret_val=0. + * Otherwise just set ret_flg=0. + */ + + +TST_WCTYPE tst_wctype_loc [] = { + + { { Twctype, TST_LOC_de }, + { + { /*inp*/ { "alnum" }, /* #01 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "alpha" }, /* #02 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "cntrl" }, /* #03 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "digit" }, /* #04 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "graph" }, /* #05 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "lower" }, /* #06 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "print" }, /* #07 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "punct" }, /* #08 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "space" }, /* #09 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "upper" }, /* #10 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xdigit" }, /* #11 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "" }, /* #12 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "ideograph" }, /* #13 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "english" }, /* #14 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "ascii" }, /* #15 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "special" }, /* #16 */ + /*exp*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, + { { Twctype, TST_LOC_enUS }, + { + { /*inp*/ { "alnum" }, /* #01 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "alpha" }, /* #02 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "cntrl" }, /* #03 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "digit" }, /* #04 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "graph" }, /* #05 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "lower" }, /* #06 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "print" }, /* #07 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "punct" }, /* #08 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "space" }, /* #09 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "upper" }, /* #10 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xdigit" }, /* #11 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "" }, /* #12 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "ideograph" }, /* #13 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "english" }, /* #14 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "ascii" }, /* #15 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "special" }, /* #16 */ + /*exp*/ { 0,1,0, }, + }, + { .is_last = 1 } + } + }, +#if 0 + { { Twctype, TST_LOC_eucJP }, +#else + { { Twctype, TST_LOC_ja_UTF8 }, +#endif + { + { /*inp*/ { "alnum" }, /* #01 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "alpha" }, /* #02 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "cntrl" }, /* #03 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "digit" }, /* #04 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "graph" }, /* #05 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "lower" }, /* #06 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "print" }, /* #07 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "punct" }, /* #08 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "space" }, /* #09 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "upper" }, /* #10 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "xdigit" }, /* #11 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "ideogram" }, /* #12 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "phonogram" }, /* #13 */ + /*exp*/ { 0,1,0, }, + }, + { /*inp*/ { "jspace" }, /* #14 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "jhira" }, /* #15 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "jkata" }, /* #16 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "jkanji" }, /* #17 */ + /*exp*/ { 0,0,0, }, + }, + { /*inp*/ { "jdigit" }, /* #18 */ + /*exp*/ { 0,0,0, }, + }, + { .is_last = 1 } + } + }, + { { Twctype, TST_LOC_end }} +}; diff --git a/test/locale-mbwc/dat_wcwidth.c b/test/locale-mbwc/dat_wcwidth.c new file mode 100644 index 0000000..b6b7c29 --- /dev/null +++ b/test/locale-mbwc/dat_wcwidth.c @@ -0,0 +1,149 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: dat_wcwidth.c + * + * WCWIDTH: int wcwidth (wchar_t wc); + */ + +TST_WCWIDTH tst_wcwidth_loc [] = { + { + { Twcwidth, TST_LOC_de }, + { + { /*inp*/ { 0x0000 }, /* #01 */ + /*exp*/ { 0, 1,0, }, + }, + { /*inp*/ { 0x0020 }, /* #02 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x007F }, /* #03 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x0080 }, /* #04 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x00C1 }, /* #06 */ + /*exp*/ { 0, 1,1, }, + }, +#ifdef SHOJI_IS_RIGHT + /* */ /* CHECK : wint_t */ + { /*inp*/ { 0x3041 }, /* #07 */ + /*exp*/ { 0, 1,0, }, + }, +#else + { /*inp*/ { 0x3041 }, /* #07 */ + /*exp*/ { 0, 1,EOF, }, + }, +#endif + { .is_last = 1 } + } + }, + { + { Twcwidth, TST_LOC_enUS }, + { + { /*inp*/ { 0x0000 }, /* #01 */ + /*exp*/ { 0, 1,0, }, + }, + { /*inp*/ { 0x0020 }, /* #02 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x007F }, /* #03 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x0080 }, /* #04 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x00C1 }, /* #06 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x3041 }, /* #07 */ + /*exp*/ { 0, 1,-1, }, + }, + { .is_last = 1 } + } + }, +#if 0 + { + { Twcwidth, TST_LOC_eucJP }, + { + { /*inp*/ { 0x0000 }, /* #01 */ + /*exp*/ { 0, 1,0, }, + }, + { /*inp*/ { 0x0020 }, /* #02 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x007F }, /* #03 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x0080 }, /* #04 */ + /*exp*/ { 0, 1,-1, }, + }, +#ifdef SHOJI_IS_RIGHT + /* */ + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,0, }, + }, +#else + /* XXX U00A1 is a valid character in EUC-JP. */ + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,2, }, + }, +#endif + /* jisx0212 */ + { /*inp*/ { 0x00C1 }, /* #06 */ + /*exp*/ { 0, 1,2, }, + }, + { /*inp*/ { 0x3041 }, /* #07 */ + /*exp*/ { 0, 1,2, }, + }, + { .is_last = 1 } + } + }, +#else + { + { Twcwidth, TST_LOC_ja_UTF8 }, + { + { /*inp*/ { 0x0000 }, /* #01 */ + /*exp*/ { 0, 1,0, }, + }, + { /*inp*/ { 0x0020 }, /* #02 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x007F }, /* #03 */ + /*exp*/ { 0, 1,-1, }, + }, + { /*inp*/ { 0x0080 }, /* #04 */ + /*exp*/ { 0, 1,-1, }, + }, +#ifdef SHOJI_IS_RIGHT + /* */ + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,0, }, + }, +#else + /* XXX U00A1 is a valid character in EUC-JP.UTF-8. */ + { /*inp*/ { 0x00A1 }, /* #05 */ + /*exp*/ { 0, 1,1, }, + }, +#endif + /* jisx0212 */ + { /*inp*/ { 0x00C1 }, /* #06 */ + /*exp*/ { 0, 1,1, }, + }, + { /*inp*/ { 0x3041 }, /* #07 */ + /*exp*/ { 0, 1,2, }, + }, + { .is_last = 1 } + } + }, +#endif + { + { Twcwidth, TST_LOC_end } + } +}; diff --git a/test/locale-mbwc/tgn_funcdef.h b/test/locale-mbwc/tgn_funcdef.h new file mode 100644 index 0000000..ec24792 --- /dev/null +++ b/test/locale-mbwc/tgn_funcdef.h @@ -0,0 +1,160 @@ +#ifndef TGN_FUNCDEF_H +#define TGN_FUNCDEF_H + +/* Unique number for each test. */ +#define Tiswalnum 1 +#define Tiswalpha 2 +#define Tiswcntrl 3 +#define Tiswctype 4 +#define Tiswdigit 5 +#define Tiswgraph 6 +#define Tiswlower 7 +#define Tiswprint 8 +#define Tiswpunct 9 +#define Tiswspace 10 +#define Tiswupper 11 +#define Tiswxdigit 12 +#define Tmblen 13 +#define Tmbrlen 14 +#define Tmbrtowc 15 +#define Tmbsrtowcs 16 +#define Tmbstowcs 17 +#define Tmbtowc 18 +#define Tstrcoll 19 +#define Tstrfmon 20 +#define Tstrxfrm 21 +#define Tswscanf 22 +#define Ttowctrans 23 +#define Ttowlower 24 +#define Ttowupper 25 +#define Twcrtomb 26 +#define Twcscat 27 +#define Twcschr 28 +#define Twcscmp 29 +#define Twcscoll 30 +#define Twcscpy 31 +#define Twcscspn 32 +#define Twcslen 33 +#define Twcsncat 34 +#define Twcsncmp 35 +#define Twcsncpy 36 +#define Twcspbrk 37 +#define Twcsrtombs 38 +#define Twcsspn 39 +#define Twcsstr 40 +#define Twcstod 41 +#define Twcstok 42 +#define Twcstombs 43 +#define Twcswidth 44 +#define Twcsxfrm 45 +#define Twctob 46 +#define Twctomb 47 +#define Twctrans 48 +#define Twctype 49 +#define Twcwidth 50 + +/* Name of each test. */ +#define S_ISWALNUM "iswalnum" +#define S_ISWALPHA "iswalpha" +#define S_ISWCNTRL "iswcntrl" +#define S_ISWCTYPE "iswctype" +#define S_ISWDIGIT "iswdigit" +#define S_ISWGRAPH "iswgraph" +#define S_ISWLOWER "iswlower" +#define S_ISWPRINT "iswprint" +#define S_ISWPUNCT "iswpunct" +#define S_ISWSPACE "iswspace" +#define S_ISWUPPER "iswupper" +#define S_ISWXDIGIT "iswxdigit" +#define S_MBLEN "mblen" +#define S_MBRLEN "mbrlen" +#define S_MBRTOWC "mbrtowc" +#define S_MBSRTOWCS "mbsrtowcs" +#define S_MBSTOWCS "mbstowcs" +#define S_MBTOWC "mbtowc" +#define S_STRCOLL "strcoll" +#define S_STRFMON "strfmon" +#define S_STRXFRM "strxfrm" +#define S_SWSCANF "swscanf" +#define S_TOWCTRANS "towctrans" +#define S_TOWLOWER "towlower" +#define S_TOWUPPER "towupper" +#define S_WCRTOMB "wcrtomb" +#define S_WCSCAT "wcscat" +#define S_WCSCHR "wcschr" +#define S_WCSCMP "wcscmp" +#define S_WCSCOLL "wcscoll" +#define S_WCSCPY "wcscpy" +#define S_WCSCSPN "wcscspn" +#define S_WCSLEN "wcslen" +#define S_WCSNCAT "wcsncat" +#define S_WCSNCMP "wcsncmp" +#define S_WCSNCPY "wcsncpy" +#define S_WCSPBRK "wcspbrk" +#define S_WCSRTOMBS "wcsrtombs" +#define S_WCSSPN "wcsspn" +#define S_WCSSTR "wcsstr" +#define S_WCSTOD "wcstod" +#define S_WCSTOK "wcstok" +#define S_WCSTOMBS "wcstombs" +#define S_WCSWIDTH "wcswidth" +#define S_WCSXFRM "wcsxfrm" +#define S_WCTOB "wctob" +#define S_WCTOMB "wctomb" +#define S_WCTRANS "wctrans" +#define S_WCTYPE "wctype" +#define S_WCWIDTH "wcwidth" + +/* Prototypes for test functions. */ +extern int tst_iswalnum (FILE *, int); +extern int tst_iswalpha (FILE *, int); +extern int tst_iswcntrl (FILE *, int); +extern int tst_iswctype (FILE *, int); +extern int tst_iswdigit (FILE *, int); +extern int tst_iswgraph (FILE *, int); +extern int tst_iswlower (FILE *, int); +extern int tst_iswprint (FILE *, int); +extern int tst_iswpunct (FILE *, int); +extern int tst_iswspace (FILE *, int); +extern int tst_iswupper (FILE *, int); +extern int tst_iswxdigit (FILE *, int); +extern int tst_mblen (FILE *, int); +extern int tst_mbrlen (FILE *, int); +extern int tst_mbrtowc (FILE *, int); +extern int tst_mbsrtowcs (FILE *, int); +extern int tst_mbstowcs (FILE *, int); +extern int tst_mbtowc (FILE *, int); +extern int tst_strcoll (FILE *, int); +extern int tst_strfmon (FILE *, int); +extern int tst_strxfrm (FILE *, int); +extern int tst_swscanf (FILE *, int); +extern int tst_towctrans (FILE *, int); +extern int tst_towlower (FILE *, int); +extern int tst_towupper (FILE *, int); +extern int tst_wcrtomb (FILE *, int); +extern int tst_wcscat (FILE *, int); +extern int tst_wcschr (FILE *, int); +extern int tst_wcscmp (FILE *, int); +extern int tst_wcscoll (FILE *, int); +extern int tst_wcscpy (FILE *, int); +extern int tst_wcscspn (FILE *, int); +extern int tst_wcslen (FILE *, int); +extern int tst_wcsncat (FILE *, int); +extern int tst_wcsncmp (FILE *, int); +extern int tst_wcsncpy (FILE *, int); +extern int tst_wcspbrk (FILE *, int); +extern int tst_wcsrtombs (FILE *, int); +extern int tst_wcsspn (FILE *, int); +extern int tst_wcsstr (FILE *, int); +extern int tst_wcstod (FILE *, int); +extern int tst_wcstok (FILE *, int); +extern int tst_wcstombs (FILE *, int); +extern int tst_wcswidth (FILE *, int); +extern int tst_wcsxfrm (FILE *, int); +extern int tst_wctob (FILE *, int); +extern int tst_wctomb (FILE *, int); +extern int tst_wctrans (FILE *, int); +extern int tst_wctype (FILE *, int); +extern int tst_wcwidth (FILE *, int); + +#endif /* TGN_FUNCDEF_H */ diff --git a/test/locale-mbwc/tgn_locdef.h b/test/locale-mbwc/tgn_locdef.h new file mode 100644 index 0000000..89146a7 --- /dev/null +++ b/test/locale-mbwc/tgn_locdef.h @@ -0,0 +1,32 @@ +#ifndef TGN_LOCDEF_H +#define TGN_LOCDEF_H + +/* Defines for all locales used in the suite. */ + +/* POSIX C locale. */ +#define TST_LOC_C "C" + +/* German locale with ISO-8859-1. */ +#define TST_LOC_de "de_DE.ISO-8859-1" + +/* For US we use ANSI_X3.4-1968 (ASCII). Changed in en_US.ISO-8859-1 */ +#define TST_LOC_en "en_US.ISO-8859-1" +#define TST_LOC_enUS TST_LOC_C + +/* NOTE: ja_JP.EUC-JP locale isn't supported into the uClibc! + UTF-8 is the only multibyte codeset supported. */ +/* Japanese locale with EUC-JP. */ +#if 0 +#define TST_LOC_eucJP "ja_JP.EUC-JP" +#endif + +/* Japanese locale with UTF-8. */ +#define TST_LOC_ja_UTF8 "ja_JP.UTF-8" + +/* German locale with UTF-8. */ +#define TST_LOC_de_UTF8 "de_DE.UTF-8" + +/* End marker - must appear in each table as last entry. */ +#define TST_LOC_end "lastEntry" + +#endif /* TGN_LOCDEF_H */ diff --git a/test/locale-mbwc/tsp_common.c b/test/locale-mbwc/tsp_common.c new file mode 100644 index 0000000..cd88274 --- /dev/null +++ b/test/locale-mbwc/tsp_common.c @@ -0,0 +1,64 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * Main driver + */ + + +#define TST_FUNCTION_CALL(func) _TST_FUNCTION_CALL(func) +#define _TST_FUNCTION_CALL(func) tst ##_## func + +#include +#include +#include +#include +#include +#include + +#include "tst_types.h" +#include "tgn_locdef.h" + + +int +main (int argc, char *argv[]) +{ + int ret; + int debug; + + debug = argc > 1 ? atoi (argv[1]) : 0; + + if (debug) + { + fprintf (stdout, "\nTST_MBWC ===> %s ...\n", argv[0]); + } + ret = TST_FUNCTION_CALL (TST_FUNCTION) (stdout, debug); + + return (ret != 0); +} + +#define MAX_RESULT_REC 132 +char result_rec[MAX_RESULT_REC]; + + +int +result (FILE * fp, char res, const char *func, const char *loc, int rec_no, + int seq_no, int case_no, const char *msg) +{ + if (fp == NULL + || strlen (func) + strlen (loc) + strlen (msg) + 32 > MAX_RESULT_REC) + { + fprintf (stderr, + "Warning: result(): can't write the result: %s:%s:%d:%d:%s\n", + func, loc, rec_no, case_no, msg); + return 0; + } + + sprintf (result_rec, "%s:%s:%d:%d:%d:%c:%s\n", func, loc, rec_no, seq_no, + case_no, res, msg); + + if (fputs (result_rec, fp) == EOF) + { + return 0; + } + + return 1; +} diff --git a/test/locale-mbwc/tst_funcs.h b/test/locale-mbwc/tst_funcs.h new file mode 100644 index 0000000..552bed2 --- /dev/null +++ b/test/locale-mbwc/tst_funcs.h @@ -0,0 +1,272 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: tst_funcs.h + * + * Definitions of macros + */ + + +#ifndef TST_FUNCS_H +#define TST_FUNCS_H + +#define C_SUCCESS 'S' /* test case test passed */ +#define C_FAILURE 'F' /* test case failed */ +#define C_IGNORED 'I' /* test case/result ignored (not tested) */ +#define C_INVALID 'D' /* test data may be wrong */ +#define C_LOCALES 'L' /* can't set locale (skip) */ + + +extern int result (FILE * fp, char res, const char *func, const char *loc, + int rec_no, int seq_num, int case_no, const char *msg); + +#define Result(C, S, E, M) \ + result (fp, (C), (S), locale, rec+1, seq_num+1, (E), (M)) + +#define CASE_0 0 +#define CASE_1 1 +#define CASE_2 2 +#define CASE_3 3 +#define CASE_4 4 +#define CASE_5 5 +#define CASE_6 6 +#define CASE_7 7 +#define CASE_8 8 +#define CASE_9 9 + +#define MS_PASSED "PASSED" +#define MS_SPACE " " +#define MS_FAILED " " +#define MS_NOTEST "NOTEST" +#define MS_ABORTU "ABEND0" +#define MS_ABORT "ABEND1" + +#define MK_PASSED 0x00 +#define MK_SPACE 0x01 +#define MK_NOTEST 0x02 +#define MK_ABORTU 0x04 +#define MK_ABORT 0x08 + + + +/* ------------------ COMMON MACROS ------------------ */ + +#define TST_ABS(x) (((x) > 0) ? (x) : -(x)) + +#define TMD_ERRET(_type_) int err_val; \ + int ret_flg; \ + _type_ ret_val + +#define TMD_RECHEAD(_FUNC_) \ + \ + typedef struct { \ + TIN_##_FUNC_##_REC input; \ + TEX_##_FUNC_##_REC expect; \ + int is_last; \ + } TST_##_FUNC_##_REC; \ + typedef struct { \ + TST_HEAD hd; \ + TST_##_FUNC_##_REC rec[ MAX_LOC_TEST ]; \ + } TST_##_FUNC_ + +#define TST_FTYP(func) tst_##func##_loc +#define TST_HEAD(func) tst_##func##_loc[ loc ].hd +#define TST_INPUT(func) tst_##func##_loc[ loc ].rec[ rec ].input +#define TST_EXPECT(func) tst_##func##_loc[ loc ].rec[ rec ].expect +#define TST_INPUT_SEQ(func) \ + tst_##func##_loc[ loc ].rec[ rec ].input.seq[ seq_num ] +#define TST_EXPECT_SEQ(func) \ + tst_##func##_loc[ loc ].rec[ rec ].expect.seq[ seq_num ] +#define TST_IS_LAST(func) \ + tst_##func##_loc[ loc ].rec[ rec ].is_last + + +#define TST_DECL_VARS(_type_) \ + int loc, rec, err_count = 0; \ + int warn_count __attribute__ ((unused)); \ + int func_id, seq_num = 0; \ + const char *locale; \ + int err_exp, ret_flg; \ + int errno_save = 0; \ + _type_ ret_exp; \ + _type_ ret + +#define TST_DO_TEST(o_func) \ + for (loc = 0; strcmp (TST_HEAD (o_func).locale, TST_LOC_end); ++loc) + + +#define TST_HEAD_LOCALE(ofunc, s_func) \ + func_id = TST_HEAD (ofunc).func_id; \ + locale = TST_HEAD (ofunc).locale; \ + if (setlocale (LC_ALL, locale) == NULL) \ + { \ + fprintf (stderr, "Warning : can't set locale: %s\nskipping ...\n", \ + locale); \ + result (fp, C_LOCALES, s_func, locale, 0, 0, 0, "can't set locale"); \ + ++err_count; \ + continue; \ + } + +#define TST_DO_REC(ofunc) \ + for (rec=0; !TST_IS_LAST (ofunc); ++rec) + +#define TST_DO_SEQ(_count_) \ + for (seq_num=0; seq_num < _count_; seq_num++) + +#define TST_GET_ERRET(_ofunc_) \ + err_exp = TST_EXPECT (_ofunc_).err_val; \ + ret_flg = TST_EXPECT (_ofunc_).ret_flg; \ + ret_exp = TST_EXPECT (_ofunc_).ret_val + +#define TST_GET_ERRET_SEQ(_ofunc_) \ + err_exp = TST_EXPECT_SEQ (_ofunc_).err_val; \ + ret_flg = TST_EXPECT_SEQ (_ofunc_).ret_flg; \ + ret_exp = TST_EXPECT_SEQ (_ofunc_).ret_val + +#define TST_CLEAR_ERRNO \ + errno = 0 + +#define TST_SAVE_ERRNO \ + errno_save = errno + +/* Test value of ret and of errno if it should have a value. */ +#define TST_IF_RETURN(_s_func_) \ + if (err_exp != 0) \ + { \ + if (errno_save == err_exp) \ + { \ + result (fp, C_SUCCESS, _s_func_, locale, rec+1, seq_num+1, 1, \ + MS_PASSED); \ + } \ + else \ + { \ + err_count++; \ + result (fp, C_FAILURE, _s_func_, locale, rec+1, seq_num+1, 1, \ + "the value of errno is different from an expected value"); \ + } \ + } \ + \ + if (ret_flg == 1) \ + { \ + if (ret == ret_exp) \ + { \ + result (fp, C_SUCCESS, _s_func_, locale, rec+1, seq_num+1, 2, \ + MS_PASSED); \ + } \ + else \ + { \ + err_count++; \ + result (fp, C_FAILURE, _s_func_, locale, rec+1, seq_num+1, 2, \ + "the return value is different from an expected value"); \ + } \ + } \ + else + +#define TEX_ERRET_REC(_type_) \ + struct { \ + TMD_ERRET (_type_); \ + } + +#define TEX_ERRET_REC_SEQ(_type_, _count_) \ + struct { \ + struct { \ + TMD_ERRET (_type_); \ + } seq[ _count_ ]; \ + } + + + +/* ------------------ FUNCTION: ISW*() ------------------- */ + +#define TST_ISW_STRUCT(_FUNC_, _func_) \ + typedef \ + struct { \ + wint_t wc; \ + } TIN_ISW##_FUNC_##_REC; \ + typedef \ + TEX_ERRET_REC (int) TEX_ISW##_FUNC_##_REC; \ + TMD_RECHEAD (ISW##_FUNC_) + +#define TST_FUNC_ISW(_FUNC_, _func_) \ +int \ +tst_isw##_func_ (FILE *fp, int debug_flg) \ +{ \ + TST_DECL_VARS(int); \ + wint_t wc; \ + TST_DO_TEST (isw##_func_) \ + { \ + TST_HEAD_LOCALE (isw##_func_, S_ISW##_FUNC_); \ + TST_DO_REC(isw##_func_) \ + { \ + TST_GET_ERRET (isw##_func_); \ + wc = TST_INPUT (isw##_func_).wc; \ + ret = isw##_func_ (wc); \ + if (debug_flg) \ + { \ + fprintf (stdout, "isw*() [ %s : %d ] ret = %d\n", locale, \ + rec+1, ret); \ + } \ + \ + TST_IF_RETURN (S_ISW##_FUNC_) \ + { \ + if (ret != 0) \ + { \ + result (fp, C_SUCCESS, S_ISW##_FUNC_, locale, rec+1, \ + seq_num+1, 3, MS_PASSED); \ + } \ + else \ + { \ + err_count++; \ + result (fp, C_FAILURE, S_ISW##_FUNC_, locale, rec+1, \ + seq_num+1, 3, \ + "the function returned 0, but should be non-zero"); \ + } \ + } \ + } \ + } \ + \ + return err_count; \ +} + + + +/* ------------------ FUNCTION: TOW*() ------------------ */ + +#define TST_TOW_STRUCT(_FUNC_, _func_) \ + typedef \ + struct { \ + wint_t wc; \ + } TIN_TOW##_FUNC_##_REC; \ + typedef \ + TEX_ERRET_REC (wint_t) TEX_TOW##_FUNC_##_REC; \ + TMD_RECHEAD (TOW##_FUNC_) + +#define TST_FUNC_TOW(_FUNC_, _func_) \ +int \ +tst_tow##_func_ (FILE *fp, int debug_flg) \ +{ \ + TST_DECL_VARS (wint_t); \ + wint_t wc; \ + TST_DO_TEST (tow##_func_) \ + { \ + TST_HEAD_LOCALE (tow##_func_, S_TOW##_FUNC_); \ + TST_DO_REC (tow##_func_) \ + { \ + TST_GET_ERRET (tow##_func_); \ + wc = TST_INPUT (tow##_func_).wc; \ + ret = tow##_func_ (wc); \ + if (debug_flg) \ + { \ + fprintf (stdout, "tow*() [ %s : %d ] ret = 0x%x\n", \ + locale, rec+1, ret); \ + } \ + \ + TST_IF_RETURN (S_TOW##_FUNC_) { }; \ + } \ + } \ + \ + return err_count; \ +} + + +#endif /* TST_FUNCS_H */ diff --git a/test/locale-mbwc/tst_iswalnum.c b/test/locale-mbwc/tst_iswalnum.c new file mode 100644 index 0000000..95ba863 --- /dev/null +++ b/test/locale-mbwc/tst_iswalnum.c @@ -0,0 +1,10 @@ +/* + ISWALNUM: int iswalnum (wint_t wc) +*/ + +#define TST_FUNCTION iswalnum + +#include "tsp_common.c" +#include "dat_iswalnum.c" + +TST_FUNC_ISW (ALNUM, alnum); diff --git a/test/locale-mbwc/tst_iswalpha.c b/test/locale-mbwc/tst_iswalpha.c new file mode 100644 index 0000000..8eff2cc --- /dev/null +++ b/test/locale-mbwc/tst_iswalpha.c @@ -0,0 +1,10 @@ +/* + ISWALPHA: int iswalpha (wint_t wc); +*/ + +#define TST_FUNCTION iswalpha + +#include "tsp_common.c" +#include "dat_iswalpha.c" + +TST_FUNC_ISW (ALPHA, alpha); diff --git a/test/locale-mbwc/tst_iswcntrl.c b/test/locale-mbwc/tst_iswcntrl.c new file mode 100644 index 0000000..4e1baa8 --- /dev/null +++ b/test/locale-mbwc/tst_iswcntrl.c @@ -0,0 +1,10 @@ +/* + ISWCNTRL: int iswcntrl (wint_t wc); +*/ + +#define TST_FUNCTION iswcntrl + +#include "tsp_common.c" +#include "dat_iswcntrl.c" + +TST_FUNC_ISW (CNTRL, cntrl); diff --git a/test/locale-mbwc/tst_iswctype.c b/test/locale-mbwc/tst_iswctype.c new file mode 100644 index 0000000..3e79e09 --- /dev/null +++ b/test/locale-mbwc/tst_iswctype.c @@ -0,0 +1,53 @@ +/* + ISWCTYPE: int iswctype (wint_t wc, wctype_t desc); +*/ + +#define TST_FUNCTION iswctype + +#include "tsp_common.c" +#include "dat_iswctype.c" + + +int +tst_iswctype (FILE *fp, int debug_flg) +{ + TST_DECL_VARS (int); + wint_t wc; + const char *ts; + + TST_DO_TEST (iswctype) + { + TST_HEAD_LOCALE (iswctype, S_ISWCTYPE); + TST_DO_REC (iswctype) + { + TST_GET_ERRET (iswctype); + wc = TST_INPUT (iswctype).wc; + ts = TST_INPUT (iswctype).ts; + ret = iswctype (wc, wctype (ts)); + TST_SAVE_ERRNO; + if (debug_flg) + { + fprintf (stdout, "iswctype() [ %s : %d ] ret = %d\n", + locale, rec+1, ret); + } + + TST_IF_RETURN (S_ISWCTYPE) + { + if (ret != 0) + { + result (fp, C_SUCCESS, S_ISWCTYPE, locale, rec+1, + seq_num+1, 3, MS_PASSED); + } + else + { + err_count++; + result (fp, C_FAILURE, S_ISWCTYPE, locale, rec+1, + seq_num+1, 3, + "the function returned 0, but should be non-zero"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_iswdigit.c b/test/locale-mbwc/tst_iswdigit.c new file mode 100644 index 0000000..5429ed0 --- /dev/null +++ b/test/locale-mbwc/tst_iswdigit.c @@ -0,0 +1,11 @@ +/* + ISWDIGIT: int iswdigit (wint_t wc); +*/ + + +#define TST_FUNCTION iswdigit + +#include "tsp_common.c" +#include "dat_iswdigit.c" + +TST_FUNC_ISW (DIGIT, digit); diff --git a/test/locale-mbwc/tst_iswgraph.c b/test/locale-mbwc/tst_iswgraph.c new file mode 100644 index 0000000..91a70e2 --- /dev/null +++ b/test/locale-mbwc/tst_iswgraph.c @@ -0,0 +1,10 @@ +/* + ISWGRAPH: int iswgraph (wint_t wc); +*/ + +#define TST_FUNCTION iswgraph + +#include "tsp_common.c" +#include "dat_iswgraph.c" + +TST_FUNC_ISW (GRAPH, graph); diff --git a/test/locale-mbwc/tst_iswlower.c b/test/locale-mbwc/tst_iswlower.c new file mode 100644 index 0000000..e091100 --- /dev/null +++ b/test/locale-mbwc/tst_iswlower.c @@ -0,0 +1,10 @@ +/* + ISWLOWER: int iswlower (wint_t wc); +*/ + +#define TST_FUNCTION iswlower + +#include "tsp_common.c" +#include "dat_iswlower.c" + +TST_FUNC_ISW (LOWER, lower); diff --git a/test/locale-mbwc/tst_iswprint.c b/test/locale-mbwc/tst_iswprint.c new file mode 100644 index 0000000..8d5bde5 --- /dev/null +++ b/test/locale-mbwc/tst_iswprint.c @@ -0,0 +1,10 @@ +/* + ISWPRINT: int iswprint (wint_t wc); +*/ + +#define TST_FUNCTION iswprint + +#include "tsp_common.c" +#include "dat_iswprint.c" + +TST_FUNC_ISW (PRINT, print); diff --git a/test/locale-mbwc/tst_iswpunct.c b/test/locale-mbwc/tst_iswpunct.c new file mode 100644 index 0000000..4749d61 --- /dev/null +++ b/test/locale-mbwc/tst_iswpunct.c @@ -0,0 +1,10 @@ +/* + ISWPUNCT: int iswpunct (wint_t wc); +*/ + +#define TST_FUNCTION iswpunct + +#include "tsp_common.c" +#include "dat_iswpunct.c" + +TST_FUNC_ISW (PUNCT, punct); diff --git a/test/locale-mbwc/tst_iswspace.c b/test/locale-mbwc/tst_iswspace.c new file mode 100644 index 0000000..6c26d5f --- /dev/null +++ b/test/locale-mbwc/tst_iswspace.c @@ -0,0 +1,10 @@ +/* + ISWSPACE: int iswspace (wint_t wc); +*/ + +#define TST_FUNCTION iswspace + +#include "tsp_common.c" +#include "dat_iswspace.c" + +TST_FUNC_ISW (SPACE, space); diff --git a/test/locale-mbwc/tst_iswupper.c b/test/locale-mbwc/tst_iswupper.c new file mode 100644 index 0000000..dfe5a5b --- /dev/null +++ b/test/locale-mbwc/tst_iswupper.c @@ -0,0 +1,10 @@ +/* + ISWUPPER: int iswupper (wint_t wc); +*/ + +#define TST_FUNCTION iswupper + +#include "tsp_common.c" +#include "dat_iswupper.c" + +TST_FUNC_ISW (UPPER, upper); diff --git a/test/locale-mbwc/tst_iswxdigit.c b/test/locale-mbwc/tst_iswxdigit.c new file mode 100644 index 0000000..5f9c0c5 --- /dev/null +++ b/test/locale-mbwc/tst_iswxdigit.c @@ -0,0 +1,10 @@ +/* + ISWXDIGIT: int iswxdigit (wint_t wc); +*/ + +#define TST_FUNCTION iswxdigit + +#include "tsp_common.c" +#include "dat_iswxdigit.c" + +TST_FUNC_ISW (XDIGIT, xdigit); diff --git a/test/locale-mbwc/tst_mblen.c b/test/locale-mbwc/tst_mblen.c new file mode 100644 index 0000000..35ccf6c --- /dev/null +++ b/test/locale-mbwc/tst_mblen.c @@ -0,0 +1,85 @@ +/* + MBLEN: int mblen (char *s, size_t n) +*/ + +#define TST_FUNCTION mblen + +#include "tsp_common.c" +#include "dat_mblen.c" + +int +tst_mblen (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + char s_flg; + const char *s_in; + size_t n; + + TST_DO_TEST (mblen) + { + TST_HEAD_LOCALE (mblen, S_MBLEN); + TST_DO_REC (mblen) + { + TST_GET_ERRET (mblen); + s_flg = TST_INPUT (mblen).s_flg; + s_in = TST_INPUT (mblen).s; + n = TST_INPUT (mblen).n; + + if (s_flg == 0) + { + s_in = NULL; + } + + if (n == USE_MBCURMAX) + { + n = MB_CUR_MAX; + } + + TST_CLEAR_ERRNO; + ret = mblen (s_in, n); + TST_SAVE_ERRNO; + + TST_IF_RETURN (S_MBLEN) + { + if (s_in == NULL) + { /* state dependency */ + if (ret_exp == +1) + { /* state-dependent */ + if (ret != 0) + { + /* non-zero: state-dependent encoding */ + Result (C_SUCCESS, S_MBLEN, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBLEN, CASE_3, + "should be state-dependent encoding, " + "but the return value shows it is" + " state-independent"); + } + } + + if (ret_exp == 0) + { /* state-independent */ + if (ret == 0) + { + /* non-zero: state-dependent encoding */ + Result (C_SUCCESS, S_MBLEN, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBLEN, CASE_3, + "should be state-independent encoding, " + "but the return value shows it is" + " state-dependent"); + } + } + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_mbrlen.c b/test/locale-mbwc/tst_mbrlen.c new file mode 100644 index 0000000..b8681b7 --- /dev/null +++ b/test/locale-mbwc/tst_mbrlen.c @@ -0,0 +1,82 @@ +/* + MBRLEN: size_t mbrlen (char *s, size_t n, mbstate_t *ps) +*/ + +#define TST_FUNCTION mbrlen + +#include "tsp_common.c" +#include "dat_mbrlen.c" + + +int +tst_mbrlen (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char s_flg; + const char *s_in; + size_t n; + char t_flg; + char t_ini; + static mbstate_t s = { 0 }; + mbstate_t *ps; + + TST_DO_TEST (mbrlen) + { + TST_HEAD_LOCALE (mbrlen, S_MBRLEN); + TST_DO_REC (mbrlen) + { + if (mbrlen (NULL, 0, &s) != 0) + { + err_count++; + Result (C_FAILURE, S_MBRLEN, CASE_3, + "Initialization (external mbstate object) failed " + "- skipped this test case."); + continue; + } + + TST_DO_SEQ (MBRLEN_SEQNUM) + { + TST_GET_ERRET_SEQ (mbrlen); + s_flg = TST_INPUT_SEQ (mbrlen).s_flg; + s_in = TST_INPUT_SEQ (mbrlen).s; + n = TST_INPUT_SEQ (mbrlen).n; + t_flg = TST_INPUT_SEQ (mbrlen).t_flg; + t_ini = TST_INPUT_SEQ (mbrlen).t_init; + if (s_flg == 0) + { + s_in = NULL; + } + + if (n == USE_MBCURMAX) /* rewrite tst_mblen() like this */ + { + n = MB_CUR_MAX; + } + + ps = (t_flg == 0) ? NULL : &s; + + if (t_ini != 0) + { + memset (&s, 0, sizeof (s)); + mbrlen (NULL, 0, NULL); + } + + TST_CLEAR_ERRNO; + ret = mbrlen (s_in, n, ps); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "mbrlen() [ %s : %d : %d ] ret = %zd\n", + locale, rec + 1, seq_num + 1, ret); + fprintf (stdout, " errno = %d\n", errno_save); + } + + TST_IF_RETURN (S_MBRLEN) + { + }; + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_mbrtowc.c b/test/locale-mbwc/tst_mbrtowc.c new file mode 100644 index 0000000..3a6070a --- /dev/null +++ b/test/locale-mbwc/tst_mbrtowc.c @@ -0,0 +1,103 @@ +/* + MBRTOWC: size_t mbrtowc (wchar_t *pwc, const char *s, size_t n, + mbstate_t *ps) +*/ + +#define TST_FUNCTION mbrtowc + +#include "tsp_common.c" +#include "dat_mbrtowc.c" + + +int +tst_mbrtowc (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char w_flg, s_flg; + char *s; + size_t n; + char t_flg, t_ini; + static mbstate_t t = { 0 }; + mbstate_t *pt; + wchar_t wc, *pwc, wc_ex; + + TST_DO_TEST (mbrtowc) + { + TST_HEAD_LOCALE (mbrtowc, S_MBRTOWC); + TST_DO_REC (mbrtowc) + { + if (mbrtowc (NULL, "", 0, &t) != 0) + { + err_count++; + Result (C_FAILURE, S_MBRTOWC, CASE_3, + "Initialization failed - skipping this test case."); + continue; + } + + TST_DO_SEQ (MBRTOWC_SEQNUM) + { + TST_GET_ERRET_SEQ (mbrtowc); + w_flg = TST_INPUT_SEQ (mbrtowc).w_flg; + s_flg = TST_INPUT_SEQ (mbrtowc).s_flg; + s = TST_INPUT_SEQ (mbrtowc).s; + n = TST_INPUT_SEQ (mbrtowc).n; + t_flg = TST_INPUT_SEQ (mbrtowc).t_flg; + t_ini = TST_INPUT_SEQ (mbrtowc).t_init; + pwc = (w_flg == 0) ? NULL : &wc; + + if (s_flg == 0) + { + s = NULL; + } + + if (n == USE_MBCURMAX) + { + n = MB_CUR_MAX; + } + + pt = (t_flg == 0) ? NULL : &t; +#if 0 + if (t_ini != 0) + { + memset (&t, 0, sizeof (t)); + } +#endif + TST_CLEAR_ERRNO; + ret = mbrtowc (pwc, s, n, pt); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "mbrtowc() [ %s : %d : %d ] ret = %zd\n", + locale, rec + 1, seq_num + 1, ret); + fprintf (stdout, " errno = %hd\n", + errno_save); + } + + TST_IF_RETURN (S_MBRTOWC) + { + }; + + if (pwc == NULL || s == NULL || ret == (size_t) - 1 + || ret == (size_t) - 2) + { + continue; + } + + wc_ex = TST_EXPECT_SEQ (mbrtowc).wc; + if (wc_ex == wc) + { + Result (C_SUCCESS, S_MBRTOWC, CASE_4, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBRTOWC, CASE_4, + "converted wc is different from an expected wc"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_mbsrtowcs.c b/test/locale-mbwc/tst_mbsrtowcs.c new file mode 100644 index 0000000..3f3ea71 --- /dev/null +++ b/test/locale-mbwc/tst_mbsrtowcs.c @@ -0,0 +1,109 @@ +/* + MBSRTOWCS: size_t mbsrtowcs (wchar_t *ws, const char **s, size_t n, + mbstate_t *ps) +*/ + +#define TST_FUNCTION mbsrtowcs + +#include "tsp_common.c" +#include "dat_mbsrtowcs.c" + +int +tst_mbsrtowcs (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char w_flg; + const char *s, *p; + size_t n; + char t_flg, t_ini; + static mbstate_t t = { 0 }; + mbstate_t *pt; + wchar_t ws[WCSSIZE], *ws_ex, *wp; + int err, i; + + TST_DO_TEST (mbsrtowcs) + { + TST_HEAD_LOCALE (mbsrtowcs, S_MBSRTOWCS); + TST_DO_REC (mbsrtowcs) + { + s = ""; + if (mbsrtowcs (NULL, &s, 0, &t) != 0) + { + err_count++; + Result (C_FAILURE, S_MBSRTOWCS, CASE_3, + "Initialization failed - skipping this test case."); + continue; + } + + TST_DO_SEQ (MBSRTOWCS_SEQNUM) + { + TST_GET_ERRET_SEQ (mbsrtowcs); + w_flg = TST_INPUT_SEQ (mbsrtowcs).w_flg; + p = s = TST_INPUT_SEQ (mbsrtowcs).s; + n = TST_INPUT_SEQ (mbsrtowcs).n; + t_flg = TST_INPUT_SEQ (mbsrtowcs).t_flg; + t_ini = TST_INPUT_SEQ (mbsrtowcs).t_init; + wp = (w_flg == 0) ? NULL : ws; + + if (n == USE_MBCURMAX) + { + n = MB_CUR_MAX; + } + + pt = (t_flg == 0) ? NULL : &t; + + if (t_ini != 0) + { + memset (&t, 0, sizeof (t)); + } + + TST_CLEAR_ERRNO; + ret = mbsrtowcs (wp, &p, n, pt); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, "mbsrtowcs: [ %d ] : ret = %zd\n", rec + 1, ret); + } + + TST_IF_RETURN (S_MBSRTOWCS) + { + }; + + if (wp == NULL || ret == (size_t) - 1 || ret == (size_t) - 2) + { + continue; + } + + ws_ex = TST_EXPECT_SEQ (mbsrtowcs).ws; + for (err = 0, i = 0; i < ret; i++) + { + if (debug_flg) + { + fprintf (stderr, + "mbsrtowcs: ws[%d] => 0x%lx : 0x%lx <= ws_ex[%d]\n", + i, (unsigned long int) ws[i], + (unsigned long int) ws_ex[i], i); + } + + if (ws[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_MBSRTOWCS, CASE_4, + "the converted wc string has " + "different value from an expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_MBSRTOWCS, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_mbstowcs.c b/test/locale-mbwc/tst_mbstowcs.c new file mode 100644 index 0000000..878df6a --- /dev/null +++ b/test/locale-mbwc/tst_mbstowcs.c @@ -0,0 +1,98 @@ +/* + MBSTOWCS: size_t mbstowcs (wchar_t *ws, char *s, size_t n) +*/ + +#define TST_FUNCTION mbstowcs + +#include "tsp_common.c" +#include "dat_mbstowcs.c" + +int +tst_mbstowcs (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char w_flg, s_flg; + const char *s; + size_t n; + wchar_t ws[WCSSIZE], *ws_ex, *wp; + int err, i; + + TST_DO_TEST (mbstowcs) + { + TST_HEAD_LOCALE (mbstowcs, S_MBSTOWCS); + TST_DO_REC (mbstowcs) + { + if (mbstowcs (NULL, "", 0) != 0) + { + err_count++; + Result (C_FAILURE, S_MBSTOWCS, CASE_3, + "Initialization failed - skipping this test case."); + continue; + } + + TST_DO_SEQ (MBSTOWCS_SEQNUM) + { + TST_GET_ERRET_SEQ (mbstowcs); + w_flg = TST_INPUT_SEQ (mbstowcs).w_flg; + s_flg = TST_INPUT_SEQ (mbstowcs).s_flg; + n = TST_INPUT_SEQ (mbstowcs).n; + + if (s_flg == 0) + s = NULL; + else + s = TST_INPUT_SEQ (mbstowcs).s; + + + wp = (wchar_t *) ((w_flg == 0) ? NULL : ws); + + TST_CLEAR_ERRNO; + ret = mbstowcs (wp, s, n); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, "mbstowcs: ret = %zd\n", ret); + } + + TST_IF_RETURN (S_MBSTOWCS) + { + }; + + if (s == NULL || wp == NULL || ret == (size_t) - 1) + { + continue; + } + + ws_ex = TST_EXPECT_SEQ (mbstowcs).ws; + + for (err = 0, i = 0; i < ret; i++) + { + if (debug_flg) + { + fprintf (stderr, + "mbstowcs: ws[%d] => 0x%lx : 0x%lx <= ws_ex[%d]\n", + i, (unsigned long int) ws[i], + (unsigned long int) ws_ex[i], i); + } + + if (ws[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_MBSTOWCS, CASE_4, + "the converted wc string has " + "different value from an expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_MBSTOWCS, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_mbtowc.c b/test/locale-mbwc/tst_mbtowc.c new file mode 100644 index 0000000..7c274f6 --- /dev/null +++ b/test/locale-mbwc/tst_mbtowc.c @@ -0,0 +1,130 @@ +/* + MBTOWC: int mbtowc (wchar_t *wc, char *s, size_t n) +*/ + +#define TST_FUNCTION mbtowc + +#include "tsp_common.c" +#include "dat_mbtowc.c" + + +int +tst_mbtowc (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + char w_flg, s_flg; + const char *s_in; + size_t n; + wchar_t wc, wc_ex, *wp; + + TST_DO_TEST (mbtowc) + { + TST_HEAD_LOCALE (mbtowc, S_MBTOWC); + TST_DO_REC (mbtowc) + { + if (mbstowcs (NULL, "", 0) != 0) + { + err_count++; + Result (C_FAILURE, S_MBSTOWCS, CASE_3, + "Initialization failed - skipping this test case."); + continue; + } + + TST_DO_SEQ (MBTOWC_SEQNUM) + { + TST_GET_ERRET_SEQ (mbtowc); + w_flg = TST_INPUT_SEQ (mbtowc).w_flg; + s_flg = TST_INPUT_SEQ (mbtowc).s_flg; + n = TST_INPUT_SEQ (mbtowc).n; + + if (n == USE_MBCURMAX) + { + n = MB_CUR_MAX; + } + + if (s_flg == 0) + s_in = NULL; + else + s_in = TST_INPUT_SEQ (mbtowc).s; + + wp = (wchar_t *) ((w_flg == 0) ? NULL : &wc); + + /* XXX Clear the internal state. We should probably have + a flag for this. */ + mbtowc (NULL, NULL, 0); + + TST_CLEAR_ERRNO; + ret = mbtowc (wp, s_in, n); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "mbtowc() [ %s : %d ] ret = %d\n", locale, + rec + 1, ret); + fprintf (stdout, " errno = %d\n", + errno_save); + } + + TST_IF_RETURN (S_MBTOWC) + { + if (s_in == NULL) + { /* state dependency */ + if (ret_exp == +1) + { /* state-dependent */ + if (ret != 0) + { + /* Non-zero: state-dependent encoding. */ + Result (C_SUCCESS, S_MBTOWC, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBTOWC, CASE_3, + "should be state-dependent encoding, " + "but a return value shows it is " + "state-independent"); + } + } + + if (ret_exp == 0) + { /* state-independent */ + if (ret == 0) + { + /* Non-zero: state-dependent encoding. */ + Result (C_SUCCESS, S_MBTOWC, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBTOWC, CASE_3, + "should be state-independent encoding, " + "but a return value shows it is " + "state-dependent"); + } + } + } + } + + if ((wp == NULL || s_in == NULL || s_in[0] == 0) || ret <= 0) + { + continue; + } + + wc_ex = TST_EXPECT_SEQ (mbtowc).wc; + + if (wc_ex == wc) + { + Result (C_SUCCESS, S_MBTOWC, CASE_4, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_MBTOWC, CASE_4, + "converted wc is different from an expected wc"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_strcoll.c b/test/locale-mbwc/tst_strcoll.c new file mode 100644 index 0000000..4c5a84f --- /dev/null +++ b/test/locale-mbwc/tst_strcoll.c @@ -0,0 +1,87 @@ +/* + STRCOLL: int strcoll (const char *s1, const char *s2) +*/ + +#define TST_FUNCTION strcoll + +#include "tsp_common.c" +#include "dat_strcoll.c" + +int +tst_strcoll (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + const char *s1, *s2; + + TST_DO_TEST (strcoll) + { + TST_HEAD_LOCALE (strcoll, S_STRCOLL); + TST_DO_REC (strcoll) + { + TST_GET_ERRET (strcoll); + s1 = TST_INPUT (strcoll).s1; + s2 = TST_INPUT (strcoll).s2; + + TST_CLEAR_ERRNO; + ret = strcoll (s1, s2); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "strcoll() [ %s : %d ] ret = %d\n", locale, + rec + 1, ret); + fprintf (stdout, " errno = %d\n", + errno_save); + fprintf (stdout, " LC_COLLATE = %s\n", + (setlocale (LC_COLLATE, NULL)) ? setlocale (LC_COLLATE, + NULL) : ""); + } + + TST_IF_RETURN (S_STRCOLL) + { + if (ret_exp == +1) + { + if (ret > 0) + { + Result (C_SUCCESS, S_STRCOLL, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_STRCOLL, CASE_3, + "the return value should be greater than 0," + " but is not ..."); + } + } + else if (ret_exp == -1) + { + if (ret < 0) + { + Result (C_SUCCESS, S_STRCOLL, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_STRCOLL, CASE_3, + "the return value should less than 0, but not ..."); + } + } + else if (ret_exp != 0) + { + if (debug_flg) + { + fprintf (stderr, "*** Warning *** : tst_strcoll : " + "(check the test data); should set ret_flg=1" + " to check a return value"); + } + + warn_count++; + Result (C_INVALID, S_WCSCHR, CASE_3, "(check the test data); " + "should set ret_flg=1 to check a return value"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_strfmon.c b/test/locale-mbwc/tst_strfmon.c new file mode 100644 index 0000000..88e9316 --- /dev/null +++ b/test/locale-mbwc/tst_strfmon.c @@ -0,0 +1,74 @@ +/* + STRFMON: size_t strfmon (char *buf, size_t nbyte, const char *fmt, ...) +*/ + +#define TST_FUNCTION strfmon + +#include "tsp_common.c" +#include "dat_strfmon.c" +#include + +int +tst_strfmon (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char buf[MONSIZE], *mon; + size_t nbt; + char *fmt; + double val; + + TST_DO_TEST (strfmon) + { + TST_HEAD_LOCALE (strfmon, S_STRFMON); + TST_DO_REC (strfmon) + { + TST_GET_ERRET (strfmon); + nbt = TST_INPUT (strfmon).nbytes; + fmt = TST_INPUT (strfmon).fmt; + val = TST_INPUT (strfmon).val; + memset (buf, 0, MONSIZE); + if (nbt > MONSIZE) + { + err_count++; + Result (C_FAILURE, S_STRFMON, CASE_3, "buffer too small in test"); + continue; + } + + TST_CLEAR_ERRNO; + ret = strfmon (buf, nbt, fmt, val, val, val); + TST_SAVE_ERRNO; + + if (debug_flg) /* seems fprintf doesn't update the errno */ + { + fprintf (stdout, "strfmon() [ %s : %d ]\n", locale, rec + 1); + fprintf (stdout, " : err = %d | %s\n", errno_save, + strerror (errno)); + fprintf (stdout, " : ret = %zd; \t fmt = |%s|\n", ret, fmt); + fprintf (stdout, " : buf = |%s|\n\n", buf); + } + + TST_IF_RETURN (S_STRFMON) + { + }; + if (errno != 0 || ret == -1) + { + continue; + } + + mon = TST_EXPECT (strfmon).mon; + + if (!strcmp (buf, mon)) + { + Result (C_SUCCESS, S_STRFMON, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_STRFMON, CASE_3, "the formatted string is " + "different from an expected result"); + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_strxfrm.c b/test/locale-mbwc/tst_strxfrm.c new file mode 100644 index 0000000..fdfeffc --- /dev/null +++ b/test/locale-mbwc/tst_strxfrm.c @@ -0,0 +1,136 @@ +/* + STRXFRM: size_t strxfrm (char *s1, const char *s2, size_t n) +*/ + +#define TST_FUNCTION strxfrm + +#include "tsp_common.c" +#include "dat_strxfrm.c" + + +int +tst_strxfrm (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + const char *org1, *org2; + char frm1[MBSSIZE], frm2[MBSSIZE]; + size_t n1, n2; + int ret_coll, ret_cmp; + + TST_DO_TEST (strxfrm) + { + TST_HEAD_LOCALE (strxfrm, S_STRXFRM); + TST_DO_REC (strxfrm) + { + TST_GET_ERRET (strxfrm); + org1 = TST_INPUT (strxfrm).org1; + org2 = TST_INPUT (strxfrm).org2; + n1 = TST_INPUT (strxfrm).n1; + n2 = TST_INPUT (strxfrm).n2; + + if (n1 < 0 || sizeof (frm1) < n1 || sizeof (frm2) < n2) + { + warn_count++; + Result (C_IGNORED, S_STRXFRM, CASE_9, + "input data n1 or n2 is invalid"); + continue; + } + + /* An errno and a return value are checked + only for 2nd strxfrm() call. + A result of 1st call is used for comparing + those 2 values by using strcmp(). + */ + + /*-- First call --*/ + + TST_CLEAR_ERRNO; + ret = strxfrm (frm1, org1, n1); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "strxfrm() [ %s : %d ] ( 1st call )\n", locale, + rec + 1); + fprintf (stdout, " : err = %d | %s\n", errno_save, + strerror (errno)); + fprintf (stdout, " : ret = %zu\n", ret); + fprintf (stdout, " : org = %s\n", org1); + } + + if (ret >= n1 || errno != 0) + { + warn_count++; + Result (C_INVALID, S_STRXFRM, CASE_8, + "got an error in fist strxfrm() call"); + continue; + } + + /*-- Second call --*/ + + TST_CLEAR_ERRNO; + ret = strxfrm (((n2 == 0) ? NULL : frm2), org2, n2); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, " ..............( 2nd call )\n"); + fprintf (stdout, " : err = %d | %s\n", errno, + strerror (errno)); + fprintf (stdout, " : ret = %zu\n", ret); + fprintf (stdout, " : org = %s\n", org2); + } + + TST_IF_RETURN (S_STRXFRM) + { + }; + + if (n2 == 0 || ret >= n2 || errno != 0) + { +#if 0 + warn_count++; + Result (C_IGNORED, S_STRXFRM, CASE_7, "did not get a result"); +#endif + continue; + } + + /*-- strcoll & strcmp --*/ + + TST_CLEAR_ERRNO; + /* Depends on strcoll() ... not good though ... */ + ret_coll = strcoll (org1, org2); + + if (errno != 0) + { + /* bug * bug may get correct results ... */ + warn_count++; + Result (C_INVALID, S_STRXFRM, CASE_6, + "got an error in strcoll() call"); + continue; + } + + ret_cmp = strcmp (frm1, frm2); + + if ((ret_coll == 0 && ret_cmp == 0) + || (ret_coll < 0 && ret_cmp < 0) || (ret_coll > 0 && ret_cmp > 0)) + { + Result (C_SUCCESS, S_STRXFRM, CASE_3, + MS_PASSED "(depends on strcoll & strcmp)"); + } + else + { + err_count++; + Result (C_FAILURE, S_STRXFRM, CASE_3, + "results from strcoll & strcmp() do not match"); + } + + if (debug_flg) + { + fprintf (stdout, ".......... strcoll = %d <-> %d = strcmp\n", + ret_coll, ret_cmp); + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_swscanf.c b/test/locale-mbwc/tst_swscanf.c new file mode 100644 index 0000000..76445d7 --- /dev/null +++ b/test/locale-mbwc/tst_swscanf.c @@ -0,0 +1,137 @@ +/* + SWSCANF: int swscanf (const wchar_t *ws, const wchar_t *fmt, ...); +*/ + +#define TST_FUNCTION swscanf + +#include "tsp_common.c" +#include "dat_swscanf.c" + +int +tst_swscanf (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t *ws; + wchar_t *fmt; + int val_int1; + unsigned val_int2; + float val_flt; + char val_c; + char val_s[MBSSIZE * 3]; + wchar_t val_S[WCSSIZE * 3], *exp_S; + int i; + + TST_DO_TEST (swscanf) + { + TST_HEAD_LOCALE (swscanf, S_SWSCANF); + TST_DO_REC (swscanf) + { + TST_GET_ERRET (swscanf); + ws = TST_INPUT (swscanf).ws; + fmt = TST_INPUT (swscanf).fmt; + val_int1 = val_int2 = val_flt = val_c = 0; + memset (val_s, 0, sizeof (val_s)); + memset (val_S, 0, sizeof (val_S)); + + TST_CLEAR_ERRNO; + + if (TST_INPUT (swscanf).wch) + { + ret = swscanf (ws, fmt, val_S); + } + else + { + ret = + swscanf (ws, fmt, &val_int1, &val_int2, &val_flt, &val_c, val_s); + } + + TST_SAVE_ERRNO; + + if (debug_flg) + { /* seems fprintf doesn't update errno */ + fprintf (stdout, "swscanf() [ %s : %d ] ret = %d\n", locale, + rec + 1, ret); + fprintf (stdout, " errno = %d\n", + errno_save); + fprintf (stdout, " collate = %s\n", + (setlocale (LC_COLLATE, NULL)) ? setlocale (LC_COLLATE, + NULL) : ""); + + if (TST_INPUT (swscanf).wch) + { + fprintf (stdout, " val_S[ 0 ] = 0x%lx\n", + (unsigned long int) val_S[0]); + } + else + { + fprintf (stdout, " val_int1 = %d\n", + val_int1); + fprintf (stdout, " val_int2 = %d\n", + val_int2); + fprintf (stdout, " val_flt = %f\n", + val_flt); + fprintf (stdout, " val_c = %c\n", + val_c); + fprintf (stdout, " val_s = %s\n", + val_s); + } + } + + TST_IF_RETURN (S_SWSCANF) + { + }; + + if (errno == 0 && TST_INPUT (swscanf).wch) + { + for (exp_S = TST_EXPECT (swscanf).val_S, i = 0; i < WCSSIZE * 3; + i++) + { + if (val_S[i] == L'\0' || exp_S[i] == L'\0') + { + if (val_S[i] != exp_S[i] && TST_INPUT (swscanf).wch == 'C') + { + err_count++; + Result (C_FAILURE, S_SWSCANF, CASE_4, + "the converted wide-char string is different" + " from an expected value."); + } + break; + } + + if (val_S[i] != exp_S[i]) + { + err_count++; + Result (C_FAILURE, S_SWSCANF, CASE_4, + "the converted wide-char string is different from" + " an expected value."); + break; + } + else + { + Result (C_SUCCESS, S_SWSCANF, CASE_4, MS_PASSED); + } + } + } + + if (errno == 0 && !TST_INPUT (swscanf).wch) + { + if (val_int1 != TST_EXPECT (swscanf).val_int || + val_int2 != TST_EXPECT (swscanf).val_uns || + val_flt != TST_EXPECT (swscanf).val_flt || + val_c != TST_EXPECT (swscanf).val_c || + strcmp (val_s, TST_EXPECT (swscanf).val_s)) + { + err_count++; + Result (C_FAILURE, S_SWSCANF, CASE_3, + "the converted values are different from expected values."); + } + else + { + Result (C_SUCCESS, S_SWSCANF, CASE_3, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_towctrans.c b/test/locale-mbwc/tst_towctrans.c new file mode 100644 index 0000000..1d874dc --- /dev/null +++ b/test/locale-mbwc/tst_towctrans.c @@ -0,0 +1,82 @@ +/* + TOWCTRANS: wint_t towctrans (wint_t wc, wctrans_t desc); +*/ + +#define TST_FUNCTION towctrans + +#include "tsp_common.c" +#include "dat_towctrans.c" + + +int +tst_towctrans (FILE *fp, int debug_flg) +{ + TST_DECL_VARS (wint_t); + wint_t wc; + const char *ts; +#if SHOJI_IS_RIGHT + int dummy=0; +#endif + wctrans_t wto; + + TST_DO_TEST (towctrans) + { + TST_HEAD_LOCALE (towctrans, S_TOWCTRANS); + TST_DO_REC (towctrans) + { + TST_GET_ERRET (towctrans); + wc = TST_INPUT (towctrans).wc; + ts = TST_INPUT (towctrans).ts; + +#if SHOJI_IS_RIGHT + if ((wto = wctrans (ts)) == (wctrans_t) 0) + { +#if 0 + result (fp, C_IGNORED, S_TOWCTRANS, locale, rec+1, seq_num+1, 3, + "Skip this data because the wctrans object is not invalid."); + warn_count++; + continue; +#else + wto = &dummy; /* not good ... */ +#endif + if (debug_flg) + { + fprintf (stdout, "towctrans() ------ wctrans() returnd 0.\n"); + } + } +#else + wto = wctrans (ts); +#endif + + TST_CLEAR_ERRNO; + ret = towctrans (wc, wto); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "towctrans() [ %s : %d ] ret = 0x%x\n", + locale, rec+1, ret); + fprintf (stdout, " errno = %d\n", + errno_save); + } + + TST_IF_RETURN (S_TOWCTRANS) + { + if (ret != 0) + { + result (fp, C_SUCCESS, S_TOWCTRANS, locale, rec+1, + seq_num+1, 3, MS_PASSED); + } + else + { + err_count++; + result (fp, C_FAILURE, S_TOWCTRANS, locale, rec+1, + seq_num+1, 3, + "the function returned 0, but should be non-zero"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_towlower.c b/test/locale-mbwc/tst_towlower.c new file mode 100644 index 0000000..7719b0d --- /dev/null +++ b/test/locale-mbwc/tst_towlower.c @@ -0,0 +1,11 @@ +/* + TOWLOWER: int towlower (wint_t wc); +*/ + +#define TST_FUNCTION towlower + +#include "tsp_common.c" +#include "dat_towlower.c" + + +TST_FUNC_TOW (LOWER, lower); diff --git a/test/locale-mbwc/tst_towupper.c b/test/locale-mbwc/tst_towupper.c new file mode 100644 index 0000000..a077d27 --- /dev/null +++ b/test/locale-mbwc/tst_towupper.c @@ -0,0 +1,10 @@ +/* + TOWUPPER: int towupper (wint_t wc); +*/ + +#define TST_FUNCTION towupper + +#include "tsp_common.c" +#include "dat_towupper.c" + +TST_FUNC_TOW (UPPER, upper); diff --git a/test/locale-mbwc/tst_types.h b/test/locale-mbwc/tst_types.h new file mode 100644 index 0000000..3d18279 --- /dev/null +++ b/test/locale-mbwc/tst_types.h @@ -0,0 +1,729 @@ +/* + * TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY + * + * FILE: tst_types.h + * + * Definitions of data types for each test function + */ + + +#ifndef TST_TYPES_H +#define TST_TYPES_H + +#include +#include +#include +#include "tst_funcs.h" +#include "tgn_funcdef.h" + +#define MBSSIZE 24 +#define WCSSIZE 12 +#define MONFMTSIZE 16 +#define MONSIZE 64 +#define USE_MBCURMAX 99 /* well, but ... */ +#define TST_DBL_EPS 2.22153e-16 +#define WCSTOK_SEQNUM 3 +#define MBLEN_SEQNUM 3 +#define MBTOWC_SEQNUM 3 +#define MBSTOWCS_SEQNUM 3 +#define WCTOMB_SEQNUM 3 +#define WCSTOMBS_SEQNUM 3 +#define MBRLEN_SEQNUM 3 +#define MBRTOWC_SEQNUM 3 +#define MBSRTOWCS_SEQNUM 3 +#define WCRTOMB_SEQNUM 3 +#define WCSRTOMBS_SEQNUM 3 + +/* Maximum numbers of test in one of the _loc arrays. */ +#define MAX_LOC_TEST 300 + + +/*----------------------------------------------------------------------*/ +/* FUNCTION */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + char *func_str; + int func_id; +} +TST_FID; + +typedef struct +{ + int func_id; + const char *locale; +} +TST_HEAD; + +typedef struct +{ + TST_HEAD *head; +} +TST_FUNCS; + + +/*----------------------------------------------------------------------*/ +/* ISW*: int isw* (wchar_t wc) */ +/*----------------------------------------------------------------------*/ + +TST_ISW_STRUCT (ALNUM, alnum); +TST_ISW_STRUCT (ALPHA, alpha); +TST_ISW_STRUCT (CNTRL, cntrl); +TST_ISW_STRUCT (DIGIT, digit); +TST_ISW_STRUCT (GRAPH, graph); +TST_ISW_STRUCT (LOWER, lower); +TST_ISW_STRUCT (PRINT, print); +TST_ISW_STRUCT (PUNCT, punct); +TST_ISW_STRUCT (SPACE, space); +TST_ISW_STRUCT (UPPER, upper); +TST_ISW_STRUCT (XDIGIT, xdigit); + +typedef struct +{ + wint_t wc; + const char *ts; +} +TIN_ISWCTYPE_REC; + +typedef +TEX_ERRET_REC (int) + TEX_ISWCTYPE_REC; +TMD_RECHEAD (ISWCTYPE); + + +/*----------------------------------------------------------------------*/ +/* MBLEN: int mblen (const char *s, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + char s_flg; + char s[MBSSIZE]; + size_t n; +} +TIN_MBLEN_REC; + +typedef TEX_ERRET_REC (int) TEX_MBLEN_REC; +TMD_RECHEAD (MBLEN); + + +/*----------------------------------------------------------------------*/ +/* MBRLEN: size_t mbrlen (const char *s, size_t n, mbstate_t *ps) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + struct + { + int s_flg; + char s[MBSSIZE]; + size_t n; + int t_flg; + int t_init; + } + seq[WCSTOK_SEQNUM]; +} +TIN_MBRLEN_REC; + +typedef TEX_ERRET_REC_SEQ (size_t, MBRLEN_SEQNUM) TEX_MBRLEN_REC; +TMD_RECHEAD (MBRLEN); + + +/*----------------------------------------------------------------------*/ +/* MBRTOWC: size_t mbrtowc (wchar_t *pwc, const char *s, size_t n, */ +/* mbstate_t *ps) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + struct + { + int w_flg; + int s_flg; + char s[MBSSIZE]; + size_t n; + int t_flg; + int t_init; + } + seq[MBRTOWC_SEQNUM]; +} +TIN_MBRTOWC_REC; + +typedef struct +{ + struct + { + TMD_ERRET (size_t); + wchar_t wc; + } + seq[MBRTOWC_SEQNUM]; +} +TEX_MBRTOWC_REC; + +TMD_RECHEAD (MBRTOWC); + + +/*----------------------------------------------------------------------*/ +/* MBSRTOWCS: size_t mbsrtowcs (wchar_t *ws, const char **s, size_t n, */ +/* mbstate_t *ps ) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + struct + { + int w_flg; + char s[MBSSIZE]; + size_t n; + int t_flg; + int t_init; + } + seq[MBSRTOWCS_SEQNUM]; +} +TIN_MBSRTOWCS_REC; + +typedef struct +{ + struct + { + TMD_ERRET (size_t); + wchar_t ws[WCSSIZE]; + } + seq[MBSRTOWCS_SEQNUM]; +} +TEX_MBSRTOWCS_REC; + +TMD_RECHEAD (MBSRTOWCS); + + +/*----------------------------------------------------------------------*/ +/* MBSTOWCS: size_t mbstowcs (wchar_t *ws, const char *s, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + struct + { + int w_flg; + int s_flg; + const char *s; + size_t n; + } + seq[MBSTOWCS_SEQNUM]; +} +TIN_MBSTOWCS_REC; + +typedef TEX_MBSRTOWCS_REC TEX_MBSTOWCS_REC; +/* MBSRTOWCS_SEQNUM == MBSTOWCS_SEQNUM */ +TMD_RECHEAD (MBSTOWCS); + + +/*----------------------------------------------------------------------*/ +/* MBTOWC: int mbtowc (wchar_t *wc, const char *s, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_MBSTOWCS_REC TIN_MBTOWC_REC; +/* MBTOWC_SEQNUM == MBSTOWCS_SEQNUM */ + +typedef struct +{ + struct + { + TMD_ERRET (int); + wchar_t wc; + } + seq[MBTOWC_SEQNUM]; +} +TEX_MBTOWC_REC; + +TMD_RECHEAD (MBTOWC); + + +/*----------------------------------------------------------------------*/ +/* STRCOLL: int strcoll (const char *s1, const char *s2) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + char s1[MBSSIZE]; + char s2[MBSSIZE]; +} +TIN_STRCOLL_REC; + +typedef TEX_ERRET_REC (int) TEX_STRCOLL_REC; +TMD_RECHEAD (STRCOLL); + + +/*----------------------------------------------------------------------*/ +/* STRFMON: size_t strfmon (char *buf, size_t nbytes, */ +/* const char *fmt, ... ) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + int nbytes; + char fmt[MONFMTSIZE]; + double val; +} +TIN_STRFMON_REC; + +typedef struct +{ + TMD_ERRET (size_t); + char mon[MONSIZE]; +} +TEX_STRFMON_REC; + +TMD_RECHEAD (STRFMON); + + +/*----------------------------------------------------------------------*/ +/* STRXFRM: size_t strxfrm (char *s1, const char *s2, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + char org1[MBSSIZE]; + char org2[MBSSIZE]; + size_t n1, n2; +} +TIN_STRXFRM_REC; + +typedef TEX_ERRET_REC (size_t) TEX_STRXFRM_REC; /* only for org2[] */ +TMD_RECHEAD (STRXFRM); + + +/*----------------------------------------------------------------------*/ +/* SWSCANF: int swscanf (const wchar_t *ws, const wchar_t *fmt, ...) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws[WCSSIZE * 3]; + wchar_t fmt[WCSSIZE * 3]; + int wch; +} +TIN_SWSCANF_REC; + +typedef struct +{ + TMD_ERRET (int); + int val_int; /* %d */ + unsigned val_uns; /* %u */ + float val_flt; /* %f */ + int val_c; /* %c */ + char val_s[MBSSIZE * 2]; /* %s */ + wchar_t val_S[WCSSIZE * 2]; /* %lc, %ls, %C, %S */ +} +TEX_SWSCANF_REC; + +TMD_RECHEAD (SWSCANF); + + +/*----------------------------------------------------------------------*/ +/* TOWCTRANS: wint_t towctrans (wint_t wc, wctrans_t desc) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_ISWCTYPE_REC TIN_TOWCTRANS_REC; +typedef TEX_ERRET_REC (wint_t) TEX_TOWCTRANS_REC; +TMD_RECHEAD (TOWCTRANS); + + +/*----------------------------------------------------------------------*/ +/* TOW*ER: wint_t tow*er (wint_t wc) */ +/*----------------------------------------------------------------------*/ + +TST_TOW_STRUCT (LOWER, lower); +TST_TOW_STRUCT (UPPER, upper); + + +/*----------------------------------------------------------------------*/ +/* WCRTOMB: wchar_t wcrtomb (char *s, wchar_t wc, mbstate_t *ps) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + int s_flg; + wchar_t wc; + int t_flg; + int t_init; +} +TIN_WCRTOMB_REC; + +typedef struct +{ + TMD_ERRET (wchar_t); + char s[MBSSIZE]; +} +TEX_WCRTOMB_REC; + +TMD_RECHEAD (WCRTOMB); + + +/*----------------------------------------------------------------------*/ +/* WCSCAT: wchar_t *wcscat (wchar_t *ws1, wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws1[WCSSIZE]; + wchar_t ws2[WCSSIZE]; +} +TIN_WCSCAT_REC; + +typedef struct +{ + TMD_ERRET (wchar_t *); + wchar_t ws[WCSSIZE]; +} +TEX_WCSCAT_REC; + +TMD_RECHEAD (WCSCAT); + + +/*----------------------------------------------------------------------*/ +/* WCSCHR: wchar_t *wcschr (wchar_t *ws, wchar_t wc); */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws[WCSSIZE]; + wchar_t wc; +} +TIN_WCSCHR_REC; + +typedef TEX_ERRET_REC (wchar_t *) TEX_WCSCHR_REC; +TMD_RECHEAD (WCSCHR); + + +/*----------------------------------------------------------------------*/ +/* WCSCMP: int wcscmp (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCAT_REC TIN_WCSCMP_REC; +typedef TEX_ERRET_REC (int) TEX_WCSCMP_REC; +TMD_RECHEAD (WCSCMP); + + +/*----------------------------------------------------------------------*/ +/* WCSCOLL: int wcscoll (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCMP_REC TIN_WCSCOLL_REC; +typedef struct +{ + TMD_ERRET (int); + int cmp_flg; +} +TEX_WCSCOLL_REC; +TMD_RECHEAD (WCSCOLL); + + +/*----------------------------------------------------------------------*/ +/* WCSCPY: wchar_t *wcscpy (wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws[WCSSIZE]; /* ws2: original string */ +} +TIN_WCSCPY_REC; + +typedef TEX_WCSCAT_REC TEX_WCSCPY_REC; +TMD_RECHEAD (WCSCPY); + + +/*----------------------------------------------------------------------*/ +/* WCSCSPN: size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCAT_REC TIN_WCSCSPN_REC; +typedef TEX_ERRET_REC (size_t) TEX_WCSCSPN_REC; +TMD_RECHEAD (WCSCSPN); + + +/*----------------------------------------------------------------------*/ +/* WCSLEN: size_t wcslen (const wchar_t *ws) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCPY_REC TIN_WCSLEN_REC; +typedef TEX_ERRET_REC (size_t) TEX_WCSLEN_REC; +TMD_RECHEAD (WCSLEN); + + +/*----------------------------------------------------------------------*/ +/* WCSNCAT: wchar_t *wcsncat (wchar_t *ws1, const wchar_t *ws2, */ +/* size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws1[WCSSIZE]; + wchar_t ws2[WCSSIZE]; + size_t n; +} +TIN_WCSNCAT_REC; + +typedef TEX_WCSCAT_REC TEX_WCSNCAT_REC; +TMD_RECHEAD (WCSNCAT); + + +/*----------------------------------------------------------------------*/ +/* WCSNCMP: int *wcsncmp (const wchar_t *ws1, const wchar_t *ws2, */ +/* size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSNCAT_REC TIN_WCSNCMP_REC; +typedef TEX_ERRET_REC (int) TEX_WCSNCMP_REC; +TMD_RECHEAD (WCSNCMP); + + +/*----------------------------------------------------------------------*/ +/* WCSNCPY: wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2, */ +/* size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t ws[WCSSIZE]; /* ws2: original string */ + size_t n; +} +TIN_WCSNCPY_REC; + +typedef TEX_WCSCPY_REC TEX_WCSNCPY_REC; +TMD_RECHEAD (WCSNCPY); + + +/*----------------------------------------------------------------------*/ +/* WCSPBRK: wchar_t *wcspbrk (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCSPN_REC TIN_WCSPBRK_REC; + +typedef struct +{ + TMD_ERRET (wchar_t *); + wchar_t wc; +} +TEX_WCSPBRK_REC; + +TMD_RECHEAD (WCSPBRK); + + +/*----------------------------------------------------------------------*/ +/* WCSRTOMBS: size_t wcsrtombs (char *s, const wchar_t **ws, size_t n, */ +/* mbstate_t *ps) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + int s_flg; + int w_flg; /* don't need this */ + wchar_t ws[WCSSIZE]; + size_t n; + int t_flg; + int t_init; +} +TIN_WCSRTOMBS_REC; + +typedef struct +{ + TMD_ERRET (size_t); + char s[MBSSIZE]; +} +TEX_WCSRTOMBS_REC; + +TMD_RECHEAD (WCSRTOMBS); + + +/*----------------------------------------------------------------------*/ +/* WCSSPN: size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCSPN_REC TIN_WCSSPN_REC; +typedef TEX_WCSCSPN_REC TEX_WCSSPN_REC; +TMD_RECHEAD (WCSSPN); + + +/*----------------------------------------------------------------------*/ +/* WCSSTR: wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSCSPN_REC TIN_WCSSTR_REC; +typedef TEX_ERRET_REC (wchar_t *) TEX_WCSSTR_REC; +TMD_RECHEAD (WCSSTR); + + +/*----------------------------------------------------------------------*/ +/* WCSTOD: double wcstod (const wchar_t *np, wchar_t **endp) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t np[WCSSIZE]; +} +TIN_WCSTOD_REC; + +typedef struct +{ + TMD_ERRET (double); + double val; + wchar_t fwc; +} +TEX_WCSTOD_REC; + +TMD_RECHEAD (WCSTOD); + + +/*----------------------------------------------------------------------*/ +/* WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm, */ +/* wchar_t **pt) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + struct + { + int w_flg; + wchar_t ws[WCSSIZE]; + wchar_t dt[WCSSIZE]; /* delimiter */ + } + seq[WCSTOK_SEQNUM]; +} +TIN_WCSTOK_REC; + +typedef struct +{ + struct + { + TMD_ERRET (wchar_t *); + wchar_t ws[WCSSIZE]; + } + seq[WCSTOK_SEQNUM]; +} +TEX_WCSTOK_REC; + +TMD_RECHEAD (WCSTOK); + + +/*----------------------------------------------------------------------*/ +/* WCSTOMBS: size_t wcstombs (char s, const wchar_t *ws, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + int s_flg; + int w_flg; /* currently we don't need it. */ + wchar_t ws[WCSSIZE]; + size_t n; +} +TIN_WCSTOMBS_REC; + +typedef struct +{ + TMD_ERRET (size_t); + char s[MBSSIZE]; +} +TEX_WCSTOMBS_REC; + +TMD_RECHEAD (WCSTOMBS); + + +/*----------------------------------------------------------------------*/ +/* WCSWIDTH: int wcswidth (const wchar_t *ws, size_t n) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCSNCPY_REC TIN_WCSWIDTH_REC; +typedef TEX_ERRET_REC (int) TEX_WCSWIDTH_REC; +TMD_RECHEAD (WCSWIDTH); + + +/*----------------------------------------------------------------------*/ +/* WCSXFRM: size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t n)*/ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t org1[WCSSIZE]; + wchar_t org2[WCSSIZE]; + int n1, n2; +} +TIN_WCSXFRM_REC; + +typedef TEX_ERRET_REC (size_t) TEX_WCSXFRM_REC; /* only for org2[] */ +TMD_RECHEAD (WCSXFRM); + + +/*----------------------------------------------------------------------*/ +/* WCTOB: int wctob (wint_t wc) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wint_t wc; +} +TIN_WCTOB_REC; + +typedef TEX_ERRET_REC (int) TEX_WCTOB_REC; +TMD_RECHEAD (WCTOB); + + +/*----------------------------------------------------------------------*/ +/* WCTOMB: int wctomb (char *s, wchar_t wc) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + int s_flg; + wchar_t wc; +} +TIN_WCTOMB_REC; + +typedef struct +{ + TMD_ERRET (int); + char s[MBSSIZE]; +} +TEX_WCTOMB_REC; + +TMD_RECHEAD (WCTOMB); + + +/*----------------------------------------------------------------------*/ +/* WCTRANS: wctrans_t wctrans (const char *charclass) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + char class[MBSSIZE]; +} +TIN_WCTRANS_REC; + +typedef TEX_ERRET_REC (wctrans_t) TEX_WCTRANS_REC; +TMD_RECHEAD (WCTRANS); + + +/*----------------------------------------------------------------------*/ +/* WCTYPE: wctype_t wctype (const char *class) */ +/*----------------------------------------------------------------------*/ + +typedef TIN_WCTRANS_REC TIN_WCTYPE_REC; +typedef TEX_ERRET_REC (wctype_t) TEX_WCTYPE_REC; +TMD_RECHEAD (WCTYPE); + + +/*----------------------------------------------------------------------*/ +/* WCWIDTH: int wcwidth (wchar_t wc) */ +/*----------------------------------------------------------------------*/ + +typedef struct +{ + wchar_t wc; +} +TIN_WCWIDTH_REC; + +typedef TEX_ERRET_REC (int) TEX_WCWIDTH_REC; +TMD_RECHEAD (WCWIDTH); + +#endif /* TST_TYPES_H */ diff --git a/test/locale-mbwc/tst_wcrtomb.c b/test/locale-mbwc/tst_wcrtomb.c new file mode 100644 index 0000000..0029a49 --- /dev/null +++ b/test/locale-mbwc/tst_wcrtomb.c @@ -0,0 +1,79 @@ +/* + WCRTOMB: wchar_t wcrtomb (char *s, wchar_t wc, mbstate_t *ps) +*/ + +#define TST_FUNCTION wcrtomb + +#include "tsp_common.c" +#include "dat_wcrtomb.c" + + +int +tst_wcrtomb (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t); + wchar_t wc; + char s[MBSSIZE], *s_in, *s_ex; + char t_flg, t_ini; + static mbstate_t t = { 0 }; + mbstate_t *pt; + int err, i; + + TST_DO_TEST (wcrtomb) + { + TST_HEAD_LOCALE (wcrtomb, S_WCRTOMB); + TST_DO_REC (wcrtomb) + { + TST_GET_ERRET (wcrtomb); + s_in = ((TST_INPUT (wcrtomb).s_flg) == 0) ? (char *) NULL : s; + wc = TST_INPUT (wcrtomb).wc; + t_flg = TST_INPUT (wcrtomb).t_flg; + t_ini = TST_INPUT (wcrtomb).t_init; + pt = (t_flg == 0) ? NULL : &t; + + if (t_ini != 0) + { + memset (&t, 0, sizeof (t)); + } + + TST_CLEAR_ERRNO; + ret = wcrtomb (s_in, wc, pt); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "wcrtomb() [ %s : %d ] ret = %lu\n", locale, + rec + 1, (unsigned long int) ret); + fprintf (stdout, " errno = %d\n", errno_save); + } + + TST_IF_RETURN (S_WCRTOMB) + { + }; + + s_ex = TST_EXPECT (wcrtomb).s; + + if (s_in) + { + for (i = 0, err = 0; *(s_ex + i) != 0 && i < MBSSIZE; i++) + { + if (s_in[i] != s_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCRTOMB, CASE_4, + "copied string is different from an " + "expected string"); + break; + } + } + if (!err) + { + Result (C_SUCCESS, S_WCRTOMB, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcscat.c b/test/locale-mbwc/tst_wcscat.c new file mode 100644 index 0000000..3dc9809 --- /dev/null +++ b/test/locale-mbwc/tst_wcscat.c @@ -0,0 +1,78 @@ +/* + WCSCAT: wchar_t *wcscat (wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcscat + +#include "tsp_common.c" +#include "dat_wcscat.c" + +int +tst_wcscat (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t *ws1, *ws2, *ws_ex; + int i, err; + + TST_DO_TEST (wcscat) + { + TST_HEAD_LOCALE (wcscat, S_WCSCAT); + TST_DO_REC (wcscat) + { + TST_GET_ERRET (wcscat); + ws1 = TST_INPUT (wcscat).ws1; /* external value: size WCSSIZE */ + ws2 = TST_INPUT (wcscat).ws2; + + TST_CLEAR_ERRNO; + ret = wcscat (ws1, ws2); + TST_SAVE_ERRNO; + + TST_IF_RETURN (S_WCSCAT) + { + if (ret == ws1) + { + Result (C_SUCCESS, S_WCSCAT, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSCAT, CASE_3, + "the return address may not be correct"); + } + } + + /* function specific test cases here */ + + if (ret == ws1) + { + ws_ex = TST_EXPECT (wcscat).ws; + for (err = 0, i = 0; + (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++) + { + if (debug_flg) + { + fprintf (stdout, "tst_wcscat() : ws1[%d] = 0x%lx\n", i, + (unsigned long int) ws1[i]); + } + + if (ws1[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSCAT, CASE_4, + "concatinated string is different from an " + "expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSCAT, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcschr.c b/test/locale-mbwc/tst_wcschr.c new file mode 100644 index 0000000..b57a05a --- /dev/null +++ b/test/locale-mbwc/tst_wcschr.c @@ -0,0 +1,70 @@ +/* + WCSCHR: wchar_t *wcschr (wchar_t *ws, wchar_t wc); +*/ + +#define TST_FUNCTION wcschr + +#include "tsp_common.c" +#include "dat_wcschr.c" + +int +tst_wcschr (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t *ws, wc; + + TST_DO_TEST (wcschr) + { + TST_HEAD_LOCALE (wcschr, S_WCSCHR); + TST_DO_REC (wcschr) + { + TST_GET_ERRET (wcschr); + ws = TST_INPUT (wcschr).ws; /* external value: size WCSSIZE */ + wc = TST_INPUT (wcschr).wc; + ret = wcschr (ws, wc); + + if (debug_flg) + { + if (ret) + { + fprintf (stderr, "wcschr: ret = 0x%lx\n", + (unsigned long int) *ret); + } + else + { + fprintf (stderr, "wcschr: ret = NULL pointer\n"); + } + } + + TST_IF_RETURN (S_WCSCHR) + { + if (ret == NULL) + { + if (debug_flg) + { + fprintf (stderr, "*** Warning *** tst_wcschr: " + "set ret_flg=1 to check NULL return value\n"); + } + + warn_count++; + Result (C_INVALID, S_WCSCHR, CASE_3, "(check the test data) " + "set ret_flg=1 to check NULL return value"); + continue; + } + + if (*ret == wc) + { + Result (C_SUCCESS, S_WCSCHR, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSCHR, CASE_3, + "the returned address of the string seems to be wrong"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcscmp.c b/test/locale-mbwc/tst_wcscmp.c new file mode 100644 index 0000000..594682c --- /dev/null +++ b/test/locale-mbwc/tst_wcscmp.c @@ -0,0 +1,40 @@ +/* + WCSCMP: int wcscmp (const wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcscmp + +#include "tsp_common.c" +#include "dat_wcscmp.c" + + +int +tst_wcscmp (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t *ws1, *ws2; + + TST_DO_TEST (wcscmp) + { + TST_HEAD_LOCALE (wcscmp, S_WCSCMP); + TST_DO_REC (wcscmp) + { + TST_GET_ERRET (wcscmp); + ws1 = TST_INPUT (wcscmp).ws1; + ws2 = TST_INPUT (wcscmp).ws2; + ret = wcscmp (ws1, ws2); + ret = (ret > 0 ? 1 : ret < 0 ? -1 : 0); + + if (debug_flg) + { + fprintf (stderr, "tst_wcscmp: ret = %d\n", ret); + } + + TST_IF_RETURN (S_WCSCMP) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcscoll.c b/test/locale-mbwc/tst_wcscoll.c new file mode 100644 index 0000000..929f80d --- /dev/null +++ b/test/locale-mbwc/tst_wcscoll.c @@ -0,0 +1,76 @@ +/* + WCSCOLL: int wcscoll (const wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcscoll + +#include "tsp_common.c" +#include "dat_wcscoll.c" + +int +tst_wcscoll (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t *ws1, *ws2; + int cmp; + + TST_DO_TEST (wcscoll) + { + TST_HEAD_LOCALE (wcscoll, S_WCSCOLL); + TST_DO_REC (wcscoll) + { + TST_GET_ERRET (wcscoll); + ws1 = TST_INPUT (wcscoll).ws1; /* external value: size WCSSIZE */ + ws2 = TST_INPUT (wcscoll).ws2; + + TST_CLEAR_ERRNO; + ret = wcscoll (ws1, ws2); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, "tst_wcscoll: ret = %d\n", ret); + } + + cmp = TST_EXPECT (wcscoll).cmp_flg; + TST_IF_RETURN (S_WCSCOLL) + { + if (cmp != 0) + { + if ((cmp == 1 && ret > 0) || (cmp == -1 && ret < 0)) + { + Result (C_SUCCESS, S_WCSCOLL, CASE_3, MS_PASSED); + } + else + { + err_count++; + if (cmp == 1) + { + if (ret == 0) + Result (C_FAILURE, S_WCSCOLL, CASE_3, + "the return value should be positive" + " but it's zero."); + else + Result (C_FAILURE, S_WCSCOLL, CASE_3, + "the return value should be positive" + " but it's negative."); + } + else + { + if (ret == 0) + Result (C_FAILURE, S_WCSCOLL, CASE_3, + "the return value should be negative" + " but it's zero."); + else + Result (C_FAILURE, S_WCSCOLL, CASE_3, + "the return value should be negative" + " but it's positive."); + } + } + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcscpy.c b/test/locale-mbwc/tst_wcscpy.c new file mode 100644 index 0000000..d5705a5 --- /dev/null +++ b/test/locale-mbwc/tst_wcscpy.c @@ -0,0 +1,85 @@ +/*-------------------------------------------------------------------------------------*/ +/* WCSCPY: wchar_t *wcscpy( wchar_t *ws1, const wchar_t *ws2 ) */ +/*-------------------------------------------------------------------------------------*/ +#define TST_FUNCTION wcscpy + +#include "tsp_common.c" +#include "dat_wcscpy.c" + +int +tst_wcscpy (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t ws1[WCSSIZE], *ws2, *ws_ex; + int err, i; + + TST_DO_TEST (wcscpy) + { + TST_HEAD_LOCALE (wcscpy, S_WCSCPY); + TST_DO_REC (wcscpy) + { + TST_GET_ERRET (wcscpy); + ws2 = TST_INPUT (wcscpy).ws; /* external value: size WCSSIZE */ + ret = wcscpy (ws1, ws2); + + TST_IF_RETURN (S_WCSCPY) + { + if (ret == ws1) + { + Result (C_SUCCESS, S_WCSCPY, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSCPY, CASE_3, + "the return address may not be correct"); + } + } + + if (ret == ws1) + { + ws_ex = TST_EXPECT (wcscpy).ws; + + for (err = 0, i = 0; + (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++) + { + if (debug_flg) + { + fprintf (stderr, + "ws1[ %d ] = 0x%lx <-> wx_ex[ %d ] = 0x%lx\n", i, + (unsigned long int) ws1[i], i, + (unsigned long int) ws_ex[i]); + } + + if (ws1[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSCPY, CASE_4, + "copied string is different from an" + " expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSCPY, CASE_4, MS_PASSED); + } + + if (ws1[i] == 0L) + { + Result (C_SUCCESS, S_WCSCPY, CASE_5, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSCPY, CASE_5, + "copied string is not null-terminated"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcscspn.c b/test/locale-mbwc/tst_wcscspn.c new file mode 100644 index 0000000..e1c8892 --- /dev/null +++ b/test/locale-mbwc/tst_wcscspn.c @@ -0,0 +1,38 @@ +/* + WCSCSPN: size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcscspn + +#include "tsp_common.c" +#include "dat_wcscspn.c" + +int +tst_wcscspn (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + wchar_t *ws1, *ws2; + + TST_DO_TEST (wcscspn) + { + TST_HEAD_LOCALE (wcscspn, S_WCSCSPN); + TST_DO_REC (wcscspn) + { + TST_GET_ERRET (wcscspn); + ws1 = TST_INPUT (wcscspn).ws1; + ws2 = TST_INPUT (wcscspn).ws2; /* external value: size WCSSIZE */ + ret = wcscspn (ws1, ws2); + + if (debug_flg) + { + fprintf (stderr, "wcscspn: ret = %zu\n", ret); + } + + TST_IF_RETURN (S_WCSCSPN) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcslen.c b/test/locale-mbwc/tst_wcslen.c new file mode 100644 index 0000000..d0ffa5a --- /dev/null +++ b/test/locale-mbwc/tst_wcslen.c @@ -0,0 +1,31 @@ +/* + WCSLEN: size_t wcslen (const wchar_t *ws); +*/ + +#define TST_FUNCTION wcslen + +#include "tsp_common.c" +#include "dat_wcslen.c" + +int +tst_wcslen (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + wchar_t *ws; + + TST_DO_TEST (wcslen) + { + TST_HEAD_LOCALE (wcslen, S_WCSLEN); + TST_DO_REC (wcslen) + { + TST_GET_ERRET (wcslen); + ws = TST_INPUT (wcslen).ws; + ret = wcslen (ws); + TST_IF_RETURN (S_WCSLEN) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsncat.c b/test/locale-mbwc/tst_wcsncat.c new file mode 100644 index 0000000..a2f6ba0 --- /dev/null +++ b/test/locale-mbwc/tst_wcsncat.c @@ -0,0 +1,75 @@ +/* + WCSNCAT: wchar_t *wcsncat (wchar_t *ws1, const wchar_t *ws2, size_t n); +*/ + +#define TST_FUNCTION wcsncat + +#include "tsp_common.c" +#include "dat_wcsncat.c" + +int +tst_wcsncat (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t *ws1, *ws2, *ws_ex; + int n, i, err; + + TST_DO_TEST (wcsncat) + { + TST_HEAD_LOCALE (wcsncat, S_WCSNCAT); + TST_DO_REC (wcsncat) + { + TST_GET_ERRET (wcsncat); + ws1 = TST_INPUT (wcsncat).ws1; /* external value: size WCSSIZE */ + ws2 = TST_INPUT (wcsncat).ws2; + n = TST_INPUT (wcsncat).n; + ret = wcsncat (ws1, ws2, n); + + TST_IF_RETURN (S_WCSNCAT) + { + if (ret == ws1) + { + Result (C_SUCCESS, S_WCSNCAT, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSNCAT, CASE_3, + "the return address may not be correct"); + } + } + + if (ret == ws1) + { + ws_ex = TST_EXPECT (wcsncat).ws; + + for (err = 0, i = 0; + (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++) + { + if (debug_flg) + { + fprintf (stderr, "ws1[%d] = 0x%lx\n", i, + (unsigned long int) ws1[i]); + } + + if (ws1[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSNCAT, CASE_4, + "the concatinated string has " + "different value from an expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSNCAT, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsncmp.c b/test/locale-mbwc/tst_wcsncmp.c new file mode 100644 index 0000000..d046ecd --- /dev/null +++ b/test/locale-mbwc/tst_wcsncmp.c @@ -0,0 +1,40 @@ +/*-------------------------------------------------------------------------------------*/ +/* WCSNCMP: int wcsncmp( const wchar_t *ws1, const wchar_t *ws2, size_t n ) */ +/*-------------------------------------------------------------------------------------*/ + +#define TST_FUNCTION wcsncmp + +#include "tsp_common.c" +#include "dat_wcsncmp.c" + +int +tst_wcsncmp (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t *ws1, *ws2; + size_t n; + + TST_DO_TEST (wcsncmp) + { + TST_HEAD_LOCALE (wcsncmp, S_WCSNCMP); + TST_DO_REC (wcsncmp) + { + TST_GET_ERRET (wcsncmp); + ws1 = TST_INPUT (wcsncmp).ws1; /* external value: size WCSSIZE */ + ws2 = TST_INPUT (wcsncmp).ws2; + n = TST_INPUT (wcsncmp).n; + ret = wcsncmp (ws1, ws2, n); + + if (debug_flg) + { + fprintf (stderr, "tst_wcsncmp: ret = %d, 0x%x\n", ret, ret); + } + + TST_IF_RETURN (S_WCSNCMP) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsncpy.c b/test/locale-mbwc/tst_wcsncpy.c new file mode 100644 index 0000000..814bbc0 --- /dev/null +++ b/test/locale-mbwc/tst_wcsncpy.c @@ -0,0 +1,93 @@ +/* + WCSNCPY: wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2, size_t n); +*/ + +#define TST_FUNCTION wcsncpy + +#include "tsp_common.c" +#include "dat_wcsncpy.c" + +#define WCSNUM_NCPY 7 + +int +tst_wcsncpy (FILE *fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t ws1[WCSSIZE] = + { 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x0000 }; + wchar_t *ws2, *ws_ex; + int err, i; + size_t n; + + TST_DO_TEST (wcsncpy) + { + TST_HEAD_LOCALE (wcsncpy, S_WCSNCPY); + TST_DO_REC (wcsncpy) + { + TST_GET_ERRET (wcsncpy); + + for (n = 0; n < WCSNUM_NCPY - 1; ++n) + { + ws1[n] = 0x9999; + } + + ws1[n] = 0; + ws2 = TST_INPUT (wcsncpy).ws; /* external value: size WCSSIZE */ + n = TST_INPUT (wcsncpy).n; + ret = wcsncpy (ws1, ws2, n); + + TST_IF_RETURN (S_WCSNCPY) + { + if (ret == ws1) + { + Result (C_SUCCESS, S_WCSNCPY, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSNCPY, CASE_3, + "the return address may not be correct"); + } + } + + if (ret == ws1) + { + if (debug_flg) + { + fprintf (stderr, "\nwcsncpy: n = %zu\n\n", n); + } + + ws_ex = TST_EXPECT (wcsncpy).ws; + + for (err = 0, i = 0; i < WCSNUM_NCPY && i < WCSSIZE; i++) + { + if (debug_flg) + fprintf (stderr, + "wcsncpy: ws1[ %d ] = 0x%lx <-> wx_ex[ %d ] = 0x%lx\n", + i, (unsigned long int) ws1[i], i, + (unsigned long int) ws_ex[i]); + + if (ws1[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSNCPY, CASE_4, + "copied string is different from an " + "expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSNCPY, CASE_4, MS_PASSED); + } + + /* A null terminate character is not supposed to be copied + unless (num chars of ws2) 0x%lx = wc_ex\n", + (unsigned long int) *ret, (unsigned long int) wc_ex); + + if (*ret != wc_ex) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSPBRK, CASE_4, "the pointed wc is " + "different from an expected wc"); + } + else + { + Result (C_SUCCESS, S_WCSPBRK, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsrtombs.c b/test/locale-mbwc/tst_wcsrtombs.c new file mode 100644 index 0000000..3a8edcc --- /dev/null +++ b/test/locale-mbwc/tst_wcsrtombs.c @@ -0,0 +1,127 @@ +/* + WCSRTOMBS: size_t wcsrtombs (char *s, const wchar_t **ws, size_t n, + mbstate_t *ps) +*/ + +#define TST_FUNCTION wcsrtombs + +#include "tsp_common.c" +#include "dat_wcsrtombs.c" + +#define MARK_VAL 0x01 + +int +tst_wcsrtombs (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char s_flg, n; + const wchar_t *ws, *wp; + char s[MBSSIZE], *s_in; + char t_flg, t_ini; + static mbstate_t t = { 0 }; + mbstate_t *pt; + int err, i; + char *s_ex; + + TST_DO_TEST (wcsrtombs) + { + TST_HEAD_LOCALE (wcsrtombs, S_WCSRTOMBS); + TST_DO_REC (wcsrtombs) + { + TST_GET_ERRET (wcsrtombs); + memset (s, MARK_VAL, MBSSIZE); + + s_flg = TST_INPUT (wcsrtombs).s_flg; + s_in = (s_flg == 1) ? s : (char *) NULL; + wp = ws = TST_INPUT (wcsrtombs).ws; + n = TST_INPUT (wcsrtombs).n; + t_flg = TST_INPUT (wcsrtombs).t_flg; + t_ini = TST_INPUT (wcsrtombs).t_init; + pt = (t_flg == 0) ? NULL : &t; + + if (t_ini != 0) + { + memset (&t, 0, sizeof (t)); + } + + TST_CLEAR_ERRNO; + ret = wcsrtombs (s_in, &wp, n, pt); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, "wcsrtombs: ret = %zu\n", ret); + } + + TST_IF_RETURN (S_WCSRTOMBS) + { + }; + + if (s_in != NULL && ret != (size_t) - 1) + { + /* No definition for s, when error occurs. */ + s_ex = TST_EXPECT (wcsrtombs).s; + + for (err = 0, i = 0; i <= ret && i < MBSSIZE; i++) + { + if (debug_flg) + { + fprintf (stderr, + " : s[%d] = 0x%hx <-> 0x%hx = s_ex[%d]\n", i, + s[i], s_ex[i], i); + } + + if (i == ret && ret == n) /* no null termination */ + { + if (s[i] == MARK_VAL) + { + Result (C_SUCCESS, S_WCSRTOMBS, CASE_4, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSRTOMBS, CASE_4, + "should not be null terminated " + "(it may be a null char), but it is"); + } + + break; + } + + if (i == ret && ret < n) /* null termination */ + { + if (s[i] == 0) + { + Result (C_SUCCESS, S_WCSRTOMBS, CASE_5, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSRTOMBS, CASE_5, + "should be null terminated, but it is not"); + } + + break; + } + + if (s[i] != s_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSRTOMBS, CASE_6, + "converted string is different from an" + " expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSRTOMBS, CASE_6, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsspn.c b/test/locale-mbwc/tst_wcsspn.c new file mode 100644 index 0000000..02157ee --- /dev/null +++ b/test/locale-mbwc/tst_wcsspn.c @@ -0,0 +1,38 @@ +/* + WCSSPN: size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcsspn + +#include "tsp_common.c" +#include "dat_wcsspn.c" + +int +tst_wcsspn (FILE *fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + wchar_t *ws1, *ws2; + + TST_DO_TEST (wcsspn) + { + TST_HEAD_LOCALE (wcsspn, S_WCSSPN); + TST_DO_REC (wcsspn) + { + TST_GET_ERRET (wcsspn); + ws1 = TST_INPUT (wcsspn).ws1; + ws2 = TST_INPUT (wcsspn).ws2; /* external value: size WCSSIZE */ + ret = wcsspn (ws1, ws2); + + if (debug_flg) + { + fprintf (stderr, "wcsspn: ret = %zu\n", ret); + } + + TST_IF_RETURN (S_WCSSPN) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsstr.c b/test/locale-mbwc/tst_wcsstr.c new file mode 100644 index 0000000..f8b00c4 --- /dev/null +++ b/test/locale-mbwc/tst_wcsstr.c @@ -0,0 +1,86 @@ +/* + WCSSTR: wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2); +*/ + +#define TST_FUNCTION wcsstr + +#include "tsp_common.c" +#include "dat_wcsstr.c" + +int +tst_wcsstr (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + wchar_t *ws1, *ws2; + int err, i; + + TST_DO_TEST (wcsstr) + { + TST_HEAD_LOCALE (wcsstr, S_WCSSTR); + TST_DO_REC (wcsstr) + { + TST_GET_ERRET (wcsstr); + ws1 = TST_INPUT (wcsstr).ws1; + ws2 = TST_INPUT (wcsstr).ws2; /* external value: size WCSSIZE */ + ret = wcsstr (ws1, ws2); + + if (debug_flg) + { + fprintf (stderr, "wcsstr: %d : ret = %s\n", rec + 1, + (ret == NULL) ? "null" : "not null"); + if (ret) + { + fprintf (stderr, + " ret[ 0 ] = 0x%lx <-> 0x%lx = ws2[ 0 ]\n", + (unsigned long int) ret[0], (unsigned long int) ws2[0]); + } + } + + TST_IF_RETURN (S_WCSSTR) + { + if (ws2[0] == 0) + { + if (ret == ws1) + { + Result (C_SUCCESS, S_WCSSTR, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSSTR, CASE_3, + "return address is not same address as ws1"); + } + + continue; + } + + for (i = 0, err = 0; *(ws2 + i) != 0 && i < WCSSIZE; i++) + { + if (debug_flg) + { + fprintf (stderr, + " : ret[ %d ] = 0x%lx <-> 0x%lx = ws2[ %d ]\n", + i, (unsigned long int) ret[i], + (unsigned long int) ws2[i], i); + } + + if (ret[i] != ws2[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSSTR, CASE_4, "pointed sub-string is " + "different from an expected sub-string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSSTR, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcstod.c b/test/locale-mbwc/tst_wcstod.c new file mode 100644 index 0000000..1648d35 --- /dev/null +++ b/test/locale-mbwc/tst_wcstod.c @@ -0,0 +1,69 @@ +/* + WCSTOD: double wcstod (wchar_t *np, const wchar_t **endp); +*/ + +#define TST_FUNCTION wcstod + +#include "tsp_common.c" +#include "dat_wcstod.c" + +int +tst_wcstod (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (double); + wchar_t *np, *endp, fwc; + double val; + + TST_DO_TEST (wcstod) + { + TST_HEAD_LOCALE (wcstod, S_WCSTOD); + TST_DO_REC (wcstod) + { + TST_GET_ERRET (wcstod); + np = TST_INPUT (wcstod).np; + + TST_CLEAR_ERRNO; + ret = wcstod (np, &endp); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "wcstod() [ %s : %d ] ret = %f\n", locale, + rec + 1, ret); + fprintf (stdout, " *endp = 0x%lx\n", + (unsigned long int) *endp); + } + + TST_IF_RETURN (S_WCSTOD) + { + if (ret != 0) + { + val = ret - TST_EXPECT (wcstod).val; + if (TST_ABS (val) < TST_DBL_EPS) + { + Result (C_SUCCESS, S_WCSTOD, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSTOD, CASE_3, "return value is wrong"); + } + } + } + + fwc = TST_EXPECT (wcstod).fwc; + + if (fwc == *endp) + { + Result (C_SUCCESS, S_WCSTOD, CASE_4, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSTOD, CASE_4, "a final wc is wrong."); + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcstok.c b/test/locale-mbwc/tst_wcstok.c new file mode 100644 index 0000000..1222b97 --- /dev/null +++ b/test/locale-mbwc/tst_wcstok.c @@ -0,0 +1,96 @@ +/* + WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm, wchar_t **pt); +*/ + + +#define TST_FUNCTION wcstok + +#include "tsp_common.c" +#include "dat_wcstok.c" + +int +tst_wcstok (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wchar_t *); + char w_flg; + wchar_t *ws; + wchar_t *dt, *pt; + wchar_t *ws_ex; + int err, i; + + TST_DO_TEST (wcstok) + { + TST_HEAD_LOCALE (wcstok, S_WCSTOK); + TST_DO_REC (wcstok) + { + TST_DO_SEQ (WCSTOK_SEQNUM) + { + TST_GET_ERRET_SEQ (wcstok); + w_flg = TST_INPUT_SEQ (wcstok).w_flg; + ws = (w_flg) ? TST_INPUT_SEQ (wcstok).ws : NULL; + dt = TST_INPUT_SEQ (wcstok).dt; + + ret = wcstok (ws, dt, &pt); + + if (debug_flg) + { + fprintf (stdout, "wcstok() [ %s : %d : %d ] *ret = 0x%lx\n", + locale, rec + 1, seq_num + 1, (unsigned long int) *ret); + if (pt && *pt) + { + fprintf (stdout, " *pt = 0x%lx\n", + (unsigned long int) *pt); + } + } + + TST_IF_RETURN (S_WCSTOK) + { + }; + + if (ret != NULL) + { + ws_ex = TST_EXPECT_SEQ (wcstok).ws; + + /* XXX: REVISIT : insufficient conditions */ + for (err = 0, i = 0; i < WCSSIZE; i++) + { + if (ret[i] == L'\0' && ws_ex[i] == L'\0') + { + break; + } + + if (debug_flg) + { + fprintf (stderr, + " ret[%d] = 0x%lx <-> " + "0x%lx = ws_ex[%d]\n", + i, (unsigned long int) ret[i], + (unsigned long int) ws_ex[i], i); + } + + if (ret[i] != ws_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSTOK, CASE_3, + "the token is different from an expected string"); + break; + } + + if (ret[i] == L'\0' || ws_ex[i] == L'\0') + { + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSTOK, CASE_3, MS_PASSED); + } + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcstombs.c b/test/locale-mbwc/tst_wcstombs.c new file mode 100644 index 0000000..c0851a4 --- /dev/null +++ b/test/locale-mbwc/tst_wcstombs.c @@ -0,0 +1,115 @@ +/* + WCSTOMBS: size_t wcstombs (char *s, const wchar_t *ws, size_t n) +*/ + +#define TST_FUNCTION wcstombs + +#include "tsp_common.c" +#include "dat_wcstombs.c" + +#define MARK_VAL 0x01 + +int +tst_wcstombs (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + char s_flg, n; + wchar_t *ws; + char s[MBSSIZE], *s_in; + int err, i; + char *s_ex; + + TST_DO_TEST (wcstombs) + { + TST_HEAD_LOCALE (wcstombs, S_WCSTOMBS); + TST_DO_REC (wcstombs) + { + TST_GET_ERRET (wcstombs); + memset (s, MARK_VAL, MBSSIZE); + + s_flg = TST_INPUT (wcstombs).s_flg; + s_in = (s_flg == 1) ? s : (char *) NULL; + ws = TST_INPUT (wcstombs).ws; + n = TST_INPUT (wcstombs).n; + + TST_CLEAR_ERRNO; + ret = wcstombs (s_in, ws, n); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "wcstombs: ret = %zu\n", ret); + } + + TST_IF_RETURN (S_WCSTOMBS) + { + }; + + if (s_in != NULL && ret != (size_t) - 1) + { + /* No definition for s, when error occurs. */ + s_ex = TST_EXPECT (wcstombs).s; + + for (err = 0, i = 0; i <= ret && i < MBSSIZE; i++) + { + if (debug_flg) + { + fprintf (stdout, + " : s[%d] = 0x%hx <-> 0x%hx = s_ex[%d]\n", i, + s[i], s_ex[i], i); + } + + if (i == ret && ret == n) /* no null termination */ + { + if (s[i] == MARK_VAL) + { + Result (C_SUCCESS, S_WCSTOMBS, CASE_4, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSTOMBS, CASE_4, + "should not be null terminated " + "(it may be a null char), but it is"); + } + + break; + } + + if (i == ret && ret < n) /* null termination */ + { + if (s[i] == 0) + { + Result (C_SUCCESS, S_WCSTOMBS, CASE_5, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSTOMBS, CASE_5, + "should be null terminated, but it is not"); + } + + break; + } + + if (s[i] != s_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCSTOMBS, CASE_6, + "converted string is different from an " + "expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCSTOMBS, CASE_6, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcswidth.c b/test/locale-mbwc/tst_wcswidth.c new file mode 100644 index 0000000..c836975 --- /dev/null +++ b/test/locale-mbwc/tst_wcswidth.c @@ -0,0 +1,39 @@ +/* + WCSWIDTH: int wcswidth (const wchar_t *ws, size_t n); +*/ + +#define TST_FUNCTION wcswidth + +#include "tsp_common.c" +#include "dat_wcswidth.c" + +int +tst_wcswidth (FILE *fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t *ws; + int n; + + TST_DO_TEST (wcswidth) + { + TST_HEAD_LOCALE (wcswidth, S_WCSWIDTH); + TST_DO_REC (wcswidth) + { + TST_GET_ERRET (wcswidth); + ws = TST_INPUT (wcswidth).ws; + n = TST_INPUT (wcswidth).n; + ret = wcswidth (ws, n); + + if (debug_flg) + { + fprintf (stderr, "wcswidth: [ %d ] : ret = %d\n", rec + 1, ret); + } + + TST_IF_RETURN (S_WCSWIDTH) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcsxfrm.c b/test/locale-mbwc/tst_wcsxfrm.c new file mode 100644 index 0000000..6fb8a1c --- /dev/null +++ b/test/locale-mbwc/tst_wcsxfrm.c @@ -0,0 +1,122 @@ +/* + WCSXFRM: size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t n); +*/ + +#define TST_FUNCTION wcsxfrm + +#include "tsp_common.c" +#include "dat_wcsxfrm.c" + +int +tst_wcsxfrm (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (size_t); + wchar_t *org1, *org2; + wchar_t frm1[MBSSIZE], frm2[MBSSIZE]; + size_t n1, n2; + int ret_coll, ret_cmp; + + TST_DO_TEST (wcsxfrm) + { + TST_HEAD_LOCALE (wcsxfrm, S_WCSXFRM); + TST_DO_REC (wcsxfrm) + { + TST_GET_ERRET (wcsxfrm); + org1 = TST_INPUT (wcsxfrm).org1; + org2 = TST_INPUT (wcsxfrm).org2; + n1 = TST_INPUT (wcsxfrm).n1; + n2 = TST_INPUT (wcsxfrm).n2; + if (n1 < 0 || sizeof (frm1) < n1 || sizeof (frm2) < n2) + { + warn_count++; + Result (C_IGNORED, S_WCSXFRM, CASE_9, + "input data n1 or n2 is invalid"); + continue; + } + + /* an errno and a return value are checked + only for 2nd wcsxfrm() call. + A result of 1st call is used to compare + those 2 values by using wcscmp(). + */ + + TST_CLEAR_ERRNO; + ret = wcsxfrm (frm1, org1, n1); /* First call */ + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stdout, "tst_wcsxfrm() : REC = %d\n", rec + 1); + fprintf (stdout, "tst_wcsxfrm() : 1st ret = %zu\n", ret); + } + + if (ret == -1 || ret >= n1 || errno_save != 0) + { + warn_count++; + Result (C_INVALID, S_WCSXFRM, CASE_8, + "got an error in fist wcsxfrm() call"); + continue; + } + + TST_CLEAR_ERRNO; + /* Second call */ + ret = wcsxfrm (((n2 == 0) ? NULL : frm2), org2, n2); + TST_SAVE_ERRNO; + + TST_IF_RETURN (S_WCSXFRM) + { + }; + + if (n2 == 0 || ret >= n2 || errno != 0) + { +#if 0 + warn_count++; + Result (C_IGNORED, S_WCSXFRM, CASE_7, "did not get a result"); +#endif + continue; + } + + if (debug_flg) + { + fprintf (stdout, "tst_wcsxfrm() : 2nd ret = %zu\n", ret); + } + + /* wcscoll() */ + TST_CLEAR_ERRNO; + /* depends on wcscoll() ... not good though ... */ + ret_coll = wcscoll (org1, org2); + TST_SAVE_ERRNO; + + if (errno != 0) /* bugs * bugs may got correct results ... */ + { + warn_count++; + Result (C_INVALID, S_WCSXFRM, CASE_6, + "got an error in wcscoll() call"); + continue; + } + /* wcscmp() */ + ret_cmp = wcscmp (frm1, frm2); + + if ((ret_coll == ret_cmp) || (ret_coll > 0 && ret_cmp > 0) + || (ret_coll < 0 && ret_cmp < 0)) + { + Result (C_SUCCESS, S_WCSXFRM, CASE_3, + MS_PASSED " (depends on wcscoll & wcscmp)"); + } + else + { + err_count++; + Result (C_FAILURE, S_WCSXFRM, CASE_3, + "results from wcscoll & wcscmp() do not match"); + } + + if (debug_flg) + { + fprintf (stdout, "tst_wcsxfrm() : coll = %d <-> %d = cmp\n", + ret_coll, ret_cmp); + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wctob.c b/test/locale-mbwc/tst_wctob.c new file mode 100644 index 0000000..2377daf --- /dev/null +++ b/test/locale-mbwc/tst_wctob.c @@ -0,0 +1,37 @@ +/*-------------------------------------------------------------------------------------*/ +/* WCTOB: int wctob( wint_t wc ) */ +/*-------------------------------------------------------------------------------------*/ + +#define TST_FUNCTION wctob + +#include "tsp_common.c" +#include "dat_wctob.c" + +int +tst_wctob (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t wc; + + TST_DO_TEST (wctob) + { + TST_HEAD_LOCALE (wctob, S_WCTOB); + TST_DO_REC (wctob) + { + TST_GET_ERRET (wctob); + wc = TST_INPUT (wctob).wc; + ret = wctob (wc); + + if (debug_flg) + { + fprintf (stderr, "tst_wctob : [ %d ] ret = %d\n", rec + 1, ret); + } + + TST_IF_RETURN (S_WCTOB) + { + }; + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wctomb.c b/test/locale-mbwc/tst_wctomb.c new file mode 100644 index 0000000..aea89fe --- /dev/null +++ b/test/locale-mbwc/tst_wctomb.c @@ -0,0 +1,99 @@ +/* + WCTOMB: int wctomb (char *s, wchar_t wc) +*/ + +#define TST_FUNCTION wctomb + +#include "tsp_common.c" +#include "dat_wctomb.c" + +int +tst_wctomb (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t wc; + char s[MBSSIZE], *s_in, *s_ex; + int err, i; + + TST_DO_TEST (wctomb) + { + TST_HEAD_LOCALE (wctomb, S_WCTOMB); + TST_DO_REC (wctomb) + { + TST_GET_ERRET (wctomb); + wc = TST_INPUT (wctomb).wc; + s_in = ((TST_INPUT (wctomb).s_flg) == 0) ? (char *) NULL : s; + ret = wctomb (s_in, wc); + + if (debug_flg) + { + fprintf (stdout, "wctomb() [ %s : %d ] ret = %d\n", locale, + rec + 1, ret); + } + + TST_IF_RETURN (S_WCTOMB) + { + if (s_in == NULL) /* state dependency */ + { + if (ret_exp == +1) /* state-dependent */ + { + if (ret != 0) + { + /* Non-zero means state-dependent encoding. */ + Result (C_SUCCESS, S_WCTOMB, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCTOMB, CASE_3, + "should be state-dependent encoding, " + "but a return value shows it is " + "state-independent"); + } + } + + if (ret_exp == 0) /* state-independent */ + { + if (ret == 0) + { + /* Non-zero means state-dependent encoding. */ + Result (C_SUCCESS, S_WCTOMB, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCTOMB, CASE_3, + "should be state-independent encoding, " + "but a return value shows it is state-dependent"); + } + } + } + } + + s_ex = TST_EXPECT (wctomb).s; + + if (s_in) + { + for (i = 0, err = 0; *(s_ex + i) != 0 && i < MBSSIZE; i++) + { + if (s_in[i] != s_ex[i]) + { + err++; + err_count++; + Result (C_FAILURE, S_WCTOMB, CASE_4, + "copied string is different from an" + " expected string"); + break; + } + } + + if (!err) + { + Result (C_SUCCESS, S_WCTOMB, CASE_4, MS_PASSED); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wctrans.c b/test/locale-mbwc/tst_wctrans.c new file mode 100644 index 0000000..b422d6f --- /dev/null +++ b/test/locale-mbwc/tst_wctrans.c @@ -0,0 +1,52 @@ +/* + WCTRANS: wctrans_t wctrans (const char *charclass); +*/ + +#define TST_FUNCTION wctrans + +#include "tsp_common.c" +#include "dat_wctrans.c" + +int +tst_wctrans (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wctrans_t); + char *class; + + TST_DO_TEST (wctrans) + { + TST_HEAD_LOCALE (wctrans, S_WCTRANS); + TST_DO_REC (wctrans) + { + TST_GET_ERRET (wctrans); + class = TST_INPUT (wctrans).class; + + TST_CLEAR_ERRNO; + ret = wctrans (class); + TST_SAVE_ERRNO; + + if (debug_flg) + { + fprintf (stderr, "tst_wctrans : [ %d ] ret = %ld\n", rec + 1, + (long int) ret); + fprintf (stderr, " errno = %d\n", errno_save); + } + + TST_IF_RETURN (S_WCTRANS) + { + if (ret != 0) + { + Result (C_SUCCESS, S_WCTYPE, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCTYPE, CASE_3, + "should return non-0, but returned 0"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wctype.c b/test/locale-mbwc/tst_wctype.c new file mode 100644 index 0000000..a203e49 --- /dev/null +++ b/test/locale-mbwc/tst_wctype.c @@ -0,0 +1,48 @@ +/* + WCTYPE: wctype_t wctype (const char *class); +*/ + + +#define TST_FUNCTION wctype + +#include "tsp_common.c" +#include "dat_wctype.c" + +int +tst_wctype (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (wctype_t); + char *class; + + TST_DO_TEST (wctype) + { + TST_HEAD_LOCALE (wctype, S_WCTYPE); + TST_DO_REC (wctype) + { + TST_GET_ERRET (wctype); + class = TST_INPUT (wctype).class; + ret = wctype (class); + + if (debug_flg) + { + fprintf (stderr, "tst_wctype : [ %d ] ret = %ld\n", rec + 1, ret); + } + + TST_IF_RETURN (S_WCTYPE) + { + if (ret != 0) + { + Result (C_SUCCESS, S_WCTYPE, CASE_3, MS_PASSED); + } + else + { + err_count++; + Result (C_FAILURE, S_WCTYPE, CASE_3, + "should return non-0, but returned 0"); + } + } + } + } + + return err_count; +} diff --git a/test/locale-mbwc/tst_wcwidth.c b/test/locale-mbwc/tst_wcwidth.c new file mode 100644 index 0000000..6a5af6f --- /dev/null +++ b/test/locale-mbwc/tst_wcwidth.c @@ -0,0 +1,38 @@ +/* + WCWIDTH: int wcwidth (wchar_t wc); +*/ + +#define TST_FUNCTION wcwidth + +#include "tsp_common.c" +#include "dat_wcwidth.c" + +int +tst_wcwidth (FILE * fp, int debug_flg) +{ + TST_DECL_VARS (int); + wchar_t wc; + + TST_DO_TEST (wcwidth) + { + TST_HEAD_LOCALE (wcwidth, S_WCWIDTH); + TST_DO_REC (wcwidth) + { + TST_GET_ERRET (wcwidth); + wc = TST_INPUT (wcwidth).wc; + ret = wcwidth (wc); + + if (debug_flg) + { + fprintf (stdout, "wcwidth() [ %s : %d ] ret = %d\n", locale, + rec + 1, ret); + } + + TST_IF_RETURN (S_WCWIDTH) + { + } + } + } + + return err_count; +} diff --git a/test/locale/Makefile b/test/locale/Makefile new file mode 100644 index 0000000..7e408b8 --- /dev/null +++ b/test/locale/Makefile @@ -0,0 +1,31 @@ +# uClibc locale tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# tst_mbtowc tst_strcoll tst_strfmon tst_strxfrm \ + +TESTS := bug-iconv-trans bug-usesetlocale collate-test dump-ctype \ + gen-unicode-ctype show-ucs-data tst-ctype \ + tst-digits tst-fmon tst-langinfo tst-leaks tst-mbswcs1 \ + tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 tst-mbswcs6 \ + tst_nl_langinfo tst-numeric tst-rpmatch tst-setlocale \ + tst-sscanf tst-strfmon1 tst-trans tst-wctype tst-xlocale1 \ + tst-xlocale2 xfrm-test + + +# NOTE: For now disabled some tests that are known not build +TESTS_DISABLED := tst-ctype tst-fmon tst-leaks tst-rpmatch tst-strfmon1 + +ifneq ($(UCLIBC_HAS_XLOCALE),y) +TESTS_DISABLED += bug-usesetlocale tst-xlocale1 tst-xlocale2 xfrm-test tst-C-locale +endif + +include ../Test.mak + +DODIFF_rint := 1 + +EXTRA_CFLAGS := -D__USE_GNU -fno-builtin + +OPTS_dump-ctype = C +OPTS_tst-ctype = < tst-ctype-de_DE.ISO-8859-1.in +OPTS_tst-langinfo = < tst-langinfo.input + +EXTRA_DIRS := C diff --git a/test/locale/bug-iconv-trans.c b/test/locale/bug-iconv-trans.c new file mode 100644 index 0000000..3886247 --- /dev/null +++ b/test/locale/bug-iconv-trans.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +int +main (void) +{ + iconv_t cd; + const char str[] = "ÄäÖöÜüß"; + const char expected[] = "AEaeOEoeUEuess"; + char *inptr = (char *) str; + size_t inlen = strlen (str) + 1; + char outbuf[500]; + char *outptr = outbuf; + size_t outlen = sizeof (outbuf); + int result = 0; + size_t n; + + if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) + { + puts ("setlocale failed"); + return 1; + } + + cd = iconv_open ("ANSI_X3.4-1968//TRANSLIT", "ISO-8859-1"); + if (cd == (iconv_t) -1) + { + puts ("iconv_open failed"); + return 1; + } + + n = iconv (cd, &inptr, &inlen, &outptr, &outlen); + if (n != 7) + { + if (n == (size_t) -1) + printf ("iconv() returned error: %m\n"); + else + printf ("iconv() returned %Zd, expected 7\n", n); + result = 1; + } + if (inlen != 0) + { + puts ("not all input consumed"); + result = 1; + } + else if (inptr - str != strlen (str) + 1) + { + printf ("inptr wrong, advanced by %td\n", inptr - str); + result = 1; + } + if (memcmp (outbuf, expected, sizeof (expected)) != 0) + { + printf ("result wrong: \"%.*s\", expected: \"%s\"\n", + (int) (sizeof (outbuf) - outlen), outbuf, expected); + result = 1; + } + else if (outlen != sizeof (outbuf) - sizeof (expected)) + { + printf ("outlen wrong: %Zd, expected %Zd\n", outlen, + sizeof (outbuf) - 15); + result = 1; + } + else + printf ("output is \"%s\" which is OK\n", outbuf); + + return result; +} diff --git a/test/locale/bug-usesetlocale.c b/test/locale/bug-usesetlocale.c new file mode 100644 index 0000000..0637067 --- /dev/null +++ b/test/locale/bug-usesetlocale.c @@ -0,0 +1,38 @@ +/* Test case for setlocale vs uselocale (LC_GLOBAL_LOCALE) bug. */ + +#define _GNU_SOURCE 1 +#include +#include +#include + +static int +do_test (void) +{ + __locale_t loc_new, loc_old; + + int first = !!isalpha(0xE4); + + setlocale (LC_ALL, "de_DE"); + + int global_de = !!isalpha(0xE4); + + loc_new = newlocale (1 << LC_ALL, "C", 0); + loc_old = uselocale (loc_new); + + int used_c = !!isalpha(0xE4); + + uselocale (loc_old); + + int used_global = !!isalpha(0xE4); + + printf ("started %d, after setlocale %d\n", first, global_de); + printf ("after uselocale %d, after LC_GLOBAL_LOCALE %d\n", + used_c, used_global); + + freelocale (loc_new); + return !(used_c == first && used_global == global_de); +} + + +#define TEST_FUNCTION do_test () +#include "test-skeleton.c" diff --git a/test/locale/collate-test.c b/test/locale/collate-test.c new file mode 100644 index 0000000..e8f4321 --- /dev/null +++ b/test/locale/collate-test.c @@ -0,0 +1,133 @@ +/* Test collation function using real data. + Copyright (C) 1997, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +struct lines +{ + char *key; + char *line; +}; + +static int xstrcoll (const void *, const void *); + +int +main (int argc, char *argv[]) +{ + int result = 0; + size_t nstrings, nstrings_max; + struct lines *strings; + char *line = NULL; + size_t len = 0; + size_t n; + + if (argc < 2) + error (1, 0, "usage: %s ", argv[0]); + + setlocale (LC_ALL, ""); + + nstrings_max = 100; + nstrings = 0; + strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines)); + if (strings == NULL) + { + perror (argv[0]); + exit (1); + } + + while (1) + { + int l; + if (getline (&line, &len, stdin) < 0) + break; + + if (nstrings == nstrings_max) + { + strings = (struct lines *) realloc (strings, + (nstrings_max *= 2) + * sizeof (*strings)); + if (strings == NULL) + { + perror (argv[0]); + exit (1); + } + } + strings[nstrings].line = strdup (line); + l = strcspn (line, ":(;"); + while (l > 0 && isspace (line[l - 1])) + --l; + strings[nstrings].key = strndup (line, l); + ++nstrings; + } + free (line); + + /* First shuffle. */ + srandom (atoi (argv[1])); + for (n = 0; n < 10 * nstrings; ++n) + { + int r1, r2, r; + size_t idx1 = random () % nstrings; + size_t idx2 = random () % nstrings; + struct lines tmp = strings[idx1]; + strings[idx1] = strings[idx2]; + strings[idx2] = tmp; + + /* While we are at it a first little test. */ + r1 = strcoll (strings[idx1].key, strings[idx2].key); + r2 = strcoll (strings[idx2].key, strings[idx1].key); + r = r1 * r2; + + if (r > 0 || (r == 0 && r1 != 0) || (r == 0 && r2 != 0)) + printf ("`%s' and `%s' collate wrong: %d vs. %d\n", + strings[idx1].key, strings[idx2].key, r1, r2); + } + + /* Now sort. */ + qsort (strings, nstrings, sizeof (struct lines), xstrcoll); + + /* Print the result. */ + for (n = 0; n < nstrings; ++n) + { + fputs (strings[n].line, stdout); + free (strings[n].line); + free (strings[n].key); + } + free (strings); + + return result; +} + + +static int +xstrcoll (ptr1, ptr2) + const void *ptr1; + const void *ptr2; +{ + const struct lines *l1 = (const struct lines *) ptr1; + const struct lines *l2 = (const struct lines *) ptr2; + + return strcoll (l1->key, l2->key); +} diff --git a/test/locale/dump-ctype.c b/test/locale/dump-ctype.c new file mode 100644 index 0000000..a1f24c6 --- /dev/null +++ b/test/locale/dump-ctype.c @@ -0,0 +1,164 @@ +/* Dump the character classes and character maps of a locale to a bunch + of individual files which can be processed with diff, sed etc. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Usage example: + $ dump-ctype de_DE.UTF-8 + */ + +#include +#include +#include +#include +#include +#include +#include + +static const char *program_name = "dump-ctype"; +static const char *locale; + +static const char *class_names[] = + { + "alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower", + "print", "punct", "space", "upper", "xdigit" + }; + +static const char *map_names[] = + { + "tolower", "toupper", "totitle" + }; + +static void dump_class (const char *class_name) +{ + wctype_t class; + FILE *f; + unsigned int ch; + + class = wctype (class_name); + if (class == (wctype_t) 0) + { + fprintf (stderr, "%s %s: noexistent class %s\n", program_name, + locale, class_name); + return; + } + + f = fopen (class_name, "w"); + if (f == NULL) + { + fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name, + locale, locale, class_name); + exit (1); + } + + for (ch = 0; ch < 0x10000; ch++) + if (iswctype (ch, class)) + fprintf (f, "0x%04X\n", ch); + + if (ferror (f) || fclose (f)) + { + fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name, + locale, locale, class_name); + exit (1); + } +} + +static void dump_map (const char *map_name) +{ + wctrans_t map; + FILE *f; + unsigned int ch; + + map = wctrans (map_name); + if (map == (wctrans_t) 0) + { + fprintf (stderr, "%s %s: noexistent map %s\n", program_name, + locale, map_name); + return; + } + + f = fopen (map_name, "w"); + if (f == NULL) + { + fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name, + locale, locale, map_name); + exit (1); + } + + for (ch = 0; ch < 0x10000; ch++) + if (towctrans (ch, map) != ch) + fprintf (f, "0x%04X\t0x%04X\n", ch, towctrans (ch, map)); + + if (ferror (f) || fclose (f)) + { + fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name, + locale, locale, map_name); + exit (1); + } +} + +int +main (int argc, char *argv[]) +{ + size_t i; + + if (argc != 2) + { + fprintf (stderr, "Usage: dump-ctype locale\n"); + exit (1); + } + locale = argv[1]; + + if (setlocale (LC_ALL, locale) == NULL) + { + fprintf (stderr, "%s: setlocale cannot switch to locale %s\n", + program_name, locale); + exit (1); + } + + if (mkdir (locale, 0777) < 0) + { + char buf[100]; + int save_errno = errno; + + sprintf (buf, "%s: cannot create directory %s", program_name, locale); + errno = save_errno; + perror (buf); + exit (1); + } + + if (chdir (locale) < 0) + { + char buf[100]; + int save_errno = errno; + + sprintf (buf, "%s: cannot chdir to %s", program_name, locale); + errno = save_errno; + perror (buf); + exit (1); + } + + for (i = 0; i < sizeof (class_names) / sizeof (class_names[0]); i++) + dump_class (class_names[i]); + + for (i = 0; i < sizeof (map_names) / sizeof (map_names[0]); i++) + dump_map (map_names[i]); + + return 0; +} diff --git a/test/locale/gen-unicode-ctype.c b/test/locale/gen-unicode-ctype.c new file mode 100644 index 0000000..849f272 --- /dev/null +++ b/test/locale/gen-unicode-ctype.c @@ -0,0 +1,785 @@ +/* Generate a Unicode conforming LC_CTYPE category from a UnicodeData file. + Copyright (C) 2000-2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Usage example: + $ gen-unicode /usr/local/share/Unidata/UnicodeData.txt 3.1 + */ + +#include +#include +#include +#include +#include + +/* This structure represents one line in the UnicodeData.txt file. */ +struct unicode_attribute +{ + const char *name; /* Character name */ + const char *category; /* General category */ + const char *combining; /* Canonical combining classes */ + const char *bidi; /* Bidirectional category */ + const char *decomposition; /* Character decomposition mapping */ + const char *decdigit; /* Decimal digit value */ + const char *digit; /* Digit value */ + const char *numeric; /* Numeric value */ + int mirrored; /* mirrored */ + const char *oldname; /* Old Unicode 1.0 name */ + const char *comment; /* Comment */ + unsigned int upper; /* Uppercase mapping */ + unsigned int lower; /* Lowercase mapping */ + unsigned int title; /* Titlecase mapping */ +}; + +/* Missing fields are represented with "" for strings, and NONE for + characters. */ +#define NONE (~(unsigned int)0) + +/* The entire contents of the UnicodeData.txt file. */ +struct unicode_attribute unicode_attributes [0x110000]; + +/* Stores in unicode_attributes[i] the values from the given fields. */ +static void +fill_attribute (unsigned int i, + const char *field1, const char *field2, + const char *field3, const char *field4, + const char *field5, const char *field6, + const char *field7, const char *field8, + const char *field9, const char *field10, + const char *field11, const char *field12, + const char *field13, const char *field14) +{ + struct unicode_attribute * uni; + + if (i >= 0x110000) + { + fprintf (stderr, "index too large\n"); + exit (1); + } + if (strcmp (field2, "Cs") == 0) + /* Surrogates are UTF-16 artefacts, not real characters. Ignore them. */ + return; + uni = &unicode_attributes[i]; + /* Copy the strings. */ + uni->name = strdup (field1); + uni->category = (field2[0] == '\0' ? "" : strdup (field2)); + uni->combining = (field3[0] == '\0' ? "" : strdup (field3)); + uni->bidi = (field4[0] == '\0' ? "" : strdup (field4)); + uni->decomposition = (field5[0] == '\0' ? "" : strdup (field5)); + uni->decdigit = (field6[0] == '\0' ? "" : strdup (field6)); + uni->digit = (field7[0] == '\0' ? "" : strdup (field7)); + uni->numeric = (field8[0] == '\0' ? "" : strdup (field8)); + uni->mirrored = (field9[0] == 'Y'); + uni->oldname = (field10[0] == '\0' ? "" : strdup (field10)); + uni->comment = (field11[0] == '\0' ? "" : strdup (field11)); + uni->upper = (field12[0] =='\0' ? NONE : strtoul (field12, NULL, 16)); + uni->lower = (field13[0] =='\0' ? NONE : strtoul (field13, NULL, 16)); + uni->title = (field14[0] =='\0' ? NONE : strtoul (field14, NULL, 16)); +} + +/* Maximum length of a field in the UnicodeData.txt file. */ +#define FIELDLEN 120 + +/* Reads the next field from STREAM. The buffer BUFFER has size FIELDLEN. + Reads up to (but excluding) DELIM. + Returns 1 when a field was successfully read, otherwise 0. */ +static int +getfield (FILE *stream, char *buffer, int delim) +{ + int count = 0; + int c; + + for (; (c = getc (stream)), (c != EOF && c != delim); ) + { + /* The original unicode.org UnicodeData.txt file happens to have + CR/LF line terminators. Silently convert to LF. */ + if (c == '\r') + continue; + + /* Put c into the buffer. */ + if (++count >= FIELDLEN - 1) + { + fprintf (stderr, "field too long\n"); + exit (1); + } + *buffer++ = c; + } + + if (c == EOF) + return 0; + + *buffer = '\0'; + return 1; +} + +/* Stores in unicode_attributes[] the entire contents of the UnicodeData.txt + file. */ +static void +fill_attributes (const char *unicodedata_filename) +{ + unsigned int i, j; + FILE *stream; + char field0[FIELDLEN]; + char field1[FIELDLEN]; + char field2[FIELDLEN]; + char field3[FIELDLEN]; + char field4[FIELDLEN]; + char field5[FIELDLEN]; + char field6[FIELDLEN]; + char field7[FIELDLEN]; + char field8[FIELDLEN]; + char field9[FIELDLEN]; + char field10[FIELDLEN]; + char field11[FIELDLEN]; + char field12[FIELDLEN]; + char field13[FIELDLEN]; + char field14[FIELDLEN]; + int lineno = 0; + + for (i = 0; i < 0x110000; i++) + unicode_attributes[i].name = NULL; + + stream = fopen (unicodedata_filename, "r"); + if (stream == NULL) + { + fprintf (stderr, "error during fopen of '%s'\n", unicodedata_filename); + exit (1); + } + + for (;;) + { + int n; + + lineno++; + n = getfield (stream, field0, ';'); + n += getfield (stream, field1, ';'); + n += getfield (stream, field2, ';'); + n += getfield (stream, field3, ';'); + n += getfield (stream, field4, ';'); + n += getfield (stream, field5, ';'); + n += getfield (stream, field6, ';'); + n += getfield (stream, field7, ';'); + n += getfield (stream, field8, ';'); + n += getfield (stream, field9, ';'); + n += getfield (stream, field10, ';'); + n += getfield (stream, field11, ';'); + n += getfield (stream, field12, ';'); + n += getfield (stream, field13, ';'); + n += getfield (stream, field14, '\n'); + if (n == 0) + break; + if (n != 15) + { + fprintf (stderr, "short line in'%s':%d\n", + unicodedata_filename, lineno); + exit (1); + } + i = strtoul (field0, NULL, 16); + if (field1[0] == '<' + && strlen (field1) >= 9 + && !strcmp (field1 + strlen(field1) - 8, ", First>")) + { + /* Deal with a range. */ + lineno++; + n = getfield (stream, field0, ';'); + n += getfield (stream, field1, ';'); + n += getfield (stream, field2, ';'); + n += getfield (stream, field3, ';'); + n += getfield (stream, field4, ';'); + n += getfield (stream, field5, ';'); + n += getfield (stream, field6, ';'); + n += getfield (stream, field7, ';'); + n += getfield (stream, field8, ';'); + n += getfield (stream, field9, ';'); + n += getfield (stream, field10, ';'); + n += getfield (stream, field11, ';'); + n += getfield (stream, field12, ';'); + n += getfield (stream, field13, ';'); + n += getfield (stream, field14, '\n'); + if (n != 15) + { + fprintf (stderr, "missing end range in '%s':%d\n", + unicodedata_filename, lineno); + exit (1); + } + if (!(field1[0] == '<' + && strlen (field1) >= 8 + && !strcmp (field1 + strlen (field1) - 7, ", Last>"))) + { + fprintf (stderr, "missing end range in '%s':%d\n", + unicodedata_filename, lineno); + exit (1); + } + field1[strlen (field1) - 7] = '\0'; + j = strtoul (field0, NULL, 16); + for (; i <= j; i++) + fill_attribute (i, field1+1, field2, field3, field4, field5, + field6, field7, field8, field9, field10, + field11, field12, field13, field14); + } + else + { + /* Single character line */ + fill_attribute (i, field1, field2, field3, field4, field5, + field6, field7, field8, field9, field10, + field11, field12, field13, field14); + } + } + if (ferror (stream) || fclose (stream)) + { + fprintf (stderr, "error reading from '%s'\n", unicodedata_filename); + exit (1); + } +} + +/* Character mappings. */ + +static unsigned int +to_upper (unsigned int ch) +{ + if (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].upper != NONE) + return unicode_attributes[ch].upper; + else + return ch; +} + +static unsigned int +to_lower (unsigned int ch) +{ + if (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].lower != NONE) + return unicode_attributes[ch].lower; + else + return ch; +} + +static unsigned int +to_title (unsigned int ch) +{ + if (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].title != NONE) + return unicode_attributes[ch].title; + else + return ch; +} + +/* Character class properties. */ + +static bool +is_upper (unsigned int ch) +{ + return (to_lower (ch) != ch); +} + +static bool +is_lower (unsigned int ch) +{ + return (to_upper (ch) != ch) + /* is lowercase, but without simple to_upper mapping. */ + || (ch == 0x00DF); +} + +static bool +is_alpha (unsigned int ch) +{ + return (unicode_attributes[ch].name != NULL + && ((unicode_attributes[ch].category[0] == 'L' + /* Theppitak Karoonboonyanan says + , should belong to is_punct. */ + && (ch != 0x0E2F) && (ch != 0x0E46)) + /* Theppitak Karoonboonyanan says + , .., .. are is_alpha. */ + || (ch == 0x0E31) + || (ch >= 0x0E34 && ch <= 0x0E3A) + || (ch >= 0x0E47 && ch <= 0x0E4E) + /* Avoid warning for . */ + || (ch == 0x0345) + /* Avoid warnings for ... */ + || (unicode_attributes[ch].category[0] == 'N' + && unicode_attributes[ch].category[1] == 'l') + /* Avoid warnings for ... */ + || (unicode_attributes[ch].category[0] == 'S' + && unicode_attributes[ch].category[1] == 'o' + && strstr (unicode_attributes[ch].name, " LETTER ") + != NULL) + /* Consider all the non-ASCII digits as alphabetic. + ISO C 99 forbids us to have them in category "digit", + but we want iswalnum to return true on them. */ + || (unicode_attributes[ch].category[0] == 'N' + && unicode_attributes[ch].category[1] == 'd' + && !(ch >= 0x0030 && ch <= 0x0039)))); +} + +static bool +is_digit (unsigned int ch) +{ +#if 0 + return (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'N' + && unicode_attributes[ch].category[1] == 'd'); + /* Note: U+0BE7..U+0BEF and U+1369..U+1371 are digit systems without + a zero. Must add <0> in front of them by hand. */ +#else + /* SUSV2 gives us some freedom for the "digit" category, but ISO C 99 + takes it away: + 7.25.2.1.5: + The iswdigit function tests for any wide character that corresponds + to a decimal-digit character (as defined in 5.2.1). + 5.2.1: + the 10 decimal digits 0 1 2 3 4 5 6 7 8 9 + */ + return (ch >= 0x0030 && ch <= 0x0039); +#endif +} + +static bool +is_outdigit (unsigned int ch) +{ + return (ch >= 0x0030 && ch <= 0x0039); +} + +static bool +is_blank (unsigned int ch) +{ + return (ch == 0x0009 /* '\t' */ + /* Category Zs without mention of "" */ + || (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'Z' + && unicode_attributes[ch].category[1] == 's' + && !strstr (unicode_attributes[ch].decomposition, ""))); +} + +static bool +is_space (unsigned int ch) +{ + /* Don't make U+00A0 a space. Non-breaking space means that all programs + should treat it like a punctuation character, not like a space. */ + return (ch == 0x0020 /* ' ' */ + || ch == 0x000C /* '\f' */ + || ch == 0x000A /* '\n' */ + || ch == 0x000D /* '\r' */ + || ch == 0x0009 /* '\t' */ + || ch == 0x000B /* '\v' */ + /* Categories Zl, Zp, and Zs without mention of "" */ + || (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'Z' + && (unicode_attributes[ch].category[1] == 'l' + || unicode_attributes[ch].category[1] == 'p' + || (unicode_attributes[ch].category[1] == 's' + && !strstr (unicode_attributes[ch].decomposition, + ""))))); +} + +static bool +is_cntrl (unsigned int ch) +{ + return (unicode_attributes[ch].name != NULL + && (!strcmp (unicode_attributes[ch].name, "") + /* Categories Zl and Zp */ + || (unicode_attributes[ch].category[0] == 'Z' + && (unicode_attributes[ch].category[1] == 'l' + || unicode_attributes[ch].category[1] == 'p')))); +} + +static bool +is_xdigit (unsigned int ch) +{ +#if 0 + return is_digit (ch) + || (ch >= 0x0041 && ch <= 0x0046) + || (ch >= 0x0061 && ch <= 0x0066); +#else + /* SUSV2 gives us some freedom for the "xdigit" category, but ISO C 99 + takes it away: + 7.25.2.1.12: + The iswxdigit function tests for any wide character that corresponds + to a hexadecimal-digit character (as defined in 6.4.4.1). + 6.4.4.1: + hexadecimal-digit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F + */ + return (ch >= 0x0030 && ch <= 0x0039) + || (ch >= 0x0041 && ch <= 0x0046) + || (ch >= 0x0061 && ch <= 0x0066); +#endif +} + +static bool +is_graph (unsigned int ch) +{ + return (unicode_attributes[ch].name != NULL + && strcmp (unicode_attributes[ch].name, "") + && !is_space (ch)); +} + +static bool +is_print (unsigned int ch) +{ + return (unicode_attributes[ch].name != NULL + && strcmp (unicode_attributes[ch].name, "") + /* Categories Zl and Zp */ + && !(unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'Z' + && (unicode_attributes[ch].category[1] == 'l' + || unicode_attributes[ch].category[1] == 'p'))); +} + +static bool +is_punct (unsigned int ch) +{ +#if 0 + return (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'P'); +#else + /* The traditional POSIX definition of punctuation is every graphic, + non-alphanumeric character. */ + return (is_graph (ch) && !is_alpha (ch) && !is_digit (ch)); +#endif +} + +static bool +is_combining (unsigned int ch) +{ + /* Up to Unicode 3.0.1 we took the Combining property from the PropList.txt + file. In 3.0.1 it was identical to the union of the general categories + "Mn", "Mc", "Me". In Unicode 3.1 this property has been dropped from the + PropList.txt file, so we take the latter definition. */ + return (unicode_attributes[ch].name != NULL + && unicode_attributes[ch].category[0] == 'M' + && (unicode_attributes[ch].category[1] == 'n' + || unicode_attributes[ch].category[1] == 'c' + || unicode_attributes[ch].category[1] == 'e')); +} + +static bool +is_combining_level3 (unsigned int ch) +{ + return is_combining (ch) + && !(unicode_attributes[ch].combining[0] != '\0' + && unicode_attributes[ch].combining[0] != '0' + && strtoul (unicode_attributes[ch].combining, NULL, 10) >= 200); +} + +/* Return the UCS symbol string for a Unicode character. */ +static const char * +ucs_symbol (unsigned int i) +{ + static char buf[11+1]; + + sprintf (buf, (i < 0x10000 ? "" : ""), i); + return buf; +} + +/* Return the UCS symbol range string for a Unicode characters interval. */ +static const char * +ucs_symbol_range (unsigned int low, unsigned int high) +{ + static char buf[24+1]; + + strcpy (buf, ucs_symbol (low)); + strcat (buf, ".."); + strcat (buf, ucs_symbol (high)); + return buf; +} + +/* Output a character class (= property) table. */ + +static void +output_charclass (FILE *stream, const char *classname, + bool (*func) (unsigned int)) +{ + char table[0x110000]; + unsigned int i; + bool need_semicolon; + const int max_column = 75; + int column; + + for (i = 0; i < 0x110000; i++) + table[i] = (int) func (i); + + fprintf (stream, "%s ", classname); + need_semicolon = false; + column = 1000; + for (i = 0; i < 0x110000; ) + { + if (!table[i]) + i++; + else + { + unsigned int low, high; + char buf[25]; + + low = i; + do + i++; + while (i < 0x110000 && table[i]); + high = i - 1; + + if (low == high) + strcpy (buf, ucs_symbol (low)); + else + strcpy (buf, ucs_symbol_range (low, high)); + + if (need_semicolon) + { + fprintf (stream, ";"); + column++; + } + + if (column + strlen (buf) > max_column) + { + fprintf (stream, "/\n "); + column = 3; + } + + fprintf (stream, "%s", buf); + column += strlen (buf); + need_semicolon = true; + } + } + fprintf (stream, "\n"); +} + +/* Output a character mapping table. */ + +static void +output_charmap (FILE *stream, const char *mapname, + unsigned int (*func) (unsigned int)) +{ + char table[0x110000]; + unsigned int i; + bool need_semicolon; + const int max_column = 75; + int column; + + for (i = 0; i < 0x110000; i++) + table[i] = (func (i) != i); + + fprintf (stream, "%s ", mapname); + need_semicolon = false; + column = 1000; + for (i = 0; i < 0x110000; i++) + if (table[i]) + { + char buf[25+1]; + + strcpy (buf, "("); + strcat (buf, ucs_symbol (i)); + strcat (buf, ","); + strcat (buf, ucs_symbol (func (i))); + strcat (buf, ")"); + + if (need_semicolon) + { + fprintf (stream, ";"); + column++; + } + + if (column + strlen (buf) > max_column) + { + fprintf (stream, "/\n "); + column = 3; + } + + fprintf (stream, "%s", buf); + column += strlen (buf); + need_semicolon = true; + } + fprintf (stream, "\n"); +} + +/* Output the width table. */ + +static void +output_widthmap (FILE *stream) +{ +} + +/* Output the tables to the given file. */ + +static void +output_tables (const char *filename, const char *version) +{ + FILE *stream; + unsigned int ch; + + stream = fopen (filename, "w"); + if (stream == NULL) + { + fprintf (stderr, "cannot open '%s' for writing\n", filename); + exit (1); + } + + fprintf (stream, "escape_char /\n"); + fprintf (stream, "comment_char %%\n"); + fprintf (stream, "\n"); + fprintf (stream, "%% Generated automatically by gen-unicode-ctype for Unicode %s.\n", + version); + fprintf (stream, "\n"); + + fprintf (stream, "LC_IDENTIFICATION\n"); + fprintf (stream, "title \"Unicode %s FDCC-set\"\n", version); + fprintf (stream, "source \"UnicodeData.txt, PropList.txt\"\n"); + fprintf (stream, "address \"\"\n"); + fprintf (stream, "contact \"\"\n"); + fprintf (stream, "email \"bug-glibc-locales@gnu.org\"\n"); + fprintf (stream, "tel \"\"\n"); + fprintf (stream, "fax \"\"\n"); + fprintf (stream, "language \"\"\n"); + fprintf (stream, "territory \"Earth\"\n"); + fprintf (stream, "revision \"%s\"\n", version); + { + time_t now; + char date[11]; + now = time (NULL); + strftime (date, sizeof (date), "%Y-%m-%d", gmtime (&now)); + fprintf (stream, "date \"%s\"\n", date); + } + fprintf (stream, "category \"unicode:2001\";LC_CTYPE\n"); + fprintf (stream, "END LC_IDENTIFICATION\n"); + fprintf (stream, "\n"); + + /* Verifications. */ + for (ch = 0; ch < 0x110000; ch++) + { + /* toupper restriction: "Only characters specified for the keywords + lower and upper shall be specified. */ + if (to_upper (ch) != ch && !(is_lower (ch) || is_upper (ch))) + fprintf (stderr, + "%s is not upper|lower but toupper(0x%04X) = 0x%04X\n", + ucs_symbol (ch), ch, to_upper (ch)); + + /* tolower restriction: "Only characters specified for the keywords + lower and upper shall be specified. */ + if (to_lower (ch) != ch && !(is_lower (ch) || is_upper (ch))) + fprintf (stderr, + "%s is not upper|lower but tolower(0x%04X) = 0x%04X\n", + ucs_symbol (ch), ch, to_lower (ch)); + + /* alpha restriction: "Characters classified as either upper or lower + shall automatically belong to this class. */ + if ((is_lower (ch) || is_upper (ch)) && !is_alpha (ch)) + fprintf (stderr, "%s is upper|lower but not alpha\n", ucs_symbol (ch)); + + /* alpha restriction: "No character specified for the keywords cntrl, + digit, punct or space shall be specified." */ + if (is_alpha (ch) && is_cntrl (ch)) + fprintf (stderr, "%s is alpha and cntrl\n", ucs_symbol (ch)); + if (is_alpha (ch) && is_digit (ch)) + fprintf (stderr, "%s is alpha and digit\n", ucs_symbol (ch)); + if (is_alpha (ch) && is_punct (ch)) + fprintf (stderr, "%s is alpha and punct\n", ucs_symbol (ch)); + if (is_alpha (ch) && is_space (ch)) + fprintf (stderr, "%s is alpha and space\n", ucs_symbol (ch)); + + /* space restriction: "No character specified for the keywords upper, + lower, alpha, digit, graph or xdigit shall be specified." + upper, lower, alpha already checked above. */ + if (is_space (ch) && is_digit (ch)) + fprintf (stderr, "%s is space and digit\n", ucs_symbol (ch)); + if (is_space (ch) && is_graph (ch)) + fprintf (stderr, "%s is space and graph\n", ucs_symbol (ch)); + if (is_space (ch) && is_xdigit (ch)) + fprintf (stderr, "%s is space and xdigit\n", ucs_symbol (ch)); + + /* cntrl restriction: "No character specified for the keywords upper, + lower, alpha, digit, punct, graph, print or xdigit shall be + specified." upper, lower, alpha already checked above. */ + if (is_cntrl (ch) && is_digit (ch)) + fprintf (stderr, "%s is cntrl and digit\n", ucs_symbol (ch)); + if (is_cntrl (ch) && is_punct (ch)) + fprintf (stderr, "%s is cntrl and punct\n", ucs_symbol (ch)); + if (is_cntrl (ch) && is_graph (ch)) + fprintf (stderr, "%s is cntrl and graph\n", ucs_symbol (ch)); + if (is_cntrl (ch) && is_print (ch)) + fprintf (stderr, "%s is cntrl and print\n", ucs_symbol (ch)); + if (is_cntrl (ch) && is_xdigit (ch)) + fprintf (stderr, "%s is cntrl and xdigit\n", ucs_symbol (ch)); + + /* punct restriction: "No character specified for the keywords upper, + lower, alpha, digit, cntrl, xdigit or as the character shall + be specified." upper, lower, alpha, cntrl already checked above. */ + if (is_punct (ch) && is_digit (ch)) + fprintf (stderr, "%s is punct and digit\n", ucs_symbol (ch)); + if (is_punct (ch) && is_xdigit (ch)) + fprintf (stderr, "%s is punct and xdigit\n", ucs_symbol (ch)); + if (is_punct (ch) && (ch == 0x0020)) + fprintf (stderr, "%s is punct\n", ucs_symbol (ch)); + + /* graph restriction: "No character specified for the keyword cntrl + shall be specified." Already checked above. */ + + /* print restriction: "No character specified for the keyword cntrl + shall be specified." Already checked above. */ + + /* graph - print relation: differ only in the character. + How is this possible if there are more than one space character?! + I think susv2/xbd/locale.html should speak of "space characters", + not "space character". */ + if (is_print (ch) && !(is_graph (ch) || /* ch == 0x0020 */ is_space (ch))) + fprintf (stderr, + "%s is print but not graph|\n", ucs_symbol (ch)); + if (!is_print (ch) && (is_graph (ch) || ch == 0x0020)) + fprintf (stderr, + "%s is graph| but not print\n", ucs_symbol (ch)); + } + + fprintf (stream, "LC_CTYPE\n"); + output_charclass (stream, "upper", is_upper); + output_charclass (stream, "lower", is_lower); + output_charclass (stream, "alpha", is_alpha); + output_charclass (stream, "digit", is_digit); + output_charclass (stream, "outdigit", is_outdigit); + output_charclass (stream, "blank", is_blank); + output_charclass (stream, "space", is_space); + output_charclass (stream, "cntrl", is_cntrl); + output_charclass (stream, "punct", is_punct); + output_charclass (stream, "xdigit", is_xdigit); + output_charclass (stream, "graph", is_graph); + output_charclass (stream, "print", is_print); + output_charclass (stream, "class \"combining\";", is_combining); + output_charclass (stream, "class \"combining_level3\";", is_combining_level3); + output_charmap (stream, "toupper", to_upper); + output_charmap (stream, "tolower", to_lower); + output_charmap (stream, "map \"totitle\";", to_title); + output_widthmap (stream); + fprintf (stream, "END LC_CTYPE\n"); + + if (ferror (stream) || fclose (stream)) + { + fprintf (stderr, "error writing to '%s'\n", filename); + exit (1); + } +} + +int +main (int argc, char * argv[]) +{ + if (argc != 3) + { + fprintf (stderr, "Usage: %s UnicodeData.txt version\n", argv[0]); + exit (1); + } + + fill_attributes (argv[1]); + + output_tables ("unicode", argv[2]); + + return 0; +} diff --git a/test/locale/show-ucs-data.c b/test/locale/show-ucs-data.c new file mode 100644 index 0000000..9992ece --- /dev/null +++ b/test/locale/show-ucs-data.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + int n; + char *line = NULL; + size_t len = 0; + + for (n = 1; n < argc; ++n) + { + FILE *fp = fopen (argv[n], "r"); + if (fp == NULL) + continue; + + while (! feof (fp)) + { + ssize_t cnt = getline (&line, &len, fp); + char *runp; + if (cnt <= 0) + break; + + runp = line; + do + { + if (runp[0] == '<' && runp[1] == 'U' && isxdigit (runp[2]) + && isxdigit (runp[3]) && isxdigit (runp[4]) + && isxdigit (runp[5]) && runp[6] == '>') + { + unsigned int val = strtoul (runp + 2, NULL, 16); + + //putchar ('<'); + if (val < 128) + putchar (val); + else if (val < 0x800) + { + putchar (0xc0 | (val >> 6)); + putchar (0x80 | (val & 0x3f)); + } + else + { + putchar (0xe0 | (val >> 12)); + putchar (0x80 | ((val >> 6) & 0x3f)); + putchar (0x80 | (val & 0x3f)); + } + //putchar ('>'); + runp += 7; + } + else + putchar (*runp++); + } + while (runp < &line[cnt]); + } + + fclose (fp); + } + + return 0; +} diff --git a/test/locale/tst-C-locale.c b/test/locale/tst-C-locale.c new file mode 100644 index 0000000..c568cf4 --- /dev/null +++ b/test/locale/tst-C-locale.c @@ -0,0 +1,498 @@ +/* Tests of C and POSIX locale contents. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +static int +run_test (const char *locname) +{ + struct lconv *lc; + const char *str; + const wchar_t *wstr; + int result = 0; + locale_t loc; + + /* ISO C stuff. */ + lc = localeconv (); + if (lc == NULL) + { + printf ("localeconv failed for locale %s\n", locname); + result = 1; + } + else + { +#define STRTEST(name, exp) \ + do \ + if (strcmp (lc->name, exp) != 0) \ + { \ + printf (#name " in locale %s wrong (is \"%s\", should be \"%s\")\n",\ + locname, lc->name, exp); \ + result = 1; \ + } \ + while (0) + STRTEST (decimal_point, "."); + STRTEST (thousands_sep, ""); + STRTEST (grouping, ""); + STRTEST (mon_decimal_point, ""); + STRTEST (mon_thousands_sep, ""); + STRTEST (mon_grouping, ""); + STRTEST (positive_sign, ""); + STRTEST (negative_sign, ""); + STRTEST (currency_symbol, ""); + STRTEST (int_curr_symbol, ""); + +#define CHARTEST(name, exp) \ + do \ + if (lc->name != exp) \ + { \ + printf (#name " in locale %s wrong (is %d, should be %d)\n", \ + locname, lc->name, CHAR_MAX); \ + result = 1; \ + } \ + while (0) + CHARTEST (frac_digits, CHAR_MAX); + CHARTEST (p_cs_precedes, CHAR_MAX); + CHARTEST (n_cs_precedes, CHAR_MAX); + CHARTEST (p_sep_by_space, CHAR_MAX); + CHARTEST (n_sep_by_space, CHAR_MAX); + CHARTEST (p_sign_posn, CHAR_MAX); + CHARTEST (n_sign_posn, CHAR_MAX); + CHARTEST (int_frac_digits, CHAR_MAX); + CHARTEST (int_p_cs_precedes, CHAR_MAX); + CHARTEST (int_n_cs_precedes, CHAR_MAX); + CHARTEST (int_p_sep_by_space, CHAR_MAX); + CHARTEST (int_n_sep_by_space, CHAR_MAX); + CHARTEST (int_p_sign_posn, CHAR_MAX); + CHARTEST (int_n_sign_posn, CHAR_MAX); + } + +#undef STRTEST +#define STRTEST(name, exp) \ + str = nl_langinfo (name); \ + if (strcmp (str, exp) != 0) \ + { \ + printf ("nl_langinfo(" #name ") in locale %s wrong " \ + "(is \"%s\", should be \"%s\")\n", locname, str, exp); \ + result = 1; \ + } +#define WSTRTEST(name, exp) \ + wstr = (wchar_t *) nl_langinfo (name); \ + if (wcscmp (wstr, exp) != 0) \ + { \ + printf ("nl_langinfo(" #name ") in locale %s wrong " \ + "(is \"%S\", should be \"%S\")\n", locname, wstr, exp); \ + result = 1; \ + } + + /* Unix stuff. */ + STRTEST (ABDAY_1, "Sun"); + STRTEST (ABDAY_2, "Mon"); + STRTEST (ABDAY_3, "Tue"); + STRTEST (ABDAY_4, "Wed"); + STRTEST (ABDAY_5, "Thu"); + STRTEST (ABDAY_6, "Fri"); + STRTEST (ABDAY_7, "Sat"); + STRTEST (DAY_1, "Sunday"); + STRTEST (DAY_2, "Monday"); + STRTEST (DAY_3, "Tuesday"); + STRTEST (DAY_4, "Wednesday"); + STRTEST (DAY_5, "Thursday"); + STRTEST (DAY_6, "Friday"); + STRTEST (DAY_7, "Saturday"); + STRTEST (ABMON_1, "Jan"); + STRTEST (ABMON_2, "Feb"); + STRTEST (ABMON_3, "Mar"); + STRTEST (ABMON_4, "Apr"); + STRTEST (ABMON_5, "May"); + STRTEST (ABMON_6, "Jun"); + STRTEST (ABMON_7, "Jul"); + STRTEST (ABMON_8, "Aug"); + STRTEST (ABMON_9, "Sep"); + STRTEST (ABMON_10, "Oct"); + STRTEST (ABMON_11, "Nov"); + STRTEST (ABMON_12, "Dec"); + STRTEST (MON_1, "January"); + STRTEST (MON_2, "February"); + STRTEST (MON_3, "March"); + STRTEST (MON_4, "April"); + STRTEST (MON_5, "May"); + STRTEST (MON_6, "June"); + STRTEST (MON_7, "July"); + STRTEST (MON_8, "August"); + STRTEST (MON_9, "September"); + STRTEST (MON_10, "October"); + STRTEST (MON_11, "November"); + STRTEST (MON_12, "December"); + STRTEST (AM_STR, "AM"); + STRTEST (PM_STR, "PM"); + STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y"); + STRTEST (D_FMT, "%m/%d/%y"); + STRTEST (T_FMT, "%H:%M:%S"); + STRTEST (T_FMT_AMPM, "%I:%M:%S %p"); + STRTEST (ERA, ""); + STRTEST (ERA_D_FMT, ""); + STRTEST (ERA_T_FMT, ""); + STRTEST (ERA_D_T_FMT, ""); + STRTEST (ALT_DIGITS, ""); + + STRTEST (RADIXCHAR, "."); + STRTEST (THOUSEP, ""); + + STRTEST (YESEXPR, "^[yY]"); + STRTEST (NOEXPR, "^[nN]"); + + /* Extensions. */ + WSTRTEST (_NL_WABDAY_1, L"Sun"); + WSTRTEST (_NL_WABDAY_2, L"Mon"); + WSTRTEST (_NL_WABDAY_3, L"Tue"); + WSTRTEST (_NL_WABDAY_4, L"Wed"); + WSTRTEST (_NL_WABDAY_5, L"Thu"); + WSTRTEST (_NL_WABDAY_6, L"Fri"); + WSTRTEST (_NL_WABDAY_7, L"Sat"); + WSTRTEST (_NL_WDAY_1, L"Sunday"); + WSTRTEST (_NL_WDAY_2, L"Monday"); + WSTRTEST (_NL_WDAY_3, L"Tuesday"); + WSTRTEST (_NL_WDAY_4, L"Wednesday"); + WSTRTEST (_NL_WDAY_5, L"Thursday"); + WSTRTEST (_NL_WDAY_6, L"Friday"); + WSTRTEST (_NL_WDAY_7, L"Saturday"); + WSTRTEST (_NL_WABMON_1, L"Jan"); + WSTRTEST (_NL_WABMON_2, L"Feb"); + WSTRTEST (_NL_WABMON_3, L"Mar"); + WSTRTEST (_NL_WABMON_4, L"Apr"); + WSTRTEST (_NL_WABMON_5, L"May"); + WSTRTEST (_NL_WABMON_6, L"Jun"); + WSTRTEST (_NL_WABMON_7, L"Jul"); + WSTRTEST (_NL_WABMON_8, L"Aug"); + WSTRTEST (_NL_WABMON_9, L"Sep"); + WSTRTEST (_NL_WABMON_10, L"Oct"); + WSTRTEST (_NL_WABMON_11, L"Nov"); + WSTRTEST (_NL_WABMON_12, L"Dec"); + WSTRTEST (_NL_WMON_1, L"January"); + WSTRTEST (_NL_WMON_2, L"February"); + WSTRTEST (_NL_WMON_3, L"March"); + WSTRTEST (_NL_WMON_4, L"April"); + WSTRTEST (_NL_WMON_5, L"May"); + WSTRTEST (_NL_WMON_6, L"June"); + WSTRTEST (_NL_WMON_7, L"July"); + WSTRTEST (_NL_WMON_8, L"August"); + WSTRTEST (_NL_WMON_9, L"September"); + WSTRTEST (_NL_WMON_10, L"October"); + WSTRTEST (_NL_WMON_11, L"November"); + WSTRTEST (_NL_WMON_12, L"December"); + WSTRTEST (_NL_WAM_STR, L"AM"); + WSTRTEST (_NL_WPM_STR, L"PM"); + WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y"); + WSTRTEST (_NL_WD_FMT, L"%m/%d/%y"); + WSTRTEST (_NL_WT_FMT, L"%H:%M:%S"); + WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p"); + WSTRTEST (_NL_WERA_D_FMT, L""); + WSTRTEST (_NL_WERA_T_FMT, L""); + WSTRTEST (_NL_WERA_D_T_FMT, L""); + WSTRTEST (_NL_WALT_DIGITS, L""); + + STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y"); + WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y"); + + STRTEST (INT_CURR_SYMBOL, ""); + STRTEST (CURRENCY_SYMBOL, ""); + STRTEST (MON_DECIMAL_POINT, ""); + STRTEST (MON_THOUSANDS_SEP, ""); + STRTEST (MON_GROUPING, ""); + STRTEST (POSITIVE_SIGN, ""); + STRTEST (NEGATIVE_SIGN, ""); + STRTEST (GROUPING, ""); + + STRTEST (YESSTR, ""); + STRTEST (NOSTR, ""); + + /* Test the new locale mechanisms. */ + loc = newlocale (LC_ALL_MASK, locname, NULL); + if (loc == NULL) + { + printf ("cannot create locale object for locale %s\n", locname); + result = 1; + } + else + { + int c; + +#undef STRTEST +#define STRTEST(name, exp) \ + str = nl_langinfo_l (name, loc); \ + if (strcmp (str, exp) != 0) \ + { \ + printf ("nl_langinfo_l(" #name ") in locale %s wrong " \ + "(is \"%s\", should be \"%s\")\n", locname, str, exp); \ + result = 1; \ + } +#undef WSTRTEST +#define WSTRTEST(name, exp) \ + wstr = (wchar_t *) nl_langinfo_l (name, loc); \ + if (wcscmp (wstr, exp) != 0) \ + { \ + printf ("nl_langinfo_l(" #name ") in locale %s wrong " \ + "(is \"%S\", should be \"%S\")\n", locname, wstr, exp); \ + result = 1; \ + } + + /* Unix stuff. */ + STRTEST (ABDAY_1, "Sun"); + STRTEST (ABDAY_2, "Mon"); + STRTEST (ABDAY_3, "Tue"); + STRTEST (ABDAY_4, "Wed"); + STRTEST (ABDAY_5, "Thu"); + STRTEST (ABDAY_6, "Fri"); + STRTEST (ABDAY_7, "Sat"); + STRTEST (DAY_1, "Sunday"); + STRTEST (DAY_2, "Monday"); + STRTEST (DAY_3, "Tuesday"); + STRTEST (DAY_4, "Wednesday"); + STRTEST (DAY_5, "Thursday"); + STRTEST (DAY_6, "Friday"); + STRTEST (DAY_7, "Saturday"); + STRTEST (ABMON_1, "Jan"); + STRTEST (ABMON_2, "Feb"); + STRTEST (ABMON_3, "Mar"); + STRTEST (ABMON_4, "Apr"); + STRTEST (ABMON_5, "May"); + STRTEST (ABMON_6, "Jun"); + STRTEST (ABMON_7, "Jul"); + STRTEST (ABMON_8, "Aug"); + STRTEST (ABMON_9, "Sep"); + STRTEST (ABMON_10, "Oct"); + STRTEST (ABMON_11, "Nov"); + STRTEST (ABMON_12, "Dec"); + STRTEST (MON_1, "January"); + STRTEST (MON_2, "February"); + STRTEST (MON_3, "March"); + STRTEST (MON_4, "April"); + STRTEST (MON_5, "May"); + STRTEST (MON_6, "June"); + STRTEST (MON_7, "July"); + STRTEST (MON_8, "August"); + STRTEST (MON_9, "September"); + STRTEST (MON_10, "October"); + STRTEST (MON_11, "November"); + STRTEST (MON_12, "December"); + STRTEST (AM_STR, "AM"); + STRTEST (PM_STR, "PM"); + STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y"); + STRTEST (D_FMT, "%m/%d/%y"); + STRTEST (T_FMT, "%H:%M:%S"); + STRTEST (T_FMT_AMPM, "%I:%M:%S %p"); + STRTEST (ERA, ""); + STRTEST (ERA_D_FMT, ""); + STRTEST (ERA_T_FMT, ""); + STRTEST (ERA_D_T_FMT, ""); + STRTEST (ALT_DIGITS, ""); + + STRTEST (RADIXCHAR, "."); + STRTEST (THOUSEP, ""); + + STRTEST (YESEXPR, "^[yY]"); + STRTEST (NOEXPR, "^[nN]"); + + /* Extensions. */ + WSTRTEST (_NL_WABDAY_1, L"Sun"); + WSTRTEST (_NL_WABDAY_2, L"Mon"); + WSTRTEST (_NL_WABDAY_3, L"Tue"); + WSTRTEST (_NL_WABDAY_4, L"Wed"); + WSTRTEST (_NL_WABDAY_5, L"Thu"); + WSTRTEST (_NL_WABDAY_6, L"Fri"); + WSTRTEST (_NL_WABDAY_7, L"Sat"); + WSTRTEST (_NL_WDAY_1, L"Sunday"); + WSTRTEST (_NL_WDAY_2, L"Monday"); + WSTRTEST (_NL_WDAY_3, L"Tuesday"); + WSTRTEST (_NL_WDAY_4, L"Wednesday"); + WSTRTEST (_NL_WDAY_5, L"Thursday"); + WSTRTEST (_NL_WDAY_6, L"Friday"); + WSTRTEST (_NL_WDAY_7, L"Saturday"); + WSTRTEST (_NL_WABMON_1, L"Jan"); + WSTRTEST (_NL_WABMON_2, L"Feb"); + WSTRTEST (_NL_WABMON_3, L"Mar"); + WSTRTEST (_NL_WABMON_4, L"Apr"); + WSTRTEST (_NL_WABMON_5, L"May"); + WSTRTEST (_NL_WABMON_6, L"Jun"); + WSTRTEST (_NL_WABMON_7, L"Jul"); + WSTRTEST (_NL_WABMON_8, L"Aug"); + WSTRTEST (_NL_WABMON_9, L"Sep"); + WSTRTEST (_NL_WABMON_10, L"Oct"); + WSTRTEST (_NL_WABMON_11, L"Nov"); + WSTRTEST (_NL_WABMON_12, L"Dec"); + WSTRTEST (_NL_WMON_1, L"January"); + WSTRTEST (_NL_WMON_2, L"February"); + WSTRTEST (_NL_WMON_3, L"March"); + WSTRTEST (_NL_WMON_4, L"April"); + WSTRTEST (_NL_WMON_5, L"May"); + WSTRTEST (_NL_WMON_6, L"June"); + WSTRTEST (_NL_WMON_7, L"July"); + WSTRTEST (_NL_WMON_8, L"August"); + WSTRTEST (_NL_WMON_9, L"September"); + WSTRTEST (_NL_WMON_10, L"October"); + WSTRTEST (_NL_WMON_11, L"November"); + WSTRTEST (_NL_WMON_12, L"December"); + WSTRTEST (_NL_WAM_STR, L"AM"); + WSTRTEST (_NL_WPM_STR, L"PM"); + WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y"); + WSTRTEST (_NL_WD_FMT, L"%m/%d/%y"); + WSTRTEST (_NL_WT_FMT, L"%H:%M:%S"); + WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p"); + WSTRTEST (_NL_WERA_D_FMT, L""); + WSTRTEST (_NL_WERA_T_FMT, L""); + WSTRTEST (_NL_WERA_D_T_FMT, L""); + WSTRTEST (_NL_WALT_DIGITS, L""); + + STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y"); + WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y"); + + STRTEST (INT_CURR_SYMBOL, ""); + STRTEST (CURRENCY_SYMBOL, ""); + STRTEST (MON_DECIMAL_POINT, ""); + STRTEST (MON_THOUSANDS_SEP, ""); + STRTEST (MON_GROUPING, ""); + STRTEST (POSITIVE_SIGN, ""); + STRTEST (NEGATIVE_SIGN, ""); + STRTEST (GROUPING, ""); + + STRTEST (YESSTR, ""); + STRTEST (NOSTR, ""); + + /* Character class tests. */ + for (c = 0; c < 128; ++c) + { +#define CLASSTEST(name) \ + if (is##name (c) != is##name##_l (c, loc)) \ + { \ + printf ("is%s('\\%o') != is%s_l('\\%o')\n", \ + #name, c, #name, c); \ + result = 1; \ + } + CLASSTEST (alnum); + CLASSTEST (alpha); + CLASSTEST (blank); + CLASSTEST (cntrl); + CLASSTEST (digit); + CLASSTEST (lower); + CLASSTEST (graph); + CLASSTEST (print); + CLASSTEST (punct); + CLASSTEST (space); + CLASSTEST (upper); + CLASSTEST (xdigit); + + /* Character mapping tests. */ +#define MAPTEST(name) \ + if (to##name (c) != to##name##_l (c, loc)) \ + { \ + printf ("to%s('\\%o') != to%s_l('\\%o'): '\\%o' vs '\\%o'\n", \ + #name, c, #name, c, \ + to##name (c), to##name##_l (c, loc)); \ + result = 1; \ + } + MAPTEST (lower); + MAPTEST (upper); + } + + /* Character class tests, this time for wide characters. Note that + this only works because we know that the internal encoding is + UCS4. */ + for (c = 0; c < 128; ++c) + { +#undef CLASSTEST +#define CLASSTEST(name) \ + if (isw##name (c) != isw##name##_l (c, loc)) \ + { \ + printf ("isw%s('\\%o') != isw%s_l('\\%o')\n", \ + #name, c, #name, c); \ + result = 1; \ + } + CLASSTEST (alnum); + CLASSTEST (alpha); + CLASSTEST (blank); + CLASSTEST (cntrl); + CLASSTEST (digit); + CLASSTEST (lower); + CLASSTEST (graph); + CLASSTEST (print); + CLASSTEST (punct); + CLASSTEST (space); + CLASSTEST (upper); + CLASSTEST (xdigit); + + /* Character mapping tests. Note that + this only works because we know that the internal encoding is + UCS4. */ +#undef MAPTEST +#define MAPTEST(name) \ + if (tow##name (c) != tow##name##_l (c, loc)) \ + { \ + printf ("tow%s('\\%o') != tow%s_l('\\%o'): '\\%o' vs '\\%o'\n",\ + #name, c, #name, c, \ + tow##name (c), tow##name##_l (c, loc)); \ + result = 1; \ + } + MAPTEST (lower); + MAPTEST (upper); + } + + freelocale (loc); + } + + return result; +} + + +static int +do_test (void) +{ + int result; + + /* First use the name "C". */ + if (setlocale (LC_ALL, "C") == NULL) + { + puts ("cannot set C locale"); + result = 1; + } + else + result = run_test ("C"); + + /* Then the name "POSIX". */ + if (setlocale (LC_ALL, "POSIX") == NULL) + { + puts ("cannot set POSIX locale"); + result = 1; + } + else + result |= run_test ("POSIX"); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/locale/tst-ctype-de_DE.ISO-8859-1.in b/test/locale/tst-ctype-de_DE.ISO-8859-1.in new file mode 100644 index 0000000..f71d76c --- /dev/null +++ b/test/locale/tst-ctype-de_DE.ISO-8859-1.in @@ -0,0 +1,56 @@ +lower  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000100000000000000000000000000 +lower ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000111111111111111111111111011111111 +upper  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000001111111111111111 +upper ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 111111101111111000000000000000000000000000000000 +alpha  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000010000000000100001000001111111111111111 +alpha ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 111111101111111111111111111111111111111011111111 +digit  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000000000000000000000 +digit ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000000000000000000000000000000000000 +xdigit  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000000000000000000000 +xdigit ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000000000000000000000000000000000000 +space  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000000000000000000000 +space ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000000000000000000000000000000000000 +print  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 111111111111111111111111111111111111111111111111 +print ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 111111111111111111111111111111111111111111111111 +graph  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 111111111111111111111111111111111111111111111111 +graph ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 111111111111111111111111111111111111111111111111 +blank  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000000000000000000000 +blank ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000000000000000000000000000000000000 +cntrl  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000000000000000000000000000000000000000000 +cntrl ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000000000000000000000000000000000000000000000 +punct  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 111111111101111111111011110111110000000000000000 +punct ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 000000010000000000000000000000000000000100000000 +alnum  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ + 000000000010000000000100001000001111111111111111 +alnum ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + 111111101111111111111111111111111111111011111111 +tolower  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ +  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæçèéêëìíîï +tolower ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ðñòóôõö×øùúûüýþßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ +toupper  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ +  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ +toupper ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ + ÐÑÒÓÔÕÖרÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞÿ diff --git a/test/locale/tst-ctype.c b/test/locale/tst-ctype.c new file mode 100644 index 0000000..c03c2da --- /dev/null +++ b/test/locale/tst-ctype.c @@ -0,0 +1,447 @@ +/* Copyright (C) 2000,02, 05 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +static const char lower[] = "abcdefghijklmnopqrstuvwxyz"; +static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const char digits[] = "0123456789"; +static const char cntrl[] = "\ +\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\ +\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f "; + + +static struct classes +{ + const char *name; + int mask; +} classes[] = +{ +#define ENTRY(name) { #name, _IS##name } + ENTRY (upper), + ENTRY (lower), + ENTRY (alpha), + ENTRY (digit), + ENTRY (xdigit), + ENTRY (space), + ENTRY (print), + ENTRY (graph), + ENTRY (blank), + ENTRY (cntrl), + ENTRY (punct), + ENTRY (alnum) +}; +#define nclasses (sizeof (classes) / sizeof (classes[0])) + + +#define FAIL(str, args...) \ + { \ + printf (" " str "\n", ##args); \ + ++errors; \ + } + + +int +main (void) +{ + const char *cp; + const char *cp2; + int errors = 0; + char *inpline = NULL; + size_t inplinelen = 0; + char *resline = NULL; + size_t reslinelen = 0; + size_t n; + + setlocale (LC_ALL, ""); + + printf ("Testing the ctype data of the `%s' locale\n", + setlocale (LC_CTYPE, NULL)); + +#if 0 + /* Just for debugging. */ + + /* Contents of the class array. */ + printf ("\ +upper = %04x lower = %04x alpha = %04x digit = %04x xdigit = %04x\n\ +space = %04x print = %04x graph = %04x blank = %04x cntrl = %04x\n\ +punct = %04x alnum = %04x\n", + _ISupper, _ISlower, _ISalpha, _ISdigit, _ISxdigit, + _ISspace, _ISprint, _ISgraph, _ISblank, _IScntrl, + _ISpunct, _ISalnum); + + while (n < 256) + { + if (n % 8 == 0) + printf ("%02x: ", n); + printf ("%04x%s", __ctype_b[n], (n + 1) % 8 == 0 ? "\n" : " "); + ++n; + } +#endif + + puts (" Test of ASCII character range\n special NUL byte handling"); + if (isupper ('\0')) + FAIL ("isupper ('\\0') is true"); + if (islower ('\0')) + FAIL ("islower ('\\0') is true"); + if (isalpha ('\0')) + FAIL ("isalpha ('\\0') is true"); + if (isdigit ('\0')) + FAIL ("isdigit ('\\0') is true"); + if (isxdigit ('\0')) + FAIL ("isxdigit ('\\0') is true"); + if (isspace ('\0')) + FAIL ("isspace ('\\0') is true"); + if (isprint ('\0')) + FAIL ("isprint ('\\0') is true"); + if (isgraph ('\0')) + FAIL ("isgraph ('\\0') is true"); + if (isblank ('\0')) + FAIL ("isblank ('\\0') is true"); + if (! iscntrl ('\0')) + FAIL ("iscntrl ('\\0') not true"); + if (ispunct ('\0')) + FAIL ("ispunct ('\\0') is true"); + if (isalnum ('\0')) + FAIL ("isalnum ('\\0') is true"); + + puts (" islower()"); + for (cp = lower; *cp != '\0'; ++cp) + if (! islower (*cp)) + FAIL ("islower ('%c') not true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (islower (*cp)) + FAIL ("islower ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (islower (*cp)) + FAIL ("islower ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (islower (*cp)) + FAIL ("islower ('\\x%02x') is true", *cp); + + puts (" isupper()"); + for (cp = lower; *cp != '\0'; ++cp) + if (isupper (*cp)) + FAIL ("isupper ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (! isupper (*cp)) + FAIL ("isupper ('%c') not true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (isupper (*cp)) + FAIL ("isupper ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isupper (*cp)) + FAIL ("isupper ('\\x%02x') is true", *cp); + + puts (" isalpha()"); + for (cp = lower; *cp != '\0'; ++cp) + if (! isalpha (*cp)) + FAIL ("isalpha ('%c') not true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (! isalpha (*cp)) + FAIL ("isalpha ('%c') not true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (isalpha (*cp)) + FAIL ("isalpha ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isalpha (*cp)) + FAIL ("isalpha ('\\x%02x') is true", *cp); + + puts (" isdigit()"); + for (cp = lower; *cp != '\0'; ++cp) + if (isdigit (*cp)) + FAIL ("isdigit ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (isdigit (*cp)) + FAIL ("isdigit ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (! isdigit (*cp)) + FAIL ("isdigit ('%c') not true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isdigit (*cp)) + FAIL ("isdigit ('\\x%02x') is true", *cp); + + puts (" isxdigit()"); + for (cp = lower; *cp != '\0'; ++cp) + if ((! isxdigit (*cp) && cp - lower < 6) + || (isxdigit (*cp) && cp - lower >= 6)) + FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is"); + for (cp = upper; *cp != '\0'; ++cp) + if ((! isxdigit (*cp) && cp - upper < 6) + || (isxdigit (*cp) && cp - upper >= 6)) + FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is"); + for (cp = digits; *cp != '\0'; ++cp) + if (! isxdigit (*cp)) + FAIL ("isxdigit ('%c') not true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isxdigit (*cp)) + FAIL ("isxdigit ('\\x%02x') is true", *cp); + + puts (" isspace()"); + for (cp = lower; *cp != '\0'; ++cp) + if (isspace (*cp)) + FAIL ("isspace ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (isspace (*cp)) + FAIL ("isspace ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (isspace (*cp)) + FAIL ("isspace ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if ((isspace (*cp) && ((*cp < '\x09' || *cp > '\x0d') && *cp != ' ')) + || (! isspace (*cp) + && ((*cp >= '\x09' && *cp <= '\x0d') || *cp == ' '))) + FAIL ("isspace ('\\x%02x') %s true", *cp, + (*cp < '\x09' || *cp > '\x0d') ? "is" : "not"); + + puts (" isprint()"); + for (cp = lower; *cp != '\0'; ++cp) + if (! isprint (*cp)) + FAIL ("isprint ('%c') not true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (! isprint (*cp)) + FAIL ("isprint ('%c') not true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (! isprint (*cp)) + FAIL ("isprint ('%c') not true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if ((isprint (*cp) && *cp != ' ') + || (! isprint (*cp) && *cp == ' ')) + FAIL ("isprint ('\\x%02x') is true", *cp); + + puts (" isgraph()"); + for (cp = lower; *cp != '\0'; ++cp) + if (! isgraph (*cp)) + FAIL ("isgraph ('%c') not true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (! isgraph (*cp)) + FAIL ("isgraph ('%c') not true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (! isgraph (*cp)) + FAIL ("isgraph ('%c') not true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isgraph (*cp)) + FAIL ("isgraph ('\\x%02x') is true", *cp); + + puts (" isblank()"); + for (cp = lower; *cp != '\0'; ++cp) + if (isblank (*cp)) + FAIL ("isblank ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (isblank (*cp)) + FAIL ("isblank ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (isblank (*cp)) + FAIL ("isblank ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if ((isblank (*cp) && *cp != '\x09' && *cp != ' ') + || (! isblank (*cp) && (*cp == '\x09' || *cp == ' '))) + FAIL ("isblank ('\\x%02x') %s true", *cp, *cp != '\x09' ? "is" : "not"); + + puts (" iscntrl()"); + for (cp = lower; *cp != '\0'; ++cp) + if (iscntrl (*cp)) + FAIL ("iscntrl ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (iscntrl (*cp)) + FAIL ("iscntrl ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (iscntrl (*cp)) + FAIL ("iscntrl ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if ((iscntrl (*cp) && *cp == ' ') + || (! iscntrl (*cp) && *cp != ' ')) + FAIL ("iscntrl ('\\x%02x') not true", *cp); + + puts (" ispunct()"); + for (cp = lower; *cp != '\0'; ++cp) + if (ispunct (*cp)) + FAIL ("ispunct ('%c') is true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (ispunct (*cp)) + FAIL ("ispunct ('%c') is true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (ispunct (*cp)) + FAIL ("ispunct ('%c') is true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (ispunct (*cp)) + FAIL ("ispunct ('\\x%02x') is true", *cp); + + puts (" isalnum()"); + for (cp = lower; *cp != '\0'; ++cp) + if (! isalnum (*cp)) + FAIL ("isalnum ('%c') not true", *cp); + for (cp = upper; *cp != '\0'; ++cp) + if (! isalnum (*cp)) + FAIL ("isalnum ('%c') not true", *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (! isalnum (*cp)) + FAIL ("isalnum ('%c') not true", *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (isalnum (*cp)) + FAIL ("isalnum ('\\x%02x') is true", *cp); + + + puts (" tolower()"); + for (cp = lower; *cp != '\0'; ++cp) + if (tolower (*cp) != *cp) + FAIL ("tolower ('%c') != '%c'", *cp, *cp); + for (cp = upper, cp2 = lower; *cp != '\0'; ++cp, ++cp2) + if (tolower (*cp) != *cp2) + FAIL ("tolower ('%c') != '%c'", *cp, *cp2); + for (cp = digits; *cp != '\0'; ++cp) + if (tolower (*cp) != *cp) + FAIL ("tolower ('%c') != '%c'", *cp, *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (tolower (*cp) != *cp) + FAIL ("tolower ('\\x%02x') != '\\x%02x'", *cp, *cp); + + puts (" toupper()"); + for (cp = lower, cp2 = upper; *cp != '\0'; ++cp, ++cp2) + if (toupper (*cp) != *cp2) + FAIL ("toupper ('%c') != '%c'", *cp, *cp2); + for (cp = upper; *cp != '\0'; ++cp) + if (toupper (*cp) != *cp) + FAIL ("toupper ('%c') != '%c'", *cp, *cp); + for (cp = digits; *cp != '\0'; ++cp) + if (toupper (*cp) != *cp) + FAIL ("toupper ('%c') != '%c'", *cp, *cp); + for (cp = cntrl; *cp != '\0'; ++cp) + if (toupper (*cp) != *cp) + FAIL ("toupper ('\\x%02x') != '\\x%02x'", *cp, *cp); + + + /* Now some locale specific tests. */ + while (! feof (stdin)) + { + unsigned char *inp; + unsigned char *resp; + + if (getline (&inpline, &inplinelen, stdin) <= 0 + || getline (&resline, &reslinelen, stdin) <= 0) + break; + + inp = (unsigned char *) strchr (inpline, '\n'); + if (inp != NULL) + *inp = '\0'; + resp = (unsigned char *) strchr (resline, '\n'); + if (resp != NULL) + *resp = '\0'; + + inp = (unsigned char *) inpline; + while (*inp != ' ' && *inp != '\t' && *inp && *inp != '\n' + && *inp != '\0') + ++inp; + + if (*inp == '\0') + { + printf ("line \"%s\" is without content\n", inpline); + continue; + } + *inp++ = '\0'; + while (*inp == ' ' || *inp == '\t') + ++inp; + + /* Try all classes. */ + for (n = 0; n < nclasses; ++n) + if (strcmp (inpline, classes[n].name) == 0) + break; + + resp = (unsigned char *) resline; + while (*resp == ' ' || *resp == '\t') + ++resp; + + if (strlen ((char *) inp) != strlen ((char *) resp)) + { + printf ("lines \"%.20s\"... and \"%.20s\" have not the same length\n", + inp, resp); + continue; + } + + if (n < nclasses) + { + if (strspn ((char *) resp, "01") != strlen ((char *) resp)) + { + printf ("result string \"%s\" malformed\n", resp); + continue; + } + + printf (" Locale-specific tests for `%s'\n", inpline); + + while (*inp != '\0' && *inp != '\n') + { + if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0) + != (*resp != '0')) + { + printf (" is%s('%c' = '\\x%02x') %s true\n", inpline, + *inp, *inp, *resp == '1' ? "not" : "is"); + ++errors; + } + ++inp; + ++resp; + } + } + else if (strcmp (inpline, "tolower") == 0) + { + while (*inp != '\0') + { + if (tolower (*inp) != *resp) + { + printf (" tolower('%c' = '\\x%02x') != '%c'\n", + *inp, *inp, *resp); + ++errors; + } + ++inp; + ++resp; + } + } + else if (strcmp (inpline, "toupper") == 0) + { + while (*inp != '\0') + { + if (toupper (*inp) != *resp) + { + printf (" toupper('%c' = '\\x%02x') != '%c'\n", + *inp, *inp, *resp); + ++errors; + } + ++inp; + ++resp; + } + } + else + printf ("\"%s\": unknown class or map\n", inpline); + } + + + if (errors != 0) + { + printf (" %d error%s for `%s' locale\n\n\n", errors, + errors == 1 ? "" : "s", setlocale (LC_ALL, NULL)); + return 1; + } + + printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL)); + return 0; +} diff --git a/test/locale/tst-digits.c b/test/locale/tst-digits.c new file mode 100644 index 0000000..8414a4b --- /dev/null +++ b/test/locale/tst-digits.c @@ -0,0 +1,249 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define ZERO "\xe2\x82\x80" +#define ONE "\xe2\x82\x81" +#define TWO "\xe2\x82\x82" +#define THREE "\xe2\x82\x83" +#define FOUR "\xe2\x82\x84" +#define FIVE "\xe2\x82\x85" +#define SIX "\xe2\x82\x86" +#define SEVEN "\xe2\x82\x87" +#define EIGHT "\xe2\x82\x88" +#define NINE "\xe2\x82\x89" + +static struct printf_int_test +{ + int n; + const char *format; + const char *expected; +} printf_int_tests[] = +{ + { 0, "%I'10d", " " ZERO }, + { 1, "%I'10d", " " ONE }, + { 2, "%I'10d", " " TWO }, + { 3, "%I'10d", " " THREE }, + { 4, "%I'10d", " " FOUR }, + { 5, "%I'10d", " " FIVE }, + { 6, "%I'10d", " " SIX }, + { 7, "%I'10d", " " SEVEN }, + { 8, "%I'10d", " " EIGHT }, + { 9, "%I'10d", " " NINE }, + { 11, "%I'10d", " " ONE ONE }, + { 12, "%I'10d", " " ONE TWO }, + { 123, "%I10d", " " ONE TWO THREE }, + { 123, "%I'10d", " " ONE TWO THREE }, + { 1234, "%I10d", ONE TWO THREE FOUR }, + { 1234, "%I'10d", ONE "," TWO THREE FOUR }, + { 12345, "%I'10d", ONE TWO "," THREE FOUR FIVE }, + { 123456, "%I'10d", ONE TWO THREE "," FOUR FIVE SIX }, + { 1234567, "%I'10d", ONE "," TWO THREE FOUR "," FIVE SIX SEVEN } +}; +#define nprintf_int_tests \ + (sizeof (printf_int_tests) / sizeof (printf_int_tests[0])) + +#define WZERO L"\x2080" +#define WONE L"\x2081" +#define WTWO L"\x2082" +#define WTHREE L"\x2083" +#define WFOUR L"\x2084" +#define WFIVE L"\x2085" +#define WSIX L"\x2086" +#define WSEVEN L"\x2087" +#define WEIGHT L"\x2088" +#define WNINE L"\x2089" + +static struct wprintf_int_test +{ + int n; + const wchar_t *format; + const wchar_t *expected; +} wprintf_int_tests[] = +{ + { 0, L"%I'10d", L" " WZERO }, + { 1, L"%I'10d", L" " WONE }, + { 2, L"%I'10d", L" " WTWO }, + { 3, L"%I'10d", L" " WTHREE }, + { 4, L"%I'10d", L" " WFOUR }, + { 5, L"%I'10d", L" " WFIVE }, + { 6, L"%I'10d", L" " WSIX }, + { 7, L"%I'10d", L" " WSEVEN }, + { 8, L"%I'10d", L" " WEIGHT }, + { 9, L"%I'10d", L" " WNINE }, + { 11, L"%I'10d", L" " WONE WONE }, + { 12, L"%I'10d", L" " WONE WTWO }, + { 123, L"%I10d", L" " WONE WTWO WTHREE }, + { 123, L"%I'10d", L" " WONE WTWO WTHREE }, + { 1234, L"%I10d", L" " WONE WTWO WTHREE WFOUR }, + { 1234, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR }, + { 12345, L"%I'10d", L" " WONE WTWO L"," WTHREE WFOUR WFIVE }, + { 123456, L"%I'10d", L" " WONE WTWO WTHREE L"," WFOUR WFIVE WSIX }, + { 1234567, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR L"," WFIVE WSIX WSEVEN } +}; +#define nwprintf_int_tests \ + (sizeof (wprintf_int_tests) / sizeof (wprintf_int_tests[0])) + + +int +main (void) +{ + int cnt; + int failures; + int status; + + if (setlocale (LC_ALL, "test7") == NULL) + { + puts ("cannot set locale `test7'"); + exit (1); + } + printf ("CODESET = \"%s\"\n", nl_langinfo (CODESET)); + + /* First: printf tests. */ + failures = 0; + for (cnt = 0; cnt < (int) nprintf_int_tests; ++cnt) + { + char buf[100]; + ssize_t n; + + n = snprintf (buf, sizeof buf, printf_int_tests[cnt].format, + printf_int_tests[cnt].n); + + printf ("%3d: got \"%s\", expected \"%s\"", + cnt, buf, printf_int_tests[cnt].expected); + + if (n != (ssize_t) strlen (printf_int_tests[cnt].expected) + || strcmp (buf, printf_int_tests[cnt].expected) != 0) + { + puts (" -> FAILED"); + ++failures; + } + else + puts (" -> OK"); + } + + printf ("%d failures in printf tests\n", failures); + status = failures != 0; + + /* wprintf tests. */ + failures = 0; + for (cnt = 0; cnt < (int) nwprintf_int_tests; ++cnt) + { + wchar_t buf[100]; + ssize_t n; + + n = swprintf (buf, sizeof buf / sizeof (buf[0]), + wprintf_int_tests[cnt].format, + wprintf_int_tests[cnt].n); + + printf ("%3d: got \"%ls\", expected \"%ls\"", + cnt, buf, wprintf_int_tests[cnt].expected); + + if (n != (ssize_t) wcslen (wprintf_int_tests[cnt].expected) + || wcscmp (buf, wprintf_int_tests[cnt].expected) != 0) + { + puts (" -> FAILED"); + ++failures; + } + else + puts (" -> OK"); + } + + printf ("%d failures in wprintf tests\n", failures); + status = failures != 0; + + /* ctype tests. This makes sure that the multibyte chracter digit + representations are not handle in this table. */ + failures = 0; + for (cnt = 0; cnt < 256; ++cnt) + if (cnt >= '0' && cnt <= '9') + { + if (! isdigit (cnt)) + { + printf ("isdigit ('%c') == 0\n", cnt); + ++failures; + } + } + else + { + if (isdigit (cnt)) + { + printf ("isdigit (%d) != 0\n", cnt); + ++failures; + } + } + + printf ("%d failures in ctype tests\n", failures); + status = failures != 0; + + /* wctype tests. This makes sure the second set of digits is also + recorded. */ + failures = 0; + for (cnt = 0; cnt < 256; ++cnt) + if (cnt >= '0' && cnt <= '9') + { + if (! iswdigit (cnt)) + { + printf ("iswdigit (L'%c') == 0\n", cnt); + ++failures; + } + } + else + { + if (iswdigit (cnt)) + { + printf ("iswdigit (%d) != 0\n", cnt); + ++failures; + } + } + + for (cnt = 0x2070; cnt < 0x2090; ++cnt) + if (cnt >= 0x2080 && cnt <= 0x2089) + { + if (! iswdigit (cnt)) + { + printf ("iswdigit (U%04X) == 0\n", cnt); + ++failures; + } + } + else + { + if (iswdigit (cnt)) + { + printf ("iswdigit (U%04X) != 0\n", cnt); + ++failures; + } + } + + printf ("%d failures in wctype tests\n", failures); + status = failures != 0; + + return status; +} diff --git a/test/locale/tst-fmon.c b/test/locale/tst-fmon.c new file mode 100644 index 0000000..11093ce --- /dev/null +++ b/test/locale/tst-fmon.c @@ -0,0 +1,68 @@ +/* Testing the implementation of strfmon(3). + Copyright (C) 1996, 1997, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jochen Hein , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* + test-strfmon gets called with three parameters: + - the locale + - the format-string to be used + - the actual number to be formatted + - the expected string + If the test passes, test-strfmon terminates with returncode 0, + otherwise with 1 +*/ +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#define EXIT_SETLOCALE 2 +#define EXIT_STRFMON 3 + +int +main (int argc, char *argv[]) +{ + char *s = malloc (201); + + if (setlocale (LC_MONETARY, argv[1]) == NULL) + { + fprintf (stderr, "setlocale(LC_MONETARY, \"%s\"): %m\n", argv[1]); + exit (EXIT_SETLOCALE); + } + + if (strfmon (s, 200, argv[2], (double) atof (argv[3])) == -1) + { + perror ("strfmon"); + exit (EXIT_STRFMON); + } + + if (strcmp (s, argv[4]) != 0) + { + printf ("\ +Locale: \"%s\" Format: \"%s\" Value: \"%s\" Received: \"%s\" Expected: \"%s\" => %s\n", + argv[1], argv[2], argv[3], s, argv[4], + strcmp (s, argv[4]) != 0 ? "false" : "correct"); + exit (EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/test/locale/tst-langinfo.c b/test/locale/tst-langinfo.c new file mode 100644 index 0000000..e95f0da --- /dev/null +++ b/test/locale/tst-langinfo.c @@ -0,0 +1,284 @@ +/* Test program for nl_langinfo() function. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +struct map +{ + const char *str; + int val; +} map[] = +{ +#define VAL(name) { #name, name } + VAL (ABDAY_1), + VAL (ABDAY_2), + VAL (ABDAY_3), + VAL (ABDAY_4), + VAL (ABDAY_5), + VAL (ABDAY_6), + VAL (ABDAY_7), + VAL (ABMON_1), + VAL (ABMON_10), + VAL (ABMON_11), + VAL (ABMON_12), + VAL (ABMON_2), + VAL (ABMON_3), + VAL (ABMON_4), + VAL (ABMON_5), + VAL (ABMON_6), + VAL (ABMON_7), + VAL (ABMON_8), + VAL (ABMON_9), + VAL (ALT_DIGITS), + VAL (AM_STR), + VAL (CRNCYSTR), + VAL (CURRENCY_SYMBOL), + VAL (DAY_1), + VAL (DAY_2), + VAL (DAY_3), + VAL (DAY_4), + VAL (DAY_5), + VAL (DAY_6), + VAL (DAY_7), + VAL (DECIMAL_POINT), + VAL (D_FMT), + VAL (D_T_FMT), + VAL (ERA), + VAL (ERA_D_FMT), + VAL (ERA_D_T_FMT), + VAL (ERA_T_FMT), + VAL (ERA_YEAR), + VAL (FRAC_DIGITS), + VAL (GROUPING), + VAL (INT_CURR_SYMBOL), + VAL (INT_FRAC_DIGITS), + VAL (MON_1), + VAL (MON_10), + VAL (MON_11), + VAL (MON_12), + VAL (MON_2), + VAL (MON_3), + VAL (MON_4), + VAL (MON_5), + VAL (MON_6), + VAL (MON_7), + VAL (MON_8), + VAL (MON_9), + VAL (MON_DECIMAL_POINT), + VAL (MON_GROUPING), + VAL (MON_THOUSANDS_SEP), + VAL (NEGATIVE_SIGN), + VAL (NOEXPR), + VAL (NOSTR), + VAL (N_CS_PRECEDES), + VAL (N_SEP_BY_SPACE), + VAL (N_SIGN_POSN), + VAL (PM_STR), + VAL (POSITIVE_SIGN), + VAL (P_CS_PRECEDES), + VAL (P_SEP_BY_SPACE), + VAL (P_SIGN_POSN), + VAL (RADIXCHAR), + VAL (THOUSANDS_SEP), + VAL (THOUSEP), + VAL (T_FMT), + VAL (T_FMT_AMPM), + VAL (YESEXPR), + VAL (YESSTR) +}; + + +static int +map_paramstr (const char *str) +{ + int low = 0; + int high = sizeof (map) / sizeof (map[0]); + + while (low < high) + { + int med = (low + high) / 2; + int cmpres; + + cmpres = strcmp (str, map[med].str); + if (cmpres == 0) + return map[med].val; + else if (cmpres > 0) + low = med + 1; + else + high = med; + } + + return -1; +} + + +#ifdef DEBUG +# define REASON(str) printf ("\"%s\" ignored: %s\n", buf, str) +#else +# define REASON(str) +#endif + +int +main (void) +{ + int result = 0; + + while (! feof (stdin)) + { + char buf[1000]; + char *rp; + char *locale; + char *paramstr; + char *expected; + char *actual; + int param; + + if (fgets (buf, sizeof (buf), stdin) == NULL) + break; + + /* Split the fields. There are three is them: + 1. locale + 2. langinfo() parameter + 3. expected result; this can be a string with white space etc. + */ + rp = buf; + while (*rp == ' ' || *rp == '\t') + ++rp; + + if (*rp == '#') + { + /* It's a comment line. Ignore it. */ + REASON ("comment"); + continue; + } + locale = rp; + + while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n') + ++rp; + if (*rp == '\0' || *rp == '\n') + { + /* Incomplete line. */ + REASON ("incomplete line"); + continue; + } + *rp++ = '\0'; + + while (*rp == ' ' || *rp == '\t') + ++rp; + paramstr = rp; + + while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n') + ++rp; + if (*rp == '\0' || *rp == '\n') + { + /* Incomplete line. */ + REASON ("incomplete line"); + continue; + } + *rp++ = '\0'; + + while (*rp == ' ' || *rp == '\t') + ++rp; + + if (*rp == '"') + { + char *wp; + + expected = wp = ++rp; + while (*rp != '"' && *rp != '\n' && *rp != '\0') + { + if (*rp == '\\') + { + ++rp; + if (*rp == '\0') + break; + if (*rp >= '0' && *rp <= '9') + { + int val = *rp - '0'; + if (rp[1] >= '0' && rp[1] <= '9') + { + ++rp; + val *= 10; + val += *rp - '0'; + if (rp[1] >= '0' && rp[1] <= '9') + { + ++rp; + val *= 10; + val += *rp - '0'; + } + } + *rp = val; + } + } + *wp++ = *rp++; + } + + if (*rp != '"') + { + REASON ("missing '\"'"); + continue; + } + + *wp = '\0'; + } + else + { + expected = rp; + while (*rp != '\0' && *rp != '\n') + ++rp; + *rp = '\0'; + } + + param = map_paramstr (paramstr); + if (param == -1) + { + /* Invalid parameter. */ + REASON ("invalid parameter"); + continue; + } + + /* Set the locale and check whether it worked. */ + printf ("LC_ALL=%s nl_langinfo(%s)", locale, paramstr); + setlocale (LC_ALL, locale); + if (strcmp (locale, setlocale (LC_ALL, NULL)) != 0) + { + puts (": failed to set locale"); + result = 1; + continue; + } + + actual = nl_langinfo (param); + printf (" = \"%s\", ", actual); + + if (strcmp (actual, expected) == 0) + puts ("OK"); + else + { + printf ("FAILED (expected: %s)\n", expected); + result = 1; + } + } + + return result; +} diff --git a/test/locale/tst-langinfo.input b/test/locale/tst-langinfo.input new file mode 100644 index 0000000..0a05ab8 --- /dev/null +++ b/test/locale/tst-langinfo.input @@ -0,0 +1,303 @@ +#! /bin/sh +# Input file for tst-langinfo. +# Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# + +# The GNU C 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. + +# The GNU C 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 the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + + +# Run the test program. +# Only decimal numerical escape sequences allowed in strings. +C ABDAY_1 Sun +C ABDAY_2 Mon +C ABDAY_3 Tue +C ABDAY_4 Wed +C ABDAY_5 Thu +C ABDAY_6 Fri +C ABDAY_7 Sat +C DAY_1 Sunday +C DAY_2 Monday +C DAY_3 Tuesday +C DAY_4 Wednesday +C DAY_5 Thursday +C DAY_6 Friday +C DAY_7 Saturday +C ABMON_1 Jan +C ABMON_2 Feb +C ABMON_3 Mar +C ABMON_4 Apr +C ABMON_5 May +C ABMON_6 Jun +C ABMON_7 Jul +C ABMON_8 Aug +C ABMON_9 Sep +C ABMON_10 Oct +C ABMON_11 Nov +C ABMON_12 Dec +C MON_1 January +C MON_2 February +C MON_3 March +C MON_4 April +C MON_5 May +C MON_6 June +C MON_7 July +C MON_8 August +C MON_9 September +C MON_10 October +C MON_11 November +C MON_12 December +C AM_STR AM +C PM_STR PM +C D_T_FMT "%a %b %e %H:%M:%S %Y" +C D_FMT "%m/%d/%y" +C T_FMT "%H:%M:%S" +C T_FMT_AMPM "%I:%M:%S %p" +C ABDAY_1 Sun +C ABDAY_2 Mon +C ABDAY_3 Tue +C ABDAY_4 Wed +C ABDAY_5 Thu +C ABDAY_6 Fri +C ABDAY_7 Sat +C DAY_1 Sunday +C DAY_2 Monday +C DAY_3 Tuesday +C DAY_4 Wednesday +C DAY_5 Thursday +C DAY_6 Friday +C DAY_7 Saturday +C RADIXCHAR . +C THOUSEP "" +C YESEXPR ^[yY] +C NOEXPR ^[nN] +en_US.ISO-8859-1 ABMON_1 Jan +en_US.ISO-8859-1 ABMON_2 Feb +en_US.ISO-8859-1 ABMON_3 Mar +en_US.ISO-8859-1 ABMON_4 Apr +en_US.ISO-8859-1 ABMON_5 May +en_US.ISO-8859-1 ABMON_6 Jun +en_US.ISO-8859-1 ABMON_7 Jul +en_US.ISO-8859-1 ABMON_8 Aug +en_US.ISO-8859-1 ABMON_9 Sep +en_US.ISO-8859-1 ABMON_10 Oct +en_US.ISO-8859-1 ABMON_11 Nov +en_US.ISO-8859-1 ABMON_12 Dec +en_US.ISO-8859-1 MON_1 January +en_US.ISO-8859-1 MON_2 February +en_US.ISO-8859-1 MON_3 March +en_US.ISO-8859-1 MON_4 April +en_US.ISO-8859-1 MON_5 May +en_US.ISO-8859-1 MON_6 June +en_US.ISO-8859-1 MON_7 July +en_US.ISO-8859-1 MON_8 August +en_US.ISO-8859-1 MON_9 September +en_US.ISO-8859-1 MON_10 October +en_US.ISO-8859-1 MON_11 November +en_US.ISO-8859-1 MON_12 December +en_US.ISO-8859-1 AM_STR AM +en_US.ISO-8859-1 PM_STR PM +en_US.ISO-8859-1 D_T_FMT "%a %d %b %Y %r %Z" +en_US.ISO-8859-1 D_FMT "%m/%d/%Y" +en_US.ISO-8859-1 T_FMT "%r" +en_US.ISO-8859-1 T_FMT_AMPM "%I:%M:%S %p" +en_US.ISO-8859-1 RADIXCHAR . +en_US.ISO-8859-1 THOUSEP , +en_US.ISO-8859-1 YESEXPR ^[yY].* +en_US.ISO-8859-1 NOEXPR ^[nN].* +de_DE.ISO-8859-1 ABDAY_1 So +de_DE.ISO-8859-1 ABDAY_2 Mo +de_DE.ISO-8859-1 ABDAY_3 Di +de_DE.ISO-8859-1 ABDAY_4 Mi +de_DE.ISO-8859-1 ABDAY_5 Do +de_DE.ISO-8859-1 ABDAY_6 Fr +de_DE.ISO-8859-1 ABDAY_7 Sa +de_DE.ISO-8859-1 DAY_1 Sonntag +de_DE.ISO-8859-1 DAY_2 Montag +de_DE.ISO-8859-1 DAY_3 Dienstag +de_DE.ISO-8859-1 DAY_4 Mittwoch +de_DE.ISO-8859-1 DAY_5 Donnerstag +de_DE.ISO-8859-1 DAY_6 Freitag +de_DE.ISO-8859-1 DAY_7 Samstag +de_DE.ISO-8859-1 ABMON_1 Jan +de_DE.ISO-8859-1 ABMON_2 Feb +de_DE.ISO-8859-1 ABMON_3 Mär +de_DE.ISO-8859-1 ABMON_4 Apr +de_DE.ISO-8859-1 ABMON_5 Mai +de_DE.ISO-8859-1 ABMON_6 Jun +de_DE.ISO-8859-1 ABMON_7 Jul +de_DE.ISO-8859-1 ABMON_8 Aug +de_DE.ISO-8859-1 ABMON_9 Sep +de_DE.ISO-8859-1 ABMON_10 Okt +de_DE.ISO-8859-1 ABMON_11 Nov +de_DE.ISO-8859-1 ABMON_12 Dez +de_DE.ISO-8859-1 MON_1 Januar +de_DE.ISO-8859-1 MON_2 Februar +de_DE.ISO-8859-1 MON_3 März +de_DE.ISO-8859-1 MON_4 April +de_DE.ISO-8859-1 MON_5 Mai +de_DE.ISO-8859-1 MON_6 Juni +de_DE.ISO-8859-1 MON_7 Juli +de_DE.ISO-8859-1 MON_8 August +de_DE.ISO-8859-1 MON_9 September +de_DE.ISO-8859-1 MON_10 Oktober +de_DE.ISO-8859-1 MON_11 November +de_DE.ISO-8859-1 MON_12 Dezember +de_DE.ISO-8859-1 D_T_FMT "%a %d %b %Y %T %Z" +de_DE.ISO-8859-1 D_FMT "%d.%m.%Y" +de_DE.ISO-8859-1 T_FMT "%T" +de_DE.ISO-8859-1 RADIXCHAR , +de_DE.ISO-8859-1 THOUSEP . +de_DE.ISO-8859-1 YESEXPR ^[jJyY].* +de_DE.ISO-8859-1 NOEXPR ^[nN].* +de_DE.UTF-8 ABDAY_1 So +de_DE.UTF-8 ABDAY_2 Mo +de_DE.UTF-8 ABDAY_3 Di +de_DE.UTF-8 ABDAY_4 Mi +de_DE.UTF-8 ABDAY_5 Do +de_DE.UTF-8 ABDAY_6 Fr +de_DE.UTF-8 ABDAY_7 Sa +de_DE.UTF-8 DAY_1 Sonntag +de_DE.UTF-8 DAY_2 Montag +de_DE.UTF-8 DAY_3 Dienstag +de_DE.UTF-8 DAY_4 Mittwoch +de_DE.UTF-8 DAY_5 Donnerstag +de_DE.UTF-8 DAY_6 Freitag +de_DE.UTF-8 DAY_7 Samstag +de_DE.UTF-8 ABMON_1 Jan +de_DE.UTF-8 ABMON_2 Feb +de_DE.UTF-8 ABMON_3 Mär +de_DE.UTF-8 ABMON_4 Apr +de_DE.UTF-8 ABMON_5 Mai +de_DE.UTF-8 ABMON_6 Jun +de_DE.UTF-8 ABMON_7 Jul +de_DE.UTF-8 ABMON_8 Aug +de_DE.UTF-8 ABMON_9 Sep +de_DE.UTF-8 ABMON_10 Okt +de_DE.UTF-8 ABMON_11 Nov +de_DE.UTF-8 ABMON_12 Dez +de_DE.UTF-8 MON_1 Januar +de_DE.UTF-8 MON_2 Februar +de_DE.UTF-8 MON_3 März +de_DE.UTF-8 MON_4 April +de_DE.UTF-8 MON_5 Mai +de_DE.UTF-8 MON_6 Juni +de_DE.UTF-8 MON_7 Juli +de_DE.UTF-8 MON_8 August +de_DE.UTF-8 MON_9 September +de_DE.UTF-8 MON_10 Oktober +de_DE.UTF-8 MON_11 November +de_DE.UTF-8 MON_12 Dezember +de_DE.UTF-8 D_T_FMT "%a %d %b %Y %T %Z" +de_DE.UTF-8 D_FMT "%d.%m.%Y" +de_DE.UTF-8 T_FMT "%T" +de_DE.UTF-8 RADIXCHAR , +de_DE.UTF-8 THOUSEP . +de_DE.UTF-8 YESEXPR ^[jJyY].* +de_DE.UTF-8 NOEXPR ^[nN].* +fr_FR.ISO-8859-1 ABDAY_1 dim +fr_FR.ISO-8859-1 ABDAY_2 lun +fr_FR.ISO-8859-1 ABDAY_3 mar +fr_FR.ISO-8859-1 ABDAY_4 mer +fr_FR.ISO-8859-1 ABDAY_5 jeu +fr_FR.ISO-8859-1 ABDAY_6 ven +fr_FR.ISO-8859-1 ABDAY_7 sam +fr_FR.ISO-8859-1 DAY_1 dimanche +fr_FR.ISO-8859-1 DAY_2 lundi +fr_FR.ISO-8859-1 DAY_3 mardi +fr_FR.ISO-8859-1 DAY_4 mercredi +fr_FR.ISO-8859-1 DAY_5 jeudi +fr_FR.ISO-8859-1 DAY_6 vendredi +fr_FR.ISO-8859-1 DAY_7 samedi +fr_FR.ISO-8859-1 ABMON_1 jan +fr_FR.ISO-8859-1 ABMON_2 fév +fr_FR.ISO-8859-1 ABMON_3 mar +fr_FR.ISO-8859-1 ABMON_4 avr +fr_FR.ISO-8859-1 ABMON_5 mai +fr_FR.ISO-8859-1 ABMON_6 jun +fr_FR.ISO-8859-1 ABMON_7 jui +fr_FR.ISO-8859-1 ABMON_8 aoû +fr_FR.ISO-8859-1 ABMON_9 sep +fr_FR.ISO-8859-1 ABMON_10 oct +fr_FR.ISO-8859-1 ABMON_11 nov +fr_FR.ISO-8859-1 ABMON_12 déc +fr_FR.ISO-8859-1 MON_1 janvier +fr_FR.ISO-8859-1 MON_2 février +fr_FR.ISO-8859-1 MON_3 mars +fr_FR.ISO-8859-1 MON_4 avril +fr_FR.ISO-8859-1 MON_5 mai +fr_FR.ISO-8859-1 MON_6 juin +fr_FR.ISO-8859-1 MON_7 juillet +fr_FR.ISO-8859-1 MON_8 août +fr_FR.ISO-8859-1 MON_9 septembre +fr_FR.ISO-8859-1 MON_10 octobre +fr_FR.ISO-8859-1 MON_11 novembre +fr_FR.ISO-8859-1 MON_12 décembre +fr_FR.ISO-8859-1 D_T_FMT "%a %d %b %Y %T %Z" +fr_FR.ISO-8859-1 D_FMT "%d.%m.%Y" +fr_FR.ISO-8859-1 T_FMT "%T" +fr_FR.ISO-8859-1 RADIXCHAR , +fr_FR.ISO-8859-1 THOUSEP "" +fr_FR.ISO-8859-1 YESEXPR ^[oOyY].* +fr_FR.ISO-8859-1 NOEXPR ^[nN].* +ja_JP.EUC-JP ABDAY_1 Æü +ja_JP.EUC-JP ABDAY_2 ·î +ja_JP.EUC-JP ABDAY_3 ²Ð +ja_JP.EUC-JP ABDAY_4 ¿å +ja_JP.EUC-JP ABDAY_5 ÌÚ +ja_JP.EUC-JP ABDAY_6 ¶â +ja_JP.EUC-JP ABDAY_7 ÅÚ +ja_JP.EUC-JP DAY_1 ÆüÍËÆü +ja_JP.EUC-JP DAY_2 ·îÍËÆü +ja_JP.EUC-JP DAY_3 ²ÐÍËÆü +ja_JP.EUC-JP DAY_4 ¿åÍËÆü +ja_JP.EUC-JP DAY_5 ÌÚÍËÆü +ja_JP.EUC-JP DAY_6 ¶âÍËÆü +ja_JP.EUC-JP DAY_7 ÅÚÍËÆü +ja_JP.EUC-JP ABMON_1 " 1·î" +ja_JP.EUC-JP ABMON_2 " 2·î" +ja_JP.EUC-JP ABMON_3 " 3·î" +ja_JP.EUC-JP ABMON_4 " 4·î" +ja_JP.EUC-JP ABMON_5 " 5·î" +ja_JP.EUC-JP ABMON_6 " 6·î" +ja_JP.EUC-JP ABMON_7 " 7·î" +ja_JP.EUC-JP ABMON_8 " 8·î" +ja_JP.EUC-JP ABMON_9 " 9·î" +ja_JP.EUC-JP ABMON_10 "10·î" +ja_JP.EUC-JP ABMON_11 "11·î" +ja_JP.EUC-JP ABMON_12 "12·î" +ja_JP.EUC-JP MON_1 "1·î" +ja_JP.EUC-JP MON_2 "2·î" +ja_JP.EUC-JP MON_3 "3·î" +ja_JP.EUC-JP MON_4 "4·î" +ja_JP.EUC-JP MON_5 "5·î" +ja_JP.EUC-JP MON_6 "6·î" +ja_JP.EUC-JP MON_7 "7·î" +ja_JP.EUC-JP MON_8 "8·î" +ja_JP.EUC-JP MON_9 "9·î" +ja_JP.EUC-JP MON_10 "10·î" +ja_JP.EUC-JP MON_11 "11·î" +ja_JP.EUC-JP MON_12 "12·î" +ja_JP.EUC-JP T_FMT_AMPM "%p%I»þ%Mʬ%SÉÃ" +ja_JP.EUC-JP ERA_D_FMT "%EY%m·î%dÆü" +ja_JP.EUC-JP ERA_D_T_FMT "%EY%m·î%dÆü %H»þ%Mʬ%SÉÃ" +ja_JP.EUC-JP RADIXCHAR . +ja_JP.EUC-JP THOUSEP , +ja_JP.EUC-JP YESEXPR ^([yY£ù£Ù]|¤Ï¤¤|¥Ï¥¤) +ja_JP.EUC-JP NOEXPR ^([nN£î£Î]|¤¤¤¤¤¨|¥¤¥¤¥¨) +# Is CRNCYSTR supposed to be the national or international sign? +# ja_JP.EUC-JP CRNCYSTR JPY +ja_JP.EUC-JP CODESET EUC-JP diff --git a/test/locale/tst-leaks.c b/test/locale/tst-leaks.c new file mode 100644 index 0000000..7a4b557 --- /dev/null +++ b/test/locale/tst-leaks.c @@ -0,0 +1,18 @@ +#include +#include + +int +main (void) +{ + int cnt; + + mtrace (); + + for (cnt = 0; cnt < 100; ++cnt) + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + setlocale (LC_ALL, "de_DE.UTF-8"); + } + + return 0; +} diff --git a/test/locale/tst-mbswcs1.c b/test/locale/tst-mbswcs1.c new file mode 100644 index 0000000..fb2ea84 --- /dev/null +++ b/test/locale/tst-mbswcs1.c @@ -0,0 +1,63 @@ +/* Test restarting behaviour of mbrtowc. + Copyright (C) 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define show(expr, nexp, wcexp) \ + n = expr; \ + printf (#expr " -> %Zd", n); \ + printf (", wc = %lu", (unsigned long int) wc); \ + if (n != (size_t) nexp || wc != wcexp) \ + { \ + printf (", expected %Zd and %lu", nexp, (unsigned long int) wcexp); \ + result = 1; \ + } \ + putc ('\n', stdout) + +int +main (void) +{ + const unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb }; + mbstate_t state; + wchar_t wc = 42; + size_t n; + int result = 0; + const char *used_locale; + + setlocale (LC_CTYPE, "de_DE.UTF-8"); + /* Double check. */ + used_locale = setlocale (LC_CTYPE, NULL); + printf ("used locale: \"%s\"\n", used_locale); + result = strcmp (used_locale, "de_DE.UTF-8"); + + memset (&state, '\0', sizeof (state)); + + show (mbrtowc (&wc, (const char *) buf + 0, 1, &state), 1, 37); + show (mbrtowc (&wc, (const char *) buf + 1, 1, &state), -2, 37); + show (mbrtowc (&wc, (const char *) buf + 2, 3, &state), 2, 8364); + show (mbrtowc (&wc, (const char *) buf + 4, 1, &state), -2, 8364); + show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), 1, 955); + show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), -1, 955); + + return result; +} diff --git a/test/locale/tst-mbswcs2.c b/test/locale/tst-mbswcs2.c new file mode 100644 index 0000000..49f13cc --- /dev/null +++ b/test/locale/tst-mbswcs2.c @@ -0,0 +1,65 @@ +/* Test restarting behaviour of mbsnrtowcs. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define show(expr, nexp, wcexp, end) \ + n = expr; \ + printf (#expr " -> %Zd", n); \ + printf (", wc = %lu, src = buf+%d", (unsigned long int) wc, \ + src - (const char *) buf); \ + if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end)) \ + { \ + printf (", expected %Zd and %lu and buf+%d", nexp, \ + (unsigned long int) wcexp, (end) - buf); \ + result = 1; \ + } \ + putc ('\n', stdout) + +int +main (void) +{ + unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb }; + mbstate_t state; + const char *src; + wchar_t wc = 42; + size_t n; + int result = 0; + const char *used_locale; + + setlocale (LC_CTYPE,"de_DE.UTF-8"); + /* Double check. */ + used_locale = setlocale (LC_CTYPE, NULL); + printf ("used locale: \"%s\"\n", used_locale); + result = strcmp (used_locale, "de_DE.UTF-8"); + + memset (&state, '\0', sizeof (state)); + + src = (const char *) buf; + show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 37, buf + 1); + show (mbsnrtowcs (&wc, &src, 3, 1, &state), 1, 8364, buf + 4); + show (mbsnrtowcs (&wc, &src, 1, 1, &state), 0, 8364, buf + 5); + show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 955, buf + 6); + + return result; +} diff --git a/test/locale/tst-mbswcs3.c b/test/locale/tst-mbswcs3.c new file mode 100644 index 0000000..0c4af4c --- /dev/null +++ b/test/locale/tst-mbswcs3.c @@ -0,0 +1,76 @@ +/* Test restarting behaviour of wcsrtombs. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define show(expr, nexp, srcexp, bufexp) \ + { \ + size_t res = expr; \ + printf (#expr " -> %Zd", res); \ + dst += res; \ + printf (", src = srcbuf+%td, dst = buf+%td", \ + src - srcbuf, dst - (char *) buf); \ + if (res != nexp || src != (srcexp) || dst != (char *) (bufexp)) \ + { \ + printf (", expected %Zd and srcbuf+%td and buf+%td", nexp, \ + (srcexp) - srcbuf, (bufexp) - (unsigned char *) buf); \ + result = 1; \ + } \ + putc ('\n', stdout); \ + } + +int +main (void) +{ + unsigned char buf[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const unsigned char bufcheck[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb }; + const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 }; + mbstate_t state; + const wchar_t *src; + char *dst; + int result = 0; + const char *used_locale; + + setlocale (LC_CTYPE, "de_DE.UTF-8"); + /* Double check. */ + used_locale = setlocale (LC_CTYPE, NULL); + printf ("used locale: \"%s\"\n", used_locale); + result = strcmp (used_locale, "de_DE.UTF-8"); + + memset (&state, '\0', sizeof (state)); + + src = srcbuf; + dst = (char *) buf; + show (wcsrtombs (dst, &src, 1, &state), 1, srcbuf + 1, buf + 1); + show (wcsrtombs (dst, &src, 1, &state), 0, srcbuf + 1, buf + 1); + show (wcsrtombs (dst, &src, 4, &state), 3, srcbuf + 2, buf + 4); + show (wcsrtombs (dst, &src, 2, &state), 2, srcbuf + 3, buf + 6); + + if (memcmp (buf, bufcheck, 6)) + { + puts ("wrong results"); + result = 1; + } + + return result; +} diff --git a/test/locale/tst-mbswcs4.c b/test/locale/tst-mbswcs4.c new file mode 100644 index 0000000..e02b675 --- /dev/null +++ b/test/locale/tst-mbswcs4.c @@ -0,0 +1,63 @@ +/* Test restarting behaviour of mbsrtowcs. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define show(expr, nexp, wcexp, end) \ + n = expr; \ + printf (#expr " -> %Zd", n); \ + printf (", wc = %lu, src = buf+%d", (unsigned long int) wc, \ + src - (const char *) buf); \ + if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end)) \ + { \ + printf (", expected %Zd and %lu and buf+%d", nexp, \ + (unsigned long int) wcexp, (end) - buf); \ + result = 1; \ + } \ + putc ('\n', stdout) + +int +main (void) +{ + unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb }; + mbstate_t state; + const char *src; + wchar_t wc = 42; + size_t n; + int result = 0; + const char *used_locale; + + setlocale (LC_CTYPE,"de_DE.UTF-8"); + /* Double check. */ + used_locale = setlocale (LC_CTYPE, NULL); + printf ("used locale: \"%s\"\n", used_locale); + result = strcmp (used_locale, "de_DE.UTF-8"); + + memset (&state, '\0', sizeof (state)); + + src = (const char *) buf; + show (mbsrtowcs (&wc, &src, 1, &state), 1, 37, buf + 1); + show (mbsrtowcs (&wc, &src, 1, &state), 1, 8364, buf + 4); + show (mbsrtowcs (&wc, &src, 1, &state), 1, 955, buf + 6); + + return result; +} diff --git a/test/locale/tst-mbswcs5.c b/test/locale/tst-mbswcs5.c new file mode 100644 index 0000000..7cab97e --- /dev/null +++ b/test/locale/tst-mbswcs5.c @@ -0,0 +1,75 @@ +/* Test restarting behaviour of wcrtomb. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define show(expr, nexp, bufexp) \ + { \ + size_t res = expr; \ + printf (#expr " -> %Zd", res); \ + dst += res; \ + printf (", dst = buf+%td", dst - (char *) buf); \ + if (res != nexp || dst != (char *) (bufexp)) \ + { \ + printf (", expected %Zd and buf+%td", nexp, \ + (bufexp) - (unsigned char *) buf); \ + result = 1; \ + } \ + putc ('\n', stdout); \ + } + +int +main (void) +{ + unsigned char buf[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const unsigned char bufcheck[7] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb, 0 }; + const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 }; + mbstate_t state; + const wchar_t *src; + char *dst; + int result = 0; + const char *used_locale; + + setlocale (LC_CTYPE, "de_DE.UTF-8"); + /* Double check. */ + used_locale = setlocale (LC_CTYPE, NULL); + printf ("used locale: \"%s\"\n", used_locale); + result = strcmp (used_locale, "de_DE.UTF-8"); + + memset (&state, '\0', sizeof (state)); + + src = srcbuf; + dst = (char *) buf; + show (wcrtomb (dst, *src++, &state), 1, buf + 1); + show (wcrtomb (dst, *src++, &state), 3, buf + 4); + show (wcrtomb (dst, *src++, &state), 2, buf + 6); + show (wcrtomb (dst, *src, &state), 1, buf + 7); + + if (memcmp (buf, bufcheck, 7)) + { + puts ("wrong results"); + result = 1; + } + + return result; +} diff --git a/test/locale/tst-mbswcs6.c b/test/locale/tst-mbswcs6.c new file mode 100644 index 0000000..eb383ac --- /dev/null +++ b/test/locale/tst-mbswcs6.c @@ -0,0 +1,74 @@ +/* Test for invalid input to wcrtomb. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +static int +do_test (const char *loc) +{ + char buf[100]; + size_t n; + mbstate_t state; + const char *nloc; + int res; + + nloc = setlocale (LC_ALL, loc); + if (nloc == NULL) + { + printf ("could not set locale \"%s\"\n", loc); + return 1; + } + printf ("new locale: %s\n", nloc); + + memset (&state, '\0', sizeof (state)); + errno = 0; + n = wcrtomb (buf, (wchar_t) -15l, &state); + + printf ("n = %zd, errno = %d (%s)\n", n, errno, strerror (errno)); + + res = n != (size_t) -1 || errno != EILSEQ; + if (res) + puts ("*** FAIL"); + putchar ('\n'); + + return res; +} + + +int +main (void) +{ + int res; + + res = do_test ("C"); + res |= do_test ("de_DE.ISO-8859-1"); + res |= do_test ("de_DE.UTF-8"); + res |= do_test ("en_US.ISO-8859-1"); + res |= do_test ("ja_JP.UTF-8"); + res |= do_test ("hr_HR.ISO-8859-2"); + //res |= do_test ("ru_RU.KOI8-R"); + + return res; +} diff --git a/test/locale/tst-numeric.c b/test/locale/tst-numeric.c new file mode 100644 index 0000000..9d3c91d --- /dev/null +++ b/test/locale/tst-numeric.c @@ -0,0 +1,74 @@ +/* Testing the implementation of LC_NUMERIC and snprintf(). + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Petter Reinholdtsen , 2003 + + Based on tst-fmon.c by Jochen Hein , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* + test-numeric gets called with three parameters: + - the locale + - the format-string to be used + - the actual number to be formatted + - the expected string + If the test passes, test-numeric terminates with returncode 0, + otherwise with 1 +*/ +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#define EXIT_SETLOCALE 2 +#define EXIT_SNPRINTF 3 + +int +main (int argc, char *argv[]) +{ + char *s = malloc (201); + double val; + + /* Make sure to read the value before setting of the locale, as + strtod() is locale-dependent. */ + val = strtod (argv[3], NULL); + + if (setlocale (LC_ALL, argv[1]) == NULL) + { + fprintf (stderr, "setlocale(LC_ALL, \"%s\"): %m\n", argv[1]); + exit (EXIT_SETLOCALE); + } + + if (snprintf (s, 200, argv[2], val) == -1) + { + perror ("snprintf"); + exit (EXIT_SNPRINTF); + } + + if (strcmp (s, argv[4]) != 0) + { + printf ("\ +locale: \"%s\", format: \"%s\", expected: \"%s\", got: \"%s\" => %s\n", + argv[1], argv[2], argv[4], s, + strcmp (s, argv[4]) != 0 ? "false" : "correct"); + exit (EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/test/locale/tst-rpmatch.c b/test/locale/tst-rpmatch.c new file mode 100644 index 0000000..d751a43 --- /dev/null +++ b/test/locale/tst-rpmatch.c @@ -0,0 +1,37 @@ +/* Test program for rpmatch function. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jochen Hein . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +main (int argc, char* argv[]) +{ + setlocale (LC_ALL, argv[1]); + + if (rpmatch (argv[2]) != atol (argv[3])) + { + fprintf (stderr,"Failed: Locale %s, String %s, Exp: %s, got %d\n", + argv[1], argv[2], argv[3], rpmatch (argv[2])); + exit (EXIT_FAILURE); + } + return EXIT_SUCCESS; +} diff --git a/test/locale/tst-setlocale.c b/test/locale/tst-setlocale.c new file mode 100644 index 0000000..1f8e68d --- /dev/null +++ b/test/locale/tst-setlocale.c @@ -0,0 +1,25 @@ +/* Test case by Jakub Jelinek . */ +#include +#include +#include + +int +main (void) +{ + char q[30]; + char *s; + + setlocale (LC_ALL, ""); + printf ("after setlocale (LC_ALL, \"\"): %s\n", setlocale(LC_NUMERIC, NULL)); + + strcpy (q, "de_DE.UTF-8"); + setlocale (LC_NUMERIC, q); + printf ("after setlocale (LC_NUMERIC, \"%s\"): %s\n", + q, setlocale(LC_NUMERIC, NULL)); + + strcpy (q, "de_DE.ISO-8859-1"); + s = setlocale (LC_NUMERIC, NULL); + printf ("after overwriting string: %s\n", s); + + return strcmp (s, "de_DE.UTF-8") != 0; +} diff --git a/test/locale/tst-sscanf.c b/test/locale/tst-sscanf.c new file mode 100644 index 0000000..32c1328 --- /dev/null +++ b/test/locale/tst-sscanf.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#define P0 "\xDB\xB0" +#define P1 "\xDB\xB1" +#define P2 "\xDB\xB2" +#define P3 "\xDB\xB3" +#define P4 "\xDB\xB4" +#define P5 "\xDB\xB5" +#define P6 "\xDB\xB6" +#define P7 "\xDB\xB7" +#define P8 "\xDB\xB8" +#define P9 "\xDB\xB9" +#define PD "\xd9\xab" +#define PT "\xd9\xac" + +static int +check_sscanf (const char *s, const char *format, const float n) +{ + float f; + + if (sscanf (s, format, &f) != 1) + { + printf ("nothing found for \"%s\"\n", s); + return 1; + } + if (f != n) + { + printf ("got %f expected %f from \"%s\"\n", f, n, s); + return 1; + } + return 0; +} + +static int +do_test (void) +{ + if (setlocale (LC_ALL, "fa_IR.UTF-8") == NULL) + { + puts ("cannot set fa_IR locale"); + return 1; + } + + int r = check_sscanf (P3 PD P1 P4, "%I8f", 3.14); + r |= check_sscanf (P3 PT P1 P4 P5, "%I'f", 3145); + r |= check_sscanf (P3 PD P1 P4 P1 P5 P9, "%If", 3.14159); + r |= check_sscanf ("-" P3 PD P1 P4 P1 P5, "%If", -3.1415); + r |= check_sscanf ("+" PD P1 P4 P1 P5, "%If", +.1415); + r |= check_sscanf (P3 PD P1 P4 P1 P5 "e+" P2, "%Ie", 3.1415e+2); + + return r; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/locale/tst-strfmon1.c b/test/locale/tst-strfmon1.c new file mode 100644 index 0000000..e30aa1b --- /dev/null +++ b/test/locale/tst-strfmon1.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +static const struct +{ + const char *locale; + const char *expected; +} tests[] = + { + { "de_DE.ISO-8859-1", "|-12,34 EUR|-12,34|" }, + { "da_DK.ISO-8859-1", "|kr -12,34|-12,34|" }, + { "zh_TW.EUC-TW", "|-NT$12.34|-12.34|" }, + { "sv_SE.ISO-8859-1", "|-12,34 kr|-12,34|" } + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +static int +do_test (void) +{ + int res = 0; + for (int i = 0; i < ntests; ++i) + { + char buf[500]; + if (setlocale (LC_ALL, tests[i].locale) == NULL) + { + printf ("failed to set locale %s\n", tests[i].locale); + res = 1; + continue; + } + strfmon (buf, sizeof (buf), "|%n|%!n|", -12.34, -12.34); + int fail = strcmp (buf, tests[i].expected) != 0; + printf ("%s%s\n", buf, fail ? " *** FAIL ***" : ""); + res |= fail; + } + return res; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/locale/tst-trans.c b/test/locale/tst-trans.c new file mode 100644 index 0000000..034a362 --- /dev/null +++ b/test/locale/tst-trans.c @@ -0,0 +1,71 @@ +/* Test program for user-defined character maps. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +int +main (void) +{ + char buf[30]; + wchar_t wbuf[30]; + wctrans_t t; + wint_t wch; + int errors = 0; + int len; + + setlocale (LC_ALL, ""); + + t = wctrans ("test"); + if (t == (wctrans_t) 0) + { + puts ("locale data files probably not loaded"); + exit (1); + } + + wch = towctrans (L'A', t); + printf ("towctrans (L'A', t) = %c\n", wch); + if (wch != L'B') + errors = 1; + + wch = towctrans (L'B', t); + printf ("towctrans (L'B', t) = %c\n", wch); + if (wch != L'C') + errors = 1; + + /* Test the output digit handling. */ + swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%Id", 0x499602D2); + errors |= wcscmp (wbuf, L"bcdefghija") != 0; + len = wcslen (wbuf); + errors |= len != 10; + printf ("len = %d, wbuf = L\"%ls\"\n", len, wbuf); + + snprintf (buf, sizeof buf, "%Id", 0x499602D2); + errors |= strcmp (buf, "bcdefghija") != 0; + len = strlen (buf); + errors |= len != 10; + printf ("len = %d, buf = \"%s\"\n", len, buf); + + return errors; +} diff --git a/test/locale/tst-wctype.c b/test/locale/tst-wctype.c new file mode 100644 index 0000000..8fd8ce5 --- /dev/null +++ b/test/locale/tst-wctype.c @@ -0,0 +1,144 @@ +/* Test program for iswctype() function in ja_JP locale. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +int +main (void) +{ + wctype_t wct; + wchar_t buf[1000]; + int result = 1; + + setlocale (LC_ALL, ""); + wprintf (L"locale = %s\n", setlocale (LC_CTYPE, NULL)); + + wct = wctype ("jhira"); + if (wct == 0) + error (EXIT_FAILURE, 0, "jhira: no such character class"); + + if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL) + { + int n; + + wprintf (L"buf[] = \"%ls\"\n", buf); + + result = 0; + + for (n = 0; buf[n] != L'\0'; ++n) + { + wprintf (L"jhira(U%04lx = %lc) = %d\n", (long) buf[n], buf[n], + iswctype (buf[n], wct)); + result |= ((buf[n] < 0xff && iswctype (buf[n], wct)) + || (buf[n] > 0xff && !iswctype (buf[n], wct))); + } + } + + wct = wctype ("jkata"); + if (wct == 0) + error (EXIT_FAILURE, 0, "jkata: no such character class"); + + if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL) + { + int n; + + wprintf (L"buf[] = \"%ls\"\n", buf); + + result = 0; + + for (n = 0; buf[n] != L'\0'; ++n) + { + wprintf (L"jkata(U%04lx = %lc) = %d\n", (long) buf[n], buf[n], + iswctype (buf[n], wct)); + result |= ((buf[n] < 0xff && iswctype (buf[n], wct)) + || (buf[n] > 0xff && !iswctype (buf[n], wct))); + } + } + + wct = wctype ("jdigit"); + if (wct == 0) + error (EXIT_FAILURE, 0, "jdigit: no such character class"); + + if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL) + { + int n; + + wprintf (L"buf[] = \"%ls\"\n", buf); + + result = 0; + + for (n = 0; buf[n] != L'\0'; ++n) + { + wprintf (L"jdigit(U%04lx = %lc) = %d\n", (long) buf[n], buf[n], + iswctype (buf[n], wct)); + result |= ((buf[n] < 0xff && iswctype (buf[n], wct)) + || (buf[n] > 0xff && !iswctype (buf[n], wct))); + } + } + + wct = wctype ("jspace"); + if (wct == 0) + error (EXIT_FAILURE, 0, "jspace: no such character class"); + + if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL) + { + int n; + + wprintf (L"buf[] = \"%ls\"\n", buf); + + result = 0; + + for (n = 0; buf[n] != L'\0'; ++n) + { + wprintf (L"jspace(U%04lx = %lc) = %d\n", (long) buf[n], buf[n], + iswctype (buf[n], wct)); + result |= ((buf[n] < 0xff && iswctype (buf[n], wct)) + || (buf[n] > 0xff && !iswctype (buf[n], wct))); + } + } + + wct = wctype ("jkanji"); + if (wct == 0) + error (EXIT_FAILURE, 0, "jkanji: no such character class"); + + if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL) + { + int n; + + wprintf (L"buf[] = \"%ls\"\n", buf); + + result = 0; + + for (n = 0; buf[n] != L'\0'; ++n) + { + wprintf (L"jkanji(U%04lx = %lc) = %d\n", (long) buf[n], buf[n], + iswctype (buf[n], wct)); + result |= ((buf[n] < 0xff && iswctype (buf[n], wct)) + || (buf[n] > 0xff && !iswctype (buf[n], wct))); + } + } + + return result; +} diff --git a/test/locale/tst-xlocale1.c b/test/locale/tst-xlocale1.c new file mode 100644 index 0000000..297c9ad --- /dev/null +++ b/test/locale/tst-xlocale1.c @@ -0,0 +1,75 @@ +#include +#include +#include + + +static struct +{ + const char *locale; + const char *str1; + const char *str2; + int result; +} tests[] = + { + { "C", "TRANSLIT", "translit", 0 }, + { "de_DE.ISO-8859-1", "TRANSLIT", "translit", 0 }, + { "de_DE.ISO-8859-1", "TRANSLIT", "trÄnslit", -1 }, + { "de_DE.UTF-8", "TRANSLIT", "translit", 0 }, + { "de_DE.ISO-8859-1", "ä", "Ä", 1 } + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +int +main (void) +{ + size_t cnt; + int result = 0; + locale_t loc = newlocale (1 << LC_ALL, "C", NULL); + + for (cnt = 0; cnt < ntests; ++cnt) + { + int r; + + if (setlocale (LC_ALL, tests[cnt].locale) == NULL) + { + printf ("cannot set locale \"%s\": %m\n", tests[cnt].locale); + result = 1; + continue; + } + + printf ("\nstrcasecmp_l (\"%s\", \"%s\", loc)\n", + tests[cnt].str1, tests[cnt].str2); + + r = strcasecmp_l (tests[cnt].str1, tests[cnt].str2, loc); + if (tests[cnt].result == 0) + { + if (r != 0) + { + printf ("\"%s\" and \"%s\" expected to be the same, result %d\n", + tests[cnt].str1, tests[cnt].str2, r); + result = 1; + } + } + else if (tests[cnt].result < 0) + { + if (r >= 0) + { + printf ("\"%s\" expected to be smaller than \"%s\", result %d\n", + tests[cnt].str1, tests[cnt].str2, r); + result = 1; + } + } + else + { + if (r <= 0) + { + printf ("\"%s\" expected to be larger than \"%s\", result %d\n", + tests[cnt].str1, tests[cnt].str2, r); + result = 1; + } + } + } + + return result; +} diff --git a/test/locale/tst-xlocale2.c b/test/locale/tst-xlocale2.c new file mode 100644 index 0000000..30d87de --- /dev/null +++ b/test/locale/tst-xlocale2.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + + +static int do_test (__locale_t l); + +int +main (void) +{ + locale_t l; + locale_t l2; + int result; + + l = newlocale (1 << LC_ALL, "de_DE.ISO-8859-1", NULL); + if (l == NULL) + { + printf ("newlocale failed: %m\n"); + exit (EXIT_FAILURE); + } + puts ("Running tests of created locale"); + result = do_test (l); + + l2 = duplocale (l); + if (l2 == NULL) + { + printf ("duplocale failed: %m\n"); + exit (EXIT_FAILURE); + } + freelocale (l); + puts ("Running tests of duplicated locale"); + result |= do_test (l2); + + return result; +} + + +static const char str[] = "0123456789abcdef ABCDEF ghijklmnopqrstuvwxyzäÄöÖüÜ"; +static const char exd[] = "11111111110000000000000000000000000000000000000000"; +static const char exa[] = "00000000001111110111111011111111111111111111111111"; +static const char exx[] = "11111111111111110111111000000000000000000000000000"; + + +static int +do_test (locale_t l) +{ + int result = 0; +size_t n; + +#define DO_TEST(TEST, RES) \ + for (n = 0; n < sizeof (str) - 1; ++n) \ + if ('0' + (TEST (str[n], l) != 0) != RES[n]) \ + { \ + printf ("%s(%c) failed\n", #TEST, str[n]); \ + result = 1; \ + } + + DO_TEST (isdigit_l, exd); + DO_TEST (isalpha_l, exa); + DO_TEST (isxdigit_l, exx); + + return result; +} diff --git a/test/locale/tst_nl_langinfo.c b/test/locale/tst_nl_langinfo.c new file mode 100644 index 0000000..fcf2fe2 --- /dev/null +++ b/test/locale/tst_nl_langinfo.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include + +#if !defined(__UCLIBC__) && 0 +#define DO_EXTRA +#endif + +int main(int argc, char **argv) +{ + char *l; + const unsigned char *x; +/* const unsigned char *y; */ + const unsigned char *p; + + if (argc > 2) { + printf("invalid args\n"); + return EXIT_FAILURE; + } + if (argc == 1) { + l = ""; + } else { + l = *++argv; + } + + if (!(x = setlocale(LC_ALL,l))) { + printf("couldn't set locale %s\n", l); + return EXIT_FAILURE; + } + +/* printf("\nsetlocale returned:\n "); */ +/* do { */ +/* printf("\\x%02x", *x); */ +/* } while (*x++); */ +/* printf("\n"); */ + +#ifndef __BCC__ +#define STR(X) #X +#else +#define STR(X) __STR(X) +#endif +#define __PASTE2(A,B) A.B + +#define DO_NL_I(X) \ + printf( STR(X) " = %d\n", (int) nl_langinfo(X) ); +#define DO_NL_S(X) \ + printf( STR(X) " = \"%s\"\n", nl_langinfo(X) ); +#define DO_NL_C(X) \ + printf( STR(X) " = \"\\x%02x\"\n", *((unsigned char *) nl_langinfo(X)) ); + + printf("ctype\n"); + + DO_NL_S(CODESET); +#ifdef DO_EXTRA + DO_NL_I(_NL_CTYPE_INDIGITS_MB_LEN); + DO_NL_S(_NL_CTYPE_INDIGITS0_MB); + DO_NL_S(_NL_CTYPE_INDIGITS1_MB); + DO_NL_S(_NL_CTYPE_INDIGITS2_MB); + DO_NL_S(_NL_CTYPE_INDIGITS3_MB); + DO_NL_S(_NL_CTYPE_INDIGITS4_MB); + DO_NL_S(_NL_CTYPE_INDIGITS5_MB); + DO_NL_S(_NL_CTYPE_INDIGITS6_MB); + DO_NL_S(_NL_CTYPE_INDIGITS7_MB); + DO_NL_S(_NL_CTYPE_INDIGITS8_MB); + DO_NL_S(_NL_CTYPE_INDIGITS9_MB); +#endif + DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB); + + + printf("numeric\n"); + + DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */ + DO_NL_S(THOUSEP); /* THOUSANDS_SEP */ +/* DO_NL_S(GROUPING); */ + + printf("GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + printf("monetary\n"); + + DO_NL_S(INT_CURR_SYMBOL); + DO_NL_S(CURRENCY_SYMBOL); + DO_NL_S(MON_DECIMAL_POINT); + DO_NL_S(MON_THOUSANDS_SEP); +/* DO_NL_S(MON_GROUPING); */ + + printf("MON_GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(MON_GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + DO_NL_S(POSITIVE_SIGN); + DO_NL_S(NEGATIVE_SIGN); + DO_NL_C(INT_FRAC_DIGITS); + DO_NL_C(FRAC_DIGITS); + DO_NL_C(P_CS_PRECEDES); + DO_NL_C(P_SEP_BY_SPACE); + DO_NL_C(N_CS_PRECEDES); + DO_NL_C(N_SEP_BY_SPACE); + DO_NL_C(P_SIGN_POSN); + DO_NL_C(N_SIGN_POSN); + DO_NL_C(INT_P_CS_PRECEDES); + DO_NL_C(INT_P_SEP_BY_SPACE); + DO_NL_C(INT_N_CS_PRECEDES); + DO_NL_C(INT_N_SEP_BY_SPACE); + DO_NL_C(INT_P_SIGN_POSN); + DO_NL_C(INT_N_SIGN_POSN); + + DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */ + + + printf("time\n"); + + DO_NL_S(ABDAY_1); + DO_NL_S(ABDAY_2); + DO_NL_S(ABDAY_3); + DO_NL_S(ABDAY_4); + DO_NL_S(ABDAY_5); + DO_NL_S(ABDAY_6); + DO_NL_S(ABDAY_7); + + DO_NL_S(DAY_1); + DO_NL_S(DAY_2); + DO_NL_S(DAY_3); + DO_NL_S(DAY_4); + DO_NL_S(DAY_5); + DO_NL_S(DAY_6); + DO_NL_S(DAY_7); + + DO_NL_S(ABMON_1); + DO_NL_S(ABMON_2); + DO_NL_S(ABMON_3); + DO_NL_S(ABMON_4); + DO_NL_S(ABMON_5); + DO_NL_S(ABMON_6); + DO_NL_S(ABMON_7); + DO_NL_S(ABMON_8); + DO_NL_S(ABMON_9); + DO_NL_S(ABMON_10); + DO_NL_S(ABMON_11); + DO_NL_S(ABMON_12); + + DO_NL_S(MON_1); + DO_NL_S(MON_2); + DO_NL_S(MON_3); + DO_NL_S(MON_4); + DO_NL_S(MON_5); + DO_NL_S(MON_6); + DO_NL_S(MON_7); + DO_NL_S(MON_8); + DO_NL_S(MON_9); + DO_NL_S(MON_10); + DO_NL_S(MON_11); + DO_NL_S(MON_12); + + DO_NL_S(AM_STR); + DO_NL_S(PM_STR); + + DO_NL_S(D_T_FMT); + DO_NL_S(D_FMT); + DO_NL_S(T_FMT); + DO_NL_S(T_FMT_AMPM); +/* DO_NL_S(ERA); */ + { + const char *p = nl_langinfo(ERA); + if (!p || !*p) { + printf("ERA = (none)\n"); + } else { + int i; + printf("ERA:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + if (!*p) break; + } + } + } + + DO_NL_S(ERA_YEAR); /* non SuSv3 */ + DO_NL_S(ERA_D_FMT); +/* DO_NL_S(ALT_DIGITS); */ + { + const char *p = nl_langinfo(ALT_DIGITS); + if (!p || !*p) { + printf("ALT_DIGITS = (none)\n"); + } else { + int i; + printf("ALT_DIGITS:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + } + } + } + DO_NL_S(ERA_D_T_FMT); + DO_NL_S(ERA_T_FMT); + +#ifdef DO_EXTRA + DO_NL_C(_NL_TIME_WEEK_NDAYS); + DO_NL_I(_NL_TIME_WEEK_1STDAY); /* grr... this won't work with 16bit ptrs */ + DO_NL_C(_NL_TIME_WEEK_1STWEEK); + DO_NL_C(_NL_TIME_FIRST_WEEKDAY); + DO_NL_C(_NL_TIME_FIRST_WORKDAY); + DO_NL_C(_NL_TIME_CAL_DIRECTION); + DO_NL_S(_NL_TIME_TIMEZONE); + DO_NL_S(_DATE_FMT); +#endif + + printf("messages\n"); + + DO_NL_S(YESEXPR); + DO_NL_S(NOEXPR); + DO_NL_S(YESSTR); + DO_NL_S(NOSTR); + +#ifdef DO_EXTRA + + printf("paper\n"); + + DO_NL_I(_NL_PAPER_HEIGHT); + DO_NL_I(_NL_PAPER_WIDTH); + + printf("name\n"); + + DO_NL_S(_NL_NAME_NAME_FMT); + DO_NL_S(_NL_NAME_NAME_GEN); + DO_NL_S(_NL_NAME_NAME_MR); + DO_NL_S(_NL_NAME_NAME_MRS); + DO_NL_S(_NL_NAME_NAME_MISS); + DO_NL_S(_NL_NAME_NAME_MS); + + printf("address\n"); + + DO_NL_S(_NL_ADDRESS_POSTAL_FMT); + DO_NL_S(_NL_ADDRESS_COUNTRY_NAME); + DO_NL_S(_NL_ADDRESS_COUNTRY_POST); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB2); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB3); + DO_NL_S(_NL_ADDRESS_COUNTRY_CAR); + DO_NL_I(_NL_ADDRESS_COUNTRY_NUM); + DO_NL_S(_NL_ADDRESS_COUNTRY_ISBN); + DO_NL_S(_NL_ADDRESS_LANG_NAME); + DO_NL_S(_NL_ADDRESS_LANG_AB); + DO_NL_S(_NL_ADDRESS_LANG_TERM); + DO_NL_S(_NL_ADDRESS_LANG_LIB); + + printf("telephone\n"); + + DO_NL_S(_NL_TELEPHONE_TEL_INT_FMT); + DO_NL_S(_NL_TELEPHONE_TEL_DOM_FMT); + DO_NL_S(_NL_TELEPHONE_INT_SELECT); + DO_NL_S(_NL_TELEPHONE_INT_PREFIX); + + printf("measurement\n"); + + DO_NL_C(_NL_MEASUREMENT_MEASUREMENT); /* 1 is metric, 2 is US */ + + printf("identification\n"); + + DO_NL_S(_NL_IDENTIFICATION_TITLE); + DO_NL_S(_NL_IDENTIFICATION_SOURCE); + DO_NL_S(_NL_IDENTIFICATION_ADDRESS); + DO_NL_S(_NL_IDENTIFICATION_CONTACT); + DO_NL_S(_NL_IDENTIFICATION_EMAIL); + DO_NL_S(_NL_IDENTIFICATION_TEL); + DO_NL_S(_NL_IDENTIFICATION_FAX); + DO_NL_S(_NL_IDENTIFICATION_LANGUAGE); + DO_NL_S(_NL_IDENTIFICATION_TERRITORY); + DO_NL_S(_NL_IDENTIFICATION_AUDIENCE); + DO_NL_S(_NL_IDENTIFICATION_APPLICATION); + DO_NL_S(_NL_IDENTIFICATION_ABBREVIATION); + DO_NL_S(_NL_IDENTIFICATION_REVISION); + DO_NL_S(_NL_IDENTIFICATION_DATE); + DO_NL_S(_NL_IDENTIFICATION_CATEGORY); + +#endif + + return EXIT_SUCCESS; +} diff --git a/test/locale/xfrm-test.c b/test/locale/xfrm-test.c new file mode 100644 index 0000000..199bb6b --- /dev/null +++ b/test/locale/xfrm-test.c @@ -0,0 +1,144 @@ +/* Test collation function via transformation using real data. + Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +struct lines +{ + char *xfrm; + char *line; +}; + +static int xstrcmp (const void *, const void *); + +int +main (int argc, char *argv[]) +{ + int result = 0; + size_t nstrings, nstrings_max; + struct lines *strings; + char *line = NULL; + size_t len = 0; + size_t n; + + if (argc < 2) + error (1, 0, "usage: %s ", argv[0]); + + setlocale (LC_ALL, ""); + + nstrings_max = 100; + nstrings = 0; + strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines)); + if (strings == NULL) + { + perror (argv[0]); + exit (1); + } + + while (1) + { + char saved, *newp; + int needed; + int l; + if (getline (&line, &len, stdin) < 0) + break; + + if (nstrings == nstrings_max) + { + strings = (struct lines *) realloc (strings, + (nstrings_max *= 2) + * sizeof (*strings)); + if (strings == NULL) + { + perror (argv[0]); + exit (1); + } + } + strings[nstrings].line = strdup (line); + l = strcspn (line, ":(;"); + while (l > 0 && isspace (line[l - 1])) + --l; + + saved = line[l]; + line[l] = '\0'; + needed = strxfrm (NULL, line, 0); + newp = malloc (needed + 1); + strxfrm (newp, line, needed + 1); + strings[nstrings].xfrm = newp; + line[l] = saved; + ++nstrings; + } + free (line); + + /* First shuffle. */ + srandom (atoi (argv[1])); + for (n = 0; n < 10 * nstrings; ++n) + { + int r1, r2, r; + size_t idx1 = random () % nstrings; + size_t idx2 = random () % nstrings; + struct lines tmp = strings[idx1]; + strings[idx1] = strings[idx2]; + strings[idx2] = tmp; + + /* While we are at it a first little test. */ + r1 = strcmp (strings[idx1].xfrm, strings[idx2].xfrm); + r2 = strcmp (strings[idx2].xfrm, strings[idx1].xfrm); + r = -(r1 ^ r2); + if (r) + r /= abs (r1 ^ r2); + + if (r < 0 || (r == 0 && (r1 != 0 || r2 != 0)) + || (r > 0 && (r1 ^ r2) >= 0)) + printf ("collate wrong: %d vs. %d\n", r1, r2); + } + + /* Now sort. */ + qsort (strings, nstrings, sizeof (struct lines), xstrcmp); + + /* Print the result. */ + for (n = 0; n < nstrings; ++n) + { + fputs (strings[n].line, stdout); + free (strings[n].line); + free (strings[n].xfrm); + } + free (strings); + + return result; +} + + +static int +xstrcmp (ptr1, ptr2) + const void *ptr1; + const void *ptr2; +{ + const struct lines *l1 = (const struct lines *) ptr1; + const struct lines *l2 = (const struct lines *) ptr2; + + return strcmp (l1->xfrm, l2->xfrm); +} diff --git a/test/malloc/Makefile b/test/malloc/Makefile new file mode 100644 index 0000000..3e92e6c --- /dev/null +++ b/test/malloc/Makefile @@ -0,0 +1,6 @@ +# uClibc malloc tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS_DISABLED := time_malloc + +include ../Test.mak diff --git a/test/malloc/malloc-standard-alignment.c b/test/malloc/malloc-standard-alignment.c new file mode 100644 index 0000000..71e5023 --- /dev/null +++ b/test/malloc/malloc-standard-alignment.c @@ -0,0 +1,42 @@ +/* exercise a bug found in malloc-standard when alignment + * values are out of whack and cause a small overflow into + * actual user data. + */ + +#include +#include +#include + +#define ok(p) ((void*)p > (void*)0x1000) +#define x \ + do { \ + printf("%i: phead = %p, phead->link @ %p = %p %s\n", \ + __LINE__, phead, \ + ok(phead) ? &phead->link : 0, \ + ok(phead) ? phead->link : 0, \ + ok(phead) ? phead->link == 0 ? "" : "!!!!!!!!!!!" : ""); \ + if (phead->link != NULL) exit(1); \ + } while (0); + +struct llist_s { + void *data; + struct llist_s *link; +} *phead; + +int main(int argc, char *argv[]) +{ + char *line, *reg; + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + phead = malloc(sizeof(*phead)); + phead->link = NULL; + +x line = malloc(80); +x line = realloc(line, 2); +x reg = malloc(32); +x free(line); + +x return 0; +} diff --git a/test/malloc/malloc.c b/test/malloc/malloc.c new file mode 100644 index 0000000..ca7c5f9 --- /dev/null +++ b/test/malloc/malloc.c @@ -0,0 +1,81 @@ + +#include +#include +#include +#include + +#define N_PTRS 1000 +#define N_ALLOCS 10000 +#define MAX_SIZE 0x10000 + +#define random_size() (random()%MAX_SIZE) +#define random_ptr() (random()%N_PTRS) + +int test1(void); +int test2(void); + +int main(int argc, char *argv[]) +{ + return test1() + test2(); +} + +int test1(void) +{ + void **ptrs; + int i,j; + int size; + int ret = 0; + + srandom(0x19730929); + + ptrs = malloc(N_PTRS*sizeof(void *)); + + for(i=0; i +#include +#include + +#define size_t unsigned int + +int +main (int argc, char *argv[]) +{ + char *dummy0; + char *dummy1; + char *fill_info_table1; + char *over_top; + size_t over_top_size = 0x3000; + char *over_top_dup; + size_t over_top_dup_size = 0x7000; + char *x; + size_t i; + + /* Here's what memory is supposed to look like (hex): + size contents + 3000 original_info_table, later fill_info_table1 + 3fa000 dummy0 + 3fa000 dummy1 + 6000 info_table_2 + 3000 over_top + + */ + /* mem: original_info_table */ + dummy0 = malloc (0x3fa000); + /* mem: original_info_table, dummy0 */ + dummy1 = malloc (0x3fa000); + /* mem: free, dummy0, dummy1, info_table_2 */ + fill_info_table1 = malloc (0x3000); + /* mem: fill_info_table1, dummy0, dummy1, info_table_2 */ + + x = malloc (0x1000); + free (x); + /* mem: fill_info_table1, dummy0, dummy1, info_table_2, freexx */ + + /* This is what loses; info_table_2 and freexx get combined unbeknownst + to mmalloc, and mmalloc puts over_top in a section of memory which + is on the free list as part of another block (where info_table_2 had + been). */ + over_top = malloc (over_top_size); + over_top_dup = malloc (over_top_dup_size); + memset (over_top, 0, over_top_size); + memset (over_top_dup, 1, over_top_dup_size); + + for (i = 0; i < over_top_size; ++i) + if (over_top[i] != 0) + { + printf ("FAIL: malloc expands info table\n"); + return 0; + } + + for (i = 0; i < over_top_dup_size; ++i) + if (over_top_dup[i] != 1) + { + printf ("FAIL: malloc expands info table\n"); + return 0; + } + + printf ("PASS: malloc expands info table\n"); + return 0; +} diff --git a/test/malloc/realloc-can-shrink.c b/test/malloc/realloc-can-shrink.c new file mode 100644 index 0000000..33249db --- /dev/null +++ b/test/malloc/realloc-can-shrink.c @@ -0,0 +1,17 @@ +/* make sure that realloc() can properly shrink buffers */ + +#include + +#define LARGE_BUFFER (1 << 20) /* idea is to span a lot of pages */ + +int main(int argc, char *argv[]) +{ + int count = 20; + char *ptr = NULL; + while (count--) { + ptr = realloc(ptr, LARGE_BUFFER); + ptr = realloc(ptr, 1); + } + free(ptr); + return 0; +} diff --git a/test/malloc/realloc0.c b/test/malloc/realloc0.c new file mode 100644 index 0000000..62ae39d --- /dev/null +++ b/test/malloc/realloc0.c @@ -0,0 +1,13 @@ +#include +#include + +int main(int argc, char **argv) +{ + void *ptr = NULL; + ptr = realloc(ptr, 0); + printf("realloc(NULL, 0) -- pointer = %p\n", ptr); + + ptr = malloc(0); + printf("malloc(0) -- pointer = %p\n", ptr); + return 0; +} diff --git a/test/malloc/testmalloc.c b/test/malloc/testmalloc.c new file mode 100644 index 0000000..42707d2 --- /dev/null +++ b/test/malloc/testmalloc.c @@ -0,0 +1,101 @@ +#include +#include +#include + + +struct list { + struct list *next; +}; + +int main(void) +{ + int z=999; + int *y=&z; + int *x=NULL; + struct list *save; + struct list *lp; + int i; + + + printf("pointer to x is %p\n", x); + printf("pointer to y is %p\n", y); + x=malloc(sizeof(int)*2000); + printf("pointer to x is %p\n", x); + y=malloc(sizeof(int)*100); + printf("pointer to y is %p\n", y); + free(x); + free(y); + printf("about to free(0)\n"); + free(0); + + x=malloc(13); + printf("x = %p\n", x); + memcpy(x, "Small string", 13); + printf("0x%p test string1: %s\n", x, (char *)x); + y = realloc(x, 36); + printf("0x%p test string1: %s\n", y, (char *)y); + memcpy(y, "********** Larger string **********", 36); + printf("0x%p test string2: %s\n", y, (char *)y); + free(y); + + + printf("Allocate 100 nodes 500 bytes each\n"); + save = 0; + for (i=0; i<100; i++) { + lp = malloc(500); + if (lp == 0) { + printf("loop 1: malloc returned 0\n"); + goto Failed; + } + lp->next = save; + save = lp; + } + + printf("freeing 100 nodes\n"); + while (save) { + lp = save; + save = save->next; + free(lp); + } + + printf("try realloc 100 times \n"); + lp = 0; + for (i=1; i<=100; i++) { + lp = realloc(lp, i*200); + if (lp == 0) { + printf("loop 3: realloc returned 0\n"); + goto Failed; + } + } + { + void *unused_ret = realloc(lp, 0); + (void) unused_ret; + } + + printf("Allocate another 100 nodes 600 bytes each\n"); + save = 0; + for (i=0; i<100; i++) { + lp = malloc(600); + if (lp == 0) { + printf("loop 2: malloc returned 0\n"); + goto Failed; + } + lp->next = save; + save = lp; + } + + printf("freeing 100 nodes\n"); + while (save) { + lp = save; + save = save->next; + free(lp); + } + + + printf("alloc test PASSED\n"); + exit(0); + +Failed: + printf("!!!!!!!!!!!! alloc test FAILED. !!!!!!!!!!!!!!!\n"); + exit(1); +} diff --git a/test/malloc/time_malloc.c b/test/malloc/time_malloc.c new file mode 100644 index 0000000..0b62665 --- /dev/null +++ b/test/malloc/time_malloc.c @@ -0,0 +1,62 @@ +#include +#define REPS (100000) +int sizes[] = { + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50, + 100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50 +}; +#define NUM (sizeof sizes / sizeof sizes[0]) +int main () +{ + int i, j; + void *allocs[NUM]; + for (i = 0; i < REPS; i++) { + for (j = 0; j < NUM; j++) { + allocs[j] = malloc(sizes[j]); + } + for (j = 0; j < NUM; j++) { + free(allocs[j]); + } + } + return 0; +} + diff --git a/test/malloc/tst-calloc.c b/test/malloc/tst-calloc.c new file mode 100644 index 0000000..b3594c9 --- /dev/null +++ b/test/malloc/tst-calloc.c @@ -0,0 +1,126 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* Number of samples per size. */ +#define N 50000 + + +static void +fixed_test (int size) +{ + char *ptrs[N]; + int i; + + for (i = 0; i < N; ++i) + { + int j; + + ptrs[i] = (char *) calloc (1, size); + + if (ptrs[i] == NULL) + break; + + for (j = 0; j < size; ++j) + { + if (ptrs[i][j] != '\0') + error (EXIT_FAILURE, 0, + "byte not cleared (size %d, element %d, byte %d)", + size, i, j); + ptrs[i][j] = '\xff'; + } + } + + while (i-- > 0) + free (ptrs[i]); +} + + +static void +random_test (void) +{ + char *ptrs[N]; + int i; + + for (i = 0; i < N; ++i) + { + int j; + int n = 1 + random () % 10; + int elem = 1 + random () % 100; + int size = n * elem; + + ptrs[i] = (char *) calloc (n, elem); + + if (ptrs[i] == NULL) + break; + + for (j = 0; j < size; ++j) + { + if (ptrs[i][j] != '\0') + error (EXIT_FAILURE, 0, + "byte not cleared (size %d, element %d, byte %d)", + size, i, j); + ptrs[i][j] = '\xff'; + } + } + + while (i-- > 0) + free (ptrs[i]); +} + + +static void +null_test (void) +{ + /* If the size is 0 the result is implementation defined. Just make + sure the program doesn't crash. */ + calloc (0, 0); + calloc (0, UINT_MAX); + calloc (UINT_MAX, 0); + calloc (0, ~((size_t) 0)); + calloc (~((size_t) 0), 0); +} + + +int +main (void) +{ + /* We are allocating blocks with `calloc' and check whether every + block is completely cleared. We first try this for some fixed + times and then with random size. */ + fixed_test (15); + fixed_test (5); + fixed_test (17); + fixed_test (6); + fixed_test (31); + fixed_test (96); + + random_test (); + + null_test (); + + return 0; +} diff --git a/test/malloc/tst-malloc.c b/test/malloc/tst-malloc.c new file mode 100644 index 0000000..468e1d4 --- /dev/null +++ b/test/malloc/tst-malloc.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +static int errors = 0; + +static void +merror (const char *msg) +{ + ++errors; + printf ("Error: %s\n", msg); +} + +int +main (void) +{ + void *p; + int save; + + errno = 0; + + p = malloc (-1); + save = errno; + + if (p != NULL) + merror ("malloc (-1) succeeded."); + + if (p == NULL && save != ENOMEM) + merror ("errno is not set correctly"); + + p = malloc (10); + if (p == NULL) + merror ("malloc (10) failed."); + + /* realloc (p, 0) == free (p). */ + p = realloc (p, 0); + if (p != NULL) + merror ("realloc (p, 0) failed."); + + p = malloc (0); +#if !defined(__UCLIBC__) || defined(__MALLOC_GLIBC_COMPAT__) + if (p == NULL) +#else + if (p != NULL) +#endif + merror ("malloc (0) failed."); + + p = realloc (p, 0); + if (p != NULL) + merror ("realloc (p, 0) failed."); + + return errors != 0; +} diff --git a/test/malloc/tst-mallocfork.c b/test/malloc/tst-mallocfork.c new file mode 100644 index 0000000..5bb1d76 --- /dev/null +++ b/test/malloc/tst-mallocfork.c @@ -0,0 +1,51 @@ +/* Derived from the test case in + http://sourceware.org/bugzilla/show_bug.cgi?id=838. */ +#include +#include +#include +#include +#include +#include +#include + +static void +sig_handler (int signum) +{ + pid_t child = vfork (); + if (child == 0) + exit (0); + TEMP_FAILURE_RETRY (waitpid (child, NULL, 0)); +} + +static int +do_test (void) +{ + pid_t parent = getpid (); + + struct sigaction action = { .sa_handler = sig_handler }; + sigemptyset (&action.sa_mask); + + malloc (sizeof (int)); + + if (sigaction (SIGALRM, &action, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + /* Create a child that sends the signal to be caught. */ + pid_t child = vfork (); + if (child == 0) + { + if (kill (parent, SIGALRM) == -1) + perror ("kill"); + exit (0); + } + + TEMP_FAILURE_RETRY (waitpid (child, NULL, 0)); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/malloc/tst-mcheck.c b/test/malloc/tst-mcheck.c new file mode 100644 index 0000000..af72c04 --- /dev/null +++ b/test/malloc/tst-mcheck.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +static int errors = 0; + +static void +merror (const char *msg) +{ + ++errors; + printf ("Error: %s\n", msg); +} + +int +main (void) +{ + void *p, *q; + + errno = 0; + + p = malloc (-1); + + if (p != NULL) + merror ("malloc (-1) succeeded."); + else if (errno != ENOMEM) + merror ("errno is not set correctly."); + + p = malloc (10); + if (p == NULL) + merror ("malloc (10) failed."); + + p = realloc (p, 0); + if (p != NULL) + merror ("realloc (p, 0) failed."); + + p = malloc (0); +#if !defined(__UCLIBC__) || defined(__MALLOC_GLIBC_COMPAT__) + if (p == NULL) +#else + if (p != NULL) +#endif + merror ("malloc (0) failed."); + + p = realloc (p, 0); + if (p != NULL) + merror ("realloc (p, 0) failed."); + + q = malloc (256); + if (q == NULL) + merror ("malloc (256) failed."); + + p = malloc (512); + if (p == NULL) + merror ("malloc (512) failed."); + + if (realloc (p, -256) != NULL) + merror ("realloc (p, -256) succeeded."); + else if (errno != ENOMEM) + merror ("errno is not set correctly."); + + free (p); + + p = malloc (512); + if (p == NULL) + merror ("malloc (512) failed."); + + if (realloc (p, -1) != NULL) + merror ("realloc (p, -1) succeeded."); + else if (errno != ENOMEM) + merror ("errno is not set correctly."); + + free (p); + free (q); + + return errors != 0; +} diff --git a/test/malloc/tst-obstack.c b/test/malloc/tst-obstack.c new file mode 100644 index 0000000..769697f --- /dev/null +++ b/test/malloc/tst-obstack.c @@ -0,0 +1,64 @@ +/* Test case by Alexandre Duret-Lutz . */ +#include +#include +#include +#include + +#define obstack_chunk_alloc verbose_malloc +#define obstack_chunk_free verbose_free +#define ALIGN_BOUNDARY 64 +#define ALIGN_MASK (ALIGN_BOUNDARY - 1) +#define OBJECT_SIZE 1000 + +static void * +verbose_malloc (size_t size) +{ + void *buf = malloc (size); + printf ("malloc (%zu) => %p\n", size, buf); + return buf; +} + +static void +verbose_free (void *buf) +{ + free (buf); + printf ("free (%p)\n", buf); +} + +int +main (void) +{ + int result = 0; + int align = 2; + + while (align <= 64) + { + struct obstack obs; + int i; + int align_mask = align - 1; + + printf ("\n Alignment mask: %d\n", align_mask); + + obstack_init (&obs); + obstack_alignment_mask (&obs) = align_mask; + /* finish an empty object to take alignment into account */ + obstack_finish (&obs); + + /* let's allocate some objects and print their addresses */ + for (i = 15; i > 0; --i) + { + void *obj = obstack_alloc (&obs, OBJECT_SIZE); + + printf ("obstack_alloc (%u) => %p \t%s\n", OBJECT_SIZE, obj, + ((uintptr_t) obj & align_mask) ? "(not aligned)" : ""); + result |= ((uintptr_t) obj & align_mask) != 0; + } + + /* clean up */ + obstack_free (&obs, 0); + + align <<= 1; + } + + return result; +} diff --git a/test/malloc/tst-valloc.c b/test/malloc/tst-valloc.c new file mode 100644 index 0000000..643a0dd --- /dev/null +++ b/test/malloc/tst-valloc.c @@ -0,0 +1,23 @@ +/* Test case by Stephen Tweedie . */ +#include +#include +#include + +int +main (void) +{ + char *p; + int pagesize = getpagesize (); + int i; + + p = valloc (pagesize); + i = (long int) p; + + if ((i & (pagesize-1)) != 0) + { + fprintf (stderr, "Alignment problem: valloc returns %p\n", p); + exit (1); + } + + return 0; +} diff --git a/test/math/Makefile b/test/math/Makefile new file mode 100644 index 0000000..09f5425 --- /dev/null +++ b/test/math/Makefile @@ -0,0 +1,26 @@ +# uClibc math tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS := basic-test rint tst-definitions test-fpucw test-float test-ifloat test-double test-idouble +ifeq ($(strip $(UCLIBC_HAS_LONG_DOUBLE_MATH)),y) +TESTS += test-ldouble test-ildouble +endif + +include ../Test.mak + +DODIFF_rint := 1 + +# NOTE: For basic-test we must disable the floating point optimization. +# Only for sh architecture because in the other architecture are disabled. +ifeq ($(TARGET_ARCH),sh) +CFLAGS_basic-test := -mieee +endif +EXTRA_CFLAGS := -fno-builtin +EXTRA_LDFLAGS := -lm + +PERL := /usr/bin/perl +ulps-file := $(firstword $(wildcard $(config-sysdirs:%=$(..)%/libm-test-ulps))) +libm-test.c: $(ulps-file) libm-test.inc gen-libm-test.pl + $(Q)$(PERL) ./gen-libm-test.pl -u $< ./libm-test.inc -o "." 2>&1 > /dev/null +EXTRA_CLEAN := libm-test.c libm-test-ulps.h +$(TARGETS): libm-test.c diff --git a/test/math/basic-test.c b/test/math/basic-test.c new file mode 100644 index 0000000..e42c014 --- /dev/null +++ b/test/math/basic-test.c @@ -0,0 +1,123 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +static int errors = 0; + + +static void +check (const char *testname, int result) +{ + if (!result) { + printf ("Failure: %s\n", testname); + errors++; + } +} + +#define TEST_FUNC(NAME, FLOAT, NANFUNC, EPSILON, HUGEVAL) \ +static void \ +NAME (void) \ +{ \ + /* Variables are declared volatile to forbid some compiler \ + optimizations. */ \ + volatile FLOAT Inf_var, NaN_var, zero_var, one_var; \ + FLOAT x1, x2; \ + \ + zero_var = 0.0; \ + one_var = 1.0; \ + NaN_var = zero_var/zero_var; \ + Inf_var = one_var / zero_var; \ + \ + (void) &zero_var; \ + (void) &one_var; \ + (void) &NaN_var; \ + (void) &Inf_var; \ + \ + \ + check (#FLOAT " isinf (inf) == 1", isinf (Inf_var) == 1); \ + check (#FLOAT " isinf (-inf) == -1", isinf (-Inf_var) == -1); \ + check (#FLOAT " !isinf (1)", !(isinf (one_var))); \ + check (#FLOAT " !isinf (NaN)", !(isinf (NaN_var))); \ + \ + check (#FLOAT " isnan (NaN)", isnan (NaN_var)); \ + check (#FLOAT " isnan (-NaN)", isnan (-NaN_var)); \ + check (#FLOAT " !isnan (1)", !(isnan (one_var))); \ + check (#FLOAT " !isnan (inf)", !(isnan (Inf_var))); \ + \ + check (#FLOAT " inf == inf", Inf_var == Inf_var); \ + check (#FLOAT " -inf == -inf", -Inf_var == -Inf_var); \ + check (#FLOAT " inf != -inf", Inf_var != -Inf_var); \ + check (#FLOAT " NaN != NaN", NaN_var != NaN_var); \ + \ + /* \ + the same tests but this time with NAN from \ + NAN is a double const \ + */ \ + check (#FLOAT " isnan (NAN)", isnan (NAN)); \ + check (#FLOAT " isnan (-NAN)", isnan (-NAN)); \ + check (#FLOAT " !isinf (NAN)", !(isinf (NAN))); \ + check (#FLOAT " !isinf (-NAN)", !(isinf (-NAN))); \ + check (#FLOAT " NAN != NAN", NAN != NAN); \ + \ + /* \ + And again with the value returned by the `nan' function. \ + */ \ + check (#FLOAT " isnan (NAN)", isnan (NANFUNC (""))); \ + check (#FLOAT " isnan (-NAN)", isnan (-NANFUNC (""))); \ + check (#FLOAT " !isinf (NAN)", !(isinf (NANFUNC ("")))); \ + check (#FLOAT " !isinf (-NAN)", !(isinf (-NANFUNC ("")))); \ + check (#FLOAT " NAN != NAN", NANFUNC ("") != NANFUNC ("")); \ + \ + /* test if EPSILON is ok */ \ + x1 = 1.0; \ + x2 = x1 + EPSILON; \ + check (#FLOAT " 1 != 1+EPSILON", x1 != x2); \ + \ + x1 = 1.0; \ + x2 = x1 - EPSILON; \ + check (#FLOAT " 1 != 1-EPSILON", x1 != x2); \ + \ + /* test if HUGE_VALx is ok */ \ + x1 = HUGEVAL; \ + check (#FLOAT " isinf (HUGE_VALx) == +1", isinf (x1) == +1); \ + x1 = - HUGEVAL; \ + check (#FLOAT " isinf (-HUGE_VALx) == -1", isinf (x1) == -1); \ +} + +TEST_FUNC (float_test, float, nanf, FLT_EPSILON, HUGE_VALF) +TEST_FUNC (double_test, double, nan, DBL_EPSILON, HUGE_VAL) +#ifndef NO_LONG_DOUBLE +TEST_FUNC (ldouble_test, long double, nanl, LDBL_EPSILON, HUGE_VALL) +#endif + +int +main (void) +{ + float_test (); + double_test (); + +#ifndef NO_LONG_DOUBLE + ldouble_test (); +#endif + + return errors != 0; +} diff --git a/test/math/fenv.h b/test/math/fenv.h new file mode 100644 index 0000000..0025a62 --- /dev/null +++ b/test/math/fenv.h @@ -0,0 +1,3 @@ +/* until we support fenv ... */ +#define feclearexcept(X) +#define fetestexcept(X) (0) diff --git a/test/math/gen-libm-test.pl b/test/math/gen-libm-test.pl new file mode 100755 index 0000000..26f819a --- /dev/null +++ b/test/math/gen-libm-test.pl @@ -0,0 +1,738 @@ +#!/usr/bin/perl -w +# Copyright (C) 1999 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Andreas Jaeger , 1999. + +# The GNU C 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. + +# The GNU C 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 the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# This file needs to be tidied up +# Note that functions and tests share the same namespace. + +# Information about tests are stored in: %results +# $results{$test}{"kind"} is either "fct" or "test" and flags whether this +# is a maximal error of a function or a single test. +# $results{$test}{"type"} is the result type, e.g. normal or complex. +# $results{$test}{"has_ulps"} is set if deltas exist. +# $results{$test}{"has_fails"} is set if exptected failures exist. +# In the following description $type and $float are: +# - $type is either "normal", "real" (for the real part of a complex number) +# or "imag" (for the imaginary part # of a complex number). +# - $float is either of float, ifloat, double, idouble, ldouble, ildouble; +# It represents the underlying floating point type (float, double or long +# double) and if inline functions (the leading i stands for inline) +# are used. +# $results{$test}{$type}{"fail"}{$float} is defined and has a 1 if +# the test is expected to fail +# $results{$test}{$type}{"ulp"}{$float} is defined and has a delta as value + + +use Getopt::Std; + +use strict; + +use vars qw ($input $output); +use vars qw (%results); +use vars qw (@tests @functions); +use vars qw ($count); +use vars qw (%beautify @all_floats); +use vars qw ($output_dir $ulps_file); + +# all_floats is sorted and contains all recognised float types +@all_floats = ('double', 'float', 'idouble', + 'ifloat', 'ildouble', 'ldouble'); + +%beautify = + ( "minus_zero" => "-0", + "plus_zero" => "+0", + "minus_infty" => "-inf", + "plus_infty" => "inf", + "nan_value" => "NaN", + "M_El" => "e", + "M_E2l" => "e^2", + "M_E3l" => "e^3", + "M_LOG10El", "log10(e)", + "M_PIl" => "pi", + "M_PI_34l" => "3/4 pi", + "M_PI_2l" => "pi/2", + "M_PI_4l" => "pi/4", + "M_PI_6l" => "pi/6", + "M_PI_34_LOG10El" => "3/4 pi*log10(e)", + "M_PI_LOG10El" => "pi*log10(e)", + "M_PI2_LOG10El" => "pi/2*log10(e)", + "M_PI4_LOG10El" => "pi/4*log10(e)", + "M_LOG_SQRT_PIl" => "log(sqrt(pi))", + "M_LOG_2_SQRT_PIl" => "log(2*sqrt(pi))", + "M_2_SQRT_PIl" => "2 sqrt (pi)", + "M_SQRT_PIl" => "sqrt (pi)", + "INVALID_EXCEPTION" => "invalid exception", + "DIVIDE_BY_ZERO_EXCEPTION" => "division by zero exception", + "INVALID_EXCEPTION_OK" => "invalid exception allowed", + "DIVIDE_BY_ZERO_EXCEPTION_OK" => "division by zero exception allowed", + "EXCEPTIONS_OK" => "exceptions allowed", + "IGNORE_ZERO_INF_SIGN" => "sign of zero/inf not specified", +"INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN" => "invalid exception and sign of zero/inf not specified" + ); + + +# get Options +# Options: +# u: ulps-file +# h: help +# o: output-directory +# n: generate new ulps file +use vars qw($opt_u $opt_h $opt_o $opt_n); +getopts('u:o:nh'); + +$ulps_file = 'libm-test-ulps'; +$output_dir = ''; + +if ($opt_h) { + print "Usage: gen-libm-test.pl [OPTIONS]\n"; + print " -h print this help, then exit\n"; + print " -o DIR directory where generated files will be placed\n"; + print " -n only generate sorted file NewUlps from libm-test-ulps\n"; + print " -u FILE input file with ulps\n"; + exit 0; +} + +$ulps_file = $opt_u if ($opt_u); +$output_dir = $opt_o if ($opt_o); + +$input = "libm-test.inc"; +$output = "${output_dir}libm-test.c"; + +$count = 0; + +&parse_ulps ($ulps_file); +&generate_testfile ($input, $output) unless ($opt_n); +&output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n); +&print_ulps_file ("${output_dir}NewUlps") if ($opt_n); + +# Return a nicer representation +sub beautify { + my ($arg) = @_; + my ($tmp); + + if (exists $beautify{$arg}) { + return $beautify{$arg}; + } + if ($arg =~ /^-/) { + $tmp = $arg; + $tmp =~ s/^-//; + if (exists $beautify{$tmp}) { + return '-' . $beautify{$tmp}; + } + } + if ($arg =~ /[0-9]L$/) { + $arg =~ s/L$//; + } + return $arg; +} + +# Return a nicer representation of a complex number +sub build_complex_beautify { + my ($r, $i) = @_; + my ($str1, $str2); + + $str1 = &beautify ($r); + $str2 = &beautify ($i); + if ($str2 =~ /^-/) { + $str2 =~ s/^-//; + $str1 .= ' - ' . $str2; + } else { + $str1 .= ' + ' . $str2; + } + $str1 .= ' i'; + return $str1; +} + +# Return name of a variable +sub get_variable { + my ($number) = @_; + + return "x" if ($number == 1); + return "y" if ($number == 2); + return "z" if ($number == 3); + # return x1,x2,... + $number =-3; + return "x$number"; +} + +# Add a new test to internal data structures and fill in the +# ulps, failures and exception information for the C line. +sub new_test { + my ($test, $exception) = @_; + my $rest; + + # Add ulp, xfail + if (exists $results{$test}{'has_ulps'}) { + $rest = ", DELTA$count"; + } else { + $rest = ', 0'; + } + if (exists $results{$test}{'has_fails'}) { + $rest .= ", FAIL$count"; + } else { + $rest .= ', 0'; + } + if (defined $exception) { + $rest .= ", $exception"; + } else { + $rest .= ', 0'; + } + $rest .= ");\n"; + # We must increment here to keep @tests and count in sync + push @tests, $test; + ++$count; + return $rest; +} + +# Treat some functions especially. +# Currently only sincos needs extra treatment. +sub special_functions { + my ($file, $args) = @_; + my (@args, $str, $test, $cline); + + @args = split /,\s*/, $args; + + unless ($args[0] =~ /sincos/) { + die ("Don't know how to handle $args[0] extra."); + } + print $file " FUNC (sincos) ($args[1], &sin_res, &cos_res);\n"; + + $str = 'sincos (' . &beautify ($args[1]) . ', &sin_res, &cos_res)'; + # handle sin + $test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res'; + if ($#args == 4) { + $test .= " plus " . &beautify ($args[4]); + } + + $cline = " check_float (\"$test\", sin_res, $args[2]"; + $cline .= &new_test ($test, $args[4]); + print $file $cline; + + # handle cos + $test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res'; + $cline = " check_float (\"$test\", cos_res, $args[3]"; + # only tests once for exception + $cline .= &new_test ($test, undef); + print $file $cline; +} + +# Parse the arguments to TEST_x_y +sub parse_args { + my ($file, $descr, $args) = @_; + my (@args, $str, $descr_args, $descr_res, @descr); + my ($current_arg, $cline, $i); + my ($pre, $post, @special); + my ($extra_var, $call, $c_call); + + if ($descr eq 'extra') { + &special_functions ($file, $args); + return; + } + ($descr_args, $descr_res) = split /_/,$descr, 2; + + @args = split /,\s*/, $args; + + $call = "$args[0] ("; + + # Generate first the string that's shown to the user + $current_arg = 1; + $extra_var = 0; + @descr = split //,$descr_args; + for ($i = 0; $i <= $#descr; $i++) { + if ($i >= 1) { + $call .= ', '; + } + # FLOAT, int, long int, long long int + if ($descr[$i] =~ /f|i|l|L/) { + $call .= &beautify ($args[$current_arg]); + ++$current_arg; + next; + } + # &FLOAT, &int - argument is added here + if ($descr[$i] =~ /F|I/) { + ++$extra_var; + $call .= '&' . &get_variable ($extra_var); + next; + } + # complex + if ($descr[$i] eq 'c') { + $call .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]); + $current_arg += 2; + next; + } + + die ("$descr[$i] is unknown"); + } + $call .= ')'; + $str = "$call == "; + + # Result + @descr = split //,$descr_res; + foreach (@descr) { + if ($_ =~ /f|i|l|L/) { + $str .= &beautify ($args[$current_arg]); + ++$current_arg; + } elsif ($_ eq 'c') { + $str .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]); + $current_arg += 2; + } elsif ($_ eq 'b') { + # boolean + $str .= ($args[$current_arg] == 0) ? "false" : "true"; + ++$current_arg; + } elsif ($_ eq '1') { + ++$current_arg; + } else { + die ("$_ is unknown"); + } + } + # consistency check + if ($current_arg == $#args) { + die ("wrong number of arguments") + unless ($args[$current_arg] =~ /EXCEPTION|IGNORE_ZERO_INF_SIGN/); + } elsif ($current_arg < $#args) { + die ("wrong number of arguments"); + } elsif ($current_arg > ($#args+1)) { + die ("wrong number of arguments"); + } + + + # check for exceptions + if ($current_arg <= $#args) { + $str .= " plus " . &beautify ($args[$current_arg]); + } + + # Put the C program line together + # Reset some variables to start again + $current_arg = 1; + $extra_var = 0; + if (substr($descr_res,0,1) eq 'f') { + $cline = 'check_float' + } elsif (substr($descr_res,0,1) eq 'b') { + $cline = 'check_bool'; + } elsif (substr($descr_res,0,1) eq 'c') { + $cline = 'check_complex'; + } elsif (substr($descr_res,0,1) eq 'i') { + $cline = 'check_int'; + } elsif (substr($descr_res,0,1) eq 'l') { + $cline = 'check_long'; + } elsif (substr($descr_res,0,1) eq 'L') { + $cline = 'check_longlong'; + } + # Special handling for some macros: + $cline .= " (\"$str\", "; + if ($args[0] =~ /fpclassify|isnormal|isfinite|signbit/) { + $c_call = "$args[0] ("; + } else { + $c_call = " FUNC($args[0]) ("; + } + @descr = split //,$descr_args; + for ($i=0; $i <= $#descr; $i++) { + if ($i >= 1) { + $c_call .= ', '; + } + # FLOAT, int, long int, long long int + if ($descr[$i] =~ /f|i|l|L/) { + $c_call .= $args[$current_arg]; + $current_arg++; + next; + } + # &FLOAT, &int + if ($descr[$i] =~ /F|I/) { + ++$extra_var; + $c_call .= '&' . &get_variable ($extra_var); + next; + } + # complex + if ($descr[$i] eq 'c') { + $c_call .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])"; + $current_arg += 2; + next; + } + } + $c_call .= ')'; + $cline .= "$c_call, "; + + @descr = split //,$descr_res; + foreach (@descr) { + if ($_ =~ /b|f|i|l|L/ ) { + $cline .= $args[$current_arg]; + $current_arg++; + } elsif ($_ eq 'c') { + $cline .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])"; + $current_arg += 2; + } elsif ($_ eq '1') { + push @special, $args[$current_arg]; + ++$current_arg; + } + } + # Add ulp, xfail + $cline .= &new_test ($str, ($current_arg <= $#args) ? $args[$current_arg] : undef); + + # special treatment for some functions + if ($args[0] eq 'frexp') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_int (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'gamma' || $args[0] eq 'lgamma') { + $pre = " signgam = 0;\n"; + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets signgam to $special[0]"; + $post = " check_int (\"$str\", signgam, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'modf') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_float (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } elsif ($args[0] eq 'remquo') { + if (defined $special[0] && $special[0] ne "IGNORE") { + my ($str) = "$call sets x to $special[0]"; + $post = " check_int (\"$str\", x, $special[0]"; + $post .= &new_test ($str, undef); + } + } + + print $file $pre if (defined $pre); + + print $file " $cline"; + + print $file $post if (defined $post); +} + +# Generate libm-test.c +sub generate_testfile { + my ($input, $output) = @_; + my ($lasttext); + my (@args, $i, $str); + + open INPUT, $input or die ("Can't open $input: $!"); + open OUTPUT, ">$output" or die ("Can't open $output: $!"); + + # Replace the special macros + while () { + + # TEST_... + if (/^\s*TEST_/) { + my ($descr, $args); + chop; + ($descr, $args) = ($_ =~ /TEST_(\w+)\s*\((.*)\)/); + &parse_args (\*OUTPUT, $descr, $args); + next; + } + # START (function) + if (/START/) { + print OUTPUT " init_max_error ();\n"; + next; + } + # END (function) + if (/END/) { + my ($fct, $line, $type); + if (/complex/) { + s/,\s*complex\s*//; + $type = 'complex'; + } else { + $type = 'normal'; + } + ($fct) = ($_ =~ /END\s*\((.*)\)/); + if ($type eq 'complex') { + $line = " print_complex_max_error (\"$fct\", "; + } else { + $line = " print_max_error (\"$fct\", "; + } + if (exists $results{$fct}{'has_ulps'}) { + $line .= "DELTA$fct"; + } else { + $line .= '0'; + } + if (exists $results{$fct}{'has_fails'}) { + $line .= ", FAIL$fct"; + } else { + $line .= ', 0'; + } + $line .= ");\n"; + print OUTPUT $line; + push @functions, $fct; + next; + } + print OUTPUT; + } + close INPUT; + close OUTPUT; +} + + + +# Parse ulps file +sub parse_ulps { + my ($file) = @_; + my ($test, $type, $float, $eps, $kind); + + # $type has the following values: + # "normal": No complex variable + # "real": Real part of complex result + # "imag": Imaginary part of complex result + open ULP, $file or die ("Can't open $file: $!"); + while () { + chop; + # ignore comments and empty lines + next if /^#/; + next if /^\s*$/; + if (/^Test/) { + if (/Real part of:/) { + s/Real part of: //; + $type = 'real'; + } elsif (/Imaginary part of:/) { + s/Imaginary part of: //; + $type = 'imag'; + } else { + $type = 'normal'; + } + s/^.+\"(.*)\".*$/$1/; + $test = $_; + $kind = 'test'; + next; + } + if (/^Function: /) { + if (/Real part of/) { + s/Real part of //; + $type = 'real'; + } elsif (/Imaginary part of/) { + s/Imaginary part of //; + $type = 'imag'; + } else { + $type = 'normal'; + } + ($test) = ($_ =~ /^Function:\s*\"([a-zA-Z0-9_]+)\"/); + $kind = 'fct'; + next; + } + if (/^i?(float|double|ldouble):/) { + ($float, $eps) = split /\s*:\s*/,$_,2; + + if ($eps eq 'fail') { + $results{$test}{$type}{'fail'}{$float} = 1; + $results{$test}{'has_fails'} = 1; + } elsif ($eps eq "0") { + # ignore + next; + } else { + $results{$test}{$type}{'ulp'}{$float} = $eps; + $results{$test}{'has_ulps'} = 1; + } + if ($type =~ /^real|imag$/) { + $results{$test}{'type'} = 'complex'; + } elsif ($type eq 'normal') { + $results{$test}{'type'} = 'normal'; + } + $results{$test}{'kind'} = $kind; + next; + } + print "Skipping unknown entry: `$_'\n"; + } + close ULP; +} + + +# Clean up a floating point number +sub clean_up_number { + my ($number) = @_; + + # Remove trailing zeros + $number =~ s/0+$//; + $number =~ s/\.$//; + return $number; +} + +# Output a file which can be read in as ulps file. +sub print_ulps_file { + my ($file) = @_; + my ($test, $type, $float, $eps, $fct, $last_fct); + + $last_fct = ''; + open NEWULP, ">$file" or die ("Can't open $file: $!"); + print NEWULP "# Begin of automatic generation\n"; + # first the function calls + foreach $test (sort keys %results) { + next if ($results{$test}{'kind'} ne 'test'); + foreach $type ('real', 'imag', 'normal') { + if (exists $results{$test}{$type}) { + if (defined $results{$test}) { + ($fct) = ($test =~ /^(\w+)\s/); + if ($fct ne $last_fct) { + $last_fct = $fct; + print NEWULP "\n# $fct\n"; + } + } + if ($type eq 'normal') { + print NEWULP "Test \"$test\":\n"; + } elsif ($type eq 'real') { + print NEWULP "Test \"Real part of: $test\":\n"; + } elsif ($type eq 'imag') { + print NEWULP "Test \"Imaginary part of: $test\":\n"; + } + foreach $float (@all_floats) { + if (exists $results{$test}{$type}{'ulp'}{$float}) { + print NEWULP "$float: ", + &clean_up_number ($results{$test}{$type}{'ulp'}{$float}), + "\n"; + } + if (exists $results{$test}{$type}{'fail'}{$float}) { + print NEWULP "$float: fail\n"; + } + } + } + } + } + print NEWULP "\n# Maximal error of functions:\n"; + + foreach $fct (sort keys %results) { + next if ($results{$fct}{'kind'} ne 'fct'); + foreach $type ('real', 'imag', 'normal') { + if (exists $results{$fct}{$type}) { + if ($type eq 'normal') { + print NEWULP "Function: \"$fct\":\n"; + } elsif ($type eq 'real') { + print NEWULP "Function: Real part of \"$fct\":\n"; + } elsif ($type eq 'imag') { + print NEWULP "Function: Imaginary part of \"$fct\":\n"; + } + foreach $float (@all_floats) { + if (exists $results{$fct}{$type}{'ulp'}{$float}) { + print NEWULP "$float: ", + &clean_up_number ($results{$fct}{$type}{'ulp'}{$float}), + "\n"; + } + if (exists $results{$fct}{$type}{'fail'}{$float}) { + print NEWULP "$float: fail\n"; + } + } + print NEWULP "\n"; + } + } + } + print NEWULP "# end of automatic generation\n"; + close NEWULP; +} + +sub get_ulps { + my ($test, $type, $float) = @_; + + if ($type eq 'complex') { + my ($res); + # Return 0 instead of BUILD_COMPLEX (0,0) + if (!exists $results{$test}{'real'}{'ulp'}{$float} && + !exists $results{$test}{'imag'}{'ulp'}{$float}) { + return "0"; + } + $res = 'BUILD_COMPLEX ('; + $res .= (exists $results{$test}{'real'}{'ulp'}{$float} + ? $results{$test}{'real'}{'ulp'}{$float} : "0"); + $res .= ', '; + $res .= (exists $results{$test}{'imag'}{'ulp'}{$float} + ? $results{$test}{'imag'}{'ulp'}{$float} : "0"); + $res .= ')'; + return $res; + } + return (exists $results{$test}{'normal'}{'ulp'}{$float} + ? $results{$test}{'normal'}{'ulp'}{$float} : "0"); +} + +sub get_failure { + my ($test, $type, $float) = @_; + if ($type eq 'complex') { + # return x,y + my ($res); + # Return 0 instead of BUILD_COMPLEX_INT (0,0) + if (!exists $results{$test}{'real'}{'ulp'}{$float} && + !exists $results{$test}{'imag'}{'ulp'}{$float}) { + return "0"; + } + $res = 'BUILD_COMPLEX_INT ('; + $res .= (exists $results{$test}{'real'}{'fail'}{$float} + ? $results{$test}{'real'}{'fail'}{$float} : "0"); + $res .= ', '; + $res .= (exists $results{$test}{'imag'}{'fail'}{$float} + ? $results{$test}{'imag'}{'fail'}{$float} : "0"); + $res .= ')'; + return $res; + } + return (exists $results{$test}{'normal'}{'fail'}{$float} + ? $results{$test}{'normal'}{'fail'}{$float} : "0"); + +} + +# Output the defines for a single test +sub output_test { + my ($file, $test, $name) = @_; + my ($ldouble, $double, $float, $ildouble, $idouble, $ifloat); + my ($type); + + # Do we have ulps/failures? + if (!exists $results{$test}{'type'}) { + return; + } + $type = $results{$test}{'type'}; + if (exists $results{$test}{'has_ulps'}) { + # XXX use all_floats (change order!) + $ldouble = &get_ulps ($test, $type, "ldouble"); + $double = &get_ulps ($test, $type, "double"); + $float = &get_ulps ($test, $type, "float"); + $ildouble = &get_ulps ($test, $type, "ildouble"); + $idouble = &get_ulps ($test, $type, "idouble"); + $ifloat = &get_ulps ($test, $type, "ifloat"); + print $file "#define DELTA$name CHOOSE($ldouble, $double, $float, $ildouble, $idouble, $ifloat)\t/* $test */\n"; + } + + if (exists $results{$test}{'has_fails'}) { + $ldouble = &get_failure ($test, "ldouble"); + $double = &get_failure ($test, "double"); + $float = &get_failure ($test, "float"); + $ildouble = &get_failure ($test, "ildouble"); + $idouble = &get_failure ($test, "idouble"); + $ifloat = &get_failure ($test, "ifloat"); + print $file "#define FAIL$name CHOOSE($ldouble, $double, $float $ildouble, $idouble, $ifloat)\t/* $test */\n"; + } +} + +# Print include file +sub output_ulps { + my ($file, $ulps_filename) = @_; + my ($i, $fct); + + open ULP, ">$file" or die ("Can't open $file: $!"); + + print ULP "/* This file is automatically generated\n"; + print ULP " from $ulps_filename with gen-libm-test.pl.\n"; + print ULP " Don't change it - change instead the master files. */\n\n"; + + print ULP "\n/* Maximal error of functions. */\n"; + foreach $fct (@functions) { + output_test (\*ULP, $fct, $fct); + } + + print ULP "\n/* Error of single function calls. */\n"; + for ($i = 0; $i < $count; $i++) { + output_test (\*ULP, $tests[$i], $i); + } + close ULP; +} diff --git a/test/math/libm-test.inc b/test/math/libm-test.inc new file mode 100644 index 0000000..c9c2c8b --- /dev/null +++ b/test/math/libm-test.inc @@ -0,0 +1,5102 @@ +/* Copyright (C) 1997-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Part of testsuite for libm. + + This file is processed by a perl script. The resulting file has to + be included by a master file that defines: + + Macros: + FUNC(function): converts general function name (like cos) to + name with correct suffix (e.g. cosl or cosf) + MATHCONST(x): like FUNC but for constants (e.g convert 0.0 to 0.0L) + FLOAT: floating point type to test + - TEST_MSG: informal message to be displayed + CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat): + chooses one of the parameters as delta for testing + equality + PRINTF_EXPR Floating point conversion specification to print a variable + of type FLOAT with printf. PRINTF_EXPR just contains + the specifier, not the percent and width arguments, + e.g. "f". + PRINTF_XEXPR Like PRINTF_EXPR, but print in hexadecimal format. + PRINTF_NEXPR Like PRINTF_EXPR, but print nice. */ + +/* This testsuite has currently tests for: + acos, acosh, asin, asinh, atan, atan2, atanh, + cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp10, exp2, expm1, + fabs, fdim, floor, fma, fmax, fmin, fmod, fpclassify, + frexp, gamma, hypot, + ilogb, isfinite, isinf, isnan, isnormal, + isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered, + j0, j1, jn, + ldexp, lgamma, log, log10, log1p, log2, logb, + modf, nearbyint, nextafter, + pow, remainder, remquo, rint, lrint, llrint, + round, lround, llround, + scalb, scalbn, scalbln, signbit, sin, sincos, sinh, sqrt, tan, tanh, tgamma, trunc, + y0, y1, yn, significand + + and for the following complex math functions: + cabs, cacos, cacosh, carg, casin, casinh, catan, catanh, + ccos, ccosh, cexp, clog, cpow, cproj, csin, csinh, csqrt, ctan, ctanh. + + At the moment the following functions aren't tested: + drem, nan + + Parameter handling is primitive in the moment: + --verbose=[0..3] for different levels of output: + 0: only error count + 1: basic report on failed tests (default) + 2: full report on all tests + -v for full output (equals --verbose=3) + -u for generation of an ULPs file + */ + +/* "Philosophy": + + This suite tests some aspects of the correct implementation of + mathematical functions in libm. Some simple, specific parameters + are tested for correctness but there's no exhaustive + testing. Handling of specific inputs (e.g. infinity, not-a-number) + is also tested. Correct handling of exceptions is checked + against. These implemented tests should check all cases that are + specified in ISO C99. + + Exception testing: At the moment only divide-by-zero and invalid + exceptions are tested. Overflow/underflow and inexact exceptions + aren't checked at the moment. + + NaN values: There exist signalling and quiet NaNs. This implementation + only uses quiet NaN as parameter but does not differenciate + between the two kinds of NaNs as result. + + Inline functions: Inlining functions should give an improvement in + speed - but not in precission. The inlined functions return + reasonable values for a reasonable range of input values. The + result is not necessarily correct for all values and exceptions are + not correctly raised in all cases. Problematic input and return + values are infinity, not-a-number and minus zero. This suite + therefore does not check these specific inputs and the exception + handling for inlined mathematical functions - just the "reasonable" + values are checked. + + Beware: The tests might fail for any of the following reasons: + - Tests are wrong + - Functions are wrong + - Floating Point Unit not working properly + - Compiler has errors + + With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error. + + + To Do: All parameter should be numbers that can be represented as + exact floating point values. Currently some values cannot be + represented exactly and therefore the result is not the expected + result. For this we will use 36 digits so that numbers can be + represented exactly. */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include "libm-test-ulps.h" +#include +#include +#include +#include "fenv.h" +#include + +#include +#include +#include +#include +#include + +/* Possible exceptions */ +#define NO_EXCEPTION 0x0 +#define INVALID_EXCEPTION 0x1 +#define DIVIDE_BY_ZERO_EXCEPTION 0x2 +/* The next flags signals that those exceptions are allowed but not required. */ +#define INVALID_EXCEPTION_OK 0x4 +#define DIVIDE_BY_ZERO_EXCEPTION_OK 0x8 +#define EXCEPTIONS_OK INVALID_EXCEPTION_OK+DIVIDE_BY_ZERO_EXCEPTION_OK +/* Some special test flags, passed togther with exceptions. */ +#define IGNORE_ZERO_INF_SIGN 0x10 + +/* Various constants (we must supply them precalculated for accuracy). */ +#define M_PI_6l .52359877559829887307710723054658383L +#define M_E2l 7.389056098930650227230427460575008L +#define M_E3l 20.085536923187667740928529654581719L +#define M_2_SQRT_PIl 3.5449077018110320545963349666822903L /* 2 sqrt (M_PIl) */ +#define M_SQRT_PIl 1.7724538509055160272981674833411451L /* sqrt (M_PIl) */ +#define M_LOG_SQRT_PIl 0.57236494292470008707171367567652933L /* log(sqrt(M_PIl)) */ +#define M_LOG_2_SQRT_PIl 1.265512123484645396488945797134706L /* log(2*sqrt(M_PIl)) */ +#define M_PI_34l (M_PIl - M_PI_4l) /* 3*pi/4 */ +#define M_PI_34_LOG10El (M_PIl - M_PI_4l) * M_LOG10El +#define M_PI2_LOG10El M_PI_2l * M_LOG10El +#define M_PI4_LOG10El M_PI_4l * M_LOG10El +#define M_PI_LOG10El M_PIl * M_LOG10El +#define M_SQRT_2_2 0.70710678118654752440084436210484903L /* sqrt (2) / 2 */ + +static FILE *ulps_file; /* File to document difference. */ +static int output_ulps; /* Should ulps printed? */ + +static int noErrors; /* number of errors */ +static int noTests; /* number of tests (without testing exceptions) */ +static int noExcTests; /* number of tests for exception flags */ +static int noXFails; /* number of expected failures. */ +static int noXPasses; /* number of unexpected passes. */ + +static int verbose; +static int output_max_error; /* Should the maximal errors printed? */ +static int output_points; /* Should the single function results printed? */ +static int ignore_max_ulp; /* Should we ignore max_ulp? */ + +static FLOAT minus_zero, plus_zero; +static FLOAT plus_infty, minus_infty, nan_value, max_value, min_value; + +static FLOAT max_error, real_max_error, imag_max_error; + + +#define BUILD_COMPLEX(real, imag) \ + ({ __complex__ FLOAT __retval; \ + __real__ __retval = (real); \ + __imag__ __retval = (imag); \ + __retval; }) + +#define BUILD_COMPLEX_INT(real, imag) \ + ({ __complex__ int __retval; \ + __real__ __retval = (real); \ + __imag__ __retval = (imag); \ + __retval; }) + + +#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \ + (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1)) + +static void +init_max_error (void) +{ + max_error = 0; + real_max_error = 0; + imag_max_error = 0; + feclearexcept (FE_ALL_EXCEPT); +} + +static void +set_max_error (FLOAT current, FLOAT *curr_max_error) +{ + if (current > *curr_max_error) + *curr_max_error = current; +} + + +/* Should the message print to screen? This depends on the verbose flag, + and the test status. */ +static int +print_screen (int ok, int xfail) +{ + if (output_points + && (verbose > 1 + || (verbose == 1 && ok == xfail))) + return 1; + return 0; +} + + +/* Should the message print to screen? This depends on the verbose flag, + and the test status. */ +static int +print_screen_max_error (int ok, int xfail) +{ + if (output_max_error + && (verbose > 1 + || ((verbose == 1) && (ok == xfail)))) + return 1; + return 0; +} + +/* Update statistic counters. */ +static void +update_stats (int ok, int xfail) +{ + ++noTests; + if (ok && xfail) + ++noXPasses; + else if (!ok && xfail) + ++noXFails; + else if (!ok && !xfail) + ++noErrors; +} + +static void +print_ulps (const char *test_name, FLOAT ulp) +{ + if (output_ulps) + { + fprintf (ulps_file, "Test \"%s\":\n", test_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (ulp)); + } +} + +static void +print_function_ulps (const char *function_name, FLOAT ulp) +{ + if (output_ulps) + { + fprintf (ulps_file, "Function: \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (ulp)); + } +} + + +static void +print_complex_function_ulps (const char *function_name, FLOAT real_ulp, + FLOAT imag_ulp) +{ + if (output_ulps) + { + if (real_ulp != 0.0) + { + fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (real_ulp)); + } + if (imag_ulp != 0.0) + { + fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name); + fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n", + CHOOSE("ldouble", "double", "float", + "ildouble", "idouble", "ifloat"), + FUNC(ceil) (imag_ulp)); + } + + + } +} + + + +/* Test if Floating-Point stack hasn't changed */ +static void +fpstack_test (const char *test_name) +{ +#ifdef i386 + static int old_stack; + int sw; + + __asm__ ("fnstsw" : "=a" (sw)); + sw >>= 11; + sw &= 7; + + if (sw != old_stack) + { + printf ("FP-Stack wrong after test %s (%d, should be %d)\n", + test_name, sw, old_stack); + ++noErrors; + old_stack = sw; + } +#endif +} + + +static void +print_max_error (const char *func_name, FLOAT allowed, int xfail) +{ + int ok = 0; + + if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp)) + { + ok = 1; + } + + if (!ok) + print_function_ulps (func_name, max_error); + + + if (print_screen_max_error (ok, xfail)) + { + printf ("Maximal error of `%s'\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (allowed)); + } + + update_stats (ok, xfail); +} + + +static void +print_complex_max_error (const char *func_name, __complex__ FLOAT allowed, + __complex__ int xfail) +{ + int ok = 0; + + if ((real_max_error == 0 && imag_max_error == 0) + || (real_max_error <= __real__ allowed + && imag_max_error <= __imag__ allowed + && !ignore_max_ulp)) + { + ok = 1; + } + + if (!ok) + print_complex_function_ulps (func_name, real_max_error, imag_max_error); + + + if (print_screen_max_error (ok, xfail)) + { + printf ("Maximal error of real part of: %s\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (real_max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (__real__ allowed)); + printf ("Maximal error of imaginary part of: %s\n", func_name); + printf (" is : %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (imag_max_error)); + printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", + FUNC(ceil) (__imag__ allowed)); + } + + update_stats (ok, xfail); +} + + +/* Test whether a given exception was raised. */ +static void +test_single_exception (const char *test_name, + int exception, + int exc_flag, + int fe_flag, + const char *flag_name) +{ +#ifndef TEST_INLINE + int ok = 1; + if (exception & exc_flag) + { + if (fetestexcept (fe_flag)) + { + if (print_screen (1, 0)) + printf ("Pass: %s: Exception \"%s\" set\n", test_name, flag_name); + } + else + { + ok = 0; + if (print_screen (0, 0)) + printf ("Failure: %s: Exception \"%s\" not set\n", + test_name, flag_name); + } + } + else + { + if (fetestexcept (fe_flag)) + { + ok = 0; + if (print_screen (0, 0)) + printf ("Failure: %s: Exception \"%s\" set\n", + test_name, flag_name); + } + else + { + if (print_screen (1, 0)) + printf ("%s: Exception \"%s\" not set\n", test_name, + flag_name); + } + } + if (!ok) + ++noErrors; + +#endif +} + + +/* Test whether exceptions given by EXCEPTION are raised. Ignore thereby + allowed but not required exceptions. +*/ +static void +test_exceptions (const char *test_name, int exception) +{ + ++noExcTests; +#ifdef FE_DIVBYZERO + if ((exception & DIVIDE_BY_ZERO_EXCEPTION_OK) == 0) + test_single_exception (test_name, exception, + DIVIDE_BY_ZERO_EXCEPTION, FE_DIVBYZERO, + "Divide by zero"); +#endif +#ifdef FE_INVALID + if ((exception & INVALID_EXCEPTION_OK) == 0) + test_single_exception (test_name, exception, INVALID_EXCEPTION, FE_INVALID, + "Invalid operation"); +#endif + feclearexcept (FE_ALL_EXCEPT); +} + + +static void +check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, + FLOAT max_ulp, int xfail, int exceptions, + FLOAT *curr_max_error) +{ + int ok = 0; + int print_diff = 0; + FLOAT diff = 0; + FLOAT ulp = 0; + + test_exceptions (test_name, exceptions); + if (isnan (computed) && isnan (expected)) + ok = 1; + else if (isinf (computed) && isinf (expected)) + { + /* Test for sign of infinities. */ + if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0 + && signbit (computed) != signbit (expected)) + { + ok = 0; + printf ("infinity has wrong sign.\n"); + } + else + ok = 1; + } + /* Don't calc ulp for NaNs or infinities. */ + else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected)) + ok = 0; + else + { + diff = FUNC(fabs) (computed - expected); + /* ilogb (0) isn't allowed. */ + if (expected == 0.0) + ulp = diff / FUNC(ldexp) (1.0, - MANT_DIG); + else + ulp = diff / FUNC(ldexp) (1.0, FUNC(ilogb) (expected) - MANT_DIG); + set_max_error (ulp, curr_max_error); + print_diff = 1; + if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0 + && computed == 0.0 && expected == 0.0 + && signbit(computed) != signbit (expected)) + ok = 0; + else if (ulp <= 0.5 || (ulp <= max_ulp && !ignore_max_ulp)) + ok = 1; + else + { + ok = 0; + print_ulps (test_name, ulp); + } + + } + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n", + computed, computed); + printf (" should be: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n", + expected, expected); + if (print_diff) + { + printf (" difference: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR + "\n", diff, diff); + printf (" ulp : % .4" PRINTF_NEXPR "\n", ulp); + printf (" max.ulp : % .4" PRINTF_NEXPR "\n", max_ulp); + } + } + update_stats (ok, xfail); + + fpstack_test (test_name); +} + + +static void +check_float (const char *test_name, FLOAT computed, FLOAT expected, + FLOAT max_ulp, int xfail, int exceptions) +{ + check_float_internal (test_name, computed, expected, max_ulp, xfail, + exceptions, &max_error); +} + + +static void +check_complex (const char *test_name, __complex__ FLOAT computed, + __complex__ FLOAT expected, + __complex__ FLOAT max_ulp, __complex__ int xfail, + int exception) +{ + FLOAT part_comp, part_exp, part_max_ulp; + int part_xfail; + char str[200]; + + sprintf (str, "Real part of: %s", test_name); + part_comp = __real__ computed; + part_exp = __real__ expected; + part_max_ulp = __real__ max_ulp; + part_xfail = __real__ xfail; + + check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail, + exception, &real_max_error); + + sprintf (str, "Imaginary part of: %s", test_name); + part_comp = __imag__ computed; + part_exp = __imag__ expected; + part_max_ulp = __imag__ max_ulp; + part_xfail = __imag__ xfail; + + /* Don't check again for exceptions, just pass through the + zero/inf sign test. */ + check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail, + exception & IGNORE_ZERO_INF_SIGN, + &imag_max_error); +} + + +/* Check that computed and expected values are equal (int values). */ +static void +check_int (const char *test_name, int computed, int expected, int max_ulp, + int xfail, int exceptions) +{ + int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (abs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %d\n", computed); + printf (" should be: %d\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* Check that computed and expected values are equal (long int values). */ +static void +check_long (const char *test_name, long int computed, long int expected, + long int max_ulp, int xfail, int exceptions) +{ + long int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (labs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %ld\n", computed); + printf (" should be: %ld\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* Check that computed value is true/false. */ +static void +check_bool (const char *test_name, int computed, int expected, + long int max_ulp, int xfail, int exceptions) +{ + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if ((computed == 0) == (expected == 0)) + ok = 1; + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure: "); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %d\n", computed); + printf (" should be: %d\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + +/* check that computed and expected values are equal (long int values) */ +static void +check_longlong (const char *test_name, long long int computed, + long long int expected, + long long int max_ulp, int xfail, + int exceptions) +{ + long long int diff = computed - expected; + int ok = 0; + + test_exceptions (test_name, exceptions); + noTests++; + if (llabs (diff) <= max_ulp) + ok = 1; + + if (!ok) + print_ulps (test_name, diff); + + if (print_screen (ok, xfail)) + { + if (!ok) + printf ("Failure:"); + printf ("Test: %s\n", test_name); + printf ("Result:\n"); + printf (" is: %lld\n", computed); + printf (" should be: %lld\n", expected); + } + + update_stats (ok, xfail); + fpstack_test (test_name); +} + + + +/* This is to prevent messages from the SVID libm emulation. */ +int +matherr (struct exception *x __attribute__ ((unused))) +{ + return 1; +} + + +/**************************************************************************** + Tests for single functions of libm. + Please keep them alphabetically sorted! +****************************************************************************/ + +static void +acos_test (void) +{ + errno = 0; + FUNC(acos) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (acos); + + TEST_f_f (acos, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, nan_value, nan_value); + + /* |x| > 1: */ + TEST_f_f (acos, 1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (acos, -1.125L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (acos, 0, M_PI_2l); + TEST_f_f (acos, minus_zero, M_PI_2l); + TEST_f_f (acos, 1, 0); + TEST_f_f (acos, -1, M_PIl); + TEST_f_f (acos, 0.5, M_PI_6l*2.0); + TEST_f_f (acos, -0.5, M_PI_6l*4.0); + TEST_f_f (acos, 0.75L, 0.722734247813415611178377352641333362L); + TEST_f_f (acos, 2e-17L, 1.57079632679489659923132169163975144L); + TEST_f_f (acos, 0.0625L, 1.50825556499840522843072005474337068L); + END (acos); +} + +static void +acosh_test (void) +{ + errno = 0; + FUNC(acosh) (7); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (acosh); + + TEST_f_f (acosh, plus_infty, plus_infty); + TEST_f_f (acosh, minus_infty, nan_value, INVALID_EXCEPTION); + + /* x < 1: */ + TEST_f_f (acosh, -1.125L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (acosh, 1, 0); + TEST_f_f (acosh, 7, 2.63391579384963341725009269461593689L); + + END (acosh); +} + +static void +asin_test (void) +{ + errno = 0; + FUNC(asin) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (asin); + + TEST_f_f (asin, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, nan_value, nan_value); + + /* asin x == NaN plus invalid exception for |x| > 1. */ + TEST_f_f (asin, 1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (asin, -1.125L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (asin, 0, 0); + TEST_f_f (asin, minus_zero, minus_zero); + TEST_f_f (asin, 0.5, M_PI_6l); + TEST_f_f (asin, -0.5, -M_PI_6l); + TEST_f_f (asin, 1.0, M_PI_2l); + TEST_f_f (asin, -1.0, -M_PI_2l); + TEST_f_f (asin, 0.75L, 0.848062078981481008052944338998418080L); + + END (asin); +} + +static void +asinh_test (void) +{ + errno = 0; + FUNC(asinh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (asinh); + + TEST_f_f (asinh, 0, 0); + TEST_f_f (asinh, minus_zero, minus_zero); +#ifndef TEST_INLINE + TEST_f_f (asinh, plus_infty, plus_infty); + TEST_f_f (asinh, minus_infty, minus_infty); +#endif + TEST_f_f (asinh, nan_value, nan_value); + TEST_f_f (asinh, 0.75L, 0.693147180559945309417232121458176568L); + + END (asinh); +} + +static void +atan_test (void) +{ + errno = 0; + FUNC(atan) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atan); + + TEST_f_f (atan, 0, 0); + TEST_f_f (atan, minus_zero, minus_zero); + + TEST_f_f (atan, plus_infty, M_PI_2l); + TEST_f_f (atan, minus_infty, -M_PI_2l); + TEST_f_f (atan, nan_value, nan_value); + + TEST_f_f (atan, 1, M_PI_4l); + TEST_f_f (atan, -1, -M_PI_4l); + + TEST_f_f (atan, 0.75L, 0.643501108793284386802809228717322638L); + + END (atan); +} + + + +static void +atanh_test (void) +{ + errno = 0; + FUNC(atanh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atanh); + + + TEST_f_f (atanh, 0, 0); + TEST_f_f (atanh, minus_zero, minus_zero); + + TEST_f_f (atanh, 1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (atanh, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (atanh, nan_value, nan_value); + + /* atanh (x) == NaN plus invalid exception if |x| > 1. */ + TEST_f_f (atanh, 1.125L, nan_value, INVALID_EXCEPTION); + TEST_f_f (atanh, -1.125L, nan_value, INVALID_EXCEPTION); + + TEST_f_f (atanh, 0.75L, 0.972955074527656652552676371721589865L); + + END (atanh); +} + +static void +atan2_test (void) +{ + errno = 0; + FUNC(atan2) (-0, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (atan2); + + /* atan2 (0,x) == 0 for x > 0. */ + TEST_ff_f (atan2, 0, 1, 0); + + /* atan2 (-0,x) == -0 for x > 0. */ + TEST_ff_f (atan2, minus_zero, 1, minus_zero); + + TEST_ff_f (atan2, 0, 0, 0); + TEST_ff_f (atan2, minus_zero, 0, minus_zero); + + /* atan2 (+0,x) == +pi for x < 0. */ + TEST_ff_f (atan2, 0, -1, M_PIl); + + /* atan2 (-0,x) == -pi for x < 0. */ + TEST_ff_f (atan2, minus_zero, -1, -M_PIl); + + TEST_ff_f (atan2, 0, minus_zero, M_PIl); + TEST_ff_f (atan2, minus_zero, minus_zero, -M_PIl); + + /* atan2 (y,+0) == pi/2 for y > 0. */ + TEST_ff_f (atan2, 1, 0, M_PI_2l); + + /* atan2 (y,-0) == pi/2 for y > 0. */ + TEST_ff_f (atan2, 1, minus_zero, M_PI_2l); + + /* atan2 (y,+0) == -pi/2 for y < 0. */ + TEST_ff_f (atan2, -1, 0, -M_PI_2l); + + /* atan2 (y,-0) == -pi/2 for y < 0. */ + TEST_ff_f (atan2, -1, minus_zero, -M_PI_2l); + + /* atan2 (y,inf) == +0 for finite y > 0. */ + TEST_ff_f (atan2, 1, plus_infty, 0); + + /* atan2 (y,inf) == -0 for finite y < 0. */ + TEST_ff_f (atan2, -1, plus_infty, minus_zero); + + /* atan2(+inf, x) == pi/2 for finite x. */ + TEST_ff_f (atan2, plus_infty, -1, M_PI_2l); + + /* atan2(-inf, x) == -pi/2 for finite x. */ + TEST_ff_f (atan2, minus_infty, 1, -M_PI_2l); + + /* atan2 (y,-inf) == +pi for finite y > 0. */ + TEST_ff_f (atan2, 1, minus_infty, M_PIl); + + /* atan2 (y,-inf) == -pi for finite y < 0. */ + TEST_ff_f (atan2, -1, minus_infty, -M_PIl); + + TEST_ff_f (atan2, plus_infty, plus_infty, M_PI_4l); + TEST_ff_f (atan2, minus_infty, plus_infty, -M_PI_4l); + TEST_ff_f (atan2, plus_infty, minus_infty, M_PI_34l); + TEST_ff_f (atan2, minus_infty, minus_infty, -M_PI_34l); + TEST_ff_f (atan2, nan_value, nan_value, nan_value); + + TEST_ff_f (atan2, 0.75L, 1, 0.643501108793284386802809228717322638L); + TEST_ff_f (atan2, -0.75L, 1.0L, -0.643501108793284386802809228717322638L); + TEST_ff_f (atan2, 0.75L, -1.0L, 2.49809154479650885165983415456218025L); + TEST_ff_f (atan2, -0.75L, -1.0L, -2.49809154479650885165983415456218025L); + TEST_ff_f (atan2, 0.390625L, .00029L, 1.57005392693128974780151246612928941L); + TEST_ff_f (atan2, 1.390625L, 0.9296875L, 0.981498387184244311516296577615519772L); + + TEST_ff_f (atan2, -0.00756827042671106339L, -.001792735857538728036L, -1.80338464113663849327153994379639112L); + + END (atan2); +} + +static void +cabs_test (void) +{ + errno = 0; + FUNC(cabs) (BUILD_COMPLEX (0.7L, 12.4L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cabs); + + /* cabs (x + iy) is specified as hypot (x,y) */ + + /* cabs (+inf + i x) == +inf. */ + TEST_c_f (cabs, plus_infty, 1.0, plus_infty); + /* cabs (-inf + i x) == +inf. */ + TEST_c_f (cabs, minus_infty, 1.0, plus_infty); + + TEST_c_f (cabs, minus_infty, nan_value, plus_infty); + TEST_c_f (cabs, minus_infty, nan_value, plus_infty); + + TEST_c_f (cabs, nan_value, nan_value, nan_value); + + /* cabs (x,y) == cabs (y,x). */ + TEST_c_f (cabs, 0.75L, 12.390625L, 12.4133028598606664302388810868156657L); + /* cabs (x,y) == cabs (-x,y). */ + TEST_c_f (cabs, -12.390625L, 0.75L, 12.4133028598606664302388810868156657L); + /* cabs (x,y) == cabs (-y,x). */ + TEST_c_f (cabs, -0.75L, 12.390625L, 12.4133028598606664302388810868156657L); + /* cabs (x,y) == cabs (-x,-y). */ + TEST_c_f (cabs, -12.390625L, -0.75L, 12.4133028598606664302388810868156657L); + /* cabs (x,y) == cabs (-y,-x). */ + TEST_c_f (cabs, -0.75L, -12.390625L, 12.4133028598606664302388810868156657L); + /* cabs (x,0) == fabs (x). */ + TEST_c_f (cabs, -0.75L, 0, 0.75L); + TEST_c_f (cabs, 0.75L, 0, 0.75L); + TEST_c_f (cabs, -1.0L, 0, 1.0L); + TEST_c_f (cabs, 1.0L, 0, 1.0L); + TEST_c_f (cabs, -5.7e7L, 0, 5.7e7L); + TEST_c_f (cabs, 5.7e7L, 0, 5.7e7L); + + TEST_c_f (cabs, 0.75L, 1.25L, 1.45773797371132511771853821938639577L); + + END (cabs); +} + + +#if 0 +static void +cacos_test (void) +{ + errno = 0; + FUNC(cacos) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cacos); + + + TEST_c_c (cacos, 0, 0, M_PI_2l, minus_zero); + TEST_c_c (cacos, minus_zero, 0, M_PI_2l, minus_zero); + TEST_c_c (cacos, minus_zero, minus_zero, M_PI_2l, 0.0); + TEST_c_c (cacos, 0, minus_zero, M_PI_2l, 0.0); + + TEST_c_c (cacos, minus_infty, plus_infty, M_PI_34l, minus_infty); + TEST_c_c (cacos, minus_infty, minus_infty, M_PI_34l, plus_infty); + + TEST_c_c (cacos, plus_infty, plus_infty, M_PI_4l, minus_infty); + TEST_c_c (cacos, plus_infty, minus_infty, M_PI_4l, plus_infty); + + TEST_c_c (cacos, -10.0, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, -10.0, minus_infty, M_PI_2l, plus_infty); + TEST_c_c (cacos, 0, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, 0, minus_infty, M_PI_2l, plus_infty); + TEST_c_c (cacos, 0.1L, plus_infty, M_PI_2l, minus_infty); + TEST_c_c (cacos, 0.1L, minus_infty, M_PI_2l, plus_infty); + + TEST_c_c (cacos, minus_infty, 0, M_PIl, minus_infty); + TEST_c_c (cacos, minus_infty, minus_zero, M_PIl, plus_infty); + TEST_c_c (cacos, minus_infty, 100, M_PIl, minus_infty); + TEST_c_c (cacos, minus_infty, -100, M_PIl, plus_infty); + + TEST_c_c (cacos, plus_infty, 0, 0.0, minus_infty); + TEST_c_c (cacos, plus_infty, minus_zero, 0.0, plus_infty); + TEST_c_c (cacos, plus_infty, 0.5, 0.0, minus_infty); + TEST_c_c (cacos, plus_infty, -0.5, 0.0, plus_infty); + + TEST_c_c (cacos, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (cacos, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cacos, 0, nan_value, M_PI_2l, nan_value); + TEST_c_c (cacos, minus_zero, nan_value, M_PI_2l, nan_value); + + TEST_c_c (cacos, nan_value, plus_infty, nan_value, minus_infty); + TEST_c_c (cacos, nan_value, minus_infty, nan_value, plus_infty); + + TEST_c_c (cacos, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacos, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacos, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacos, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacos, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cacos, 0.75L, 1.25L, 1.11752014915610270578240049553777969L, -1.13239363160530819522266333696834467L); + TEST_c_c (cacos, -2, -3, 2.1414491111159960199416055713254211L, 1.9833870299165354323470769028940395L); + + END (cacos, complex); +} + +static void +cacosh_test (void) +{ + errno = 0; + FUNC(cacosh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cacosh); + + + TEST_c_c (cacosh, 0, 0, 0.0, M_PI_2l); + TEST_c_c (cacosh, minus_zero, 0, 0.0, M_PI_2l); + TEST_c_c (cacosh, 0, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (cacosh, minus_zero, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (cacosh, minus_infty, plus_infty, plus_infty, M_PI_34l); + TEST_c_c (cacosh, minus_infty, minus_infty, plus_infty, -M_PI_34l); + + TEST_c_c (cacosh, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (cacosh, plus_infty, minus_infty, plus_infty, -M_PI_4l); + + TEST_c_c (cacosh, -10.0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, -10.0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (cacosh, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (cacosh, 0.1L, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (cacosh, 0.1L, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (cacosh, minus_infty, 0, plus_infty, M_PIl); + TEST_c_c (cacosh, minus_infty, minus_zero, plus_infty, -M_PIl); + TEST_c_c (cacosh, minus_infty, 100, plus_infty, M_PIl); + TEST_c_c (cacosh, minus_infty, -100, plus_infty, -M_PIl); + + TEST_c_c (cacosh, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (cacosh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (cacosh, plus_infty, 0.5, plus_infty, 0.0); + TEST_c_c (cacosh, plus_infty, -0.5, plus_infty, minus_zero); + + TEST_c_c (cacosh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (cacosh, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (cacosh, 0, nan_value, nan_value, nan_value); + TEST_c_c (cacosh, minus_zero, nan_value, nan_value, nan_value); + + TEST_c_c (cacosh, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (cacosh, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (cacosh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacosh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacosh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cacosh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cacosh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cacosh, 0.75L, 1.25L, 1.13239363160530819522266333696834467L, 1.11752014915610270578240049553777969L); + TEST_c_c (cacosh, -2, -3, 1.9833870299165354323470769028940395L, -2.1414491111159960199416055713254211L); + + END (cacosh, complex); +} + + +static void +carg_test (void) +{ + START (carg); + + /* carg (x + iy) is specified as atan2 (y, x) */ + + /* carg (x + i 0) == 0 for x > 0. */ + TEST_c_f (carg, 2.0, 0, 0); + /* carg (x - i 0) == -0 for x > 0. */ + TEST_c_f (carg, 2.0, minus_zero, minus_zero); + + TEST_c_f (carg, 0, 0, 0); + TEST_c_f (carg, 0, minus_zero, minus_zero); + + /* carg (x + i 0) == +pi for x < 0. */ + TEST_c_f (carg, -2.0, 0, M_PIl); + + /* carg (x - i 0) == -pi for x < 0. */ + TEST_c_f (carg, -2.0, minus_zero, -M_PIl); + + TEST_c_f (carg, minus_zero, 0, M_PIl); + TEST_c_f (carg, minus_zero, minus_zero, -M_PIl); + + /* carg (+0 + i y) == pi/2 for y > 0. */ + TEST_c_f (carg, 0, 2.0, M_PI_2l); + + /* carg (-0 + i y) == pi/2 for y > 0. */ + TEST_c_f (carg, minus_zero, 2.0, M_PI_2l); + + /* carg (+0 + i y) == -pi/2 for y < 0. */ + TEST_c_f (carg, 0, -2.0, -M_PI_2l); + + /* carg (-0 + i y) == -pi/2 for y < 0. */ + TEST_c_f (carg, minus_zero, -2.0, -M_PI_2l); + + /* carg (inf + i y) == +0 for finite y > 0. */ + TEST_c_f (carg, plus_infty, 2.0, 0); + + /* carg (inf + i y) == -0 for finite y < 0. */ + TEST_c_f (carg, plus_infty, -2.0, minus_zero); + + /* carg(x + i inf) == pi/2 for finite x. */ + TEST_c_f (carg, 10.0, plus_infty, M_PI_2l); + + /* carg(x - i inf) == -pi/2 for finite x. */ + TEST_c_f (carg, 10.0, minus_infty, -M_PI_2l); + + /* carg (-inf + i y) == +pi for finite y > 0. */ + TEST_c_f (carg, minus_infty, 10.0, M_PIl); + + /* carg (-inf + i y) == -pi for finite y < 0. */ + TEST_c_f (carg, minus_infty, -10.0, -M_PIl); + + TEST_c_f (carg, plus_infty, plus_infty, M_PI_4l); + + TEST_c_f (carg, plus_infty, minus_infty, -M_PI_4l); + + TEST_c_f (carg, minus_infty, plus_infty, 3 * M_PI_4l); + + TEST_c_f (carg, minus_infty, minus_infty, -3 * M_PI_4l); + + TEST_c_f (carg, nan_value, nan_value, nan_value); + + END (carg); +} + +static void +casin_test (void) +{ + errno = 0; + FUNC(casin) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (casin); + + TEST_c_c (casin, 0, 0, 0.0, 0.0); + TEST_c_c (casin, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (casin, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (casin, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (casin, plus_infty, plus_infty, M_PI_4l, plus_infty); + TEST_c_c (casin, plus_infty, minus_infty, M_PI_4l, minus_infty); + TEST_c_c (casin, minus_infty, plus_infty, -M_PI_4l, plus_infty); + TEST_c_c (casin, minus_infty, minus_infty, -M_PI_4l, minus_infty); + + TEST_c_c (casin, -10.0, plus_infty, minus_zero, plus_infty); + TEST_c_c (casin, -10.0, minus_infty, minus_zero, minus_infty); + TEST_c_c (casin, 0, plus_infty, 0.0, plus_infty); + TEST_c_c (casin, 0, minus_infty, 0.0, minus_infty); + TEST_c_c (casin, minus_zero, plus_infty, minus_zero, plus_infty); + TEST_c_c (casin, minus_zero, minus_infty, minus_zero, minus_infty); + TEST_c_c (casin, 0.1L, plus_infty, 0.0, plus_infty); + TEST_c_c (casin, 0.1L, minus_infty, 0.0, minus_infty); + + TEST_c_c (casin, minus_infty, 0, -M_PI_2l, plus_infty); + TEST_c_c (casin, minus_infty, minus_zero, -M_PI_2l, minus_infty); + TEST_c_c (casin, minus_infty, 100, -M_PI_2l, plus_infty); + TEST_c_c (casin, minus_infty, -100, -M_PI_2l, minus_infty); + + TEST_c_c (casin, plus_infty, 0, M_PI_2l, plus_infty); + TEST_c_c (casin, plus_infty, minus_zero, M_PI_2l, minus_infty); + TEST_c_c (casin, plus_infty, 0.5, M_PI_2l, plus_infty); + TEST_c_c (casin, plus_infty, -0.5, M_PI_2l, minus_infty); + + TEST_c_c (casin, nan_value, plus_infty, nan_value, plus_infty); + TEST_c_c (casin, nan_value, minus_infty, nan_value, minus_infty); + + TEST_c_c (casin, 0.0, nan_value, 0.0, nan_value); + TEST_c_c (casin, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (casin, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (casin, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (casin, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casin, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casin, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casin, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casin, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (casin, 0.75L, 1.25L, 0.453276177638793913448921196101971749L, 1.13239363160530819522266333696834467L); + TEST_c_c (casin, -2, -3, -0.57065278432109940071028387968566963L, -1.9833870299165354323470769028940395L); + + END (casin, complex); +} + + +static void +casinh_test (void) +{ + errno = 0; + FUNC(casinh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (casinh); + + TEST_c_c (casinh, 0, 0, 0.0, 0.0); + TEST_c_c (casinh, minus_zero, 0, minus_zero, 0); + TEST_c_c (casinh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (casinh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (casinh, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (casinh, plus_infty, minus_infty, plus_infty, -M_PI_4l); + TEST_c_c (casinh, minus_infty, plus_infty, minus_infty, M_PI_4l); + TEST_c_c (casinh, minus_infty, minus_infty, minus_infty, -M_PI_4l); + + TEST_c_c (casinh, -10.0, plus_infty, minus_infty, M_PI_2l); + TEST_c_c (casinh, -10.0, minus_infty, minus_infty, -M_PI_2l); + TEST_c_c (casinh, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (casinh, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (casinh, minus_zero, plus_infty, minus_infty, M_PI_2l); + TEST_c_c (casinh, minus_zero, minus_infty, minus_infty, -M_PI_2l); + TEST_c_c (casinh, 0.1L, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (casinh, 0.1L, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (casinh, minus_infty, 0, minus_infty, 0.0); + TEST_c_c (casinh, minus_infty, minus_zero, minus_infty, minus_zero); + TEST_c_c (casinh, minus_infty, 100, minus_infty, 0.0); + TEST_c_c (casinh, minus_infty, -100, minus_infty, minus_zero); + + TEST_c_c (casinh, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (casinh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (casinh, plus_infty, 0.5, plus_infty, 0.0); + TEST_c_c (casinh, plus_infty, -0.5, plus_infty, minus_zero); + + TEST_c_c (casinh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (casinh, minus_infty, nan_value, minus_infty, nan_value); + + TEST_c_c (casinh, nan_value, 0, nan_value, 0.0); + TEST_c_c (casinh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (casinh, nan_value, plus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (casinh, nan_value, minus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (casinh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casinh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casinh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (casinh, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (casinh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (casinh, 0.75L, 1.25L, 1.03171853444778027336364058631006594L, 0.911738290968487636358489564316731207L); + TEST_c_c (casinh, -2, -3, -1.9686379257930962917886650952454982L, -0.96465850440760279204541105949953237L); + + END (casinh, complex); +} + + +static void +catan_test (void) +{ + errno = 0; + FUNC(catan) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (catan); + + TEST_c_c (catan, 0, 0, 0, 0); + TEST_c_c (catan, minus_zero, 0, minus_zero, 0); + TEST_c_c (catan, 0, minus_zero, 0, minus_zero); + TEST_c_c (catan, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (catan, plus_infty, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, plus_infty, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, plus_infty, -M_PI_2l, 0); + TEST_c_c (catan, minus_infty, minus_infty, -M_PI_2l, minus_zero); + + + TEST_c_c (catan, plus_infty, -10.0, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, -10.0, -M_PI_2l, minus_zero); + TEST_c_c (catan, plus_infty, minus_zero, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_infty, minus_zero, -M_PI_2l, minus_zero); + TEST_c_c (catan, plus_infty, 0.0, M_PI_2l, 0); + TEST_c_c (catan, minus_infty, 0.0, -M_PI_2l, 0); + TEST_c_c (catan, plus_infty, 0.1L, M_PI_2l, 0); + TEST_c_c (catan, minus_infty, 0.1L, -M_PI_2l, 0); + + TEST_c_c (catan, 0.0, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, minus_zero, minus_infty, -M_PI_2l, minus_zero); + TEST_c_c (catan, 100.0, minus_infty, M_PI_2l, minus_zero); + TEST_c_c (catan, -100.0, minus_infty, -M_PI_2l, minus_zero); + + TEST_c_c (catan, 0.0, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, minus_zero, plus_infty, -M_PI_2l, 0); + TEST_c_c (catan, 0.5, plus_infty, M_PI_2l, 0); + TEST_c_c (catan, -0.5, plus_infty, -M_PI_2l, 0); + + TEST_c_c (catan, nan_value, 0.0, nan_value, 0); + TEST_c_c (catan, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (catan, nan_value, plus_infty, nan_value, 0); + TEST_c_c (catan, nan_value, minus_infty, nan_value, minus_zero); + + TEST_c_c (catan, 0.0, nan_value, nan_value, nan_value); + TEST_c_c (catan, minus_zero, nan_value, nan_value, nan_value); + + TEST_c_c (catan, plus_infty, nan_value, M_PI_2l, 0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (catan, minus_infty, nan_value, -M_PI_2l, 0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (catan, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catan, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catan, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catan, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catan, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (catan, 0.75L, 1.25L, 1.10714871779409050301706546017853704L, 0.549306144334054845697622618461262852L); + TEST_c_c (catan, -2, -3, -1.4099210495965755225306193844604208L, -0.22907268296853876629588180294200276L); + + END (catan, complex); +} + +static void +catanh_test (void) +{ + errno = 0; + FUNC(catanh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (catanh); + + TEST_c_c (catanh, 0, 0, 0.0, 0.0); + TEST_c_c (catanh, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (catanh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (catanh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (catanh, plus_infty, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, minus_infty, 0.0, -M_PI_2l); + TEST_c_c (catanh, minus_infty, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, minus_infty, minus_zero, -M_PI_2l); + + TEST_c_c (catanh, -10.0, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, -10.0, minus_infty, minus_zero, -M_PI_2l); + TEST_c_c (catanh, minus_zero, plus_infty, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_zero, minus_infty, minus_zero, -M_PI_2l); + TEST_c_c (catanh, 0, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, 0, minus_infty, 0.0, -M_PI_2l); + TEST_c_c (catanh, 0.1L, plus_infty, 0.0, M_PI_2l); + TEST_c_c (catanh, 0.1L, minus_infty, 0.0, -M_PI_2l); + + TEST_c_c (catanh, minus_infty, 0, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, minus_zero, minus_zero, -M_PI_2l); + TEST_c_c (catanh, minus_infty, 100, minus_zero, M_PI_2l); + TEST_c_c (catanh, minus_infty, -100, minus_zero, -M_PI_2l); + + TEST_c_c (catanh, plus_infty, 0, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, minus_zero, 0.0, -M_PI_2l); + TEST_c_c (catanh, plus_infty, 0.5, 0.0, M_PI_2l); + TEST_c_c (catanh, plus_infty, -0.5, 0.0, -M_PI_2l); + + TEST_c_c (catanh, 0, nan_value, 0.0, nan_value); + TEST_c_c (catanh, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (catanh, plus_infty, nan_value, 0.0, nan_value); + TEST_c_c (catanh, minus_infty, nan_value, minus_zero, nan_value); + + TEST_c_c (catanh, nan_value, 0, nan_value, nan_value); + TEST_c_c (catanh, nan_value, minus_zero, nan_value, nan_value); + + TEST_c_c (catanh, nan_value, plus_infty, 0.0, M_PI_2l, IGNORE_ZERO_INF_SIGN); + TEST_c_c (catanh, nan_value, minus_infty, 0.0, -M_PI_2l, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (catanh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catanh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catanh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (catanh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (catanh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (catanh, 0.75L, 1.25L, 0.261492138795671927078652057366532140L, 0.996825126463918666098902241310446708L); + TEST_c_c (catanh, -2, -3, -0.14694666622552975204743278515471595L, -1.3389725222944935611241935759091443L); + + END (catanh, complex); +} +#endif + +static void +cbrt_test (void) +{ + errno = 0; + FUNC(cbrt) (8); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cbrt); + + TEST_f_f (cbrt, 0.0, 0.0); + TEST_f_f (cbrt, minus_zero, minus_zero); + + TEST_f_f (cbrt, plus_infty, plus_infty); + TEST_f_f (cbrt, minus_infty, minus_infty); + TEST_f_f (cbrt, nan_value, nan_value); + + TEST_f_f (cbrt, -0.001L, -0.1L); + TEST_f_f (cbrt, 8, 2); + TEST_f_f (cbrt, -27.0, -3.0); + TEST_f_f (cbrt, 0.9921875L, 0.997389022060725270579075195353955217L); + TEST_f_f (cbrt, 0.75L, 0.908560296416069829445605878163630251L); + + END (cbrt); +} + + +#if 0 +static void +ccos_test (void) +{ + errno = 0; + FUNC(ccos) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ccos); + + TEST_c_c (ccos, 0.0, 0.0, 1.0, minus_zero); + TEST_c_c (ccos, minus_zero, 0.0, 1.0, 0.0); + TEST_c_c (ccos, 0.0, minus_zero, 1.0, 0.0); + TEST_c_c (ccos, minus_zero, minus_zero, 1.0, minus_zero); + + TEST_c_c (ccos, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, 0.0, plus_infty, plus_infty, minus_zero); + TEST_c_c (ccos, 0.0, minus_infty, plus_infty, 0.0); + TEST_c_c (ccos, minus_zero, plus_infty, plus_infty, 0.0); + TEST_c_c (ccos, minus_zero, minus_infty, plus_infty, minus_zero); + + TEST_c_c (ccos, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccos, 4.625, plus_infty, minus_infty, plus_infty); + TEST_c_c (ccos, 4.625, minus_infty, minus_infty, minus_infty); + TEST_c_c (ccos, -4.625, plus_infty, minus_infty, minus_infty); + TEST_c_c (ccos, -4.625, minus_infty, minus_infty, plus_infty); + + TEST_c_c (ccos, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccos, minus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccos, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (ccos, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (ccos, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccos, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccos, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, -10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccos, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccos, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ccos, 0.75L, 1.25L, 1.38173873063425888530729933139078645L, -1.09193013555397466170919531722024128L); + TEST_c_c (ccos, -2, -3, -4.18962569096880723013255501961597373L, -9.10922789375533659797919726277886212L); + + END (ccos, complex); +} + + +static void +ccosh_test (void) +{ + errno = 0; + FUNC(ccosh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ccosh); + + TEST_c_c (ccosh, 0.0, 0.0, 1.0, 0.0); + TEST_c_c (ccosh, minus_zero, 0.0, 1.0, minus_zero); + TEST_c_c (ccosh, 0.0, minus_zero, 1.0, minus_zero); + TEST_c_c (ccosh, minus_zero, minus_zero, 1.0, 0.0); + + TEST_c_c (ccosh, 0.0, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, 0.0, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, plus_infty, 0.0, plus_infty, 0.0); + TEST_c_c (ccosh, minus_infty, 0.0, plus_infty, minus_zero); + TEST_c_c (ccosh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (ccosh, minus_infty, minus_zero, plus_infty, 0.0); + + TEST_c_c (ccosh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccosh, plus_infty, 4.625, minus_infty, minus_infty); + TEST_c_c (ccosh, minus_infty, 4.625, minus_infty, plus_infty); + TEST_c_c (ccosh, plus_infty, -4.625, minus_infty, plus_infty); + TEST_c_c (ccosh, minus_infty, -4.625, minus_infty, minus_infty); + + TEST_c_c (ccosh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ccosh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ccosh, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (ccosh, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (ccosh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ccosh, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ccosh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ccosh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ccosh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ccosh, 0.75L, 1.25L, 0.408242591877968807788852146397499084L, 0.780365930845853240391326216300863152L); + + TEST_c_c (ccosh, -2, -3, -3.72454550491532256547397070325597253L, 0.511822569987384608834463849801875634L); + + END (ccosh, complex); +} +#endif + + +static void +ceil_test (void) +{ + START (ceil); + + TEST_f_f (ceil, 0.0, 0.0); + TEST_f_f (ceil, minus_zero, minus_zero); + TEST_f_f (ceil, plus_infty, plus_infty); + TEST_f_f (ceil, minus_infty, minus_infty); + TEST_f_f (ceil, nan_value, nan_value); + + TEST_f_f (ceil, M_PIl, 4.0); + TEST_f_f (ceil, -M_PIl, -3.0); + TEST_f_f (ceil, 0.25, 1.0); + TEST_f_f (ceil, -0.25, minus_zero); + +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (ceil, 4503599627370495.5L, 4503599627370496.0L); + TEST_f_f (ceil, 4503599627370496.25L, 4503599627370497.0L); + TEST_f_f (ceil, 4503599627370496.5L, 4503599627370497.0L); + TEST_f_f (ceil, 4503599627370496.75L, 4503599627370497.0L); + TEST_f_f (ceil, 4503599627370497.5L, 4503599627370498.0L); + + TEST_f_f (ceil, -4503599627370495.5L, -4503599627370495.0L); + TEST_f_f (ceil, -4503599627370496.25L, -4503599627370496.0L); + TEST_f_f (ceil, -4503599627370496.5L, -4503599627370496.0L); + TEST_f_f (ceil, -4503599627370496.75L, -4503599627370496.0L); + TEST_f_f (ceil, -4503599627370497.5L, -4503599627370497.0L); + + TEST_f_f (ceil, 9007199254740991.5L, 9007199254740992.0L); + TEST_f_f (ceil, 9007199254740992.25L, 9007199254740993.0L); + TEST_f_f (ceil, 9007199254740992.5L, 9007199254740993.0L); + TEST_f_f (ceil, 9007199254740992.75L, 9007199254740993.0L); + TEST_f_f (ceil, 9007199254740993.5L, 9007199254740994.0L); + + TEST_f_f (ceil, -9007199254740991.5L, -9007199254740991.0L); + TEST_f_f (ceil, -9007199254740992.25L, -9007199254740992.0L); + TEST_f_f (ceil, -9007199254740992.5L, -9007199254740992.0L); + TEST_f_f (ceil, -9007199254740992.75L, -9007199254740992.0L); + TEST_f_f (ceil, -9007199254740993.5L, -9007199254740993.0L); + + TEST_f_f (ceil, 72057594037927935.5L, 72057594037927936.0L); + TEST_f_f (ceil, 72057594037927936.25L, 72057594037927937.0L); + TEST_f_f (ceil, 72057594037927936.5L, 72057594037927937.0L); + TEST_f_f (ceil, 72057594037927936.75L, 72057594037927937.0L); + TEST_f_f (ceil, 72057594037927937.5L, 72057594037927938.0L); + + TEST_f_f (ceil, -72057594037927935.5L, -72057594037927935.0L); + TEST_f_f (ceil, -72057594037927936.25L, -72057594037927936.0L); + TEST_f_f (ceil, -72057594037927936.5L, -72057594037927936.0L); + TEST_f_f (ceil, -72057594037927936.75L, -72057594037927936.0L); + TEST_f_f (ceil, -72057594037927937.5L, -72057594037927937.0L); + + TEST_f_f (ceil, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L); + TEST_f_f (ceil, 10141204801825835211973625643008.25L, 10141204801825835211973625643009.0L); + TEST_f_f (ceil, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L); + TEST_f_f (ceil, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L); + TEST_f_f (ceil, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L); +#endif + + END (ceil); +} + + +#if 0 +static void +cexp_test (void) +{ + errno = 0; + FUNC(cexp) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cexp); + + TEST_c_c (cexp, plus_zero, plus_zero, 1, 0.0); + TEST_c_c (cexp, minus_zero, plus_zero, 1, 0.0); + TEST_c_c (cexp, plus_zero, minus_zero, 1, minus_zero); + TEST_c_c (cexp, minus_zero, minus_zero, 1, minus_zero); + + TEST_c_c (cexp, plus_infty, plus_zero, plus_infty, 0.0); + TEST_c_c (cexp, plus_infty, minus_zero, plus_infty, minus_zero); + + TEST_c_c (cexp, minus_infty, plus_zero, 0.0, 0.0); + TEST_c_c (cexp, minus_infty, minus_zero, 0.0, minus_zero); + + TEST_c_c (cexp, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, -100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, 100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (cexp, -100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (cexp, minus_infty, 2.0, minus_zero, 0.0); + TEST_c_c (cexp, minus_infty, 4.0, minus_zero, minus_zero); + TEST_c_c (cexp, plus_infty, 2.0, minus_infty, plus_infty); + TEST_c_c (cexp, plus_infty, 4.0, minus_infty, minus_infty); + + TEST_c_c (cexp, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (cexp, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, minus_infty, plus_infty, 0.0, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (cexp, minus_infty, minus_infty, 0.0, minus_zero, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, minus_infty, nan_value, 0, 0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (cexp, plus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (cexp, nan_value, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, nan_value, 1.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (cexp, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (cexp, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cexp, 0.75L, 1.25L, 0.667537446429131586942201977015932112L, 2.00900045494094876258347228145863909L); + TEST_c_c (cexp, -2.0, -3.0, -0.13398091492954261346140525546115575L, -0.019098516261135196432576240858800925L); + + END (cexp, complex); +} + + +static void +cimag_test (void) +{ + START (cimag); + TEST_c_f (cimag, 1.0, 0.0, 0.0); + TEST_c_f (cimag, 1.0, minus_zero, minus_zero); + TEST_c_f (cimag, 1.0, nan_value, nan_value); + TEST_c_f (cimag, nan_value, nan_value, nan_value); + TEST_c_f (cimag, 1.0, plus_infty, plus_infty); + TEST_c_f (cimag, 1.0, minus_infty, minus_infty); + TEST_c_f (cimag, 2.0, 3.0, 3.0); + + END (cimag); +} + +static void +clog_test (void) +{ + errno = 0; + FUNC(clog) (BUILD_COMPLEX (-2, -3)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (clog); + + TEST_c_c (clog, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog, minus_infty, plus_infty, plus_infty, M_PI_34l); + TEST_c_c (clog, minus_infty, minus_infty, plus_infty, -M_PI_34l); + + TEST_c_c (clog, plus_infty, plus_infty, plus_infty, M_PI_4l); + TEST_c_c (clog, plus_infty, minus_infty, plus_infty, -M_PI_4l); + + TEST_c_c (clog, 0, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, 3, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, minus_zero, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, -3, plus_infty, plus_infty, M_PI_2l); + TEST_c_c (clog, 0, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, 3, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, minus_zero, minus_infty, plus_infty, -M_PI_2l); + TEST_c_c (clog, -3, minus_infty, plus_infty, -M_PI_2l); + + TEST_c_c (clog, minus_infty, 0, plus_infty, M_PIl); + TEST_c_c (clog, minus_infty, 1, plus_infty, M_PIl); + TEST_c_c (clog, minus_infty, minus_zero, plus_infty, -M_PIl); + TEST_c_c (clog, minus_infty, -1, plus_infty, -M_PIl); + + TEST_c_c (clog, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (clog, plus_infty, 1, plus_infty, 0.0); + TEST_c_c (clog, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (clog, plus_infty, -1, plus_infty, minus_zero); + + TEST_c_c (clog, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (clog, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (clog, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (clog, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (clog, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (clog, 0.75L, 1.25L, 0.376885901188190075998919126749298416L, 1.03037682652431246378774332703115153L); + TEST_c_c (clog, -2, -3, 1.2824746787307683680267437207826593L, -2.1587989303424641704769327722648368L); + + END (clog, complex); +} + + +static void +clog10_test (void) +{ + errno = 0; + FUNC(clog10) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (clog10); + + TEST_c_c (clog10, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog10, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog10, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION); + TEST_c_c (clog10, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_c_c (clog10, minus_infty, plus_infty, plus_infty, M_PI_34_LOG10El); + + TEST_c_c (clog10, plus_infty, plus_infty, plus_infty, M_PI4_LOG10El); + TEST_c_c (clog10, plus_infty, minus_infty, plus_infty, -M_PI4_LOG10El); + + TEST_c_c (clog10, 0, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, 3, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, minus_zero, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, -3, plus_infty, plus_infty, M_PI2_LOG10El); + TEST_c_c (clog10, 0, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, 3, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, minus_zero, minus_infty, plus_infty, -M_PI2_LOG10El); + TEST_c_c (clog10, -3, minus_infty, plus_infty, -M_PI2_LOG10El); + + TEST_c_c (clog10, minus_infty, 0, plus_infty, M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, 1, plus_infty, M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, minus_zero, plus_infty, -M_PI_LOG10El); + TEST_c_c (clog10, minus_infty, -1, plus_infty, -M_PI_LOG10El); + + TEST_c_c (clog10, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (clog10, plus_infty, 1, plus_infty, 0.0); + TEST_c_c (clog10, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (clog10, plus_infty, -1, plus_infty, minus_zero); + + TEST_c_c (clog10, plus_infty, nan_value, plus_infty, nan_value); + TEST_c_c (clog10, minus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (clog10, nan_value, plus_infty, plus_infty, nan_value); + TEST_c_c (clog10, nan_value, minus_infty, plus_infty, nan_value); + + TEST_c_c (clog10, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog10, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (clog10, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (clog10, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (clog10, 0.75L, 1.25L, 0.163679467193165171449476605077428975L, 0.447486970040493067069984724340855636L); + TEST_c_c (clog10, -2, -3, 0.556971676153418384603252578971164214L, -0.937554462986374708541507952140189646L); + + END (clog10, complex); +} +#endif + + +#if 0 +static void +conj_test (void) +{ + START (conj); + TEST_c_c (conj, 0.0, 0.0, 0.0, minus_zero); + TEST_c_c (conj, 0.0, minus_zero, 0.0, 0.0); + TEST_c_c (conj, nan_value, nan_value, nan_value, nan_value); + TEST_c_c (conj, plus_infty, minus_infty, plus_infty, plus_infty); + TEST_c_c (conj, plus_infty, plus_infty, plus_infty, minus_infty); + TEST_c_c (conj, 1.0, 2.0, 1.0, -2.0); + TEST_c_c (conj, 3.0, -4.0, 3.0, 4.0); + + END (conj, complex); +} +#endif + + +static void +copysign_test (void) +{ + START (copysign); + + TEST_ff_f (copysign, 0, 4, 0); + TEST_ff_f (copysign, 0, -4, minus_zero); + TEST_ff_f (copysign, minus_zero, 4, 0); + TEST_ff_f (copysign, minus_zero, -4, minus_zero); + + TEST_ff_f (copysign, plus_infty, 0, plus_infty); + TEST_ff_f (copysign, plus_infty, minus_zero, minus_infty); + TEST_ff_f (copysign, minus_infty, 0, plus_infty); + TEST_ff_f (copysign, minus_infty, minus_zero, minus_infty); + + TEST_ff_f (copysign, 0, plus_infty, 0); + TEST_ff_f (copysign, 0, minus_zero, minus_zero); + TEST_ff_f (copysign, minus_zero, plus_infty, 0); + TEST_ff_f (copysign, minus_zero, minus_zero, minus_zero); + + /* XXX More correctly we would have to check the sign of the NaN. */ + TEST_ff_f (copysign, nan_value, 0, nan_value); + TEST_ff_f (copysign, nan_value, minus_zero, nan_value); + TEST_ff_f (copysign, -nan_value, 0, nan_value); + TEST_ff_f (copysign, -nan_value, minus_zero, nan_value); + + END (copysign); +} + + +static void +cos_test (void) +{ + errno = 0; + FUNC(cos) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cos); + + TEST_f_f (cos, 0, 1); + TEST_f_f (cos, minus_zero, 1); + TEST_f_f (cos, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (cos, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (cos, nan_value, nan_value); + + TEST_f_f (cos, M_PI_6l * 2.0, 0.5); + TEST_f_f (cos, M_PI_6l * 4.0, -0.5); + TEST_f_f (cos, M_PI_2l, 0); + + TEST_f_f (cos, 0.75L, 0.731688868873820886311838753000084544L); + +#ifdef TEST_DOUBLE + TEST_f_f (cos, 0.80190127184058835, 0.69534156199418473); +#endif + + END (cos); +} + + +static void +cosh_test (void) +{ + errno = 0; + FUNC(cosh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cosh); + TEST_f_f (cosh, 0, 1); + TEST_f_f (cosh, minus_zero, 1); + +#ifndef TEST_INLINE + TEST_f_f (cosh, plus_infty, plus_infty); + TEST_f_f (cosh, minus_infty, plus_infty); +#endif + TEST_f_f (cosh, nan_value, nan_value); + + TEST_f_f (cosh, 0.75L, 1.29468328467684468784170818539018176L); + + END (cosh); +} + + +#if 0 +static void +cpow_test (void) +{ + errno = 0; + FUNC(cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (cpow); + + TEST_cc_c (cpow, 1, 0, 0, 0, 1.0, 0.0); + TEST_cc_c (cpow, 2, 0, 10, 0, 1024.0, 0.0); + + TEST_cc_c (cpow, M_El, 0, 0, 2 * M_PIl, 1.0, 0.0); + TEST_cc_c (cpow, 2, 3, 4, 0, -119.0, -120.0); + + TEST_cc_c (cpow, nan_value, nan_value, nan_value, nan_value, nan_value, nan_value); + + TEST_cc_c (cpow, 0.75L, 1.25L, 0.75L, 1.25L, 0.117506293914473555420279832210420483L, 0.346552747708338676483025352060418001L); + TEST_cc_c (cpow, 0.75L, 1.25L, 1.0L, 1.0L, 0.0846958290317209430433805274189191353L, 0.513285749182902449043287190519090481L); + TEST_cc_c (cpow, 0.75L, 1.25L, 1.0L, 0.0L, 0.75L, 1.25L); + TEST_cc_c (cpow, 0.75L, 1.25L, 0.0L, 1.0L, 0.331825439177608832276067945276730566L, 0.131338600281188544930936345230903032L); + + END (cpow, complex); +} + + +static void +cproj_test (void) +{ + START (cproj); + TEST_c_c (cproj, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (cproj, minus_zero, minus_zero, minus_zero, minus_zero); + TEST_c_c (cproj, 0.0, minus_zero, 0.0, minus_zero); + TEST_c_c (cproj, minus_zero, 0.0, minus_zero, 0.0); + + TEST_c_c (cproj, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0); + TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero); + TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0); + TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero); + + TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0); + TEST_c_c (cproj, 2.0, 3.0, 0.2857142857142857142857142857142857L, 0.42857142857142857142857142857142855L); + + END (cproj, complex); +} + + +static void +creal_test (void) +{ + START (creal); + TEST_c_f (creal, 0.0, 1.0, 0.0); + TEST_c_f (creal, minus_zero, 1.0, minus_zero); + TEST_c_f (creal, nan_value, 1.0, nan_value); + TEST_c_f (creal, nan_value, nan_value, nan_value); + TEST_c_f (creal, plus_infty, 1.0, plus_infty); + TEST_c_f (creal, minus_infty, 1.0, minus_infty); + TEST_c_f (creal, 2.0, 3.0, 2.0); + + END (creal); +} + +static void +csin_test (void) +{ + errno = 0; + FUNC(csin) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csin); + + TEST_c_c (csin, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (csin, minus_zero, 0.0, minus_zero, 0.0); + TEST_c_c (csin, 0.0, minus_zero, 0, minus_zero); + TEST_c_c (csin, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (csin, 0.0, plus_infty, 0.0, plus_infty); + TEST_c_c (csin, minus_zero, plus_infty, minus_zero, plus_infty); + TEST_c_c (csin, 0.0, minus_infty, 0.0, minus_infty); + TEST_c_c (csin, minus_zero, minus_infty, minus_zero, minus_infty); + + TEST_c_c (csin, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, plus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, plus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, minus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csin, minus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (csin, 4.625, plus_infty, minus_infty, minus_infty); + TEST_c_c (csin, 4.625, minus_infty, minus_infty, plus_infty); + TEST_c_c (csin, -4.625, plus_infty, plus_infty, minus_infty); + TEST_c_c (csin, -4.625, minus_infty, plus_infty, plus_infty); + + TEST_c_c (csin, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, nan_value, plus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csin, nan_value, minus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csin, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, 0.0, nan_value, 0.0, nan_value); + TEST_c_c (csin, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (csin, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csin, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csin, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csin, 0.75L, 1.25L, 1.28722291002649188575873510790565441L, 1.17210635989270256101081285116138863L); + TEST_c_c (csin, -2, -3, -9.15449914691142957346729954460983256L, 4.16890695996656435075481305885375484L); + + END (csin, complex); +} + + +static void +csinh_test (void) +{ + errno = 0; + FUNC(csinh) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csinh); + + TEST_c_c (csinh, 0.0, 0.0, 0.0, 0.0); + TEST_c_c (csinh, minus_zero, 0.0, minus_zero, 0.0); + TEST_c_c (csinh, 0.0, minus_zero, 0.0, minus_zero); + TEST_c_c (csinh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (csinh, 0.0, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, 0.0, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, 0.0, plus_infty, 0.0); + TEST_c_c (csinh, minus_infty, 0.0, minus_infty, 0.0); + TEST_c_c (csinh, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (csinh, minus_infty, minus_zero, minus_infty, minus_zero); + + TEST_c_c (csinh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, 4.625, minus_infty, minus_infty); + TEST_c_c (csinh, minus_infty, 4.625, plus_infty, minus_infty); + TEST_c_c (csinh, plus_infty, -4.625, minus_infty, plus_infty); + TEST_c_c (csinh, minus_infty, -4.625, plus_infty, plus_infty); + + TEST_c_c (csinh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (csinh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (csinh, 0.0, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_zero, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, plus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + TEST_c_c (csinh, minus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csinh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, 0.0, nan_value, 0.0); + TEST_c_c (csinh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (csinh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csinh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csinh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csinh, 0.75L, 1.25L, 0.259294854551162779153349830618433028L, 1.22863452409509552219214606515777594L); + TEST_c_c (csinh, -2, -3, 3.59056458998577995201256544779481679L, -0.530921086248519805267040090660676560L); + + END (csinh, complex); +} + + +static void +csqrt_test (void) +{ + errno = 0; + FUNC(csqrt) (BUILD_COMPLEX (-1, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (csqrt); + + TEST_c_c (csqrt, 0, 0, 0.0, 0.0); + TEST_c_c (csqrt, 0, minus_zero, 0, minus_zero); + TEST_c_c (csqrt, minus_zero, 0, 0.0, 0.0); + TEST_c_c (csqrt, minus_zero, minus_zero, 0.0, minus_zero); + + TEST_c_c (csqrt, minus_infty, 0, 0.0, plus_infty); + TEST_c_c (csqrt, minus_infty, 6, 0.0, plus_infty); + TEST_c_c (csqrt, minus_infty, minus_zero, 0.0, minus_infty); + TEST_c_c (csqrt, minus_infty, -6, 0.0, minus_infty); + + TEST_c_c (csqrt, plus_infty, 0, plus_infty, 0.0); + TEST_c_c (csqrt, plus_infty, 6, plus_infty, 0.0); + TEST_c_c (csqrt, plus_infty, minus_zero, plus_infty, minus_zero); + TEST_c_c (csqrt, plus_infty, -6, plus_infty, minus_zero); + + TEST_c_c (csqrt, 0, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, 4, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, plus_infty, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, minus_zero, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, -4, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, minus_infty, plus_infty, plus_infty, plus_infty); + TEST_c_c (csqrt, 0, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, 4, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, plus_infty, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, minus_zero, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, -4, minus_infty, plus_infty, minus_infty); + TEST_c_c (csqrt, minus_infty, minus_infty, plus_infty, minus_infty); + + TEST_c_c (csqrt, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (csqrt, plus_infty, nan_value, plus_infty, nan_value); + + TEST_c_c (csqrt, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, -1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csqrt, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, 8, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (csqrt, nan_value, -8, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (csqrt, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (csqrt, 16.0, -30.0, 5.0, -3.0); + TEST_c_c (csqrt, -1, 0, 0.0, 1.0); + TEST_c_c (csqrt, 0, 2, 1.0, 1.0); + TEST_c_c (csqrt, 119, 120, 12.0, 5.0); + TEST_c_c (csqrt, 0.75L, 1.25L, 1.05065169626078392338656675760808326L, 0.594868882070379067881984030639932657L); + TEST_c_c (csqrt, -2, -3, 0.89597747612983812471573375529004348L, -1.6741492280355400404480393008490519L); + TEST_c_c (csqrt, -2, 3, 0.89597747612983812471573375529004348L, 1.6741492280355400404480393008490519L); + /* Principal square root should be returned (i.e., non-negative real + part). */ + TEST_c_c (csqrt, 0, -1, M_SQRT_2_2, -M_SQRT_2_2); + + END (csqrt, complex); +} + +static void +ctan_test (void) +{ + errno = 0; + FUNC(ctan) (BUILD_COMPLEX (0.7L, 1.2L)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ctan); + + TEST_c_c (ctan, 0, 0, 0.0, 0.0); + TEST_c_c (ctan, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (ctan, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (ctan, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (ctan, 0, plus_infty, 0.0, 1.0); + TEST_c_c (ctan, 1, plus_infty, 0.0, 1.0); + TEST_c_c (ctan, minus_zero, plus_infty, minus_zero, 1.0); + TEST_c_c (ctan, -1, plus_infty, minus_zero, 1.0); + + TEST_c_c (ctan, 0, minus_infty, 0.0, -1.0); + TEST_c_c (ctan, 1, minus_infty, 0.0, -1.0); + TEST_c_c (ctan, minus_zero, minus_infty, minus_zero, -1.0); + TEST_c_c (ctan, -1, minus_infty, minus_zero, -1.0); + + TEST_c_c (ctan, plus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, plus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctan, minus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ctan, nan_value, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ctan, nan_value, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ctan, 0, nan_value, 0.0, nan_value); + TEST_c_c (ctan, minus_zero, nan_value, minus_zero, nan_value); + + TEST_c_c (ctan, 0.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, -4.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctan, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctan, nan_value, -0.25, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctan, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ctan, 0.75L, 1.25L, 0.160807785916206426725166058173438663L, 0.975363285031235646193581759755216379L); + TEST_c_c (ctan, -2, -3, 0.376402564150424829275122113032269084e-2L, -1.00323862735360980144635859782192726L); + + END (ctan, complex); +} + + +static void +ctanh_test (void) +{ + errno = 0; + FUNC(ctanh) (BUILD_COMPLEX (0, 0)); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (ctanh); + + TEST_c_c (ctanh, 0, 0, 0.0, 0.0); + TEST_c_c (ctanh, 0, minus_zero, 0.0, minus_zero); + TEST_c_c (ctanh, minus_zero, 0, minus_zero, 0.0); + TEST_c_c (ctanh, minus_zero, minus_zero, minus_zero, minus_zero); + + TEST_c_c (ctanh, plus_infty, 0, 1.0, 0.0); + TEST_c_c (ctanh, plus_infty, 1, 1.0, 0.0); + TEST_c_c (ctanh, plus_infty, minus_zero, 1.0, minus_zero); + TEST_c_c (ctanh, plus_infty, -1, 1.0, minus_zero); + TEST_c_c (ctanh, minus_infty, 0, -1.0, 0.0); + TEST_c_c (ctanh, minus_infty, 1, -1.0, 0.0); + TEST_c_c (ctanh, minus_infty, minus_zero, -1.0, minus_zero); + TEST_c_c (ctanh, minus_infty, -1, -1.0, minus_zero); + + TEST_c_c (ctanh, 0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, 2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, -2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_c_c (ctanh, -2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + + TEST_c_c (ctanh, plus_infty, nan_value, 1.0, 0.0, IGNORE_ZERO_INF_SIGN); + TEST_c_c (ctanh, minus_infty, nan_value, -1.0, 0.0, IGNORE_ZERO_INF_SIGN); + + TEST_c_c (ctanh, nan_value, 0, nan_value, 0.0); + TEST_c_c (ctanh, nan_value, minus_zero, nan_value, minus_zero); + + TEST_c_c (ctanh, nan_value, 0.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, nan_value, -4.5, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctanh, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, 5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_c_c (ctanh, -0.25, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK); + + TEST_c_c (ctanh, nan_value, nan_value, nan_value, nan_value); + + TEST_c_c (ctanh, 0, M_PI_4l, 0.0, 1.0); + + TEST_c_c (ctanh, 0.75L, 1.25L, 1.37260757053378320258048606571226857L, 0.385795952609750664177596760720790220L); + TEST_c_c (ctanh, -2, -3, -0.965385879022133124278480269394560686L, 0.988437503832249372031403430350121098e-2L); + + END (ctanh, complex); +} +#endif + + +static void +erf_test (void) +{ + errno = 0; + FUNC(erf) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (erf); + + TEST_f_f (erf, 0, 0); + TEST_f_f (erf, minus_zero, minus_zero); + TEST_f_f (erf, plus_infty, 1); + TEST_f_f (erf, minus_infty, -1); + TEST_f_f (erf, nan_value, nan_value); + + TEST_f_f (erf, 0.125L, 0.140316204801333817393029446521623398L); + TEST_f_f (erf, 0.75L, 0.711155633653515131598937834591410777L); + TEST_f_f (erf, 1.25L, 0.922900128256458230136523481197281140L); + TEST_f_f (erf, 2.0L, 0.995322265018952734162069256367252929L); + TEST_f_f (erf, 4.125L, 0.999999994576599200434933994687765914L); + TEST_f_f (erf, 27.0L, 1.0L); + + END (erf); +} + + +static void +erfc_test (void) +{ + errno = 0; + FUNC(erfc) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (erfc); + + TEST_f_f (erfc, plus_infty, 0.0); + TEST_f_f (erfc, minus_infty, 2.0); + TEST_f_f (erfc, 0.0, 1.0); + TEST_f_f (erfc, minus_zero, 1.0); + TEST_f_f (erfc, nan_value, nan_value); + + TEST_f_f (erfc, 0.125L, 0.859683795198666182606970553478376602L); + TEST_f_f (erfc, 0.75L, 0.288844366346484868401062165408589223L); + TEST_f_f (erfc, 1.25L, 0.0770998717435417698634765188027188596L); + TEST_f_f (erfc, 2.0L, 0.00467773498104726583793074363274707139L); + TEST_f_f (erfc, 4.125L, 0.542340079956506600531223408575531062e-8L); +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ +# if LDBL_MIN_10_EXP < -319 + TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L); +# endif +#endif + + END (erfc); +} + + +static void +exp_test (void) +{ + errno = 0; + FUNC(exp) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp); + + TEST_f_f (exp, 0, 1); + TEST_f_f (exp, minus_zero, 1); + +#ifndef TEST_INLINE + TEST_f_f (exp, plus_infty, plus_infty); + TEST_f_f (exp, minus_infty, 0); +#endif + TEST_f_f (exp, nan_value, nan_value); + TEST_f_f (exp, 1, M_El); + + TEST_f_f (exp, 2, M_E2l); + TEST_f_f (exp, 3, M_E3l); + TEST_f_f (exp, 0.75L, 2.11700001661267466854536981983709561L); + TEST_f_f (exp, 50.0L, 5184705528587072464087.45332293348538L); +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L); +#endif + + END (exp); +} + + +#if 0 +static void +exp10_test (void) +{ + errno = 0; + FUNC(exp10) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp10); + + TEST_f_f (exp10, 0, 1); + TEST_f_f (exp10, minus_zero, 1); + + TEST_f_f (exp10, plus_infty, plus_infty); + TEST_f_f (exp10, minus_infty, 0); + TEST_f_f (exp10, nan_value, nan_value); + TEST_f_f (exp10, 3, 1000); + TEST_f_f (exp10, -1, 0.1L); + TEST_f_f (exp10, 1e6, plus_infty); + TEST_f_f (exp10, -1e6, 0); + TEST_f_f (exp10, 0.75L, 5.62341325190349080394951039776481231L); + + END (exp10); +} + + +static void +exp2_test (void) +{ + errno = 0; + FUNC(exp2) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (exp2); + + TEST_f_f (exp2, 0, 1); + TEST_f_f (exp2, minus_zero, 1); + TEST_f_f (exp2, plus_infty, plus_infty); + TEST_f_f (exp2, minus_infty, 0); + TEST_f_f (exp2, nan_value, nan_value); + + TEST_f_f (exp2, 10, 1024); + TEST_f_f (exp2, -1, 0.5); + TEST_f_f (exp2, 1e6, plus_infty); + TEST_f_f (exp2, -1e6, 0); + TEST_f_f (exp2, 0.75L, 1.68179283050742908606225095246642979L); + + END (exp2); +} +#endif + + +static void +expm1_test (void) +{ + errno = 0; + FUNC(expm1) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (expm1); + + TEST_f_f (expm1, 0, 0); + TEST_f_f (expm1, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (expm1, plus_infty, plus_infty); + TEST_f_f (expm1, minus_infty, -1); +#endif + TEST_f_f (expm1, nan_value, nan_value); + + TEST_f_f (expm1, 1, M_El - 1.0); + TEST_f_f (expm1, 0.75L, 1.11700001661267466854536981983709561L); + + END (expm1); +} + + +static void +fabs_test (void) +{ + START (fabs); + + TEST_f_f (fabs, 0, 0); + TEST_f_f (fabs, minus_zero, 0); + + TEST_f_f (fabs, plus_infty, plus_infty); + TEST_f_f (fabs, minus_infty, plus_infty); + TEST_f_f (fabs, nan_value, nan_value); + + TEST_f_f (fabs, 38.0, 38.0); + TEST_f_f (fabs, -M_El, M_El); + + END (fabs); +} + + +#if 0 +static void +fdim_test (void) +{ + START (fdim); + + TEST_ff_f (fdim, 0, 0, 0); + TEST_ff_f (fdim, 9, 0, 9); + TEST_ff_f (fdim, 0, 9, 0); + TEST_ff_f (fdim, -9, 0, 0); + TEST_ff_f (fdim, 0, -9, 9); + + TEST_ff_f (fdim, plus_infty, 9, plus_infty); + TEST_ff_f (fdim, plus_infty, -9, plus_infty); + TEST_ff_f (fdim, minus_infty, 9, 0); + TEST_ff_f (fdim, minus_infty, -9, 0); + TEST_ff_f (fdim, 9, minus_infty, plus_infty); + TEST_ff_f (fdim, -9, minus_infty, plus_infty); + TEST_ff_f (fdim, 9, plus_infty, 0); + TEST_ff_f (fdim, -9, plus_infty, 0); + + TEST_ff_f (fdim, 0, nan_value, nan_value); + TEST_ff_f (fdim, 9, nan_value, nan_value); + TEST_ff_f (fdim, -9, nan_value, nan_value); + TEST_ff_f (fdim, nan_value, 9, nan_value); + TEST_ff_f (fdim, nan_value, -9, nan_value); + TEST_ff_f (fdim, plus_infty, nan_value, nan_value); + TEST_ff_f (fdim, minus_infty, nan_value, nan_value); + TEST_ff_f (fdim, nan_value, plus_infty, nan_value); + TEST_ff_f (fdim, nan_value, minus_infty, nan_value); + TEST_ff_f (fdim, nan_value, nan_value, nan_value); + + TEST_ff_f (fdim, plus_infty, plus_infty, 0); + + END (fdim); +} +#endif + + +static void +floor_test (void) +{ + START (floor); + + TEST_f_f (floor, 0.0, 0.0); + TEST_f_f (floor, minus_zero, minus_zero); + TEST_f_f (floor, plus_infty, plus_infty); + TEST_f_f (floor, minus_infty, minus_infty); + TEST_f_f (floor, nan_value, nan_value); + + TEST_f_f (floor, M_PIl, 3.0); + TEST_f_f (floor, -M_PIl, -4.0); + + TEST_f_f (floor, 0.25, 0.0); + TEST_f_f (floor, -0.25, -1.0); + + +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L); + TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L); + TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L); + TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L); + TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L); + + TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L); + TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L); + TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L); + TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L); + TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L); + + TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L); + TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L); + TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L); + TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L); + TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L); + + TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L); + TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L); + TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L); + TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L); + TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L); + + TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L); + TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L); + TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L); + TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L); + TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L); + + TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L); + TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L); + TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L); + TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L); + TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L); + + TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L); + TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L); + TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L); + TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L); + TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L); +#endif + + END (floor); +} + + +#if 0 +static void +fma_test (void) +{ + START (fma); + + TEST_fff_f (fma, 1.0, 2.0, 3.0, 5.0); + TEST_fff_f (fma, nan_value, 2.0, 3.0, nan_value); + TEST_fff_f (fma, 1.0, nan_value, 3.0, nan_value); + TEST_fff_f (fma, 1.0, 2.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, plus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, minus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK); + TEST_fff_f (fma, plus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, 0.0, plus_infty, 1.0, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, 0.0, minus_infty, 1.0, nan_value, INVALID_EXCEPTION); + + TEST_fff_f (fma, plus_infty, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_fff_f (fma, minus_infty, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + + TEST_fff_f (fma, 1.25L, 0.75L, 0.0625L, 1.0L); + + END (fma); +} + + +static void +fmax_test (void) +{ + START (fmax); + + TEST_ff_f (fmax, 0, 0, 0); + TEST_ff_f (fmax, minus_zero, minus_zero, minus_zero); + TEST_ff_f (fmax, 9, 0, 9); + TEST_ff_f (fmax, 0, 9, 9); + TEST_ff_f (fmax, -9, 0, 0); + TEST_ff_f (fmax, 0, -9, 0); + + TEST_ff_f (fmax, plus_infty, 9, plus_infty); + TEST_ff_f (fmax, 0, plus_infty, plus_infty); + TEST_ff_f (fmax, -9, plus_infty, plus_infty); + TEST_ff_f (fmax, plus_infty, -9, plus_infty); + + TEST_ff_f (fmax, minus_infty, 9, 9); + TEST_ff_f (fmax, minus_infty, -9, -9); + TEST_ff_f (fmax, 9, minus_infty, 9); + TEST_ff_f (fmax, -9, minus_infty, -9); + + TEST_ff_f (fmax, 0, nan_value, 0); + TEST_ff_f (fmax, 9, nan_value, 9); + TEST_ff_f (fmax, -9, nan_value, -9); + TEST_ff_f (fmax, nan_value, 0, 0); + TEST_ff_f (fmax, nan_value, 9, 9); + TEST_ff_f (fmax, nan_value, -9, -9); + TEST_ff_f (fmax, plus_infty, nan_value, plus_infty); + TEST_ff_f (fmax, minus_infty, nan_value, minus_infty); + TEST_ff_f (fmax, nan_value, plus_infty, plus_infty); + TEST_ff_f (fmax, nan_value, minus_infty, minus_infty); + TEST_ff_f (fmax, nan_value, nan_value, nan_value); + + END (fmax); +} + + +static void +fmin_test (void) +{ + START (fmin); + + TEST_ff_f (fmin, 0, 0, 0); + TEST_ff_f (fmin, minus_zero, minus_zero, minus_zero); + TEST_ff_f (fmin, 9, 0, 0); + TEST_ff_f (fmin, 0, 9, 0); + TEST_ff_f (fmin, -9, 0, -9); + TEST_ff_f (fmin, 0, -9, -9); + + TEST_ff_f (fmin, plus_infty, 9, 9); + TEST_ff_f (fmin, 9, plus_infty, 9); + TEST_ff_f (fmin, plus_infty, -9, -9); + TEST_ff_f (fmin, -9, plus_infty, -9); + TEST_ff_f (fmin, minus_infty, 9, minus_infty); + TEST_ff_f (fmin, minus_infty, -9, minus_infty); + TEST_ff_f (fmin, 9, minus_infty, minus_infty); + TEST_ff_f (fmin, -9, minus_infty, minus_infty); + + TEST_ff_f (fmin, 0, nan_value, 0); + TEST_ff_f (fmin, 9, nan_value, 9); + TEST_ff_f (fmin, -9, nan_value, -9); + TEST_ff_f (fmin, nan_value, 0, 0); + TEST_ff_f (fmin, nan_value, 9, 9); + TEST_ff_f (fmin, nan_value, -9, -9); + TEST_ff_f (fmin, plus_infty, nan_value, plus_infty); + TEST_ff_f (fmin, minus_infty, nan_value, minus_infty); + TEST_ff_f (fmin, nan_value, plus_infty, plus_infty); + TEST_ff_f (fmin, nan_value, minus_infty, minus_infty); + TEST_ff_f (fmin, nan_value, nan_value, nan_value); + + END (fmin); +} +#endif + + +static void +fmod_test (void) +{ + errno = 0; + FUNC(fmod) (6.5, 2.3L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (fmod); + + /* fmod (+0, y) == +0 for y != 0. */ + TEST_ff_f (fmod, 0, 3, 0); + + /* fmod (-0, y) == -0 for y != 0. */ + TEST_ff_f (fmod, minus_zero, 3, minus_zero); + + /* fmod (+inf, y) == NaN plus invalid exception. */ + TEST_ff_f (fmod, plus_infty, 3, nan_value, INVALID_EXCEPTION); + /* fmod (-inf, y) == NaN plus invalid exception. */ + TEST_ff_f (fmod, minus_infty, 3, nan_value, INVALID_EXCEPTION); + /* fmod (x, +0) == NaN plus invalid exception. */ + TEST_ff_f (fmod, 3, 0, nan_value, INVALID_EXCEPTION); + /* fmod (x, -0) == NaN plus invalid exception. */ + TEST_ff_f (fmod, 3, minus_zero, nan_value, INVALID_EXCEPTION); + + /* fmod (x, +inf) == x for x not infinite. */ + TEST_ff_f (fmod, 3.0, plus_infty, 3.0); + /* fmod (x, -inf) == x for x not infinite. */ + TEST_ff_f (fmod, 3.0, minus_infty, 3.0); + + TEST_ff_f (fmod, nan_value, nan_value, nan_value); + + TEST_ff_f (fmod, 6.5, 2.25L, 2.0L); + TEST_ff_f (fmod, -6.5, 2.25L, -2.0L); + TEST_ff_f (fmod, 6.5, -2.25L, 2.0L); + TEST_ff_f (fmod, -6.5, -2.25L, -2.0L); + + END (fmod); +} + + +static void +fpclassify_test (void) +{ + START (fpclassify); + + TEST_f_i (fpclassify, nan_value, FP_NAN); + TEST_f_i (fpclassify, plus_infty, FP_INFINITE); + TEST_f_i (fpclassify, minus_infty, FP_INFINITE); + TEST_f_i (fpclassify, plus_zero, FP_ZERO); + TEST_f_i (fpclassify, minus_zero, FP_ZERO); + TEST_f_i (fpclassify, 1000, FP_NORMAL); + + END (fpclassify); +} + + +static void +frexp_test (void) +{ + int x; + + START (frexp); + + TEST_fI_f1 (frexp, plus_infty, plus_infty, IGNORE); + TEST_fI_f1 (frexp, minus_infty, minus_infty, IGNORE); + TEST_fI_f1 (frexp, nan_value, nan_value, IGNORE); + + TEST_fI_f1 (frexp, 0.0, 0.0, 0.0); + TEST_fI_f1 (frexp, minus_zero, minus_zero, 0.0); + + TEST_fI_f1 (frexp, 12.8L, 0.8L, 4); + TEST_fI_f1 (frexp, -27.34L, -0.854375L, 5); + + END (frexp); +} + + +static void +gamma_test (void) +{ + errno = 0; + FUNC(gamma) (1); + + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (gamma); + + TEST_f_f (gamma, plus_infty, plus_infty); + TEST_f_f (gamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (gamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (gamma, minus_infty, plus_infty); + TEST_f_f (gamma, nan_value, nan_value); + + TEST_f_f1 (gamma, 1, 0, 1); + TEST_f_f1 (gamma, 3, M_LN2l, 1); + + TEST_f_f1 (gamma, 0.5, M_LOG_SQRT_PIl, 1); + TEST_f_f1 (gamma, -0.5, M_LOG_2_SQRT_PIl, -1); + + END (gamma); +} + +static void +hypot_test (void) +{ + errno = 0; + FUNC(hypot) (0.7L, 12.4L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (hypot); + + TEST_ff_f (hypot, plus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN); + TEST_ff_f (hypot, minus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN); + +#ifndef TEST_INLINE + TEST_ff_f (hypot, plus_infty, nan_value, plus_infty); + TEST_ff_f (hypot, minus_infty, nan_value, plus_infty); + TEST_ff_f (hypot, nan_value, plus_infty, plus_infty); + TEST_ff_f (hypot, nan_value, minus_infty, plus_infty); +#endif + + TEST_ff_f (hypot, nan_value, nan_value, nan_value); + + /* hypot (x,y) == hypot (+-x, +-y) */ + TEST_ff_f (hypot, 0.7L, 12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -0.7L, 12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 0.7L, -12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -0.7L, -12.4L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 12.4L, 0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -12.4L, 0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, 12.4L, -0.7L, 12.419742348374220601176836866763271L); + TEST_ff_f (hypot, -12.4L, -0.7L, 12.419742348374220601176836866763271L); + + /* hypot (x,0) == fabs (x) */ + TEST_ff_f (hypot, 0.75L, 0, 0.75L); + TEST_ff_f (hypot, -0.75L, 0, 0.75L); + TEST_ff_f (hypot, -5.7e7, 0, 5.7e7L); + + TEST_ff_f (hypot, 0.75L, 1.25L, 1.45773797371132511771853821938639577L); + + END (hypot); +} + + +static void +ilogb_test (void) +{ + START (ilogb); + + TEST_f_i (ilogb, 1, 0); + TEST_f_i (ilogb, M_El, 1); + TEST_f_i (ilogb, 1024, 10); + TEST_f_i (ilogb, -2000, 10); + + /* XXX We have a problem here: the standard does not tell us whether + exceptions are allowed/required. ignore them for now. */ + + TEST_f_i (ilogb, 0.0, FP_ILOGB0, EXCEPTIONS_OK); + TEST_f_i (ilogb, nan_value, FP_ILOGBNAN, EXCEPTIONS_OK); + TEST_f_i (ilogb, plus_infty, INT_MAX, EXCEPTIONS_OK); + TEST_f_i (ilogb, minus_infty, INT_MAX, EXCEPTIONS_OK); + + END (ilogb); +} + +static void +isfinite_test (void) +{ + START (isfinite); + + TEST_f_b (isfinite, 0, 1); + TEST_f_b (isfinite, minus_zero, 1); + TEST_f_b (isfinite, 10, 1); + TEST_f_b (isfinite, plus_infty, 0); + TEST_f_b (isfinite, minus_infty, 0); + TEST_f_b (isfinite, nan_value, 0); + + END (isfinite); +} + +static void +isnormal_test (void) +{ + START (isnormal); + + TEST_f_b (isnormal, 0, 0); + TEST_f_b (isnormal, minus_zero, 0); + TEST_f_b (isnormal, 10, 1); + TEST_f_b (isnormal, plus_infty, 0); + TEST_f_b (isnormal, minus_infty, 0); + TEST_f_b (isnormal, nan_value, 0); + + END (isnormal); +} + +static void +j0_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(j0) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (j0); + + /* j0 is the Bessel function of the first kind of order 0 */ + TEST_f_f (j0, nan_value, nan_value); + TEST_f_f (j0, plus_infty, 0); + TEST_f_f (j0, -1.0, 0.765197686557966551449717526102663221L); + TEST_f_f (j0, 0.0, 1.0); + TEST_f_f (j0, 0.125L, 0.996097563041985204620768999453174712L); + TEST_f_f (j0, 0.75L, 0.864242275166648623555731103820923211L); + TEST_f_f (j0, 1.0, 0.765197686557966551449717526102663221L); + TEST_f_f (j0, 1.5, 0.511827671735918128749051744283411720L); + TEST_f_f (j0, 2.0, 0.223890779141235668051827454649948626L); + TEST_f_f (j0, 8.0, 0.171650807137553906090869407851972001L); + TEST_f_f (j0, 10.0, -0.245935764451348335197760862485328754L); + TEST_f_f (j0, 4.0, -3.9714980986384737228659076845169804197562E-1L); + TEST_f_f (j0, -4.0, -3.9714980986384737228659076845169804197562E-1L); + + END (j0); +} + + +static void +j1_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(j1) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* j1 is the Bessel function of the first kind of order 1 */ + + START (j1); + + TEST_f_f (j1, nan_value, nan_value); + TEST_f_f (j1, plus_infty, 0); + + TEST_f_f (j1, -1.0, -0.440050585744933515959682203718914913L); + TEST_f_f (j1, 0.0, 0.0); + TEST_f_f (j1, 0.125L, 0.0623780091344946810942311355879361177L); + TEST_f_f (j1, 0.75L, 0.349243602174862192523281016426251335L); + TEST_f_f (j1, 1.0, 0.440050585744933515959682203718914913L); + TEST_f_f (j1, 1.5, 0.557936507910099641990121213156089400L); + TEST_f_f (j1, 2.0, 0.576724807756873387202448242269137087L); + TEST_f_f (j1, 8.0, 0.234636346853914624381276651590454612L); + TEST_f_f (j1, 10.0, 0.0434727461688614366697487680258592883L); + + END (j1); +} + +static void +jn_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(jn) (1, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* jn is the Bessel function of the first kind of order n. */ + START (jn); + + /* jn (0, x) == j0 (x) */ + TEST_ff_f (jn, 0, nan_value, nan_value); + TEST_ff_f (jn, 0, plus_infty, 0); + TEST_ff_f (jn, 0, -1.0, 0.765197686557966551449717526102663221L); + TEST_ff_f (jn, 0, 0.0, 1.0); + TEST_ff_f (jn, 0, 0.125L, 0.996097563041985204620768999453174712L); + TEST_ff_f (jn, 0, 0.75L, 0.864242275166648623555731103820923211L); + TEST_ff_f (jn, 0, 1.0, 0.765197686557966551449717526102663221L); + TEST_ff_f (jn, 0, 1.5, 0.511827671735918128749051744283411720L); + TEST_ff_f (jn, 0, 2.0, 0.223890779141235668051827454649948626L); + TEST_ff_f (jn, 0, 8.0, 0.171650807137553906090869407851972001L); + TEST_ff_f (jn, 0, 10.0, -0.245935764451348335197760862485328754L); + TEST_ff_f (jn, 0, 4.0, -3.9714980986384737228659076845169804197562E-1L); + TEST_ff_f (jn, 0, -4.0, -3.9714980986384737228659076845169804197562E-1L); + + /* jn (1, x) == j1 (x) */ + TEST_ff_f (jn, 1, nan_value, nan_value); + TEST_ff_f (jn, 1, plus_infty, 0); + TEST_ff_f (jn, 1, -1.0, -0.440050585744933515959682203718914913L); + TEST_ff_f (jn, 1, 0.0, 0.0); + TEST_ff_f (jn, 1, 0.125L, 0.0623780091344946810942311355879361177L); + TEST_ff_f (jn, 1, 0.75L, 0.349243602174862192523281016426251335L); + TEST_ff_f (jn, 1, 1.0, 0.440050585744933515959682203718914913L); + TEST_ff_f (jn, 1, 1.5, 0.557936507910099641990121213156089400L); + TEST_ff_f (jn, 1, 2.0, 0.576724807756873387202448242269137087L); + TEST_ff_f (jn, 1, 8.0, 0.234636346853914624381276651590454612L); + TEST_ff_f (jn, 1, 10.0, 0.0434727461688614366697487680258592883L); + + /* jn (3, x) */ + TEST_ff_f (jn, 3, nan_value, nan_value); + TEST_ff_f (jn, 3, plus_infty, 0); + + TEST_ff_f (jn, 3, -1.0, -0.0195633539826684059189053216217515083L); + TEST_ff_f (jn, 3, 0.0, 0.0); + TEST_ff_f (jn, 3, 0.125L, 0.406503832554912875023029337653442868e-4L); + TEST_ff_f (jn, 3, 0.75L, 0.848438342327410884392755236884386804e-2L); + TEST_ff_f (jn, 3, 1.0, 0.0195633539826684059189053216217515083L); + TEST_ff_f (jn, 3, 2.0, 0.128943249474402051098793332969239835L); + TEST_ff_f (jn, 3, 10.0, 0.0583793793051868123429354784103409563L); + + /* jn (10, x) */ + TEST_ff_f (jn, 10, nan_value, nan_value); + TEST_ff_f (jn, 10, plus_infty, 0); + + TEST_ff_f (jn, 10, -1.0, 0.263061512368745320699785368779050294e-9L); + TEST_ff_f (jn, 10, 0.0, 0.0); + TEST_ff_f (jn, 10, 0.125L, 0.250543369809369890173993791865771547e-18L); + TEST_ff_f (jn, 10, 0.75L, 0.149621713117596814698712483621682835e-10L); + TEST_ff_f (jn, 10, 1.0, 0.263061512368745320699785368779050294e-9L); + TEST_ff_f (jn, 10, 2.0, 0.251538628271673670963516093751820639e-6L); + TEST_ff_f (jn, 10, 10.0, 0.207486106633358857697278723518753428L); + + END (jn); +} + + +static void +ldexp_test (void) +{ + TEST_ff_f (ldexp, 0, 0, 0); + TEST_ff_f (ldexp, minus_zero, 0, minus_zero); + + TEST_ff_f (ldexp, plus_infty, 1, plus_infty); + TEST_ff_f (ldexp, minus_infty, 1, minus_infty); + TEST_ff_f (ldexp, nan_value, 1, nan_value); + + TEST_ff_f (ldexp, 0.8L, 4, 12.8L); + TEST_ff_f (ldexp, -0.854375L, 5, -27.34L); + + /* ldexp (x, 0) == x. */ + TEST_ff_f (ldexp, 1.0L, 0L, 1.0L); +} + + +static void +lgamma_test (void) +{ + errno = 0; + FUNC(lgamma) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (lgamma); + + TEST_f_f (lgamma, plus_infty, plus_infty); + TEST_f_f (lgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (lgamma, nan_value, nan_value); + + /* lgamma (x) == +inf plus divide by zero exception for integer x <= 0. */ + TEST_f_f (lgamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (lgamma, minus_infty, plus_infty); + + TEST_f_f1 (lgamma, 1, 0, 1); + + TEST_f_f1 (lgamma, 3, M_LN2l, 1); + + TEST_f_f1 (lgamma, 0.5, M_LOG_SQRT_PIl, 1); + TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1); + TEST_f_f1 (lgamma, 0.7L, 0.260867246531666514385732417016759578L, 1); + TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197028392998854470e-1L, 1); + + END (lgamma); +} + + +#if 0 +static void +lrint_test (void) +{ + /* XXX this test is incomplete. We need to have a way to specifiy + the rounding method and test the critical cases. So far, only + unproblematic numbers are tested. */ + + START (lrint); + + TEST_f_l (lrint, 0.0, 0); + TEST_f_l (lrint, minus_zero, 0); + TEST_f_l (lrint, 0.2L, 0); + TEST_f_l (lrint, -0.2L, 0); + + TEST_f_l (lrint, 1.4L, 1); + TEST_f_l (lrint, -1.4L, -1); + + TEST_f_l (lrint, 8388600.3L, 8388600); + TEST_f_l (lrint, -8388600.3L, -8388600); + + TEST_f_l (lrint, 1071930.0008, 1071930); +#ifndef TEST_FLOAT + TEST_f_l (lrint, 1073741824.01, 1073741824); +# if LONG_MAX > 281474976710656 + TEST_f_l (lrint, 281474976710656.025, 281474976710656); +# endif +#endif + + END (lrint); +} + + +static void +llrint_test (void) +{ + /* XXX this test is incomplete. We need to have a way to specifiy + the rounding method and test the critical cases. So far, only + unproblematic numbers are tested. */ + + START (llrint); + + TEST_f_L (llrint, 0.0, 0); + TEST_f_L (llrint, minus_zero, 0); + TEST_f_L (llrint, 0.2L, 0); + TEST_f_L (llrint, -0.2L, 0); + + TEST_f_L (llrint, 1.4L, 1); + TEST_f_L (llrint, -1.4L, -1); + + TEST_f_L (llrint, 8388600.3L, 8388600); + TEST_f_L (llrint, -8388600.3L, -8388600); + + TEST_f_l (llrint, 1071930.0008, 1071930); + + /* Test boundary conditions. */ + /* 0x1FFFFF */ + TEST_f_L (llrint, 2097151.0,2097151LL); + /* 0x800000 */ + TEST_f_L (llrint, 8388608.0, 8388608LL); + /* 0x1000000 */ + TEST_f_L (llrint, 16777216.0, 16777216LL); + /* 0x20000000000 */ + TEST_f_L (llrint, 2199023255552.0, 2199023255552LL); + /* 0x40000000000 */ + TEST_f_L (llrint, 4398046511104.0, 4398046511104LL); + /* 0x1000000000000 */ + TEST_f_L (llrint, 281474976710656.0, 281474976710656LL); + /* 0x10000000000000 */ + TEST_f_L (llrint, 4503599627370496.0, 4503599627370496LL); + /* 0x10000080000000 */ + TEST_f_L (llrint, 4503601774854144.0, 4503601774854144LL); + /* 0x20000000000000 */ + TEST_f_L (llrint, 9007199254740992.0, 9007199254740992LL); + /* 0x80000000000000 */ + TEST_f_L (llrint, 36028797018963968.0, 36028797018963968LL); + /* 0x100000000000000 */ + TEST_f_L (llrint, 72057594037927936.0, 72057594037927936LL); +#ifdef TEST_LDOUBLE + /* The input can only be represented in long double. */ + TEST_f_L (llrint, 4503599627370495.5L, 4503599627370496LL); + TEST_f_L (llrint, 4503599627370496.25L, 4503599627370496LL); + TEST_f_L (llrint, 4503599627370496.5L, 4503599627370496LL); + TEST_f_L (llrint, 4503599627370496.75L, 4503599627370497LL); + TEST_f_L (llrint, 4503599627370497.5L, 4503599627370498LL); + + TEST_f_L (llrint, -4503599627370495.5L, -4503599627370496LL); + TEST_f_L (llrint, -4503599627370496.25L, -4503599627370496LL); + TEST_f_L (llrint, -4503599627370496.5L, -4503599627370496LL); + TEST_f_L (llrint, -4503599627370496.75L, -4503599627370497LL); + TEST_f_L (llrint, -4503599627370497.5L, -4503599627370498LL); + + TEST_f_L (llrint, 9007199254740991.5L, 9007199254740992LL); + TEST_f_L (llrint, 9007199254740992.25L, 9007199254740992LL); + TEST_f_L (llrint, 9007199254740992.5L, 9007199254740992LL); + TEST_f_L (llrint, 9007199254740992.75L, 9007199254740993LL); + TEST_f_L (llrint, 9007199254740993.5L, 9007199254740994LL); + + TEST_f_L (llrint, -9007199254740991.5L, -9007199254740992LL); + TEST_f_L (llrint, -9007199254740992.25L, -9007199254740992LL); + TEST_f_L (llrint, -9007199254740992.5L, -9007199254740992LL); + TEST_f_L (llrint, -9007199254740992.75L, -9007199254740993LL); + TEST_f_L (llrint, -9007199254740993.5L, -9007199254740994LL); + + TEST_f_L (llrint, 72057594037927935.5L, 72057594037927936LL); + TEST_f_L (llrint, 72057594037927936.25L, 72057594037927936LL); + TEST_f_L (llrint, 72057594037927936.5L, 72057594037927936LL); + TEST_f_L (llrint, 72057594037927936.75L, 72057594037927937LL); + TEST_f_L (llrint, 72057594037927937.5L, 72057594037927938LL); + + TEST_f_L (llrint, -72057594037927935.5L, -72057594037927936LL); + TEST_f_L (llrint, -72057594037927936.25L, -72057594037927936LL); + TEST_f_L (llrint, -72057594037927936.5L, -72057594037927936LL); + TEST_f_L (llrint, -72057594037927936.75L, -72057594037927937LL); + TEST_f_L (llrint, -72057594037927937.5L, -72057594037927938LL); +#endif + + END (llrint); +} +#endif + + +static void +log_test (void) +{ + errno = 0; + FUNC(log) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + START (log); + + TEST_f_f (log, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log, 1, 0); + + TEST_f_f (log, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (log, plus_infty, plus_infty); + + TEST_f_f (log, M_El, 1); + TEST_f_f (log, 1.0 / M_El, -1); + TEST_f_f (log, 2, M_LN2l); + TEST_f_f (log, 10, M_LN10l); + TEST_f_f (log, 0.75L, -0.287682072451780927439219005993827432L); + + END (log); +} + + +static void +log10_test (void) +{ + errno = 0; + FUNC(log10) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log10); + + TEST_f_f (log10, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log10, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log10, 1, 0); + + /* log10 (x) == NaN plus invalid exception if x < 0. */ + TEST_f_f (log10, -1, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log10, plus_infty, plus_infty); + TEST_f_f (log10, nan_value, nan_value); + + TEST_f_f (log10, 0.1L, -1); + TEST_f_f (log10, 10.0, 1); + TEST_f_f (log10, 100.0, 2); + TEST_f_f (log10, 10000.0, 4); + TEST_f_f (log10, M_El, M_LOG10El); + TEST_f_f (log10, 0.75L, -0.124938736608299953132449886193870744L); + + END (log10); +} + + +static void +log1p_test (void) +{ + errno = 0; + FUNC(log1p) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log1p); + + TEST_f_f (log1p, 0, 0); + TEST_f_f (log1p, minus_zero, minus_zero); + + TEST_f_f (log1p, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log1p, -2, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log1p, plus_infty, plus_infty); + TEST_f_f (log1p, nan_value, nan_value); + + TEST_f_f (log1p, M_El - 1.0, 1); + + TEST_f_f (log1p, -0.25L, -0.287682072451780927439219005993827432L); + TEST_f_f (log1p, -0.875, -2.07944154167983592825169636437452970L); + + END (log1p); +} + + +#if 0 +static void +log2_test (void) +{ + errno = 0; + FUNC(log2) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (log2); + + TEST_f_f (log2, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (log2, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (log2, 1, 0); + + TEST_f_f (log2, -1, nan_value, INVALID_EXCEPTION); + + TEST_f_f (log2, plus_infty, plus_infty); + TEST_f_f (log2, nan_value, nan_value); + + TEST_f_f (log2, M_El, M_LOG2El); + TEST_f_f (log2, 2.0, 1); + TEST_f_f (log2, 16.0, 4); + TEST_f_f (log2, 256.0, 8); + TEST_f_f (log2, 0.75L, -.415037499278843818546261056052183492L); + + END (log2); +} +#endif + + +static void +logb_test (void) +{ + START (logb); + + TEST_f_f (logb, plus_infty, plus_infty); + TEST_f_f (logb, minus_infty, plus_infty); + + TEST_f_f (logb, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_f_f (logb, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (logb, nan_value, nan_value); + + TEST_f_f (logb, 1, 0); + TEST_f_f (logb, M_El, 1); + TEST_f_f (logb, 1024, 10); + TEST_f_f (logb, -2000, 10); + + END (logb); +} + + +#if 0 +static void +lround_test (void) +{ + START (lround); + + TEST_f_l (lround, 0, 0); + TEST_f_l (lround, minus_zero, 0); + TEST_f_l (lround, 0.2L, 0.0); + TEST_f_l (lround, -0.2L, 0); + TEST_f_l (lround, 0.5, 1); + TEST_f_l (lround, -0.5, -1); + TEST_f_l (lround, 0.8L, 1); + TEST_f_l (lround, -0.8L, -1); + TEST_f_l (lround, 1.5, 2); + TEST_f_l (lround, -1.5, -2); + TEST_f_l (lround, 22514.5, 22515); + TEST_f_l (lround, -22514.5, -22515); + TEST_f_l (lround, 1071930.0008, 1071930); +#ifndef TEST_FLOAT + TEST_f_l (lround, 1073741824.01, 1073741824); +# if LONG_MAX > 281474976710656 + TEST_f_l (lround, 281474976710656.025, 281474976710656); +# endif + TEST_f_l (lround, 2097152.5, 2097153); + TEST_f_l (lround, -2097152.5, -2097153); +#endif + END (lround); +} + + +static void +llround_test (void) +{ + START (llround); + + TEST_f_L (llround, 0, 0); + TEST_f_L (llround, minus_zero, 0); + TEST_f_L (llround, 0.2L, 0.0); + TEST_f_L (llround, -0.2L, 0); + TEST_f_L (llround, 0.5, 1); + TEST_f_L (llround, -0.5, -1); + TEST_f_L (llround, 0.8L, 1); + TEST_f_L (llround, -0.8L, -1); + TEST_f_L (llround, 1.5, 2); + TEST_f_L (llround, -1.5, -2); + TEST_f_L (llround, 22514.5, 22515); + TEST_f_L (llround, -22514.5, -22515); + TEST_f_l (llround, 1071930.0008, 1071930); +#ifndef TEST_FLOAT + TEST_f_L (llround, 2097152.5, 2097153); + TEST_f_L (llround, -2097152.5, -2097153); + TEST_f_L (llround, 34359738368.5, 34359738369ll); + TEST_f_L (llround, -34359738368.5, -34359738369ll); +#endif + + /* Test boundary conditions. */ + /* 0x1FFFFF */ + TEST_f_L (llround, 2097151.0, 2097151LL); + /* 0x800000 */ + TEST_f_L (llround, 8388608.0, 8388608LL); + /* 0x1000000 */ + TEST_f_L (llround, 16777216.0, 16777216LL); + /* 0x20000000000 */ + TEST_f_L (llround, 2199023255552.0, 2199023255552LL); + /* 0x40000000000 */ + TEST_f_L (llround, 4398046511104.0, 4398046511104LL); + /* 0x1000000000000 */ + TEST_f_L (llround, 281474976710656.0, 281474976710656LL); + /* 0x10000000000000 */ + TEST_f_L (llround, 4503599627370496.0, 4503599627370496LL); + /* 0x10000080000000 */ + TEST_f_L (llround, 4503601774854144.0, 4503601774854144LL); + /* 0x20000000000000 */ + TEST_f_L (llround, 9007199254740992.0, 9007199254740992LL); + /* 0x80000000000000 */ + TEST_f_L (llround, 36028797018963968.0, 36028797018963968LL); + /* 0x100000000000000 */ + TEST_f_L (llround, 72057594037927936.0, 72057594037927936LL); + +#ifndef TEST_FLOAT + /* 0x100000000 */ + TEST_f_L (llround, 4294967295.5, 4294967296LL); + /* 0x200000000 */ + TEST_f_L (llround, 8589934591.5, 8589934592LL); +#endif + +#ifdef TEST_LDOUBLE + /* The input can only be represented in long double. */ + TEST_f_L (llround, 4503599627370495.5L, 4503599627370496LL); + TEST_f_L (llround, 4503599627370496.25L, 4503599627370496LL); + TEST_f_L (llround, 4503599627370496.5L, 4503599627370497LL); + TEST_f_L (llround, 4503599627370496.75L, 4503599627370497LL); + TEST_f_L (llround, 4503599627370497.5L, 4503599627370498LL); + + TEST_f_L (llround, -4503599627370495.5L, -4503599627370496LL); + TEST_f_L (llround, -4503599627370496.25L, -4503599627370496LL); + TEST_f_L (llround, -4503599627370496.5L, -4503599627370497LL); + TEST_f_L (llround, -4503599627370496.75L, -4503599627370497LL); + TEST_f_L (llround, -4503599627370497.5L, -4503599627370498LL); + + TEST_f_L (llround, 9007199254740991.5L, 9007199254740992LL); + TEST_f_L (llround, 9007199254740992.25L, 9007199254740992LL); + TEST_f_L (llround, 9007199254740992.5L, 9007199254740993LL); + TEST_f_L (llround, 9007199254740992.75L, 9007199254740993LL); + TEST_f_L (llround, 9007199254740993.5L, 9007199254740994LL); + + TEST_f_L (llround, -9007199254740991.5L, -9007199254740992LL); + TEST_f_L (llround, -9007199254740992.25L, -9007199254740992LL); + TEST_f_L (llround, -9007199254740992.5L, -9007199254740993LL); + TEST_f_L (llround, -9007199254740992.75L, -9007199254740993LL); + TEST_f_L (llround, -9007199254740993.5L, -9007199254740994LL); + + TEST_f_L (llround, 72057594037927935.5L, 72057594037927936LL); + TEST_f_L (llround, 72057594037927936.25L, 72057594037927936LL); + TEST_f_L (llround, 72057594037927936.5L, 72057594037927937LL); + TEST_f_L (llround, 72057594037927936.75L, 72057594037927937LL); + TEST_f_L (llround, 72057594037927937.5L, 72057594037927938LL); + + TEST_f_L (llround, -72057594037927935.5L, -72057594037927936LL); + TEST_f_L (llround, -72057594037927936.25L, -72057594037927936LL); + TEST_f_L (llround, -72057594037927936.5L, -72057594037927937LL); + TEST_f_L (llround, -72057594037927936.75L, -72057594037927937LL); + TEST_f_L (llround, -72057594037927937.5L, -72057594037927938LL); + + TEST_f_L (llround, 9223372036854775806.25L, 9223372036854775806LL); + TEST_f_L (llround, -9223372036854775806.25L, -9223372036854775806LL); + TEST_f_L (llround, 9223372036854775806.5L, 9223372036854775807LL); + TEST_f_L (llround, -9223372036854775806.5L, -9223372036854775807LL); + TEST_f_L (llround, 9223372036854775807.0L, 9223372036854775807LL); + TEST_f_L (llround, -9223372036854775807.0L, -9223372036854775807LL); +#endif + + END (llround); +} +#endif + +static void +modf_test (void) +{ + FLOAT x; + + START (modf); + + TEST_fF_f1 (modf, plus_infty, 0, plus_infty); + TEST_fF_f1 (modf, minus_infty, minus_zero, minus_infty); + TEST_fF_f1 (modf, nan_value, nan_value, nan_value); + TEST_fF_f1 (modf, 0, 0, 0); + TEST_fF_f1 (modf, 1.5, 0.5, 1); + TEST_fF_f1 (modf, 2.5, 0.5, 2); + TEST_fF_f1 (modf, -2.5, -0.5, -2); + TEST_fF_f1 (modf, 20, 0, 20); + TEST_fF_f1 (modf, 21, 0, 21); + TEST_fF_f1 (modf, 89.5, 0.5, 89); + + END (modf); +} + + +#if 0 +static void +nearbyint_test (void) +{ + START (nearbyint); + + TEST_f_f (nearbyint, 0.0, 0.0); + TEST_f_f (nearbyint, minus_zero, minus_zero); + TEST_f_f (nearbyint, plus_infty, plus_infty); + TEST_f_f (nearbyint, minus_infty, minus_infty); + TEST_f_f (nearbyint, nan_value, nan_value); + + /* Default rounding mode is round to nearest. */ + TEST_f_f (nearbyint, 0.5, 0.0); + TEST_f_f (nearbyint, 1.5, 2.0); + TEST_f_f (nearbyint, -0.5, minus_zero); + TEST_f_f (nearbyint, -1.5, -2.0); + + END (nearbyint); +} + +static void +nextafter_test (void) +{ + + START (nextafter); + + TEST_ff_f (nextafter, 0, 0, 0); + TEST_ff_f (nextafter, minus_zero, 0, 0); + TEST_ff_f (nextafter, 0, minus_zero, minus_zero); + TEST_ff_f (nextafter, minus_zero, minus_zero, minus_zero); + + TEST_ff_f (nextafter, 9, 9, 9); + TEST_ff_f (nextafter, -9, -9, -9); + TEST_ff_f (nextafter, plus_infty, plus_infty, plus_infty); + TEST_ff_f (nextafter, minus_infty, minus_infty, minus_infty); + + TEST_ff_f (nextafter, nan_value, 1.1L, nan_value); + TEST_ff_f (nextafter, 1.1L, nan_value, nan_value); + TEST_ff_f (nextafter, nan_value, nan_value, nan_value); + + FLOAT fltmax = CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX, + LDBL_MAX, DBL_MAX, FLT_MAX); + TEST_ff_f (nextafter, fltmax, plus_infty, plus_infty); + TEST_ff_f (nextafter, -fltmax, minus_infty, minus_infty); + +#ifdef TEST_LDOUBLE + // XXX Enable once gcc is fixed. + //TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L); +#endif + + /* XXX We need the hexadecimal FP number representation here for further + tests. */ + + END (nextafter); +} + + +static void +nexttoward_test (void) +{ + START (nexttoward); + TEST_ff_f (nexttoward, 0, 0, 0); + TEST_ff_f (nexttoward, minus_zero, 0, 0); + TEST_ff_f (nexttoward, 0, minus_zero, minus_zero); + TEST_ff_f (nexttoward, minus_zero, minus_zero, minus_zero); + + TEST_ff_f (nexttoward, 9, 9, 9); + TEST_ff_f (nexttoward, -9, -9, -9); + TEST_ff_f (nexttoward, plus_infty, plus_infty, plus_infty); + TEST_ff_f (nexttoward, minus_infty, minus_infty, minus_infty); + + TEST_ff_f (nexttoward, nan_value, 1.1L, nan_value); + TEST_ff_f (nexttoward, 1.1L, nan_value, nan_value); + TEST_ff_f (nexttoward, nan_value, nan_value, nan_value); + + /* XXX We need the hexadecimal FP number representation here for further + tests. */ + + END (nexttoward); +} +#endif + + +static void +pow_test (void) +{ + + errno = 0; + FUNC(pow) (0, 0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (pow); + + TEST_ff_f (pow, 0, 0, 1); + TEST_ff_f (pow, 0, minus_zero, 1); + TEST_ff_f (pow, minus_zero, 0, 1); + TEST_ff_f (pow, minus_zero, minus_zero, 1); + + TEST_ff_f (pow, 10, 0, 1); + TEST_ff_f (pow, 10, minus_zero, 1); + TEST_ff_f (pow, -10, 0, 1); + TEST_ff_f (pow, -10, minus_zero, 1); + + TEST_ff_f (pow, nan_value, 0, 1); + TEST_ff_f (pow, nan_value, minus_zero, 1); + + +#ifndef TEST_INLINE + TEST_ff_f (pow, 1.1L, plus_infty, plus_infty); + TEST_ff_f (pow, plus_infty, plus_infty, plus_infty); + TEST_ff_f (pow, -1.1L, plus_infty, plus_infty); + TEST_ff_f (pow, minus_infty, plus_infty, plus_infty); + + TEST_ff_f (pow, 0.9L, plus_infty, 0); + TEST_ff_f (pow, 1e-7L, plus_infty, 0); + TEST_ff_f (pow, -0.9L, plus_infty, 0); + TEST_ff_f (pow, -1e-7L, plus_infty, 0); + + TEST_ff_f (pow, 1.1L, minus_infty, 0); + TEST_ff_f (pow, plus_infty, minus_infty, 0); + TEST_ff_f (pow, -1.1L, minus_infty, 0); + TEST_ff_f (pow, minus_infty, minus_infty, 0); + + TEST_ff_f (pow, 0.9L, minus_infty, plus_infty); + TEST_ff_f (pow, 1e-7L, minus_infty, plus_infty); + TEST_ff_f (pow, -0.9L, minus_infty, plus_infty); + TEST_ff_f (pow, -1e-7L, minus_infty, plus_infty); + + TEST_ff_f (pow, plus_infty, 1e-7L, plus_infty); + TEST_ff_f (pow, plus_infty, 1, plus_infty); + TEST_ff_f (pow, plus_infty, 1e7L, plus_infty); + + TEST_ff_f (pow, plus_infty, -1e-7L, 0); + TEST_ff_f (pow, plus_infty, -1, 0); + TEST_ff_f (pow, plus_infty, -1e7L, 0); + + TEST_ff_f (pow, minus_infty, 1, minus_infty); + TEST_ff_f (pow, minus_infty, 11, minus_infty); + TEST_ff_f (pow, minus_infty, 1001, minus_infty); + + TEST_ff_f (pow, minus_infty, 2, plus_infty); + TEST_ff_f (pow, minus_infty, 12, plus_infty); + TEST_ff_f (pow, minus_infty, 1002, plus_infty); + TEST_ff_f (pow, minus_infty, 0.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 1.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 11.1L, plus_infty); + TEST_ff_f (pow, minus_infty, 1001.1L, plus_infty); + + TEST_ff_f (pow, minus_infty, -1, minus_zero); + TEST_ff_f (pow, minus_infty, -11, minus_zero); + TEST_ff_f (pow, minus_infty, -1001, minus_zero); + + TEST_ff_f (pow, minus_infty, -2, 0); + TEST_ff_f (pow, minus_infty, -12, 0); + TEST_ff_f (pow, minus_infty, -1002, 0); + TEST_ff_f (pow, minus_infty, -0.1L, 0); + TEST_ff_f (pow, minus_infty, -1.1L, 0); + TEST_ff_f (pow, minus_infty, -11.1L, 0); + TEST_ff_f (pow, minus_infty, -1001.1L, 0); +#endif + + TEST_ff_f (pow, nan_value, nan_value, nan_value); + TEST_ff_f (pow, 0, nan_value, nan_value); + TEST_ff_f (pow, 1, nan_value, 1); + TEST_ff_f (pow, -1, nan_value, nan_value); + TEST_ff_f (pow, nan_value, 1, nan_value); + TEST_ff_f (pow, nan_value, -1, nan_value); + + /* pow (x, NaN) == NaN. */ + TEST_ff_f (pow, 3.0, nan_value, nan_value); + + TEST_ff_f (pow, 1, plus_infty, 1); + TEST_ff_f (pow, -1, plus_infty, 1); + TEST_ff_f (pow, 1, minus_infty, 1); + TEST_ff_f (pow, -1, minus_infty, 1); + TEST_ff_f (pow, 1, 1, 1); + TEST_ff_f (pow, 1, -1, 1); + TEST_ff_f (pow, 1, 1.25, 1); + TEST_ff_f (pow, 1, -1.25, 1); + TEST_ff_f (pow, 1, 0x1p62L, 1); + TEST_ff_f (pow, 1, 0x1p63L, 1); + TEST_ff_f (pow, 1, 0x1p64L, 1); + TEST_ff_f (pow, 1, 0x1p72L, 1); + + /* pow (x, +-0) == 1. */ + TEST_ff_f (pow, plus_infty, 0, 1); + TEST_ff_f (pow, plus_infty, minus_zero, 1); + TEST_ff_f (pow, minus_infty, 0, 1); + TEST_ff_f (pow, minus_infty, minus_zero, 1); + TEST_ff_f (pow, 32.75L, 0, 1); + TEST_ff_f (pow, 32.75L, minus_zero, 1); + TEST_ff_f (pow, -32.75L, 0, 1); + TEST_ff_f (pow, -32.75L, minus_zero, 1); + TEST_ff_f (pow, 0x1p72L, 0, 1); + TEST_ff_f (pow, 0x1p72L, minus_zero, 1); + TEST_ff_f (pow, 0x1p-72L, 0, 1); + TEST_ff_f (pow, 0x1p-72L, minus_zero, 1); + + TEST_ff_f (pow, -0.1L, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -0.1L, -1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -10.1L, 1.1L, nan_value, INVALID_EXCEPTION); + TEST_ff_f (pow, -10.1L, -1.1L, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (pow, 0, -1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, 0, -11, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -11, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_ff_f (pow, 0, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, 0, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_ff_f (pow, minus_zero, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + + TEST_ff_f (pow, 0x1p72L, 0x1p72L, plus_infty); + TEST_ff_f (pow, 10, -0x1p72L, 0); + TEST_ff_f (pow, max_value, max_value, plus_infty); + TEST_ff_f (pow, 10, -max_value, 0); + + TEST_ff_f (pow, 0, 1, 0); + TEST_ff_f (pow, 0, 11, 0); + + TEST_ff_f (pow, minus_zero, 1, minus_zero); + TEST_ff_f (pow, minus_zero, 11, minus_zero); + + + TEST_ff_f (pow, 0, 2, 0); + TEST_ff_f (pow, 0, 11.1L, 0); + + + TEST_ff_f (pow, minus_zero, 2, 0); + TEST_ff_f (pow, minus_zero, 11.1L, 0); + TEST_ff_f (pow, 0, plus_infty, 0); + TEST_ff_f (pow, minus_zero, plus_infty, 0); + +#ifndef TEST_INLINE + /* pow (x, +inf) == +inf for |x| > 1. */ + TEST_ff_f (pow, 1.5, plus_infty, plus_infty); + + /* pow (x, +inf) == +0 for |x| < 1. */ + TEST_ff_f (pow, 0.5, plus_infty, 0.0); + + /* pow (x, -inf) == +0 for |x| > 1. */ + TEST_ff_f (pow, 1.5, minus_infty, 0.0); + + /* pow (x, -inf) == +inf for |x| < 1. */ + TEST_ff_f (pow, 0.5, minus_infty, plus_infty); +#endif + + /* pow (+inf, y) == +inf for y > 0. */ + TEST_ff_f (pow, plus_infty, 2, plus_infty); + + /* pow (+inf, y) == +0 for y < 0. */ + TEST_ff_f (pow, plus_infty, -1, 0.0); + + /* pow (-inf, y) == -inf for y an odd integer > 0. */ + TEST_ff_f (pow, minus_infty, 27, minus_infty); + + /* pow (-inf, y) == +inf for y > 0 and not an odd integer. */ + TEST_ff_f (pow, minus_infty, 28, plus_infty); + + /* pow (-inf, y) == -0 for y an odd integer < 0. */ + TEST_ff_f (pow, minus_infty, -3, minus_zero); + /* pow (-inf, y) == +0 for y < 0 and not an odd integer. */ + TEST_ff_f (pow, minus_infty, -2.0, 0.0); + + /* pow (+0, y) == +0 for y an odd integer > 0. */ + TEST_ff_f (pow, 0.0, 27, 0.0); + + /* pow (-0, y) == -0 for y an odd integer > 0. */ + TEST_ff_f (pow, minus_zero, 27, minus_zero); + + /* pow (+0, y) == +0 for y > 0 and not an odd integer. */ + TEST_ff_f (pow, 0.0, 4, 0.0); + + /* pow (-0, y) == +0 for y > 0 and not an odd integer. */ + TEST_ff_f (pow, minus_zero, 4, 0.0); + + TEST_ff_f (pow, 16, 0.25L, 2); + TEST_ff_f (pow, 0x1p64L, 0.125L, 256); + TEST_ff_f (pow, 2, 4, 16); + TEST_ff_f (pow, 256, 8, 0x1p64L); + + TEST_ff_f (pow, 0.75L, 1.25L, 0.697953644326574699205914060237425566L); + +#if defined TEST_DOUBLE || defined TEST_LDOUBLE + TEST_ff_f (pow, -7.49321e+133, -9.80818e+16, 0); +#endif + + END (pow); +} + +static void +remainder_test (void) +{ + errno = 0; + FUNC(remainder) (1.625, 1.0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (remainder); + + TEST_ff_f (remainder, 1, 0, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, 1, minus_zero, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, plus_infty, 1, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, minus_infty, 1, nan_value, INVALID_EXCEPTION); + TEST_ff_f (remainder, nan_value, nan_value, nan_value); + + TEST_ff_f (remainder, 1.625, 1.0, -0.375); + TEST_ff_f (remainder, -1.625, 1.0, 0.375); + TEST_ff_f (remainder, 1.625, -1.0, -0.375); + TEST_ff_f (remainder, -1.625, -1.0, 0.375); + TEST_ff_f (remainder, 5.0, 2.0, 1.0); + TEST_ff_f (remainder, 3.0, 2.0, -1.0); + + END (remainder); +} + +#if 0 +static void +remquo_test (void) +{ + /* x is needed. */ + int x; + + errno = 0; + FUNC(remquo) (1.625, 1.0, &x); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (remquo); + + TEST_ffI_f1 (remquo, 1, 0, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, 1, minus_zero, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, plus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, minus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION); + TEST_ffI_f1 (remquo, nan_value, nan_value, nan_value, IGNORE); + + TEST_ffI_f1 (remquo, 1.625, 1.0, -0.375, 2); + TEST_ffI_f1 (remquo, -1.625, 1.0, 0.375, -2); + TEST_ffI_f1 (remquo, 1.625, -1.0, -0.375, -2); + TEST_ffI_f1 (remquo, -1.625, -1.0, 0.375, 2); + + TEST_ffI_f1 (remquo, 5, 2, 1, 2); + TEST_ffI_f1 (remquo, 3, 2, -1, 2); + + END (remquo); +} +#endif + +static void +rint_test (void) +{ + START (rint); + + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, plus_infty, plus_infty); + TEST_f_f (rint, minus_infty, minus_infty); + + /* Default rounding mode is round to even. */ + TEST_f_f (rint, 0.5, 0.0); + TEST_f_f (rint, 1.5, 2.0); + TEST_f_f (rint, 2.5, 2.0); + TEST_f_f (rint, 3.5, 4.0); + TEST_f_f (rint, 4.5, 4.0); + TEST_f_f (rint, -0.5, -0.0); + TEST_f_f (rint, -1.5, -2.0); + TEST_f_f (rint, -2.5, -2.0); + TEST_f_f (rint, -3.5, -4.0); + TEST_f_f (rint, -4.5, -4.0); +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (rint, 4503599627370495.5L, 4503599627370496.0L); + TEST_f_f (rint, 4503599627370496.25L, 4503599627370496.0L); + TEST_f_f (rint, 4503599627370496.5L, 4503599627370496.0L); + TEST_f_f (rint, 4503599627370496.75L, 4503599627370497.0L); + TEST_f_f (rint, 4503599627370497.5L, 4503599627370498.0L); + + TEST_f_f (rint, -4503599627370495.5L, -4503599627370496.0L); + TEST_f_f (rint, -4503599627370496.25L, -4503599627370496.0L); + TEST_f_f (rint, -4503599627370496.5L, -4503599627370496.0L); + TEST_f_f (rint, -4503599627370496.75L, -4503599627370497.0L); + TEST_f_f (rint, -4503599627370497.5L, -4503599627370498.0L); + + TEST_f_f (rint, 9007199254740991.5L, 9007199254740992.0L); + TEST_f_f (rint, 9007199254740992.25L, 9007199254740992.0L); + TEST_f_f (rint, 9007199254740992.5L, 9007199254740992.0L); + TEST_f_f (rint, 9007199254740992.75L, 9007199254740993.0L); + TEST_f_f (rint, 9007199254740993.5L, 9007199254740994.0L); + + TEST_f_f (rint, -9007199254740991.5L, -9007199254740992.0L); + TEST_f_f (rint, -9007199254740992.25L, -9007199254740992.0L); + TEST_f_f (rint, -9007199254740992.5L, -9007199254740992.0L); + TEST_f_f (rint, -9007199254740992.75L, -9007199254740993.0L); + TEST_f_f (rint, -9007199254740993.5L, -9007199254740994.0L); + + TEST_f_f (rint, 72057594037927935.5L, 72057594037927936.0L); + TEST_f_f (rint, 72057594037927936.25L, 72057594037927936.0L); + TEST_f_f (rint, 72057594037927936.5L, 72057594037927936.0L); + TEST_f_f (rint, 72057594037927936.75L, 72057594037927937.0L); + TEST_f_f (rint, 72057594037927937.5L, 72057594037927938.0L); + + TEST_f_f (rint, -72057594037927935.5L, -72057594037927936.0L); + TEST_f_f (rint, -72057594037927936.25L, -72057594037927936.0L); + TEST_f_f (rint, -72057594037927936.5L, -72057594037927936.0L); + TEST_f_f (rint, -72057594037927936.75L, -72057594037927937.0L); + TEST_f_f (rint, -72057594037927937.5L, -72057594037927938.0L); + + TEST_f_f (rint, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L); + TEST_f_f (rint, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L); + TEST_f_f (rint, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L); + TEST_f_f (rint, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L); + TEST_f_f (rint, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L); +#endif + + END (rint); +} + +#if 0 +static void +rint_test_tonearest (void) +{ + int save_round_mode; + START (rint_tonearest); + + save_round_mode = fegetround(); + + if (!fesetround (FE_TONEAREST)) + { + TEST_f_f (rint, 2.0, 2.0); + TEST_f_f (rint, 1.5, 2.0); + TEST_f_f (rint, 1.0, 1.0); + TEST_f_f (rint, 0.5, 0.0); + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, -0.5, -0.0); + TEST_f_f (rint, -1.0, -1.0); + TEST_f_f (rint, -1.5, -2.0); + TEST_f_f (rint, -2.0, -2.0); + } + + fesetround(save_round_mode); + + END (rint_tonearest); +} + +static void +rint_test_towardzero (void) +{ + int save_round_mode; + START (rint_towardzero); + + save_round_mode = fegetround(); + + if (!fesetround (FE_TOWARDZERO)) + { + TEST_f_f (rint, 2.0, 2.0); + TEST_f_f (rint, 1.5, 1.0); + TEST_f_f (rint, 1.0, 1.0); + TEST_f_f (rint, 0.5, 0.0); + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, -0.5, -0.0); + TEST_f_f (rint, -1.0, -1.0); + TEST_f_f (rint, -1.5, -1.0); + TEST_f_f (rint, -2.0, -2.0); + } + + fesetround(save_round_mode); + + END (rint_towardzero); +} + +static void +rint_test_downward (void) +{ + int save_round_mode; + START (rint_downward); + + save_round_mode = fegetround(); + + if (!fesetround (FE_DOWNWARD)) + { + TEST_f_f (rint, 2.0, 2.0); + TEST_f_f (rint, 1.5, 1.0); + TEST_f_f (rint, 1.0, 1.0); + TEST_f_f (rint, 0.5, 0.0); + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, -0.5, -1.0); + TEST_f_f (rint, -1.0, -1.0); + TEST_f_f (rint, -1.5, -2.0); + TEST_f_f (rint, -2.0, -2.0); + } + + fesetround(save_round_mode); + + END (rint_downward); +} + +static void +rint_test_upward (void) +{ + int save_round_mode; + START (rint_upward); + + save_round_mode = fegetround(); + + if (!fesetround (FE_UPWARD)) + { + TEST_f_f (rint, 2.0, 2.0); + TEST_f_f (rint, 1.5, 2.0); + TEST_f_f (rint, 1.0, 1.0); + TEST_f_f (rint, 0.5, 1.0); + TEST_f_f (rint, 0.0, 0.0); + TEST_f_f (rint, minus_zero, minus_zero); + TEST_f_f (rint, -0.5, -0.0); + TEST_f_f (rint, -1.0, -1.0); + TEST_f_f (rint, -1.5, -1.0); + TEST_f_f (rint, -2.0, -2.0); + } + + fesetround(save_round_mode); + + END (rint_upward); +} + +static void +round_test (void) +{ + START (round); + + TEST_f_f (round, 0, 0); + TEST_f_f (round, minus_zero, minus_zero); + TEST_f_f (round, 0.2L, 0.0); + TEST_f_f (round, -0.2L, minus_zero); + TEST_f_f (round, 0.5, 1.0); + TEST_f_f (round, -0.5, -1.0); + TEST_f_f (round, 0.8L, 1.0); + TEST_f_f (round, -0.8L, -1.0); + TEST_f_f (round, 1.5, 2.0); + TEST_f_f (round, -1.5, -2.0); + TEST_f_f (round, 2097152.5, 2097153); + TEST_f_f (round, -2097152.5, -2097153); + +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (round, 4503599627370495.5L, 4503599627370496.0L); + TEST_f_f (round, 4503599627370496.25L, 4503599627370496.0L); + TEST_f_f (round, 4503599627370496.5L, 4503599627370497.0L); + TEST_f_f (round, 4503599627370496.75L, 4503599627370497.0L); + TEST_f_f (round, 4503599627370497.5L, 4503599627370498.0L); + + TEST_f_f (round, -4503599627370495.5L, -4503599627370496.0L); + TEST_f_f (round, -4503599627370496.25L, -4503599627370496.0L); + TEST_f_f (round, -4503599627370496.5L, -4503599627370497.0L); + TEST_f_f (round, -4503599627370496.75L, -4503599627370497.0L); + TEST_f_f (round, -4503599627370497.5L, -4503599627370498.0L); + + TEST_f_f (round, 9007199254740991.5L, 9007199254740992.0L); + TEST_f_f (round, 9007199254740992.25L, 9007199254740992.0L); + TEST_f_f (round, 9007199254740992.5L, 9007199254740993.0L); + TEST_f_f (round, 9007199254740992.75L, 9007199254740993.0L); + TEST_f_f (round, 9007199254740993.5L, 9007199254740994.0L); + + TEST_f_f (round, -9007199254740991.5L, -9007199254740992.0L); + TEST_f_f (round, -9007199254740992.25L, -9007199254740992.0L); + TEST_f_f (round, -9007199254740992.5L, -9007199254740993.0L); + TEST_f_f (round, -9007199254740992.75L, -9007199254740993.0L); + TEST_f_f (round, -9007199254740993.5L, -9007199254740994.0L); + + TEST_f_f (round, 72057594037927935.5L, 72057594037927936.0L); + TEST_f_f (round, 72057594037927936.25L, 72057594037927936.0L); + TEST_f_f (round, 72057594037927936.5L, 72057594037927937.0L); + TEST_f_f (round, 72057594037927936.75L, 72057594037927937.0L); + TEST_f_f (round, 72057594037927937.5L, 72057594037927938.0L); + + TEST_f_f (round, -72057594037927935.5L, -72057594037927936.0L); + TEST_f_f (round, -72057594037927936.25L, -72057594037927936.0L); + TEST_f_f (round, -72057594037927936.5L, -72057594037927937.0L); + TEST_f_f (round, -72057594037927936.75L, -72057594037927937.0L); + TEST_f_f (round, -72057594037927937.5L, -72057594037927938.0L); + + TEST_f_f (round, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L); + TEST_f_f (round, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L); + TEST_f_f (round, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L); + TEST_f_f (round, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L); + TEST_f_f (round, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L); +#endif + + END (round); +} +#endif + + +static void +scalb_test (void) +{ + + START (scalb); + + TEST_ff_f (scalb, 2.0, 0.5, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, 3.0, -2.5, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, 0, nan_value, nan_value); + TEST_ff_f (scalb, 1, nan_value, nan_value); + + TEST_ff_f (scalb, 1, 0, 1); + TEST_ff_f (scalb, -1, 0, -1); + + TEST_ff_f (scalb, 0, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, minus_zero, plus_infty, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, 0, 2, 0); + TEST_ff_f (scalb, minus_zero, -4, minus_zero); + TEST_ff_f (scalb, 0, 0, 0); + TEST_ff_f (scalb, minus_zero, 0, minus_zero); + TEST_ff_f (scalb, 0, -1, 0); + TEST_ff_f (scalb, minus_zero, -10, minus_zero); + TEST_ff_f (scalb, 0, minus_infty, 0); + TEST_ff_f (scalb, minus_zero, minus_infty, minus_zero); + + TEST_ff_f (scalb, plus_infty, -1, plus_infty); + TEST_ff_f (scalb, minus_infty, -10, minus_infty); + TEST_ff_f (scalb, plus_infty, 0, plus_infty); + TEST_ff_f (scalb, minus_infty, 0, minus_infty); + TEST_ff_f (scalb, plus_infty, 2, plus_infty); + TEST_ff_f (scalb, minus_infty, 100, minus_infty); + + TEST_ff_f (scalb, 0.1L, minus_infty, 0.0); + TEST_ff_f (scalb, -0.1L, minus_infty, minus_zero); + + TEST_ff_f (scalb, 1, plus_infty, plus_infty); + TEST_ff_f (scalb, -1, plus_infty, minus_infty); + TEST_ff_f (scalb, plus_infty, plus_infty, plus_infty); + TEST_ff_f (scalb, minus_infty, plus_infty, minus_infty); + + TEST_ff_f (scalb, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_ff_f (scalb, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION); + + TEST_ff_f (scalb, nan_value, 1, nan_value); + TEST_ff_f (scalb, 1, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, 0, nan_value); + TEST_ff_f (scalb, 0, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, plus_infty, nan_value); + TEST_ff_f (scalb, plus_infty, nan_value, nan_value); + TEST_ff_f (scalb, nan_value, nan_value, nan_value); + + TEST_ff_f (scalb, 0.8L, 4, 12.8L); + TEST_ff_f (scalb, -0.854375L, 5, -27.34L); + + END (scalb); +} + + +static void +scalbn_test (void) +{ + + START (scalbn); + + TEST_fi_f (scalbn, 0, 0, 0); + TEST_fi_f (scalbn, minus_zero, 0, minus_zero); + + TEST_fi_f (scalbn, plus_infty, 1, plus_infty); + TEST_fi_f (scalbn, minus_infty, 1, minus_infty); + TEST_fi_f (scalbn, nan_value, 1, nan_value); + + TEST_fi_f (scalbn, 0.8L, 4, 12.8L); + TEST_fi_f (scalbn, -0.854375L, 5, -27.34L); + + TEST_fi_f (scalbn, 1, 0L, 1); + + END (scalbn); +} + + +#if 0 +static void +scalbln_test (void) +{ + + START (scalbln); + + TEST_fl_f (scalbln, 0, 0, 0); + TEST_fl_f (scalbln, minus_zero, 0, minus_zero); + + TEST_fl_f (scalbln, plus_infty, 1, plus_infty); + TEST_fl_f (scalbln, minus_infty, 1, minus_infty); + TEST_fl_f (scalbln, nan_value, 1, nan_value); + + TEST_fl_f (scalbln, 0.8L, 4, 12.8L); + TEST_fl_f (scalbln, -0.854375L, 5, -27.34L); + + TEST_fl_f (scalbln, 1, 0L, 1); + + END (scalbn); +} +#endif + + +static void +signbit_test (void) +{ + + START (signbit); + + TEST_f_b (signbit, 0, 0); + TEST_f_b (signbit, minus_zero, 1); + TEST_f_b (signbit, plus_infty, 0); + TEST_f_b (signbit, minus_infty, 1); + + /* signbit (x) != 0 for x < 0. */ + TEST_f_b (signbit, -1, 1); + /* signbit (x) == 0 for x >= 0. */ + TEST_f_b (signbit, 1, 0); + + END (signbit); +} + + +static void +sin_test (void) +{ + errno = 0; + FUNC(sin) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sin); + + TEST_f_f (sin, 0, 0); + TEST_f_f (sin, minus_zero, minus_zero); + TEST_f_f (sin, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sin, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sin, nan_value, nan_value); + + TEST_f_f (sin, M_PI_6l, 0.5); + TEST_f_f (sin, -M_PI_6l, -0.5); + TEST_f_f (sin, M_PI_2l, 1); + TEST_f_f (sin, -M_PI_2l, -1); + TEST_f_f (sin, 0.75L, 0.681638760023334166733241952779893935L); + +#ifdef TEST_DOUBLE + TEST_f_f (sin, 0.80190127184058835, 0.71867942238767868); +#endif + + END (sin); + +} + + +#if 0 +static void +sincos_test (void) +{ + FLOAT sin_res, cos_res; + + errno = 0; + FUNC(sincos) (0, &sin_res, &cos_res); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sincos); + + /* sincos is treated differently because it returns void. */ + TEST_extra (sincos, 0, 0, 1); + + TEST_extra (sincos, minus_zero, minus_zero, 1); + TEST_extra (sincos, plus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_extra (sincos, minus_infty, nan_value, nan_value, INVALID_EXCEPTION); + TEST_extra (sincos, nan_value, nan_value, nan_value); + + TEST_extra (sincos, M_PI_2l, 1, 0); + TEST_extra (sincos, M_PI_6l, 0.5, 0.86602540378443864676372317075293616L); + TEST_extra (sincos, M_PI_6l*2.0, 0.86602540378443864676372317075293616L, 0.5); + TEST_extra (sincos, 0.75L, 0.681638760023334166733241952779893935L, 0.731688868873820886311838753000084544L); + +#ifdef TEST_DOUBLE + TEST_extra (sincos, 0.80190127184058835, 0.71867942238767868, 0.69534156199418473); +#endif + + END (sincos); +} +#endif + +static void +sinh_test (void) +{ + errno = 0; + FUNC(sinh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sinh); + TEST_f_f (sinh, 0, 0); + TEST_f_f (sinh, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (sinh, plus_infty, plus_infty); + TEST_f_f (sinh, minus_infty, minus_infty); +#endif + TEST_f_f (sinh, nan_value, nan_value); + + TEST_f_f (sinh, 0.75L, 0.822316731935829980703661634446913849L); + TEST_f_f (sinh, 0x8p-32L, 1.86264514923095703232705808926175479e-9L); + + END (sinh); +} + +static void +sqrt_test (void) +{ + errno = 0; + FUNC(sqrt) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (sqrt); + + TEST_f_f (sqrt, 0, 0); + TEST_f_f (sqrt, nan_value, nan_value); + TEST_f_f (sqrt, plus_infty, plus_infty); + + TEST_f_f (sqrt, minus_zero, minus_zero); + + /* sqrt (x) == NaN plus invalid exception for x < 0. */ + TEST_f_f (sqrt, -1, nan_value, INVALID_EXCEPTION); + TEST_f_f (sqrt, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (sqrt, nan_value, nan_value); + + TEST_f_f (sqrt, 2209, 47); + TEST_f_f (sqrt, 4, 2); + TEST_f_f (sqrt, 2, M_SQRT2l); + TEST_f_f (sqrt, 0.25, 0.5); + TEST_f_f (sqrt, 6642.25, 81.5); + TEST_f_f (sqrt, 15190.5625L, 123.25L); + TEST_f_f (sqrt, 0.75L, 0.866025403784438646763723170752936183L); + + END (sqrt); +} + + +static void +tan_test (void) +{ + errno = 0; + FUNC(tan) (0); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (tan); + + TEST_f_f (tan, 0, 0); + TEST_f_f (tan, minus_zero, minus_zero); + TEST_f_f (tan, plus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tan, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tan, nan_value, nan_value); + + TEST_f_f (tan, M_PI_4l, 1); + TEST_f_f (tan, 0.75L, 0.931596459944072461165202756573936428L); + + END (tan); +} + +static void +tanh_test (void) +{ + errno = 0; + FUNC(tanh) (0.7L); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + START (tanh); + + TEST_f_f (tanh, 0, 0); + TEST_f_f (tanh, minus_zero, minus_zero); + +#ifndef TEST_INLINE + TEST_f_f (tanh, plus_infty, 1); + TEST_f_f (tanh, minus_infty, -1); +#endif + TEST_f_f (tanh, nan_value, nan_value); + + TEST_f_f (tanh, 0.75L, 0.635148952387287319214434357312496495L); + TEST_f_f (tanh, -0.75L, -0.635148952387287319214434357312496495L); + + TEST_f_f (tanh, 1.0L, 0.7615941559557648881194582826047935904L); + TEST_f_f (tanh, -1.0L, -0.7615941559557648881194582826047935904L); + + /* 2^-57 */ + TEST_f_f (tanh, 0x1p-57L, 6.938893903907228377647697925567626953125e-18L); + + END (tanh); +} + +#if 0 +static void +tgamma_test (void) +{ + errno = 0; + FUNC(tgamma) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + feclearexcept (FE_ALL_EXCEPT); + + START (tgamma); + + TEST_f_f (tgamma, plus_infty, plus_infty); + TEST_f_f (tgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION); + TEST_f_f (tgamma, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION); + /* tgamma (x) == NaN plus invalid exception for integer x <= 0. */ + TEST_f_f (tgamma, -2, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, minus_infty, nan_value, INVALID_EXCEPTION); + TEST_f_f (tgamma, nan_value, nan_value); + + TEST_f_f (tgamma, 0.5, M_SQRT_PIl); + TEST_f_f (tgamma, -0.5, -M_2_SQRT_PIl); + + TEST_f_f (tgamma, 1, 1); + TEST_f_f (tgamma, 4, 6); + + TEST_f_f (tgamma, 0.7L, 1.29805533264755778568117117915281162L); + TEST_f_f (tgamma, 1.2L, 0.918168742399760610640951655185830401L); + + END (tgamma); +} +#endif + + +#if 0 +static void +trunc_test (void) +{ + START (trunc); + + TEST_f_f (trunc, plus_infty, plus_infty); + TEST_f_f (trunc, minus_infty, minus_infty); + TEST_f_f (trunc, nan_value, nan_value); + + TEST_f_f (trunc, 0, 0); + TEST_f_f (trunc, minus_zero, minus_zero); + TEST_f_f (trunc, 0.625, 0); + TEST_f_f (trunc, -0.625, minus_zero); + TEST_f_f (trunc, 1, 1); + TEST_f_f (trunc, -1, -1); + TEST_f_f (trunc, 1.625, 1); + TEST_f_f (trunc, -1.625, -1); + + TEST_f_f (trunc, 1048580.625L, 1048580L); + TEST_f_f (trunc, -1048580.625L, -1048580L); + + TEST_f_f (trunc, 8388610.125L, 8388610.0L); + TEST_f_f (trunc, -8388610.125L, -8388610.0L); + + TEST_f_f (trunc, 4294967296.625L, 4294967296.0L); + TEST_f_f (trunc, -4294967296.625L, -4294967296.0L); + +#ifdef TEST_LDOUBLE + /* The result can only be represented in long double. */ + TEST_f_f (trunc, 4503599627370495.5L, 4503599627370495.0L); + TEST_f_f (trunc, 4503599627370496.25L, 4503599627370496.0L); + TEST_f_f (trunc, 4503599627370496.5L, 4503599627370496.0L); + TEST_f_f (trunc, 4503599627370496.75L, 4503599627370496.0L); + TEST_f_f (trunc, 4503599627370497.5L, 4503599627370497.0L); + + TEST_f_f (trunc, -4503599627370495.5L, -4503599627370495.0L); + TEST_f_f (trunc, -4503599627370496.25L, -4503599627370496.0L); + TEST_f_f (trunc, -4503599627370496.5L, -4503599627370496.0L); + TEST_f_f (trunc, -4503599627370496.75L, -4503599627370496.0L); + TEST_f_f (trunc, -4503599627370497.5L, -4503599627370497.0L); + + TEST_f_f (trunc, 9007199254740991.5L, 9007199254740991.0L); + TEST_f_f (trunc, 9007199254740992.25L, 9007199254740992.0L); + TEST_f_f (trunc, 9007199254740992.5L, 9007199254740992.0L); + TEST_f_f (trunc, 9007199254740992.75L, 9007199254740992.0L); + TEST_f_f (trunc, 9007199254740993.5L, 9007199254740993.0L); + + TEST_f_f (trunc, -9007199254740991.5L, -9007199254740991.0L); + TEST_f_f (trunc, -9007199254740992.25L, -9007199254740992.0L); + TEST_f_f (trunc, -9007199254740992.5L, -9007199254740992.0L); + TEST_f_f (trunc, -9007199254740992.75L, -9007199254740992.0L); + TEST_f_f (trunc, -9007199254740993.5L, -9007199254740993.0L); + + TEST_f_f (trunc, 72057594037927935.5L, 72057594037927935.0L); + TEST_f_f (trunc, 72057594037927936.25L, 72057594037927936.0L); + TEST_f_f (trunc, 72057594037927936.5L, 72057594037927936.0L); + TEST_f_f (trunc, 72057594037927936.75L, 72057594037927936.0L); + TEST_f_f (trunc, 72057594037927937.5L, 72057594037927937.0L); + + TEST_f_f (trunc, -72057594037927935.5L, -72057594037927935.0L); + TEST_f_f (trunc, -72057594037927936.25L, -72057594037927936.0L); + TEST_f_f (trunc, -72057594037927936.5L, -72057594037927936.0L); + TEST_f_f (trunc, -72057594037927936.75L, -72057594037927936.0L); + TEST_f_f (trunc, -72057594037927937.5L, -72057594037927937.0L); + + TEST_f_f (trunc, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L); + TEST_f_f (trunc, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L); + TEST_f_f (trunc, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L); + TEST_f_f (trunc, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L); + TEST_f_f (trunc, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L); +#endif + + END (trunc); +} +#endif + +static void +y0_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(y0) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* y0 is the Bessel function of the second kind of order 0 */ + START (y0); + + TEST_f_f (y0, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_f_f (y0, 0.0, minus_infty); + TEST_f_f (y0, nan_value, nan_value); + TEST_f_f (y0, plus_infty, 0); + + TEST_f_f (y0, 0.125L, -1.38968062514384052915582277745018693L); + TEST_f_f (y0, 0.75L, -0.137172769385772397522814379396581855L); + TEST_f_f (y0, 1.0, 0.0882569642156769579829267660235151628L); + TEST_f_f (y0, 1.5, 0.382448923797758843955068554978089862L); + TEST_f_f (y0, 2.0, 0.510375672649745119596606592727157873L); + TEST_f_f (y0, 8.0, 0.223521489387566220527323400498620359L); + TEST_f_f (y0, 10.0, 0.0556711672835993914244598774101900481L); + + END (y0); +} + + +static void +y1_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(y1) (1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* y1 is the Bessel function of the second kind of order 1 */ + START (y1); + + TEST_f_f (y1, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_f_f (y1, 0.0, minus_infty); + TEST_f_f (y1, plus_infty, 0); + TEST_f_f (y1, nan_value, nan_value); + + TEST_f_f (y1, 0.125L, -5.19993611253477499595928744876579921L); + TEST_f_f (y1, 0.75L, -1.03759455076928541973767132140642198L); + TEST_f_f (y1, 1.0, -0.781212821300288716547150000047964821L); + TEST_f_f (y1, 1.5, -0.412308626973911295952829820633445323L); + TEST_f_f (y1, 2.0, -0.107032431540937546888370772277476637L); + TEST_f_f (y1, 8.0, -0.158060461731247494255555266187483550L); + TEST_f_f (y1, 10.0, 0.249015424206953883923283474663222803L); + + END (y1); +} + + +static void +yn_test (void) +{ + errno = 0; +#if 0 + FLOAT s, c; + FUNC (sincos) (0, &s, &c); + if (errno == ENOSYS) + /* Required function not implemented. */ + return; +#endif + FUNC(yn) (1, 1); + if (errno == ENOSYS) + /* Function not implemented. */ + return; + + /* yn is the Bessel function of the second kind of order n */ + START (yn); + + /* yn (0, x) == y0 (x) */ + TEST_ff_f (yn, 0, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_ff_f (yn, 0, 0.0, minus_infty); + TEST_ff_f (yn, 0, nan_value, nan_value); + TEST_ff_f (yn, 0, plus_infty, 0); + + TEST_ff_f (yn, 0, 0.125L, -1.38968062514384052915582277745018693L); + TEST_ff_f (yn, 0, 0.75L, -0.137172769385772397522814379396581855L); + TEST_ff_f (yn, 0, 1.0, 0.0882569642156769579829267660235151628L); + TEST_ff_f (yn, 0, 1.5, 0.382448923797758843955068554978089862L); + TEST_ff_f (yn, 0, 2.0, 0.510375672649745119596606592727157873L); + TEST_ff_f (yn, 0, 8.0, 0.223521489387566220527323400498620359L); + TEST_ff_f (yn, 0, 10.0, 0.0556711672835993914244598774101900481L); + + /* yn (1, x) == y1 (x) */ + TEST_ff_f (yn, 1, -1.0, minus_infty, INVALID_EXCEPTION); + TEST_ff_f (yn, 1, 0.0, minus_infty); + TEST_ff_f (yn, 1, plus_infty, 0); + TEST_ff_f (yn, 1, nan_value, nan_value); + + TEST_ff_f (yn, 1, 0.125L, -5.19993611253477499595928744876579921L); + TEST_ff_f (yn, 1, 0.75L, -1.03759455076928541973767132140642198L); + TEST_ff_f (yn, 1, 1.0, -0.781212821300288716547150000047964821L); + TEST_ff_f (yn, 1, 1.5, -0.412308626973911295952829820633445323L); + TEST_ff_f (yn, 1, 2.0, -0.107032431540937546888370772277476637L); + TEST_ff_f (yn, 1, 8.0, -0.158060461731247494255555266187483550L); + TEST_ff_f (yn, 1, 10.0, 0.249015424206953883923283474663222803L); + + /* yn (3, x) */ + TEST_ff_f (yn, 3, plus_infty, 0); + TEST_ff_f (yn, 3, nan_value, nan_value); + + TEST_ff_f (yn, 3, 0.125L, -2612.69757350066712600220955744091741L); + TEST_ff_f (yn, 3, 0.75L, -12.9877176234475433186319774484809207L); + TEST_ff_f (yn, 3, 1.0, -5.82151760596472884776175706442981440L); + TEST_ff_f (yn, 3, 2.0, -1.12778377684042778608158395773179238L); + TEST_ff_f (yn, 3, 10.0, -0.251362657183837329779204747654240998L); + + /* yn (10, x) */ + TEST_ff_f (yn, 10, plus_infty, 0); + TEST_ff_f (yn, 10, nan_value, nan_value); + + TEST_ff_f (yn, 10, 0.125L, -127057845771019398.252538486899753195L); + TEST_ff_f (yn, 10, 0.75L, -2133501638.90573424452445412893839236L); + TEST_ff_f (yn, 10, 1.0, -121618014.278689189288130426667971145L); + TEST_ff_f (yn, 10, 2.0, -129184.542208039282635913145923304214L); + TEST_ff_f (yn, 10, 10.0, -0.359814152183402722051986577343560609L); + + END (yn); + +} + + +static void +significand_test (void) +{ + /* significand returns the mantissa of the exponential representation. */ + START (significand); + + TEST_f_f (significand, 4.0, 1.0); + TEST_f_f (significand, 6.0, 1.5); + TEST_f_f (significand, 8.0, 1.0); + + END (significand); +} + + +static void +initialize (void) +{ + fpstack_test ("start *init*"); + plus_zero = 0.0; + nan_value = plus_zero / plus_zero; /* Suppress GCC warning */ + + minus_zero = FUNC(copysign) (0.0, -1.0); + plus_infty = CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF, + HUGE_VALL, HUGE_VAL, HUGE_VALF); + minus_infty = CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF, + -HUGE_VALL, -HUGE_VAL, -HUGE_VALF); + max_value = CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX, + LDBL_MAX, DBL_MAX, FLT_MAX); + min_value = CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN, + LDBL_MIN, DBL_MIN, FLT_MIN); + + (void) &plus_zero; + (void) &nan_value; + (void) &minus_zero; + (void) &plus_infty; + (void) &minus_infty; + (void) &max_value; + (void) &min_value; + + /* Clear all exceptions. From now on we must not get random exceptions. */ + feclearexcept (FE_ALL_EXCEPT); + + /* Test to make sure we start correctly. */ + fpstack_test ("end *init*"); +} + +#if 0 +/* function to check our ulp calculation. */ +void +check_ulp (void) +{ + int i; + + FLOAT u, diff, ulp; + /* This gives one ulp. */ + u = FUNC(nextafter) (10, 20); + check_equal (10.0, u, 1, &diff, &ulp); + printf ("One ulp: % .4" PRINTF_NEXPR "\n", ulp); + + /* This gives one more ulp. */ + u = FUNC(nextafter) (u, 20); + check_equal (10.0, u, 2, &diff, &ulp); + printf ("two ulp: % .4" PRINTF_NEXPR "\n", ulp); + + /* And now calculate 100 ulp. */ + for (i = 2; i < 100; i++) + u = FUNC(nextafter) (u, 20); + check_equal (10.0, u, 100, &diff, &ulp); + printf ("100 ulp: % .4" PRINTF_NEXPR "\n", ulp); +} +#endif + +int +main (int argc, char **argv) +{ + + int key; + + verbose = 1; + output_ulps = 0; + output_max_error = 1; + output_points = 1; + /* XXX set to 0 for releases. */ + ignore_max_ulp = 0; + + /* Parse and process arguments. */ + while ((key = getopt(argc, argv, "fi:puv")) > 0) { + switch (key) + { + case 'f': + output_max_error = 0; + break; + case 'i': + if (strcmp (optarg, "yes") == 0) + ignore_max_ulp = 1; + else if (strcmp (optarg, "no") == 0) + ignore_max_ulp = 0; + break; + case 'p': + output_points = 0; + break; + case 'u': + output_ulps = 1; + break; + case 'v': + verbose = 3; + break; + default: + fprintf (stderr, "Unknown argument: %c", key); + exit (EXIT_FAILURE); + } + } + + if (optind != argc) + { + fprintf (stderr, "wrong number of arguments"); + exit (EXIT_FAILURE); + } + + if (output_ulps) + { + ulps_file = fopen ("ULPs", "a"); + if (ulps_file == NULL) + { + perror ("can't open file `ULPs' for writing: "); + exit (1); + } + } + + + initialize (); + printf (TEST_MSG); + +#if 0 + check_ulp (); +#endif + + /* Keep the tests a wee bit ordered (according to ISO C99). */ + /* Classification macros: */ + fpclassify_test (); + isfinite_test (); + isnormal_test (); + signbit_test (); + + /* Trigonometric functions: */ + acos_test (); + asin_test (); + atan_test (); + atan2_test (); + cos_test (); + sin_test (); +#if 0 + sincos_test (); +#endif + tan_test (); + + /* Hyperbolic functions: */ + acosh_test (); + asinh_test (); + atanh_test (); + cosh_test (); + sinh_test (); + tanh_test (); + + /* Exponential and logarithmic functions: */ + exp_test (); +#if 0 + exp10_test (); + exp2_test (); +#endif + expm1_test (); + frexp_test (); + ldexp_test (); + log_test (); + log10_test (); + log1p_test (); +#if 0 + log2_test (); +#endif + logb_test (); + modf_test (); + ilogb_test (); + scalb_test (); + scalbn_test (); +#if 0 + scalbln_test (); +#endif + significand_test (); + + /* Power and absolute value functions: */ + cbrt_test (); + fabs_test (); + hypot_test (); + pow_test (); + sqrt_test (); + + /* Error and gamma functions: */ + erf_test (); + erfc_test (); + gamma_test (); + lgamma_test (); +#if 0 + tgamma_test (); +#endif + + /* Nearest integer functions: */ + ceil_test (); + floor_test (); +#if 0 + nearbyint_test (); +#endif + rint_test (); +#if 0 + rint_test_tonearest (); + rint_test_towardzero (); + rint_test_downward (); + rint_test_upward (); + lrint_test (); + llrint_test (); + round_test (); + lround_test (); + llround_test (); + trunc_test (); +#endif + + /* Remainder functions: */ + fmod_test (); + remainder_test (); +#if 0 + remquo_test (); +#endif + + /* Manipulation functions: */ + copysign_test (); +#if 0 + nextafter_test (); + nexttoward_test (); + + /* maximum, minimum and positive difference functions */ + fdim_test (); + fmax_test (); + fmin_test (); + + /* Multiply and add: */ + fma_test (); + + /* Complex functions: */ + cabs_test (); + cacos_test (); + cacosh_test (); + carg_test (); + casin_test (); + casinh_test (); + catan_test (); + catanh_test (); + ccos_test (); + ccosh_test (); + cexp_test (); + cimag_test (); + clog10_test (); + clog_test (); +#if 0 + conj_test (); +#endif + cpow_test (); + cproj_test (); + creal_test (); + csin_test (); + csinh_test (); + csqrt_test (); + ctan_test (); + ctanh_test (); +#endif + + /* Bessel functions: */ +#if 0 + j0_test (); + j1_test (); + jn_test (); + y0_test (); + y1_test (); + yn_test (); +#endif + + if (output_ulps) + fclose (ulps_file); + + printf ("\nTest suite completed:\n"); + printf (" %d test cases plus %d tests for exception flags executed.\n", + noTests, noExcTests); + if (noXFails) + printf (" %d expected failures occurred.\n", noXFails); + if (noXPasses) + printf (" %d unexpected passes occurred.\n", noXPasses); + if (noErrors) + { + printf (" %d errors occurred.\n", noErrors); + return 1; + } + printf (" All tests passed successfully.\n"); + + return 0; +} + +/* + * Local Variables: + * mode:c + * End: + */ diff --git a/test/math/rint.c b/test/math/rint.c new file mode 100644 index 0000000..04c1953 --- /dev/null +++ b/test/math/rint.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main(void) { + double d1, d2; + d1 = 0.6; d2 = rint(d1); + printf("d1 = %f, d2 = %f\n", d1, d2); + return 0; +} + diff --git a/test/math/test-double.c b/test/math/test-double.c new file mode 100644 index 0000000..4d239a7 --- /dev/null +++ b/test/math/test-double.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function +#define FLOAT double +#define TEST_MSG "testing double (without inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cdouble +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_DOUBLE 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-float.c b/test/math/test-float.c new file mode 100644 index 0000000..26a4213 --- /dev/null +++ b/test/math/test-float.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function ## f +#define FLOAT float +#define TEST_MSG "testing float (without inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cfloat +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_FLOAT 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-fpucw.c b/test/math/test-fpucw.c new file mode 100644 index 0000000..6d638c6 --- /dev/null +++ b/test/math/test-fpucw.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +main (void) +{ +#ifdef _FPU_GETCW +/* Some architectures don't have _FPU_GETCW (e.g. Linux/Alpha). */ + fpu_control_t cw; + + _FPU_GETCW (cw); + + cw &= ~_FPU_RESERVED; + + if (cw != (_FPU_DEFAULT & ~_FPU_RESERVED)) + printf ("control word is 0x%lx but should be 0x%lx.\n", + (long int) cw, (long int) (_FPU_DEFAULT & ~_FPU_RESERVED)); + + return cw != (_FPU_DEFAULT & ~_FPU_RESERVED); + +#else + return 0; +#endif +} diff --git a/test/math/test-idouble.c b/test/math/test-idouble.c new file mode 100644 index 0000000..7606a89 --- /dev/null +++ b/test/math/test-idouble.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function +#define FLOAT double +#define TEST_MSG "testing double (inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinedouble +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_DOUBLE 1 +#define TEST_INLINE + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ifloat.c b/test/math/test-ifloat.c new file mode 100644 index 0000000..9eb9ce5 --- /dev/null +++ b/test/math/test-ifloat.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function ## f +#define FLOAT float +#define TEST_MSG "testing float (inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinefloat +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_FLOAT 1 +#define TEST_INLINE 1 + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ildoubl.c b/test/math/test-ildoubl.c new file mode 100644 index 0000000..597edbc --- /dev/null +++ b/test/math/test-ildoubl.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function##l +#define FLOAT long double +#define TEST_MSG "testing long double (inline functions)\n" +#define MATHCONST(x) x##L +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinelongdouble +#define PRINTF_EXPR "Le" +#define PRINTF_XEXPR "La" +#define PRINTF_NEXPR "Lf" +#define TEST_INLINE +#define TEST_LDOUBLE 1 + +#ifdef __NO_MATH_INLINES +# undef __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/test-ldouble.c b/test/math/test-ldouble.c new file mode 100644 index 0000000..2721227 --- /dev/null +++ b/test/math/test-ldouble.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1997. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FUNC(function) function##l +#define FLOAT long double +#define TEST_MSG "testing long double (without inline functions)\n" +#define MATHCONST(x) x##L +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Clongdouble +#define PRINTF_EXPR "Le" +#define PRINTF_XEXPR "La" +#define PRINTF_NEXPR "Lf" +#define TEST_LDOUBLE 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#include "libm-test.c" diff --git a/test/math/tst-definitions.c b/test/math/tst-definitions.c new file mode 100644 index 0000000..7d352af --- /dev/null +++ b/test/math/tst-definitions.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2000. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +main (void) +{ + int result = 0; + + if (FP_ILOGB0 != INT_MIN && FP_ILOGB0 != -INT_MAX) + { + puts ("FP_ILOGB0 has no valid value"); + result = 1; + } + else + puts ("FP_ILOGB0 value is OK"); + + if (FP_ILOGBNAN != INT_MIN && FP_ILOGBNAN != INT_MAX) + { + puts ("FP_ILOBNAN has no valid value"); + result = 1; + } + else + puts ("FP_ILOGBNAN value is OK"); + + return result; +} diff --git a/test/misc/Makefile b/test/misc/Makefile new file mode 100644 index 0000000..48c549e --- /dev/null +++ b/test/misc/Makefile @@ -0,0 +1,14 @@ +# uClibc misc tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS_DISABLED := outb tst-fnmatch bug-glob1 tst-gnuglob + +include ../Test.mak + +CFLAGS_dirent64 := -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + +DODIFF_dirent := 1 +DODIFF_dirent64 := 1 + +OPTS_bug-glob1 := $(PWD) +OPTS_tst-fnmatch := < tst-fnmatch.input diff --git a/test/misc/bug-glob1.c b/test/misc/bug-glob1.c new file mode 100644 index 0000000..aec84ad --- /dev/null +++ b/test/misc/bug-glob1.c @@ -0,0 +1,94 @@ +/* Test case for globbing dangling symlink. By Ulrich Drepper. */ +#include +#include +#include +#include +#include +#include +#include + + +static void prepare (int argc, char *argv[]); +#define PREPARE prepare +static int do_test (void); +#define TEST_FUNCTION do_test () + +#include "../test-skeleton.c" + + +static char *fname; + +static void +prepare (int argc, char *argv[]) +{ + if (argc < 2) + error (EXIT_FAILURE, 0, "missing argument"); + + size_t len = strlen (argv[1]); + static const char ext[] = "globXXXXXX"; + fname = malloc (len + sizeof (ext)); + if (fname == NULL) + error (EXIT_FAILURE, errno, "cannot create temp file"); + again: + strcpy (stpcpy (fname, argv[1]), ext); + +/* + fname = mktemp (fname); +*/ + close(mkstemp(fname)); + unlink(fname); + + if (fname == NULL || *fname == '\0') + error (EXIT_FAILURE, errno, "cannot create temp file name"); + if (symlink ("bug-glob1-does-not-exist", fname) != 0) + { + if (errno == EEXIST) + goto again; + + error (EXIT_FAILURE, errno, "cannot create symlink"); + } + add_temp_file (fname); +} + + +static int +do_test (void) +{ + glob_t gl; + int retval = 0; + int e; + + e = glob (fname, 0, NULL, &gl); + if (e == 0) + { + printf ("glob(\"%s\") succeeded when it should not have\n", fname); + retval = 1; + } + globfree (&gl); + + size_t fnamelen = strlen (fname); + char buf[fnamelen + 2]; + + strcpy (buf, fname); + buf[fnamelen - 1] = '?'; + e = glob (buf, 0, NULL, &gl); + if (e == 0) + { + printf ("glob(\"%s\") succeeded when it should not have\n", buf); + retval = 1; + } + globfree (&gl); + + strcpy (buf, fname); + buf[fnamelen] = '*'; + buf[fnamelen + 1] = '\0'; + e = glob (buf, 0, NULL, &gl); + if (e == 0) + { + printf ("glob(\"%s\") succeeded when it should not have\n", buf); + retval = 1; + } + globfree (&gl); + + return retval; +} diff --git a/test/misc/bug-glob2.c b/test/misc/bug-glob2.c new file mode 100644 index 0000000..f8b030e --- /dev/null +++ b/test/misc/bug-glob2.c @@ -0,0 +1,302 @@ +/* Test glob memory management. + for the filesystem access functions. + Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +// #define DEBUG +#ifdef DEBUG +# define PRINTF(fmt, args...) \ + do \ + { \ + int save_errno = errno; \ + printf (fmt, ##args); \ + errno = save_errno; \ + } while (0) +#else +# define PRINTF(fmt, args...) +#endif + + +#ifdef GLOB_ALTDIRFUNC +static struct +{ + const char *name; + int level; + int type; + mode_t mode; +} filesystem[] = +{ + { ".", 1, DT_DIR, 0755 }, + { "..", 1, DT_DIR, 0755 }, + { "dir", 1, DT_DIR, 0755 }, + { ".", 2, DT_DIR, 0755 }, + { "..", 2, DT_DIR, 0755 }, + { "readable", 2, DT_DIR, 0755 }, + { ".", 3, DT_DIR, 0755 }, + { "..", 3, DT_DIR, 0755 }, + { "a", 3, DT_REG, 0644 }, + { "unreadable", 2, DT_DIR, 0111 }, + { ".", 3, DT_DIR, 0111 }, + { "..", 3, DT_DIR, 0755 }, + { "a", 3, DT_REG, 0644 }, + { "zz-readable", 2, DT_DIR, 0755 }, + { ".", 3, DT_DIR, 0755 }, + { "..", 3, DT_DIR, 0755 }, + { "a", 3, DT_REG, 0644 } +}; +#define nfiles (sizeof (filesystem) / sizeof (filesystem[0])) + + +typedef struct +{ + int level; + int idx; + struct dirent d; + char room_for_dirent[NAME_MAX]; +} my_DIR; + + +static long int +find_file (const char *s) +{ + int level = 1; + long int idx = 0; + + if (strcmp (s, ".") == 0) + return 0; + + if (s[0] == '.' && s[1] == '/') + s += 2; + + while (*s != '\0') + { + char *endp = strchrnul (s, '/'); + + PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level); + + while (idx < nfiles && filesystem[idx].level >= level) + { + if (filesystem[idx].level == level + && memcmp (s, filesystem[idx].name, endp - s) == 0 + && filesystem[idx].name[endp - s] == '\0') + break; + ++idx; + } + + if (idx == nfiles || filesystem[idx].level < level) + { + errno = ENOENT; + return -1; + } + + if (*endp == '\0') + return idx + 1; + + if (filesystem[idx].type != DT_DIR + && (idx + 1 >= nfiles + || filesystem[idx].level >= filesystem[idx + 1].level)) + { + errno = ENOTDIR; + return -1; + } + + ++idx; + + s = endp + 1; + ++level; + } + + errno = ENOENT; + return -1; +} + + +static void * +my_opendir (const char *s) +{ + long int idx = find_file (s); + my_DIR *dir; + + if (idx == -1) + { + PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s); + return NULL; + } + + if ((filesystem[idx].mode & 0400) == 0) + { + errno = EACCES; + PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s); + return NULL; + } + + dir = (my_DIR *) malloc (sizeof (my_DIR)); + if (dir == NULL) + { + printf ("cannot allocate directory handle: %m\n"); + exit (EXIT_FAILURE); + } + + dir->level = filesystem[idx].level; + dir->idx = idx; + + PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n", + s, filesystem[idx].level, idx); + + return dir; +} + + +static struct dirent * +my_readdir (void *gdir) +{ + my_DIR *dir = gdir; + + if (dir->idx == -1) + { + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n", + dir->level, (long int) dir->idx); + return NULL; + } + + while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level) + ++dir->idx; + + if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level) + { + dir->idx = -1; + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n", + dir->level, (long int) dir->idx); + return NULL; + } + + dir->d.d_ino = dir->idx; + +#ifdef _DIRENT_HAVE_D_TYPE + dir->d.d_type = filesystem[dir->idx].type; +#endif + + strcpy (dir->d.d_name, filesystem[dir->idx].name); + +#ifdef _DIRENT_HAVE_D_TYPE + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n", + dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type, + dir->d.d_name); +#else + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n", + dir->level, (long int) dir->idx, dir->d.d_ino, + dir->d.d_name); +#endif + + ++dir->idx; + + return &dir->d; +} + + +static void +my_closedir (void *dir) +{ + PRINTF ("my_closedir ()\n"); + free (dir); +} + + +/* We use this function for lstat as well since we don't have any. */ +static int +my_stat (const char *name, struct stat *st) +{ + long int idx = find_file (name); + + if (idx == -1) + { + PRINTF ("my_stat (\"%s\", ...) = -1 (%m)\n", name); + return -1; + } + + memset (st, '\0', sizeof (*st)); + + if (filesystem[idx].type == DT_UNKNOWN) + st->st_mode = DTTOIF (idx + 1 < nfiles + && filesystem[idx].level < filesystem[idx + 1].level + ? DT_DIR : DT_REG) | filesystem[idx].mode; + else + st->st_mode = DTTOIF (filesystem[idx].type) | filesystem[idx].mode; + + PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode); + + return 0; +} + + +static void +init_glob_altdirfuncs (glob_t *pglob) +{ + pglob->gl_closedir = my_closedir; + pglob->gl_readdir = my_readdir; + pglob->gl_opendir = my_opendir; + pglob->gl_lstat = my_stat; + pglob->gl_stat = my_stat; +} + + +static int +do_test (void) +{ + glob_t gl; + memset (&gl, 0, sizeof (gl)); + init_glob_altdirfuncs (&gl); + + if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl) + != GLOB_ABORTED) + { + puts ("glob did not fail with GLOB_ABORTED"); + exit (EXIT_FAILURE); + } + + globfree (&gl); + + memset (&gl, 0, sizeof (gl)); + init_glob_altdirfuncs (&gl); + + gl.gl_offs = 3; + if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH) + { + puts ("glob did not fail with GLOB_NOMATCH"); + exit (EXIT_FAILURE); + } + + globfree (&gl); + + return 0; +} +#else +static int do_test (void) { return 0; } +#endif + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/misc/bug-readdir1.c b/test/misc/bug-readdir1.c new file mode 100644 index 0000000..a8594a8 --- /dev/null +++ b/test/misc/bug-readdir1.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include + + +int +main (void) +{ + DIR *dirp; + struct dirent* ent; + + /* open a dir stream */ + dirp = opendir ("/tmp"); + if (dirp == NULL) + { + if (errno == ENOENT) + exit (0); + + perror ("opendir"); + exit (1); + } + + /* close the directory file descriptor, making it invalid */ + if (close (dirfd (dirp)) != 0) + { + puts ("could not close directory file descriptor"); + /* This is not an error. It is not guaranteed this is possible. */ + return 0; + } + + ent = readdir (dirp); + + return ent != NULL || errno != EBADF; +} diff --git a/test/misc/dirent.c b/test/misc/dirent.c new file mode 100644 index 0000000..491e3cf --- /dev/null +++ b/test/misc/dirent.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +#define _DTIFY(DT) [DT] #DT +const char * const types[] = { + _DTIFY(DT_UNKNOWN), + _DTIFY(DT_FIFO), + _DTIFY(DT_CHR), + _DTIFY(DT_DIR), + _DTIFY(DT_BLK), + _DTIFY(DT_REG), + _DTIFY(DT_LNK), + _DTIFY(DT_SOCK), + _DTIFY(DT_WHT) +}; + +int main(int argc, char *argv[]) +{ + DIR *dirh; + struct dirent *de; + const char *mydir = (argc == 1 ? "/" : argv[1]); + + if ((dirh = opendir(mydir)) == NULL) { + perror("opendir"); + return 1; + } + + printf("readdir() says:\n"); + while ((de = readdir(dirh)) != NULL) + printf("\tdir entry %s: %s\n", types[de->d_type], de->d_name); + + closedir(dirh); + + return 0; +} diff --git a/test/misc/dirent64.c b/test/misc/dirent64.c new file mode 100644 index 0000000..26455ab --- /dev/null +++ b/test/misc/dirent64.c @@ -0,0 +1 @@ +#include "dirent.c" diff --git a/test/misc/fdopen.c b/test/misc/fdopen.c new file mode 100644 index 0000000..f64cfb6 --- /dev/null +++ b/test/misc/fdopen.c @@ -0,0 +1,52 @@ +/* Test for fdopen bugs. */ + +#include +#include +#include +#include + +#define assert(x) \ + if (!(x)) \ + { \ + fputs ("test failed: " #x "\n", stderr); \ + retval = 1; \ + goto the_end; \ + } + +int +main (int argc, char *argv[]) +{ + char name[256]; + FILE *fp = NULL; + int retval = 0; + int fd; + + /* hack to get a tempfile name w/out using tmpname() + * as that func causes a link time warning */ + sprintf(name, "%s-uClibc-test.XXXXXX", __FILE__); + fd = mkstemp(name); + close(fd); + + fp = fopen (name, "w"); + assert (fp != NULL) + assert (fputs ("foobar and baz", fp) > 0); + assert (fclose (fp) == 0); + fp = NULL; + + fd = open (name, O_RDWR|O_CREAT); + assert (fd != -1); + assert (lseek (fd, 5, SEEK_SET) == 5); + + fp = fdopen (fd, "a"); + assert (fp != NULL); + /* SuSv3 says that doing a fdopen() does not reset the file position, + * thus the '5' here is correct, not '14'. */ + assert (ftell (fp) == 5); + +the_end: + if (fp != NULL) + assert (fclose (fp) == 0); + unlink (name); + + return retval; +} diff --git a/test/misc/opendir-tst1.c b/test/misc/opendir-tst1.c new file mode 100644 index 0000000..983d4b4 --- /dev/null +++ b/test/misc/opendir-tst1.c @@ -0,0 +1,95 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +/* Name of the FIFO. */ +char tmpname[] = "fifoXXXXXX"; + + +/* Do the real work. */ +static int +real_test (void) +{ + DIR *dirp; + + /* This should not block for an FIFO. */ + dirp = opendir (tmpname); + + /* Successful. */ + if (dirp != NULL) + { + /* Oh, oh, how can this work? */ + fputs ("`opendir' succeeded on a FIFO???\n", stdout); + closedir (dirp); + return 1; + } + + if (errno != ENOTDIR) + { + fprintf (stdout, "`opendir' return error `%s' instead of `%s'\n", + strerror (errno), strerror (ENOTDIR)); + return 1; + } + + return 0; +} + + +static int +do_test (int argc, char *argv[]) +{ + int retval; + + retval = mkstemp(tmpname); + close(retval); + unlink(tmpname); + + /* Try to generate a FIFO. */ + if (mknod (tmpname, 0600 | S_IFIFO, 0) < 0) + { + perror ("mknod"); + /* We cannot make this an error. */ + return 0; + } + + retval = real_test (); + + remove (tmpname); + + return retval; +} + + +static void +do_cleanup (void) +{ + remove (tmpname); +} +#define CLEANUP_HANDLER do_cleanup () + + +/* Include the test skeleton. */ +#include diff --git a/test/misc/outb.c b/test/misc/outb.c new file mode 100644 index 0000000..bbe18ea --- /dev/null +++ b/test/misc/outb.c @@ -0,0 +1,9 @@ +#include + +int main(void) +{ + ioperm(0x340,0x342,1); + outb(0x340,0x0); + exit(0); +} + diff --git a/test/misc/popen.c b/test/misc/popen.c new file mode 100644 index 0000000..868b70e --- /dev/null +++ b/test/misc/popen.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +#define TEST(r, f, x, m) ( \ +((r) = (f)) == (x) || \ +(printf(__FILE__ ":%d: %s failed (" m ")\n", __LINE__, #f, r, x), err++, 0) ) + +#define TEST_E(f) ( (errno = 0), (f) || \ +(printf(__FILE__ ":%d: %s failed (errno = %d)\n", __LINE__, #f, errno), err++, 0) ) + +#define TEST_S(s, x, m) ( \ +!strcmp((s),(x)) || \ +(printf(__FILE__ ":%d: [%s] != [%s] (%s)\n", __LINE__, s, x, m), err++, 0) ) + +static sig_atomic_t got_sig; + +static void handler(int sig) +{ + got_sig = 1; +} + +int main(void) +{ + int i; + char foo[6]; + char cmd[64]; + int err = 0; + FILE *f; + + TEST_E(f = popen("echo hello", "r")); + TEST_E(fgets(foo, sizeof foo, f)); + TEST_S(foo, "hello", "child process did not say hello"); + TEST(i, pclose(f), 0, "exit status %04x != %04x"); + + signal(SIGUSR1, handler); + snprintf(cmd, sizeof cmd, "read a ; test \"x$a\" = xhello && kill -USR1 %d", getpid()); + TEST_E(f = popen(cmd, "w")); + TEST_E(fputs("hello", f) >= 0); + TEST(i, pclose(f), 0, "exit status %04x != %04x"); + signal(SIGUSR1, SIG_DFL); + TEST(i, got_sig, 1, "child process did not send signal (%i!=%i)"); + + return err; +} diff --git a/test/misc/seek.c b/test/misc/seek.c new file mode 100644 index 0000000..c5edb94 --- /dev/null +++ b/test/misc/seek.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr)) + +int main(void) +{ + struct { + off_t offset; + int whence; + } tests[] = { + { 0x00, SEEK_SET }, + { 0x01, SEEK_SET }, + { 0xFF, SEEK_SET } + }; + char buf[2000]; + off_t ret; + int i, fd; + FILE *fp; + int tmp; + + fd = open("lseek.out", O_RDWR|O_CREAT, 0600); + if (fd == -1) { + perror("open(lseek.out) failed"); + return 1; + } + unlink("lseek.out"); + fp = fdopen(fd, "rw"); + if (fp == NULL) { + perror("fopen(lseek.out) failed"); + return 1; + } + + memset(buf, 0xAB, sizeof(buf)); + ret = write(fd, buf, sizeof(buf)); + if (ret != sizeof(buf)) { + fprintf(stderr, "write() failed to write %zi bytes (wrote %li): ", sizeof(buf), (long)ret); + perror(""); + return 1; + } + + tmp = fseeko(fp, 1024, SEEK_SET); + assert(tmp == 0); + tmp = fseeko(fp, (off_t)-16, SEEK_CUR); + assert(tmp == 0); + ret = ftell(fp); + if (ret != (1024-16)) { + fprintf(stderr, "ftell() failed, we wanted pos %i but got %li: ", (1024-16), (long)ret); + perror(""); + return 1; + } + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + ret = lseek(fd, tests[i].offset, tests[i].whence); + if (ret != tests[i].offset) { + fprintf(stderr, "lseek(%li,%i) failed (wanted %li, got %li): ", (long)tests[i].offset, + tests[i].whence, (long)tests[i].offset, (long)ret); + perror(""); + return 1; + } + ret = fseek(fp, tests[i].offset, tests[i].whence); + if (ret != 0) { + fprintf(stderr, "fseek(%li,%i) failed (wanted 0, got %li): ", (long)tests[i].offset, + tests[i].whence, (long)ret); + perror(""); + return 1; + } + } + + fclose(fp); + close(fd); + + printf("Success!\n"); + + return 0; +} diff --git a/test/misc/sem.c b/test/misc/sem.c new file mode 100644 index 0000000..62a59b1 --- /dev/null +++ b/test/misc/sem.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int k, r; + union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; + } sd; + struct semid_ds sd_buf; + + k = semget(IPC_PRIVATE, 10, IPC_CREAT | 0666 ); + printf("semget(IPC_CREAT) = %d\n", k); + + if (k < 0) { + fprintf(stderr, "semget failed: %s\n", strerror(errno)); + return 1; + } + + sd.buf = &sd_buf; + r = semctl(k, 0, IPC_STAT, sd); + printf("semctl(k) = %d\n", r); + + if (r < 0) { + perror("semctl IPC_STAT failed"); + return 1; + } + + printf("sem_nsems = %lu\n", sd_buf.sem_nsems); + if (sd_buf.sem_nsems != 10) { + fprintf(stderr, "failed: incorrect sem_nsems!\n"); + return 1; + } + + printf("succeeded\n"); + + return 0; +} diff --git a/test/misc/stdarg.c b/test/misc/stdarg.c new file mode 100644 index 0000000..1566e0c --- /dev/null +++ b/test/misc/stdarg.c @@ -0,0 +1,23 @@ +/* copied from rsync */ + +#include +#include +#include +#include +#include +static int foo(const char *format, ...) +{ + va_list ap; + size_t len; + char buf[5]; + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) return(1); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) return(1); + + return(0); +} +int main(void) { return foo("hello"); } diff --git a/test/misc/tst-fnmatch.c b/test/misc/tst-fnmatch.c new file mode 100644 index 0000000..bb102c5 --- /dev/null +++ b/test/misc/tst-fnmatch.c @@ -0,0 +1,444 @@ +/* Tests for fnmatch function. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static char *next_input (char **line, int first, int last); +static int convert_flags (const char *str); +static char *flag_output (int flags); +static char *escape (const char *str, size_t *reslenp, char **resbuf); + + +int str_isalpha(const char *str) +{ + size_t i = strlen(str); + while (i--) + if (isascii(str[i]) == 0) + return 0; + return 1; +} +int str_has_funk(const char *str, const char x) +{ + size_t i, max = strlen(str); + for (i=0; i+1 reslen) + { + resbuf = (char *) realloc (resbuf, 2 * len + 1); + if (resbuf == NULL) + error (EXIT_FAILURE, errno, "while allocating buffer for printing"); + *reslenp = 2 * len + 1; + *resbufp = resbuf; + } + + wp = resbuf; + while (*str != '\0') + if (*str == '\t') + { + *wp++ = '\\'; + *wp++ = 't'; + ++str; + } + else if (*str == '\n') + { + *wp++ = '\\'; + *wp++ = 'n'; + ++str; + } + else if (*str == '"') + { + *wp++ = '\\'; + *wp++ = '"'; + ++str; + } + else if (*str == '\\') + { + *wp++ = '\\'; + *wp++ = '\\'; + ++str; + } + else + *wp++ = *str++; + + *wp = '\0'; + + return resbuf; +} diff --git a/test/misc/tst-fnmatch.input b/test/misc/tst-fnmatch.input new file mode 100644 index 0000000..9061d19 --- /dev/null +++ b/test/misc/tst-fnmatch.input @@ -0,0 +1,755 @@ +# Tests for fnmatch. +# Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributes by Ulrich Drepper . +# + +# The GNU C 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. + +# The GNU C 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 the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + + +# Derived from the IEEE 2003.2 text. The standard only contains some +# wording describing the situations to be tested. It does not specify +# any specific tests. I.e., the tests below are in no case sufficient. +# They are hopefully necessary, though. + +# B.6 004(C) +C "!#%+,-./01234567889" "!#%+,-./01234567889" 0 +C ":;=@ABCDEFGHIJKLMNO" ":;=@ABCDEFGHIJKLMNO" 0 +C "PQRSTUVWXYZ]abcdefg" "PQRSTUVWXYZ]abcdefg" 0 +C "hijklmnopqrstuvwxyz" "hijklmnopqrstuvwxyz" 0 +C "^_{}~" "^_{}~" 0 + +# B.6 005(C) +C "\"$&'()" "\\\"\\$\\&\\'\\(\\)" 0 +C "*?[\\`|" "\\*\\?\\[\\\\\\`\\|" 0 +C "<>" "\\<\\>" 0 + +# B.6 006(C) +C "?*[" "[?*[][?*[][?*[]" 0 +C "a/b" "?/b" 0 + +# B.6 007(C) +C "a/b" "a?b" 0 +C "a/b" "a/?" 0 +C "aa/b" "?/b" NOMATCH +C "aa/b" "a?b" NOMATCH +C "a/bb" "a/?" NOMATCH + +# B.6 009(C) +C "abc" "[abc]" NOMATCH +C "x" "[abc]" NOMATCH +C "a" "[abc]" 0 +C "[" "[[abc]" 0 +C "a" "[][abc]" 0 +C "a]" "[]a]]" 0 + +# B.6 010(C) +C "xyz" "[!abc]" NOMATCH +C "x" "[!abc]" 0 +C "a" "[!abc]" NOMATCH + +# B.6 011(C) +C "]" "[][abc]" 0 +C "abc]" "[][abc]" NOMATCH +C "[]abc" "[][]abc" NOMATCH +C "]" "[!]]" NOMATCH +C "aa]" "[!]a]" NOMATCH +C "]" "[!a]" 0 +C "]]" "[!a]]" 0 + +# B.6 012(C) +C "a" "[[.a.]]" 0 +C "-" "[[.-.]]" 0 +C "-" "[[.-.][.].]]" 0 +C "-" "[[.].][.-.]]" 0 +C "-" "[[.-.][=u=]]" 0 +C "-" "[[.-.][:alpha:]]" 0 +C "a" "[![.a.]]" NOMATCH + +# B.6 013(C) +C "a" "[[.b.]]" NOMATCH +C "a" "[[.b.][.c.]]" NOMATCH +C "a" "[[.b.][=b=]]" NOMATCH + + +# B.6 015(C) +C "a" "[[=a=]]" 0 +C "b" "[[=a=]b]" 0 +C "b" "[[=a=][=b=]]" 0 +C "a" "[[=a=][=b=]]" 0 +C "a" "[[=a=][.b.]]" 0 +C "a" "[[=a=][:digit:]]" 0 + +# B.6 016(C) +C "=" "[[=a=]b]" NOMATCH +C "]" "[[=a=]b]" NOMATCH +C "a" "[[=b=][=c=]]" NOMATCH +C "a" "[[=b=][.].]]" NOMATCH +C "a" "[[=b=][:digit:]]" NOMATCH + +# B.6 017(C) +C "a" "[[:alnum:]]" 0 +C "a" "[![:alnum:]]" NOMATCH +C "-" "[[:alnum:]]" NOMATCH +C "a]a" "[[:alnum:]]a" NOMATCH +C "-" "[[:alnum:]-]" 0 +C "aa" "[[:alnum:]]a" 0 +C "-" "[![:alnum:]]" 0 +C "]" "[!][:alnum:]]" NOMATCH +C "[" "[![:alnum:][]" NOMATCH +C "a" "[[:alnum:]]" 0 +C "b" "[[:alnum:]]" 0 +C "c" "[[:alnum:]]" 0 +C "d" "[[:alnum:]]" 0 +C "e" "[[:alnum:]]" 0 +C "f" "[[:alnum:]]" 0 +C "g" "[[:alnum:]]" 0 +C "h" "[[:alnum:]]" 0 +C "i" "[[:alnum:]]" 0 +C "j" "[[:alnum:]]" 0 +C "k" "[[:alnum:]]" 0 +C "l" "[[:alnum:]]" 0 +C "m" "[[:alnum:]]" 0 +C "n" "[[:alnum:]]" 0 +C "o" "[[:alnum:]]" 0 +C "p" "[[:alnum:]]" 0 +C "q" "[[:alnum:]]" 0 +C "r" "[[:alnum:]]" 0 +C "s" "[[:alnum:]]" 0 +C "t" "[[:alnum:]]" 0 +C "u" "[[:alnum:]]" 0 +C "v" "[[:alnum:]]" 0 +C "w" "[[:alnum:]]" 0 +C "x" "[[:alnum:]]" 0 +C "y" "[[:alnum:]]" 0 +C "z" "[[:alnum:]]" 0 +C "A" "[[:alnum:]]" 0 +C "B" "[[:alnum:]]" 0 +C "C" "[[:alnum:]]" 0 +C "D" "[[:alnum:]]" 0 +C "E" "[[:alnum:]]" 0 +C "F" "[[:alnum:]]" 0 +C "G" "[[:alnum:]]" 0 +C "H" "[[:alnum:]]" 0 +C "I" "[[:alnum:]]" 0 +C "J" "[[:alnum:]]" 0 +C "K" "[[:alnum:]]" 0 +C "L" "[[:alnum:]]" 0 +C "M" "[[:alnum:]]" 0 +C "N" "[[:alnum:]]" 0 +C "O" "[[:alnum:]]" 0 +C "P" "[[:alnum:]]" 0 +C "Q" "[[:alnum:]]" 0 +C "R" "[[:alnum:]]" 0 +C "S" "[[:alnum:]]" 0 +C "T" "[[:alnum:]]" 0 +C "U" "[[:alnum:]]" 0 +C "V" "[[:alnum:]]" 0 +C "W" "[[:alnum:]]" 0 +C "X" "[[:alnum:]]" 0 +C "Y" "[[:alnum:]]" 0 +C "Z" "[[:alnum:]]" 0 +C "0" "[[:alnum:]]" 0 +C "1" "[[:alnum:]]" 0 +C "2" "[[:alnum:]]" 0 +C "3" "[[:alnum:]]" 0 +C "4" "[[:alnum:]]" 0 +C "5" "[[:alnum:]]" 0 +C "6" "[[:alnum:]]" 0 +C "7" "[[:alnum:]]" 0 +C "8" "[[:alnum:]]" 0 +C "9" "[[:alnum:]]" 0 +C "!" "[[:alnum:]]" NOMATCH +C "#" "[[:alnum:]]" NOMATCH +C "%" "[[:alnum:]]" NOMATCH +C "+" "[[:alnum:]]" NOMATCH +C "," "[[:alnum:]]" NOMATCH +C "-" "[[:alnum:]]" NOMATCH +C "." "[[:alnum:]]" NOMATCH +C "/" "[[:alnum:]]" NOMATCH +C ":" "[[:alnum:]]" NOMATCH +C ";" "[[:alnum:]]" NOMATCH +C "=" "[[:alnum:]]" NOMATCH +C "@" "[[:alnum:]]" NOMATCH +C "[" "[[:alnum:]]" NOMATCH +C "\\" "[[:alnum:]]" NOMATCH +C "]" "[[:alnum:]]" NOMATCH +C "^" "[[:alnum:]]" NOMATCH +C "_" "[[:alnum:]]" NOMATCH +C "{" "[[:alnum:]]" NOMATCH +C "}" "[[:alnum:]]" NOMATCH +C "~" "[[:alnum:]]" NOMATCH +C "\"" "[[:alnum:]]" NOMATCH +C "$" "[[:alnum:]]" NOMATCH +C "&" "[[:alnum:]]" NOMATCH +C "'" "[[:alnum:]]" NOMATCH +C "(" "[[:alnum:]]" NOMATCH +C ")" "[[:alnum:]]" NOMATCH +C "*" "[[:alnum:]]" NOMATCH +C "?" "[[:alnum:]]" NOMATCH +C "`" "[[:alnum:]]" NOMATCH +C "|" "[[:alnum:]]" NOMATCH +C "<" "[[:alnum:]]" NOMATCH +C ">" "[[:alnum:]]" NOMATCH +C "\t" "[[:cntrl:]]" 0 +C "t" "[[:cntrl:]]" NOMATCH +C "t" "[[:lower:]]" 0 +C "\t" "[[:lower:]]" NOMATCH +C "T" "[[:lower:]]" NOMATCH +C "\t" "[[:space:]]" 0 +C "t" "[[:space:]]" NOMATCH +C "t" "[[:alpha:]]" 0 +C "\t" "[[:alpha:]]" NOMATCH +C "0" "[[:digit:]]" 0 +C "\t" "[[:digit:]]" NOMATCH +C "t" "[[:digit:]]" NOMATCH +C "\t" "[[:print:]]" NOMATCH +C "t" "[[:print:]]" 0 +C "T" "[[:upper:]]" 0 +C "\t" "[[:upper:]]" NOMATCH +C "t" "[[:upper:]]" NOMATCH +C "\t" "[[:blank:]]" 0 +C "t" "[[:blank:]]" NOMATCH +C "\t" "[[:graph:]]" NOMATCH +C "t" "[[:graph:]]" 0 +C "." "[[:punct:]]" 0 +C "t" "[[:punct:]]" NOMATCH +C "\t" "[[:punct:]]" NOMATCH +C "0" "[[:xdigit:]]" 0 +C "\t" "[[:xdigit:]]" NOMATCH +C "a" "[[:xdigit:]]" 0 +C "A" "[[:xdigit:]]" 0 +C "t" "[[:xdigit:]]" NOMATCH +C "a" "[[alpha]]" NOMATCH +C "a" "[[alpha:]]" NOMATCH +C "a]" "[[alpha]]" 0 +C "a]" "[[alpha:]]" 0 +C "a" "[[:alpha:][.b.]]" 0 +C "a" "[[:alpha:][=b=]]" 0 +C "a" "[[:alpha:][:digit:]]" 0 +C "a" "[[:digit:][:alpha:]]" 0 + +# B.6 018(C) +C "a" "[a-c]" 0 +C "b" "[a-c]" 0 +C "c" "[a-c]" 0 +C "a" "[b-c]" NOMATCH +C "d" "[b-c]" NOMATCH +C "B" "[a-c]" NOMATCH +C "b" "[A-C]" NOMATCH +C "" "[a-c]" NOMATCH +C "as" "[a-ca-z]" NOMATCH +C "a" "[[.a.]-c]" 0 +C "a" "[a-[.c.]]" 0 +C "a" "[[.a.]-[.c.]]" 0 +C "b" "[[.a.]-c]" 0 +C "b" "[a-[.c.]]" 0 +C "b" "[[.a.]-[.c.]]" 0 +C "c" "[[.a.]-c]" 0 +C "c" "[a-[.c.]]" 0 +C "c" "[[.a.]-[.c.]]" 0 +C "d" "[[.a.]-c]" NOMATCH +C "d" "[a-[.c.]]" NOMATCH +C "d" "[[.a.]-[.c.]]" NOMATCH + +# B.6 019(C) +C "a" "[c-a]" NOMATCH +C "a" "[[.c.]-a]" NOMATCH +C "a" "[c-[.a.]]" NOMATCH +C "a" "[[.c.]-[.a.]]" NOMATCH +C "c" "[c-a]" NOMATCH +C "c" "[[.c.]-a]" NOMATCH +C "c" "[c-[.a.]]" NOMATCH +C "c" "[[.c.]-[.a.]]" NOMATCH + +# B.6 020(C) +C "a" "[a-c0-9]" 0 +C "d" "[a-c0-9]" NOMATCH +C "B" "[a-c0-9]" NOMATCH + +# B.6 021(C) +C "-" "[-a]" 0 +C "a" "[-b]" NOMATCH +C "-" "[!-a]" NOMATCH +C "a" "[!-b]" 0 +C "-" "[a-c-0-9]" 0 +C "b" "[a-c-0-9]" 0 +C "a:" "a[0-9-a]" NOMATCH +C "a:" "a[09-a]" 0 + +# B.6 024(C) +C "" "*" 0 +C "asd/sdf" "*" 0 + +# B.6 025(C) +C "as" "[a-c][a-z]" 0 +C "as" "??" 0 + +# B.6 026(C) +C "asd/sdf" "as*df" 0 +C "asd/sdf" "as*" 0 +C "asd/sdf" "*df" 0 +C "asd/sdf" "as*dg" NOMATCH +C "asdf" "as*df" 0 +C "asdf" "as*df?" NOMATCH +C "asdf" "as*??" 0 +C "asdf" "a*???" 0 +C "asdf" "*????" 0 +C "asdf" "????*" 0 +C "asdf" "??*?" 0 + +# B.6 027(C) +C "/" "/" 0 +C "/" "/*" 0 +C "/" "*/" 0 +C "/" "/?" NOMATCH +C "/" "?/" NOMATCH +C "/" "?" 0 +C "." "?" 0 +C "/." "??" 0 +C "/" "[!a-c]" 0 +C "." "[!a-c]" 0 + +# B.6 029(C) +C "/" "/" 0 PATHNAME +C "//" "//" 0 PATHNAME +C "/.a" "/*" 0 PATHNAME +C "/.a" "/?a" 0 PATHNAME +C "/.a" "/[!a-z]a" 0 PATHNAME +C "/.a/.b" "/*/?b" 0 PATHNAME + +# B.6 030(C) +C "/" "?" NOMATCH PATHNAME +C "/" "*" NOMATCH PATHNAME +C "a/b" "a?b" NOMATCH PATHNAME +C "/.a/.b" "/*b" NOMATCH PATHNAME + +# B.6 031(C) +C "/$" "\\/\\$" 0 +C "/[" "\\/\\[" 0 +C "/[" "\\/[" NOMATCH + +# B.6 032(C) +C "/$" "\\/\\$" NOMATCH NOESCAPE +C "/\\$" "\\/\\$" NOMATCH NOESCAPE +C "\\/\\$" "\\/\\$" 0 NOESCAPE + +# B.6 033(C) +C ".asd" ".*" 0 PERIOD +C "/.asd" "*" 0 PERIOD +C "/as/.df" "*/?*f" 0 PERIOD +C "..asd" ".[!a-z]*" 0 PERIOD + +# B.6 034(C) +C ".asd" "*" NOMATCH PERIOD +C ".asd" "?asd" NOMATCH PERIOD +C ".asd" "[!a-z]*" NOMATCH PERIOD + +# B.6 035(C) +C "/." "/." 0 PATHNAME|PERIOD +C "/.a./.b." "/.*/.*" 0 PATHNAME|PERIOD +C "/.a./.b." "/.??/.??" 0 PATHNAME|PERIOD + +# B.6 036(C) +C "/." "*" NOMATCH PATHNAME|PERIOD +C "/." "/*" NOMATCH PATHNAME|PERIOD +C "/." "/?" NOMATCH PATHNAME|PERIOD +C "/." "/[!a-z]" NOMATCH PATHNAME|PERIOD +C "/a./.b." "/*/*" NOMATCH PATHNAME|PERIOD +C "/a./.b." "/??/???" NOMATCH PATHNAME|PERIOD + +# Some home-grown tests. +C "foobar" "foo*[abc]z" NOMATCH +C "foobaz" "foo*[abc][xyz]" 0 +C "foobaz" "foo?*[abc][xyz]" 0 +C "foobaz" "foo?*[abc][x/yz]" 0 +C "foobaz" "foo?*[abc]/[xyz]" NOMATCH PATHNAME +C "a" "a/" NOMATCH PATHNAME +C "a/" "a" NOMATCH PATHNAME +C "//a" "/a" NOMATCH PATHNAME +C "/a" "//a" NOMATCH PATHNAME +C "az" "[a-]z" 0 +C "bz" "[ab-]z" 0 +C "cz" "[ab-]z" NOMATCH +C "-z" "[ab-]z" 0 +C "az" "[-a]z" 0 +C "bz" "[-ab]z" 0 +C "cz" "[-ab]z" NOMATCH +C "-z" "[-ab]z" 0 +C "\\" "[\\\\-a]" 0 +C "_" "[\\\\-a]" 0 +C "a" "[\\\\-a]" 0 +C "-" "[\\\\-a]" NOMATCH +C "\\" "[\\]-a]" NOMATCH +C "_" "[\\]-a]" 0 +C "a" "[\\]-a]" 0 +C "]" "[\\]-a]" 0 +C "-" "[\\]-a]" NOMATCH +C "\\" "[!\\\\-a]" NOMATCH +C "_" "[!\\\\-a]" NOMATCH +C "a" "[!\\\\-a]" NOMATCH +C "-" "[!\\\\-a]" 0 +C "!" "[\\!-]" 0 +C "-" "[\\!-]" 0 +C "\\" "[\\!-]" NOMATCH +C "Z" "[Z-\\\\]" 0 +C "[" "[Z-\\\\]" 0 +C "\\" "[Z-\\\\]" 0 +C "-" "[Z-\\\\]" NOMATCH +C "Z" "[Z-\\]]" 0 +C "[" "[Z-\\]]" 0 +C "\\" "[Z-\\]]" 0 +C "]" "[Z-\\]]" 0 +C "-" "[Z-\\]]" NOMATCH + +# Following are tests outside the scope of IEEE 2003.2 since they are using +# locales other than the C locale. The main focus of the tests is on the +# handling of ranges and the recognition of character (vs bytes). +de_DE.ISO-8859-1 "a" "[a-z]" 0 +de_DE.ISO-8859-1 "z" "[a-z]" 0 +de_DE.ISO-8859-1 "ä" "[a-z]" 0 +de_DE.ISO-8859-1 "ö" "[a-z]" 0 +de_DE.ISO-8859-1 "ü" "[a-z]" 0 +de_DE.ISO-8859-1 "A" "[a-z]" NOMATCH +de_DE.ISO-8859-1 "Z" "[a-z]" NOMATCH +de_DE.ISO-8859-1 "Ä" "[a-z]" NOMATCH +de_DE.ISO-8859-1 "Ö" "[a-z]" NOMATCH +de_DE.ISO-8859-1 "Ü" "[a-z]" NOMATCH +de_DE.ISO-8859-1 "a" "[A-Z]" NOMATCH +de_DE.ISO-8859-1 "z" "[A-Z]" NOMATCH +de_DE.ISO-8859-1 "ä" "[A-Z]" NOMATCH +de_DE.ISO-8859-1 "ö" "[A-Z]" NOMATCH +de_DE.ISO-8859-1 "ü" "[A-Z]" NOMATCH +de_DE.ISO-8859-1 "A" "[A-Z]" 0 +de_DE.ISO-8859-1 "Z" "[A-Z]" 0 +de_DE.ISO-8859-1 "Ä" "[A-Z]" 0 +de_DE.ISO-8859-1 "Ö" "[A-Z]" 0 +de_DE.ISO-8859-1 "Ü" "[A-Z]" 0 +de_DE.ISO-8859-1 "a" "[[:lower:]]" 0 +de_DE.ISO-8859-1 "z" "[[:lower:]]" 0 +de_DE.ISO-8859-1 "ä" "[[:lower:]]" 0 +de_DE.ISO-8859-1 "ö" "[[:lower:]]" 0 +de_DE.ISO-8859-1 "ü" "[[:lower:]]" 0 +de_DE.ISO-8859-1 "A" "[[:lower:]]" NOMATCH +de_DE.ISO-8859-1 "Z" "[[:lower:]]" NOMATCH +de_DE.ISO-8859-1 "Ä" "[[:lower:]]" NOMATCH +de_DE.ISO-8859-1 "Ö" "[[:lower:]]" NOMATCH +de_DE.ISO-8859-1 "Ü" "[[:lower:]]" NOMATCH +de_DE.ISO-8859-1 "a" "[[:upper:]]" NOMATCH +de_DE.ISO-8859-1 "z" "[[:upper:]]" NOMATCH +de_DE.ISO-8859-1 "ä" "[[:upper:]]" NOMATCH +de_DE.ISO-8859-1 "ö" "[[:upper:]]" NOMATCH +de_DE.ISO-8859-1 "ü" "[[:upper:]]" NOMATCH +de_DE.ISO-8859-1 "A" "[[:upper:]]" 0 +de_DE.ISO-8859-1 "Z" "[[:upper:]]" 0 +de_DE.ISO-8859-1 "Ä" "[[:upper:]]" 0 +de_DE.ISO-8859-1 "Ö" "[[:upper:]]" 0 +de_DE.ISO-8859-1 "Ü" "[[:upper:]]" 0 +de_DE.ISO-8859-1 "a" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "z" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "ä" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "ö" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "ü" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "A" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "Z" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "Ä" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "Ö" "[[:alpha:]]" 0 +de_DE.ISO-8859-1 "Ü" "[[:alpha:]]" 0 + +de_DE.ISO-8859-1 "a" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "â" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "à" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "á" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "ä" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "b" "[[=a=]b]" 0 +de_DE.ISO-8859-1 "c" "[[=a=]b]" NOMATCH +de_DE.ISO-8859-1 "a" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "â" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "à" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "á" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "ä" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "b" "[[=â=]b]" 0 +de_DE.ISO-8859-1 "c" "[[=â=]b]" NOMATCH +de_DE.ISO-8859-1 "a" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "â" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "à" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "á" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "ä" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "b" "[[=à=]b]" 0 +de_DE.ISO-8859-1 "c" "[[=à=]b]" NOMATCH +de_DE.ISO-8859-1 "a" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "â" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "à" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "á" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "ä" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "b" "[[=á=]b]" 0 +de_DE.ISO-8859-1 "c" "[[=á=]b]" NOMATCH +de_DE.ISO-8859-1 "a" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "â" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "à" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "á" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "ä" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "b" "[[=ä=]b]" 0 +de_DE.ISO-8859-1 "c" "[[=ä=]b]" NOMATCH + +de_DE.ISO-8859-1 "aa" "[[.a.]]a" 0 +de_DE.ISO-8859-1 "ba" "[[.a.]]a" NOMATCH + + +# And with a multibyte character set. +de_DE.UTF-8 "a" "[a-z]" 0 +de_DE.UTF-8 "z" "[a-z]" 0 +de_DE.UTF-8 "ä" "[a-z]" 0 +de_DE.UTF-8 "ö" "[a-z]" 0 +de_DE.UTF-8 "ü" "[a-z]" 0 +de_DE.UTF-8 "A" "[a-z]" NOMATCH +de_DE.UTF-8 "Z" "[a-z]" NOMATCH +de_DE.UTF-8 "Ä" "[a-z]" NOMATCH +de_DE.UTF-8 "Ö" "[a-z]" NOMATCH +de_DE.UTF-8 "Ü" "[a-z]" NOMATCH +de_DE.UTF-8 "a" "[A-Z]" NOMATCH +de_DE.UTF-8 "z" "[A-Z]" NOMATCH +de_DE.UTF-8 "ä" "[A-Z]" NOMATCH +de_DE.UTF-8 "ö" "[A-Z]" NOMATCH +de_DE.UTF-8 "ü" "[A-Z]" NOMATCH +de_DE.UTF-8 "A" "[A-Z]" 0 +de_DE.UTF-8 "Z" "[A-Z]" 0 +de_DE.UTF-8 "Ä" "[A-Z]" 0 +de_DE.UTF-8 "Ö" "[A-Z]" 0 +de_DE.UTF-8 "Ü" "[A-Z]" 0 +de_DE.UTF-8 "a" "[[:lower:]]" 0 +de_DE.UTF-8 "z" "[[:lower:]]" 0 +de_DE.UTF-8 "ä" "[[:lower:]]" 0 +de_DE.UTF-8 "ö" "[[:lower:]]" 0 +de_DE.UTF-8 "ü" "[[:lower:]]" 0 +de_DE.UTF-8 "A" "[[:lower:]]" NOMATCH +de_DE.UTF-8 "Z" "[[:lower:]]" NOMATCH +de_DE.UTF-8 "Ä" "[[:lower:]]" NOMATCH +de_DE.UTF-8 "Ö" "[[:lower:]]" NOMATCH +de_DE.UTF-8 "Ü" "[[:lower:]]" NOMATCH +de_DE.UTF-8 "a" "[[:upper:]]" NOMATCH +de_DE.UTF-8 "z" "[[:upper:]]" NOMATCH +de_DE.UTF-8 "ä" "[[:upper:]]" NOMATCH +de_DE.UTF-8 "ö" "[[:upper:]]" NOMATCH +de_DE.UTF-8 "ü" "[[:upper:]]" NOMATCH +de_DE.UTF-8 "A" "[[:upper:]]" 0 +de_DE.UTF-8 "Z" "[[:upper:]]" 0 +de_DE.UTF-8 "Ä" "[[:upper:]]" 0 +de_DE.UTF-8 "Ö" "[[:upper:]]" 0 +de_DE.UTF-8 "Ü" "[[:upper:]]" 0 +de_DE.UTF-8 "a" "[[:alpha:]]" 0 +de_DE.UTF-8 "z" "[[:alpha:]]" 0 +de_DE.UTF-8 "ä" "[[:alpha:]]" 0 +de_DE.UTF-8 "ö" "[[:alpha:]]" 0 +de_DE.UTF-8 "ü" "[[:alpha:]]" 0 +de_DE.UTF-8 "A" "[[:alpha:]]" 0 +de_DE.UTF-8 "Z" "[[:alpha:]]" 0 +de_DE.UTF-8 "Ä" "[[:alpha:]]" 0 +de_DE.UTF-8 "Ö" "[[:alpha:]]" 0 +de_DE.UTF-8 "Ü" "[[:alpha:]]" 0 + +de_DE.UTF-8 "a" "[[=a=]b]" 0 +de_DE.UTF-8 "â" "[[=a=]b]" 0 +de_DE.UTF-8 "à" "[[=a=]b]" 0 +de_DE.UTF-8 "á" "[[=a=]b]" 0 +de_DE.UTF-8 "ä" "[[=a=]b]" 0 +de_DE.UTF-8 "b" "[[=a=]b]" 0 +de_DE.UTF-8 "c" "[[=a=]b]" NOMATCH +de_DE.UTF-8 "a" "[[=â=]b]" 0 +de_DE.UTF-8 "â" "[[=â=]b]" 0 +de_DE.UTF-8 "à" "[[=â=]b]" 0 +de_DE.UTF-8 "á" "[[=â=]b]" 0 +de_DE.UTF-8 "ä" "[[=â=]b]" 0 +de_DE.UTF-8 "b" "[[=â=]b]" 0 +de_DE.UTF-8 "c" "[[=â=]b]" NOMATCH +de_DE.UTF-8 "a" "[[=à=]b]" 0 +de_DE.UTF-8 "â" "[[=à=]b]" 0 +de_DE.UTF-8 "à" "[[=à=]b]" 0 +de_DE.UTF-8 "á" "[[=à=]b]" 0 +de_DE.UTF-8 "ä" "[[=à=]b]" 0 +de_DE.UTF-8 "b" "[[=à=]b]" 0 +de_DE.UTF-8 "c" "[[=à=]b]" NOMATCH +de_DE.UTF-8 "a" "[[=á=]b]" 0 +de_DE.UTF-8 "â" "[[=á=]b]" 0 +de_DE.UTF-8 "à" "[[=á=]b]" 0 +de_DE.UTF-8 "á" "[[=á=]b]" 0 +de_DE.UTF-8 "ä" "[[=á=]b]" 0 +de_DE.UTF-8 "b" "[[=á=]b]" 0 +de_DE.UTF-8 "c" "[[=á=]b]" NOMATCH +de_DE.UTF-8 "a" "[[=ä=]b]" 0 +de_DE.UTF-8 "â" "[[=ä=]b]" 0 +de_DE.UTF-8 "à" "[[=ä=]b]" 0 +de_DE.UTF-8 "á" "[[=ä=]b]" 0 +de_DE.UTF-8 "ä" "[[=ä=]b]" 0 +de_DE.UTF-8 "b" "[[=ä=]b]" 0 +de_DE.UTF-8 "c" "[[=ä=]b]" NOMATCH + +de_DE.UTF-8 "aa" "[[.a.]]a" 0 +de_DE.UTF-8 "ba" "[[.a.]]a" NOMATCH + + +# Test of GNU extensions. +C "x" "x" 0 PATHNAME|LEADING_DIR +C "x/y" "x" 0 PATHNAME|LEADING_DIR +C "x/y/z" "x" 0 PATHNAME|LEADING_DIR +C "x" "*" 0 PATHNAME|LEADING_DIR +C "x/y" "*" 0 PATHNAME|LEADING_DIR +C "x/y/z" "*" 0 PATHNAME|LEADING_DIR +C "x" "*x" 0 PATHNAME|LEADING_DIR +C "x/y" "*x" 0 PATHNAME|LEADING_DIR +C "x/y/z" "*x" 0 PATHNAME|LEADING_DIR +C "x" "x*" 0 PATHNAME|LEADING_DIR +C "x/y" "x*" 0 PATHNAME|LEADING_DIR +C "x/y/z" "x*" 0 PATHNAME|LEADING_DIR +C "x" "a" NOMATCH PATHNAME|LEADING_DIR +C "x/y" "a" NOMATCH PATHNAME|LEADING_DIR +C "x/y/z" "a" NOMATCH PATHNAME|LEADING_DIR +C "x" "x/y" NOMATCH PATHNAME|LEADING_DIR +C "x/y" "x/y" 0 PATHNAME|LEADING_DIR +C "x/y/z" "x/y" 0 PATHNAME|LEADING_DIR +C "x" "x?y" NOMATCH PATHNAME|LEADING_DIR +C "x/y" "x?y" NOMATCH PATHNAME|LEADING_DIR +C "x/y/z" "x?y" NOMATCH PATHNAME|LEADING_DIR + +# ksh style matching. +C "abcd" "?@(a|b)*@(c)d" 0 EXTMATCH +C "/dev/udp/129.22.8.102/45" "/dev/@(tcp|udp)/*/*" 0 PATHNAME|EXTMATCH +C "12" "[1-9]*([0-9])" 0 EXTMATCH +C "12abc" "[1-9]*([0-9])" NOMATCH EXTMATCH +C "1" "[1-9]*([0-9])" 0 EXTMATCH +C "07" "+([0-7])" 0 EXTMATCH +C "0377" "+([0-7])" 0 EXTMATCH +C "09" "+([0-7])" NOMATCH EXTMATCH +C "paragraph" "para@(chute|graph)" 0 EXTMATCH +C "paramour" "para@(chute|graph)" NOMATCH EXTMATCH +C "para991" "para?([345]|99)1" 0 EXTMATCH +C "para381" "para?([345]|99)1" NOMATCH EXTMATCH +C "paragraph" "para*([0-9])" NOMATCH EXTMATCH +C "para" "para*([0-9])" 0 EXTMATCH +C "para13829383746592" "para*([0-9])" 0 EXTMATCH +C "paragraph" "para+([0-9])" NOMATCH EXTMATCH +C "para" "para+([0-9])" NOMATCH EXTMATCH +C "para987346523" "para+([0-9])" 0 EXTMATCH +C "paragraph" "para!(*.[0-9])" 0 EXTMATCH +C "para.38" "para!(*.[0-9])" 0 EXTMATCH +C "para.graph" "para!(*.[0-9])" 0 EXTMATCH +C "para39" "para!(*.[0-9])" 0 EXTMATCH +C "" "*(0|1|3|5|7|9)" 0 EXTMATCH +C "137577991" "*(0|1|3|5|7|9)" 0 EXTMATCH +C "2468" "*(0|1|3|5|7|9)" NOMATCH EXTMATCH +C "1358" "*(0|1|3|5|7|9)" NOMATCH EXTMATCH +C "file.c" "*.c?(c)" 0 EXTMATCH +C "file.C" "*.c?(c)" NOMATCH EXTMATCH +C "file.cc" "*.c?(c)" 0 EXTMATCH +C "file.ccc" "*.c?(c)" NOMATCH EXTMATCH +C "parse.y" "!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH +C "shell.c" "!(*.c|*.h|Makefile.in|config*|README)" NOMATCH EXTMATCH +C "Makefile" "!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH +C "VMS.FILE;1" "*\;[1-9]*([0-9])" 0 EXTMATCH +C "VMS.FILE;0" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH +C "VMS.FILE;" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH +C "VMS.FILE;139" "*\;[1-9]*([0-9])" 0 EXTMATCH +C "VMS.FILE;1N" "*\;[1-9]*([0-9])" NOMATCH EXTMATCH +C "abcfefg" "ab**(e|f)" 0 EXTMATCH +C "abcfefg" "ab**(e|f)g" 0 EXTMATCH +C "ab" "ab*+(e|f)" NOMATCH EXTMATCH +C "abef" "ab***ef" 0 EXTMATCH +C "abef" "ab**" 0 EXTMATCH +C "fofo" "*(f*(o))" 0 EXTMATCH +C "ffo" "*(f*(o))" 0 EXTMATCH +C "foooofo" "*(f*(o))" 0 EXTMATCH +C "foooofof" "*(f*(o))" 0 EXTMATCH +C "fooofoofofooo" "*(f*(o))" 0 EXTMATCH +C "foooofof" "*(f+(o))" NOMATCH EXTMATCH +C "xfoooofof" "*(f*(o))" NOMATCH EXTMATCH +C "foooofofx" "*(f*(o))" NOMATCH EXTMATCH +C "ofxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "ofooofoofofooo" "*(f*(o))" NOMATCH EXTMATCH +C "foooxfooxfoxfooox" "*(f*(o)x)" 0 EXTMATCH +C "foooxfooxofoxfooox" "*(f*(o)x)" NOMATCH EXTMATCH +C "foooxfooxfxfooox" "*(f*(o)x)" 0 EXTMATCH +C "ofxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "ofoooxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "ofoooxoofxoofoooxoofxo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "ofoooxoofxoofoooxoofxoo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "ofoooxoofxoofoooxoofxofo" "*(*(of*(o)x)o)" NOMATCH EXTMATCH +C "ofoooxoofxoofoooxoofxooofxofxo" "*(*(of*(o)x)o)" 0 EXTMATCH +C "aac" "*(@(a))a@(c)" 0 EXTMATCH +C "ac" "*(@(a))a@(c)" 0 EXTMATCH +C "c" "*(@(a))a@(c)" NOMATCH EXTMATCH +C "aaac" "*(@(a))a@(c)" 0 EXTMATCH +C "baaac" "*(@(a))a@(c)" NOMATCH EXTMATCH +C "abcd" "?@(a|b)*@(c)d" 0 EXTMATCH +C "abcd" "@(ab|a*@(b))*(c)d" 0 EXTMATCH +C "acd" "@(ab|a*(b))*(c)d" 0 EXTMATCH +C "abbcd" "@(ab|a*(b))*(c)d" 0 EXTMATCH +C "effgz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH +C "efgz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH +C "egz" "@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH +C "egzefffgzbcdij" "*(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH +C "egz" "@(b+(c)d|e+(f)g?|?(h)i@(j|k))" NOMATCH EXTMATCH +C "ofoofo" "*(of+(o))" 0 EXTMATCH +C "oxfoxoxfox" "*(oxf+(ox))" 0 EXTMATCH +C "oxfoxfox" "*(oxf+(ox))" NOMATCH EXTMATCH +C "ofoofo" "*(of+(o)|f)" 0 EXTMATCH +C "foofoofo" "@(foo|f|fo)*(f|of+(o))" 0 EXTMATCH +C "oofooofo" "*(of|oof+(o))" 0 EXTMATCH +C "fffooofoooooffoofffooofff" "*(*(f)*(o))" 0 EXTMATCH +C "fofoofoofofoo" "*(fo|foo)" 0 EXTMATCH +C "foo" "!(x)" 0 EXTMATCH +C "foo" "!(x)*" 0 EXTMATCH +C "foo" "!(foo)" NOMATCH EXTMATCH +C "foo" "!(foo)*" 0 EXTMATCH +C "foobar" "!(foo)" 0 EXTMATCH +C "foobar" "!(foo)*" 0 EXTMATCH +C "moo.cow" "!(*.*).!(*.*)" 0 EXTMATCH +C "mad.moo.cow" "!(*.*).!(*.*)" NOMATCH EXTMATCH +C "mucca.pazza" "mu!(*(c))?.pa!(*(z))?" NOMATCH EXTMATCH +C "fff" "!(f)" 0 EXTMATCH +C "fff" "*(!(f))" 0 EXTMATCH +C "fff" "+(!(f))" 0 EXTMATCH +C "ooo" "!(f)" 0 EXTMATCH +C "ooo" "*(!(f))" 0 EXTMATCH +C "ooo" "+(!(f))" 0 EXTMATCH +C "foo" "!(f)" 0 EXTMATCH +C "foo" "*(!(f))" 0 EXTMATCH +C "foo" "+(!(f))" 0 EXTMATCH +C "f" "!(f)" NOMATCH EXTMATCH +C "f" "*(!(f))" NOMATCH EXTMATCH +C "f" "+(!(f))" NOMATCH EXTMATCH +C "foot" "@(!(z*)|*x)" 0 EXTMATCH +C "zoot" "@(!(z*)|*x)" NOMATCH EXTMATCH +C "foox" "@(!(z*)|*x)" 0 EXTMATCH +C "zoox" "@(!(z*)|*x)" 0 EXTMATCH +C "foo" "*(!(foo)) 0 EXTMATCH +C "foob" "!(foo)b*" NOMATCH EXTMATCH +C "foobb" "!(foo)b*" 0 EXTMATCH +C "[" "*([a[])" 0 EXTMATCH +C "]" "*([]a[])" 0 EXTMATCH +C "a" "*([]a[])" 0 EXTMATCH +C "b" "*([!]a[])" 0 EXTMATCH +C "[" "*([!]a[]|[[])" 0 EXTMATCH +C "]" "*([!]a[]|[]])" 0 EXTMATCH +C "[" "!([!]a[])" 0 EXTMATCH +C "]" "!([!]a[])" 0 EXTMATCH +C ")" "*([)])" 0 EXTMATCH +C "*" "*([*(])" 0 EXTMATCH +C "abcd" "*!(|a)cd" 0 EXTMATCH +C "ab/.a" "+([abc])/*" NOMATCH EXTMATCH|PATHNAME|PERIOD +C "" "" 0 +C "" "" 0 EXTMATCH +C "" "*([abc])" 0 EXTMATCH +C "" "?([abc])" 0 EXTMATCH diff --git a/test/misc/tst-gnuglob.c b/test/misc/tst-gnuglob.c new file mode 100644 index 0000000..04c6743 --- /dev/null +++ b/test/misc/tst-gnuglob.c @@ -0,0 +1,447 @@ +/* Test the GNU extensions in glob which allow the user to provide callbacks + for the filesystem access functions. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +// #define DEBUG +#ifdef DEBUG +# define PRINTF(fmt, args...) printf (fmt, ##args) +#else +# define PRINTF(fmt, args...) +#endif + + +#ifdef GLOB_ALTDIRFUNC +static struct +{ + const char *name; + int level; + int type; +} filesystem[] = +{ + { ".", 1, DT_DIR }, + { "..", 1, DT_DIR }, + { "file1lev1", 1, DT_REG }, + { "file2lev1", 1, DT_UNKNOWN }, + { "dir1lev1", 1, DT_UNKNOWN }, + { ".", 2, DT_DIR }, + { "..", 2, DT_DIR }, + { "file1lev2", 2, DT_REG }, + { "dir1lev2", 2, DT_DIR }, + { ".", 3, DT_DIR }, + { "..", 3, DT_DIR }, + { "dir2lev2", 2, DT_DIR }, + { ".", 3, DT_DIR }, + { "..", 3, DT_DIR }, + { ".foo", 3, DT_REG }, + { "dir1lev3", 3, DT_DIR }, + { ".", 4, DT_DIR }, + { "..", 4, DT_DIR }, + { "file1lev4", 4, DT_REG }, + { "file1lev3", 3, DT_REG }, + { "file2lev3", 3, DT_REG }, + { "file2lev2", 2, DT_REG }, + { "file3lev2", 2, DT_REG }, + { "dir3lev2", 2, DT_DIR }, + { ".", 3, DT_DIR }, + { "..", 3, DT_DIR }, + { "file3lev3", 3, DT_REG }, + { "file4lev3", 3, DT_REG }, + { "dir2lev1", 1, DT_DIR }, + { ".", 2, DT_DIR }, + { "..", 2, DT_DIR }, + { "dir1lev2", 2, DT_UNKNOWN }, + { ".", 3, DT_DIR }, + { "..", 3, DT_DIR }, + { ".foo", 3, DT_REG }, + { ".dir", 3, DT_DIR }, + { ".", 4, DT_DIR }, + { "..", 4, DT_DIR }, + { "hidden", 4, DT_REG } +}; +#define nfiles (sizeof (filesystem) / sizeof (filesystem[0])) + + +typedef struct +{ + int level; + int idx; + struct dirent d; + char room_for_dirent[NAME_MAX]; +} my_DIR; + + +static long int +find_file (const char *s) +{ + int level = 1; + long int idx = 0; + + if (strcmp (s, ".") == 0) + return 0; + + if (s[0] == '.' && s[1] == '/') + s += 2; + + while (*s != '\0') + { + char *endp = strchrnul (s, '/'); + + PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level); + + while (idx < nfiles && filesystem[idx].level >= level) + { + if (filesystem[idx].level == level + && memcmp (s, filesystem[idx].name, endp - s) == 0 + && filesystem[idx].name[endp - s] == '\0') + break; + ++idx; + } + + if (idx == nfiles || filesystem[idx].level < level) + { + errno = ENOENT; + return -1; + } + + if (*endp == '\0') + return idx + 1; + + if (filesystem[idx].type != DT_DIR + && (idx + 1 >= nfiles + || filesystem[idx].level >= filesystem[idx + 1].level)) + { + errno = ENOTDIR; + return -1; + } + + ++idx; + + s = endp + 1; + ++level; + } + + errno = ENOENT; + return -1; +} + + +static void * +my_opendir (const char *s) +{ + long int idx = find_file (s); + my_DIR *dir; + + + if (idx == -1) + { + PRINTF ("my_opendir(\"%s\") == NULL\n", s); + return NULL; + } + + dir = (my_DIR *) malloc (sizeof (my_DIR)); + if (dir == NULL) + error (EXIT_FAILURE, errno, "cannot allocate directory handle"); + + dir->level = filesystem[idx].level; + dir->idx = idx; + + PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n", + s, filesystem[idx].level, idx); + + return dir; +} + + +static struct dirent * +my_readdir (void *gdir) +{ + my_DIR *dir = gdir; + + if (dir->idx == -1) + { + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n", + dir->level, (long int) dir->idx); + return NULL; + } + + while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level) + ++dir->idx; + + if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level) + { + dir->idx = -1; + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n", + dir->level, (long int) dir->idx); + return NULL; + } + + dir->d.d_ino = dir->idx; + +#ifdef _DIRENT_HAVE_D_TYPE + dir->d.d_type = filesystem[dir->idx].type; +#endif + + strcpy (dir->d.d_name, filesystem[dir->idx].name); + +#ifdef _DIRENT_HAVE_D_TYPE + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n", + dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type, + dir->d.d_name); +#else + PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n", + dir->level, (long int) dir->idx, dir->d.d_ino, + dir->d.d_name); +#endif + + ++dir->idx; + + return &dir->d; +} + + +static void +my_closedir (void *dir) +{ + PRINTF ("my_closedir ()\n"); + free (dir); +} + + +/* We use this function for lstat as well since we don't have any. */ +static int +my_stat (const char *name, struct stat *st) +{ + long int idx = find_file (name); + + if (idx == -1) + { + PRINTF ("my_stat (\"%s\", ...) = -1 (%s)\n", name, strerror (errno)); + return -1; + } + + memset (st, '\0', sizeof (*st)); + + if (filesystem[idx].type == DT_UNKNOWN) + st->st_mode = DTTOIF (idx + 1 < nfiles + && filesystem[idx].level < filesystem[idx + 1].level + ? DT_DIR : DT_REG) | 0777; + else + st->st_mode = DTTOIF (filesystem[idx].type) | 0777; + + PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode); + + return 0; +} + + +static const char *glob_errstring[] = +{ + [GLOB_NOSPACE] = "out of memory", + [GLOB_ABORTED] = "read error", + [GLOB_NOMATCH] = "no matches found" +}; +#define nglob_errstring (sizeof (glob_errstring) / sizeof (glob_errstring[0])) + + +static const char * +flagstr (int flags) +{ + const char *strs[] = + { + "GLOB_ERR", "GLOB_MARK", "GLOB_NOSORT", "GLOB_DOOFSS", "GLOB_NOCHECK", + "GLOB_APPEND", "GLOB_NOESCAPE", "GLOB_PERIOD", "GLOB_MAGCHAR", + "GLOB_ALTDIRFUNC", "GLOB_BRACE", "GLOB_NOMAGIC", "GLOB_TILDE", + "GLOB_ONLYDIR", "GLOB_TILDECHECK" + }; +#define nstrs (sizeof (strs) / sizeof (strs[0])) + static char buf[100]; + char *cp = buf; + int cnt; + + for (cnt = 0; cnt < nstrs; ++cnt) + if (flags & (1 << cnt)) + { + flags &= ~(1 << cnt); + if (cp != buf) + *cp++ = '|'; + cp = stpcpy (cp, strs[cnt]); + } + + if (flags != 0) + { + if (cp != buf) + *cp++ = '|'; + sprintf (cp, "%#x", flags); + } + + return buf; +} + + +static int +test_result (const char *fmt, int flags, glob_t *gl, const char *str[]) +{ + size_t cnt; + int result = 0; + + printf ("results for glob (\"%s\", %s)\n", fmt, flagstr (flags)); + for (cnt = 0; cnt < gl->gl_pathc && str[cnt] != NULL; ++cnt) + { + int ok = strcmp (gl->gl_pathv[cnt], str[cnt]) == 0; + const char *errstr = ""; + + if (! ok) + { + size_t inner; + + for (inner = 0; str[inner] != NULL; ++inner) + if (strcmp (gl->gl_pathv[cnt], str[inner]) == 0) + break; + + if (str[inner] == NULL) + errstr = ok ? "" : " *** WRONG"; + else + errstr = ok ? "" : " * wrong position"; + + result = 1; + } + + printf (" %s%s\n", gl->gl_pathv[cnt], errstr); + } + puts (""); + + if (str[cnt] != NULL || cnt < gl->gl_pathc) + { + puts (" *** incorrect number of entries"); + result = 1; + } + + return result; +} + + +int +main (void) +{ + glob_t gl; + int errval; + int result = 0; + const char *fmt; + int flags; + + memset (&gl, '\0', sizeof (gl)); + + gl.gl_closedir = my_closedir; + gl.gl_readdir = my_readdir; + gl.gl_opendir = my_opendir; + gl.gl_lstat = my_stat; + gl.gl_stat = my_stat; + +#define test(a, b, c...) \ + fmt = a; \ + flags = b; \ + errval = glob (fmt, flags, NULL, &gl); \ + if (errval != 0) \ + { \ + printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags), \ + errval >= 0 && errval < nglob_errstring \ + ? glob_errstring[errval] : "???"); \ + result = 1; \ + } \ + else \ + result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL }) + + test ("*/*/*", GLOB_ALTDIRFUNC, + "dir1lev1/dir2lev2/dir1lev3", + "dir1lev1/dir2lev2/file1lev3", + "dir1lev1/dir2lev2/file2lev3", + "dir1lev1/dir3lev2/file3lev3", + "dir1lev1/dir3lev2/file4lev3"); + + test ("*/*/*", GLOB_ALTDIRFUNC | GLOB_PERIOD, + "dir1lev1/dir1lev2/.", + "dir1lev1/dir1lev2/..", + "dir1lev1/dir2lev2/.", + "dir1lev1/dir2lev2/..", + "dir1lev1/dir2lev2/.foo", + "dir1lev1/dir2lev2/dir1lev3", + "dir1lev1/dir2lev2/file1lev3", + "dir1lev1/dir2lev2/file2lev3", + "dir1lev1/dir3lev2/.", + "dir1lev1/dir3lev2/..", + "dir1lev1/dir3lev2/file3lev3", + "dir1lev1/dir3lev2/file4lev3", + "dir2lev1/dir1lev2/.", + "dir2lev1/dir1lev2/..", + "dir2lev1/dir1lev2/.dir", + "dir2lev1/dir1lev2/.foo"); + + test ("*/*/.*", GLOB_ALTDIRFUNC, + "dir1lev1/dir1lev2/.", + "dir1lev1/dir1lev2/..", + "dir1lev1/dir2lev2/.", + "dir1lev1/dir2lev2/..", + "dir1lev1/dir2lev2/.foo", + "dir1lev1/dir3lev2/.", + "dir1lev1/dir3lev2/..", + "dir2lev1/dir1lev2/.", + "dir2lev1/dir1lev2/..", + "dir2lev1/dir1lev2/.dir", + "dir2lev1/dir1lev2/.foo"); + + test ("*1*/*2*/.*", GLOB_ALTDIRFUNC, + "dir1lev1/dir1lev2/.", + "dir1lev1/dir1lev2/..", + "dir1lev1/dir2lev2/.", + "dir1lev1/dir2lev2/..", + "dir1lev1/dir2lev2/.foo", + "dir1lev1/dir3lev2/.", + "dir1lev1/dir3lev2/..", + "dir2lev1/dir1lev2/.", + "dir2lev1/dir1lev2/..", + "dir2lev1/dir1lev2/.dir", + "dir2lev1/dir1lev2/.foo"); + + test ("*1*/*1*/.*", GLOB_ALTDIRFUNC, + "dir1lev1/dir1lev2/.", + "dir1lev1/dir1lev2/..", + "dir2lev1/dir1lev2/.", + "dir2lev1/dir1lev2/..", + "dir2lev1/dir1lev2/.dir", + "dir2lev1/dir1lev2/.foo"); + + globfree (&gl); + + return result; +} + +#else +int main(void) { return 0; } +#endif diff --git a/test/misc/tst-scandir.c b/test/misc/tst-scandir.c new file mode 100644 index 0000000..df62a40 --- /dev/null +++ b/test/misc/tst-scandir.c @@ -0,0 +1,23 @@ +#include +#include +#include /* perror() */ +#include + +int skip_all(const struct dirent *dirbuf) +{ + errno = EBADF; + return 0; +} + +int main(void) +{ + struct dirent **namelist; + int n; + + n = scandir(".", &namelist, skip_all, 0); + if (n < 0) { + perror("scandir"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/test/misc/tst-seekdir.c b/test/misc/tst-seekdir.c new file mode 100644 index 0000000..7dd5d2e --- /dev/null +++ b/test/misc/tst-seekdir.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + DIR * dirp; + long int save3 = 0; + long int cur; + int i = 0; + int result = 0; + struct dirent *dp; + off_t save0, rewind_ret; + + dirp = opendir ("."); + if (dirp == NULL) + { + printf ("opendir failed: %s\n", strerror(errno)); + return 1; + } + + save0 = telldir (dirp); + if (save0 == -1) + { + printf ("telldir failed: %s\n", strerror(errno)); + result = 1; + } + + for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp)) + { + /* save position 3 (after fourth entry) */ + if (i++ == 3) + save3 = telldir (dirp); + + printf ("%s\n", dp->d_name); + + /* stop at 400 (just to make sure dirp->__offset and dirp->__size are + scrambled */ + if (i == 400) + break; + } + + printf ("going back past 4-th entry...\n"); + + /* go back to saved entry */ + seekdir (dirp, save3); + + /* Check whether telldir equals to save3 now. */ + cur = telldir (dirp); + if (cur != save3) + { + printf ("seekdir (d, %ld); telldir (d) == %ld\n", save3, cur); + result = 1; + } + + /* print remaining files (3-last) */ + for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp)) + printf ("%s\n", dp->d_name); + + /* Check rewinddir */ + rewinddir (dirp); + rewind_ret = telldir (dirp); + if (rewind_ret == -1) + { + printf ("telldir failed: %s\n", strerror(errno)); + result = 1; + } + else if (save0 != rewind_ret) + { + printf ("rewinddir didn't reset directory stream\n"); + result = 1; + } + + closedir (dirp); + return result; +} diff --git a/test/misc/tst-utmp.c b/test/misc/tst-utmp.c new file mode 100644 index 0000000..12a2088 --- /dev/null +++ b/test/misc/tst-utmp.c @@ -0,0 +1,404 @@ +/* Tests for UTMP functions. + Copyright (C) 1998, 2001-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#ifdef UTMPX +# include +# define utmp utmpx +# define utmpname utmpxname +# define setutent setutxent +# define getutent getutxent +# define endutent endutxent +# define getutline getutxline +# define getutid getutxid +# define pututline pututxline +#else +# include +#endif + + +#if _HAVE_UT_TYPE || defined UTMPX + +/* Prototype for our test function. */ +static int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +static void do_prepare (int argc, char *argv[]); +#define PREPARE do_prepare + +/* This defines the `main' function and some more. */ +#include + + +/* These are for the temporary file we generate. */ +char *name; +int fd; + +static void +do_prepare (int argc, char *argv[]) +{ + size_t name_len; + + name_len = strlen (test_dir); + name = malloc (name_len + sizeof ("/utmpXXXXXX")); + mempcpy (mempcpy (name, test_dir, name_len), + "/utmpXXXXXX", sizeof ("/utmpXXXXXX")); + add_temp_file (name); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); +} + +struct utmp entry[] = +{ +#if _HAVE_UT_TV || defined UTMPX +#define UT(a) .ut_tv = { .tv_sec = (a)} +#else +#define UT(a) .ut_time = (a) +#endif + + { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) }, + { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) }, + { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) }, + { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1", + .ut_user = "LOGIN", UT(4000) }, + { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2", + .ut_user = "albert", UT(8000) }, + { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0", + .ut_user = "niels", UT(10000) }, + { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) }, + { .ut_type = EMPTY }, + { .ut_type = EMPTY } +}; +int num_entries = sizeof entry / sizeof (struct utmp); + +time_t entry_time = 20000; +pid_t entry_pid = 234; + +static int +do_init (void) +{ + int n; + + setutent (); + + for (n = 0; n < num_entries; n++) + { + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + } + + endutent (); + + return 0; +} + + +static int +do_check (void) +{ + struct utmp *ut; + int n; + + setutent (); + + n = 0; + while ((ut = getutent ())) + { + if (n < num_entries && + memcmp (ut, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + n++; + } + + if (n != num_entries) + { + error (0, 0, "number of UTMP entries is incorrect"); + return 1; + } + + endutent (); + + return 0; +} + +static int +simulate_login (const char *line, const char *user) +{ + int n; + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0 || + entry[n].ut_type == DEAD_PROCESS) + { + if (entry[n].ut_pid == DEAD_PROCESS) + entry[n].ut_pid = (entry_pid += 27); + entry[n].ut_type = USER_PROCESS; + strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user)); +#if _HAVE_UT_TV - 0 || defined UTMPX + entry[n].ut_tv.tv_sec = (entry_time += 1000); +#else + entry[n].ut_time = (entry_time += 1000); +#endif + setutent (); + + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + + endutent (); + + return 0; + } + } + + error (0, 0, "no entries available"); + return 1; +} + +static int +simulate_logout (const char *line) +{ + int n; + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0) + { + entry[n].ut_type = DEAD_PROCESS; + strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); +#if _HAVE_UT_TV - 0 || defined UTMPX + entry[n].ut_tv.tv_sec = (entry_time += 1000); +#else + entry[n].ut_time = (entry_time += 1000); +#endif + setutent (); + + if (pututline (&entry[n]) == NULL) + { + error (0, errno, "cannot write UTMP entry"); + return 1; + } + + endutent (); + + return 0; + } + } + + error (0, 0, "no entry found for `%s'", line); + return 1; +} + +static int +check_login (const char *line) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + strcpy (ut.ut_line, line); + up = getutline (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for line `%s'", line); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (strcmp (line, entry[n].ut_line) == 0) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for line `%s'", line); + return 1; +} + +static int +check_logout (const char *line) +{ + struct utmp ut; + + setutent (); + + strcpy (ut.ut_line, line); + if (getutline (&ut) != NULL) + { + error (0, 0, "bogus login entry for `%s'", line); + return 1; + } + + endutent (); + + return 0; +} + +static int +check_id (const char *id) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + ut.ut_type = USER_PROCESS; + strcpy (ut.ut_id, id); + up = getutid (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for ID `%s'", id); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (strcmp (id, entry[n].ut_id) == 0) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for ID `%s'", id); + return 1; +} + +static int +check_type (int type) +{ + struct utmp *up; + struct utmp ut; + int n; + + setutent (); + + ut.ut_type = type; + up = getutid (&ut); + if (up == NULL) + { + error (0, errno, "cannot get entry for type `%d'", type); + return 1; + } + + endutent (); + + for (n = 0; n < num_entries; n++) + { + if (type == entry[n].ut_type) + { + if (memcmp (up, &entry[n], sizeof (struct utmp))) + { + error (0, 0, "UTMP entry does not match"); + return 1; + } + + return 0; + } + } + + error (0, 0, "bogus entry for type `%d'", type); + return 1; +} + +static int +do_test (int argc, char *argv[]) +{ + int result = 0; + + utmpname (name); + + result |= do_init (); + result |= do_check (); + + result |= simulate_login ("tty1", "erwin"); + result |= do_check (); + + result |= simulate_login ("ttyp1", "paul"); + result |= do_check (); + + result |= simulate_logout ("tty2"); + result |= do_check (); + + result |= simulate_logout ("ttyp0"); + result |= do_check (); + + result |= simulate_login ("ttyp2", "richard"); + result |= do_check (); + + result |= check_login ("tty1"); + result |= check_logout ("ttyp0"); + result |= check_id ("p1"); + result |= check_id ("2"); + result |= check_id ("si"); + result |= check_type (BOOT_TIME); + result |= check_type (RUN_LVL); + + return result; +} + +#else + +/* No field 'ut_type' in struct utmp. */ +int +main () +{ + return 0; +} + +#endif diff --git a/test/mmap/Makefile b/test/mmap/Makefile new file mode 100644 index 0000000..b4c3010 --- /dev/null +++ b/test/mmap/Makefile @@ -0,0 +1,4 @@ +# uClibc mmap tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak diff --git a/test/mmap/mmap.c b/test/mmap/mmap.c new file mode 100644 index 0000000..8b29737 --- /dev/null +++ b/test/mmap/mmap.c @@ -0,0 +1,73 @@ + +/* The mmap test is useful, since syscalls with 6 arguments + * (as mmap) are done differently on various architectures. + */ + +#include +#include +#include +#include +#include +#include + +#define SIZEOF_ARRAY(type) (sizeof(type)/sizeof(*type)) + +struct mmap_test { + void *ret; + int err; + struct { + void *start; + size_t length; + int prot; + int flags; + int fd; + off_t offset; + } args; +}; + +struct mmap_test tests[] = { + [0] { + .err = 0, + .args.start = NULL, + .args.length = 4096, + .args.prot = PROT_READ|PROT_WRITE, + .args.flags = MAP_PRIVATE|MAP_ANONYMOUS, + .args.fd = 0, + .args.offset = 0 + }, +}; + +#define err(fmt, args...) \ + do { \ + fprintf(stderr, fmt "\n" , ## args); \ + exit(1); \ + } while (0) +#define errp(fmt, args...) err(fmt ": %s" , ## args , strerror(errno)) + +int main(int argc, char **argv) +{ + int i; + struct mmap_test *t; + + for (i=0; iret = mmap(t->args.start, t->args.length, t->args.prot, + t->args.flags, t->args.fd, t->args.offset); + + if (t->err) { + if (t->ret != MAP_FAILED) + err("mmap test %i should have failed, but gave us %p", i, t->ret); + else if (t->err != errno) + errp("mmap test %i failed, but gave us wrong errno (got %i instead of %i)", i, errno, t->err); + } else { + if (t->ret == MAP_FAILED) + errp("mmap test %i failed", i); + else if (munmap(t->ret, t->args.length) != 0) + errp("munmap test %i failed", i); + } + } + + exit(0); +} diff --git a/test/mmap/mmap2.c b/test/mmap/mmap2.c new file mode 100644 index 0000000..b9a8f9a --- /dev/null +++ b/test/mmap/mmap2.c @@ -0,0 +1,41 @@ +/* When trying to map /dev/mem with offset 0xFFFFF000 on the ARM platform, mmap + * returns -EOVERFLOW. + * + * Since off_t is defined as a long int and the sign bit is set in the address, + * the shift operation shifts in ones instead of zeroes + * from the left. This results the offset sent to the kernel function becomes + * 0xFFFFFFFF instead of 0x000FFFFF with MMAP2_PAGE_SHIFT set to 12. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ + __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) + +#define MAP_SIZE 4096UL +#define MAP_MASK (MAP_SIZE - 1) + +int main(int argc, char **argv) { + void* map_base = 0; + int fd; + off_t target = 0xfffff000; + if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; + printf("/dev/mem opened.\n"); + fflush(stdout); + + /* Map one page */ + map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, target & ~MAP_MASK); + if(map_base == (void *) -1) FATAL; + printf("Memory mapped at address %p.\n", map_base); + fflush(stdout); + if(munmap(map_base, MAP_SIZE) == -1) FATAL; + close(fd); + return 0; +} diff --git a/test/mmap/mmap64.c b/test/mmap/mmap64.c new file mode 100644 index 0000000..87165fe --- /dev/null +++ b/test/mmap/mmap64.c @@ -0,0 +1,29 @@ + +/* The mmap test is useful, since syscalls with 6 arguments + * (as mmap) are done differently on various architectures. + */ + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ +#ifdef __UCLIBC_HAS_LFS__ + void *ptr; + + ptr = mmap64(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + + if (ptr == MAP_FAILED) { + perror("mmap"); + exit(1); + } + printf("mmap returned %p\n", ptr); + exit(0); +#else + exit(0); +#endif +} diff --git a/test/pthread/Makefile b/test/pthread/Makefile new file mode 100644 index 0000000..ef924ad --- /dev/null +++ b/test/pthread/Makefile @@ -0,0 +1,8 @@ +# uClibc pthread tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +EXTRA_LDFLAGS := -lpthread + +LDFLAGS_cancellation-points := -lrt diff --git a/test/pthread/cancellation-points.c b/test/pthread/cancellation-points.c new file mode 100644 index 0000000..3fe49fc --- /dev/null +++ b/test/pthread/cancellation-points.c @@ -0,0 +1,280 @@ +/* + * Make sure functions marked as cancellation points actually are. + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_05 + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* take care of optional things ... */ +#define STUB(func, args) static void func args { sleep(0); } +#if !defined(__UCLIBC__) || defined(__UCLIBC_AIO__) +# include +#else +STUB(aio_suspend, (void *p, int n, const void *p2)) +#endif +#if !defined(__UCLIBC__) || defined(__UCLIBC_STROPTS__) +# include +#else +STUB(getmsg, (int f, void *p, void *p2, void *p3)) +STUB(getpmsg, (int f, void *p, void *p2, void *p3, void *p4)) +STUB(putmsg, (int f, void *p, void *p2, void *p3)) +STUB(putpmsg, (int f, void *p, void *p2, void *p3, void *p4)) +#endif +#if defined(__UCLIBC__) +STUB(clock_nanosleep, (int i, int f, const void *p, void *p2)) +#endif + +int cnt; +bool ready; + +void cancel_timeout(int sig) +{ + ready = false; +} +void cancel_thread_cleanup(void *arg) +{ + ready = false; +} + +/* some funcs need some help as they wont take NULL args ... */ +const struct timespec zero_sec = { .tv_sec = 0, .tv_nsec = 0 }; + +sem_t sem; +void help_sem_setup(void) +{ + if (sem_init(&sem, 0, 1) == -1) { + perror("sem_init() failed"); + exit(-1); + } +} + +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +pthread_mutex_t mutex; +void help_pthread_setup(void) +{ + pthread_mutex_init(&mutex, NULL); + pthread_mutex_lock(&mutex); +} + +/* the pthread function that will call the cancellable function over and over */ +#define _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, setup) \ +void *cancel_thread_##func(void *arg) \ +{ \ + if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) { \ + perror("unable to set cancel type to deferred; something is seriously broken"); \ + exit(-1); \ + } \ + pthread_cleanup_push(cancel_thread_cleanup, NULL); \ + setup; \ + ready = true; \ + while (ready) \ + sysfunc args; \ + pthread_cleanup_pop(1); \ + return NULL; \ +} +#define MAKE_CANCEL_THREAD_FUNC_RE(func, sysfunc, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, (void)0) +#define MAKE_CANCEL_THREAD_FUNC_EX(func, args, setup) _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, setup) +#define MAKE_CANCEL_THREAD_FUNC(func, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, (void)0) + +MAKE_CANCEL_THREAD_FUNC(accept, (-1, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(aio_suspend, (NULL, 0, &zero_sec)) +MAKE_CANCEL_THREAD_FUNC(clock_nanosleep, (0, 0, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(close, (-1)) +MAKE_CANCEL_THREAD_FUNC(connect, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(creat, ("", 0)) +MAKE_CANCEL_THREAD_FUNC(fcntl, (0, F_SETLKW, NULL)) +MAKE_CANCEL_THREAD_FUNC(fdatasync, (-1)) +MAKE_CANCEL_THREAD_FUNC(fsync, (0)) +MAKE_CANCEL_THREAD_FUNC(getmsg, (-1, NULL, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(getpmsg, (-1, NULL, NULL, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(lockf, (-1, F_TEST, 0)) +MAKE_CANCEL_THREAD_FUNC(mq_receive, (0, NULL, 0, NULL)) +MAKE_CANCEL_THREAD_FUNC(mq_send, (0, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(mq_timedreceive, (0, NULL, 0, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(mq_timedsend, (0, NULL, 0, 0, NULL)) +MAKE_CANCEL_THREAD_FUNC(msgrcv, (-1, NULL, 0, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(msgsnd, (-1, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(msync, (NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(nanosleep, (NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(open, ("", 0)) +MAKE_CANCEL_THREAD_FUNC(pause, ()) +MAKE_CANCEL_THREAD_FUNC(poll, (NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(pread, (-1, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(pselect, (0, NULL, NULL, NULL, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_timedwait, (&cond, &mutex, &zero_sec), help_pthread_setup()) +MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_wait, (&cond, &mutex), help_pthread_setup()) +/*MAKE_CANCEL_THREAD_FUNC_EX(pthread_join, (0, NULL))*/ +MAKE_CANCEL_THREAD_FUNC(pthread_testcancel, ()) +MAKE_CANCEL_THREAD_FUNC(putmsg, (-1, NULL, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(putpmsg, (-1, NULL, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(pwrite, (-1, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(read, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(readv, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(recv, (-1, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(recvfrom, (-1, NULL, 0, 0, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(recvmsg, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(select, (0, NULL, NULL, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC_EX(sem_timedwait, (&sem, &zero_sec), help_sem_setup()) +MAKE_CANCEL_THREAD_FUNC_EX(sem_wait, (&sem), help_sem_setup()) +MAKE_CANCEL_THREAD_FUNC(send, (-1, NULL, 0, 0)) +MAKE_CANCEL_THREAD_FUNC(sendmsg, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(sendto, (-1, NULL, 0, 0, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(sigpause, (0)) +MAKE_CANCEL_THREAD_FUNC(sigsuspend, (NULL)) +MAKE_CANCEL_THREAD_FUNC(sigtimedwait, (NULL, NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(sigwait, (NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(sigwaitinfo, (NULL, NULL)) +MAKE_CANCEL_THREAD_FUNC(sleep, (0)) +MAKE_CANCEL_THREAD_FUNC(system, ("")) +MAKE_CANCEL_THREAD_FUNC(tcdrain, (-1)) +MAKE_CANCEL_THREAD_FUNC(usleep, (0)) +MAKE_CANCEL_THREAD_FUNC(wait, (NULL)) +MAKE_CANCEL_THREAD_FUNC(waitid, (0, 0, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(waitpid, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(write, (-1, NULL, 0)) +MAKE_CANCEL_THREAD_FUNC(writev, (-1, NULL, 0)) + +/* test a few variations that should not cancel ... */ +MAKE_CANCEL_THREAD_FUNC_RE(fcntl_another, fcntl, (0, F_GETFD)) + +/* main test that creates thread, cancels it, etc... */ +int _test_func(const char *func_name, void *(*func)(void*), const int should_cancel) +{ + int ret; + pthread_t cancel_thread_id; + + ++cnt; + + printf("testing %-30s ", func_name); + + printf("."); + if (signal(SIGALRM, cancel_timeout) == SIG_ERR) { + perror("unable to bind SIGALRM"); + exit(-1); + } + + printf("."); + ready = false; + pthread_create(&cancel_thread_id, NULL, func, NULL); + + printf("."); + while (!ready) + sched_yield(); + + printf("."); + if (pthread_cancel(cancel_thread_id)) { + perror("unable to cancel thread"); + exit(-1); + } + + printf("."); + alarm(5); + while (ready) + sched_yield(); + + printf("."); + ret = (!!!alarm(0) == should_cancel); + + if (ret) + printf(" failed ;(\n"); + else + printf(" OK!\n"); + + return ret; +} +#define TEST_FUNC(f) _test_func(#f, cancel_thread_##f, 1) +#define TEST_FUNC_RE(f) _test_func(#f, cancel_thread_##f, 0) + +int main(int argc, char *argv[]) +{ + int ret = 0; + setbuf(stdout, NULL); + cnt = 0; + + ret += TEST_FUNC(accept); + ret += TEST_FUNC(aio_suspend); + ret += TEST_FUNC(clock_nanosleep); + ret += TEST_FUNC(close); + ret += TEST_FUNC(connect); + ret += TEST_FUNC(creat); + ret += TEST_FUNC(fcntl); + ret += TEST_FUNC(fdatasync); + ret += TEST_FUNC(fsync); + ret += TEST_FUNC(getmsg); + ret += TEST_FUNC(getpmsg); + ret += TEST_FUNC(lockf); + ret += TEST_FUNC(mq_receive); + ret += TEST_FUNC(mq_send); + ret += TEST_FUNC(mq_timedreceive); + ret += TEST_FUNC(mq_timedsend); + ret += TEST_FUNC(msgrcv); + ret += TEST_FUNC(msgsnd); + ret += TEST_FUNC(msync); + ret += TEST_FUNC(nanosleep); + ret += TEST_FUNC(open); + ret += TEST_FUNC(pause); + ret += TEST_FUNC(poll); + ret += TEST_FUNC(pread); + ret += TEST_FUNC(pselect); + ret += TEST_FUNC(pthread_cond_timedwait); + ret += TEST_FUNC(pthread_cond_wait); + /*ret += TEST_FUNC(pthread_join);*/ + ret += TEST_FUNC(pthread_testcancel); + ret += TEST_FUNC(putmsg); + ret += TEST_FUNC(putpmsg); + ret += TEST_FUNC(pwrite); + ret += TEST_FUNC(read); + ret += TEST_FUNC(readv); + ret += TEST_FUNC(recv); + ret += TEST_FUNC(recvfrom); + ret += TEST_FUNC(recvmsg); + ret += TEST_FUNC(select); + ret += TEST_FUNC(sem_timedwait); + ret += TEST_FUNC(sem_wait); + ret += TEST_FUNC(send); + ret += TEST_FUNC(sendmsg); + ret += TEST_FUNC(sendto); + ret += TEST_FUNC(sigpause); + ret += TEST_FUNC(sigsuspend); + ret += TEST_FUNC(sigtimedwait); + ret += TEST_FUNC(sigwait); + ret += TEST_FUNC(sigwaitinfo); + ret += TEST_FUNC(sleep); + ret += TEST_FUNC(system); + ret += TEST_FUNC(tcdrain); + ret += TEST_FUNC(usleep); + ret += TEST_FUNC(wait); + ret += TEST_FUNC(waitid); + ret += TEST_FUNC(waitpid); + ret += TEST_FUNC(write); + ret += TEST_FUNC(writev); + + ret += TEST_FUNC_RE(fcntl_another); + + if (ret) + printf("!!! %i / %i tests failed\n", ret, cnt); + + return ret; +} diff --git a/test/pthread/ex1.c b/test/pthread/ex1.c new file mode 100644 index 0000000..4d9de03 --- /dev/null +++ b/test/pthread/ex1.c @@ -0,0 +1,35 @@ +/* Creates two threads, one printing 10000 "a"s, the other printing + 10000 "b"s. + Illustrates: thread creation, thread joining. */ + +#include +#include +#include +#include "pthread.h" + +static void *process(void * arg) +{ + int i; + printf("Starting process %s\n", (char *)arg); + for (i = 0; i < 10000; i++) + write(1, (char *) arg, 1); + return NULL; +} + +#define sucfail(r) (r != 0 ? "failed" : "succeeded") +int main(void) +{ + int pret, ret = 0; + pthread_t th_a, th_b; + void *retval; + + ret += (pret = pthread_create(&th_a, NULL, process, (void *)"a")); + printf("create a %s %d\n", sucfail(pret), pret); + ret += (pret = pthread_create(&th_b, NULL, process, (void *)"b")); + printf("create b %s %d\n", sucfail(pret), pret); + ret += (pret = pthread_join(th_a, &retval)); + printf("join a %s %d\n", sucfail(pret), pret); + ret += (pret = pthread_join(th_b, &retval)); + printf("join b %s %d\n", sucfail(pret), pret); + return ret; +} diff --git a/test/pthread/ex2.c b/test/pthread/ex2.c new file mode 100644 index 0000000..98bd4b3 --- /dev/null +++ b/test/pthread/ex2.c @@ -0,0 +1,113 @@ +/* The classic producer-consumer example. + Illustrates mutexes and conditions. + All integers between 0 and 9999 should be printed exactly twice, + once to the right of the arrow and once to the left. */ + +#include +#include "pthread.h" + +#define BUFFER_SIZE 16 + +/* Circular buffer of integers. */ + +struct prodcons { + int buffer[BUFFER_SIZE]; /* the actual data */ + pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */ + int readpos, writepos; /* positions for reading and writing */ + pthread_cond_t notempty; /* signaled when buffer is not empty */ + pthread_cond_t notfull; /* signaled when buffer is not full */ +}; + +/* Initialize a buffer */ + +static void init(struct prodcons * b) +{ + pthread_mutex_init(&b->lock, NULL); + pthread_cond_init(&b->notempty, NULL); + pthread_cond_init(&b->notfull, NULL); + b->readpos = 0; + b->writepos = 0; +} + +/* Store an integer in the buffer */ + +static void put(struct prodcons * b, int data) +{ + pthread_mutex_lock(&b->lock); + /* Wait until buffer is not full */ + while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) { + pthread_cond_wait(&b->notfull, &b->lock); + /* pthread_cond_wait reacquired b->lock before returning */ + } + /* Write the data and advance write pointer */ + b->buffer[b->writepos] = data; + b->writepos++; + if (b->writepos >= BUFFER_SIZE) b->writepos = 0; + /* Signal that the buffer is now not empty */ + pthread_cond_signal(&b->notempty); + pthread_mutex_unlock(&b->lock); +} + +/* Read and remove an integer from the buffer */ + +static int get(struct prodcons * b) +{ + int data; + pthread_mutex_lock(&b->lock); + /* Wait until buffer is not empty */ + while (b->writepos == b->readpos) { + pthread_cond_wait(&b->notempty, &b->lock); + } + /* Read the data and advance read pointer */ + data = b->buffer[b->readpos]; + b->readpos++; + if (b->readpos >= BUFFER_SIZE) b->readpos = 0; + /* Signal that the buffer is now not full */ + pthread_cond_signal(&b->notfull); + pthread_mutex_unlock(&b->lock); + return data; +} + +/* A test program: one thread inserts integers from 1 to 10000, + the other reads them and prints them. */ + +#define OVER (-1) + +struct prodcons buffer; + +static void * producer(void * data) +{ + int n; + for (n = 0; n < 10000; n++) { + printf("%d --->\n", n); + put(&buffer, n); + } + put(&buffer, OVER); + return NULL; +} + +static void * consumer(void * data) +{ + int d; + while (1) { + d = get(&buffer); + if (d == OVER) break; + printf("---> %d\n", d); + } + return NULL; +} + +int main(void) +{ + pthread_t th_a, th_b; + void * retval; + + init(&buffer); + /* Create the threads */ + pthread_create(&th_a, NULL, producer, 0); + pthread_create(&th_b, NULL, consumer, 0); + /* Wait until producer and consumer finish. */ + pthread_join(th_a, &retval); + pthread_join(th_b, &retval); + return 0; +} diff --git a/test/pthread/ex3.c b/test/pthread/ex3.c new file mode 100644 index 0000000..8ef7797 --- /dev/null +++ b/test/pthread/ex3.c @@ -0,0 +1,152 @@ +/* Multi-thread searching. + Illustrates: thread cancellation, cleanup handlers. */ + +#include +#include +#include +#include +#include +#include + +/* Defines the number of searching threads */ +#define NUM_THREADS 5 + +/* Function prototypes */ +void *search(void *); +void print_it(void *); + +/* Global variables */ +pthread_t threads[NUM_THREADS]; +pthread_mutex_t lock; +int tries; +volatile int started; + +int main(int argc, char ** argv) +{ + unsigned long i; + unsigned long pid; + + /* create a number to search for */ + pid = getpid(); + printf("Searching for the number = %ld...\n", pid); + + /* Initialize the mutex lock */ + pthread_mutex_init(&lock, NULL); + + /* Create the searching threads */ + for (started=0; started +#include +#include +#include +#include + +/* This is a typical example of a library function that uses + static variables to accumulate results between calls. + Here, it just returns the concatenation of all string arguments + that were given to it. */ + +#if 0 + +static char * str_accumulate(char * s) +{ + static char accu[1024] = { 0 }; + strcat(accu, s); + return accu; +} + +#endif + +/* Of course, this cannot be used in a multi-threaded program + because all threads store "accu" at the same location. + So, we'll use thread-specific data to have a different "accu" + for each thread. */ + +/* Key identifying the thread-specific data */ +static pthread_key_t str_key; +/* "Once" variable ensuring that the key for str_alloc will be allocated + exactly once. */ +static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT; + +/* Forward functions */ +static void str_alloc_key(void); +static void str_alloc_destroy_accu(void * accu); + +/* Thread-safe version of str_accumulate */ + +static char * str_accumulate(const char * s) +{ + char * accu; + + /* Make sure the key is allocated */ + pthread_once(&str_alloc_key_once, str_alloc_key); + /* Get the thread-specific data associated with the key */ + accu = (char *) pthread_getspecific(str_key); + /* It's initially NULL, meaning that we must allocate the buffer first. */ + if (accu == NULL) { + accu = malloc(1024); + if (accu == NULL) return NULL; + accu[0] = 0; + /* Store the buffer pointer in the thread-specific data. */ + pthread_setspecific(str_key, (void *) accu); + printf("Thread %lx: allocating buffer at %p\n", pthread_self(), accu); + } + /* Now we can use accu just as in the non thread-safe code. */ + strcat(accu, s); + return accu; +} + +/* Function to allocate the key for str_alloc thread-specific data. */ + +static void str_alloc_key(void) +{ + pthread_key_create(&str_key, str_alloc_destroy_accu); + printf("Thread %lx: allocated key %d\n", pthread_self(), str_key); +} + +/* Function to free the buffer when the thread exits. */ +/* Called only when the thread-specific data is not NULL. */ + +static void str_alloc_destroy_accu(void * accu) +{ + printf("Thread %lx: freeing buffer at %p\n", pthread_self(), accu); + free(accu); +} + +/* Test program */ + +static void * process(void * arg) +{ + char * res; + res = str_accumulate("Result of "); + res = str_accumulate((char *) arg); + res = str_accumulate(" thread"); + printf("Thread %lx: \"%s\"\n", pthread_self(), res); + return NULL; +} + +int main(int argc, char ** argv) +{ + char * res; + pthread_t th1, th2; + + res = str_accumulate("Result of "); + pthread_create(&th1, NULL, process, (void *) "first"); + pthread_create(&th2, NULL, process, (void *) "second"); + res = str_accumulate("initial thread"); + printf("Thread %lx: \"%s\"\n", pthread_self(), res); + pthread_join(th1, NULL); + pthread_join(th2, NULL); + exit(0); +} diff --git a/test/pthread/ex5.c b/test/pthread/ex5.c new file mode 100644 index 0000000..7a293eb --- /dev/null +++ b/test/pthread/ex5.c @@ -0,0 +1,102 @@ +/* The classic producer-consumer example, implemented with semaphores. + All integers between 0 and 9999 should be printed exactly twice, + once to the right of the arrow and once to the left. */ + +#include +#include "pthread.h" +#include "semaphore.h" + +#define BUFFER_SIZE 16 + +/* Circular buffer of integers. */ + +struct prodcons { + int buffer[BUFFER_SIZE]; /* the actual data */ + int readpos, writepos; /* positions for reading and writing */ + sem_t sem_read; /* number of elements available for reading */ + sem_t sem_write; /* number of locations available for writing */ +}; + +/* Initialize a buffer */ + +static void init(struct prodcons * b) +{ + sem_init(&b->sem_write, 0, BUFFER_SIZE - 1); + sem_init(&b->sem_read, 0, 0); + b->readpos = 0; + b->writepos = 0; +} + +/* Store an integer in the buffer */ + +static void put(struct prodcons * b, int data) +{ + /* Wait until buffer is not full */ + sem_wait(&b->sem_write); + /* Write the data and advance write pointer */ + b->buffer[b->writepos] = data; + b->writepos++; + if (b->writepos >= BUFFER_SIZE) b->writepos = 0; + /* Signal that the buffer contains one more element for reading */ + sem_post(&b->sem_read); +} + +/* Read and remove an integer from the buffer */ + +static int get(struct prodcons * b) +{ + int data; + /* Wait until buffer is not empty */ + sem_wait(&b->sem_read); + /* Read the data and advance read pointer */ + data = b->buffer[b->readpos]; + b->readpos++; + if (b->readpos >= BUFFER_SIZE) b->readpos = 0; + /* Signal that the buffer has now one more location for writing */ + sem_post(&b->sem_write); + return data; +} + +/* A test program: one thread inserts integers from 1 to 10000, + the other reads them and prints them. */ + +#define OVER (-1) + +struct prodcons buffer; + +static void * producer(void * data) +{ + int n; + for (n = 0; n < 10000; n++) { + printf("%d --->\n", n); + put(&buffer, n); + } + put(&buffer, OVER); + return NULL; +} + +static void * consumer(void * data) +{ + int d; + while (1) { + d = get(&buffer); + if (d == OVER) break; + printf("---> %d\n", d); + } + return NULL; +} + +int main(void) +{ + pthread_t th_a, th_b; + void * retval; + + init(&buffer); + /* Create the threads */ + pthread_create(&th_a, NULL, producer, 0); + pthread_create(&th_b, NULL, consumer, 0); + /* Wait until producer and consumer finish. */ + pthread_join(th_a, &retval); + pthread_join(th_b, &retval); + return 0; +} diff --git a/test/pthread/ex6.c b/test/pthread/ex6.c new file mode 100644 index 0000000..bb96ca5 --- /dev/null +++ b/test/pthread/ex6.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +static void * +test_thread (void *v_param) +{ + return NULL; +} + +int +main (void) +{ + unsigned long count; + + setvbuf (stdout, NULL, _IONBF, 0); + + for (count = 0; count < 2000; ++count) + { + pthread_t thread; + int status; + + status = pthread_create (&thread, NULL, test_thread, NULL); + if (status != 0) + { + printf ("status = %d, count = %lu: %s\n", status, count, + strerror (errno)); + return 1; + } + else + { + printf ("count = %lu\n", count); + } + /* pthread_detach (thread); */ + pthread_join (thread, NULL); + usleep (10); + } + return 0; +} diff --git a/test/pthread/ex7.c b/test/pthread/ex7.c new file mode 100644 index 0000000..49af18d --- /dev/null +++ b/test/pthread/ex7.c @@ -0,0 +1,103 @@ +/* ex7 + * + * Test case that illustrates a timed wait on a condition variable. + */ + +#include +#include +#include +#include +#include +#include + +/* Our event variable using a condition variable contruct. */ +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + int flag; +} event_t; + + +/* Global event to signal main thread the timeout of the child thread. */ +event_t main_event; + + +static void * +test_thread (void *ms_param) +{ + unsigned long status = 0; + event_t foo; + struct timespec timeout; + struct timeval now; + long ms = (long) ms_param; + + /* initialize cond var */ + pthread_cond_init(&foo.cond, NULL); + pthread_mutex_init(&foo.mutex, NULL); + foo.flag = 0; + + /* set the time out value */ + printf("waiting %ld ms ...\n", ms); + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + ms/1000 + (now.tv_usec + (ms%1000)*1000)/1000000; + timeout.tv_nsec = ((now.tv_usec + (ms%1000)*1000) % 1000000) * 1000; + + /* Just use this to test the time out. The cond var is never signaled. */ + pthread_mutex_lock(&foo.mutex); + while (foo.flag == 0 && status != ETIMEDOUT) { + status = pthread_cond_timedwait(&foo.cond, &foo.mutex, &timeout); + } + pthread_mutex_unlock(&foo.mutex); + + /* post the main event */ + pthread_mutex_lock(&main_event.mutex); + main_event.flag = 1; + pthread_cond_signal(&main_event.cond); + pthread_mutex_unlock(&main_event.mutex); + + /* that's it, bye */ + return (void*) status; +} + +int +main (void) +{ + unsigned long count; + + setvbuf (stdout, NULL, _IONBF, 0); + + /* initialize main event cond var */ + pthread_cond_init(&main_event.cond, NULL); + pthread_mutex_init(&main_event.mutex, NULL); + main_event.flag = 0; + + for (count = 0; count < 20; ++count) + { + pthread_t thread; + int status; + + /* pass down the milli-second timeout in the void* param */ + status = pthread_create (&thread, NULL, test_thread, (void*) (count*100)); + if (status != 0) { + printf ("status = %d, count = %lu: %s\n", status, count, + strerror (errno)); + return 1; + } + else { + + /* wait for the event posted by the child thread */ + pthread_mutex_lock(&main_event.mutex); + while (main_event.flag == 0) { + pthread_cond_wait(&main_event.cond, &main_event.mutex); + } + main_event.flag = 0; + pthread_mutex_unlock(&main_event.mutex); + + printf ("count = %lu\n", count); + } + + usleep (10); + } + + return 0; +} diff --git a/test/pthread/tst-too-many-cleanups.c b/test/pthread/tst-too-many-cleanups.c new file mode 100644 index 0000000..7828c50 --- /dev/null +++ b/test/pthread/tst-too-many-cleanups.c @@ -0,0 +1,104 @@ +/* + * This illustrates the bug where the cleanup function + * of a thread may be called too many times. + * + * main thread: + * - grab mutex + * - spawn thread1 + * - go to sleep + * thread1: + * - register cleanup handler via pthread_cleanup_push() + * - try to grab mutex and sleep + * main: + * - kill thread1 + * - go to sleep + * thread1 cleanup handler: + * - try to grab mutex and sleep + * main: + * - kill thread1 + * - go to sleep + * thread1 cleanup handler: + * - wrongly called again + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +#define warn(fmt, args...) fprintf(stderr, "[%p] " fmt, (void*)pthread_self(), ## args) +#define warnf(fmt, args...) warn("%s:%i: " fmt, __FUNCTION__, __LINE__, ## args) + +int ok_to_kill_thread; + +static void thread_killed(void *arg); + +static void *KillMeThread(void *thread_par) +{ + pthread_t pthread_id; + + warnf("Starting child thread\n"); + + pthread_id = pthread_self(); + pthread_cleanup_push(thread_killed, (void *)pthread_id); + + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + /* main code */ + warnf("please kill me now\n"); + while (1) { + ok_to_kill_thread = 1; + sleep(1); + } + + pthread_cleanup_pop(0); + + return 0; +} + +static void thread_killed(void *arg) +{ + static int num_times_called = 0; + + warnf("killing %p [cnt=%i]\n", arg, ++num_times_called); + assert(num_times_called == 1); + + /* pick any cancellation endpoint, sleep() will do just fine */ + while (1) { + warnf("sleeping in cancellation endpoint ...\n"); + sleep(1); + } + + warnf("done cleaning up\n"); +} + +int main(int argc, char *argv[]) +{ + int count = 3; + pthread_t app_pthread_id; + + /* need to tweak this test a bit to play nice with signals and LT */ + return 0; + + ok_to_kill_thread = 0; + + pthread_create(&app_pthread_id, NULL, KillMeThread, NULL); + + warnf("waiting for thread to prepare itself\n"); + while (!ok_to_kill_thread) + sleep(1); + + while (count--) { + warnf("killing thread\n"); + pthread_cancel(app_pthread_id); + sleep(3); + } + + return 0; +} diff --git a/test/pwd_grp/.indent.pro b/test/pwd_grp/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/test/pwd_grp/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/test/pwd_grp/Makefile b/test/pwd_grp/Makefile new file mode 100644 index 0000000..e6362d3 --- /dev/null +++ b/test/pwd_grp/Makefile @@ -0,0 +1,10 @@ +# uClibc pwd_grp tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +DODIFF_test_pwd := 1 +DODIFF_test_grp := 1 +DODIFF_pwcat := 1 +DODIFF_grcat := 1 +DODIFF_getgroups := 1 diff --git a/test/pwd_grp/getgroups.c b/test/pwd_grp/getgroups.c new file mode 100644 index 0000000..0c09308 --- /dev/null +++ b/test/pwd_grp/getgroups.c @@ -0,0 +1,99 @@ +/* This test was ripped out of GNU 'id' from coreutils-5.0 + * by Erik Andersen. + * + * + * id is Copyright (C) 1989-2003 Free Software Foundation, Inc. + * and licensed under the GPL v2 or later, and was written by + * Arnold Robbins, with a major rewrite by David MacKenzie, + */ + +#include +#include +#include +#include +#include +#include +#include + +/* The number of errors encountered so far. */ +static int problems = 0; + +/* Print the name or value of group ID GID. */ +static void print_group(gid_t gid) +{ + struct group *grp = NULL; + + grp = getgrgid(gid); + if (grp == NULL) { + warn("cannot find name for group ID %u", gid); + problems++; + } + + if (grp == NULL) + printf("%u", (unsigned)gid); + else + printf("%s", grp->gr_name); +} + +static int xgetgroups(gid_t gid, int *n_groups, gid_t ** groups) +{ + int max_n_groups; + int ng; + gid_t *g; + int fail = 0; + + max_n_groups = getgroups(0, NULL); + + /* Add 1 just in case max_n_groups is zero. */ + g = (gid_t *) malloc(max_n_groups * sizeof(gid_t) + 1); + if (g == NULL) + err(EXIT_FAILURE, "out of memory"); + ng = getgroups(max_n_groups, g); + + if (ng < 0) { + warn("cannot get supplemental group list"); + ++fail; + free(groups); + } + if (!fail) { + *n_groups = ng; + *groups = g; + } + return fail; +} + +/* Print all of the distinct groups the user is in. */ +int main(int argc, char *argv[]) +{ + struct passwd *pwd; + + pwd = getpwuid(getuid()); + if (pwd == NULL) + problems++; + + print_group(getgid()); + if (getegid() != getgid()) { + putchar(' '); + print_group(getegid()); + } + + { + int n_groups = 0; + gid_t *groups; + register int i; + + if (xgetgroups((pwd ? pwd->pw_gid : (gid_t) - 1), + &n_groups, &groups)) { + return ++problems; + } + + for (i = 0; i < n_groups; i++) + if (groups[i] != getgid() && groups[i] != getegid()) { + putchar(' '); + print_group(groups[i]); + } + free(groups); + } + putchar('\n'); + return (problems != 0); +} diff --git a/test/pwd_grp/grcat.c b/test/pwd_grp/grcat.c new file mode 100644 index 0000000..a896140 --- /dev/null +++ b/test/pwd_grp/grcat.c @@ -0,0 +1,32 @@ +/* + * grcat.c + * + * Generate a printable version of the group database + */ +/* + * Arnold Robbins, arnold@gnu.org, May 1993 + * Public Domain + */ + +#include +#include +#include + +int main(int argc, char **argv) +{ + struct group *g; + int i; + + while ((g = getgrent()) != NULL) { + printf("%s:%s:%ld:", g->gr_name, g->gr_passwd, + (long) g->gr_gid); + for (i = 0; g->gr_mem[i] != NULL; i++) { + printf("%s", g->gr_mem[i]); + if (g->gr_mem[i+1] != NULL) + putchar(','); + } + putchar('\n'); + } + endgrent(); + return 0; +} diff --git a/test/pwd_grp/pwcat.c b/test/pwd_grp/pwcat.c new file mode 100644 index 0000000..afad8e1 --- /dev/null +++ b/test/pwd_grp/pwcat.c @@ -0,0 +1,26 @@ +/* + * pwcat.c + * + * Generate a printable version of the password database + */ +/* + * Arnold Robbins, arnold@gnu.org, May 1993 + * Public Domain + */ + +#include +#include +#include + +int main(int argc, char **argv) +{ + struct passwd *p; + + while ((p = getpwent()) != NULL) + printf("%s:%s:%ld:%ld:%s:%s:%s\n", + p->pw_name, p->pw_passwd, (long) p->pw_uid, + (long) p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell); + + endpwent(); + return 0; +} diff --git a/test/pwd_grp/test_grp.c b/test/pwd_grp/test_grp.c new file mode 100644 index 0000000..573806c --- /dev/null +++ b/test/pwd_grp/test_grp.c @@ -0,0 +1,87 @@ +/* + * test_grp.c - This file is part of the libc-8086/grp package for ELKS, + * Copyright (C) 1995, 1996 Nat Friedman . + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + struct group *group; + char **tmp_mem; + int test_gid; + + fprintf(stdout, "Beginning test of libc/grp...\n"); + + fprintf(stdout, "=> Testing setgrent(), getgrent(), endgrent()...\n"); + fprintf(stdout, "-> setgrent()...\n"); + setgrent(); + fprintf(stdout, "-> getgrent()...\n"); + printf + ("********************************************************************************\n"); + while ((group = getgrent()) != NULL) { + printf("gr_name\t\t: %s\n", group->gr_name); + printf("gr_passwd\t: %s\n", group->gr_passwd); + printf("gr_gid\t\t: %d\n", (int) group->gr_gid); + printf("gr_mem\t\t: "); + fflush(stdout); + tmp_mem = group->gr_mem; + while (*tmp_mem != NULL) { + printf("%s, ", *tmp_mem); + tmp_mem++; + } + printf + ("\n********************************************************************************\n"); + } + fprintf(stdout, "-> endgrent()...\n"); + endgrent(); + fprintf(stdout, + "=> Test of setgrent(), getgrent(), endgrent() complete.\n"); + fprintf(stdout, "=> Testing getgrid(), getgrnam()...\n"); + fprintf(stdout, "-> getgrgid()...\n"); + printf + ("********************************************************************************\n"); + for (test_gid = 0; test_gid < 100; test_gid++) { + fprintf(stdout, "-> getgrgid(%d)...\n", test_gid); + group = getgrgid((gid_t) test_gid); + if (group != NULL) { + printf("gr_name\t: %s\n", group->gr_name); + printf("gr_passwd\t: %s\n", group->gr_passwd); + printf("gr_gid\t: %d\n", (int) group->gr_gid); + printf("gr_mem\t\t: "); + fflush(stdout); + tmp_mem = group->gr_mem; + while (*tmp_mem != NULL) { + printf("%s, ", *tmp_mem); + tmp_mem++; + } + } + printf + ("\n********************************************************************************\n"); + } + fprintf(stdout, "-> getgrnam()...\n"); + group = getgrnam("root"); + if (group == NULL) { + printf(">NULL<\n"); + } else { + printf("gr_name\t: %s\n", group->gr_name); + printf("gr_passwd\t: %s\n", group->gr_passwd); + printf("gr_gid\t: %d\n", (int) group->gr_gid); + printf("gr_mem\t\t: "); + fflush(stdout); + tmp_mem = group->gr_mem; + while (*tmp_mem != NULL) { + printf("%s, ", *tmp_mem); + tmp_mem++; + } + printf("\n"); + } + + + return 0; +} diff --git a/test/pwd_grp/test_pwd.c b/test/pwd_grp/test_pwd.c new file mode 100644 index 0000000..065864e --- /dev/null +++ b/test/pwd_grp/test_pwd.c @@ -0,0 +1,74 @@ +/* + * test_pwd.c - This file is part of the libc-8086/pwd package for ELKS, + * Copyright (C) 1995, 1996 Nat Friedman . + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + struct passwd *passwd; + int test_uid; + + fprintf(stdout, "Beginning test of libc/pwd...\n"); + + fprintf(stdout, "=> Testing setpwent(), getpwent(), endpwent()...\n"); + fprintf(stdout, "-> setpwent()...\n"); + setpwent(); + fprintf(stdout, "-> getpwent()...\n"); + printf + ("********************************************************************************\n"); + while ((passwd = getpwent()) != NULL) { + printf("pw_name\t\t: %s\n", passwd->pw_name); + printf("pw_passwd\t: %s\n", passwd->pw_passwd); + printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); + printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); + printf("pw_gecos\t: %s\n", passwd->pw_gecos); + printf("pw_dir\t\t: %s\n", passwd->pw_dir); + printf("pw_shell\t: %s\n", passwd->pw_shell); + printf + ("********************************************************************************\n"); + } + fprintf(stdout, "-> endpwent()...\n"); + endpwent(); + fprintf(stdout, + "=> Test of setpwent(), getpwent(), endpwent() complete.\n"); + fprintf(stdout, "=> Testing getpwuid(), getpwnam()...\n"); + fprintf(stdout, "-> getpwuid()...\n"); + printf + ("********************************************************************************\n"); + for (test_uid = 0; test_uid < 1000; test_uid++) { + fprintf(stdout, "-> getpwuid(%d)...\n", test_uid); + passwd = getpwuid((uid_t) test_uid); + if (passwd != NULL) { + printf("pw_name\t\t: %s\n", passwd->pw_name); + printf("pw_passwd\t: %s\n", passwd->pw_passwd); + printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); + printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); + printf("pw_gecos\t: %s\n", passwd->pw_gecos); + printf("pw_dir\t\t: %s\n", passwd->pw_dir); + printf("pw_shell\t: %s\n", passwd->pw_shell); + printf + ("********************************************************************************\n"); + } + } + fprintf(stdout, "-> getpwnam()...\n"); + passwd = getpwnam("root"); + if (passwd == NULL) { + printf(">NULL<\n"); + } else { + printf("pw_name\t\t: %s\n", passwd->pw_name); + printf("pw_passwd\t: %s\n", passwd->pw_passwd); + printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid); + printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid); + printf("pw_gecos\t: %s\n", passwd->pw_gecos); + printf("pw_dir\t\t: %s\n", passwd->pw_dir); + printf("pw_shell\t: %s\n", passwd->pw_shell); + } + return 0; +} diff --git a/test/regex/.regex.ChangeLog.14 b/test/regex/.regex.ChangeLog.14 new file mode 100644 index 0000000..ace9f3b --- /dev/null +++ b/test/regex/.regex.ChangeLog.14 @@ -0,0 +1,2176 @@ +2002-11-19 Ulrich Drepper + + * intl/localealias.c (read_alias_file): Use only about 400 bytes + of stack space instead of 16k. + +2002-11-18 Wolfram Gloger + + * malloc/arena.c + (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2): Do + nothing if not initialized. Bug report from Marcus Brinkmann + . + +2002-11-19 Roland McGrath + + * posix/Versions (libc: GLIBC_2.3.2): Add sched_getaffinity and + sched_setaffinity. + + * configure.in (libc_cv_gcc_dwarf2_unwind_info check): Use libraries + `-lgcc -lgcc_eh -lgcc', not just `-lgcc -lgcc_eh' in link commands for + test leading to libc_cv_gcc_dwarf2_unwind_info=no_registry_needed. + * configure: Regenerated. + +2002-11-19 Ulrich Drepper + + * include/dlfcn.h: __libc_dlopen is now a macro calling + __libc_dlopen_mode with the extra parameter RTLD_LAZY. + (__libc_dlopen_mode): New prototype. + * elf/dl-libc.c (__libc_dlopen_mode): Renamed from __libc_dlopen. Add + new parameter. Store new parameter in mode field of structure passed + to do_dlopen. + (struct do_dlopen_args): Add new field mode. + (do_dlopen): Pass mode from parameter structure to _dl_open. + +2002-11-11 Randolf Chung + + * sysdeps/unix/sysv/linux/hppa/bits/fcntl.h [__USE_FILE_OFFSET64] + (F_GETLK, F_SETLK, F_SETLKW): Define to F_*64 versions. + * sysdeps/unix/sysv/linux/hppa/fcntl.c: New file. + + * sysdeps/hppa/fpu/libm-test-ulps: New file (generated). + + * sysdeps/hppa/Makefile (CFLAGS-rtld.c): New variable. + Set -mdisable-fpregs for this file. + +2002-11-11 Carlos O'Donell + + * sysdeps/unix/sysv/linux/configure.in: + Make 2.4.19 minimum linux kernel for hppa, and add unwind symbols + from gcc-3.0 era for backwards compatibility. + * sysdeps/unix/sysv/linux/configure: Regenerate. + + * sysdeps/unix/sysv/linux/hppa/sys/ucontext.h: + Define mcontext_t as a sigcontext. + +2002-11-18 Roland McGrath + + * dlfcn/dlerror.c (fini): New function, __attribute__ ((destructor)). + Free memory in `last_result' if it was used. + + * resolv/nss_dns/dns-network.c (getanswer_r): In BYNAME case, search + all aliases for one that matches the ".IN-ADDR.ARPA" form. + Do the parsing inline instead of copying strings and calling + inet_network, and properly skip all alias names not matching the form. + + * manual/pattern.texi (Variable Substitution): Fix # and ## examples. + +2002-11-17 Ulrich Drepper + + * manual/pattern.texi (Wordexp Example): Fix sample code. + + * sysdeps/unix/sysv/linux/i386/clone.S: Initialize word in the + childs stack which will be loaded into the %esi register. + +2002-11-14 Paul Eggert + + * resolv/nss_dns/dns-network.c (getanswer_r): Check for buffer + overflow when skipping the question part and when unpacking aliases. + +2002-11-15 Roland McGrath + + * math/Makefile (libm-calls): Remove s_copysign, s_isinf, s_isnan, + s_finite, s_modf, s_scalbn, s_frexp, m_ldexp, s_signbit. + Instead add $(calls:s_%=m_%) to get m_* versions of them all. + +2002-11-15 Jakub Jelinek + + * sysdeps/i386/dl-machine.h (elf_machine_rela): Handle R_386_COPY. + * sysdeps/arm/dl-machine.h (elf_machine_rela): Handle R_ARM_COPY. + +2002-11-15 Roland McGrath + + * math/Makefile (libm-calls): Change s_ldexp to m_ldexp. + * Makerules ($(+sysdir_pfx)sysd-rules): Emit pattern rules for m_%.[Sc] + from sysdeps/.../s_%.[Sc] with commands $(+make-include-of-dep). + (+make-include-of-dep): New canned sequence. + + * stdlib/canonicalize.c (__realpath): Check for malloc failure. + From Dmitry V. Levin . + +2002-11-14 Roland McGrath + + * sysdeps/generic/errno.c (__libc_errno): Remove alias. + * inet/herrno.c (__libc_h_errno): Likewise. + * resolv/res_libc.c (__libc_res): Likewise. + [USE___THREAD]: Use this in place of [USE_TLS && HAVE___THREAD]. + (__res_state) [! USE___THREAD]: Don't define as weak. + * csu/Versions: Revert last change. + * resolv/Versions: Revert last change. + + * Makerules ($(common-objpfx)%.make): New pattern rule. + * tls.make.c: New file. + * Makefile (distribute): Add it. + + * sysdeps/generic/errno.c [! USE___THREAD] + [HAVE_ELF && SHARED && DO_VERSIONING] (errno, _errno): Declare these + with compat_symbol so they are not link-time visible. + [! USE___THREAD] (__libc_errno): New alias for errno. + * csu/Versions [!(USE_TLS && HAVE___THREAD)] (libc: GLIBC_PRIVATE): + Add __libc_errno here. + * inet/herrno.c [USE___THREAD]: Use this conditional + in place of [USE_TLS && HAVE___THREAD]. + [! USE___THREAD] [HAVE_ELF && SHARED && DO_VERSIONING] + (h_errno, _h_errno): Declare these with compat_symbol so they are not + link-time visible. + [! USE___THREAD] (__libc_h_errno): New alias for h_errno. + * resolv/res_libc.c [! USE___THREAD] + [HAVE_ELF && SHARED && DO_VERSIONING] (_res): Likewise. + (_res): Use __attribute__ ((section (".bss"))) so we can have an alias. + (__libc_res): Define as alias for _res. + * resolv/Versions [!(USE_TLS && HAVE___THREAD)] (libc: GLIBC_PRIVATE): + Add __libc_h_errno and __libc_res here. + +2002-11-14 Jakub Jelinek + + * csu/Versions (errno): Move STT_TLS symbol to GLIBC_PRIVATE for now. + * resolv/Versions (h_errno, _res): Likewise. + +2002-11-14 Roland McGrath + + * Makerules (%.dynsym): Remove $(objpfx) from target and dep. + (%.symlist): Likewise. + +2002-11-13 Roland McGrath + + * scripts/abilist.awk: New file. + * Makefile (distribute): Add it. + * Makerules ($(objpfx)%.dynsym, $(objpfx)%.symlist): New rules. + (tests): Depend on .symlist file for each $(install-lib.so-versioned). + [$(subdir) = elf] (tests): Depend on libc.symlist. + (generated, common-generated): Add those files. + + * aclocal.m4 (LIBC_PROG_BINUTILS): Check for objdump, set OBJDUMP. + * configure: Regenerated. + * config.make.in (OBJDUMP): New variable, substituted by configure. + + * malloc/mcheck.c (struct hdr): New members `block' and `magic2'. + (mallochook, reallochook): Set them up. + (checkhdr): Check HDR->magic2 value. + (freehook): Reset HDR->magic2. + (memalignhook): New static function. + (old_memalign_hook): New static variable. + (mcheck, reallochook): Set __memalign_hook to memalignhook. + + * sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage): Zero the space + for the new TCB. + +2002-11-13 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Check for visibility + attribute. + * sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise. + +2002-11-11 Paul Eggert + + * manual/crypt.texi (Cryptographic Functions): Mention that + the MD5 one-way algorithm is compatible with BSD's. + +2002-11-11 Isamu Hasegawa + + * posix/regex_internal.c (re_string_skip_chars): Also return the last + wide character. + (re_string_reconstruct): Calculate the context by itself when the + offset points out of the valid range. + (re_string_context_at): Use wide character when MB_CUR_MAX > 1. + * posix/regex_internal.h (WIDE_NEWLINE_CHAR): New macro. + (IS_WIDE_WORD_CHAR): New macro. + (IS_WIDE_NEWLINE): New macro. + +2002-11-12 Andreas Jaeger + + * sysdeps/x86_64/strchr.S: Don't use one register for two + purposes, this fixes a bug noticed by test-strchr.c. + + * sysdeps/x86_64/strcat.S: Fix algorithm to align source pointer + correctly. + +2002-11-12 Roland McGrath + + * libio/libioP.h [_LIBC && !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)] + (_G_IO_NO_BACKWARD_COMPAT): Define it. + + * sysdeps/ia64/dl-fptr.c [_LIBC_REENTRANT]: Include + instead of . + [_LIBC_REENTRANT] (lock, unlock): Use __sync_lock_* macros instead of + testandset. + From Ian Wienand . + +2002-11-10 Roland McGrath + + * libio/bug-wfflush.c (do_test): Call rewind instead of fsetpos. + Call fputs instead of fwprintf (simpler to follow in debugger). + + * crypt/md5-crypt.c: Doc fix. + + * sysdeps/unix/make-syscalls.sh: Insert $(make-target-directory) at + the beginning of generated target commands. + + * csu/Makefile ($(objpfx)crti.o, $(objpfx)crtn.o): Add explicit + dependencies for these in case implicit rule search skipped the + nonexistent source directory. + * sysdeps/gnu/Makefile ($(objpfx)errlist.d): Give this rule all the + files with $(object-suffixes) as targets too. + * Makerules [no_deps && objpfx] (before-compile): Add $(objpfx). + and a target for it using $(make-target-directory). + + * Rules (before-compile): Add $(common-objpfx)bits/stdio-lim.h. + +2002-11-10 Roland McGrath + + * sysdeps/unix/sysv/linux/bits/pthreadtypes.h: Moved to ... + * sysdeps/generic/bits/pthreadtypes.h: ... here. + + * sysdeps/mach/hurd/fcntl.c (__libc_fcntl): Treat a struct flock with + l_start == 0 and l_len == 1 as we do l_len == 0. + +2002-11-10 Ulrich Drepper + + * po/da.po: Update from translation team. + +2002-11-10 Roland McGrath + + * config.make.in (includedir): New variable, substituted by configure. + Reported missing by Jocelyn Fournier . + * Makeconfig (includedir): Use $(prefix), not $(exec_prefix). + +2002-11-10 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/sys/ucontext.h (enum): Add + REG_OLDMASK and REG_CR2 to synch with kernel header. + (NGREG): Increase. + + * nss/getXXent.c (GETFUNC_NAME): Use union type to avoid strict + aliasing problem. + * nss/getXXbyYY_r.c (INTERNAL): Likewise. + * nss/getnssent_r.c (__nss_getent_r): Likewise. + (__nss_setent): Likewise. + (__nss_getent_r): Likewise. + * inet/getnetgrent_r.c (innetgr): Likewise. + (__internal_setnetgrent_reuse): Likewise. + (internal_getnetgrent_r): Likewise. + * inet/ether_hton.c (ether_hostton): Likewise. + * inet/ether_ntoh.c (ether_ntohost): Likewise. + * sunrpc/netname.c (netname2user): Likewise. + * sunrpc/publickey.c (getpublickey): Likewise. + (getsecretkey): Likewise. + +2002-11-09 Marcus Brinkmann + + * sysdeps/mach/hurd/i386/ioperm.c (ioperm): Correct off by one + error in range calculation. + +2002-10-09 Jakub Jelinek + + * string/test-strspn.c (do_test): Ensure zero termination. + * string/test-strpbrk.c (do_test): Likewise. + * string/test-strncmp.c (stupid_strncmp): Use strnlen, not strlen. + * string/test-strncpy.c (stupid_strncpy): Likewise. + * string/test-stpncpy.c (stupid_stpncpy): Likewise. + +2002-10-08 Roland McGrath + + * string/test-string.h (test_init): Fill BUF1 and BUF2 with + nonzero characters. + +2002-09-22 H.J. Lu + + * sysdeps/unix/sysv/linux/mmap64.c (MMAP2_PAGE_SHIFT): Renamed + from PAGE_SHIFT. Define if not defined. Check MMAP2_PAGE_SHIFT + only if __NR_mmap2 is defined. + + * sysdeps/unix/sysv/linux/powerpc/mmap64.c: Moved to ... + * sysdeps/unix/sysv/linux/mmap64.c: ... here. + * sysdeps/unix/sysv/linux/hppa/mmap64.c: File removed. + * sysdeps/unix/sysv/linux/sparc/sparc32/mmap64.c: FIle removed, + +2002-11-08 Jakub Jelinek + + * posix/bug-regex13.c (tests): Add new test. + + * string/test-strchr.c (stupid_strchr): New function. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strpbrk.c (stupid_strpbrk): New function. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strcmp.c (stupid_strcmp): New function. + (do_random_tests): Make sure the strings are zero terminated. + * string/test-strspn.c (stupid_strspn): New function. + (simple_strspn): Rename rej argument to acc. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strcspn.c (stupid_strcspn): New function. + * string/test-strncpy.c (stupid_strncpy): New function. + * string/test-stpncpy.c (stupid_stpncpy): New function. + * string/test-strncmp.c (stupid_strncmp): New function. + (do_random_tests): Make sure the strings are zero terminated. + * string/test-string.h (impl_t): Change test into long. + (IMPL): Add __attribute__((aligned (sizeof (void *)))). + +2002-11-08 Roland McGrath + + * sysdeps/ia64/elf/configure.in: Add TLS check. + From Ian Wienand . + * sysdeps/ia64/elf/configure: Regenerated. + +2002-11-07 Roland McGrath + + * libio/fileops.c (_IO_new_file_overflow): Use INTUSE(_IO_do_write) in + place of _IO_new_do_write. + [_LIBC] (_IO_do_write): Define as macro for _IO_new_do_write and + #undef before versioned_symbol use. + +2002-11-07 Richard Henderson + + * configure.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove test. + * configure: Regenerated. + * config.h.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove #undef. + * sysdeps/alpha/dl-machine.h (TRAMPOLINE_TEMPLATE): Use !samegp. + (RTLD_START): Likewise. Access _dl_skip_args, _rtld_local, and + _dl_fini via gp-relative relocations. + * sysdeps/alpha/fpu/e_sqrt.c: Use !samegp. + + * elf/tls-macros.h: Add alpha versions. + * sysdeps/alpha/dl-machine.h (elf_machine_rela): Handle TLS relocs. + * sysdeps/unix/alpha/sysdep.S: Support USE___THREAD. + * sysdeps/unix/alpha/sysdep.h: Likewise. Add SYSCALL_ERROR_HANDLER. + * sysdeps/unix/sysv/linux/alpha/brk.S: Use it. + * sysdeps/unix/sysv/linux/alpha/clone.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/getitimer.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/getrusage.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/gettimeofday.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/rt_sigaction.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/select.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/setitimer.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/settimeofday.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/sigsuspend.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/syscall.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/utimes.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/wait4.S: Likewise. + + * sysdeps/unix/sysv/linux/alpha/sysdep.h: Re-include protect. + Kill argument registers across the inline syscall. + + * sysdeps/unix/sysv/linux/alpha/clone.S: Add user_tid and tls args. + + * linuxthreads/sysdeps/alpha/tls.h: New file. + * sysdeps/alpha/dl-tls.h: New file. + +2002-10-29 David Mosberger + + * sysdeps/ia64/elf/initfini.c [HAVE_INITFINI_ARRAY] + (gmon_initializer): New function. + (.init prologue): If HAVE_INITFINI_ARRAY is true, don't call + __gmon_start__ here. Call it from gmon_initializer() instead. + +2002-03-12 H.J. Lu + + * elf/Makefile [$(have-initfini-array) = yes] (tests): Add tst-array1, + tst-array2, and tst-array3. + [$(have-initfini-array) = yes] (tests-static): Add tst-array3. + [$(have-initfini-array) = yes] (modules-names): Add tst-array2dep. + ($(objpfx)tst-array1.out): New target. + ($(objpfx)tst-array2): Likewise. + ($(objpfx)tst-array2.out): Likewise. + ($(objpfx)tst-array3.out): Likewise. + * elf/tst-array1.c: New file. + * elf/tst-array1.exp: Likewise. + * elf/tst-array2.c: Likewise. + * elf/tst-array2dep.c: Likewise. + * elf/tst-array2.exp: Likewise. + * elf/tst-array3.c: Likewise. + +2002-10-28 David Mosberger + + * elf/dl-fini.c (_dl_fini): Invoke fini_array in _reverse_ order. + Don't add L->l_addr to array entry values. + +2002-11-07 Jakub Jelinek + + * string/test-string.h: New file. + * string/test-strlen.c: New file. + * string/test-string.h: New file. + * string/test-strcmp.c: New file. + * string/test-strchr.c: New file. + * string/test-strrchr.c: New file. + * string/test-strcpy.c: New file. + * string/test-stpcpy.c: New file. + * string/test-strncpy.c: New file. + * string/test-stpncpy.c: New file. + * string/test-strpbrk.c: New file. + * string/test-strcspn.c: New file. + * string/test-strspn.c: New file. + * string/test-strcat.c: New file. + * string/test-strncmp.c: New file. + * string/test-memchr.c: New file. + * string/test-memcmp.c: New file. + * string/test-memset.c: New file. + * string/test-memcpy.c: New file. + * string/test-mempcpy.c: New file. + * string/test-memmove.c: New file. + * string/Makefile (strop-tests): New variable. + (tests): Add strop-tests. + (distribute): Add test-string.h. + +2002-11-06 Ulrich Drepper + + * posix/regcomp.c: Use tabs instead of spaces. + * posix/regexec.c: Likewise. + * posix/regex_internal.h: Likewise. + + * posix/regcomp.c (re_compile_fastmap_iter): Use __wcrtomb not wctomb. + +2002-11-06 Jakub Jelinek + + * posix/regcomp.c (re_compile_pattern): Don't set regs_allocated + here. + (regcomp): Don't set can_be_null here. + (re_comp): Clear whole re_comp_buf with the exception of fastmap. + (re_compile_internal): Clear can_be_null, set regs_allocated. + + * posix/regcomp.c (re_set_fastmap): New function. + (re_compile_fastmap_iter): Use it. Remove redundant type == + COMPLEX_BRACKET check. + * posix/regexec.c (re_search_internal): Optimize searching with + fastmap. Call re_string_reconstruct even if match_first is + smaller than raw_mbs_idx. + +2002-11-06 Isamu Hasegawa + + * posix/regcomp (free_dfa_content): Use free_state. + * posix/regex_internal.c (re_string_realloc_buffers): Don't edit + pointers in case that realloc failed. + (re_node_set_merge): Likewise. + (register_state): Likewise. + (create_newstate_common): Invoke memory release functions in case of + error conditions. + (create_ci_newstate): Likewise. + (create_cd_newstate): Likewise. + (free_state): New function. + * posix/regexec.c (re_search_internal): Invoke memory release + functions in case of error conditions. + (sift_states_backward): Likewise. + (merge_state_array): Likewise. + (add_epsilon_src_nodes): Likewise. + (sub_epsilon_src_nodes): Likewise. + (search_subexp): Likewise. + (sift_states_bkref): Likewise. + (transit_state_sb): Likewise. + (transit_state_mb): Likewise. + (transit_state_bkref_loop): Likewise. + (group_nodes_into_DFAstates): Likewise. + (push_fail_stack): Don't edit pointers in case that realloc failed. + (extend_buffers): Likewise. + (match_ctx_add_entry): Likewise. + +2002-11-06 Roland McGrath + + * sysdeps/unix/sysv/linux/mips/configure.in: File removed. + * sysdeps/unix/sysv/linux/mips/configure: Likewise. + + * configure.in: Add checks on as and ld for binutils 2.13 or later. + * configure: Regenerated. + +2002-11-06 Ulrich Drepper + + * posix/regcomp.c (regcomp): __re_compile_fastmap can never fail. + If re_compile_internal failed free fastmap buffer. + (free_dfa_content): Broken out of regfree function. Frees all dfa + related data. + (regfree): Add free_dfa_content. + (re_compile_internal): If any of the called functions fails free + all dfa related memory. + +2002-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/sys/sysctl.h: Add ugly hacks to prevent + warnings from the kernel headers. + +2002-11-05 Roland McGrath + + * sysdeps/unix/mips/sysdep.h [! __PIC__] (PSEUDO): Add nop after jump. + From Johannes Stezenbach . + + * sysdeps/unix/sysv/linux/mips/Versions (libc: GLIBC_2.0): Change + #errlist-compat magic comment to give 123 as size. + (libc: GLIBC_2.1): Remove this set, moving #errlist-compat magic to ... + (libc: GLIBC_2.2): ... here. + (libc: GLIBC_2.3): Likewise. + +2002-11-05 Ulrich Drepper + + * elf/dl-fini.c (_dl_fini): Correct the increment of l_opencount + which happens at the beginning so that we can unload modules in + __libc_freeres. + +2002-11-06 Kaz Kojima + + * sysdeps/sh/bits/setjmp.h (JB_SIZE): Define only + under [__USE_MISC || _ASM]. + + * elf/elf.h: Remove the obsolete SH TLS relocations. + +2002-11-05 Ulrich Drepper + + * posix/regcomp.c (regcomp): Initialize preg->can_be_null to zero. + +2002-11-05 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Handle + __NR_pread64 and __NR_pwrite64. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Remove __NR_pread64 + and __NR_pwrite64. + Revert change to use INLINE_SYSCALL. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/ftruncate64.c: Revert change to use + INLINE_SYSCALL. + * sysdeps/unix/sysv/linux/powerpc/truncate64.c: Likewise. + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h (INLINE_SYSCALL): + Update clobber list and add a comment about the syscall ABI. + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_pread64, + s_pwrite64, s_ftruncate, s_truncate): Re-add. + +2002-11-05 Jakub Jelinek + + * iconv/gconv_dl.c (free_mem): Clear loaded. + * locale/loadarchive.c (_nl_archive_subfreeres): Call locale_data's + cleanup if any. + +2002-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fexecve.c: Include . + + * libio/ioseekoff.c: Remove INTDEF. Define _IO_seekoff_unlocked. Same + as old code without locking. _IO_seekoff calls this function after + locking the stream. + * libio/ioseekpos.c: Likewise for _IO_seekpos. + * libio/libioP.h: Replace _IO_seekoff_internal and _IO_seekpos_internal + prototypes with _IO_seekoff_unlocked and _IO_seekpos_unlocked + prototypes. + * libio/iolibio.h (_IO_fseek): Call _IO_seekoff_unlocked instead + of _IO_seekoff_internal. + (_IO_rewind): Likewise. + * libio/ioftell.c: Likewise. + * libio/ftello.c: Likewise. + * libio/ftello64.c: Likewise. + * libio/iofgetpos.c: Likewise. + * libio/iofgetpos64.c: Likewise. + * libio/oldiofgetpos.c: Likewise. + * libio/oldiofgetpos64.c: Likewise. + * libio/iofsetpos.c: Call _IO_seekpos_unlocked instead of + _IO_seekpos_internal. + * libio/iofsetpos64.c: Likewise. + * libio/oldiofsetpos.c: Likewise. + * libio/oldiofsetpos64.c: Likewise. + +2002-11-04 Roland McGrath + + * sysdeps/unix/sysv/linux/powerpc/chown.c: Use INLINE_SYSCALL macro. + * sysdeps/unix/sysv/linux/powerpc/ftruncate64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/ioctl.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/tcgetattr.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/tcsetattr.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/truncate64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_ioctl, + s_chown, s_ftruncate64, s_mmap2, s_pread64, s_pwrite64, s_truncate64, + sys_fstat, sys_lstat, sys_mknod, sys_readv, sys_stat, sys_writev): + Remove these, no longer used. + +2002-11-04 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_ipc, + s_llseek, s_readahead, s_execve, s_fcntl, s_fcntl64, s_fstat64, + s_getcwd, s_getdents, s_getdents64, s_getpmsg, s_getpriority, + s_getrlimit, s_lstat64, s_poll, s_ptrace, s_putpmsg, s_reboot, + s_setrlimit, s_sigaction, s_sigpending, s_sigprocmask, s_sigsuspend, + s_stat64, s_sysctl, s_ugetrlimit, s_ustat, s_vfork): Remove now unused + syscall stubs. + + * sysdeps/unix/sysv/linux/pwrite.c: Fix typo. + * sysdeps/unix/sysv/linux/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Handle both __NR_pread64 + and __NR_pread. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Handle both __NR_pwrite64 + and __NR_pwrite. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + +2002-11-03 Roland McGrath + + * sysdeps/generic/ldsodefs.h (struct rtld_global): New member + `_dl_tls_static_used'. + * sysdeps/generic/libc-tls.c (_dl_tls_static_used): New variable. + (__libc_setup_tls): Initialize it. Let the initial value of + _dl_tls_static_size indicate some surplus space in the computed value. + * elf/dl-open.c (_dl_tls_static_size): New variable. + * sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Initialize + _dl_tls_static_used. Add some surplus space into _dl_tls_static_size. + * elf/dl-reloc.c [USE_TLS] (allocate_static_tls): New function. + (CHECK_STATIC_TLS): Use it. + * elf/dl-close.c (_dl_close): Adjust _dl_tls_static_used when the + closed objects occupied a trailing contiguous chunk of static TLS area. + +2002-10-18 Bruno Haible + + * charmaps/ISO_5428: Use Greek characters introduced in Unicode 3.0. + +2002-11-04 Ulrich Drepper + + * libio/wfileops.c (_IO_wfile_seekoff): Don't modify _offset and + _wide_data->_IO_read_end if adjustment can be made in the current + buffer. + + * sysdeps/unix/sysv/linux/fexecve.c: New file. + + * libio/bug-wfflush.c (do_test): Using fseek is not allowed when + wide oriented streams are used. + + * nss/getXXent_r.c (ENDFUNC_NAME): Don't do anything if the + service hasn't been used [PR libc/4744]. + + * include/features.h: Use __STDC_VERSION__ not __STDC_VERSION. + Reported by Miloslav Trmac [PR libc/4766]. + + * manual/examples/dir.c: Don't include . + * manual/examples/select.c: Include for TEMP_FAILURE_RETRY. + Reported by Frédéric Delanoy . + +2002-11-02 H.J. Lu + + * stdio-common/reg-printf.c: Include . + +2002-11-03 Ulrich Drepper + + * sysdeps/generic/libc-tls.c: Define _dl_tls_static_used. + + * po/ca.po: Update from translation team. + * po/es.po: Likewise. + + * sysdeps/generic/segfault.c (catch_segfault): If HAVE_PROC_SELF + is defined write out memory map. + * sysdeps/unix/sysv/linux/segfault.c: New file. + +2002-11-02 Roland McGrath + + * sysdeps/unix/sysv/linux/getdents.c (__GETDENTS): Use union type for + pointers that can alias. + Reported by Daniel Jacobowitz . + + * sysdeps/unix/bsd/bsd4.4/freebsd/bits/typesizes.h: New file. + +2002-11-02 Roland McGrath + + * manual/filesys.texi (Reading/Closing Directory): Rewrite readdir_r + description to be clearer and to say that *RESULT is set to ENTRY. + +2002-10-30 Jakub Jelinek + + * posix/regexec.c (build_trtable): Alloca or malloc dests_node and + dests_ch arrays together. Alloca or malloc dest_states, + dest_states_word and dest_states_nl arrays together. Free memory on + error exit. + +2002-10-29 Daniel Jacobowitz + + * crypt/crypt_util.c (__init_des_r): Initialize current_salt + and current_saltbits. + +2002-11-02 Roland McGrath + + * stdio-common/reg-printf.c: Include . + +2002-11-02 H.J. Lu + + * sysdeps/unix/sysv/linux/mips/syscalls.list (s_execve): Set + caller to EXTRA instead of execve. + +2002-11-01 Roland McGrath + + * sysdeps/generic/errno-loc.c [! USE___THREAD]: Use this conditional + in place of [!(USE_TLS && HAVE___THREAD)]. + (__errno_location) [! USE___THREAD]: Define as strong, not weak. + +2002-10-31 Roger Sayle + + * sysdeps/i386/soft-fp/sfp-machine.h (_FP_NANFRAC_Q, _FP_NANSIGN_Q): + New macros. + * sysdeps/x86_64/soft-fp/sfp-machine.h: Likewise. + + * soft-fp/soft-fp.h: Allow sfp-machine.h to define FP_RND_NEAREST + without defining FP_ROUNDMODE. + +2002-10-29 Jakub Jelinek + + * sysdeps/gnu/siglist.c (PTR_SIZE_STR): Remove. + (__old_sys_siglist, __old_sys_sigabbrev): Use strong_alias and + declare_symbol. + * sysdeps/mach/hurd/siglist.h (OLD_SIGLIST_SIZE_STR): Remove. + (OLD_SIGLIST_SIZE): Define. + * sysdeps/unix/sysv/linux/siglist.h (OLD_SIGLIST_SIZE_STR): Remove. + (OLD_SIGLIST_SIZE): Define. + * sysdeps/unix/sysv/linux/arm/siglist.c: Remove. + +2002-11-01 Jakub Jelinek + + * sysdeps/ia64/strncpy.S: Fix recovery code. + +2002-10-30 Jakub Jelinek + + * include/libc-symbols.h (__libc_freeres_fn_section, libc_freeres_fn): + New macros. + * elf/dl-close.c (free_mem): Use libc_freeres_fn macro, remove + text_set_element. + * elf/dl-libc.c (free_mem): Likewise. + * iconv/gconv_conf.c (free_mem): Likewise. + * iconv/gconv_db.c (free_mem): Likewise. + * iconv/gconv_dl.c (free_mem): Likewise. + * iconv/gconv_cache.c (free_mem): Likewise. + * intl/finddomain.c (free_mem): Likewise. + * intl/dcigettext.c (free_mem): Likewise. + * locale/setlocale.c (free_mem): Likewise. + * misc/fstab.c (fstab_free): Likewise. + * nss/nsswitch.c (free_mem): Likewise. + * posix/regcomp.c (free_mem): Likewise. + * resolv/gai_misc.c (free_res): Likewise. + * stdlib/fmtmsg.c (free_mem): Likewise. + * sunrpc/clnt_perr.c (free_mem): Likewise. + * sysdeps/generic/setenv.c (free_mem): Likewise. + * sysdeps/unix/sysv/linux/shm_open.c (freeit): Likewise. + * sysdeps/pthread/aio_misc.c (free_res): Likewise. + * time/tzset.c (free_mem): Likewise. + * malloc/mtrace.c (release_libc_mem): Add __libc_freeres_fn_section. + * locale/loadarchive.c (_nl_archive_subfreeres): Likewise. + * malloc/set-freeres.c (__libc_freeres): Likewise. + + * login/getutent.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutent): Allocate buffer the first time it is run. + * login/getutid.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutid): Allocate buffer the first time it is run. + * login/getutline.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutline): Allocate buffer the first time it is run. + * malloc/mtrace.c (malloc_trace_buffer): Change into char *. + (mtrace): Allocate malloc_trace_buffer. + * resolv/nsap_addr.c (inet_nsap_ntoa): Decrease size of tmpbuf. + * resolv/ns_print.c (ns_sprintrrf): Decrease size of t. + * string/strerror.c: Include libintl.h and errno.h. + (buf): New variable. + (strerror): Only allocate buffer if actually needed (unknown error). + * time/tzfile.c (transitions): Add libc_freeres_ptr. + (freeres): Remove. + +2002-10-25 Jakub Jelinek + + * include/libc-symbols.h (libc_freeres_ptr): New macro. + * malloc/set-freeres.c (__libc_freeres_ptrs): Define using + symbol_set_define. + (__libc_freeres): Free all pointers in that section. + * Makerules (build-shlib): Add $(LDSEDCMD-$(@F:lib%.so=%).so) to sed + commands when creating .lds script. + (LDSEDCMD-c.so): New variable. + * inet/rcmd.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rcmd_af): Use strdup to allocate ahostbuf. + * inet/rexec.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rexec_af): Use strdup to allocate ahostbuf. + * stdio-common/reg-printf.c (printf_funcs): Remove. + (__printf_arginfo_table): Change into printf_arginfo_function **. + Add libc_freeres_ptr. + (__register_printf_function): Allocate __printf_arginfo_table + and __printf_function_table the first time it is called. + * stdio-common/printf-parse.h (__printf_arginfo_table): Change into + printf_arginfo_function **. + (parse_one_spec): Add __builtin_expect. + * grp/fgetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * inet/getnetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * intl/localealias.c (libc_freeres_ptr): Define if !_LIBC. + (string_space, map): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/efgcvt.c (FCVT_BUFPTR): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/mntent.c (getmntent_buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * crypt/md5-crypt.c (libc_freeres_ptr): Define if !_LIBC. + (buffer): Add libc_freeres_ptr. + (free_mem): Remove for _LIBC. + * nss/getXXbyYY.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * nss/getXXent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * pwd/fgetpwent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * resolv/res_hconf.c (ifaddrs): Add libc_freeres_ptr. + (free_mem): Remove. + * shadow/fgetspent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/posix/ttyname.c (getttyname_name): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/getsysstats.c (mount_proc): Add + libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/ttyname.c (getttyname_name, ttyname_buf): Add + libc_freeres_ptr. + (free_mem): Remove. + +2002-10-30 Jakub Jelinek + + * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias + instead of duplicating the whole function in libc. + +2002-10-31 Roland McGrath + + * sysdeps/i386/bits/byteswap.h [__GNUC__ < 2] (__bswap_32): + Renamed from __bswap_16 (typo fix). Reported by . + +2002-10-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/Makefile (syscall-%.h): Add -D for each + 32bit-predefine when creating .new32 list and -U for each + 32bit-predefine when creating .new64 list. + * sysdeps/unix/sysv/linux/x86_64/Makefile (32bit-predefine): New. + +2002-10-29 Andreas Schwab + + * sysdeps/generic/allocrtsig.c: Include , not + "testrtsig.h". Reported by Daniel Jacobowitz . + +2002-10-25 Roland McGrath + + * sysdeps/unix/sysv/linux/configure.in: Fix typo in last change. + * sysdeps/unix/sysv/linux/configure: Regenerated. + + * sysdeps/generic/ldsodefs.h: Remove [! SHARED] conditional from + _dl_starting_up decl. + +2002-10-20 H.J. Lu + + * sysdeps/unix/sysv/linux/configure.in: Don't check + /lib/modules/`uname -r`/build/include for kernel headers if + cross compiling. + * sysdeps/unix/sysv/linux/configure: Regenerated. + +2002-10-25 Roland McGrath + + * math/math.h (M_LOG2El): Correct the value. + From Stephen L Moshier . + + * sysdeps/unix/sysv/linux/init-first.c (init): Remove [! SHARED] + conditional from __libc_multiple_libcs access. Remove kludge for weak + symbol access with old compilers we no longer support. + * sysdeps/unix/sysv/aix/init-first.c (init): Likewise. + * sysdeps/generic/libc-start.c (__libc_start_main): Likewise. + +2002-10-25 Roland McGrath + + * sysdeps/posix/sigvec.c [SA_RESETHAND]: Disable wrapper hacks and + implement SV_RESETHAND by translating it to SA_RESETHAND. + +2002-10-23 Alexandre Oliva + + * elf/dl-reloc.c (_dl_reloc_bad_use): Print the full 32-bit relocation + type on ELF64 platforms. + +2002-10-24 Ulrich Drepper + + * elf/elf.h (R_X86_64_GOTTPOFF): Renamed from r_x86_64_GOTTPOFF. + + * elf/elf.h: Define ELF_NOTE_OS_FREEBSD and NT_TASKSTRUCT. + +2002-10-24 Jakub Jelinek + + * elf/dl-misc.c: Include . + (_dl_debug_vdprintf): Only take dl_load_lock if not _dl_starting_up. + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h: Include + dl-sysdep.h. + (SYSCALL_ERROR_HANDLER): Define RTLD_PRIVATE_ERRNO variant. + (__INTERNAL_SYSCALL_STRING): Define. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h: Include + dl-sysdep.h. + (SYSCALL_ERROR_HANDLER): Define RTLD_PRIVATE_ERRNO variant. + (__INTERNAL_SYSCALL_STRING): Define. + * sysdeps/unix/sysv/linux/sparc/sysdep.h (INLINE_SYSCALL): Pass + __SYSCALL_STRING to inline_syscall*. + (INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): + New macros. + (inline_syscall0, inline_syscall1, inline_syscall2, inline_syscall3, + inline_syscall4, inline_syscall5, inline_syscall6): Add string + argument. + +2002-10-24 Roland McGrath + + * sysdeps/generic/ldsodefs.h (_dl_starting_up): Declare it here. + * sysdeps/unix/sysv/linux/init-first.c: Not here. + * sysdeps/powerpc/elf/libc-start.c: Or here. + * sysdeps/unix/sysv/aix/libc-start.c: Or here. + * sysdeps/unix/sysv/aix/start-libc.c: Or here. + * sysdeps/unix/sysv/aix/init-first.c: Or here. + * sysdeps/generic/libc-start.c: Or here. + * sysdeps/unix/sysv/linux/init-first.c (init): Protect _dl_starting_up + access with [! SHARED]. + * sysdeps/unix/sysv/aix/init-first.c (init): Likewise. + + * libio/bug-wfflush.c: New file. + * libio/Makefile (tests): Add bug-wfflush. + +2002-10-23 Roland McGrath + + * stdio-common/tst-fphex.c: New file. + * stdio-common/Makefile (tests): Add tst-fphex. + * sysdeps/generic/printf_fphex.c (__printf_fphex): Fix initialization + of WNUMEND. Fix counting of decimal point in WIDTH. Print '0' pad + chars always before the value digits. + Reported by James Antill . + +2002-10-24 Jakub Jelinek + + * posix/regcomp.c (re_comp): Call __regfree on re_comp_buf. + (free_mem): New function. + * posix/Makefile (tests): Add bug-regex14. Add bug-regex14-mem + if not cross compiling. + (generated): Add bug-regex14-mem and bug-regex14.mtrace. + (bug-regex14-ENV): Set. + (bug-regex14-mem): New target. + * posix/bug-regex14.c: New file. + +2002-10-23 Roland McGrath + + * elf/Makefile ($(objpfx)librtld.map): Use temporary file for output + target, so we don't touch it when the link fails. + + * libio/ftello.c (ftello): Use _IO_off64_t for type of POS. + Check for the result overflowing off_t and fail with EOVERFLOW. + * libio/ioftell.c (_IO_ftell): Likewise. + * libio/iofgetpos.c (_IO_new_fgetpos): Likewise. + + * login/logwtmp.c (logwtmp): If sizeof ut_tv != sizeof struct timeval, + use a temporary timeval on the stack for gettimeofday and copy it. + * login/logout.c (logout): Likewise. + Reported by Steven Munroe . + + * sysdeps/unix/sysv/linux/bits/statfs.h (struct statfs): + Use __SWORD_TYPE instead of int for member types. + (struct statfs64): Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/statfs.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/statfs.h: New file. + * sysdeps/unix/sysv/linux/ia64/bits/statfs.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/statfs.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/statfs.h: File removed. + + * sysdeps/unix/sysv/linux/sparc/bits/statvfs.h: Moved to ... + * sysdeps/unix/sysv/linux/bits/statvfs.h: ... here. + (ST_NODIRATIME): Restore fixed value of 2048. + * sysdeps/unix/sysv/linux/alpha/bits/statvfs.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/statvfs.h: File removed. + + Rearranged definitions to reduce duplication. + * sysdeps/generic/bits/types.h: Rewritten, using macros from + and new header . + * posix/Makefile (headers): Add bits/typesizes.h here. + * sysdeps/generic/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/typesizes.h: New file. + * sysdeps/mach/hurd/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/mips/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/s390/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/types.h: File removed. + * posix/sys/types.h [__USE_POSIX199506 || __USE_UNIX98]: Include + here, not in . + * signal/signal.h: Likewise. + + * streams/stropts.h: Include . + * streams/Makefile (headers): Add bits/xtitypes.h here. + * sysdeps/generic/bits/xtitypes.h: New file. + * sysdeps/s390/bits/xtitypes.h: New file. + * sysdeps/ia64/bits/xtitypes.h: New file. + * sysdeps/x86_64/bits/xtitypes.h: New file. + + * sysvipc/Makefile (headers): Add bits/ipctypes.h here. + * sysdeps/generic/bits/ipctypes.h: New file. + * sysdeps/mips/bits/ipctypes.h: New file. + * sysdeps/gnu/bits/shm.h: Include . + * sysdeps/gnu/bits/msq.h: Likewise. + * sysvipc/sys/ipc.h: Likewise. + +2002-10-22 Ulrich Drepper + + * elf/dl-load.c (struct filebuf): For buf element to have the + alignment of ElfXX_Ehdr since this is what will be stored in it. + +2002-10-22 Jakub Jelinek + + * locale/programs/locarchive.c (add_alias): Change locrec_offset arg + into pointer to locrec_offset. + (add_locale_to_archive): Adjust callers. Free normalized_name right + before returning, not immediately after add_locale, pass it to + add_alias if not NULL instead of name. Rename second normalized_name + occurence to nnormalized_codeset_name. + + * locale/programs/locarchive.c (enlarge_archive): Make sure + string_size is always a multiple of 4. + Reported by Andreas Schwab . + +2002-10-21 Andreas Schwab + + * sysdeps/unix/sysv/linux/ia64/syscalls.list (s_execve): Set + caller to EXTRA instead of execve, since the latter has a + higher-priority implementation in linuxthreads. + +2002-10-21 Roland McGrath + + * sysdeps/generic/libc-tls.c (__libc_setup_tls): Initialize the static + slotinfo list's len member to the proper size, not just 1. + Initialize static_map.l_tls_initimage. + + * elf/dl-open.c (dl_open_worker): Fix loop searching for + dtv_slotinfo_list element containing new modules' l_tls_modid. + + * elf/tst-tls9.c, elf/tst-tls9-static.c: New files. + * elf/tst-tlsmod5.c, elf/tst-tlsmod6.c: New files. + * elf/Makefile (tests): Add tst-tls9. + (tests-static): Add tst-tls9-static. + (tst-tls9-static-ENV): New variable. + ($(objpfx)tst-tls9-static, $(objpfx)tst-tls9-static.out): New targets. + + * elf/dl-close.c (remove_slotinfo): Remove an assert; the number of + modids used by partially loaded modules being closed can't be known. + +2002-10-21 Isamu Hasegawa + + * posix/Makefile: Add a test case for the bug reported by Aharon + Robbins . + * posix/bug-regex13.c: New file. + * posix/regcomp.c (peek_token_bracket): Skip the byte already read. + +2002-10-21 Ulrich Drepper + + * csu/gmon-start.c: Pretty printing. + +2002-10-19 Art Haas + + * configure.in: Replace AC_CONFIG_HEADER with AC_CONFIG_HEADERS, + add AC_HELP_STRING to all AC_ARG_WITH and AC_ARG_ENABLE macros, + add autoconf quotes to the AC_CONFIG_AUX_DIR macro. + * configure: Regenerated. + +2002-10-19 Roland McGrath + + * configure.in: Call AC_CONFIG_SUBDIRS with empty argument + and then set $subdirs directly, because the new Autoconf breaks + compatibility in every way imaginable and insists on whining + about usage that worked since the dawn of time. + * configure: Regenerated. + + * configure: Regenerated (using Autoconf 2.54). + * sysdeps/alpha/elf/configure: Likewise. + * sysdeps/generic/configure: Likewise. + * sysdeps/i386/elf/configure: Likewise. + * sysdeps/ia64/elf/configure: Likewise. + * sysdeps/mach/hurd/configure: Likewise. + * sysdeps/mach/configure: Likewise. + * sysdeps/unix/configure: Likewise. + * sysdeps/unix/common/configure: Likewise. + * sysdeps/unix/sysv/aix/configure: Likewise. + * sysdeps/unix/sysv/linux/configure: Likewise. + * sysdeps/unix/sysv/linux/mips/configure: Likewise. + * sysdeps/x86_64/elf/configure: Likewise. + + * config.make.in: Nix completely-soft nonsense. + * configure.in: Likewise. Under --without-fp, use nofpu subdirectory + of machine directories instead of fpu subdirectory. + * sysdeps/powerpc/soft-fp/Makefile: Remove cruft added in last change. + * sysdeps/powerpc/nofpu/Makefile: Put it in this new file instead. + * sysdeps/powerpc/soft-fp/sim-full.c: Moved to ... + * sysdeps/powerpc/nofpu/sim-full.c: ... here. + * sysdeps/powerpc/soft-fp/fraiseexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fraiseexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fegetexcept.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetexcept.c: ... here. + * sysdeps/powerpc/soft-fp/fclrexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fclrexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/ftestexcept.c: Moved to ... + * sysdeps/powerpc/nofpu/ftestexcept.c: ... here. + * sysdeps/powerpc/soft-fp/fgetexcptflg.c: Moved to ... + * sysdeps/powerpc/nofpu/fgetexcptflg.c: ... here. + * sysdeps/powerpc/soft-fp/fsetexcptflg.c: Moved to ... + * sysdeps/powerpc/nofpu/fsetexcptflg.c: ... here. + * sysdeps/powerpc/soft-fp/fedisblxcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fedisblxcpt.c: ... here. + * sysdeps/powerpc/soft-fp/feenablxcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/feenablxcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fegetenv.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetenv.c: ... here. + * sysdeps/powerpc/soft-fp/fesetenv.c: Moved to ... + * sysdeps/powerpc/nofpu/fesetenv.c: ... here. + * sysdeps/powerpc/soft-fp/fegetround.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetround.c: ... here. + * sysdeps/powerpc/soft-fp/fesetround.c: Moved to ... + * sysdeps/powerpc/nofpu/fesetround.c: ... here. + * sysdeps/powerpc/soft-fp/feupdateenv.c: Moved to ... + * sysdeps/powerpc/nofpu/feupdateenv.c: ... here. + * sysdeps/powerpc/soft-fp/feholdexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/feholdexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fenv_const.c: Moved to ... + * sysdeps/powerpc/nofpu/fenv_const.c: ... here. + * sysdeps/powerpc/soft-fp/libm-test-ulps: Moved to ... + * sysdeps/powerpc/nofpu/libm-test-ulps: ... here. + * sysdeps/powerpc/soft-fp/soft-supp.h: Moved to ... + * sysdeps/powerpc/nofpu/soft-supp.h: ... here. + * sysdeps/powerpc/soft-fp/Versions (libc: GLIBC_2.3.2): Moved to ... + * sysdeps/powerpc/nofpu/Versions: ... here, new file. + +2002-10-19 Bruno Haible + + * sysdeps/unix/bsd/bsd4.4/freebsd/sys/sysmacros.h: New file. + +2002-10-18 Roland McGrath + + * io/Makefile (routines): Add lchmod. + * io/sys/stat.h [__USE_BSD] (lchmod): Declare it. + * sysdeps/generic/lchmod.c: New file. + * sysdeps/mach/hurd/lchmod.c: New file. + * io/Versions (libc: GLIBC_2.3.2): New set, add lchmod. + +2002-10-18 Art Haas + + * configure.in: Remove remaining AC_FD_CC macros, and replace + AC_FD_MSG with AS_MESSAGE_FD. + +2002-10-18 Roland McGrath + + * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela): Fix + typos: VALUE -> FINALADDR. + + * sysdeps/unix/alpha/sysdep.h (INLINE_SYSCALL, INLINE_SYSCALL1) + (inline_syscall_clobbers, inline_syscall0, inline_syscall1) + (inline_syscall2, inline_syscall3, inline_syscall4, inline_syscall5) + (inline_syscall6): Move these macros ... + * sysdeps/unix/sysv/linux/alpha/sysdep.h: ... to here. + + * configure.in (libc_link_dests, libc_link_sources): Remove these + variables and the AC_LINK_FILES call. + + * sysdeps/powerpc/soft-fp/Versions (libc: GLIBC_2.3.2): Fix last + change to put new symbols here instead of in GLIBC_2.2. + * sysdeps/powerpc/Subdirs: Move this file ... + * sysdeps/powerpc/soft-fp/Subdirs: ... here. + +2002-10-07 Roland McGrath + + * sysdeps/generic/bits/time.h: Replaced with contents of the + sysdeps/unix/sysv/linux/i386/bits/time.h file. All the following + files were identical except for the absence of CLOCK_THREAD_CPUTIME_ID + and CLOCK_PROCESS_CPUTIME_ID in .../linux/bits/time.h; adding these + macros is ok even for architectures that don't now implement them. + * sysdeps/mach/hurd/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/i386/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/time.h: File removed. + +2002-10-18 Jeff Bailey + + * configure.in: Replace obsolete AC_OUTPUT syntax with + AC_CONFIG_FILES, AC_CONFIG_COMMANDS, and new-type AC_OUTPUT trio. + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDEs for + _AS_PATH_SEPARATOR_PREPARE and _AS_TEST_PREPARE. + + * configure.in: Replace AC_FD_CC with AS_MESSAGE_LOG_FD. + * sysdeps/alpha/elf/configure.in: Likewise. + * sysdeps/i386/elf/configure.in: Likewise. + * sysdeps/mach/hurd/configure.in: Likewise. + * sysdeps/x86_64/elf/configure.in: Likewise. + + * configure.in: Use AC_CONFIG_SRCDIR and new AC_INIT syntax. + + * sysdeps/alpha/elf/configure.in: Remove unneeded sinclude statement. + * sysdeps/generic/configure.in: Likewise. + * sysdeps/i386/elf/configure.in: Likewise. + * sysdeps/ia64/elf/configure.in: Likewise. + * sysdeps/mach/configure.in: Likewise. + * sysdeps/mach/hurd/configure.in: Likewise. + * sysdeps/unix/configure.in: Likewise. + * sysdeps/unix/common/configure.in: Likewise. + * sysdeps/unix/sysv/aix/configure.in: Likewise. + * sysdeps/unix/sysv/linux/configure.in: Likewise. + * sysdeps/unix/sysv/linux/mips/configure.in: Likewise. + * sysdeps/x86_64/elf/configure.in: Likewise. + + * aclocal.m4: Use just the bits from AS_INIT that are needed for the + GLIBC_PROVIDES. Use plain comment instead of HEADER-COMMENT so + that it's obvious when extra autoconf machinery is being dragged in. + +2002-10-18 Roland McGrath + + * configure.in: Remove bogus echo included in + 2002-10-08 Aldy Hernandez change. + * configure: Regenerated. + +2002-10-18 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pathconf.h (statfs_link_max): Add inline. + (statfs_filesize_max): New function. + * sysdeps/unix/sysv/linux/linux_fsinfo.h (JFFS_SUPER_MAGIC, + JFFS2_SUPER_MAGIC, JFS_SUPER_MAGIC, NTFS_SUPER_MAGIC, + ROMFS_SUPER_MAGIC, UDF_SUPER_MAGIC): Define. + * sysdeps/unix/sysv/linux/fpathconf.c (__fpathconf): Use + statfs_filesize_max. + * sysdeps/unix/sysv/linux/pathconf.c (__pathconf): Likewise. + * sysdeps/unix/sysv/linux/alpha/fpathconf.c: Removed. + * sysdeps/unix/sysv/linux/alpha/pathconf.c: Removed. + +2002-10-17 Roland McGrath + + * configure.in (MIG): Just AC_SUBST it here. + * configure: Regenerated. + * sysdeps/mach/configure.in (MIG): Do the AC_CHECK_TOOL here. + Adding final - argument to all AC_CHECK_HEADER uses for .defs files. + * sysdeps/mach/configure: Regenerated. + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDE([_AS_TR_SH_PREPARE]) + and AC_PROVIDE([_AS_CR_PREPARE]). + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDE([_AS_ECHO_N_PREPARE]). + Remove AC_LANG(C) call, instead just define([_AC_LANG], [C]). + + * elf/dl-support.c: Move _dl_tls_* variables to ... + * sysdeps/generic/libc-tls.c: ... here. + + * elf/dl-close.c (remove_slotinfo): Take new argument. If false, + allow IDX to be one past the current last slotinfo entry. + (_dl_close): Pass IMAP->l_init_called for that parameter. + +2002-10-07 Andreas Schwab + + * aclocal.m4: Fix for autoconf 2.53. + * configure.in: Likewise. Require autoconf 2.53. + +2002-10-08 Richard Henderson + + * soft-fp/op-4.h: Handle carry correctly in + __FP_FRAC_ADD_3, __FP_FRAC_ADD_4, __FP_FRAC_SUB_3, + __FP_FRAC_SUB_4, __FP_FRAC_DEC_3, __FP_FRAC_DEC_4. + * soft-fp/op-common.h: New macros _FP_DIV_MEAT_N_loop. + +2002-10-08 Aldy Hernandez + + * configure.in: Compute completely-soft. + * config.make.in: Make completely-soft available to sub-makes. + * sysdeps/powerpc/soft-fp/Makefile: Add gcc-single-routines and + gcc-double-routines. Add sim-full.c. Add fenv_const and + fe_nomask to libm-support. + * sysdeps/powerpc/soft-fp/sim-full.c: New file. + * sysdeps/powerpc/soft-fp/fraiseexcpt.c: New file. + * sysdeps/powerpc/soft-fp/fegetexcept.c: New file. + * sysdeps/powerpc/soft-fp/fclrexcpt.c: New file. + * sysdeps/powerpc/soft-fp/ftestexcept.c: New file. + * sysdeps/powerpc/soft-fp/fgetexcptflg.c: New file. + * sysdeps/powerpc/soft-fp/fsetexcptflg.c: New file. + * sysdeps/powerpc/soft-fp/fedisblxcpt.c: New file. + * sysdeps/powerpc/soft-fp/feenablxcpt.c: New file. + * sysdeps/powerpc/soft-fp/fegetenv.c: New file. + * sysdeps/powerpc/soft-fp/fesetenv.c: New file. + * sysdeps/powerpc/soft-fp/fegetround.c: New file. + * sysdeps/powerpc/soft-fp/fesetround.c: New file. + * sysdeps/powerpc/soft-fp/feupdateenv.c: New file. + * sysdeps/powerpc/soft-fp/feholdexcpt.c: New file. + * sysdeps/powerpc/soft-fp/fenv_const.c: New file. + * sysdeps/powerpc/soft-fp/libm-test-ulps: New file. + * sysdeps/powerpc/soft-fp/soft-supp.h: New file. + * sysdeps/powerpc/soft-fp/Versions: Add libgcc soft-float + symbols. Add __sim_disabled_exceptions, __sim_exceptions, + __sim_round_mode. + * sysdeps/powerpc/soft-float/Dist: Add sim-full.c, fenv_const.c. + * sysdeps/powerpc/soft-float/sfp-machine.h: Define + FP_HANDLE_EXCEPTIONS. + Define FP_ROUNDMODE. + Redefine FP_* macros to correspond to the FE_* bit positions. + Define FP_DIV_MEAT_S to _FP_DIV_MEAT_1_loop. + Define externs for __sim_exceptions, __sim_disabled_exceptions, + __sim_round_mode, __simulate_exceptions. + * sysdeps/powerpc/fpu/bits/fenv.h: Move file from here... + * sysdeps/powerpc/bits/fenv.h: ...to here. + +2002-10-06 Jakub Jelinek + + * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela): + Store R_PPC_UADDR32 and R_PPC_UADDR16 one byte at a time. + Use __builtin_expect for R_PPC_ADDR24 overflow check. Fix + R_PPC_ADDR16, R_PPC_UADDR16 and R_PPC_ADDR14* overflow check, use + __builtin_expect. + +2002-10-15 Jakub Jelinek + + * include/resolv.h (__libc_res_nquery, __libc_res_nsearch, + __libc_res_nsend): New prototypes. + * resolv/res_query.c (QUERYSIZE): Define. + (__libc_res_nquery): Renamed from res_nquery. Added answerp + argument. Allocate only QUERYSIZE bytes first, if res_nmkquery + fails use MAXPACKET buffer. Call __libc_res_nsend instead of + res_nsend, pass answerp. + (res_nquery): Changed into wrapper around __libc_res_nquery. + (__libc_res_nsearch): Renamed from res_nsearch. Added answerp + argument. Call __libc_res_nquerydomain and __libc_res_nquery + instead of the non-__libc_ variants, pass them answerp. + (res_nsearch): Changed into wrapper around __libc_res_nsearch. + (__libc_res_nquerydomain): Renamed from res_nquerydomain. + Added answerp argument. Call __libc_res_nquery instead of + res_nquery, pass answerp. + (res_nquerydomain): Changed into wrapper around + __libc_res_nquerydomain. + * resolv/res_send.c: Include sys/ioctl.h. + (MAXPACKET): Define. + (send_vc): Change arguments. Reallocate answer buffer if it is + too small. + (send_dg): Likewise. + (__libc_res_nsend): Renamed from res_nsend. Added ansp argument. + Reallocate answer buffer if it is too small and hooks are in use. + Adjust calls to send_vc and send_dg. + (res_nsend): Changed into wrapper around __libc_res_nsend. + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r): Allocate + just 1K answer buffer on the stack, use __libc_res_nsearch instead + of res_nsearch. + (_nss_dns_gethostbyaddr_r): Similarly with __libc_res_nquery. + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyaddr_r): Likewise. + (_nss_dns_getnetbyname_r): Similarly with __libc_res_nsearch. + * resolv/gethnamaddr.c (gethostbyname2): Likewise. + (gethostbyaddr): Similarly with __libc_res_nquery. + * resolv/Versions (libresolv): Export __libc_res_nquery and + __libc_res_nsearch at GLIBC_PRIVATE. + +2002-10-17 Roland McGrath + + * configure.in: Grok --without-__thread and disable HAVE___THREAD. + * configure: Regenerated. + + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Do CHECK_STATIC_TLS + before performing the reloc, not after. + * sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise. + +2002-10-17 Ulrich Drepper + + * locale/programs/locale.c (write_locales): Use 'm' flag in fopen call. + * locale/programs/linereader.c (lr_open): Likewise. + * locale/programs/charmap-dir.c (charmap_open): Likewise. + * locale/programs/locarchive.c (add_locale_to_archive): Likewise. + +2002-10-17 Isamu Hasegawa + + * posix/bug-regex11.c: Add a test case for the bug reported by + Paolo Bonzini . + * posix/regexec.c (sift_states_bkref): Use correct destination of + the back reference. + +2002-10-17 Roland McGrath + + * elf/dl-load.c (_dl_map_object_from_fd): Don't check DF_STATIC_TLS. + * elf/dl-reloc.c (_dl_relocate_object: CHECK_STATIC_TLS): New macro + to signal error if an IE-model TLS reloc resolved to a dlopen'd module. + * sysdeps/i386/dl-machine.h (elf_machine_rel, elf_machine_rela): + Call it after performing TPOFF relocs. + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise. + * sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise. + * elf/dl-conflict.c (CHECK_STATIC_TLS): New macro (no-op). + + * elf/dl-close.c (remove_slotinfo): Change asserts so as not to crash + when closing a partially-initialized object. + + * elf/dl-load.c (_dl_map_object_from_fd) [! USE_TLS]: Call lose + instead of _dl_fatal_printf when we see PT_TLS. + + * Makeconfig (CPPFLAGS): Fix last change to use $(libof-$( + + * cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Variable removed. + instead of += to append, to be sure $(lib) gets expanded at defn time. + (libof-$(cpp-src)): New variable, define this instead. + * extra-lib.mk (cpp-srcs-left): Reduce duplication in include setup. + (lib): Don't use override. + (CPPFLAGS-$(lib)): New variable, put -D's here. + * Makeconfig (CPPFLAGS): Use basename fn for CPPFLAGS-basename. + Also add $(CPPFLAGS-LIB) before the file-specific flags, for each + LIB found by $(libof-*) for basename, target, or source. + * Makerules (CPPFLAGS-nonlib): New variable. + * nscd/Makefile (lib): Set to nonlib when using cppflags-iterator.mk. + * locale/Makefile (lib): Likewise. + * sunrpc/Makefile (lib): Likewise. + + * sysdeps/unix/sysv/linux/fpathconf.c (LINUX_LINK_MAX): Move macro ... + * sysdeps/unix/sysv/linux/linux_fsinfo.h (LINUX_LINK_MAX): ... here. + * sysdeps/unix/sysv/linux/pathconf.h: New file. + (statfs_link_max): New function, guts from fpathconf.c. + * sysdeps/unix/sysv/linux/fpathconf.c: Rewritten using that. + * sysdeps/unix/sysv/linux/pathconf.c (__pathconf): Likewise. + * sysdeps/unix/sysv/linux/alpha/pathconf.c (__pathconf): Rewritten + to use the linux/pathconf.c code by #include rather than duplication. + * sysdeps/unix/sysv/linux/alpha/fpathconf.c (__pathconf): Likewise. + +2002-10-16 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Use __libc_errno only for libc itself. + +2002-10-16 Andreas Jaeger + + * sysdeps/x86_64/_mcount.S: Fix off-by-1 error in argument access. + +2002-10-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_ERROR_HANDLER): + Use __libc_errno only for libc itself. + +2002-10-15 Roland McGrath + Jakub Jelinek + + * sysdeps/unix/sysv/linux/Makefile + ($(objpfx)syscall-%.h $(objpfx)syscall-%.d): Take code from + sparc/Makefile to produce a bi-arch file as needed. + That's now parameterized by the variable $(64bit-predefine). + Use LC_ALL=C for `comm' commands in that rule. + No longer conditional on [$(no_syscall_list_h)]. + * sysdeps/unix/sysv/linux/sparc/Makefile: Remove replacement rules. + (64bit-predefine): New variable. + * sysdeps/unix/sysv/linux/x86_64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/Makefile: New file. + * sysdeps/unix/sysv/linux/powerpc/Makefile + (64bit-predefine): New variable. + +2002-10-15 Roland McGrath + + * sysdeps/unix/sysv/linux/Makefile + ($(objpfx)syscall-%.h $(objpfx)syscall-%.d) + + * login/utmp-private.h: Declare __libc_utmp_lock. + * sysdeps/unix/getlogin_r.c (getlogin_r): Take __libc_utmp_lock once + and call __libc_utmp_jump_table functions directly, instead of using + __setutent et al. + + * sysdeps/unix/sysv/linux/configure.in: Use case instead of if. + * sysdeps/unix/sysv/linux/configure: Regenerated. + + * sysdeps/gnu/bits/utmp.h: Include . + (struct lastlog) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: + Use int32_t for ll_time. + (struct utmp) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: + Use int32_t instead of long int for ut_session. + Use an anonymous struct with 32-bit fields for ut_tv. + * sysdeps/gnu/bits/utmpx.h: Include . + (struct utmpx) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: Do the same + here as in utmp.h for `struct utmp'. + * sysdeps/unix/sysv/linux/powerpc/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/powerpc/bits/utmpx.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/utmpx.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/utmpx.h: File removed. + + * sysdeps/unix/sysv/linux/bits/resource.h: Replaced with the contents + of the sysdeps/unix/sysv/linux/i386/bits/resource.h file. + All the following files were identical or equivalent to it. + * sysdeps/unix/sysv/linux/i386/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/arm/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/cris/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/hppa/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/m68k/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/powerpc/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/s390/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/sh/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/resource.h: File removed. + + * sysdeps/unix/sysv/linux/bits/socket.h (struct msghdr): Use size_t + instead of int for msg_iovlen, instead of socklen_t for msg_controllen. + Other than the previously incorrect sign of msg_iovlen, this is a + no-op on 32-bit platforms. On 64-bit platforms it makes this header + match their layouts as well, so the following are now identical to it. + * sysdeps/unix/sysv/linux/s390/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/alpha/bits/socket.h: File removed. + +2002-10-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_VFORK_SYSCALL): + Define for 2.4+ kernels. + + * sysdeps/unix/sysv/linux/i386/vfork.S: Optimize for kernels which + are known to have the vfork syscall. Don't confuse the CPUs + branch prediction unit by jumping to the return address. + + * sysdeps/unix/sysv/linux/alpha/fpathconf.c (__fpathconf): Add + support for reiserfs and xfs. + + * sysdeps/unix/sysv/linux/fpathconf.c (__fpathconf): Add case for + XFS link count. + * sysdeps/unix/sysv/linux/linux_fsinfo.h: Define XFS_SUPER_MAGIC + and XFS_LINK_MAX. + Patch by Eric Sandeen [PR libc/4706]. + +2002-10-16 Jakub Jelinek + + * include/libc-symbols.h (attribute_tls_model_ie): Define. + * include/errno.h (errno): Define to __libc_errno in libc.so. + Add attribute_tls_model_ie. + * include/netdb.h (h_errno): Define to __libc_h_errno in libc.so. + Add attribute_tls_model_ie. + * include/resolv.h (_res): Define to __libc_res in libc.so. Add + attribute_tls_model_ie. + * inet/herrno.c (__libc_h_errno): Add hidden alias to h_errno. + (h_errno): Define. + * resolv/res_libc.c (__libc_res): Add hidden alias to _res. + (_res): Define. + * sysdeps/generic/bits/libc-tsd.h (__libc_tsd_define): Add + attribute_tls_model_ie. + * sysdeps/generic/errno-loc.c (errno): Only undefine if not using + __thread. + * sysdeps/generic/errno.c (__libc_errno): Add hidden alias to errno. + * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_ERROR_HANDLER): Use + __libc_errno in USE___THREAD case. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Likewise. + * configure.in (HAVE_TLS_MODEL_ATTRIBUTE): Check for + __attribute__((tls_model (""))). + * configure: Rebuilt. + * config.h.in (HAVE_TLS_MODEL_ATTRIBUTE): Add. + +2002-10-15 Ulrich Drepper + + * timezone/asia: Update from tzdata2002d. + * timezone/australasia: Likewise. + * timezone/iso3166.tab: Likewise. + * timezone/southamerica: Likewise. + * timezone/zone-tab: Likewise. + +2002-10-15 Roland McGrath + + * sysdeps/generic/dl-tls.c (_dl_deallocate_tls) [TLS_TCB_AT_TP]: + Adjust TCB pointer before calling free, so we get the whole block. + +2002-10-14 Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/sigaction.c + [HAVE_HIDDEN && !HAVE_BROKEN_VISIBILITY_ATTRIBUTE]: Declare restore_rt + extern using attribute_hidden instead of static, avoids warning. + +2002-10-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/configure.in: Use */lib64 for s390x too. + * sysdeps/unix/sysv/linux/configure: Rebuilt. + +2002-10-14 Ulrich Drepper + + * po/sv.po: Update from translation team. + +2002-10-12 H.J. Lu + + * sunrpc/thrsvc.c (PROCQUIT): New. + (struct rpc_arg): New. + (dispatch): Call exit (0) if request->rq_proc == PROCQUIT. + (test_one_call): Take struct rpc_arg * instead of CLIENT *c. + (thread_wrapper): Modified for struct rpc_arg * and call PROCQUIT. + (main): Modified for struct rpc_arg *. + +2002-10-14 Ulrich Drepper + + * dirent/scandir.c: Rearrange code a bit to reduce binary size. + +2002-10-14 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Include tls.h. + (SYSCALL_ERROR_HANDLER): Use RTLD_PRIVATE_ERRNO sequence + in ld.so even if __thread is supported. + +2002-10-13 Jakub Jelinek + + * sysdeps/unix/sysv/linux/arm/profil-counter.h (profil_counter): + Add hack to prevent the compiler from clobbering the signal context. + * sysdeps/unix/sysv/linux/sh/profil-counter.h (profil_counter): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/profil-counter.h (profil_counter): + Likewise. + +2002-10-14 Andreas Jaeger + + * sysdeps/mips/fpu/libm-test-ulps: Regenerated by + Guido Guenther . + +2002-10-14 Ulrich Drepper + + * po/sk.po: Update from translation team. + +2002-09-26 Roland McGrath + + * elf/dl-load.c (_dl_dst_count, _dl_dst_substitute): Handle $LIB + dynamic string tag. + * elf/Makefile ($(objpfx)trusted-dirs.st): Make the output define + DL_DST_LIB based on $(slibdir). + +2002-10-13 Roland McGrath + + * elf/rtld-Rules ($(objpfx)rtld-libc.a): Use $(verbose) in ar command. + + * sysdeps/mach/hurd/getresuid.c: New file. + * sysdeps/mach/hurd/getresgid.c: New file. + * sysdeps/mach/hurd/setresuid.c: New file. + * sysdeps/mach/hurd/setresgid.c: New file. + + * posix/unistd.h [__USE_GNU] (getresuid, getresgid, setresuid, + setresgid): Declare them. + * NEWS: Mention it. + * include/unistd.h + (__getresuid, __getresgid, __setresuid, __setresgid): Declare them, + add libc_hidden_proto. + * posix/Versions (libc: GLIBC_2.3.2): New set. Add + getresuid, getresgid, setresuid, setresgid here. + * Versions.def (libc): Define GLIBC_2.3.2 set. + * sysdeps/generic/getresuid.c (__getresuid): Fix argument types. + Add libc_hidden_def. + * sysdeps/generic/getresgid.c (__getresgid): Likewise. + * sysdeps/generic/setresgid.c: New file. + * sysdeps/generic/setresuid.c: New file. + * sysdeps/unix/sysv/linux/Makefile [$(subdir) = misc] + (sysdep_routines): Don't add getresuid and getresgid here. + * sysdeps/unix/sysv/linux/arm/Makefile [$(subdir) = misc] + (sysdep_routines): Don't add setresuid and setresgid here. + * sysdeps/unix/sysv/linux/cris/Makefile: Likewise. + * sysdeps/unix/sysv/linux/sh/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. + * sysdeps/unix/sysv/linux/m68k/Makefile: Likewise. + * posix/Makefile (routines): Add them all here instead. + * sysdeps/unix/sysv/linux/i386/getresuid.c (getresuid): Renamed to + __getresuid. Add libc_hidden_def for that, and weak alias to old name. + * sysdeps/unix/sysv/linux/i386/getresgid.c (getresgid): Renamed to + __getresgid. Add libc_hidden_def for that, and weak alias to old name. + * sysdeps/unix/sysv/linux/i386/setresuid.c: Add libc_hidden_def. + [! __NR_setresuid]: Include generic file. + * sysdeps/unix/sysv/linux/i386/setresgid.c (setresgid): Renamed to + __setresgid. Add libc_hidden_def for that, and weak alias to old name. + [! __NR_setresuid]: Include generic file. + * sysdeps/unix/sysv/linux/syscalls.list (setresuid, setresgid): + Caller is - now, not EXTRA. + * sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list + (setresuid, setresgid, getresuid, getresgid): Likewise. + * sysdeps/unix/sysv/linux/syscalls.list (getresuid, getresgid): + Add these calls here. + * sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove them here. + * sysdeps/unix/sysv/linux/hppa/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/x86_64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/mips/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/ia64/syscalls.list: Likewise. + + * sysdeps/unix/sysv/linux/Makefile [$(subdir) = misc] + (sysdep_routines): Add setfsuid and setfsgid here. + * sysdeps/unix/sysv/linux/arm/Makefile: Not here. + * sysdeps/unix/sysv/linux/sparc/sparc32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/cris/Makefile: Likewise. + * sysdeps/unix/sysv/linux/sh/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. + * sysdeps/unix/sysv/linux/m68k/Makefile: Likewise. + + * hurd/errno.c: Renamed to ... + * hurd/errno-loc.c: ... this. + * hurd/Makefile (routines): errno -> errno-loc + +2002-10-13 Ulrich Drepper + + * po/de.po: Update from translation team. + + * MakeTAGS: Add -E flag to xgettext runs. + +2002-10-12 Ulrich Drepper + + * po/fr.po: Update from translation team. + + * sysdeps/posix/system.c: Remove support for old and buggy SCO systems. + Optimize a bit for use in glibc. + +2002-10-12 Roland McGrath + + * stdio-common/tst-rndseek.c (TIMEOUT): Increase to 10 seconds. + Some machines are slow. Guido Guenther has one. + +2002-10-12 Ulrich Drepper + + * po/sv.po: Update from translation team. + +2002-10-11 Isamu Hasegawa + + * posix/regcomp.c (re_compile_fastmap_iter): Remove the handling + OP_CONTEXT_NODE. + (regfree): Likewise. + (create_initial_state): Likewise. + (analyze): Remove the substitutions which became useless. + (calc_first): Likewise. + (calc_epsdest): Use edests of OP_BACK_REF in case that it has + epsilon destination. + (duplicate_node_closure): New function. + (duplicate_node): Remove the handling OP_CONTEXT_NODE. + (calc_inveclosure): Likewise. + (calc_eclosure): Likewise. + (calc_eclosure_iter): Invoke duplicate_node_closure instead of + direct invocation of duplicate_node. + (parse): Don't use comma operator in the return to avoid compiler + warning. + (parse_reg_exp): Likewise. + (parse_branch): Likewise. + (parse_expression): Likewise. + (parse_sub_exp): Likewise. + (parse_dup_op): Likewise. + * posix/regex_internal.c (re_dfa_add_node): Remove the substitutions + which became useless. + (create_ci_newstate): Remove the handling OP_CONTEXT_NODE. + (create_cd_newstate): Likewise. + * posix/regex_internal.h (re_token_type_t): Remove the obsolete type. + (re_token_t): Likewise. + (re_dfa_t): Likewise. + (re_node_set_remove): New macro. + * posix/regexec.c (check_matching): Remove the handling + OP_CONTEXT_NODE. + (check_halt_node_context): Likewise. + (proceed_next_node): Likewise. + (pop_fail_stack): Fix the memory leak. + (set_regs): Likewise. + (free_fail_stack_return): New function. + (sift_states_backward): Fix the memory leak. Remove the handling + OP_CONTEXT_NODE. + (update_cur_sifted_state): Append some if clause to avoid redundant + call. + (sub_epsilon_src_nodes): Use IS_EPSILON_NODE since it might be a + back reference. + (check_dst_limits): Remove the handling OP_CONTEXT_NODE. + (check_subexp_limits): Likewise. + (search_subexp): Likewise. + (sift_states_bkref): Likewise. + (transit_state_mb): Likewise. + (transit_state_bkref_loop): Likewise. + (transit_state_bkref_loop): Likewise. + (group_nodes_into_DFAstates): Likewise. + (check_node_accept): Likewise. + (sift_ctx_init): Add initializing. + +2002-10-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep.h (INLINE_SYSCALL): Use + __builtin_expect. + +2002-10-11 Ulrich Drepper + + * elf/dl-load.c (_dl_map_object_from_fd): Remove unnecessarily + duplicated variable c. + + * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Use INTERNAL_SYSCALL + if possible. + + * sysdeps/unix/sysv/linux/i386/sysdep.h + (INTERNAL_SYSCALL_ERROR_P): New define. + (INTERNAL_SYSCALL_ERRNO): Likewise. + + * sysdeps/unix/sysv/linux/i386/profil-counter.h (profil_counter): + Add hack to prevent the compiler from clobbering the signal context. + +2002-10-11 Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Fix typos. + + * sysdeps/generic/dl-lookupcfg.h: Include . + * sysdeps/sh/dl-lookupcfg.h: File removed. + * sysdeps/i386/dl-lookupcfg.h: File removed. + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): Add + missing labels and ; from last change. + + * stdio-common/tst-sscanf.c (val_double): Append .0 to large whole + number literals, so they are doubles instead of ints. + +2002-10-09 Roland McGrath + + * sysdeps/generic/bits/libc-tsd.h [USE___THREAD]: Conditional + changed from [USE_TLS && HAVE___THREAD]. + + * sysdeps/i386/dl-machine.h (elf_machine_type_class, elf_machine_rel): + Disable TLS relocs if [RTLD_BOOTSTRAP && !USE___THREAD]. + * sysdeps/x86_64/dl-machine.h + (elf_machine_type_class, elf_machine_rela): Likewise. + * sysdeps/sh/dl-machine.h (elf_machine_type_class, elf_machine_rela): + Likewise. + + * include/link.h (struct link_map): Remove member l_tls_tp_initialized. + * elf/rtld.c (_dl_start_final, dl_main): Don't use it. + (_dl_start): Conditionalize PT_TLS check on [USE___THREAD]. + + * sysdeps/i386/dl-tls.h (__TLS_GET_ADDR): Use ___tls_get_addr_internal + instead of ___tls_get_addr. + (___tls_get_addr_internal): Add attribute_hidden to decl. + + * sysdeps/generic/ldsodefs.h (struct rtld_global): New variable + _dl_error_catch_tsd. + * elf/rtld.c (startup_error_tsd): New function. + (dl_main): Point _dl_error_catch_tsd at that. + * elf/dl-error.c: Don't use libc-tsd.h for DL_ERROR, + use new function pointer instead. + * elf/dl-tsd.c: New file. + * elf/Makefile (routines): Add it. + +2002-10-07 Roland McGrath + + * elf/dl-misc.c (_dl_debug_vdprintf): Use INTERNAL_SYSCALL macro for + writev if it's available. Otherwise if [RTLD_PRIVATE_ERRNO] then + take _dl_load_lock around calling __writev. + + * sysdeps/unix/sysv/linux/i386/sysdep.h (INTERNAL_SYSCALL): New macro. + (INLINE_SYSCALL): Use that. + + * sysdeps/generic/dl-sysdep.h: New file. + * sysdeps/mach/hurd/dl-sysdep.h: New file. + * sysdeps/generic/ldsodefs.h: Include . + * include/errno.h [IS_IN_rtld]: Include to define ... + [RTLD_PRIVATE_ERRNO]: Use a hidden global variable for errno and + access it directly. + * elf/dl-minimal.c (__errno_location): Removed. + * sysdeps/unix/i386/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: + Use GOTOFF access for errno. + * sysdeps/unix/sysv/linux/i386/sysdep.h + [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. + + * sysdeps/unix/x86_64/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: + Use PC-relative access for errno. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h + [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. + + * include/tls.h: New file. + (USE___THREAD): New macro. + Define to 1 under [USE_TLS && HAVE___THREAD] and only when compiling + libc or libpthread. + * sysdeps/unix/sysv/linux/i386/sysdep.h [USE___THREAD]: Conditional + changed from [USE_TLS && HAVE___THREAD]. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. + * sysdeps/unix/i386/sysdep.S: Likewise. + * sysdeps/unix/x86_64/sysdep.S: Likewise. + * include/errno.h: Likewise. + * include/netdb.h: Likewise. + * include/resolv.h: Likewise. + + * sysdeps/generic/errno.c: New file. + * csu/Makefile (aux): New variable, list errno. + * sysdeps/unix/sysv/linux/i386/sysdep.S (errno, _errno): Remove defns. + * sysdeps/unix/sysv/linux/m68k/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/arm/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/cris/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/hppa/sysdep.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/sysdep.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep.S: Likewise. + * sysdeps/unix/alpha/sysdep.S: Likewise. + * sysdeps/generic/start.c: Likewise. + * sysdeps/unix/start.c: Likewise. + * sysdeps/unix/arm/start.c: Likewise. + * sysdeps/unix/bsd/ultrix4/mips/start.S: Likewise. + * sysdeps/unix/sparc/start.c: Likewise. + * sysdeps/unix/sysv/irix4/start.c: Likewise. + * sysdeps/unix/sysv/linux/mips/sysdep.S: File removed. + + * manual/search.texi (Tree Search Function, Hash Search Function): + Mention search.h clearly. + +2002-10-05 Roland McGrath + + * elf/dl-fxstat64.c: File removed. + * elf/dl-xstat64.c: File removed. + * elf/Makefile (rtld-routines): Remove them. + * sysdeps/unix/sysv/linux/xstat64.c: Remove RTLD_STAT64 conditionals. + Instead, use strong_alias instead of versioned_symbol in the + !SHLIB_COMPAT case. + * sysdeps/unix/sysv/linux/fxstat64.c: Likewise. + * sysdeps/unix/sysv/linux/lxstat64.c: Likewise. + + * include/shlib-compat.h + (SHLIB_COMPAT): Require that IS_IN_##lib be defined nonzero. + [! NOT_IN_libc] (IS_IN_libc): Define it. + * cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Use -Dx=1 not just -Dx. + * elf/Makefile (CPPFLAGS-.os): Likewise. + + * sunrpc/rpc_main.c (main): Don't declare with noreturn attribute. + Return the status instead of calling exit. + + * Makeconfig (CFLAGS): Prepend -std=gnu99. + * Makerules (+make-deps): Use $(CFLAGS) only for .c sources. + Remove superfluous rm command, whose @ plus make bugs hid + all these commands from the make output. + + * include/stubs-prologue.h: New file. Give #error under #ifdef _LIBC. + * Makefile ($(inst_includedir)/gnu/stubs.h): Depend on it. + Use that file's contents instead of literal echo's for the prologue. + * include/features.h: Include unconditionally. + * include/gnu/stubs.h: New file. + +2002-09-30 Roland McGrath + + * elf/rtld-Rules: New file. + * elf/Makefile ($(objpfx)librtld.map, $(objpfx)librtld.mk, + $(objpfx)rtld-libc.a): New targets. + (generated): Add them. + (reloc-link): Remove -o $@ from the variable. + ($(objpfx)dl-allobjs.os): Add -o $@ after $(reloc-link). + (distribute): Add rtld-Rules. + (CPPFLAGS-.os): Define this instead of CFLAGS-.os. + * Makerules ($(+sysdir_pfx)sysd-rules): Emit rules for rtld-% targets. + (common-mostlyclean, common-clean): Clean up rtld-* files. + * sysdeps/unix/make-syscalls.sh: Add rtld-*.os target name to rules. + +2003-05-20 Jakub Jelinek + + * elf/dynamic-link.h (elf_get_dynamic_info): Add temp argument. + If temp != NULL, copy dynamic entries which need relocation to temp + array before relocating. + (DL_RO_DYN_TEMP_CNT): Define. + * elf/dl-load.c (_dl_map_object_from_fd): Adjust caller. + * elf/rtld.c (_dl_start): Likewise. + (dl_main): Likewise. Add dyn_temp static variable. + +2002-10-11 Roland McGrath + + * sysdeps/generic/dl-tls.c (__tls_get_addr): After freeing block in + now-unused dtv slot, reset the slot to TLS_DTV_UNALLOCATED. + + * elf/tls-macros.h [__x86_64__] (TLS_GD): Fix the sequence with the + proper set of no-op insn prefixes. + + * elf/tst-tls8.c (do_test): Use %zd format for l_tls_modid members. + +2002-10-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/execve.c: Don't try calling + __pthread_kill_other_threads_np. + + * sysdeps/generic/pselect.c: Avoid unnecessary sigprocmask calls. + +2002-10-08 Roland McGrath + + * locale/newlocale.c (__newlocale): If setting all categories to "C", + just return &_nl_C_locobj instead of copying it. + * locale/freelocale.c (__freelocale): Check for &_nl_C_locobj. + * locale/duplocale.c (__duplocale): Likewise. + +2002-10-07 Roland McGrath + + * config.h.in (HAVE_I386_SET_GDT): New #undef. + * sysdeps/mach/configure.in: Define it with new check for i386_set_gdt. + * sysdeps/mach/configure: Regenerated. + +2002-10-06 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h (INLINE_SYSCALL): + Add all necessary register outputs for syscall-clobbered registers. + +2002-10-02 David Mosberger + + * sysdeps/ia64/bzero.S: Rewritten by Sverre Jarp to tune for + Itanium 2 (and Itanium). + Fix unwind directives and make it fit in 80 columns. + * sysdeps/ia64/memset.S: Likewise. + * sysdeps/ia64/memcpy.S: Likewise. + Move jump table to .rodata section. + +2002-10-03 Roland McGrath + + * sysdeps/mach/hurd/i386/init-first.c (_hurd_stack_setup): Add + clobbers to asm. + +2002-10-10 Andreas Jaeger + + * sysdeps/x86_64/_mcount.S: Restore correct registers. + +2002-10-10 Ulrich Drepper + + * posix/Versions (libc) [GLIBC_PRIVATE]: Add __pselect. + +2002-10-09 Ulrich Drepper + + * sysdeps/generic/ldsodefs.h: Remove attribute_hidden from + _dl_allocate_tls_init. Add rtld_hidden_proto. + * sysdeps/generic/dl-tls.c (_dl_allocate_tls_init): Add + rtld_hidden_def. + * elf/Versions (ld) [GLIBC_PRIVATE]: Add _dl_allocate_tls_init. + + * version.h (VERSION): Bump to 2.3.1. + + * Make-dist: Add back one of the tar invocations removed before. + + * stdlib/Makefile (distribute): Add allocalim.h. + + * sysdeps/generic/bits/libc-tsd.h [!(USE_TLS && HAVE___THREAD)] + (__libc_tsd_address): Use correct variable name. + Patch by Stefan Jones . + + * sysdeps/unix/sysv/linux/ia64/getcontext.S: Add missing ;;. + Reported by edwardsg@sgi.com [PR libc/4678]. + + * Versions.def (libc): Add GLIBC_2.3.1. + (libpthread): Add GLIBC_2.3.1. + + * include/signal.h: Add libc_hidden_proto for __sigwait, __sigwaitinfo, + and __sigtimedwait. + * signal/Versions: Add __sigtimedwait, __sigwait, and __sigwaitinfo. + * sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Add + libc_hidden_def. + * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Likewise. + * sysdeps/unix/sysv/linux/sigwaitinfo.c (__sigwaitinfo): Likewise. + + * include/sys/msg.h: Declare __libc_msgrcv and __libc_msgsnd. + * sysdeps/unix/sysv/linux/msgrcv.c (__msgrcv): Rename to __libc_msgrcv + and make old name an alias. + * sysdeps/unix/sysv/linux/msgsnd.c (__msgsnd): Rename to __libc_msgsnd + and make old name an alias. + * sysvipc/Versions (libc) [GLIBC_PRIVATE]: Add __libc_msgrcv and + __libc_msgsnd. + + * include/sys/uio.h: Declare __libc_readv and __libc_writev. + * misc/Versions (libc) [GLIBC_PRIVATE]: Add __libc_readv and + __libc_writev. + * sysdeps/generic/readv.c (__readv): Rename to __libc_readv and make + old name an alias. + * sysdeps/posix/readv.c: Likewise + * sysdeps/unix/sysv/aix/readv.c: Likewise. + * sysdeps/unix/sysv/linux/readv.c: Likewise. + * sysdeps/generic/writev.c (__writev): Rename to __libc_writev and make + old name an alias. + * sysdeps/posix/writev.c: Likewise + * sysdeps/unix/sysv/aix/writev.c: Likewise. + * sysdeps/unix/sysv/linux/writev.c: Likewise. + + * include/sys/wait.h: Declare __waitid. + * posix/Versions (libc) [GLIBC_PRIVATE]: Add __waitid. + * sysdeps/generic/waitid.c (waitid): Rename to __waitid and make old + name an alias. + * sysdeps/posix/waitid.c: Likewise. + * sysdeps/unix/sysv/aix/waitid.c: Likewise. + + * sysdeps/unix/sysv/linux/syscalls.list: Add creat syscall. + +2002-10-07 Jakub Jelinek + + * include/alloca.h (__libc_use_alloca, __libc_alloca_cutoff): New + prototypes. + (__MAX_ALLOCA_CUTOFF): Define. + Include allocalim.h. + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r, + _nss_dns_gethostbyaddr_r): Use alloca or malloc to allocate + host_buffer depending on __libc_use_alloca. + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r, + _nss_dns_getnetbyaddr_r): Use alloca or malloc to allocate + net_buffer depending on __libc_use_alloca. + * resolv/res_query.c (res_nquery): Use alloca or malloc to allocate + buf depending on __libc_use_alloca. + * resolv/gethnamaddr.c (gethostbyname2, gethostbyaddr): Likewise. + * stdio-common/vfprintf.c (vfprintf): Use __libc_use_alloca + instead of hardcoded constants. + Pass proper size argument to alloca and compute end for wide char + version. + * stdio-common/printf_fp.c (__printf_fp): Use __libc_use_alloca + instead of hardcoded constants. + * string/strcoll.c (strcoll): Likewise. + * string/strxfrm.c (strxfrm): Likewise. + * sysdeps/posix/readv.c (__readv): Likewise. + * sysdeps/posix/writev.c (__writev): Likewise. + * sysdeps/generic/allocalim.h: New file. + +2002-10-08 Roland McGrath + + * configure.in (aux_missing warning): Change "too old" to + "incompatible versions", since for autoconf it's "too new" right now. + * configure: Regenerated. + + * configure.in (AUTOCONF): New check to set it. Set to "no" if the + one found doesn't work on our configure.in. + * configure: Regenerated. + * config.make.in (AUTOCONF): New substituted variable. + * Makefile (autoconf-it-cvs): New canned sequence, broken out of ... + (autoconf-it): ... here, use that instead of defining conditionally. + Use $(AUTOCONF) instead of literal autoconf. + [$(AUTOCONF) != no] (configure, %/configure): Protect these rules + with this condition. + * Make-dist (autoconf-it, configure, %/configure): Copy those changes. + +2002-10-08 Ulrich Drepper + + * Make-dist (dist): Cleanup a bit. We are not interested in the + 14 char filename limit anymore. Remove intermediate files and + symlinks. + +2002-10-05 Ulrich Drepper + + * po/sk.po: Update from translation team. + * po/tr.po: Likewise. + * po/gl.po: Likewise. + +2002-10-05 Kaz Kojima + + * elf/tls-macros.h: Fix SH version of macros so as to match ABI syntax. + +2002-10-03 Ulrich Drepper + + * version.h (RELEASE): Change to stable. + +2002-10-03 Jakub Jelinek + + * sysdeps/unix/sysv/linux/_exit.c (__syscall_exit, + __syscall_exit_group): New prototypes. + +2002-10-03 Ulrich Drepper + + * glibc 2.3 released. + + +See ChangeLog.13 for earlier changes. diff --git a/test/regex/LICENSE b/test/regex/LICENSE new file mode 100644 index 0000000..2e5acb9 --- /dev/null +++ b/test/regex/LICENSE @@ -0,0 +1,72 @@ +From gsf@research.att.com Wed Mar 1 20:30:54 2006 +Return-Path: +X-Original-To: mps@bridge.intra +Delivered-To: mps@bridge.intra +Received: from localhost (localhost [127.0.0.1]) + by localhost (Postfix) with ESMTP id B8C814E4F + for ; Wed, 1 Mar 2006 20:30:53 +0100 (CET) +Received: from mail.bridge.intra ([127.0.0.1]) + by localhost (lnx.bridge.intra [127.0.0.1]) (amavisd-new, port 10024) + with LMTP id 05987-03 for ; + Wed, 1 Mar 2006 20:30:42 +0100 (CET) +Received: from pop.gmx.net (localhost [127.0.0.1]) + by mail.bridge.intra (Postfix) with ESMTP id C8C73794D + for ; Wed, 1 Mar 2006 20:30:38 +0100 (CET) +X-Flags: 0000 +Delivered-To: GMX delivery to ps.m@gmx.net +Received: (qmail invoked by alias); 01 Mar 2006 19:23:46 -0000 +Received: from mail-red.research.att.com (EHLO mail-white.research.att.com) [192.20.225.110] + by mx0.gmx.net (mx085) with SMTP; 01 Mar 2006 20:23:46 +0100 +Received: from raptor.research.att.com (raptor.research.att.com [135.207.23.32]) + by mail-blue.research.att.com (Postfix) with ESMTP id B7929147CBB + for ; Wed, 1 Mar 2006 14:23:45 -0500 (EST) +Received: (from gsf@localhost) + by raptor.research.att.com (SGI-8.9.3p2/8.8.7) id OAA86112 + for ps.m@gmx.net; Wed, 1 Mar 2006 14:23:45 -0500 (EST) +Date: Wed, 1 Mar 2006 14:23:45 -0500 (EST) +From: Glenn Fowler +Message-Id: <200603011923.OAA86112@raptor.research.att.com> +Organization: AT&T Research +X-Mailer: mailx (AT&T/BSD) 9.9 2005-04-21 +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +References: +To: mps@bridge.intra +Subject: Re: testregex licensing question +X-GMX-Antivirus: -1 (not scanned, may not use virus scanner) +X-GMX-Antispam: 0 (Mail was not recognized as spam) +X-GMX-UID: lJF3ZO9DeSEkJ2TcbHQhaXN1IGRvb0Ca +X-Virus-Scanned: by amavisd-new at localhost +Status: RO +X-Status: +X-Keywords: +X-UID: 44736 + + +you may include it directly +retain the testregex.c header comment +it uses a very free license to maximize distribution +you can copy that .c comment to any test data files you use +using # comment style to be complete + +let me know how it works with your libc +also pass on any new tests you cook up + +On Wed, 1 Mar 2006 20:15:02 +0100 (CET) Peter S. Mazinger wrote: +> Hello Glenn! + +> I would want to add testregex.c and the related *.dat files to the uClibc +> testsuite. uClibc is licensed under LGPL v2.1. I haven't found any +> licensing related info on testregex. + +> Is it allowed to use the code there, or should I accomodate the testsuite +> to download the needed files from the original site each time it is ran? + +> Thanks, Peter + +> -- +> Peter S. Mazinger ID: 0xA5F059F2 +> Key fingerprint = 92A4 31E1 56BC 3D5A 2D08 BB6E C389 975E A5F0 59F2 + + diff --git a/test/regex/Makefile b/test/regex/Makefile new file mode 100644 index 0000000..7c55c3c --- /dev/null +++ b/test/regex/Makefile @@ -0,0 +1,17 @@ +# uClibc regex tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +#TESTS_DISABLED := testregexi testregexn + +include ../Test.mak + +CFLAGS_tst-regex2 := -std=c99 + +OPTS_testregex := < basic.dat +OPTS_testregexc := < categorize.dat +OPTS_testregexf := < forcedassoc.dat +OPTS_testregexi := -c < interpretation.dat +OPTS_testregexl := < leftassoc.dat +OPTS_testregexn := -c < nullsubexpr.dat +OPTS_testregexp := < repetition.dat +OPTS_testregexr := < rightassoc.dat diff --git a/test/regex/basic.dat b/test/regex/basic.dat new file mode 100644 index 0000000..5c50f37 --- /dev/null +++ b/test/regex/basic.dat @@ -0,0 +1,216 @@ +NOTE all standard compliant implementations should pass these : 2002-05-31 + +BE abracadabra$ abracadabracadabra (7,18) +BE a...b abababbb (2,7) +BE XXXXXX ..XXXXXX (2,8) +E \) () (1,2) +BE a] a]a (0,2) +B } } (0,1) +E \} } (0,1) +BE \] ] (0,1) +B ] ] (0,1) +E ] ] (0,1) +B { { (0,1) +B } } (0,1) +BE ^a ax (0,1) +BE \^a a^a (1,3) +BE a\^ a^ (0,2) +BE a$ aa (1,2) +BE a\$ a$ (0,2) +BE ^$ NULL (0,0) +E $^ NULL (0,0) +E a($) aa (1,2)(2,2) +E a*(^a) aa (0,1)(0,1) +E (..)*(...)* a (0,0) +E (..)*(...)* abcd (0,4)(2,4) +E (ab|a)(bc|c) abc (0,3)(0,2)(2,3) +E (ab)c|abc abc (0,3)(0,2) +E a{0}b ab (1,2) +E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) +E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7) +E a{9876543210} NULL BADBR +E ((a|a)|a) a (0,1)(0,1)(0,1) +E (a*)(a|aa) aaaa (0,4)(0,3)(3,4) +E a*(a.|aa) aaaa (0,4)(2,4) +E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2) +E (a|b)?.* b (0,1)(0,1) +E (a|b)c|a(b|c) ac (0,2)(0,1) +E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2) +E (a|b)*c|(a|ab)*c abc (0,3)(1,2) +E (a|b)*c|(a|ab)*c xc (1,2) +E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2) +E a?(ab|ba)ab abab (0,4)(0,2) +E a?(ac{0}b|ba)ab abab (0,4)(0,2) +E ab|abab abbabab (0,2) +E aba|bab|bba baaabbbaba (5,8) +E aba|bab baaabbbaba (6,9) +E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2) +E (a.|.a.)*|(a|.a...) aa (0,2)(0,2) +E ab|a xabc (1,3) +E ab|a xxabc (2,4) +Ei (Ab|cD)* aBcD (0,4)(2,4) +BE [^-] --a (2,3) +BE [a-]* --a (0,3) +BE [a-m-]* --amoma-- (0,4) +E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17) +E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17) +{E [[:upper:]] A (0,1) [[]] not supported +E [[:lower:]]+ `az{ (1,3) +E [[:upper:]]+ @AZ[ (1,3) +BE [[-]] [[-]] (2,4) +BE [[.NIL.]] NULL ECOLLATE +BE [[=aleph=]] NULL ECOLLATE +} +BE$ \n \n (0,1) +BEn$ \n \n (0,1) +BE$ [^a] \n (0,1) +BE$ \na \na (0,2) +E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3) +BE xxx xxx (0,3) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3) +E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11) +E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1) +E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2) +E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81) +E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25) +E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22) +E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11) +BE$ .* \x01\xff (0,2) +E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57) +L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH +E a*a*a*a*a*b aaaaaaaaab (0,10) +BE ^ NULL (0,0) +BE $ NULL (0,0) +BE ^$ NULL (0,0) +BE ^a$ a (0,1) +BE abc abc (0,3) +BE abc xabcy (1,4) +BE abc ababc (2,5) +BE ab*c abc (0,3) +BE ab*bc abc (0,3) +BE ab*bc abbc (0,4) +BE ab*bc abbbbc (0,6) +E ab+bc abbc (0,4) +E ab+bc abbbbc (0,6) +E ab?bc abbc (0,4) +E ab?bc abc (0,3) +E ab?c abc (0,3) +BE ^abc$ abc (0,3) +BE ^abc abcc (0,3) +BE abc$ aabc (1,4) +BE ^ abc (0,0) +BE $ abc (3,3) +BE a.c abc (0,3) +BE a.c axc (0,3) +BE a.*c axyzc (0,5) +BE a[bc]d abd (0,3) +BE a[b-d]e ace (0,3) +BE a[b-d] aac (1,3) +BE a[-b] a- (0,2) +BE a[b-] a- (0,2) +BE a] a] (0,2) +BE a[]]b a]b (0,3) +BE a[^bc]d aed (0,3) +BE a[^-b]c adc (0,3) +BE a[^]b]c adc (0,3) +E ab|cd abc (0,2) +E ab|cd abcd (0,2) +E a\(b a(b (0,3) +E a\(*b ab (0,2) +E a\(*b a((b (0,4) +E ((a)) abc (0,1)(0,1)(0,1) +E (a)b(c) abc (0,3)(0,1)(2,3) +E a+b+c aabbabc (4,7) +E a* aaa (0,3) +E (a*)* - (0,0)(0,0) +E (a*)+ - (0,0)(0,0) +E (a*|b)* - (0,0)(0,0) +E (a+|b)* ab (0,2)(1,2) +E (a+|b)+ ab (0,2)(1,2) +E (a+|b)? ab (0,1)(0,1) +BE [^ab]* cde (0,3) +E (^)* - (0,0)(0,0) +BE a* NULL (0,0) +E ([abc])*d abbbcd (0,6)(4,5) +E ([abc])*bcd abcd (0,4)(0,1) +E a|b|c|d|e e (0,1) +E (a|b|c|d|e)f ef (0,2)(0,1) +E ((a*|b))* - (0,0)(0,0)(0,0) +BE abcd*efg abcdefg (0,7) +BE ab* xabyabbbz (1,3) +BE ab* xayabbbz (1,2) +E (ab|cd)e abcde (2,5)(2,4) +BE [abhgefdc]ij hij (0,3) +E (a|b)c*d abcd (1,4)(1,2) +E (ab|ab*)bc abc (0,3)(0,1) +E a([bc]*)c* abc (0,3)(1,3) +E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4) +E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4) +E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4) +E a[bcd]*dcdcde adcdcde (0,7) +E (ab|a)b*c abc (0,3)(0,2) +E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4) +BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5) +E ^a(bc+|b[eh])g|.h$ abh (1,3) +E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5) +E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2) +E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6) +E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1) +BE multiple words multiple words yeah (0,14) +E (.*)c(.*) abcde (0,5)(0,2)(3,5) +BE abcd abcd (0,4) +E a(bc)d abcd (0,4)(1,3) +E a[-]?c ac (0,3) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12) +E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12) +E a+(b|c)*d+ aabcdd (0,6)(3,4) +E ^.+$ vivi (0,4) +E ^(.+)$ vivi (0,4)(0,4) +E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19) +E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3) +E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7) +E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7) +E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11) +E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3) +E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7) +E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3) +E ((foo)|bar)!bas bar!bas (0,7)(0,3) +E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7) +E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3) +E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3) +E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7) +E (foo|(bar))!bas foo!bas (0,7)(0,3) +E (foo|bar)!bas bar!bas (0,7)(0,3) +E (foo|bar)!bas foo!bar!bas (4,11)(4,7) +E (foo|bar)!bas foo!bas (0,7)(0,3) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11) +E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11) +E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7) +E .*(/XXX).* /XXX (0,4)(0,4) +E .*(\\XXX).* \XXX (0,4)(0,4) +E \\XXX \XXX (0,4) +E .*(/000).* /000 (0,4)(0,4) +E .*(\\000).* \000 (0,4)(0,4) +E \\000 \000 (0,4) diff --git a/test/regex/categorize.dat b/test/regex/categorize.dat new file mode 100644 index 0000000..d348512 --- /dev/null +++ b/test/regex/categorize.dat @@ -0,0 +1,62 @@ +NOTE regex implementation categorization 2004-05-31 + +?E aa* xaxaax (1,2) POSITION=leftmost +; POSITION=bug + +?E (a*)(ab)*(b*) abc (0,2)(0,1)(?,?)(1,2) ASSOCIATIVITY=right +|E (a*)(ab)*(b*) abc (0,2)(0,0)(0,2)(2,2) ASSOCIATIVITY=left +; ASSOCIATIVITY=bug + +?E ((a*)(ab)*)((b*)(a*)) aba (0,3)(0,2)(0,0)(0,2)(2,3)(2,2)(2,3) SUBEXPRESSION=precedence +|E ((a*)(ab)*)((b*)(a*)) aba (0,3)(0,1)(0,1)(?,?)(1,3)(1,2)(2,3) SUBEXPRESSION=grouping +; SUBEXPRESSION=bug + +?E (...?.?)* xxxxxx (0,6)(4,6) REPEAT_LONGEST=first +|E (...?.?)* xxxxxx (0,6)(2,6) REPEAT_LONGEST=last +|E (...?.?)* xxxxxx OK REPEAT_LONGEST=unknown +; REPEAT_LONGEST=bug + +?E (a|ab)(bc|c) abcabc (0,3)(0,2)(2,3) EXPECTED +|E (a|ab)(bc|c) abcabc (0,3)(0,1)(1,3) BUG=alternation-order +; BUG=alternation-order-UNKNOWN + +?E (aba|a*b)(aba|a*b) ababa (0,5)(0,2)(2,5) EXPECTED +|E (aba|a*b)(aba|a*b) ababa (0,4)(0,3)(3,4) BUG=first-match +; BUG=unknown-match + +?B a\(b\)*\1 a NOMATCH EXPECTED +|B a\(b\)*\1 a (0,1) BUG=nomatch-match +|B a\(b\)*\1 abab (0,2)(1,2) # BUG=repeat-any +; BUG=nomatch-match-UNKNOWN + +?E (a*){2} xxxxx (0,0)(0,0) EXPECTED +|E (a*){2} xxxxx (5,5)(5,5) BUG=range-null +; BUG=range-null-UNKNOWN + +?B a\(b\)*\1 abab NOMATCH EXPECTED +|B a\(b\)*\1 abab (0,1) # BUG=nomatch-match +|B a\(b\)*\1 abab (0,2)(1,2) BUG=repeat-any +; BUG=repeat-any-UNKNOWN + +?E (a*)* a (0,1)(0,1) EXPECTED +|E (a*)* ax (0,1)(0,1) BUG=repeat-null-unknown +|E (a*)* a (0,1)(1,1) BUG=repeat-null +; BUG=repeat-null-UNKNOWN + +?E (aba|a*b)* ababa (0,5)(2,5) EXPECTED +|E (aba|a*b)* ababa (0,5)(3,4) BUG=repeat-short +|E (aba|a*b)* ababa (0,4)(3,4) # LENGTH=first +; BUG=repeat-short-UNKNOWN + +?E (a(b)?)+ aba (0,3)(2,3) EXPECTED +|E (a(b)?)+ aba (0,3)(2,3)(1,2) BUG=repeat-artifact +; BUG=repeat-artifact-UNKNOWN + +?B \(a\(b\)*\)*\2 abab NOMATCH EXPECTED +|B \(a\(b\)*\)*\2 abab (0,4)(2,3)(1,2) BUG=repeat-artifact-nomatch +; BUG=repeat-artifact-nomatch-UNKNOWN + +?E (a?)((ab)?)(b?)a?(ab)?b? abab (0,4)(0,1)(1,1)(?,?)(1,2)(2,4) BUG=subexpression-first +|E .*(.*) ab (0,2)(2,2) EXPECTED +|E .*(.*) ab (0,2)(0,2) BUG=subexpression-first +; BUG=subexpression-first-UNKNOWN diff --git a/test/regex/forcedassoc.dat b/test/regex/forcedassoc.dat new file mode 100644 index 0000000..39f3111 --- /dev/null +++ b/test/regex/forcedassoc.dat @@ -0,0 +1,30 @@ +NOTE left-assoc:pass-all right-assoc:pass-all : 2002-04-29 + +E (a|ab)(c|bcd) abcd (0,4)(0,1)(1,4) +E (a|ab)(bcd|c) abcd (0,4)(0,1)(1,4) +E (ab|a)(c|bcd) abcd (0,4)(0,1)(1,4) +E (ab|a)(bcd|c) abcd (0,4)(0,1)(1,4) +E ((a|ab)(c|bcd))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4) +E ((a|ab)(bcd|c))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4) +E ((ab|a)(c|bcd))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4) +E ((ab|a)(bcd|c))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4) +E (a|ab)((c|bcd)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4) +E (a|ab)((bcd|c)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4) +E (ab|a)((c|bcd)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4) +E (ab|a)((bcd|c)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4) +E (a*)(b|abc) abc (0,3)(0,0)(0,3) +E (a*)(abc|b) abc (0,3)(0,0)(0,3) +E ((a*)(b|abc))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3) +E ((a*)(abc|b))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3) +E (a*)((b|abc)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3) +E (a*)((abc|b)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3) +E (a*)(b|abc) abc (0,3)(0,0)(0,3) +E (a*)(abc|b) abc (0,3)(0,0)(0,3) +E ((a*)(b|abc))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3) +E ((a*)(abc|b))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3) +E (a*)((b|abc)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3) +E (a*)((abc|b)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3) +E (a|ab) ab (0,2)(0,2) +E (ab|a) ab (0,2)(0,2) +E (a|ab)(b*) ab (0,2)(0,2)(2,2) +E (ab|a)(b*) ab (0,2)(0,2)(2,2) diff --git a/test/regex/interpretation.dat b/test/regex/interpretation.dat new file mode 100644 index 0000000..72e186e --- /dev/null +++ b/test/regex/interpretation.dat @@ -0,0 +1,93 @@ +:RE#01:E a+ xaax (1,3) +:RE#02:B .\(a*\). xaax (0,4)(1,3) +:RE#03:E (a?)((ab)?) ab (0,2)(0,0)(0,2)(0,2) +:RE#04:E (a?)((ab)?)(b?) ab (0,2)(0,1)(1,1)(?,?)(1,2) +:RE#05:E ((a?)((ab)?))(b?) ab (0,2)(0,2)(0,0)(0,2)(0,2)(2,2) +:RE#06:E (a?)(((ab)?)(b?)) ab (0,2)(0,1)(1,2)(1,1)(?,?)(1,2) +:RE#07:E (.?) x (0,1)(0,1) +:RE#08:E (.?){1} x (0,1)(0,1) +:RE#09:E (.?)(.?) x (0,1)(0,1)(1,1) +:RE#10:E (.?){2} x (0,1)(1,1) +:RE#11:E (.?)* x (0,1)(0,1) +:RE#12:E (.?.?) xxx (0,2)(0,2) +:RE#13:E (.?.?){1} xxx (0,2)(0,2) +:RE#14:E (.?.?)(.?.?) xxx (0,3)(0,2)(2,3) +:RE#15:E (.?.?){2} xxx (0,3)(2,3) +:RE#16:E (.?.?)(.?.?)(.?.?) xxx (0,3)(0,2)(2,3)(3,3) +:RE#17:E (.?.?){3} xxx (0,3)(3,3) +:RE#18:E (.?.?)* xxx (0,3)(2,3) +:RE#19:E a?((ab)?)(b?) ab (0,2)(1,1)(?,?)(1,2) +:RE#20:E (a?)((ab)?)b? ab (0,2)(0,1)(1,1)(?,?) +:RE#21:E a?((ab)?)b? ab (0,2)(1,1)(?,?) +:RE#22:E (a*){2} xxxxx (0,0)(0,0) +:RE#23:E (ab?)(b?a) aba (0,3)(0,2)(2,3) +:RE#24:E (a|ab)(ba|a) aba (0,3)(0,2)(2,3) +:RE#25:E (a|ab|ba) aba (0,2)(0,2) +:RE#26:E (a|ab|ba)(a|ab|ba) aba (0,3)(0,2)(2,3) +:RE#27:E (a|ab|ba)* aba (0,3)(2,3) +:RE#28:E (aba|a*b) ababa (0,3)(0,3) +:RE#29:E (aba|a*b)(aba|a*b) ababa (0,5)(0,2)(2,5) +:RE#30:E (aba|a*b)* ababa (0,5)(2,5) +:RE#31:E (aba|ab|a) ababa (0,3)(0,3) +:RE#32:E (aba|ab|a)(aba|ab|a) ababa (0,5)(0,2)(2,5) +:RE#33:E (aba|ab|a)* ababa (0,5)(2,5) +:RE#34:E (a(b)?) aba (0,2)(0,2)(1,2) +:RE#35:E (a(b)?)(a(b)?) aba (0,3)(0,2)(1,2)(2,3)(?,?) +:RE#36:E (a(b)?)+ aba (0,3)(2,3)(?,?) +:RE#37:E (.*)(.*) xx (0,2)(0,2)(2,2) +:RE#38:E .*(.*) xx (0,2)(2,2) +:RE#39:E (a.*z|b.*y) azbazby (0,5)(0,5) +:RE#40:E (a.*z|b.*y)(a.*z|b.*y) azbazby (0,7)(0,5)(5,7) +:RE#41:E (a.*z|b.*y)* azbazby (0,7)(5,7) +:RE#42:E (.|..)(.*) ab (0,2)(0,2)(2,2) +:RE#43:E ((..)*(...)*) xxx (0,3)(0,3)(?,?)(0,3) +:RE#44:E ((..)*(...)*)((..)*(...)*) xxx (0,3)(0,3)(?,?)(0,3)(3,3)(?,?) +:RE#45:E ((..)*(...)*)* xxx (0,3)(0,3)(?,?)(0,3) +:RE#46:B \(a\{0,1\}\)*b\1 ab (0,2)(1,1) +:RE#47:B \(a*\)*b\1 ab (0,2)(1,1) +:RE#48:B \(a*\)b\1* ab (0,2)(0,1) +:RE#49:B \(a*\)*b\1* ab (0,2)(1,1) +:RE#50:B \(a\{0,1\}\)*b\(\1\) ab (0,2)(1,1)(2,2) +:RE#51:B \(a*\)*b\(\1\) ab (0,2)(1,1)(2,2) +:RE#52:B \(a*\)b\(\1\)* ab (0,2)(0,1)(?,?) +:RE#53:B \(a*\)*b\(\1\)* ab (0,2)(1,1)(2,2) +:RE#54:B \(a\{0,1\}\)*b\1 aba (0,3)(0,1) +:RE#55:B \(a*\)*b\1 aba (0,3)(0,1) +:RE#56:B \(a*\)b\1* aba (0,3)(0,1) +:RE#57:B \(a*\)*b\1* aba (0,3)(0,1) +:RE#58:B \(a*\)*b\(\1\)* aba (0,3)(0,1)(2,3) +:RE#59:B \(a\{0,1\}\)*b\1 abaa (0,3)(0,1) +:RE#60:B \(a*\)*b\1 abaa (0,3)(0,1) +:RE#61:B \(a*\)b\1* abaa (0,4)(0,1) +:RE#62:B \(a*\)*b\1* abaa (0,4)(0,1) +:RE#63:B \(a*\)*b\(\1\)* abaa (0,4)(0,1)(3,4) +:RE#64:B \(a\{0,1\}\)*b\1 aab (0,3)(2,2) +:RE#65:B \(a*\)*b\1 aab (0,3)(2,2) +:RE#66:B \(a*\)b\1* aab (0,3)(0,2) +:RE#67:B \(a*\)*b\1* aab (0,3)(2,2) +:RE#68:B \(a*\)*b\(\1\)* aab (0,3)(2,2)(3,3) +:RE#69:B \(a\{0,1\}\)*b\1 aaba (0,4)(1,2) +:RE#70:B \(a*\)*b\1 aaba (0,4)(1,2) +:RE#71:B \(a*\)b\1* aaba (0,3)(0,2) +:RE#72:B \(a*\)*b\1* aaba (0,4)(1,2) +:RE#73:B \(a*\)*b\(\1\)* aaba (0,4)(1,2)(3,4) +:RE#74:B \(a\{0,1\}\)*b\1 aabaa (0,4)(1,2) +:RE#75:B \(a*\)*b\1 aabaa (0,5)(0,2) +:RE#76:B \(a*\)b\1* aabaa (0,5)(0,2) +:RE#77:B \(a*\)*b\1* aabaa (0,5)(0,2) +:RE#78:B \(a*\)*b\(\1\)* aabaa (0,5)(0,2)(3,5) +:RE#79:B \(x\)*a\1 a NOMATCH +:RE#80:B \(x\)*a\1* a (0,1)(?,?) +:RE#81:B \(x\)*a\(\1\) a NOMATCH +:RE#82:B \(x\)*a\(\1\)* a (0,1)(?,?)(?,?) +:RE#83:E (aa(b(b))?)+ aabbaa (0,6)(4,6)(?,?)(?,?) +:RE#84:E (a(b)?)+ aba (0,3)(2,3)(?,?) +:RE#85:E ([ab]+)([bc]+)([cd]*) abcd (0,4)(0,2)(2,3)(3,4) +:RE#86:B \([ab]*\)\([bc]*\)\([cd]*\)\1 abcdaa (0,5)(0,1)(1,3)(3,4) +:RE#87:B \([ab]*\)\([bc]*\)\([cd]*\)\1 abcdab (0,6)(0,2)(2,3)(3,4) +:RE#88:B \([ab]*\)\([bc]*\)\([cd]*\)\1* abcdaa (0,6)(0,1)(1,3)(3,4) +:RE#89:B \([ab]*\)\([bc]*\)\([cd]*\)\1* abcdab (0,6)(0,2)(2,3)(3,4) +:RE#90:E ^(A([^B]*))?(B(.*))? Aa (0,2)(0,2)(1,2) +:RE#91:E ^(A([^B]*))?(B(.*))? Bb (0,2)(?,?)(?,?)(0,2)(1,2) +:RE#92:B .*\([AB]\).*\1 ABA (0,3)(0,1) +:RE#93:B$ [^A]*A \nA (0,2) diff --git a/test/regex/leftassoc.dat b/test/regex/leftassoc.dat new file mode 100644 index 0000000..9c068c6 --- /dev/null +++ b/test/regex/leftassoc.dat @@ -0,0 +1,16 @@ +NOTE left-assoc:pass-all right-assoc:pass-none : 2002-04-29 + +E (a|ab)(c|bcd)(d*) abcd (0,4)(0,1)(1,4)(4,4) +E (a|ab)(bcd|c)(d*) abcd (0,4)(0,1)(1,4)(4,4) +E (ab|a)(c|bcd)(d*) abcd (0,4)(0,1)(1,4)(4,4) +E (ab|a)(bcd|c)(d*) abcd (0,4)(0,1)(1,4)(4,4) + +E (a*)(b|abc)(c*) abc (0,3)(0,0)(0,3)(3,3) +E (a*)(abc|b)(c*) abc (0,3)(0,0)(0,3)(3,3) +E (a*)(b|abc)(c*) abc (0,3)(0,0)(0,3)(3,3) +E (a*)(abc|b)(c*) abc (0,3)(0,0)(0,3)(3,3) + +E (a|ab)(c|bcd)(d|.*) abcd (0,4)(0,1)(1,4)(4,4) +E (a|ab)(bcd|c)(d|.*) abcd (0,4)(0,1)(1,4)(4,4) +E (ab|a)(c|bcd)(d|.*) abcd (0,4)(0,1)(1,4)(4,4) +E (ab|a)(bcd|c)(d|.*) abcd (0,4)(0,1)(1,4)(4,4) diff --git a/test/regex/nullsubexpr.dat b/test/regex/nullsubexpr.dat new file mode 100644 index 0000000..c73d8f0 --- /dev/null +++ b/test/regex/nullsubexpr.dat @@ -0,0 +1,73 @@ +NOTE null subexpression matches : 2002-06-06 + +E (a*)* a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a*)+ a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a+)* a (0,1)(0,1) +E SAME x (0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E (a+)+ a (0,1)(0,1) +E SAME x NOMATCH +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) + +E ([a]*)* a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E ([a]*)+ a (0,1)(0,1) +E SAME x (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaax (0,6)(0,6) +E ([^b]*)* a (0,1)(0,1) +E SAME b (0,0)(0,0) +E SAME aaaaaa (0,6)(0,6) +E SAME aaaaaab (0,6)(0,6) +E ([ab]*)* a (0,1)(0,1) +E SAME aaaaaa (0,6)(0,6) +E SAME ababab (0,6)(0,6) +E SAME bababa (0,6)(0,6) +E SAME b (0,1)(0,1) +E SAME bbbbbb (0,6)(0,6) +E SAME aaaabcde (0,5)(0,5) +E ([^a]*)* b (0,1)(0,1) +E SAME bbbbbb (0,6)(0,6) +E SAME aaaaaa (0,0)(0,0) +E ([^ab]*)* ccccxx (0,6)(0,6) +E SAME ababab (0,0)(0,0) + +E ((z)+|a)* zabcde (0,2)(1,2) + +{E a+? aaaaaa (0,1) no *? +? mimimal match ops +E (a) aaa (0,1)(0,1) +E (a*?) aaa (0,0)(0,0) +E (a)*? aaa (0,0) +E (a*?)*? aaa (0,0) +} + +B \(a*\)*\(x\) x (0,1)(0,0)(0,1) +B \(a*\)*\(x\) ax (0,2)(0,1)(1,2) +B \(a*\)*\(x\) axa (0,2)(0,1)(1,2) +B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1) +B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2) +B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3) +B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4) +B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3) + +E (a*)*(x) x (0,1)(0,0)(0,1) +E (a*)*(x) ax (0,2)(0,1)(1,2) +E (a*)*(x) axa (0,2)(0,1)(1,2) + +E (a*)+(x) x (0,1)(0,0)(0,1) +E (a*)+(x) ax (0,2)(0,1)(1,2) +E (a*)+(x) axa (0,2)(0,1)(1,2) + +E (a*){2}(x) x (0,1)(0,0)(0,1) +E (a*){2}(x) ax (0,2)(1,1)(1,2) +E (a*){2}(x) axa (0,2)(1,1)(1,2) diff --git a/test/regex/repetition.dat b/test/regex/repetition.dat new file mode 100644 index 0000000..b54a2c6 --- /dev/null +++ b/test/regex/repetition.dat @@ -0,0 +1,79 @@ +NOTE implicit vs. explicit repetitions : 2002-08-01 +# +# Glenn Fowler +# conforming matches (column 4) must match one of the following BREs +# NOMATCH +# (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)* +# (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)* +# i.e., each 3-tuple has two identical elements and one (?,?) +# + +E ((..)|(.)) NULL NOMATCH +E ((..)|(.))((..)|(.)) NULL NOMATCH +E ((..)|(.))((..)|(.))((..)|(.)) NULL NOMATCH + +E ((..)|(.)){1} NULL NOMATCH +E ((..)|(.)){2} NULL NOMATCH +E ((..)|(.)){3} NULL NOMATCH + +E ((..)|(.))* NULL (0,0) + +E ((..)|(.)) a (0,1)(0,1)(?,?)(0,1) +E ((..)|(.))((..)|(.)) a NOMATCH +E ((..)|(.))((..)|(.))((..)|(.)) a NOMATCH + +E ((..)|(.)){1} a (0,1)(0,1)(?,?)(0,1) +E ((..)|(.)){2} a NOMATCH +E ((..)|(.)){3} a NOMATCH + +E ((..)|(.))* a (0,1)(0,1)(?,?)(0,1) + +E ((..)|(.)) aa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.))((..)|(.)) aa (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2) +E ((..)|(.))((..)|(.))((..)|(.)) aa NOMATCH + +E ((..)|(.)){1} aa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.)){2} aa (0,2)(1,2)(?,?)(1,2) +E ((..)|(.)){3} aa NOMATCH + +E ((..)|(.))* aa (0,2)(0,2)(0,2)(?,?) + +E ((..)|(.)) aaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.))((..)|(.)) aaa (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3) +E ((..)|(.))((..)|(.))((..)|(.)) aaa (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3) + +E ((..)|(.)){1} aaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.)){2} aaa (0,3)(2,3)(?,?)(2,3) +E ((..)|(.)){3} aaa (0,3)(2,3)(?,?)(2,3) + +E ((..)|(.))* aaa (0,3)(2,3)(?,?)(2,3) + +E ((..)|(.)) aaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) +E ((..)|(.))((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4) + +E ((..)|(.)){1} aaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.)){2} aaaa (0,4)(2,4)(2,4)(?,?) +E ((..)|(.)){3} aaaa (0,4)(3,4)(?,?)(3,4) + +E ((..)|(.))* aaaa (0,4)(2,4)(2,4)(?,?) + +E ((..)|(.)) aaaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.))((..)|(.)) aaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) +E ((..)|(.))((..)|(.))((..)|(.)) aaaaa (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5) + +E ((..)|(.)){1} aaaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.)){2} aaaaa (0,4)(2,4)(2,4)(?,?) +E ((..)|(.)){3} aaaaa (0,5)(4,5)(?,?)(4,5) + +E ((..)|(.))* aaaaa (0,5)(4,5)(?,?)(4,5) + +E ((..)|(.)) aaaaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.))((..)|(.)) aaaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?) +E ((..)|(.))((..)|(.))((..)|(.)) aaaaaa (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?) + +E ((..)|(.)){1} aaaaaa (0,2)(0,2)(0,2)(?,?) +E ((..)|(.)){2} aaaaaa (0,4)(2,4)(2,4)(?,?) +E ((..)|(.)){3} aaaaaa (0,6)(4,6)(4,6)(?,?) + +E ((..)|(.))* aaaaaa (0,6)(4,6)(4,6)(?,?) diff --git a/test/regex/rightassoc.dat b/test/regex/rightassoc.dat new file mode 100644 index 0000000..ed7f28e --- /dev/null +++ b/test/regex/rightassoc.dat @@ -0,0 +1,16 @@ +NOTE left-assoc:pass-none right-assoc:pass-all : 2002-04-29 + +E (a|ab)(c|bcd)(d*) abcd (0,4)(0,2)(2,3)(3,4) +E (a|ab)(bcd|c)(d*) abcd (0,4)(0,2)(2,3)(3,4) +E (ab|a)(c|bcd)(d*) abcd (0,4)(0,2)(2,3)(3,4) +E (ab|a)(bcd|c)(d*) abcd (0,4)(0,2)(2,3)(3,4) + +E (a*)(b|abc)(c*) abc (0,3)(0,1)(1,2)(2,3) +E (a*)(abc|b)(c*) abc (0,3)(0,1)(1,2)(2,3) +E (a*)(b|abc)(c*) abc (0,3)(0,1)(1,2)(2,3) +E (a*)(abc|b)(c*) abc (0,3)(0,1)(1,2)(2,3) + +E (a|ab)(c|bcd)(d|.*) abcd (0,4)(0,2)(2,3)(3,4) +E (a|ab)(bcd|c)(d|.*) abcd (0,4)(0,2)(2,3)(3,4) +E (ab|a)(c|bcd)(d|.*) abcd (0,4)(0,2)(2,3)(3,4) +E (ab|a)(bcd|c)(d|.*) abcd (0,4)(0,2)(2,3)(3,4) diff --git a/test/regex/testregex.c b/test/regex/testregex.c new file mode 100644 index 0000000..3992c26 --- /dev/null +++ b/test/regex/testregex.c @@ -0,0 +1,2119 @@ +/* + * regex(3) test harness + * + * build: cc -o testregex testregex.c + * help: testregex --man + * note: REG_* features are detected by #ifdef; if REG_* are enums + * then supply #define REG_foo REG_foo for each enum REG_foo + * + * Glenn Fowler + * AT&T Labs Research + * + * PLEASE: publish your tests so everyone can benefit + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following disclaimer: + * + * THIS SOFTWARE IS PROVIDED BY AT&T ``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 AT&T 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. + */ + +static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2005-05-20 $\0\n"; + +#if _PACKAGE_ast +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#include +#endif + +#if !_PACKAGE_ast +#undef REG_DISCIPLINE +#endif + +#ifndef REG_DELIMITED +#undef _REG_subcomp +#endif + +#define TEST_ARE 0x00000001 +#define TEST_BRE 0x00000002 +#define TEST_ERE 0x00000004 +#define TEST_KRE 0x00000008 +#define TEST_LRE 0x00000010 +#define TEST_SRE 0x00000020 + +#define TEST_EXPAND 0x00000040 +#define TEST_LENIENT 0x00000080 + +#define TEST_QUERY 0x00000100 +#define TEST_SUB 0x00000200 +#define TEST_UNSPECIFIED 0x00000400 +#define TEST_VERIFY 0x00000800 +#define TEST_AND 0x00001000 +#define TEST_OR 0x00002000 + +#define TEST_DELIMIT 0x00010000 +#define TEST_OK 0x00020000 +#define TEST_SAME 0x00040000 + +#define TEST_ACTUAL 0x00100000 +#define TEST_BASELINE 0x00200000 +#define TEST_FAIL 0x00400000 +#define TEST_PASS 0x00800000 +#define TEST_SUMMARY 0x01000000 + +#define TEST_IGNORE_ERROR 0x02000000 +#define TEST_IGNORE_OVER 0x04000000 +#define TEST_IGNORE_POSITION 0x08000000 + +#define TEST_CATCH 0x10000000 +#define TEST_VERBOSE 0x20000000 + +#define TEST_GLOBAL (TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE) + +#ifdef REG_DISCIPLINE + + +#include + +typedef struct Disc_s +{ + regdisc_t disc; + int ordinal; + Sfio_t* sp; +} Disc_t; + +static void* +compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc) +{ + Disc_t* dp = (Disc_t*)disc; + + return (void*)++dp->ordinal; +} + +static int +execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc) +{ + Disc_t* dp = (Disc_t*)disc; + + sfprintf(dp->sp, "{%-.*s}(%d:%d)", xlen, xstr, (int)data, slen); + return atoi(xstr); +} + +static void* +resizef(void* handle, void* data, size_t size) +{ + if (!size) + return 0; + return stkalloc((Sfio_t*)handle, size); +} + +#endif + +#ifndef NiL +#ifdef __STDC__ +#define NiL 0 +#else +#define NiL (char*)0 +#endif +#endif + +#define H(x) do{if(html)fprintf(stderr,x);}while(0) +#define T(x) fprintf(stderr,x) + +static void +help(int html) +{ +H("\n"); +H("\n"); +H("\n"); +H("testregex man document\n"); +H("\n"); +H("\n"); +H("

\n");
+T("NAME\n");
+T("  testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T("  testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T("  testregex reads regex(3) test specifications, one per line, from the\n");
+T("  standard input and writes one output line for each failed test. A\n");
+T("  summary line is written after all tests are done. Each successful\n");
+T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
+T("  before the first test, and tests requiring these features are\n");
+T("  silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T("  -c	catch signals and non-terminating calls\n");
+T("  -e	ignore error return mismatches\n");
+T("  -h	list help on standard error\n");
+T("  -n	do not repeat successful tests with regnexec()\n");
+T("  -o	ignore match[] overrun errors\n");
+T("  -p	ignore negative position mismatches\n");
+T("  -s	use stack instead of malloc\n");
+T("  -x	do not repeat successful tests with REG_NOSUB\n");
+T("  -v	list each test line\n");
+T("  -A	list failed test lines with actual answers\n");
+T("  -B	list all test lines with actual answers\n");
+T("  -F	list failed test lines\n");
+T("  -P	list passed test lines\n");
+T("  -S	output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T("  Input lines may be blank, a comment beginning with #, or a test\n");
+T("  specification. A specification is five fields separated by one\n");
+T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T("  0 pointer.\n");
+T("\n");
+T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T("  flag. The test is skipped if REG_feature is not supported by the\n");
+T("  implementation. If the first character is not [BEASKL] then the\n");
+T("  specification is a global control line. One or more of [BEASKL] may be\n");
+T("  specified; the test will be repeated for each mode.\n");
+T("\n");
+T("    B 	basic			BRE	(grep, ed, sed)\n");
+T("    E 	REG_EXTENDED		ERE	(egrep)\n");
+T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
+T("    S	REG_SHELL		SRE	(sh glob)\n");
+T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
+T("    L	REG_LITERAL		LRE	(fgrep)\n");
+T("\n");
+T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
+T("    b	REG_NOTBOL		lhs does not match ^\n");
+T("    c	REG_COMMENT		ignore space and #...\\n\n");
+T("    d	REG_SHELL_DOT		explicit leading . match\n");
+T("    e	REG_NOTEOL		rhs does not match $\n");
+T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
+T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
+T("    h	REG_MULTIREF		multiple digit backref\n");
+T("    i	REG_ICASE		ignore case\n");
+T("    j	REG_SPAN		. matches \\n\n");
+T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
+T("    l	REG_LEFT		implicit ^...\n");
+T("    m	REG_MINIMAL		minimal match\n");
+T("    n	REG_NEWLINE		explicit \\n match\n");
+T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
+T("    p	REG_SHELL_PATH		explicit / match\n");
+T("    q	REG_DELIMITED		delimited pattern\n");
+T("    r	REG_RIGHT		implicit ...$\n");
+T("    s	REG_SHELL_ESCAPED	\\ not special\n");
+T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
+T("    u	standard unspecified behavior -- errors not counted\n");
+T("    w	REG_NOSUB		no subexpression match array\n");
+T("    x	REG_LENIENT		let some errors slide\n");
+T("    y	REG_LEFT		regexec() implicit ^...\n");
+T("    z	REG_NULL		NULL subexpressions ok\n");
+T("    $	                        expand C \\c escapes in fields 2 and 3\n");
+T("    /	                        field 2 is a regsubcomp() expression\n");
+T("\n");
+T("  Field 1 control lines:\n");
+T("\n");
+T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
+T("    &test ...	output field 5 if current and previous passed\n");
+T("    |test ...	output field 5 if current passed and previous failed\n");
+T("    ; ...	output field 2 if previous failed\n");
+T("    {test ...	skip if failed until }\n");
+T("    }		end of skip\n");
+T("\n");
+T("    : comment		comment copied as output NOTE\n");
+T("    :comment:test	:comment: ignored\n");
+T("    N[OTE] comment	comment copied as output NOTE\n");
+T("    T[EST] comment	comment\n");
+T("\n");
+T("    number		use number for nmatch (20 by default)\n");
+T("\n");
+T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T("    the previous specification.\n");
+T("\n");
+T("  Field 3: the string to match.\n");
+T("\n");
+T("  Field 4: the test outcome. This is either one of the posix error\n");
+T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T("    entries with m and n being first and last+1 positions in the\n");
+T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T("    error code. The match[] array is initialized to (-2,-2) before\n");
+T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
+T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T("    o is the expression ordinal counting from 1, and n is the length of\n");
+T("    the unmatched portion of the subject string. If x starts with a\n");
+T("    number then that is the return value of re_execf(), otherwise 0 is\n");
+T("    returned.\n");
+T("\n");
+T("  Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T("    If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
+T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
+T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
+T("  Tom Lord        lord@regexps.com            (rx tests)\n");
+T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
+T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
+T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
+T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
+T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
+H("
\n"); +H("\n"); +H("\n"); +} + +#ifndef elementsof +#define elementsof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef streq +#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b)) +#endif + +#define HUNG 2 +#define NOTEST (~0) + +#ifndef REG_TEST_DEFAULT +#define REG_TEST_DEFAULT 0 +#endif + +#ifndef REG_EXEC_DEFAULT +#define REG_EXEC_DEFAULT 0 +#endif + +static const char* unsupported[] = +{ + "BASIC", +#ifndef REG_EXTENDED + "EXTENDED", +#endif +#ifndef REG_AUGMENTED + "AUGMENTED", +#endif +#ifndef REG_SHELL + "SHELL", +#endif + +#ifndef REG_COMMENT + "COMMENT", +#endif +#ifndef REG_DELIMITED + "DELIMITED", +#endif +#ifndef REG_DISCIPLINE + "DISCIPLINE", +#endif +#ifndef REG_ESCAPE + "ESCAPE", +#endif +#ifndef REG_ICASE + "ICASE", +#endif +#ifndef REG_LEFT + "LEFT", +#endif +#ifndef REG_LENIENT + "LENIENT", +#endif +#ifndef REG_LITERAL + "LITERAL", +#endif +#ifndef REG_MINIMAL + "MINIMAL", +#endif +#ifndef REG_MULTIPLE + "MULTIPLE", +#endif +#ifndef REG_MULTIREF + "MULTIREF", +#endif +#ifndef REG_MUSTDELIM + "MUSTDELIM", +#endif +#ifndef REG_NEWLINE + "NEWLINE", +#endif +#ifndef REG_NOTBOL + "NOTBOL", +#endif +#ifndef REG_NOTEOL + "NOTEOL", +#endif +#ifndef REG_NULL + "NULL", +#endif +#ifndef REG_RIGHT + "RIGHT", +#endif +#ifndef REG_SHELL_DOT + "SHELL_DOT", +#endif +#ifndef REG_SHELL_ESCAPED + "SHELL_ESCAPED", +#endif +#ifndef REG_SHELL_GROUP + "SHELL_GROUP", +#endif +#ifndef REG_SHELL_PATH + "SHELL_PATH", +#endif +#ifndef REG_SPAN + "SPAN", +#endif +#if REG_NOSUB & REG_TEST_DEFAULT + "SUBMATCH", +#endif +#if !_REG_nexec + "regnexec", +#endif +#if !_REG_subcomp + "regsubcomp", +#endif + 0 +}; + +#ifndef REG_COMMENT +#define REG_COMMENT NOTEST +#endif +#ifndef REG_DELIMITED +#define REG_DELIMITED NOTEST +#endif +#ifndef REG_ESCAPE +#define REG_ESCAPE NOTEST +#endif +#ifndef REG_ICASE +#define REG_ICASE NOTEST +#endif +#ifndef REG_LEFT +#define REG_LEFT NOTEST +#endif +#ifndef REG_LENIENT +#define REG_LENIENT 0 +#endif +#ifndef REG_MINIMAL +#define REG_MINIMAL NOTEST +#endif +#ifndef REG_MULTIPLE +#define REG_MULTIPLE NOTEST +#endif +#ifndef REG_MULTIREF +#define REG_MULTIREF NOTEST +#endif +#ifndef REG_MUSTDELIM +#define REG_MUSTDELIM NOTEST +#endif +#ifndef REG_NEWLINE +#define REG_NEWLINE NOTEST +#endif +#ifndef REG_NOTBOL +#define REG_NOTBOL NOTEST +#endif +#ifndef REG_NOTEOL +#define REG_NOTEOL NOTEST +#endif +#ifndef REG_NULL +#define REG_NULL NOTEST +#endif +#ifndef REG_RIGHT +#define REG_RIGHT NOTEST +#endif +#ifndef REG_SHELL_DOT +#define REG_SHELL_DOT NOTEST +#endif +#ifndef REG_SHELL_ESCAPED +#define REG_SHELL_ESCAPED NOTEST +#endif +#ifndef REG_SHELL_GROUP +#define REG_SHELL_GROUP NOTEST +#endif +#ifndef REG_SHELL_PATH +#define REG_SHELL_PATH NOTEST +#endif +#ifndef REG_SPAN +#define REG_SPAN NOTEST +#endif + +#define REG_UNKNOWN (-1) + +#ifndef REG_ENEWLINE +#define REG_ENEWLINE (REG_UNKNOWN-1) +#endif +#ifndef REG_ENULL +#ifndef REG_EMPTY +#define REG_ENULL (REG_UNKNOWN-2) +#else +#define REG_ENULL REG_EMPTY +#endif +#endif +#ifndef REG_ECOUNT +#define REG_ECOUNT (REG_UNKNOWN-3) +#endif +#ifndef REG_BADESC +#define REG_BADESC (REG_UNKNOWN-4) +#endif +#ifndef REG_EMEM +#define REG_EMEM (REG_UNKNOWN-5) +#endif +#ifndef REG_EHUNG +#define REG_EHUNG (REG_UNKNOWN-6) +#endif +#ifndef REG_EBUS +#define REG_EBUS (REG_UNKNOWN-7) +#endif +#ifndef REG_EFAULT +#define REG_EFAULT (REG_UNKNOWN-8) +#endif +#ifndef REG_EFLAGS +#define REG_EFLAGS (REG_UNKNOWN-9) +#endif +#ifndef REG_EDELIM +#define REG_EDELIM (REG_UNKNOWN-9) +#endif + +static const struct { int code; char* name; } codes[] = +{ + {REG_UNKNOWN, "UNKNOWN"}, + {REG_NOMATCH, "NOMATCH"}, + {REG_BADPAT, "BADPAT"}, + {REG_ECOLLATE, "ECOLLATE"}, + {REG_ECTYPE, "ECTYPE"}, + {REG_EESCAPE, "EESCAPE"}, + {REG_ESUBREG, "ESUBREG"}, + {REG_EBRACK, "EBRACK"}, + {REG_EPAREN, "EPAREN"}, + {REG_EBRACE, "EBRACE"}, + {REG_BADBR, "BADBR"}, + {REG_ERANGE, "ERANGE"}, + {REG_ESPACE, "ESPACE"}, + {REG_BADRPT, "BADRPT"}, + {REG_ENEWLINE, "ENEWLINE"}, + {REG_ENULL, "ENULL"}, + {REG_ECOUNT, "ECOUNT"}, + {REG_BADESC, "BADESC"}, + {REG_EMEM, "EMEM"}, + {REG_EHUNG, "EHUNG"}, + {REG_EBUS, "EBUS"}, + {REG_EFAULT, "EFAULT"}, + {REG_EFLAGS, "EFLAGS"}, + {REG_EDELIM, "EDELIM"}, +}; + +static struct +{ + regmatch_t NOMATCH; + int errors; + int extracted; + int ignored; + int lineno; + int passed; + int signals; + int unspecified; + int verify; + int warnings; + char* file; + char* stack; + char* which; + jmp_buf gotcha; +#ifdef REG_DISCIPLINE + Disc_t disc; +#endif +} state; + +static void +quote(char* s, int len, unsigned long test) +{ + unsigned char* u = (unsigned char*)s; + unsigned char* e; + int c; + + if (!u) + printf("NIL"); + else if (!*u && len <= 1) + printf("NULL"); + else if (test & TEST_EXPAND) + { + if (len < 0) + len = strlen((char*)u); + e = u + len; + if (test & TEST_DELIMIT) + printf("\""); + while (u < e) + switch (c = *u++) + { + case '\\': + printf("\\\\"); + break; + case '"': + if (test & TEST_DELIMIT) + printf("\\\""); + else + printf("\""); + break; + case '\a': + printf("\\a"); + break; + case '\b': + printf("\\b"); + break; + case 033: + printf("\\e"); + break; + case '\f': + printf("\\f"); + break; + case '\n': + printf("\\n"); + break; + case '\r': + printf("\\r"); + break; + case '\t': + printf("\\t"); + break; + case '\v': + printf("\\v"); + break; + default: + if (!iscntrl(c) && isprint(c)) + putchar(c); + else + printf("\\x%02x", c); + break; + } + if (test & TEST_DELIMIT) + printf("\""); + } + else + printf("%s", s); +} + +static void +report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test) +{ + if (state.file) + printf("%s:", state.file); + printf("%d:", state.lineno); + if (re) + { + printf(" "); + quote(re, -1, test|TEST_DELIMIT); + if (s) + { + printf(" versus "); + quote(s, len, test|TEST_DELIMIT); + } + } + if (test & TEST_UNSPECIFIED) + { + state.unspecified++; + printf(" unspecified behavior"); + } + else + state.errors++; + if (state.which) + printf(" %s", state.which); + if (flags & REG_NOSUB) + printf(" NOSUB"); + if (fun) + printf(" %s", fun); + if (comment[strlen(comment)-1] == '\n') + printf(" %s", comment); + else + { + printf(" %s: ", comment); + if (msg) + printf("%s: ", msg); + } +} + +static void +error(regex_t* preg, int code) +{ + char* msg; + char buf[256]; + + switch (code) + { + case REG_EBUS: + msg = "bus error"; + break; + case REG_EFAULT: + msg = "memory fault"; + break; + case REG_EHUNG: + msg = "did not terminate"; + break; + default: + regerror(code, preg, msg = buf, sizeof buf); + break; + } + printf("%s\n", msg); +} + +static void +bad(char* comment, char* re, char* s, int len, unsigned long test) +{ + printf("bad test case "); + report(comment, NiL, re, s, len, NiL, 0, test); + exit(1); +} + +static int +escape(char* s) +{ + char* b; + char* t; + char* q; + char* e; + int c; + + for (b = t = s; (*t = *s); s++, t++) + if (*s == '\\') + switch (*++s) + { + case '\\': + break; + case 'a': + *t = '\a'; + break; + case 'b': + *t = '\b'; + break; + case 'c': + if ((*t = *++s)) + *t &= 037; + else + s--; + break; + case 'e': + case 'E': + *t = 033; + break; + case 'f': + *t = '\f'; + break; + case 'n': + *t = '\n'; + break; + case 'r': + *t = '\r'; + break; + case 's': + *t = ' '; + break; + case 't': + *t = '\t'; + break; + case 'v': + *t = '\v'; + break; + case 'u': + case 'x': + c = 0; + q = c == 'u' ? (s + 5) : (char*)0; + e = s + 1; + while (!e || !q || s < q) + { + switch (*++s) + { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + c = (c << 4) + *s - 'a' + 10; + continue; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + c = (c << 4) + *s - 'A' + 10; + continue; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + c = (c << 4) + *s - '0'; + continue; + case '{': + case '[': + if (s != e) + { + s--; + break; + } + e = 0; + continue; + case '}': + case ']': + if (e) + s--; + break; + default: + s--; + break; + } + break; + } + *t = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = *s - '0'; + q = s + 2; + while (s < q) + { + switch (*++s) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = (c << 3) + *s - '0'; + break; + default: + q = --s; + break; + } + } + *t = c; + break; + default: + *(s + 1) = 0; + bad("invalid C \\ escape\n", s - 1, NiL, 0, 0); + } + return t - b; +} + +static void +matchoffprint(int off) +{ + switch (off) + { + case -2: + printf("X"); + break; + case -1: + printf("?"); + break; + default: + printf("%d", off); + break; + } +} + +static void +matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test) +{ + int i; + + for (; nmatch > nsub + 1; nmatch--) + if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || (match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))) + break; + for (i = 0; i < nmatch; i++) + { + printf("("); + matchoffprint(match[i].rm_so); + printf(","); + matchoffprint(match[i].rm_eo); + printf(")"); + } + if (!(test & (TEST_ACTUAL|TEST_BASELINE))) + { + if (ans) + printf(" expected: %s", ans); + printf("\n"); + } +} + +static int +matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test) +{ + char* p; + int i; + int m; + int n; + + if (streq(ans, "OK")) + return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY); + for (i = 0, p = ans; i < nmatch && *p; i++) + { + if (*p == '{') + { +#ifdef REG_DISCIPLINE + char* x; + + x = sfstruse(state.disc.sp); + if (strcmp(p, x)) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + return 0; + report("callout failed", NiL, re, s, len, NiL, flags, test); + quote(p, -1, test); + printf(" expected, "); + quote(x, -1, test); + printf(" returned\n"); + } +#endif + break; + } + if (*p++ != '(') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + m = -1; + p++; + } + else + m = strtol(p, &p, 10); + if (*p++ != ',') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + n = -1; + p++; + } + else + n = strtol(p, &p, 10); + if (*p++ != ')') + bad("improper answer\n", re, s, -1, test); + if (m!=match[i].rm_so || n!=match[i].rm_eo) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) + { + report("failed: match was", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch, nsub, ans, test); + } + return 0; + } + } + for (; i < nmatch; i++) + { + if (match[i].rm_so!=-1 || match[i].rm_eo!=-1) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY))) + { + if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0)) + { + state.ignored++; + return 0; + } + if (!(test & TEST_SUMMARY)) + { + report("failed: match was", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch, nsub, ans, test); + } + } + return 0; + } + } + if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) + { + report("failed: overran match array", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch + 1, nsub, NiL, test); + } + return 0; + } + return 1; +} + +static void +sigunblock(int s) +{ +#ifdef SIG_SETMASK + int op; + sigset_t mask; + + sigemptyset(&mask); + if (s) + { + sigaddset(&mask, s); + op = SIG_UNBLOCK; + } + else op = SIG_SETMASK; + sigprocmask(op, &mask, NiL); +#else +#ifdef sigmask + sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L); +#endif +#endif +} + +static void +gotcha(int sig) +{ + int ret; + + signal(sig, gotcha); + alarm(0); + state.signals++; + switch (sig) + { + case SIGALRM: + ret = REG_EHUNG; + break; + case SIGBUS: + ret = REG_EBUS; + break; + default: + ret = REG_EFAULT; + break; + } + sigunblock(sig); + longjmp(state.gotcha, ret); +} + +static char* +my_getline(FILE* fp) +{ + static char buf[32 * 1024]; + + register char* s = buf; + register char* e = &buf[sizeof(buf)]; + register char* b; + + for (;;) + { + if (!(b = fgets(s, e - s, fp))) + return 0; + state.lineno++; + s += strlen(s); + if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\') + { + *s = 0; + break; + } + s--; + } + return buf; +} + +static unsigned long +note(unsigned long level, char* msg, unsigned long skip, unsigned long test) +{ + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip) + { + printf("NOTE\t"); + if (msg) + printf("%s: ", msg); + printf("skipping lines %d", state.lineno); + } + return skip | level; +} + +#define TABS(n) &ts[7-((n)&7)] + +static char ts[] = "\t\t\t\t\t\t\t"; + +static unsigned long +extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test) +{ + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY)) + { + state.extracted = 1; + if (test & TEST_OK) + { + state.passed++; + if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + if (msg && strcmp(msg, "EXPECTED")) + printf("NOTE\t%s\n", msg); + return skip; + } + test &= ~(TEST_PASS|TEST_QUERY); + } + if (test & (TEST_QUERY|TEST_VERIFY)) + { + if (test & TEST_BASELINE) + test &= ~(TEST_BASELINE|TEST_PASS); + else + test |= TEST_PASS; + skip |= level; + } + if (!(test & TEST_OK)) + { + if (test & TEST_UNSPECIFIED) + state.unspecified++; + else + state.errors++; + } + if (test & (TEST_PASS|TEST_SUMMARY)) + return skip; + test &= ~TEST_DELIMIT; + printf("%s%s", spec, TABS(*tabs++)); + if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME)) + printf("SAME"); + else + quote(re, -1, test); + printf("%s", TABS(*tabs++)); + quote(s, -1, test); + printf("%s", TABS(*tabs++)); + if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || (!accept && !match)) + printf("%s", ans); + else if (accept) + printf("%s", accept); + else + matchprint(match, nmatch, nsub, NiL, test); + if (msg) + printf("%s%s", TABS(*tabs++), msg); + putchar('\n'); + } + else if (test & TEST_QUERY) + skip = note(level, msg, skip, test); + else if (test & TEST_VERIFY) + state.extracted = 1; + return skip; +} + +static int +catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test) +{ + int eret; + + if (!(test & TEST_CATCH)) + { + regfree(preg); + eret = 0; + } + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + regfree(preg); + alarm(0); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + else + { + report("failed", "regfree", re, NiL, -1, msg, flags, test); + error(preg, eret); + } + return eret; +} + +int +main(int argc, char** argv) +{ + int flags; + int cflags; + int eflags; + int nmatch; + int nexec; + int nstr; + int cret; + int eret; + int nsub; + int i; + int j; + int expected; + int got; + int locale; + int subunitlen = 0; + int testno; + unsigned long level; + unsigned long skip; + char* p; + char* line; + char* spec; + char* re; + char* s; + char* ans; + char* msg; + char* fun; + char* ppat = NULL; + char* subunit = NULL; + char* version; + char* field[6]; + char* delim[6]; + FILE* fp; + int tabs[6]; + char unit[64]; + regmatch_t match[100]; + regex_t preg; + + static char pat[32 * 1024]; + + int nonosub = REG_NOSUB == 0; + int nonexec = 0; + + unsigned long test = 0; + + static char* filter[] = { "-", 0 }; + + state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2; + p = unit; + version = (char*)id + 10; + while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p)) + p++; + *p = 0; + while ((p = *++argv) && *p == '-') + for (;;) + { + switch (*++p) + { + case 0: + break; + case 'c': + test |= TEST_CATCH; + continue; + case 'e': + test |= TEST_IGNORE_ERROR; + continue; + case 'h': + case '?': + help(0); + return 2; + case '-': + help(p[1] == 'h'); + return 2; + case 'n': + nonexec = 1; + continue; + case 'o': + test |= TEST_IGNORE_OVER; + continue; + case 'p': + test |= TEST_IGNORE_POSITION; + continue; + case 's': +#ifdef REG_DISCIPLINE + if (!(state.stack = stkalloc(stkstd, 0))) + fprintf(stderr, "%s: out of space [stack]", unit); + state.disc.disc.re_resizef = resizef; + state.disc.disc.re_resizehandle = (void*)stkstd; +#endif + continue; + case 'x': + nonosub = 1; + continue; + case 'v': + test |= TEST_VERBOSE; + continue; + case 'A': + test |= TEST_ACTUAL; + continue; + case 'B': + test |= TEST_BASELINE; + continue; + case 'F': + test |= TEST_FAIL; + continue; + case 'P': + test |= TEST_PASS; + continue; + case 'S': + test |= TEST_SUMMARY; + continue; + default: + fprintf(stderr, "%s: %c: invalid option\n", unit, *p); + return 2; + } + break; + } + if (!*argv) + argv = filter; + locale = 0; + while ((state.file = *argv++)) + { + if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0")) + { + state.file = 0; + fp = stdin; + } + else if (!(fp = fopen(state.file, "r"))) + { + fprintf(stderr, "%s: %s: cannot read\n", unit, state.file); + return 2; + } + testno = state.errors = state.ignored = state.lineno = state.passed = + state.signals = state.unspecified = state.warnings = 0; + skip = 0; + level = 1; + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + printf("TEST\t%s ", unit); + if ((s = state.file)) + { + subunit = p = 0; + for (;;) + { + switch (*s++) + { + case 0: + break; + case '/': + subunit = s; + continue; + case '.': + p = s - 1; + continue; + default: + continue; + } + break; + } + if (!subunit) + subunit = state.file; + if (p < subunit) + p = s - 1; + subunitlen = p - subunit; + printf("%-.*s ", subunitlen, subunit); + } + else + subunit = 0; + for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++) + putchar(*s); + if (test & TEST_CATCH) + printf(", catch"); + if (test & TEST_IGNORE_ERROR) + printf(", ignore error code mismatches"); + if (test & TEST_IGNORE_POSITION) + printf(", ignore negative position mismatches"); +#ifdef REG_DISCIPLINE + if (state.stack) + printf(", stack"); +#endif + if (test & TEST_VERBOSE) + printf(", verbose"); + printf("\n"); +#ifdef REG_VERSIONID + if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0) + s = pat; + else +#endif +#ifdef REG_TEST_VERSION + s = REG_TEST_VERSION; +#else + s = "regex"; +#endif + printf("NOTE\t%s\n", s); + if (elementsof(unsupported) > 1) + { +#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED) + i = 0; +#else + i = REG_EXTENDED != 0; +#endif + for (got = 0; i < elementsof(unsupported) - 1; i++) + { + if (!got) + { + got = 1; + printf("NOTE\tunsupported: %s", unsupported[i]); + } + else + printf(",%s", unsupported[i]); + } + if (got) + printf("\n"); + } + } +#ifdef REG_DISCIPLINE + state.disc.disc.re_version = REG_VERSION; + state.disc.disc.re_compf = compf; + state.disc.disc.re_execf = execf; + if (!(state.disc.sp = sfstropen())) + bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0); + preg.re_disc = &state.disc.disc; +#endif + if (test & TEST_CATCH) + { + signal(SIGALRM, gotcha); + signal(SIGBUS, gotcha); + signal(SIGSEGV, gotcha); + } + while ((p = my_getline(fp))) + { + + /* parse: */ + + line = p; + if (*p == ':' && !isspace(*(p + 1))) + { + while (*++p && *p != ':'); + if (!*p++) + { + if (test & TEST_BASELINE) + printf("%s\n", line); + continue; + } + } + while (isspace(*p)) + p++; + if (*p == 0 || *p == '#' || *p == 'T') + { + if (test & TEST_BASELINE) + printf("%s\n", line); + continue; + } + if (*p == ':' || *p == 'N') + { + if (test & TEST_BASELINE) + printf("%s\n", line); + else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + while (*++p && !isspace(*p)); + while (isspace(*p)) + p++; + printf("NOTE %s\n", p); + } + continue; + } + j = 0; + i = 0; + field[i++] = p; + for (;;) + { + switch (*p++) + { + case 0: + p--; + j = 0; + goto checkfield; + case '\t': + *(delim[i] = p - 1) = 0; + j = 1; + checkfield: + s = field[i - 1]; + if (streq(s, "NIL")) + field[i - 1] = 0; + else if (streq(s, "NULL")) + *s = 0; + while (*p == '\t') + { + p++; + j++; + } + tabs[i - 1] = j; + if (!*p) + break; + if (i >= elementsof(field)) + bad("too many fields\n", NiL, NiL, 0, 0); + field[i++] = p; + /*FALLTHROUGH*/ + default: + continue; + } + break; + } + if (!(spec = field[0])) + bad("NIL spec\n", NiL, NiL, 0, 0); + + /* interpret: */ + + cflags = REG_TEST_DEFAULT; + eflags = REG_EXEC_DEFAULT; + test &= TEST_GLOBAL; + state.extracted = 0; + nmatch = 20; + nsub = -1; + for (p = spec; *p; p++) + { + if (isdigit(*p)) + { + nmatch = strtol(p, &p, 10); + if (nmatch >= elementsof(match)) + bad("nmatch must be < 100\n", NiL, NiL, 0, 0); + p--; + continue; + } + switch (*p) + { + case 'A': + test |= TEST_ARE; + continue; + case 'B': + test |= TEST_BRE; + continue; + case 'C': + if (!(test & TEST_QUERY) && !(skip & level)) + bad("locale must be nested\n", NiL, NiL, 0, 0); + test &= ~TEST_QUERY; + if (locale) + bad("locale nesting not supported\n", NiL, NiL, 0, 0); + if (i != 2) + bad("locale field expected\n", NiL, NiL, 0, 0); + if (!(skip & level)) + { +#if defined(LC_COLLATE) && defined(LC_CTYPE) + s = field[1]; + if (!s || streq(s, "POSIX")) + s = "C"; + if (!(ans = setlocale(LC_COLLATE, s)) || streq(ans, "C") || streq(ans, "POSIX") || !(ans = setlocale(LC_CTYPE, s)) || streq(ans, "C") || streq(ans, "POSIX")) + skip = note(level, s, skip, test); + else + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + printf("NOTE \"%s\" locale\n", s); + locale = level; + } +#else + skip = note(level, skip, test, "locales not supported"); +#endif + } + cflags = NOTEST; + continue; + case 'E': + test |= TEST_ERE; + continue; + case 'K': + test |= TEST_KRE; + continue; + case 'L': + test |= TEST_LRE; + continue; + case 'S': + test |= TEST_SRE; + continue; + + case 'a': + cflags |= REG_LEFT|REG_RIGHT; + continue; + case 'b': + eflags |= REG_NOTBOL; + continue; + case 'c': + cflags |= REG_COMMENT; + continue; + case 'd': + cflags |= REG_SHELL_DOT; + continue; + case 'e': + eflags |= REG_NOTEOL; + continue; + case 'f': + cflags |= REG_MULTIPLE; + continue; + case 'g': + cflags |= NOTEST; + continue; + case 'h': + cflags |= REG_MULTIREF; + continue; + case 'i': + cflags |= REG_ICASE; + continue; + case 'j': + cflags |= REG_SPAN; + continue; + case 'k': + cflags |= REG_ESCAPE; + continue; + case 'l': + cflags |= REG_LEFT; + continue; + case 'm': + cflags |= REG_MINIMAL; + continue; + case 'n': + cflags |= REG_NEWLINE; + continue; + case 'o': + cflags |= REG_SHELL_GROUP; + continue; + case 'p': + cflags |= REG_SHELL_PATH; + continue; + case 'q': + cflags |= REG_DELIMITED; + continue; + case 'r': + cflags |= REG_RIGHT; + continue; + case 's': + cflags |= REG_SHELL_ESCAPED; + continue; + case 't': + cflags |= REG_MUSTDELIM; + continue; + case 'u': + test |= TEST_UNSPECIFIED; + continue; + case 'w': + cflags |= REG_NOSUB; + continue; + case 'x': + if (REG_LENIENT) + cflags |= REG_LENIENT; + else + test |= TEST_LENIENT; + continue; + case 'y': + eflags |= REG_LEFT; + continue; + case 'z': + cflags |= REG_NULL; + continue; + + case '$': + test |= TEST_EXPAND; + continue; + + case '/': + test |= TEST_SUB; + continue; + + case '?': + test |= TEST_VERIFY; + test &= ~(TEST_AND|TEST_OR); + state.verify = state.passed; + continue; + case '&': + test |= TEST_VERIFY|TEST_AND; + test &= ~TEST_OR; + continue; + case '|': + test |= TEST_VERIFY|TEST_OR; + test &= ~TEST_AND; + continue; + case ';': + test |= TEST_OR; + test &= ~TEST_AND; + continue; + + case '{': + level <<= 1; + if (skip & (level >> 1)) + { + skip |= level; + cflags = NOTEST; + } + else + { + skip &= ~level; + test |= TEST_QUERY; + } + continue; + case '}': + if (level == 1) + bad("invalid {...} nesting\n", NiL, NiL, 0, 0); + if ((skip & level) && !(skip & (level>>1))) + { + if (!(test & (TEST_BASELINE|TEST_SUMMARY))) + { + if (test & (TEST_ACTUAL|TEST_FAIL)) + printf("}\n"); + else if (!(test & TEST_PASS)) + printf("-%d\n", state.lineno); + } + } +#if defined(LC_COLLATE) && defined(LC_CTYPE) + else if (locale & level) + { + locale = 0; + if (!(skip & level)) + { + s = "C"; + setlocale(LC_COLLATE, s); + setlocale(LC_CTYPE, s); + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + printf("NOTE \"%s\" locale\n", s); + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS)) + printf("}\n"); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL)) + printf("}\n"); + } +#endif + level >>= 1; + cflags = NOTEST; + continue; + + default: + bad("bad spec\n", spec, NiL, 0, test); + break; + + } + break; + } + if ((cflags|eflags) == NOTEST || ((skip & level) && (test & TEST_BASELINE))) + { + if (test & TEST_BASELINE) + { + while (i > 1) + *delim[--i] = '\t'; + printf("%s\n", line); + } + continue; + } + if (test & TEST_OR) + { + if (!(test & TEST_VERIFY)) + { + test &= ~TEST_OR; + if (state.passed == state.verify && i > 1) + printf("NOTE\t%s\n", field[1]); + continue; + } + else if (state.passed > state.verify) + continue; + } + else if (test & TEST_AND) + { + if (state.passed == state.verify) + continue; + state.passed = state.verify; + } + if (i < 4) + bad("too few fields\n", NiL, NiL, 0, test); + while (i < elementsof(field)) + field[i++] = 0; + if ((re = field[1])) + { + if (streq(re, "SAME")) + { + re = ppat; + test |= TEST_SAME; + } + else + { + if (test & TEST_EXPAND) + escape(re); + strcpy(ppat = pat, re); + } + } + else + ppat = 0; + nstr = -1; + if ((s = field[2]) && (test & TEST_EXPAND)) + { + nstr = escape(s); +#if _REG_nexec + if (nstr != strlen(s)) + nexec = nstr; +#endif + } + if (!(ans = field[3])) + bad("NIL answer\n", NiL, NiL, 0, test); + msg = field[4]; + fflush(stdout); + if (test & TEST_SUB) +#if _REG_subcomp + cflags |= REG_DELIMITED; +#else + continue; +#endif + + compile: + + if (state.extracted || (skip & level)) + continue; +#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) +#ifdef REG_EXTENDED + if (REG_EXTENDED != 0 && (test & TEST_BRE)) +#else + if (test & TEST_BRE) +#endif + { + test &= ~TEST_BRE; + flags = cflags; + state.which = "BRE"; + } + else +#endif +#ifdef REG_EXTENDED + if (test & TEST_ERE) + { + test &= ~TEST_ERE; + flags = cflags | REG_EXTENDED; + state.which = "ERE"; + } + else +#endif +#ifdef REG_AUGMENTED + if (test & TEST_ARE) + { + test &= ~TEST_ARE; + flags = cflags | REG_AUGMENTED; + state.which = "ARE"; + } + else +#endif +#ifdef REG_LITERAL + if (test & TEST_LRE) + { + test &= ~TEST_LRE; + flags = cflags | REG_LITERAL; + state.which = "LRE"; + } + else +#endif +#ifdef REG_SHELL + if (test & TEST_SRE) + { + test &= ~TEST_SRE; + flags = cflags | REG_SHELL; + state.which = "SRE"; + } + else +#ifdef REG_AUGMENTED + if (test & TEST_KRE) + { + test &= ~TEST_KRE; + flags = cflags | REG_SHELL | REG_AUGMENTED; + state.which = "KRE"; + } + else +#endif +#endif + { + if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) + extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK); + continue; + } + if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE) + { + printf("test %-3d %s ", state.lineno, state.which); + quote(re, -1, test|TEST_DELIMIT); + printf(" "); + quote(s, nstr, test|TEST_DELIMIT); + printf("\n"); + } + + nosub: + fun = "regcomp"; +#if _REG_nexec + if (nstr >= 0 && nstr != strlen(s)) + nexec = nstr; + + else +#endif + nexec = -1; + if (state.extracted || (skip & level)) + continue; + if (!(test & TEST_QUERY)) + testno++; +#ifdef REG_DISCIPLINE + if (state.stack) + stkset(stkstd, state.stack, 0); + flags |= REG_DISCIPLINE; + state.disc.ordinal = 0; + sfstrseek(state.disc.sp, 0, SEEK_SET); +#endif + if (!(test & TEST_CATCH)) + cret = regcomp(&preg, re, flags); + else if (!(cret = setjmp(state.gotcha))) + { + alarm(HUNG); + cret = regcomp(&preg, re, flags); + alarm(0); + } +#if _REG_subcomp + if (!cret && (test & TEST_SUB)) + { + fun = "regsubcomp"; + p = re + preg.re_npat; + if (!(test & TEST_CATCH)) + cret = regsubcomp(&preg, p, NiL, 0, 0); + else if (!(cret = setjmp(state.gotcha))) + { + alarm(HUNG); + cret = regsubcomp(&preg, p, NiL, 0, 0); + alarm(0); + } + if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST)) + { + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + cret = REG_EFLAGS; + } + } +#endif + if (!cret) + { + if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(') + { + for (p = ans; *p; p++) + if (*p == '(') + nsub++; + else if (*p == '{') + nsub--; + if (nsub >= 0) + { + if (test & TEST_IGNORE_OVER) + { + if (nmatch > nsub) + nmatch = nsub + 1; + } + else if (nsub != preg.re_nsub) + { + if (nsub > preg.re_nsub) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test); + printf("at least %d expected, %zd returned\n", nsub, preg.re_nsub); + state.errors++; + } + } + else + nsub = preg.re_nsub; + } + } + } + if (!(test & TEST_SUB) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else if (!(test & TEST_LENIENT)) + { + report("failed", fun, re, NiL, -1, msg, flags, test); + printf("%s expected, OK returned\n", ans); + } + catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + continue; + } + } + else + { + if (test & TEST_LENIENT) + /* we'll let it go this time */; + else if (!*ans || ans[0]=='(' || (cret == REG_BADPAT && streq(ans, "NOMATCH"))) + { + got = 0; + for (i = 1; i < elementsof(codes); i++) + if (cret==codes[i].code) + got = i; + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("failed", fun, re, NiL, -1, msg, flags, test); + printf("%s returned: ", codes[got].name); + error(&preg, cret); + } + } + else + { + expected = got = 0; + for (i = 1; i < elementsof(codes); i++) + { + if (streq(ans, codes[i].name)) + expected = i; + if (cret==codes[i].code) + got = i; + } + if (!expected) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test); + printf("%s expected, %s returned\n", ans, codes[got].name); + } + } + else if (cret != codes[expected].code && cret != REG_BADPAT) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else if (test & TEST_IGNORE_ERROR) + state.ignored++; + else + { + report("should fail and did", fun, re, NiL, -1, msg, flags, test); + printf("%s expected, %s returned: ", ans, codes[got].name); + state.errors--; + state.warnings++; + error(&preg, cret); + } + } + } + goto compile; + } + +#if _REG_nexec + execute: + if (nexec >= 0) + fun = "regnexec"; + else +#endif + fun = "regexec"; + + for (i = 0; i < elementsof(match); i++) + match[i] = state.NOMATCH; + +#if _REG_nexec + if (nexec >= 0) + { + eret = regnexec(&preg, s, nexec, nmatch, match, eflags); + s[nexec] = 0; + } + else +#endif + { + if (!(test & TEST_CATCH)) + eret = regexec(&preg, s, nmatch, match, eflags); + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + eret = regexec(&preg, s, nmatch, match, eflags); + alarm(0); + } + } +#if _REG_subcomp + if ((test & TEST_SUB) && !eret) + { + fun = "regsubexec"; + if (!(test & TEST_CATCH)) + eret = regsubexec(&preg, s, nmatch, match); + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + eret = regsubexec(&preg, s, nmatch, match); + alarm(0); + } + } +#endif + if (flags & REG_NOSUB) + { + if (eret) + { + if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test); + error(&preg, eret); + } + } + } + else if (streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("should fail and didn't", fun, re, s, nstr, msg, flags, test); + error(&preg, eret); + } + } + } + else if (eret) + { + if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("failed", fun, re, s, nstr, msg, flags, test); + if (eret != REG_NOMATCH) + error(&preg, eret); + else if (*ans) + printf("expected: %s\n", ans); + else + printf("\n"); + } + } + } + else if (streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("should fail and didn't", fun, re, s, nstr, msg, flags, test); + matchprint(match, nmatch, nsub, NiL, test); + } + } +#if _REG_subcomp + else if (test & TEST_SUB) + { + p = preg.re_sub->re_buf; + if (strcmp(p, ans)) + { + report("failed", fun, re, s, nstr, msg, flags, test); + quote(ans, -1, test|TEST_DELIMIT); + printf(" expected, "); + quote(p, -1, test|TEST_DELIMIT); + printf(" returned\n"); + } + } +#endif + else if (!*ans) + { + if (match[0].rm_so != state.NOMATCH.rm_so) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + else + { + report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test); + matchprint(match, nmatch, nsub, NiL, test); + } + } + } + else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test)) + { +#if _REG_nexec + if (nexec < 0 && !nonexec) + { + nexec = nstr >= 0 ? nstr : strlen(s); + s[nexec] = '\n'; + testno++; + goto execute; + } +#endif + if (!(test & (TEST_SUB|TEST_VERIFY)) && !nonosub) + { + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + flags |= REG_NOSUB; + goto nosub; + } + if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + goto compile; + } + if (test & TEST_SUMMARY) + printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals); + else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS))) + { + printf("TEST\t%s", unit); + if (subunit) + printf(" %-.*s", subunitlen, subunit); + printf(", %d test%s", testno, testno == 1 ? "" : "s"); + if (state.ignored) + printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s"); + if (state.warnings) + printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s"); + if (state.unspecified) + printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s"); + if (state.signals) + printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s"); + printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s"); + } + if (fp != stdin) + fclose(fp); + } + return 0; +} diff --git a/test/regex/testregexc.c b/test/regex/testregexc.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexc.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexf.c b/test/regex/testregexf.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexf.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexi.c b/test/regex/testregexi.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexi.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexl.c b/test/regex/testregexl.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexl.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexn.c b/test/regex/testregexn.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexn.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexp.c b/test/regex/testregexp.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexp.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/testregexr.c b/test/regex/testregexr.c new file mode 100644 index 0000000..46b3ee8 --- /dev/null +++ b/test/regex/testregexr.c @@ -0,0 +1 @@ +#include "testregex.c" diff --git a/test/regex/tst-regex2.c b/test/regex/tst-regex2.c new file mode 100644 index 0000000..94be59d --- /dev/null +++ b/test/regex/tst-regex2.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef _POSIX_CPUTIME +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 +static clockid_t cl; +static int use_clock; +#endif + +static int +do_test (void) +{ +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 +# if _POSIX_CPUTIME == 0 + if (sysconf (_SC_CPUTIME) < 0) + use_clock = 0; + else +# endif + /* See whether we can use the CPU clock. */ + use_clock = clock_getcpuclockid (0, &cl) == 0; +#endif + + static const char *pat[] = { + ".?.?.?.?.?.?.?Log\\.13", + "(.?)(.?)(.?)(.?)(.?)(.?)(.?)Log\\.13", + "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" + "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" + "((((((((((.?))))))))))Log\\.13" }; + + int fd = open (".regex.ChangeLog.14", O_RDONLY); + if (fd < 0) + { + printf ("Couldn't open .regex.ChangeLog.14: %s\n", strerror(errno)); + return 1; + } + + struct stat64 st; + if (fstat64 (fd, &st) < 0) + { + printf ("Couldn't fstat ChangeLog.14: %s\n", strerror(errno)); + return 1; + } + + char *buf = malloc (st.st_size + 1); + if (buf == NULL) + { + printf ("Couldn't allocate buffer: %s\n", strerror(errno)); + return 1; + } + + if (read (fd, buf, st.st_size) != (ssize_t) st.st_size) + { + puts ("Couldn't read ChangeLog.14"); + return 1; + } + + close (fd); + buf[st.st_size] = '\0'; + +#ifdef __UCLIBC_HAS_XLOCALE__ + setlocale (LC_ALL, "de_DE.UTF-8"); +#endif + + char *string = buf; + size_t len = st.st_size; + + for (int testno = 0; testno < 4; ++testno) + for (int i = 0; i < sizeof (pat) / sizeof (pat[0]); ++i) + { + printf ("test %d pattern %d", testno, i); + + regex_t rbuf; + struct re_pattern_buffer rpbuf; + int err; + if (testno < 2) + { + err = regcomp (&rbuf, pat[i], + REG_EXTENDED | (testno ? REG_NOSUB : 0)); + if (err != 0) + { + putchar ('\n'); + char errstr[300]; + regerror (err, &rbuf, errstr, sizeof (errstr)); + puts (errstr); + return err; + } + } + else + { + re_set_syntax (RE_SYNTAX_POSIX_EGREP + | (testno == 3 ? RE_NO_SUB : 0)); + + memset (&rpbuf, 0, sizeof (rpbuf)); + const char *s = re_compile_pattern (pat[i], strlen (pat[i]), + &rpbuf); + if (s != NULL) + { + printf ("\n%s\n", s); + return 1; + } + + /* Just so that this can be tested with earlier glibc as well. */ + if (testno == 3) + rpbuf.no_sub = 1; + } + +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 + struct timespec start, stop; + if (use_clock) + use_clock = clock_gettime (cl, &start) == 0; +#endif + + if (testno < 2) + { + regmatch_t pmatch[71]; + err = regexec (&rbuf, string, 71, pmatch, 0); + if (err == REG_NOMATCH) + { + puts ("\nregexec failed"); + return 1; + } + + if (testno == 0) + { + if (pmatch[0].rm_eo != pmatch[0].rm_so + 13 + || pmatch[0].rm_eo > len + || pmatch[0].rm_so < len - 100 + || strncmp (string + pmatch[0].rm_so, + " ChangeLog.13 for earlier changes", + sizeof " ChangeLog.13 for earlier changes" - 1) + != 0) + { + puts ("\nregexec without REG_NOSUB did not find the correct match"); + return 1; + } + + if (i > 0) + for (int j = 0, l = 1; j < 7; ++j) + for (int k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) + if (pmatch[l].rm_so != pmatch[0].rm_so + j + || pmatch[l].rm_eo != pmatch[l].rm_so + 1) + { + printf ("\npmatch[%d] incorrect\n", l); + return 1; + } + } + } + else + { + struct re_registers regs; + + memset (®s, 0, sizeof (regs)); + int match = re_search (&rpbuf, string, len, 0, len, + ®s); + if (match < 0) + { + puts ("\nre_search failed"); + return 1; + } + + if (match + 13 > len + || match < len - 100 + || strncmp (string + match, + " ChangeLog.13 for earlier changes", + sizeof " ChangeLog.13 for earlier changes" - 1) + != 0) + { + puts ("\nre_search did not find the correct match"); + return 1; + } + + if (testno == 2) + { + if (regs.num_regs != 2 + (i == 0 ? 0 : i == 1 ? 7 : 70)) + { + printf ("\nincorrect num_regs %d\n", regs.num_regs); + return 1; + } + + if (regs.start[0] != match || regs.end[0] != match + 13) + { + printf ("\nincorrect regs.{start,end}[0] = { %d, %d}\n", + regs.start[0], regs.end[0]); + return 1; + } + + if (regs.start[regs.num_regs - 1] != -1 + || regs.end[regs.num_regs - 1] != -1) + { + puts ("\nincorrect regs.{start,end}[num_regs - 1]"); + return 1; + } + + if (i > 0) + for (int j = 0, l = 1; j < 7; ++j) + for (int k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) + if (regs.start[l] != match + j + || regs.end[l] != regs.start[l] + 1) + { + printf ("\nregs.{start,end}[%d] incorrect\n", l); + return 1; + } + } + } + +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 + if (use_clock) + use_clock = clock_gettime (cl, &stop) == 0; + if (use_clock) + { + stop.tv_sec -= start.tv_sec; + if (stop.tv_nsec < start.tv_nsec) + { + stop.tv_sec--; + stop.tv_nsec += 1000000000 - start.tv_nsec; + } + else + stop.tv_nsec -= start.tv_nsec; + printf (": %ld.%09lds\n", (long) stop.tv_sec, (long) stop.tv_nsec); + } + else +#endif + putchar ('\n'); + + if (testno < 2) + regfree (&rbuf); + else + regfree (&rpbuf); + } + + return 0; +} + +#define TIMEOUT 20 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/regex/tst-regexloc.c b/test/regex/tst-regexloc.c new file mode 100644 index 0000000..88ab581 --- /dev/null +++ b/test/regex/tst-regexloc.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ +#ifdef __UCLIBC_HAS_XLOCALE__ + regex_t re; + regmatch_t mat[1]; + int res = 1; + + if (setlocale (LC_ALL, "de_DE.ISO-8859-1") == NULL) + puts ("cannot set locale"); + else if (regcomp (&re, "[a-f]*", 0) != REG_NOERROR) + puts ("cannot compile expression \"[a-f]*\""); + else if (regexec (&re, "abcdefCDEF", 1, mat, 0) == REG_NOMATCH) + puts ("no match"); + else + { + printf ("match from %d to %d\n", mat[0].rm_so, mat[0].rm_eo); + res = mat[0].rm_so != 0 || mat[0].rm_eo != 6; + } + + return res; +#else + puts("Test requires locale; skipping"); + return 0; +#endif +} diff --git a/test/rpc/Makefile b/test/rpc/Makefile new file mode 100644 index 0000000..8ea9348 --- /dev/null +++ b/test/rpc/Makefile @@ -0,0 +1,12 @@ +# uClibc rpc tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS := getrpcent + +ifeq ($(UCLIBC_HAS_REENTRANT_RPC),y) +TESTS += getrpcent_r +endif + +include ../Test.mak + +DODIFF_getrpcent := 1 diff --git a/test/rpc/getrpcent.c b/test/rpc/getrpcent.c new file mode 100644 index 0000000..e12e768 --- /dev/null +++ b/test/rpc/getrpcent.c @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct rpcent *ent; + + while ((ent = getrpcent()) != NULL) { + printf("%s: %i", ent->r_name, ent->r_number); + while (ent->r_aliases[0]) + printf(" %s", *ent->r_aliases++); + printf("\n"); + } + + endrpcent(); + + return 0; +} diff --git a/test/rpc/getrpcent_r.c b/test/rpc/getrpcent_r.c new file mode 100644 index 0000000..708deba --- /dev/null +++ b/test/rpc/getrpcent_r.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int ret; + char rpcdata[1024]; + struct rpcent rpcbuf, *ent; + + while ((ret = getrpcent_r(&rpcbuf, rpcdata, sizeof(rpcdata), &ent)) == 0) { + printf("%s: %i", ent->r_name, ent->r_number); + while (ent->r_aliases[0]) + printf(" %s", *ent->r_aliases++); + printf("\n"); + } + + if (ret != ENOENT) + printf("Test failed: %s\n", strerror(ret)); + + endrpcent(); + + return 0; +} diff --git a/test/setjmp/Makefile b/test/setjmp/Makefile new file mode 100644 index 0000000..581ab32 --- /dev/null +++ b/test/setjmp/Makefile @@ -0,0 +1,4 @@ +# uClibc setjmp tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak diff --git a/test/setjmp/bug269-setjmp.c b/test/setjmp/bug269-setjmp.c new file mode 100644 index 0000000..b11ac7b --- /dev/null +++ b/test/setjmp/bug269-setjmp.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ ; + +/* Test case for Bugzilla # 269 */ + +#include +#include +#include + +jmp_buf buf1; +jmp_buf buf2; +int *p; +int n_x = 6; + +static int g_counter = 0; + +static int +f (void) +{ + static int counter = 0; + static int way_point1 = 3; + static int way_point2 = 2; + int lose = 0; + + if (setjmp (buf1) != 101) + { + int a[n_x]; /* reallocate stack space */ + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else + { + _setjmp (buf2); + _longjmp (buf1, 101); + } + } + + way_point1--; + + if (counter == 0) + { + counter++; + { + int a[n_x]; /* reallocate stack space */ + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else + { + _setjmp (buf2); + _longjmp (buf1, 101); + } + } + } + + way_point2--; + + if (counter == 1) + { + counter++; + longjmp (buf2, 2); + } + + lose = !(way_point1 == 0 && way_point2 == 0 + && g_counter == 6 && counter == 2); + + return lose; +} + +static int +do_test (void) +{ + int lose; + + lose = f (); + + if (lose) + puts ("Test FAILED!"); + else + puts ("Test succeeded!"); + + return lose ? EXIT_FAILURE : EXIT_SUCCESS; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/setjmp/jmpbug.c b/test/setjmp/jmpbug.c new file mode 100644 index 0000000..da087a7 --- /dev/null +++ b/test/setjmp/jmpbug.c @@ -0,0 +1,51 @@ +/* setjmp vs alloca test case. Exercised bug on sparc. */ + +#include +#include +#include + +int ret; +int verbose; + +__attribute__ ((__noreturn__)) +static void +sub5 (jmp_buf buf) +{ + longjmp (buf, 1); +} + +static void +test (int x) +{ + jmp_buf buf; + char *foo; + int arr[100]; + + ++ret; + + arr[77] = x; + if (setjmp (buf)) + { + --ret; + if (verbose) + printf ("made it ok; %d\n", arr[77]); + return; + } + + foo = (char *) alloca (128); + sub5 (buf); +} + +int +main (int argc, char *argv[]) +{ + int i; + + verbose = (argc != 1); + ret = 0; + + for (i = 123; i < 345; ++i) + test (i); + + return ret; +} diff --git a/test/setjmp/sigjmpbug.c b/test/setjmp/sigjmpbug.c new file mode 100644 index 0000000..5b17181 --- /dev/null +++ b/test/setjmp/sigjmpbug.c @@ -0,0 +1,51 @@ +/* sigsetjmp vs alloca test case. Exercised bug on sparc. */ + +#include +#include +#include + +int ret; +int verbose; + +__attribute__ ((__noreturn__)) +static void +sub5 (jmp_buf buf) +{ + siglongjmp (buf, 1); +} + +static void +test (int x) +{ + sigjmp_buf buf; + char *foo; + int arr[100]; + + ++ret; + + arr[77] = x; + if (sigsetjmp (buf, 1)) + { + --ret; + if (verbose) + printf ("made it ok; %d\n", arr[77]); + return; + } + + foo = (char *) alloca (128); + sub5 (buf); +} + +int +main (int argc, char *argv[]) +{ + int i; + + verbose = (argc != 1); + ret = 0; + + for (i = 123; i < 345; ++i) + test (i); + + return ret; +} diff --git a/test/setjmp/tst-setjmp.c b/test/setjmp/tst-setjmp.c new file mode 100644 index 0000000..f0feb99 --- /dev/null +++ b/test/setjmp/tst-setjmp.c @@ -0,0 +1,119 @@ +/* Copyright (C) 1991, 1992, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +static jmp_buf env; +static int last_value = -1, lose = 0; + +__attribute__ ((__noreturn__)) +static void +jump (int val) +{ + longjmp (env, val); +} + +int +main (void) +{ + int value; + + value = setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + + if (!lose && value == 10) + { + /* Do a second test, this time without `setjmp' being a macro. + This is not required by ISO C but we have this for compatibility. */ +#undef setjmp + extern int setjmp (jmp_buf); + + last_value = -1; + lose = 0; + + value = setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + } + + if (!lose && value == 10) + { + /* And again for the `_setjmp' function. */ +#ifndef _setjmp + extern int _setjmp (jmp_buf); +#endif + last_value = -1; + lose = 0; + + value = _setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + } + + if (lose || value != 10) + puts ("Test FAILED!"); + else + puts ("Test succeeded!"); + + return lose ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/test/setjmp/tst-vfork-longjmp.c b/test/setjmp/tst-vfork-longjmp.c new file mode 100644 index 0000000..2784424 --- /dev/null +++ b/test/setjmp/tst-vfork-longjmp.c @@ -0,0 +1,108 @@ +/* make sure we can vfork/exec across setjmp/longjmp's + * and make sure signal block masks don't get corrupted + * in the process. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int verbose = 0; + +static int execute_child(const char *prog) +{ + int status; + pid_t child; + child = vfork(); + if (child == 0) { + execlp(prog, prog, NULL); + perror("Could not execute specified prog"); + _exit(1); + } else if (child == 1) + return 1; + wait(&status); + return WEXITSTATUS(status); +} + +sigset_t orig_mask; + +static int check_sig_mask(void) +{ + int status; + pid_t child; + + child = vfork(); + if (child == 0) { + int ret; + sigset_t child_mask; + memset(&child_mask, 0x00, sizeof(child_mask)); + ret = sigprocmask(SIG_BLOCK, NULL, &child_mask); + if (ret != 0) { + perror("could not get child sig block mask"); + _exit(1); + } + ret = memcmp(&orig_mask, &child_mask, sizeof(orig_mask)); + if (verbose) { + printf("sigmsk: %08lx%08lx ", child_mask.__val[1], child_mask.__val[0]); + printf("sigmsk: %08lx%08lx ", orig_mask.__val[1], orig_mask.__val[0]); + printf("%i\n", ret); + } + _exit(ret); + } else if (child == 1) + return 1; + wait(&status); + return WEXITSTATUS(status); +} + +int main(int argc, char *argv[]) +{ + const char *prog; + jmp_buf env; + sigjmp_buf sigenv; + int max; + /* values modified between setjmp/longjmp cannot be local to this func */ + static int cnt, ret; + + memset(&orig_mask, 0x00, sizeof(orig_mask)); + ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask); + if (ret != 0) { + perror("could not get orig sig block mask"); + return 1; + } + + prog = (argc > 1 ? argv[1] : "true"); + ret = 0; + verbose = 0; + max = 10; + + /* test vfork()/exec() inside of sigsetjmp/siglongjmp */ + cnt = 0; + sigsetjmp(sigenv, 1); + ++cnt; + if (verbose) + printf("sigsetjmp loop %i\n", cnt); + ret |= check_sig_mask(); + ret |= execute_child(prog); + if (cnt < max) + siglongjmp(sigenv, 0); + + /* test vfork()/sigprocmask() inside of setjmp/longjmp */ + cnt = 0; + setjmp(env); + ++cnt; + if (verbose) + printf("setjmp loop %i\n", cnt); + ret |= check_sig_mask(); + ret |= execute_child(prog); + if (cnt < max) + longjmp(env, 0); + + return ret; +} diff --git a/test/signal/.indent.pro b/test/signal/.indent.pro new file mode 100644 index 0000000..492ecf1 --- /dev/null +++ b/test/signal/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/test/signal/Makefile b/test/signal/Makefile new file mode 100644 index 0000000..2ff96fa --- /dev/null +++ b/test/signal/Makefile @@ -0,0 +1,8 @@ +# uClibc signal tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_OBSOLETE_BSD_SIGNAL),) +TESTS_DISABLED := tst-sigsimple +endif + +include ../Test.mak diff --git a/test/signal/sigchld.c b/test/signal/sigchld.c new file mode 100644 index 0000000..22febac --- /dev/null +++ b/test/signal/sigchld.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __ARCH_USE_MMU__ + +static void test_handler(int signo) +{ + write(1, "caught SIGCHLD\n", 15); + return; +} + +int main(void) +{ + pid_t mypid; + struct sigaction siga; + static sigset_t set; + + /* Set up sighandling */ + sigfillset(&set); + siga.sa_handler = test_handler; + siga.sa_mask = set; + siga.sa_flags = 0; + if (sigaction(SIGCHLD, &siga, (struct sigaction *)NULL) != 0) { + fprintf(stderr, "sigaction choked: %s!", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Setup a child process to exercise the sig handling for us */ + mypid = getpid(); + if (fork() == 0) { + int i; + + for (i=0; i < 3; i++) { + sleep(2); + kill(mypid, SIGCHLD); + } + _exit(EXIT_SUCCESS); + } + + + /* Wait for signals */ + write(1, "waiting for a SIGCHLD\n",22); + for(;;) { + sleep(10); + if (waitpid(-1, NULL, WNOHANG | WUNTRACED) > 0) + break; + write(1, "after sleep\n", 12); + } + + printf("Bye-bye! All done!\n"); + return 0; +} + +#else + +int main(void) +{ + printf("Skipping test on non-mmu host!\n"); + return 0; +} + +#endif diff --git a/test/signal/signal.c b/test/signal/signal.c new file mode 100644 index 0000000..01d1a78 --- /dev/null +++ b/test/signal/signal.c @@ -0,0 +1,95 @@ +/* vi: set sw=4 ts=4: */ +/* + * signal testing function for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include + + +/* -------------------------------------------------*/ +/* This stuff is common to all the testing routines */ +/* -------------------------------------------------*/ +const char *it = ""; /* Routine name for message routines. */ +size_t errors = 0; + +static void check(int thing, int number) +{ + if (!thing) { + printf("%s: flunked test %d\n", it, number); + ++errors; + } +} + +#if 0 +static void equal(const char *a, const char *b, int number) +{ + check(a != NULL && b != NULL && (strcmp(a, b) == 0), number); +} +#endif + + +/* -------------------------------------------------*/ +/* Let the tests begin.... */ +/* -------------------------------------------------*/ + +int global_int = 0; + +static void set_global_int_to_one(int signum) +{ + printf ("Received signal %d (%s).\n", signum, strsignal(signum)); + global_int = 1; + return; +} + +static void signal_test_1(void) +{ + global_int = 0; + + it = "global variable set from signal handler"; + if (signal(SIGUSR1, set_global_int_to_one) == SIG_ERR) { + perror("signal(SIGUSR1) failed"); + exit(-1); + } + raise(SIGUSR1); + + /* This should already have jumped to the signal handler */ + check((global_int == 1), 1); + + global_int = 0; + if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) { + perror("signal(SIGUSR1) failed"); + exit(-1); + } + raise(SIGUSR1); + /* This should not go to the signal handler this time since we */ + check((global_int == 0), 1); +} + + +int main(void) +{ + int status; + + signal_test_1(); + + if (errors == 0) { + status = EXIT_SUCCESS; + printf("No errors.\n"); + } else { + status = EXIT_FAILURE; + printf("%lu errors.\n", (unsigned long)errors); + } + exit(status); +} diff --git a/test/signal/tst-raise.c b/test/signal/tst-raise.c new file mode 100644 index 0000000..d24c316 --- /dev/null +++ b/test/signal/tst-raise.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +volatile int count; + +static void +sh (int sig) +{ + ++count; +} + +int +main (void) +{ + struct sigaction sa; + sa.sa_handler = sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction (SIGUSR1, &sa, NULL) < 0) + { + printf ("sigaction failed: %s\n", strerror(errno)); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("first raise failed: %s\n", strerror(errno)); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("second raise failed: %s\n", strerror(errno)); + exit (1); + } + if (count != 2) + { + printf ("signal handler not called 2 times\n"); + exit (1); + } + exit (0); +} diff --git a/test/signal/tst-signal.c b/test/signal/tst-signal.c new file mode 100644 index 0000000..6d31787 --- /dev/null +++ b/test/signal/tst-signal.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +int win = 0; + +static void +handler (int sig) +{ + printf ("Received signal %d (%s).\n", sig, strsignal(sig)); + win = 1; +} + +int +main (void) +{ + if (signal (SIGTERM, handler) == SIG_ERR) + { + perror ("signal: SIGTERM"); + exit (EXIT_FAILURE); + } + + puts ("Set handler."); + + printf ("Sending myself signal %d.\n", SIGTERM); + fflush (stdout); + + if (raise (SIGTERM) < 0) + { + perror ("raise: SIGTERM"); + exit (EXIT_FAILURE); + } + + if (!win) + { + puts ("Didn't get any signal. Test FAILED!"); + exit (EXIT_FAILURE); + } + + puts ("Got a signal. Test succeeded."); + + return EXIT_SUCCESS; +} diff --git a/test/signal/tst-sigset.c b/test/signal/tst-sigset.c new file mode 100644 index 0000000..bc1b057 --- /dev/null +++ b/test/signal/tst-sigset.c @@ -0,0 +1,45 @@ +/* Test sig*set functions. */ + +#include +#include +#include +#include + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ + int result = 0; + int sig = -1; + +#define TRY(call) \ + if (call) \ + { \ + printf ("%s (sig = %d): %s\n", #call, sig, strerror(errno)); \ + result = 1; \ + } \ + else + + + sigset_t set; + TRY (sigemptyset (&set) != 0); + +#ifdef SIGRTMAX + int max_sig = SIGRTMAX; +#else + int max_sig = NSIG - 1; +#endif + + for (sig = 1; sig <= max_sig; ++sig) + { + TRY (sigismember (&set, sig) != 0); + TRY (sigaddset (&set, sig) != 0); + TRY (sigismember (&set, sig) == 0); + TRY (sigdelset (&set, sig) != 0); + TRY (sigismember (&set, sig) != 0); + } + + return result; +} + +#include "../test-skeleton.c" diff --git a/test/signal/tst-sigsimple.c b/test/signal/tst-sigsimple.c new file mode 100644 index 0000000..22bb85c --- /dev/null +++ b/test/signal/tst-sigsimple.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + int e; + +#define RUN(test) \ + errno = 0; \ + e = test; \ + if (e != -1) \ + { \ + printf ("%s returned %d\n", #test, e); \ + result = 1; \ + } \ + else if (errno != EINVAL) \ + { \ + printf ("%s didn't set errno to EINVAL (%s instead)\n", \ + #test, strerror (errno)); \ + result = 1; \ + } + + RUN (sighold (-1)); + RUN (sighold (_NSIG + 100)); + + RUN (sigrelse (-1)); + RUN (sigrelse (_NSIG + 100)); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/silly/Makefile b/test/silly/Makefile new file mode 100644 index 0000000..ccd7018 --- /dev/null +++ b/test/silly/Makefile @@ -0,0 +1,7 @@ +# uClibc silly tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +RET_hello := 42 +RET_tiny := 42 diff --git a/test/silly/hello.c b/test/silly/hello.c new file mode 100644 index 0000000..4aba926 --- /dev/null +++ b/test/silly/hello.c @@ -0,0 +1,8 @@ +#include +#include + +int main(void) +{ + printf("hello world\n"); + exit(42); +} diff --git a/test/silly/tiny.c b/test/silly/tiny.c new file mode 100644 index 0000000..e54c0ff --- /dev/null +++ b/test/silly/tiny.c @@ -0,0 +1,6 @@ +#include + +int main(void) +{ + _exit(42); +} diff --git a/test/stat/Makefile b/test/stat/Makefile new file mode 100644 index 0000000..008a812 --- /dev/null +++ b/test/stat/Makefile @@ -0,0 +1,12 @@ +# uClibc stat tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +CFLAGS_stat64 := -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + +DODIFF_stat := 1 +DODIFF_stat64 := 1 + +OPTS_stat := Makefile +OPTS_stat64 := Makefile diff --git a/test/stat/memcmp-stat.c b/test/stat/memcmp-stat.c new file mode 100644 index 0000000..c38e3ff --- /dev/null +++ b/test/stat/memcmp-stat.c @@ -0,0 +1,107 @@ +/* Distilled from issue found with tar and symlinks. + * Make sure that the whole stat struct between runs + * is agreeable. + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void show_stat(struct stat *st) +{ + printf( + "------------------\n" + "st_dev = %li\n" + "st_ino = %li\n" + "st_mode = %li\n" + "st_nlink = %li\n" + "st_uid = %li\n" + "st_gid = %li\n" + "st_rdev = %li\n" + "st_size = %li\n" + "st_blksize = %li\n" + "st_blocks = %li\n" + "st_atime = %li\n" + "st_ansec = %li\n" + "st_mtime = %li\n" + "st_mnsec = %li\n" + "st_ctime = %li\n" + "st_cnsec = %li\n", + (long int)st->st_dev, + (long int)st->st_ino, + (long int)st->st_mode, + (long int)st->st_nlink, + (long int)st->st_uid, + (long int)st->st_gid, + (long int)st->st_rdev, + (long int)st->st_size, + (long int)st->st_blksize, + (long int)st->st_blocks, +#ifndef __UCLIBC__ + (long int)st->st_atime, + (long int)st->st_atim.tv_nsec, + (long int)st->st_mtime, + (long int)st->st_mtim.tv_nsec, + (long int)st->st_ctime, + (long int)st->st_ctim.tv_nsec +#else + (long int)st->st_atime, + (long int)st->st_atimensec, + (long int)st->st_mtime, + (long int)st->st_mtimensec, + (long int)st->st_ctime, + (long int)st->st_ctimensec +#endif + ); +} + +int main(void) +{ + int ret; + int fd; + struct stat fst, st; + + memset(&fst, 0xAA, sizeof(fst)); + memset(&st, 0x55, sizeof(st)); + + unlink(".testfile"); + fd = open(".testfile", O_WRONLY | O_CREAT | O_EXCL, 0); + if (fd < 0) { + perror("open(.testfile) failed"); + return 1; + } + ret = fstat(fd, &fst); + if (ret != 0) { + perror("fstat(.testfile) failed"); + return 1; + } + close(fd); + + ret = stat(".testfile", &st); + if (ret != 0) { + perror("stat(.testfile) failed"); + return 1; + } + + ret = memcmp(&fst, &st, sizeof(fst)); + if (ret != 0) { + printf("FAILED: memcmp() = %i\n", ret); + show_stat(&fst); + show_stat(&st); + } + + unlink(".testfile"); + + return ret; +} diff --git a/test/stat/stat.c b/test/stat/stat.c new file mode 100644 index 0000000..4980cdd --- /dev/null +++ b/test/stat/stat.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +static void print_struct_stat(char *msg, struct stat *s) +{ + printf("%s\n", msg); + /* The casts are because glibc thinks it's cool */ + printf("device : 0x%llx\n",(long long)s->st_dev); + printf("inode : %lld\n", (long long)s->st_ino); + printf("mode : 0x%llx\n",(long long)s->st_mode); + printf("nlink : %lld\n", (long long)s->st_nlink); + printf("uid : %lld\n", (long long)s->st_uid); + printf("gid : %lld\n", (long long)s->st_gid); + printf("rdev : 0x%llx\n",(long long)s->st_rdev); + printf("size : %lld\n", (long long)s->st_size); + printf("blksize : %lld\n", (long long)s->st_blksize); + printf("blocks : %lld\n", (long long)s->st_blocks); + printf("atime : %lld\n", (long long)s->st_atime); + printf("mtime : %lld\n", (long long)s->st_mtime); + printf("ctime : %lld\n", (long long)s->st_ctime); +} + +int main(int argc,char **argv) +{ + int fd, ret; + char *file; + struct stat s; + + if (argc < 2) { + fprintf(stderr, "Usage: stat FILE\n"); + exit(1); + } + file = argv[1]; + + memset(&s, 0, sizeof(struct stat)); + ret = stat(file, &s); + if(ret<0){ + perror("stat"); + exit(1); + } + print_struct_stat("\nTesting stat:", &s); + + memset(&s, 0, sizeof(struct stat)); + ret = lstat(file, &s); + if(ret<0){ + perror("lstat"); + exit(1); + } + print_struct_stat("\nTesting lstat:", &s); + + + fd = open(file, O_RDONLY); + if(fd<0){ + perror("open"); + exit(1); + } + memset(&s, 0, sizeof(struct stat)); + ret = fstat(fd,&s); + if(ret<0){ + perror("fstat"); + exit(1); + } + print_struct_stat("\nTesting fstat:", &s); + + exit(0); +} + diff --git a/test/stat/stat64.c b/test/stat/stat64.c new file mode 100644 index 0000000..a074251 --- /dev/null +++ b/test/stat/stat64.c @@ -0,0 +1 @@ +#include "stat.c" diff --git a/test/stdio/64bit.c b/test/stdio/64bit.c new file mode 100644 index 0000000..9b94dd8 --- /dev/null +++ b/test/stdio/64bit.c @@ -0,0 +1,12 @@ +#include + +int main(void) +{ + unsigned long long val = -1; + void *ptr = (void *)-1; + printf("%p\n", ptr); + + sscanf("123456789", "%Lx", &val); + printf("val = %Lx\n", val); + return 0; +} diff --git a/test/stdio/Makefile b/test/stdio/Makefile new file mode 100644 index 0000000..d3ae2f3 --- /dev/null +++ b/test/stdio/Makefile @@ -0,0 +1,6 @@ +# uClibc assert tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +DODIFF_64bit := 1 diff --git a/test/stdio/fclose-loop.c b/test/stdio/fclose-loop.c new file mode 100644 index 0000000..fc0cc42 --- /dev/null +++ b/test/stdio/fclose-loop.c @@ -0,0 +1,21 @@ +/* From: Denis Vlasenko + * With certain combination of .config options fclose() does not + * remove FILE* pointer from _stdio_openlist. As a result, subsequent + * fopen() may allocate new FILE structure exactly in place of one + * freed by previous fclose(), which then makes _stdio_openlist + * circularlt looped. The following program will enter infinite loop + * trying to walk _stdio_openlist in exit(): + */ + +#include +#include + +int main(int argc, char *argv[]) +{ + FILE* fp; + fp = fopen("/dev/null", "r"); + fclose(fp); + fp = fopen("/dev/zero", "r"); + fclose(fp); + return 0; +} diff --git a/test/stdlib/Makefile b/test/stdlib/Makefile new file mode 100644 index 0000000..efec56d --- /dev/null +++ b/test/stdlib/Makefile @@ -0,0 +1,9 @@ +# uClibc stdlib tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +DODIFF_qsort := 1 +DODIFF_testatexit := 1 +DODIFF_teston_exit := 1 +DODIFF_teststrtol := 1 diff --git a/test/stdlib/ptytest.c b/test/stdlib/ptytest.c new file mode 100644 index 0000000..a795638 --- /dev/null +++ b/test/stdlib/ptytest.c @@ -0,0 +1,20 @@ +#define _XOPEN_SOURCE +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int fd; + char *cp; + + fd=open("/dev/ptmx",O_NOCTTY|O_RDWR); + cp=ptsname(fd); + if (cp==NULL) + return EXIT_FAILURE; + printf("ptsname %s\n",cp); + return EXIT_SUCCESS; +} + diff --git a/test/stdlib/qsort.c b/test/stdlib/qsort.c new file mode 100644 index 0000000..abc505e --- /dev/null +++ b/test/stdlib/qsort.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +static int select_files(const struct dirent *dirbuf) +{ + if (dirbuf->d_name[0] == '.') + return 0; + else + return 1; +} + +int main(void) +{ + struct dirent **array; + struct dirent *dirbuf; + + int i, numdir; + + chdir("/"); + numdir = scandir(".", &array, select_files, NULL); + printf("\nGot %d entries from scandir().\n", numdir); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + free(array[i]); + } + free(array); + numdir = scandir(".", &array, select_files, alphasort); + printf("\nGot %d entries from scandir() using alphasort().\n", numdir); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + } + printf("\nCalling qsort()\n"); + qsort(array, numdir, sizeof(struct dirent *), alphasort); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + free(array[i]); + } + free(array); + return (0); +} diff --git a/test/stdlib/test-canon.c b/test/stdlib/test-canon.c new file mode 100644 index 0000000..9770a94 --- /dev/null +++ b/test/stdlib/test-canon.c @@ -0,0 +1,251 @@ +/* Test program for returning the canonical absolute name of a given file. + Copyright (C) 1996,1997,2000,2002,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file must be run from within a directory called "stdlib". */ + +#include +#include +#include +#include +#include +#include +#include + +/* Prototype for our test function. */ +extern int do_test (int argc, char *argv[]); +#include + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif +static char cwd[PATH_MAX]; +static size_t cwd_len; + +struct { + const char * name; + const char * value; +} symlinks[] = { + {"SYMLINK_LOOP", "SYMLINK_LOOP"}, + {"SYMLINK_1", "."}, + {"SYMLINK_2", "//////./../../etc"}, + {"SYMLINK_3", "SYMLINK_1"}, + {"SYMLINK_4", "SYMLINK_2"}, + {"SYMLINK_5", "doesNotExist"}, +}; + +struct { + const char * in; + const char * retval; /* what realpath should return */ + const char * retbuf; /* what realpath should store in buf */ + /* if both of the above are NULL, we won't check for result, + * it's undefined */ + int error; /* expected errno value */ +} tests[] = { + /* 0 */ + {"/", "/"}, + {"/////////////////////////////////", "/"}, + {"/.././.././.././..///", "/"}, + {"/etc", "/etc"}, + {"/etc/../etc", "/etc"}, + /* 5 */ + {"/doesNotExist/../etc", 0, "/doesNotExist", ENOENT}, + {"./././././././././.", "."}, + {"/etc/.//doesNotExist", 0, "/etc/doesNotExist", ENOENT}, + {"./doesExist", "./doesExist"}, + {"./doesExist/", "./doesExist"}, + /* 10 */ + {"./doesExist/../doesExist", "./doesExist"}, + {"foobar", 0, "./foobar", ENOENT}, + {".", "."}, + {"./foobar", 0, "./foobar", ENOENT}, + {"SYMLINK_LOOP", 0, 0, ELOOP}, + /* 15 */ + {"./SYMLINK_LOOP", 0, 0, ELOOP}, + {"SYMLINK_1", "."}, + {"SYMLINK_1/foobar", 0, "./foobar", ENOENT}, + {"SYMLINK_2", "/etc"}, + {"SYMLINK_3", "."}, + /* 20 */ + {"SYMLINK_4", "/etc"}, + {"../stdlib/SYMLINK_1", "."}, + {"../stdlib/SYMLINK_2", "/etc"}, + {"../stdlib/SYMLINK_3", "."}, + {"../stdlib/SYMLINK_4", "/etc"}, + /* 25 */ + {"./SYMLINK_5", 0, "./doesNotExist", ENOENT}, + {"SYMLINK_5", 0, "./doesNotExist", ENOENT}, + {"SYMLINK_5/foobar", 0, "./doesNotExist", ENOENT}, + {"doesExist/../../stdlib/doesExist", "./doesExist"}, + {"doesExist/.././../stdlib/.", "."}, +#ifndef __UCLIBC__ + /* we dont check for ENOTDIR in readlink() which causes failures to + * propogate up to realpath() ... so disable for now ... */ + /* 30 */ + {"./doesExist/someFile/", 0, "./doesExist/someFile", ENOTDIR}, + {"./doesExist/someFile/..", 0, "./doesExist/someFile", ENOTDIR}, +#endif +}; + + +static int +check_path (const char * result, const char * expected) +{ + int good; + + if (!result) + return (expected == NULL); + + if (!expected) + return 0; + + if (expected[0] == '.' && (expected[1] == '/' || expected[1] == '\0')) + good = (strncmp (result, cwd, cwd_len) == 0 + && strcmp (result + cwd_len, expected + 1) == 0); + else + good = (strcmp (expected, result) == 0); + + return good; +} + + +int +do_test (int argc, char ** argv) +{ + char * result; + int i, errors = 0; + char buf[PATH_MAX]; + + getcwd (cwd, sizeof(buf)); + cwd_len = strlen (cwd); + +#ifndef __UCLIBC__ + /* we choose to crash in uClibc when given a NULL */ + errno = 0; + if (realpath (NULL, buf) != NULL || errno != EINVAL) + { + printf ("%s: expected return value NULL and errno set to EINVAL" + " for realpath(NULL,...)\n", argv[0]); + ++errors; + } +#endif + +#if 0 + /* This is now allowed. The test is invalid. */ + errno = 0; + if (realpath ("/", NULL) != NULL || errno != EINVAL) + { + printf ("%s: expected return value NULL and errno set to EINVAL" + " for realpath(...,NULL)\n", argv[0]); + ++errors; + } +#endif + + errno = 0; + if (realpath ("", buf) != NULL || errno != ENOENT) + { + printf ("%s: expected return value NULL and set errno to ENOENT" + " for realpath(\"\",...)\n", argv[0]); + ++errors; + } + + for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i) + symlink (symlinks[i].value, symlinks[i].name); + + int has_dir = mkdir ("doesExist", 0777) == 0; + + int fd = has_dir ? creat ("doesExist/someFile", 0777) : -1; + + for (i = 0; i < (int) (sizeof (tests) / sizeof (tests[0])); ++i) + { + buf[0] = '\0'; + errno = 0; + result = realpath (tests[i].in, buf); + + if (!check_path (result, tests[i].retval)) + { + printf ("%s: flunked test %d (expected `%s', got `%s')\n", + argv[0], i, tests[i].retval ? tests[i].retval : "NULL", + result ? result : "NULL"); + ++errors; + continue; + } + + if (result && !check_path (buf, tests[i].retval ? tests[i].retval : tests[i].retbuf)) + { + printf ("%s: flunked test %d (expected resolved `%s', got `%s')\n", + argv[0], i, tests[i].retval ? tests[i].retval : tests[i].retbuf, + buf); + ++errors; + continue; + } + + if (errno != tests[i].error) + { + printf ("%s: flunked test %d (expected errno %d, got %d)\n", + argv[0], i, tests[i].error, errno); + ++errors; + continue; + } + +#ifndef __UCLIBC__ + /* we choose to crash in uClibc when given a NULL */ + char *result2 = realpath (tests[i].in, NULL); + if ((result2 == NULL && result != NULL) + || (result2 != NULL && strcmp (result, result2) != 0)) + { + printf ("\ +%s: realpath(..., NULL) produced different result than realpath(..., buf): '%s' vs '%s'\n", + argv[0], result2, result); + ++errors; + } + free (result2); +#endif + } + + getcwd (buf, sizeof(buf)); + if (strcmp (buf, cwd)) + { + printf ("%s: current working directory changed from %s to %s\n", + argv[0], cwd, buf); + ++errors; + } + + if (fd >= 0) + { + close (fd); + unlink ("doesExist/someFile"); + } + + if (has_dir) + rmdir ("doesExist"); + + for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i) + unlink (symlinks[i].name); + + if (errors != 0) + { + printf ("%d errors.\n", errors); + return EXIT_FAILURE; + } + + puts ("No errors."); + return EXIT_SUCCESS; +} diff --git a/test/stdlib/testatexit.c b/test/stdlib/testatexit.c new file mode 100644 index 0000000..01874fd --- /dev/null +++ b/test/stdlib/testatexit.c @@ -0,0 +1,81 @@ +/* + * This test program will register the maximum number of exit functions + * with atexit(). When this program exits, each exit function should get + * called in the reverse order in which it was registered. (If the system + * supports more than 25 exit functions, the function names will loop, but + * the effect will be the same. Feel free to add more functions if desired) + */ +#include +#include + +typedef void (*vfuncp) (void); + +/* All functions call exit(), in order to test that exit functions can call + * exit() without screwing everything up. :) + */ +#define make_exitfunc(num) \ +__attribute__ ((__noreturn__)) static \ +void exitfunc##num(void) \ +{ \ + printf("Executing exitfunc"#num".\n"); \ + exit(0); \ +} +make_exitfunc(0) +make_exitfunc(1) +make_exitfunc(2) +make_exitfunc(3) +make_exitfunc(4) +make_exitfunc(5) +make_exitfunc(6) +make_exitfunc(7) +make_exitfunc(8) +make_exitfunc(9) +make_exitfunc(10) +make_exitfunc(11) +make_exitfunc(12) +make_exitfunc(13) +make_exitfunc(14) +make_exitfunc(15) +make_exitfunc(16) +make_exitfunc(17) +make_exitfunc(18) +make_exitfunc(19) +make_exitfunc(20) +make_exitfunc(21) +make_exitfunc(22) +make_exitfunc(23) +make_exitfunc(24) + +static vfuncp func_table[] = + { + exitfunc0, exitfunc1, exitfunc2, exitfunc3, exitfunc4, + exitfunc5, exitfunc6, exitfunc7, exitfunc8, exitfunc9, + exitfunc10, exitfunc11, exitfunc12, exitfunc13, exitfunc14, + exitfunc15, exitfunc16, exitfunc17, exitfunc18, exitfunc19, + exitfunc20, exitfunc21, exitfunc22, exitfunc23, exitfunc24 + }; + +/* glibc dynamically adds exit functions, so it will keep adding until + * it runs out of memory! So this will limit the number of exit functions + * we add in the loop below. uClibc has a set limit (currently 20), so the + * loop will go until it can't add any more (so it should not hit this limit). + */ +#define ATEXIT_LIMIT 20 + +int +main ( void ) +{ + int i = 0; + int count = 0; + int numfuncs = sizeof(func_table)/sizeof(vfuncp); + + /* loop until no more can be added */ + while(count < ATEXIT_LIMIT && atexit(func_table[i]) >= 0) { + printf("Registered exitfunc%d with atexit()\n", i); + count++; + i = (i+1) % numfuncs; + } + printf("%d functions registered with atexit.\n", count); + + return 0; +} diff --git a/test/stdlib/teston_exit.c b/test/stdlib/teston_exit.c new file mode 100644 index 0000000..f7e8fd0 --- /dev/null +++ b/test/stdlib/teston_exit.c @@ -0,0 +1,82 @@ +/* + * This test program will register the maximum number of exit functions + * with on_exit(). When this program exits, each exit function should get + * called in the reverse order in which it was registered. (If the system + * supports more than 25 exit functions, the function names will loop, but + * the effect will be the same. Feel free to add more functions if desired) + */ +#include +#include + +typedef void (*efuncp) (int, void *); + +/* All functions call exit(), in order to test that exit functions can call + * exit() without screwing everything up. The value passed in through arg gets + * used as the next exit status. + */ +#define make_exitfunc(num) \ +__attribute__ ((__noreturn__)) static \ +void exitfunc##num(int status, void *arg) \ +{ \ + printf("Executing exitfunc"#num" (status=%d, arg=%lu)\n", status, (unsigned long)arg); \ + exit((unsigned long)arg); \ +} +make_exitfunc(0) +make_exitfunc(1) +make_exitfunc(2) +make_exitfunc(3) +make_exitfunc(4) +make_exitfunc(5) +make_exitfunc(6) +make_exitfunc(7) +make_exitfunc(8) +make_exitfunc(9) +make_exitfunc(10) +make_exitfunc(11) +make_exitfunc(12) +make_exitfunc(13) +make_exitfunc(14) +make_exitfunc(15) +make_exitfunc(16) +make_exitfunc(17) +make_exitfunc(18) +make_exitfunc(19) +make_exitfunc(20) +make_exitfunc(21) +make_exitfunc(22) +make_exitfunc(23) +make_exitfunc(24) + +static efuncp func_table[] = + { + exitfunc0, exitfunc1, exitfunc2, exitfunc3, exitfunc4, + exitfunc5, exitfunc6, exitfunc7, exitfunc8, exitfunc9, + exitfunc10, exitfunc11, exitfunc12, exitfunc13, exitfunc14, + exitfunc15, exitfunc16, exitfunc17, exitfunc18, exitfunc19, + exitfunc20, exitfunc21, exitfunc22, exitfunc23, exitfunc24 + }; + +/* glibc dynamically adds exit functions, so it will keep adding until + * it runs out of memory! So this will limit the number of exit functions + * we add in the loop below. uClibc has a set limit (currently 20), so the + * loop will go until it can't add any more (so it should not hit this limit). + */ +#define ON_EXIT_LIMIT 20 + +int +main ( void ) +{ + int i = 0; + unsigned long count = 0; + int numfuncs = sizeof(func_table)/sizeof(efuncp); + + /* loop until no more can be added */ + while(count < ON_EXIT_LIMIT && on_exit(func_table[i], (void *)count) >= 0) { + count++; + printf("Registered exitfunc%d with on_exit()\n", i); + i = (i+1) % numfuncs; + } + printf("%lu functions registered with on_exit.\n", count); + exit(count); +} + diff --git a/test/stdlib/teststrtol.c b/test/stdlib/teststrtol.c new file mode 100644 index 0000000..5b43a9b --- /dev/null +++ b/test/stdlib/teststrtol.c @@ -0,0 +1,109 @@ + +#include +#include + + +const char *strings[]={ + /* some simple stuff */ + "0", "1", "10", + "100", "1000", "10000", "100000", "1000000", + "10000000", "100000000", "1000000000", + + /* negative */ + "-0", "-1", "-10", + "-100", "-1000", "-10000", "-100000", "-1000000", + "-10000000", "-100000000", "-1000000000", + + /* test base>10 */ + "a", "b", "f", "g", "z", + + /* test hex */ + "0x0", "0x1", "0xa", "0xf", "0x10", + + /* test octal */ + "00", "01", "07", "08", "0a", "010", + + /* other */ + "0x8000000", + + /* check overflow cases: (for 32 bit) */ + "2147483645", + "2147483646", + "2147483647", + "2147483648", + "2147483649", + "-2147483645", + "-2147483646", + "-2147483647", + "-2147483648", + "-2147483649", + "4294967293", + "4294967294", + "4294967295", + "4294967296", + "4294967297", + "-4294967293", + "-4294967294", + "-4294967295", + "-4294967296", + "-4294967297", + + /* bad input tests */ + "", + "00", + "0x", + "0x0", + "-", + "+", + " ", + " -", + " - 0", +}; +int n_tests=sizeof(strings)/sizeof(strings[0]); + +void do_test(int base); +void do_utest(int base); + +int main(int argc,char *argv[]) +{ + do_test(0); + do_test(8); + do_test(10); + do_test(16); + do_test(36); + + do_utest(0); + do_utest(8); + do_utest(10); + do_utest(16); + do_utest(36); + + return 0; +} + +void do_test(int base) +{ + int i; + long n; + char *endptr; + + for(i=0;i +#include +#include + +int +main (void) +{ + const char t1[] = "0-0-0-0-0-0-0-0-0-0.COM"; + const char t2[] = "00000-00000.COM"; + int res1; + int res2; + + setlocale (LC_ALL, "en_US.ISO-8859-1"); + + res1 = strcoll (t1, t2); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, res1); + res2 = strcoll (t2, t1); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, res2); + + return ((res1 == 0 && res2 != 0) + || (res1 != 0 && res2 == 0) + || (res1 < 0 && res2 < 0) + || (res1 > 0 && res2 > 0)); +} diff --git a/test/string/bug-strncat1.c b/test/string/bug-strncat1.c new file mode 100644 index 0000000..f1b5c37 --- /dev/null +++ b/test/string/bug-strncat1.c @@ -0,0 +1,31 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +char d[3] = "\0\1\2"; + +int +main (void) +{ + strncat (d, "\5\6", 1); + if (d[0] != '\5') + { + puts ("d[0] != '\\5'"); + exit (1); + } + if (d[1] != '\0') + { + puts ("d[1] != '\\0'"); + exit (1); + } + if (d[2] != '\2') + { + puts ("d[2] != '\\2'"); + exit (1); + } + + return 0; +} diff --git a/test/string/bug-strpbrk1.c b/test/string/bug-strpbrk1.c new file mode 100644 index 0000000..28238b0 --- /dev/null +++ b/test/string/bug-strpbrk1.c @@ -0,0 +1,19 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +int +main (void) +{ + const char *a = "abc"; + const char *b = a; + + strpbrk (b++, ""); + if (b != a + 1) + return 1; + + return 0; +} diff --git a/test/string/bug-strspn1.c b/test/string/bug-strspn1.c new file mode 100644 index 0000000..a657baf --- /dev/null +++ b/test/string/bug-strspn1.c @@ -0,0 +1,19 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +int +main (void) +{ + const char *a = "abc"; + const char *b = a; + + strspn (b++, ""); + if (b != a + 1) + return 1; + + return 0; +} diff --git a/test/string/stratcliff.c b/test/string/stratcliff.c new file mode 100644 index 0000000..41e7746 --- /dev/null +++ b/test/string/stratcliff.c @@ -0,0 +1,349 @@ +/* Test for string function add boundaries of usable memory. + Copyright (C) 1996,1997,1999-2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _GNU_SOURCE 1 + +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#undef __USE_STRING_INLINES + +#include +#include +#include +#include +#include +#include + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +int +main (int argc, char *argv[]) +{ + int size = sysconf (_SC_PAGESIZE); + char *adr, *dest; + int result = 0; + + adr = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + dest = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (adr == MAP_FAILED || dest == MAP_FAILED) + { + if (errno == ENOSYS) + puts ("No test, mmap not available."); + else + { + printf ("mmap failed: %s", strerror(errno)); + result = 1; + } + } + else + { + int inner, middle, outer; + + mprotect(adr, size, PROT_NONE); + mprotect(adr + 2 * size, size, PROT_NONE); + adr += size; + + mprotect(dest, size, PROT_NONE); + mprotect(dest + 2 * size, size, PROT_NONE); + dest += size; + + memset (adr, 'T', size); + + /* strlen test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if (strlen (&adr[outer]) != (size_t) (inner - outer)) + { + printf ("strlen flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* strchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + for (inner = middle; inner < size; ++inner) + { + char *cp; + adr[middle] = 'V'; + adr[inner] = '\0'; + + cp = strchr (&adr[outer], 'V'); + + if ((inner == middle && cp != NULL) + || (inner != middle + && (cp - &adr[outer]) != middle - outer)) + { + printf ("strchr flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + + adr[inner] = 'T'; + adr[middle] = 'T'; + } + } + } + + /* Special test. */ + adr[size - 1] = '\0'; + if (strchr (&adr[size - 1], '\n') != NULL) + { + puts ("strchr flunked for test of empty string at end of page"); + result = 1; + } + + /* strrchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + for (inner = middle; inner < size; ++inner) + { + char *cp; + adr[middle] = 'V'; + adr[inner] = '\0'; + + cp = strrchr (&adr[outer], 'V'); + + if ((inner == middle && cp != NULL) + || (inner != middle + && (cp - &adr[outer]) != middle - outer)) + { + printf ("strrchr flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + + adr[inner] = 'T'; + adr[middle] = 'T'; + } + } + } + + /* rawmemchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + char *cp; + adr[middle] = 'V'; + + cp = rawmemchr (&adr[outer], 'V'); + + if (cp - &adr[outer] != middle - outer) + { + printf ("rawmemchr flunked for outer = %d, middle = %d\n", + outer, middle); + result = 1; + } + + adr[middle] = 'T'; + } + } + + /* strcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if (strcpy (dest, &adr[outer]) != dest + || strlen (dest) != (size_t) (inner - outer)) + { + printf ("strcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* strncpy tests */ + adr[size-1] = 'T'; + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + size_t len; + + for (len = 0; len < size - outer; ++len) + { + if (strncpy (dest, &adr[outer], len) != dest + || memcmp (dest, &adr[outer], len) != 0) + { + printf ("outer strncpy flunked for outer = %d, len = %Zd\n", + outer, len); + result = 1; + } + } + } + adr[size-1] = '\0'; + + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + size_t len; + + adr[inner] = '\0'; + + for (len = 0; len < size - outer + 64; ++len) + { + if (strncpy (dest, &adr[outer], len) != dest + || memcmp (dest, &adr[outer], + MIN (inner - outer, len)) != 0 + || (inner - outer < len + && strlen (dest) != (inner - outer))) + { + printf ("strncpy flunked for outer = %d, inner = %d, len = %Zd\n", + outer, inner, len); + result = 1; + } + if (strncpy (dest + 1, &adr[outer], len) != dest + 1 + || memcmp (dest + 1, &adr[outer], + MIN (inner - outer, len)) != 0 + || (inner - outer < len + && strlen (dest + 1) != (inner - outer))) + { + printf ("strncpy+1 flunked for outer = %d, inner = %d, len = %Zd\n", + outer, inner, len); + result = 1; + } + } + + adr[inner] = 'T'; + } + } + + /* stpcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if ((stpcpy (dest, &adr[outer]) - dest) != inner - outer) + { + printf ("stpcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* stpncpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + adr[middle] = '\0'; + + for (inner = 0; inner < size - outer; ++ inner) + { + if ((stpncpy (dest, &adr[outer], inner) - dest) + != MIN (inner, middle - outer)) + { + printf ("stpncpy flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + } + + adr[middle] = 'T'; + } + } + + /* memcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (memcpy (dest, &adr[outer], inner) != dest) + { + printf ("memcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + /* mempcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (mempcpy (dest, &adr[outer], inner) != dest + inner) + { + printf ("mempcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + /* memccpy test */ + memset (adr, '\0', size); + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (memccpy (dest, &adr[outer], '\1', inner) != NULL) + { + printf ("memccpy flunked full copy for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (middle = 0; middle < size - outer; ++middle) + { + memset (dest, '\2', middle + 1); + for (inner = 0; inner < middle; ++inner) + { + adr[outer + inner] = '\1'; + + if (memccpy (dest, &adr[outer], '\1', middle + 128) + != dest + inner + 1) + { + printf ("\ +memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n", + outer, middle, inner); + result = 1; + } + else if (dest[inner + 1] != '\2') + { + printf ("\ +memccpy copied too much for outer = %d, middle = %d, inner = %d\n", + outer, middle, inner); + result = 1; + } + adr[outer + inner] = '\0'; + } + } + } + + return result; +} diff --git a/test/string/test-ffs.c b/test/string/test-ffs.c new file mode 100644 index 0000000..86e1175 --- /dev/null +++ b/test/string/test-ffs.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1994, 1997, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil), + On-Line Applications Research Corporation. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +main (void) +{ + int failures = 0; + int i; + + auto void try (const char *name, long long int param, int value, + int expected); + + void try (const char *name, long long int param, int value, int expected) + { + if (value != expected) + { + printf ("%s(%#llx) expected %d got %d\n", + name, param, expected, value); + ++failures; + } + else + printf ("%s(%#llx) as expected %d\n", name, param, value); + } + +#define TEST(fct, type) \ + try (#fct, 0, fct ((type) 0), 0); \ + for (i=0 ; i < 8 * sizeof (type); i++) \ + try (#fct, 1ll << i, fct (((type) 1) << i), i + 1); \ + for (i=0 ; i < 8 * sizeof (type) ; i++) \ + try (#fct, (~((type) 0) >> i) << i, fct ((~((type) 0) >> i) << i), i + 1);\ + try (#fct, 0x80008000, fct ((type) 0x80008000), 16) + + TEST (ffs, int); +/* Not implemented in uClibc (yet?) + TEST (ffsl, long int); + TEST (ffsll, long long int); +*/ + + if (failures) + printf ("Test FAILED! %d failure%s.\n", failures, &"s"[failures == 1]); + else + puts ("Test succeeded."); + + return failures; +} diff --git a/test/string/testcopy.c b/test/string/testcopy.c new file mode 100644 index 0000000..60039f7 --- /dev/null +++ b/test/string/testcopy.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1990, 1991, 1992, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +main (void) +{ + char *mem, *memp; + char *rand_mem; + char *lo_around, *hi_around; + int size, max_size; + int src_off, dst_off; + int i; + int space_around = 10; + + max_size = 256; + + mem = malloc (max_size + 2 * max_size + 2 * space_around); + rand_mem = malloc (max_size); + lo_around = malloc (space_around); + hi_around = malloc (space_around); + memp = mem + space_around; + + /* Fill RAND_MEM with random bytes, each non-zero. */ + for (i = 0; i < max_size; i++) + { + int x; + do + x = random (); + while (x == 0); + rand_mem[i] = x; + } + + for (size = 0; size < max_size; size++) + { + printf("phase %d\n", size); + for (src_off = 0; src_off <= 16; src_off++) + { + for (dst_off = 0; dst_off <= 16; dst_off++) + { + /* Put zero around the intended destination, to check + that it's not clobbered. */ + for (i = 1; i < space_around; i++) + { + memp[dst_off - i] = 0; + memp[dst_off + size - 1 + i] = 0; + } + + /* Fill the source area with known contents. */ + for (i = 0; i < size; i++) + memp[src_off + i] = rand_mem[i]; + + /* Remember the contents around the destination area. + (It might not be what we wrote some lines above, since + the src area and the dst area overlap.) */ + for (i = 1; i < space_around; i++) + { + lo_around[i] = memp[dst_off - i]; + hi_around[i] = memp[dst_off + size - 1 + i]; + } + + memmove (memp + dst_off, memp + src_off, size); + + /* Check that the destination area has the same + contents we wrote to the source area. */ + for (i = 0; i < size; i++) + { + if (memp[dst_off + i] != rand_mem[i]) + abort (); + } + + /* Check that the area around the destination is not + clobbered. */ + for (i = 1; i < space_around; i++) + { + if (memp[dst_off - i] != lo_around[i]) + abort (); + if (memp[dst_off + size - 1 + i] != hi_around[i]) + abort (); + } + } + } + } + + puts ("Test succeeded."); + + return 0; +} diff --git a/test/string/tester.c b/test/string/tester.c new file mode 100644 index 0000000..7c8d314 --- /dev/null +++ b/test/string/tester.c @@ -0,0 +1,1647 @@ +/* Tester for string functions. + Copyright (C) 1995-2001, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#if !defined DO_STRING_INLINES +#undef __USE_STRING_INLINES +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC__ +# define __TEST_BSD_FUNCS__ +#else +# undef __TEST_BSD_FUNCS__ +#endif + +#if defined(__UCLIBC_SUSV3_LEGACY__) || defined(__UCLIBC_SUSV3_LEGACY_MACROS__) +# define __TEST_SUSV3_LEGACY__ +#else +# undef __TEST_SUSV3_LEGACY__ +#endif + +#define STREQ(a, b) (strcmp((a), (b)) == 0) + +const char *it = ""; /* Routine name for message routines. */ +size_t errors = 0; + +/* Complain if condition is not true. */ +static void +check (int thing, int number) +{ + if (!thing) + { + printf("%s flunked test %d\n", it, number); + ++errors; + } +} + +/* Complain if first two args don't strcmp as equal. */ +static void +equal (const char *a, const char *b, int number) +{ + check(a != NULL && b != NULL && STREQ (a, b), number); +} + +char one[50]; +char two[50]; +char *cp; + +static void +test_strcmp (void) +{ + it = "strcmp"; + check (strcmp ("", "") == 0, 1); /* Trivial case. */ + check (strcmp ("a", "a") == 0, 2); /* Identity. */ + check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */ + check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */ + check (strcmp ("abcd", "abc") > 0, 5); + check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */ + check (strcmp ("abce", "abcd") > 0, 7); + check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */ + check (strcmp ("a\203", "a\003") > 0, 9); + + { + char buf1[0x40], buf2[0x40]; + int i, j; + for (i=0; i < 0x10; i++) + for (j = 0; j < 0x10; j++) + { + int k; + for (k = 0; k < 0x3f; k++) + { + buf1[k] = '0' ^ (k & 4); + buf2[k] = '4' ^ (k & 4); + } + buf1[i] = buf1[0x3f] = 0; + buf2[j] = buf2[0x3f] = 0; + for (k = 0; k < 0xf; k++) + { + int cnum = 0x10+0x10*k+0x100*j+0x1000*i; + check (strcmp (buf1+i,buf2+j) == 0, cnum); + buf1[i+k] = 'A' + i + k; + buf1[i+k+1] = 0; + check (strcmp (buf1+i,buf2+j) > 0, cnum+1); + check (strcmp (buf2+j,buf1+i) < 0, cnum+2); + buf2[j+k] = 'B' + i + k; + buf2[j+k+1] = 0; + check (strcmp (buf1+i,buf2+j) < 0, cnum+3); + check (strcmp (buf2+j,buf1+i) > 0, cnum+4); + buf2[j+k] = 'A' + i + k; + buf1[i] = 'A' + i + 0x80; + check (strcmp (buf1+i,buf2+j) > 0, cnum+5); + check (strcmp (buf2+j,buf1+i) < 0, cnum+6); + buf1[i] = 'A' + i; + } + } + } +} + +#define SIMPLE_COPY(fn, n, str, ntest) \ + do { \ + int __n; \ + char *cp; \ + for (__n = 0; __n < (int) sizeof (one); ++__n) \ + one[__n] = 'Z'; \ + fn (one, str); \ + for (cp = one, __n = 0; __n < n; ++__n, ++cp) \ + check (*cp == '0' + (n % 10), ntest); \ + check (*cp == '\0', ntest); \ + } while (0) + +static void +test_strcpy (void) +{ + int i; + it = "strcpy"; + check (strcpy (one, "abcd") == one, 1); /* Returned value. */ + equal (one, "abcd", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + equal (one, "x", 3); /* Writeover. */ + equal (one+2, "cd", 4); /* Wrote too much? */ + + (void) strcpy (two, "hi there"); + (void) strcpy (one, two); + equal (one, "hi there", 5); /* Basic test encore. */ + equal (two, "hi there", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + equal (one, "", 7); /* Boundary condition. */ + + for (i = 0; i < 16; i++) + { + (void) strcpy (one + i, "hi there"); /* Unaligned destination. */ + equal (one + i, "hi there", 8 + (i * 2)); + (void) strcpy (two, one + i); /* Unaligned source. */ + equal (two, "hi there", 9 + (i * 2)); + } + + SIMPLE_COPY(strcpy, 0, "", 41); + SIMPLE_COPY(strcpy, 1, "1", 42); + SIMPLE_COPY(strcpy, 2, "22", 43); + SIMPLE_COPY(strcpy, 3, "333", 44); + SIMPLE_COPY(strcpy, 4, "4444", 45); + SIMPLE_COPY(strcpy, 5, "55555", 46); + SIMPLE_COPY(strcpy, 6, "666666", 47); + SIMPLE_COPY(strcpy, 7, "7777777", 48); + SIMPLE_COPY(strcpy, 8, "88888888", 49); + SIMPLE_COPY(strcpy, 9, "999999999", 50); + SIMPLE_COPY(strcpy, 10, "0000000000", 51); + SIMPLE_COPY(strcpy, 11, "11111111111", 52); + SIMPLE_COPY(strcpy, 12, "222222222222", 53); + SIMPLE_COPY(strcpy, 13, "3333333333333", 54); + SIMPLE_COPY(strcpy, 14, "44444444444444", 55); + SIMPLE_COPY(strcpy, 15, "555555555555555", 56); + SIMPLE_COPY(strcpy, 16, "6666666666666666", 57); + + /* Simple test using implicitly coerced `void *' arguments. */ + const void *src = "frobozz"; + void *dst = one; + check (strcpy (dst, src) == dst, 1); + equal (dst, "frobozz", 2); +} + +static void +test_stpcpy (void) +{ + it = "stpcpy"; + check ((stpcpy (one, "a") - one) == 1, 1); + equal (one, "a", 2); + + check ((stpcpy (one, "ab") - one) == 2, 3); + equal (one, "ab", 4); + + check ((stpcpy (one, "abc") - one) == 3, 5); + equal (one, "abc", 6); + + check ((stpcpy (one, "abcd") - one) == 4, 7); + equal (one, "abcd", 8); + + check ((stpcpy (one, "abcde") - one) == 5, 9); + equal (one, "abcde", 10); + + check ((stpcpy (one, "abcdef") - one) == 6, 11); + equal (one, "abcdef", 12); + + check ((stpcpy (one, "abcdefg") - one) == 7, 13); + equal (one, "abcdefg", 14); + + check ((stpcpy (one, "abcdefgh") - one) == 8, 15); + equal (one, "abcdefgh", 16); + + check ((stpcpy (one, "abcdefghi") - one) == 9, 17); + equal (one, "abcdefghi", 18); + + check ((stpcpy (one, "x") - one) == 1, 19); + equal (one, "x", 20); /* Writeover. */ + equal (one+2, "cdefghi", 21); /* Wrote too much? */ + + check ((stpcpy (one, "xx") - one) == 2, 22); + equal (one, "xx", 23); /* Writeover. */ + equal (one+3, "defghi", 24); /* Wrote too much? */ + + check ((stpcpy (one, "xxx") - one) == 3, 25); + equal (one, "xxx", 26); /* Writeover. */ + equal (one+4, "efghi", 27); /* Wrote too much? */ + + check ((stpcpy (one, "xxxx") - one) == 4, 28); + equal (one, "xxxx", 29); /* Writeover. */ + equal (one+5, "fghi", 30); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxx") - one) == 5, 31); + equal (one, "xxxxx", 32); /* Writeover. */ + equal (one+6, "ghi", 33); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxx") - one) == 6, 34); + equal (one, "xxxxxx", 35); /* Writeover. */ + equal (one+7, "hi", 36); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxxx") - one) == 7, 37); + equal (one, "xxxxxxx", 38); /* Writeover. */ + equal (one+8, "i", 39); /* Wrote too much? */ + + check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40); + equal (one, "abc", 41); + equal (one + 4, "xxx", 42); + + SIMPLE_COPY(stpcpy, 0, "", 43); + SIMPLE_COPY(stpcpy, 1, "1", 44); + SIMPLE_COPY(stpcpy, 2, "22", 45); + SIMPLE_COPY(stpcpy, 3, "333", 46); + SIMPLE_COPY(stpcpy, 4, "4444", 47); + SIMPLE_COPY(stpcpy, 5, "55555", 48); + SIMPLE_COPY(stpcpy, 6, "666666", 49); + SIMPLE_COPY(stpcpy, 7, "7777777", 50); + SIMPLE_COPY(stpcpy, 8, "88888888", 51); + SIMPLE_COPY(stpcpy, 9, "999999999", 52); + SIMPLE_COPY(stpcpy, 10, "0000000000", 53); + SIMPLE_COPY(stpcpy, 11, "11111111111", 54); + SIMPLE_COPY(stpcpy, 12, "222222222222", 55); + SIMPLE_COPY(stpcpy, 13, "3333333333333", 56); + SIMPLE_COPY(stpcpy, 14, "44444444444444", 57); + SIMPLE_COPY(stpcpy, 15, "555555555555555", 58); + SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59); +} + +static void +test_stpncpy (void) +{ + it = "stpncpy"; + memset (one, 'x', sizeof (one)); + check (stpncpy (one, "abc", 2) == one + 2, 1); + check (stpncpy (one, "abc", 3) == one + 3, 2); + check (stpncpy (one, "abc", 4) == one + 3, 3); + check (one[3] == '\0' && one[4] == 'x', 4); + check (stpncpy (one, "abcd", 5) == one + 4, 5); + check (one[4] == '\0' && one[5] == 'x', 6); + check (stpncpy (one, "abcd", 6) == one + 4, 7); + check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8); +} + +static void +test_strcat (void) +{ + it = "strcat"; + (void) strcpy (one, "ijk"); + check (strcat (one, "lmn") == one, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strcat (one, "yz"); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strcat (one, two); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strcat (one, ""); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strcat (one, ""); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strcat (one, "cd"); + equal (one, "cd", 9); +} + +static void +test_strncat (void) +{ + /* First test it as strcat, with big counts, then test the count + mechanism. */ + it = "strncat"; + (void) strcpy (one, "ijk"); + check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strncat (one, "yz", 99); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strncat (one, two, 99); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strncat (one, "", 99); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strncat (one, "", 99); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strncat (one, "cd", 99); + equal (one, "cd", 9); + + (void) strcpy (one, "ab"); + (void) strncat (one, "cdef", 2); + equal (one, "abcd", 10); /* Count-limited. */ + + (void) strncat (one, "gh", 0); + equal (one, "abcd", 11); /* Zero count. */ + + (void) strncat (one, "gh", 2); + equal (one, "abcdgh", 12); /* Count and length equal. */ + + (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */ + equal (one, "abcdghij", 13); +} + +static void +test_strlcat (void) +{ +#ifdef __TEST_BSD_FUNCS__ + /* First test it as strcat, with big counts, then test the count + mechanism. */ + it = "strlcat"; + (void) strcpy (one, "ijk"); + check (strlcat (one, "lmn", 99) == 6, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strlcat (one, "yz", 99); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strlcat (one, two, 99); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strlcat (one, "", 99); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strlcat (one, "", 99); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strlcat (one, "cd", 99); + equal (one, "cd", 9); + + (void) strcpy (one, "ab"); + (void) strlcat (one, "cdef", 2); + equal (one, "ab", 10); /* Count-limited. */ + + (void) strlcat (one, "gh", 0); + equal (one, "ab", 11); /* Zero count. */ + + (void) strlcat (one, "gh", 4); + equal (one, "abg", 12); /* Count and length equal. */ + + (void) strlcat (one, "ij", (size_t)-1); /* set sign bit in count */ + equal (one, "abgij", 13); +#endif +} + +static void +test_strncmp (void) +{ + /* First test as strcmp with big counts, then test count code. */ + it = "strncmp"; + check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */ + check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */ + check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */ + check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */ + check (strncmp ("abcd", "abc", 99) > 0, 5); + check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */ + check (strncmp ("abce", "abcd", 99) > 0, 7); + check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */ + check (strncmp ("a\203", "a\003", 2) > 0, 9); + check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */ + check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */ + check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */ + check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */ + check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */ + check (strncmp ("abc", "abc", (size_t)-2) == 0, 15); + check (strncmp ("aa", "ab", (size_t)-1) < 0, 16); +} + +static void +test_strncpy (void) +{ + /* Testing is a bit different because of odd semantics. */ + it = "strncpy"; + check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */ + equal (one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 2); + equal (one, "xycdefgh", 3); /* Copy cut by count. */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */ + equal (one, "xyzdefgh", 4); + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */ + equal (one, "xyz", 5); + equal (one+4, "efgh", 6); /* Wrote too much? */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 5); /* Copy includes padding. */ + equal (one, "xyz", 7); + equal (one+4, "", 8); + equal (one+5, "fgh", 9); + + (void) strcpy (one, "abc"); + (void) strncpy (one, "xyz", 0); /* Zero-length copy. */ + equal (one, "abc", 10); + + (void) strncpy (one, "", 2); /* Zero-length source. */ + equal (one, "", 11); + equal (one+1, "", 12); + equal (one+2, "c", 13); + + (void) strcpy (one, "hi there"); + (void) strncpy (two, one, 9); + equal (two, "hi there", 14); /* Just paranoia. */ + equal (one, "hi there", 15); /* Stomped on source? */ +} + +static void +test_strlcpy (void) +{ +#ifdef __TEST_BSD_FUNCS__ + /* Testing is a bit different because of odd semantics. */ + it = "strlcpy"; + check (strlcpy (one, "abc", sizeof(one)) == 3, 1); /* Returned value. */ + equal (one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 2); + equal (one, "x\0cdefgh", 3); /* Copy cut by count. */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 3); /* Copy cut just before NUL. */ + equal (one, "xy\0defgh", 4); + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 4); /* Copy just includes NUL. */ + equal (one, "xyz", 5); + equal (one+4, "efgh", 6); /* Wrote too much? */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 5); /* Copy includes padding. */ + equal (one, "xyz", 7); + equal (one+3, "", 8); + equal (one+4, "efgh", 9); + + (void) strcpy (one, "abc"); + (void) strlcpy (one, "xyz", 0); /* Zero-length copy. */ + equal (one, "abc", 10); + + (void) strlcpy (one, "", 2); /* Zero-length source. */ + equal (one, "", 11); + equal (one+1, "bc", 12); + equal (one+2, "c", 13); + + (void) strcpy (one, "hi there"); + (void) strlcpy (two, one, 9); + equal (two, "hi there", 14); /* Just paranoia. */ + equal (one, "hi there", 15); /* Stomped on source? */ +#endif +} + +static void +test_strlen (void) +{ + it = "strlen"; + check (strlen ("") == 0, 1); /* Empty. */ + check (strlen ("a") == 1, 2); /* Single char. */ + check (strlen ("abcd") == 4, 3); /* Multiple chars. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strlen (p) == 2, 4+i); + } + } +} + +static void +test_strnlen (void) +{ + it = "strnlen"; + check (strnlen ("", 10) == 0, 1); /* Empty. */ + check (strnlen ("a", 10) == 1, 2); /* Single char. */ + check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */ + check (strnlen ("foo", (size_t)-1) == 3, 4); /* limits of n. */ + + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strnlen (p, 100) == 2, 5+i); + } + } +} + +static void +test_strchr (void) +{ + it = "strchr"; + check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (strchr (one, 'c') == one+2, 2); /* Basic test. */ + check (strchr (one, 'd') == one+3, 3); /* End of string. */ + check (strchr (one, 'a') == one, 4); /* Beginning. */ + check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strchr (one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy (one, ""); + check (strchr (one, 'b') == NULL, 7); /* Empty string. */ + check (strchr (one, '\0') == one, 8); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strchr (p, '/') == NULL, 9+i); + } + } +} + +static void +test_strchrnul (void) +{ + const char *os; + it = "strchrnul"; + cp = strchrnul ((os = "abcd"), 'z'); + check (*cp == '\0', 1); /* Not found. */ + check (cp == os + 4, 2); + (void) strcpy (one, "abcd"); + check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */ + check (strchrnul (one, 'd') == one+3, 4); /* End of string. */ + check (strchrnul (one, 'a') == one, 5); /* Beginning. */ + check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */ + (void) strcpy (one, ""); + check (strchrnul (one, 'b') == one, 8); /* Empty string. */ + check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + cp = strchrnul (p, '/'); + check (*cp == '\0', 9+2*i); + check (cp == p+2, 10+2*i); + } + } +} + +static void +test_rawmemchr (void) +{ + it = "rawmemchr"; + (void) strcpy (one, "abcd"); + check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */ + check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */ + check (rawmemchr (one, 'a') == one, 3); /* Beginning. */ + check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */ + (void) strcpy (one, ""); + check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (rawmemchr (p, 'R') == p+8, 6+i); + } + } +} + +static void +test_index (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "index"; + check (index ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (index (one, 'c') == one+2, 2); /* Basic test. */ + check (index (one, 'd') == one+3, 3); /* End of string. */ + check (index (one, 'a') == one, 4); /* Beginning. */ + check (index (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (index (one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy (one, ""); + check (index (one, 'b') == NULL, 7); /* Empty string. */ + check (index (one, '\0') == one, 8); /* NUL in empty string. */ +#endif +} + +static void +test_strrchr (void) +{ + it = "strrchr"; + check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (strrchr (one, 'c') == one+2, 2); /* Basic test. */ + check (strrchr (one, 'd') == one+3, 3); /* End of string. */ + check (strrchr (one, 'a') == one, 4); /* Beginning. */ + check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strrchr (one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + check (strrchr (one, 'b') == NULL, 7); /* Empty string. */ + check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strrchr (p, '/') == NULL, 9+i); + } + } +} + +static void +test_memrchr (void) +{ + size_t l; + it = "memrchr"; + check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + l = strlen (one) + 1; + check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */ + check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */ + check (memrchr (one, 'a', l) == one, 4); /* Beginning. */ + check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + l = strlen (one) + 1; + check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + l = strlen (one) + 1; + check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */ + check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */ + + /* now test all possible alignment and length combinations to catch + bugs due to unrolled loops (assuming unrolling is limited to no + more than 128 byte chunks: */ + { + char buf[128 + sizeof(long)]; + long align, len, i, pos; + + for (align = 0; align < (long) sizeof(long); ++align) { + for (len = 0; len < (long) (sizeof(buf) - align); ++len) { + for (i = 0; i < len; ++i) + buf[align + i] = 'x'; /* don't depend on memset... */ + + for (pos = len - 1; pos >= 0; --pos) { +#if 0 + printf("align %d, len %d, pos %d\n", align, len, pos); +#endif + check(memrchr(buf + align, 'x', len) == buf + align + pos, 9); + check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL, + 10); + buf[align + pos] = '-'; + } + } + } + } +} + +static void +test_rindex (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "rindex"; + check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (rindex (one, 'c') == one+2, 2); /* Basic test. */ + check (rindex (one, 'd') == one+3, 3); /* End of string. */ + check (rindex (one, 'a') == one, 4); /* Beginning. */ + check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (rindex (one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + check (rindex (one, 'b') == NULL, 7); /* Empty string. */ + check (rindex (one, '\0') == one, 8); /* NUL in empty string. */ +#endif +} + +static void +test_strpbrk (void) +{ + it = "strpbrk"; + check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(strpbrk(one, "c") == one+2, 2); /* Basic test. */ + check(strpbrk(one, "d") == one+3, 3); /* End of string. */ + check(strpbrk(one, "a") == one, 4); /* Beginning. */ + check(strpbrk(one, "") == NULL, 5); /* Empty search list. */ + check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */ + (void) strcpy(one, "abcabdea"); + check(strpbrk(one, "b") == one+1, 7); /* Finding first. */ + check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */ + check(strpbrk(one, "db") == one+1, 9); /* Another variant. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */ + check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */ + (void) strcpy(one, "abcabdea"); + check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */ + check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */ + check(strpbrk(one, "db") == one+1, 16); /* Another variant. */ + check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */ +} + +static void +test_strstr (void) +{ + it = "strstr"; + check(strstr("abcd", "z") == NULL, 1); /* Not found. */ + check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */ + (void) strcpy(one, "abcd"); + check(strstr(one, "c") == one+2, 3); /* Basic test. */ + check(strstr(one, "bc") == one+1, 4); /* Multichar. */ + check(strstr(one, "d") == one+3, 5); /* End of string. */ + check(strstr(one, "cd") == one+2, 6); /* Tail of string. */ + check(strstr(one, "abc") == one, 7); /* Beginning. */ + check(strstr(one, "abcd") == one, 8); /* Exact match. */ + check(strstr(one, "abcde") == NULL, 9); /* Too long. */ + check(strstr(one, "de") == NULL, 10); /* Past end. */ + check(strstr(one, "") == one, 11); /* Finding empty. */ + (void) strcpy(one, "ababa"); + check(strstr(one, "ba") == one+1, 12); /* Finding first. */ + (void) strcpy(one, ""); + check(strstr(one, "b") == NULL, 13); /* Empty string. */ + check(strstr(one, "") == one, 14); /* Empty in empty string. */ + (void) strcpy(one, "bcbca"); + check(strstr(one, "bca") == one+2, 15); /* False start. */ + (void) strcpy(one, "bbbcabbca"); + check(strstr(one, "bbca") == one+1, 16); /* With overlap. */ +} + +static void +test_strspn (void) +{ + it = "strspn"; + check(strspn("abcba", "abc") == 5, 1); /* Whole string. */ + check(strspn("abcba", "ab") == 2, 2); /* Partial. */ + check(strspn("abc", "qx") == 0, 3); /* None. */ + check(strspn("", "ab") == 0, 4); /* Null string. */ + check(strspn("abc", "") == 0, 5); /* Null search list. */ +} + +static void +test_strcspn (void) +{ + it = "strcspn"; + check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */ + check(strcspn("abcba", "cx") == 2, 2); /* Partial. */ + check(strcspn("abc", "abc") == 0, 3); /* None. */ + check(strcspn("", "ab") == 0, 4); /* Null string. */ + check(strcspn("abc", "") == 3, 5); /* Null search list. */ +} + +static void +test_strtok (void) +{ + it = "strtok"; + (void) strcpy(one, "first, second, third"); + equal(strtok(one, ", "), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strtok((char *)NULL, ", "), "second", 3); + equal(strtok((char *)NULL, ", "), "third", 4); + check(strtok((char *)NULL, ", ") == NULL, 5); + (void) strcpy(one, ", first, "); + equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */ + check(strtok((char *)NULL, ", ") == NULL, 7); + (void) strcpy(one, "1a, 1b; 2a, 2b"); + equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */ + equal(strtok((char *)NULL, "; "), "1b", 9); + equal(strtok((char *)NULL, ", "), "2a", 10); + (void) strcpy(two, "x-y"); + equal(strtok(two, "-"), "x", 11); /* New string before done. */ + equal(strtok((char *)NULL, "-"), "y", 12); + check(strtok((char *)NULL, "-") == NULL, 13); + (void) strcpy(one, "a,b, c,, ,d"); + equal(strtok(one, ", "), "a", 14); /* Different separators. */ + equal(strtok((char *)NULL, ", "), "b", 15); + equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */ + equal(strtok((char *)NULL, " ,"), "d", 17); + check(strtok((char *)NULL, ", ") == NULL, 18); + check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */ + (void) strcpy(one, ", "); + check(strtok(one, ", ") == NULL, 20); /* No tokens. */ + (void) strcpy(one, ""); + check(strtok(one, ", ") == NULL, 21); /* Empty string. */ + (void) strcpy(one, "abc"); + equal(strtok(one, ", "), "abc", 22); /* No delimiters. */ + check(strtok((char *)NULL, ", ") == NULL, 23); + (void) strcpy(one, "abc"); + equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */ + check(strtok((char *)NULL, "") == NULL, 25); + (void) strcpy(one, "abcdefgh"); + (void) strcpy(one, "a,b,c"); + equal(strtok(one, ","), "a", 26); /* Basics again... */ + equal(strtok((char *)NULL, ","), "b", 27); + equal(strtok((char *)NULL, ","), "c", 28); + check(strtok((char *)NULL, ",") == NULL, 29); + equal(one+6, "gh", 30); /* Stomped past end? */ + equal(one, "a", 31); /* Stomped old tokens? */ + equal(one+2, "b", 32); + equal(one+4, "c", 33); +} + +static void +test_strtok_r (void) +{ + it = "strtok_r"; + (void) strcpy(one, "first, second, third"); + cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */ + equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strtok_r((char *)NULL, ", ", &cp), "second", 3); + equal(strtok_r((char *)NULL, ", ", &cp), "third", 4); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5); + (void) strcpy(one, ", first, "); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7); + (void) strcpy(one, "1a, 1b; 2a, 2b"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */ + equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9); + equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10); + (void) strcpy(two, "x-y"); + cp = NULL; + equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */ + equal(strtok_r((char *)NULL, "-", &cp), "y", 12); + check(strtok_r((char *)NULL, "-", &cp) == NULL, 13); + (void) strcpy(one, "a,b, c,, ,d"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */ + equal(strtok_r((char *)NULL, ", ", &cp), "b", 15); + equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */ + equal(strtok_r((char *)NULL, " ,", &cp), "d", 17); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */ + (void) strcpy(one, ", "); + cp = NULL; + check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */ + (void) strcpy(one, ""); + cp = NULL; + check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */ + (void) strcpy(one, "abc"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24); + (void) strcpy(one, "abc"); + cp = NULL; + equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */ + check(strtok_r((char *)NULL, "", &cp) == NULL, 26); + (void) strcpy(one, "abcdefgh"); + (void) strcpy(one, "a,b,c"); + cp = NULL; + equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */ + equal(strtok_r((char *)NULL, ",", &cp), "b", 28); + equal(strtok_r((char *)NULL, ",", &cp), "c", 29); + check(strtok_r((char *)NULL, ",", &cp) == NULL, 30); + equal(one+6, "gh", 31); /* Stomped past end? */ + equal(one, "a", 32); /* Stomped old tokens? */ + equal(one+2, "b", 33); + equal(one+4, "c", 34); +} + +static void +test_strsep (void) +{ + char *ptr; + it = "strsep"; + cp = strcpy(one, "first, second, third"); + equal(strsep(&cp, ", "), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strsep(&cp, ", "), "", 3); + equal(strsep(&cp, ", "), "second", 4); + equal(strsep(&cp, ", "), "", 5); + equal(strsep(&cp, ", "), "third", 6); + check(strsep(&cp, ", ") == NULL, 7); + cp = strcpy(one, ", first, "); + equal(strsep(&cp, ", "), "", 8); + equal(strsep(&cp, ", "), "", 9); + equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */ + equal(strsep(&cp, ", "), "", 11); + equal(strsep(&cp, ", "), "", 12); + check(strsep(&cp, ", ") == NULL, 13); + cp = strcpy(one, "1a, 1b; 2a, 2b"); + equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */ + equal(strsep(&cp, ", "), "", 15); + equal(strsep(&cp, "; "), "1b", 16); + equal(strsep(&cp, ", "), "", 17); + equal(strsep(&cp, ", "), "2a", 18); + cp = strcpy(two, "x-y"); + equal(strsep(&cp, "-"), "x", 19); /* New string before done. */ + equal(strsep(&cp, "-"), "y", 20); + check(strsep(&cp, "-") == NULL, 21); + cp = strcpy(one, "a,b, c,, ,d "); + equal(strsep(&cp, ", "), "a", 22); /* Different separators. */ + equal(strsep(&cp, ", "), "b", 23); + equal(strsep(&cp, " ,"), "", 24); + equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */ + equal(strsep(&cp, " ,"), "", 26); + equal(strsep(&cp, " ,"), "", 27); + equal(strsep(&cp, " ,"), "", 28); + equal(strsep(&cp, " ,"), "d", 29); + equal(strsep(&cp, " ,"), "", 30); + check(strsep(&cp, ", ") == NULL, 31); + check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */ + cp = strcpy(one, ", "); + equal(strsep(&cp, ", "), "", 33); + equal(strsep(&cp, ", "), "", 34); + equal(strsep(&cp, ", "), "", 35); + check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */ + cp = strcpy(one, ""); + equal(strsep(&cp, ", "), "", 37); + check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */ + cp = strcpy(one, "abc"); + equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */ + check(strsep(&cp, ", ") == NULL, 40); + cp = strcpy(one, "abc"); + equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */ + check(strsep(&cp, "") == NULL, 42); + (void) strcpy(one, "abcdefgh"); + cp = strcpy(one, "a,b,c"); + equal(strsep(&cp, ","), "a", 43); /* Basics again... */ + equal(strsep(&cp, ","), "b", 44); + equal(strsep(&cp, ","), "c", 45); + check(strsep(&cp, ",") == NULL, 46); + equal(one+6, "gh", 47); /* Stomped past end? */ + equal(one, "a", 48); /* Stomped old tokens? */ + equal(one+2, "b", 49); + equal(one+4, "c", 50); + + { + char text[] = "This,is,a,test"; + char *list = strdupa (text); + equal (strsep (&list, ","), "This", 51); + equal (strsep (&list, ","), "is", 52); + equal (strsep (&list, ","), "a", 53); + equal (strsep (&list, ","), "test", 54); + check (strsep (&list, ",") == NULL, 55); + } + + cp = strcpy(one, "a,b, c,, ,d,"); + equal(strsep(&cp, ","), "a", 56); /* Different separators. */ + equal(strsep(&cp, ","), "b", 57); + equal(strsep(&cp, ","), " c", 58); /* Permute list too. */ + equal(strsep(&cp, ","), "", 59); + equal(strsep(&cp, ","), " ", 60); + equal(strsep(&cp, ","), "d", 61); + equal(strsep(&cp, ","), "", 62); + check(strsep(&cp, ",") == NULL, 63); + check(strsep(&cp, ",") == NULL, 64); /* Persistence. */ + + cp = strcpy(one, "a,b, c,, ,d,"); + equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */ + equal(strsep(&cp, "x,y"), "b", 66); + equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */ + equal(strsep(&cp, "xy,"), "", 68); + equal(strsep(&cp, "x,y"), " ", 69); + equal(strsep(&cp, ",xy"), "d", 70); + equal(strsep(&cp, "xy,"), "", 71); + check(strsep(&cp, "x,y") == NULL, 72); + check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */ + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */ + ptr = strsep(&cp, ":"); + equal(ptr, "", 75); + check(ptr == one + 3, 76); + check(cp == NULL, 77); + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */ + ptr = strsep(&cp, ":."); + equal(ptr, "", 79); + check(ptr == one + 3, 80); + + cp = strcpy(one, "ABC"); /* No token in string. */ + equal(strsep(&cp, ","), "ABC", 81); + check(cp == NULL, 82); + + *one = '\0'; /* Empty string. */ + cp = one; + ptr = strsep(&cp, ","); + equal(ptr, "", 83); + check(ptr == one, 84); + check(cp == NULL, 85); + + *one = '\0'; /* Empty string and no token. */ + cp = one; + ptr = strsep(&cp, ""); + equal(ptr, "", 86); + check(ptr == one , 87); + check(cp == NULL, 88); +} + +static void +test_memcmp (void) +{ + int i, cnt = 1; + char one[21], two[21]; + + it = "memcmp"; + check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */ + check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */ + check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */ + check(memcmp("abcf", "abcd", 4) > 0, cnt++); + check(memcmp("alph", "cold", 4) < 0, cnt++); + check(memcmp("a\203", "a\003", 2) > 0, cnt++); + check(memcmp("a\003", "a\203", 2) < 0, cnt++); + check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++); + check(memcmp("abc\203", "abc\003", 4) > 0, cnt++); + check(memcmp("abc\003", "abc\203", 4) < 0, cnt++); + check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */ + check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */ + /* Comparisons with shifting 4-byte boundaries. */ + for (i=0; i<4; i++) + { + char *a = one + i, *b = two + i; + strncpy( a, "--------11112222", 16); + strncpy( b, "--------33334444", 16); + check( memcmp(b, a, 16) > 0, cnt++); + check( memcmp(a, b, 16) < 0, cnt++); + } +} + +static void +test_memchr (void) +{ + it = "memchr"; + check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */ + check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */ + check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */ + check(memchr(one, 'a', 4) == one, 4); /* Beginning. */ + check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */ + check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */ + check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */ + (void) strcpy(one, "a\203b"); + check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */ + + /* now test all possible alignment and length combinations to catch + bugs due to unrolled loops (assuming unrolling is limited to no + more than 128 byte chunks: */ + { + char buf[128 + sizeof(long)]; + long align, len, i, pos; + + for (align = 0; align < (long) sizeof(long); ++align) { + for (len = 0; len < (long) (sizeof(buf) - align); ++len) { + for (i = 0; i < len; ++i) { + buf[align + i] = 'x'; /* don't depend on memset... */ + } + for (pos = 0; pos < len; ++pos) { +#if 0 + printf("align %d, len %d, pos %d\n", align, len, pos); +#endif + check(memchr(buf + align, 'x', len) == buf + align + pos, 10); + check(memchr(buf + align, 'x', pos) == NULL, 11); + buf[align + pos] = '-'; + } + } + } + } +} + +static void +test_memcpy (void) +{ + int i; + it = "memcpy"; + check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memcpy(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memcpy(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + for (i = 0; i < 16; i++) + { + const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + strcpy (one, x); + check (memcpy (one + i, "hi there", 9) == one + i, + 7 + (i * 6)); /* Unaligned destination. */ + check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */ + equal (one + i, "hi there", 9 + (i * 6)); + check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */ + check (memcpy (two, one + i, 9) == two, + 11 + (i * 6)); /* Unaligned source. */ + equal (two, "hi there", 12 + (i * 6)); + } +} + +static void +test_mempcpy (void) +{ + int i; + it = "mempcpy"; + check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) mempcpy(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) mempcpy(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) mempcpy(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + for (i = 0; i < 16; i++) + { + const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + strcpy (one, x); + check (mempcpy (one + i, "hi there", 9) == one + i + 9, + 7 + (i * 6)); /* Unaligned destination. */ + check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */ + equal (one + i, "hi there", 9 + (i * 6)); + check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */ + check (mempcpy (two, one + i, 9) == two + 9, + 11 + (i * 6)); /* Unaligned source. */ + equal (two, "hi there", 12 + (i * 6)); + } +} + +static void +test_memmove (void) +{ + it = "memmove"; + check(memmove(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memmove(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memmove(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, one, 9); + equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, one+2, 7); + equal(one, "acdefgh", 8); /* Overlap, left-to-right. */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one, one, 9); + equal(one, "abcdefgh", 9); /* 100% overlap. */ +} + +static void +test_memccpy (void) +{ + /* First test like memcpy, then the search part The SVID, the only + place where memccpy is mentioned, says overlap might fail, so we + don't try it. Besides, it's hard to see the rationale for a + non-left-to-right memccpy. */ + it = "memccpy"; + check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memccpy(one+1, "xyz", 'q', 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memccpy(one, "xyz", 'q', 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memccpy(two, one, 'q', 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) strcpy(two, "horsefeathers"); + check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */ + equal(one, "abcdefgh", 8); /* Source intact? */ + equal(two, "abcdefeathers", 9); /* Copy correct? */ + + (void) strcpy(one, "abcd"); + (void) strcpy(two, "bumblebee"); + check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */ + equal(two, "aumblebee", 11); + check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */ + equal(two, "abcdlebee", 13); + (void) strcpy(one, "xyz"); + check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */ + equal(two, "xbcdlebee", 15); +} + +static void +test_memset (void) +{ + int i; + + it = "memset"; + (void) strcpy(one, "abcdefgh"); + check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */ + equal(one, "axxxefgh", 2); /* Basic test. */ + + (void) memset(one+2, 'y', 0); + equal(one, "axxxefgh", 3); /* Zero-length set. */ + + (void) memset(one+5, 0, 1); + equal(one, "axxxe", 4); /* Zero fill. */ + equal(one+6, "gh", 5); /* And the leftover. */ + + (void) memset(one+2, 010045, 1); + equal(one, "ax\045xe", 6); /* Unsigned char convert. */ + + /* Non-8bit fill character. */ + memset (one, 0x101, sizeof (one)); + for (i = 0; i < (int) sizeof (one); ++i) + check (one[i] == '\01', 7); + + /* Test for more complex versions of memset, for all alignments and + lengths up to 256. This test takes a little while, perhaps it should + be made weaker? */ + { + char data[512]; + int j; + int k; + int c; + + for (i = 0; i < 512; i++) + data[i] = 'x'; + for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and + memset(,'y',) */ + for (j = 0; j < 256; j++) + for (i = 0; i < 256; i++) + { + memset (data + i, c, j); + for (k = 0; k < i; k++) + if (data[k] != 'x') + goto fail; + for (k = i; k < i+j; k++) + { + if (data[k] != c) + goto fail; + data[k] = 'x'; + } + for (k = i+j; k < 512; k++) + if (data[k] != 'x') + goto fail; + continue; + + fail: + check (0, 8 + i + j * 256 + (c != 0) * 256 * 256); + } + } +} + +static void +test_bcopy (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + /* Much like memcpy. Berklix manual is silent about overlap, so + don't test it. */ + it = "bcopy"; + (void) bcopy("abc", one, 4); + equal(one, "abc", 1); /* Simple copy. */ + + (void) strcpy(one, "abcdefgh"); + (void) bcopy("xyz", one+1, 2); + equal(one, "axydefgh", 2); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) bcopy("xyz", one, 0); + equal(one, "abc", 3); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) bcopy(one, two, 9); + equal(two, "hi there", 4); /* Just paranoia. */ + equal(one, "hi there", 5); /* Stomped on source? */ +#endif +} + +static void +test_bzero (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "bzero"; + (void) strcpy(one, "abcdef"); + bzero(one+2, 2); + equal(one, "ab", 1); /* Basic test. */ + equal(one+3, "", 2); + equal(one+4, "ef", 3); + + (void) strcpy(one, "abcdef"); + bzero(one+2, 0); + equal(one, "abcdef", 4); /* Zero-length copy. */ +#endif +} + +static void +test_strndup (void) +{ + char *p, *q; + it = "strndup"; + p = strndup("abcdef", 12); + check(p != NULL, 1); + if (p != NULL) + { + equal(p, "abcdef", 2); + q = strndup(p + 1, 2); + check(q != NULL, 3); + if (q != NULL) + equal(q, "bc", 4); + free (q); + } + free (p); + p = strndup("abc def", 3); + check(p != NULL, 5); + if (p != NULL) + equal(p, "abc", 6); + free (p); +} + +static void +test_bcmp (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "bcmp"; + check(bcmp("a", "a", 1) == 0, 1); /* Identity. */ + check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ + check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */ + check(bcmp("abce", "abcd", 4) != 0, 4); + check(bcmp("alph", "beta", 4) != 0, 5); + check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */ + check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */ +#endif +} + +static void +test_strerror (void) +{ + it = "strerror"; + check(strerror(EDOM) != 0, 1); + check(strerror(ERANGE) != 0, 2); + check(strerror(ENOENT) != 0, 3); +} + +static void +test_strcasecmp (void) +{ + it = "strcasecmp"; + /* Note that the locale is "C". */ + check(strcasecmp("a", "a") == 0, 1); + check(strcasecmp("a", "A") == 0, 2); + check(strcasecmp("A", "a") == 0, 3); + check(strcasecmp("a", "b") < 0, 4); + check(strcasecmp("c", "b") > 0, 5); + check(strcasecmp("abc", "AbC") == 0, 6); + check(strcasecmp("0123456789", "0123456789") == 0, 7); + check(strcasecmp("", "0123456789") < 0, 8); + check(strcasecmp("AbC", "") > 0, 9); + check(strcasecmp("AbC", "A") > 0, 10); + check(strcasecmp("AbC", "Ab") > 0, 11); + check(strcasecmp("AbC", "ab") > 0, 12); +} + +static void +test_strncasecmp (void) +{ + it = "strncasecmp"; + /* Note that the locale is "C". */ + check(strncasecmp("a", "a", 5) == 0, 1); + check(strncasecmp("a", "A", 5) == 0, 2); + check(strncasecmp("A", "a", 5) == 0, 3); + check(strncasecmp("a", "b", 5) < 0, 4); + check(strncasecmp("c", "b", 5) > 0, 5); + check(strncasecmp("abc", "AbC", 5) == 0, 6); + check(strncasecmp("0123456789", "0123456789", 10) == 0, 7); + check(strncasecmp("", "0123456789", 10) < 0, 8); + check(strncasecmp("AbC", "", 5) > 0, 9); + check(strncasecmp("AbC", "A", 5) > 0, 10); + check(strncasecmp("AbC", "Ab", 5) > 0, 11); + check(strncasecmp("AbC", "ab", 5) > 0, 12); + check(strncasecmp("0123456789", "AbC", 0) == 0, 13); + check(strncasecmp("AbC", "abc", 1) == 0, 14); + check(strncasecmp("AbC", "abc", 2) == 0, 15); + check(strncasecmp("AbC", "abc", 3) == 0, 16); + check(strncasecmp("AbC", "abcd", 3) == 0, 17); + check(strncasecmp("AbC", "abcd", 4) < 0, 18); + check(strncasecmp("ADC", "abcd", 1) == 0, 19); + check(strncasecmp("ADC", "abcd", 2) > 0, 20); +} + +int +main (void) +{ + int status; + + /* Test strcmp first because we use it to test other things. */ + test_strcmp (); + + /* Test strcpy next because we need it to set up other tests. */ + test_strcpy (); + + /* A closely related function is stpcpy. */ + test_stpcpy (); + + /* stpncpy. */ + test_stpncpy (); + + /* strcat. */ + test_strcat (); + + /* strncat. */ + test_strncat (); + + /* strlcat. */ + test_strlcat (); + + /* strncmp. */ + test_strncmp (); + + /* strncpy. */ + test_strncpy (); + + /* strlcpy. */ + test_strlcpy (); + + /* strlen. */ + test_strlen (); + + /* strnlen. */ + test_strnlen (); + + /* strchr. */ + test_strchr (); + + /* strchrnul. */ + test_strchrnul (); + + /* rawmemchr. */ + test_rawmemchr (); + + /* index - just like strchr. */ + test_index (); + + /* strrchr. */ + test_strrchr (); + + /* memrchr. */ + test_memrchr (); + + /* rindex - just like strrchr. */ + test_rindex (); + + /* strpbrk - somewhat like strchr. */ + test_strpbrk (); + + /* strstr - somewhat like strchr. */ + test_strstr (); + + /* strspn. */ + test_strspn (); + + /* strcspn. */ + test_strcspn (); + + /* strtok - the hard one. */ + test_strtok (); + + /* strtok_r. */ + test_strtok_r (); + + /* strsep. */ + test_strsep (); + + /* memcmp. */ + test_memcmp (); + + /* memchr. */ + test_memchr (); + + /* memcpy - need not work for overlap. */ + test_memcpy (); + + /* memmove - must work on overlap. */ + test_memmove (); + + /* mempcpy */ + test_mempcpy (); + + /* memccpy. */ + test_memccpy (); + + /* memset. */ + test_memset (); + + /* bcopy. */ + test_bcopy (); + + /* bzero. */ + test_bzero (); + + /* bcmp - somewhat like memcmp. */ + test_bcmp (); + + /* strndup. */ + test_strndup (); + + /* strerror - VERY system-dependent. */ + test_strerror (); + + /* strcasecmp. Without locale dependencies. */ + test_strcasecmp (); + + /* strncasecmp. Without locale dependencies. */ + test_strncasecmp (); + + if (errors == 0) + { + status = EXIT_SUCCESS; + puts("No errors."); + } + else + { + status = EXIT_FAILURE; + printf("%Zd errors.\n", errors); + } + + return status; +} diff --git a/test/string/tst-bswap.c b/test/string/tst-bswap.c new file mode 100644 index 0000000..b2b4ef0 --- /dev/null +++ b/test/string/tst-bswap.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +extern unsigned long long int wash (unsigned long long int a); + +int +main (void) +{ + int result = 0; + + /* Test the functions with constant arguments. */ + if (bswap_16 (0x1234) != 0x3412) + { + puts ("bswap_16 (constant) flunked"); + result = 1; + } + if (bswap_32 (0x12345678) != 0x78563412) + { + puts ("bswap_32 (constant) flunked"); + result = 1; + } + if (bswap_64 (0x1234567890abcdefULL) != 0xefcdab9078563412ULL) + { + puts ("bswap_64 (constant) flunked"); + result = 1; + } + + /* Test the functions with non-constant arguments. */ + if (bswap_16 (wash (0x1234)) != 0x3412) + { + puts ("bswap_16 (non-constant) flunked"); + result = 1; + } + if (bswap_32 (wash (0x12345678)) != 0x78563412) + { + puts ("bswap_32 (non-constant) flunked"); + result = 1; + } + if (bswap_64 (wash (0x1234567890abcdefULL)) != 0xefcdab9078563412ULL) + { + puts ("bswap_64 (non-constant) flunked"); + result = 1; + } + + return result; +} + + +unsigned long long int +wash (unsigned long long int a) +{ + /* Do nothing. This function simply exists to avoid that the compiler + regards the argument to the bswap_*() functions as constant. */ + return a + 0; +} diff --git a/test/string/tst-inlcall.c b/test/string/tst-inlcall.c new file mode 100644 index 0000000..2a4124e --- /dev/null +++ b/test/string/tst-inlcall.c @@ -0,0 +1,83 @@ +/* Tester for calling inline string functions. + Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +/* Make sure we test the optimized inline functions. */ +#define __USE_STRING_INLINES 1 + +#include +#include +#include +#include +#include +#include + + +int +main (void) +{ + int status; + int errors = 0; + char buf1[1000]; + char *cp; + char ch; + + cp = strcpy (buf1, "hello world"); + if (strcmp ("hello world", cp++) != 0) + { + puts ("strcmp test 1 failed"); + ++errors; + } + + cp = buf1; + if (strcmp (cp++, "hello world") != 0) + { + puts ("strcmp test 2 failed"); + ++errors; + } + + ch = 'h'; + if (strchr ("hello world", ch++) == NULL) + { + puts ("strchr test 1 failed"); + ++errors; + } + + const char * const hw = "hello world"; + if (strpbrk (hw, "o") - hw != 4) + { + puts ("strpbrk test 1 failed"); + ++errors; + } + + if (errors == 0) + { + status = EXIT_SUCCESS; + puts ("No errors."); + } + else + { + status = EXIT_FAILURE; + printf ("%d errors.\n", errors); + } + return status; +} diff --git a/test/string/tst-strlen.c b/test/string/tst-strlen.c new file mode 100644 index 0000000..a1e1159 --- /dev/null +++ b/test/string/tst-strlen.c @@ -0,0 +1,45 @@ +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#undef __USE_STRING_INLINES + +#include +#include + +int +main(int argc, char *argv[]) +{ + static const size_t lens[] = { 0, 1, 0, 2, 0, 1, 0, 3, + 0, 1, 0, 2, 0, 1, 0, 4 }; + char basebuf[24 + 32]; + size_t base; + + for (base = 0; base < 32; ++base) + { + char *buf = basebuf + base; + size_t words; + + for (words = 0; words < 4; ++words) + { + size_t last; + memset (buf, 'a', words * 4); + + for (last = 0; last < 16; ++last) + { + buf[words * 4 + 0] = (last & 1) != 0 ? 'b' : '\0'; + buf[words * 4 + 1] = (last & 2) != 0 ? 'c' : '\0'; + buf[words * 4 + 2] = (last & 4) != 0 ? 'd' : '\0'; + buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0'; + buf[words * 4 + 4] = '\0'; + + if (strlen (buf) != words * 4 + lens[last] + || strnlen (buf, -1) != words * 4 + lens[last]) + { + printf ("failed for base=%Zu, words=%Zu, and last=%Zu\n", + base, words, last); + return 1; + } + } + } + } + return 0; +} diff --git a/test/string/tst-strtok.c b/test/string/tst-strtok.c new file mode 100644 index 0000000..7e34aee --- /dev/null +++ b/test/string/tst-strtok.c @@ -0,0 +1,23 @@ +/* Testcase for strtok reported by Andrew Church . */ +#include +#include + +int +main (void) +{ + char buf[1] = { 0 }; + int result = 0; + + if (strtok (buf, " ") != NULL) + { + puts ("first strtok call did not return NULL"); + result = 1; + } + else if (strtok (NULL, " ") != NULL) + { + puts ("second strtok call did not return NULL"); + result = 1; + } + + return result; +} diff --git a/test/string/tst-strxfrm.c b/test/string/tst-strxfrm.c new file mode 100644 index 0000000..ff1b396 --- /dev/null +++ b/test/string/tst-strxfrm.c @@ -0,0 +1,80 @@ +/* Based on a test case by Paul Eggert. */ +#include +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include +#include +#include + + +char const string[] = ""; + + +static int +test (const char *locale) +{ + size_t bufsize; + size_t r; + size_t l; + char *buf; + locale_t loc; + int result = 0; + + if (setlocale (LC_COLLATE, locale) == NULL) + { + printf ("cannot set locale \"%s\"\n", locale); + return 1; + } + bufsize = strxfrm (NULL, string, 0) + 1; + buf = malloc (bufsize); + if (buf == NULL) + { + printf ("cannot allocate %zd bytes\n", bufsize); + return 1; + } + r = strxfrm (buf, string, bufsize); + l = strlen (buf); + if (r != l) + { + printf ("locale \"%s\": strxfrm returned %zu, strlen returned %zu\n", + locale, r, l); + result = 1; + } + + loc = newlocale (1 << LC_ALL, locale, NULL); + + r = strxfrm_l (buf, string, bufsize, loc); + l = strlen (buf); + if (r != l) + { + printf ("locale \"%s\": strxfrm_l returned %zu, strlen returned %zu\n", + locale, r, l); + result = 1; + } + + freelocale (loc); + + free (buf); + + return result; +} + + +int +main (void) +{ + int result = 0; + + result |= test ("C"); + result |= test ("en_US.ISO-8859-1"); + result |= test ("de_DE.UTF-8"); + + return result; +} + +#else +int main(void) +{ + return 0; +} +#endif diff --git a/test/termios/Makefile b/test/termios/Makefile new file mode 100644 index 0000000..2aa6ccd --- /dev/null +++ b/test/termios/Makefile @@ -0,0 +1,4 @@ +# uClibc termios tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak diff --git a/test/termios/termios.c b/test/termios/termios.c new file mode 100644 index 0000000..5fbc344 --- /dev/null +++ b/test/termios/termios.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc,char *argv[]) +{ + struct termios t; + int ret; + + printf("TCGETS = 0x%08x\n",TCGETS); + printf("sizeof(struct termios) = %ld\n",(long)sizeof(struct termios)); + + ret = ioctl(fileno(stdout),TCGETS,&t); + + if(ret<0){ + perror("ioctl"); + }else{ + printf("ioctl returned %d\n",ret); + } + + return 0; +} diff --git a/test/test-skeleton.c b/test/test-skeleton.c new file mode 100644 index 0000000..adfc8b7 --- /dev/null +++ b/test/test-skeleton.c @@ -0,0 +1,394 @@ +/* Skeleton for test programs. + Copyright (C) 1998,2000-2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The test function is normally called `do_test' and it is called + with argc and argv as the arguments. We nevertheless provide the + possibility to overwrite this name. */ +#ifndef TEST_FUNCTION +# define TEST_FUNCTION do_test (argc, argv) +#endif + +#ifndef TEST_DATA_LIMIT +# define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with. */ +#endif + +#define OPT_DIRECT 1000 +#define OPT_TESTDIR 1001 + +static struct option options[] = +{ +#ifdef CMDLINE_OPTIONS + CMDLINE_OPTIONS +#endif + { "direct", no_argument, NULL, OPT_DIRECT }, + { "test-dir", required_argument, NULL, OPT_TESTDIR }, + { NULL, 0, NULL, 0 } +}; + +/* PID of the test itself. */ +static pid_t pid; + +/* Directory to place temporary files in. */ +static const char *test_dir; + +/* List of temporary files. */ +struct temp_name_list +{ + struct qelem q; + const char *name; +} *temp_name_list; + +/* Add temporary files in list. */ +static void +__attribute__ ((unused)) +add_temp_file (const char *name) +{ + struct temp_name_list *newp + = (struct temp_name_list *) calloc (sizeof (*newp), 1); + if (newp != NULL) + { + newp->name = name; + if (temp_name_list == NULL) + temp_name_list = (struct temp_name_list *) &newp->q; + else + insque (newp, temp_name_list); + } +} + +/* Delete all temporary files. */ +static void +delete_temp_files (void) +{ + while (temp_name_list != NULL) + { + remove (temp_name_list->name); + temp_name_list = (struct temp_name_list *) temp_name_list->q.q_forw; + } +} + +/* Create a temporary file. */ +static int +__attribute__ ((unused)) +create_temp_file (const char *base, char **filename) +{ + char *fname; + int fd; + + fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base) + + sizeof ("XXXXXX")); + if (fname == NULL) + { + puts ("out of memory"); + return -1; + } + strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX"); + + fd = mkstemp (fname); + if (fd == -1) + { + printf ("cannot open temporary file '%s': %s\n", fname, strerror(errno)); + free (fname); + return -1; + } + + add_temp_file (fname); + if (filename != NULL) + *filename = fname; + + return fd; +} + +/* Timeout handler. We kill the child and exit with an error. */ +static void +__attribute__ ((noreturn)) +timeout_handler (int sig __attribute__ ((unused))) +{ + int killed = 0; + int status; + + /* Send signal. */ + kill (pid, SIGKILL); + + /* Wait for it to terminate. */ + int i; + for (i = 0; i < 5; ++i) + { + killed = waitpid (pid, &status, WNOHANG|WUNTRACED); + if (killed != 0) + break; + + /* Delay, give the system time to process the kill. If the + nanosleep() call return prematurely, all the better. We + won't restart it since this probably means the child process + finally died. */ + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 100000000; + nanosleep (&ts, NULL); + } + if (killed != 0 && killed != pid) + { + perror ("Failed to kill test process"); + exit (1); + } + +#ifdef CLEANUP_HANDLER + CLEANUP_HANDLER; +#endif + + /* If we expected this signal: good! */ +#ifdef EXPECTED_SIGNAL + if (EXPECTED_SIGNAL == SIGALRM) + exit (0); +#endif + + if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL)) + fputs ("Timed out: killed the child process\n", stderr); + else if (WIFSTOPPED (status)) + fprintf (stderr, "Timed out: the child process was %s\n", + strsignal (WSTOPSIG (status))); + else if (WIFSIGNALED (status)) + fprintf (stderr, "Timed out: the child process got signal %s\n", + strsignal (WTERMSIG (status))); + else + fprintf (stderr, "Timed out: killed the child process but it exited %d\n", + WEXITSTATUS (status)); + + /* Exit with an error. */ + exit (1); +} + +/* We provide the entry point here. */ +int +main (int argc, char *argv[]) +{ +#ifdef __ARCH_USE_MMU__ + int direct = 0; /* Directly call the test function? */ +#else + int direct = 1; +#endif + int status; + int opt; + unsigned int timeoutfactor = 1; + pid_t termpid; + + /* Make uses of freed and uninitialized memory known. */ +#ifdef __MALLOC_STANDARD__ +#ifndef M_PERTURB +# define M_PERTURB -6 +#endif + mallopt (M_PERTURB, 42); +#endif + +#ifdef STDOUT_UNBUFFERED + setbuf (stdout, NULL); +#endif + + while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1) + switch (opt) + { + case '?': + exit (1); + case OPT_DIRECT: + direct = 1; + break; + case OPT_TESTDIR: + test_dir = optarg; + break; +#ifdef CMDLINE_PROCESS + CMDLINE_PROCESS +#endif + } + + /* If set, read the test TIMEOUTFACTOR value from the environment. + This value is used to scale the default test timeout values. */ + char *envstr_timeoutfactor = getenv ("TIMEOUTFACTOR"); + if (envstr_timeoutfactor != NULL) + { + char *envstr_conv = envstr_timeoutfactor; + unsigned long int env_fact; + + env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0); + if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor) + timeoutfactor = MAX (env_fact, 1); + } + + /* Set TMPDIR to specified test directory. */ + if (test_dir != NULL) + { + setenv ("TMPDIR", test_dir, 1); + + if (chdir (test_dir) < 0) + { + perror ("chdir"); + exit (1); + } + } + else + { + test_dir = getenv ("TMPDIR"); + if (test_dir == NULL || test_dir[0] == '\0') + test_dir = "/tmp"; + } + + /* Make sure we see all message, even those on stdout. */ + setvbuf (stdout, NULL, _IONBF, 0); + + /* make sure temporary files are deleted. */ + atexit (delete_temp_files); + + /* Correct for the possible parameters. */ + argv[optind - 1] = argv[0]; + argv += optind - 1; + argc -= optind - 1; + + /* Call the initializing function, if one is available. */ +#ifdef PREPARE + PREPARE (argc, argv); +#endif + + /* If we are not expected to fork run the function immediately. */ + if (direct) + return TEST_FUNCTION; + + /* Set up the test environment: + - prevent core dumps + - set up the timer + - fork and execute the function. */ + +#if defined __ARCH_USE_MMU__ || ! defined __UCLIBC__ + pid = fork (); + if (pid == 0) + { + /* This is the child. */ +#ifdef RLIMIT_CORE + /* Try to avoid dumping core. */ + struct rlimit core_limit; + core_limit.rlim_cur = 0; + core_limit.rlim_max = 0; + setrlimit (RLIMIT_CORE, &core_limit); +#endif + +#ifdef RLIMIT_DATA + /* Try to avoid eating all memory if a test leaks. */ + struct rlimit data_limit; + if (getrlimit (RLIMIT_DATA, &data_limit) == 0) + { + if (TEST_DATA_LIMIT == RLIM_INFINITY) + data_limit.rlim_cur = data_limit.rlim_max; + else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT) + data_limit.rlim_cur = MIN ((rlim_t) TEST_DATA_LIMIT, + data_limit.rlim_max); + if (setrlimit (RLIMIT_DATA, &data_limit) < 0) + perror ("setrlimit: RLIMIT_DATA"); + } + else + perror ("getrlimit: RLIMIT_DATA"); +#endif + + /* We put the test process in its own pgrp so that if it bogusly + generates any job control signals, they won't hit the whole build. */ + setpgid (0, 0); + + /* Execute the test function and exit with the return value. */ + exit (TEST_FUNCTION); + } + else if (pid < 0) +#endif + { + perror ("Cannot fork test program"); + exit (1); + } + + /* Set timeout. */ +#ifndef TIMEOUT + /* Default timeout is two seconds. */ +# define TIMEOUT 2 +#endif + signal (SIGALRM, timeout_handler); + alarm (TIMEOUT * timeoutfactor); + + /* Wait for the regular termination. */ + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("Waiting for test program failed: %s\n", strerror(errno)); + exit (1); + } + if (termpid != pid) + { + printf ("Oops, wrong test program terminated: expected %ld, got %ld\n", + (long int) pid, (long int) termpid); + exit (1); + } + +#ifndef EXPECTED_SIGNAL + /* We don't expect any signal. */ +# define EXPECTED_SIGNAL 0 +#endif + if (WTERMSIG (status) != EXPECTED_SIGNAL) + { + if (EXPECTED_SIGNAL != 0) + { + if (WTERMSIG (status) == 0) + fprintf (stderr, + "Expected signal '%s' from child, got none\n", + strsignal (EXPECTED_SIGNAL)); + else + fprintf (stderr, + "Incorrect signal from child: got `%s', need `%s'\n", + strsignal (WTERMSIG (status)), + strsignal (EXPECTED_SIGNAL)); + } + else + fprintf (stderr, "Didn't expect signal from child: got `%s'\n", + strsignal (WTERMSIG (status))); + exit (1); + } + + /* Simply exit with the return value of the test. */ +#ifndef EXPECTED_STATUS + return WEXITSTATUS (status); +#else + if (WEXITSTATUS (status) != EXPECTED_STATUS) + { + fprintf (stderr, "Expected status %d, got %d\n", + EXPECTED_STATUS, WEXITSTATUS (status)); + exit (1); + } + + return 0; +#endif +} diff --git a/test/testsuite.h b/test/testsuite.h new file mode 100644 index 0000000..afc45b0 --- /dev/null +++ b/test/testsuite.h @@ -0,0 +1,100 @@ +/* vi: set sw=4 ts=4: */ +/* + * Some simple macros for use in test applications. + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef TESTSUITE_H +#define TESTSUITE_H + +#ifdef __NO_TESTCODE__ +extern size_t test_number; +#endif + +extern void init_testsuite(const char* testname); +extern void done_testing(void) __attribute__((noreturn)); +extern void success_msg(int result, const char* command); +extern void error_msg(int result, int line, const char* file, const char* command); + +#ifndef __NO_TESTCODE__ + +size_t test_number = 0; +static int failures = 0; + +void error_msg(int result, int line, const char* file, const char* command) +{ + failures++; + + printf("\nFAILED TEST %lu: \n\t%s\n", (unsigned long)test_number, command); + printf("AT LINE: %d, FILE: %s\n\n", line, file); +} + +void success_msg(int result, const char* command) +{ +#if 0 + printf("passed test: %s == 0\n", command); +#endif +} + +void done_testing(void) +{ + if (0 < failures) { + printf("Failed %d tests\n", failures); + exit(EXIT_FAILURE); + } else { + printf("All functions tested sucessfully\n"); + exit(EXIT_SUCCESS); + } +} + +void init_testsuite(const char* testname) +{ + printf("%s", testname); + test_number = 0; + failures = 0; +#if !defined(__UCLIBC__) || defined(__UCLIBC_DYNAMIC_ATEXIT__) + atexit(done_testing); +#endif +} + +#endif /* __NO_TESTCODE__ */ + + +#define TEST_STRING_OUTPUT(command, expected_result) \ + do { \ + int result = strcmp(command, expected_result); \ + test_number++; \ + if (result == expected_result) { \ + success_msg(result, "command"); \ + } else { \ + error_msg(result, __LINE__, __FILE__, command); \ + }; \ + } while (0) + +#define TEST_NUMERIC(command, expected_result) \ + do { \ + int result = (command); \ + test_number++; \ + if (result == expected_result) { \ + success_msg(result, # command); \ + } else { \ + error_msg(result, __LINE__, __FILE__, # command); \ + }; \ + } while (0) + +#define TEST(command) \ + do { \ + int result = (command); \ + test_number++; \ + if (result == 1) { \ + success_msg(result, # command); \ + } else { \ + error_msg(result, __LINE__, __FILE__, # command); \ + }; \ + } while (0) + +#define STR_CMD(cmd) cmd + +#endif /* TESTSUITE_H */ diff --git a/test/time/Makefile b/test/time/Makefile new file mode 100644 index 0000000..8c6978f --- /dev/null +++ b/test/time/Makefile @@ -0,0 +1,13 @@ +# uClibc time tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS_DISABLED := bug-asctime bug-asctime_r time tst-mktime2 tst-posixtz \ + tst-strftime tst-strptime tst-timezone + +ifneq ($(UCLIBC_HAS_XLOCALE),y) +TESTS_DISABLED += tst-ftime_l +endif + +include ../Test.mak + +CFLAGS_tst-strptime2 := -std=c99 diff --git a/test/time/bug-asctime.c b/test/time/bug-asctime.c new file mode 100644 index 0000000..149e4e0 --- /dev/null +++ b/test/time/bug-asctime.c @@ -0,0 +1,40 @@ +/* Note: we disable this on uClibc because we dont bother + * verifying if the year is sane ... we just return ???? + * for the year value ... + */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + time_t t = time (NULL); + struct tm *tp = localtime (&t); + tp->tm_year = INT_MAX; + errno = 0; + char *s = asctime (tp); + if (s != NULL || errno != EOVERFLOW) + { + printf ("asctime did not fail correctly: s=%p, wanted %p; errno=%i, wanted %i\n", + s, NULL, errno, EOVERFLOW); + result = 1; + } + char buf[1000]; + errno = 0; + s = asctime_r (tp, buf); + if (s != NULL || errno != EOVERFLOW) + { + printf ("asctime_r did not fail correctly: s=%p, wanted %p; errno=%i, wanted %i\n", + s, NULL, errno, EOVERFLOW); + result = 1; + } + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/time/bug-asctime_r.c b/test/time/bug-asctime_r.c new file mode 100644 index 0000000..1fcc465 --- /dev/null +++ b/test/time/bug-asctime_r.c @@ -0,0 +1,37 @@ +/* Note: we disable this on uClibc because we dont bother + * verifying if the year is sane ... we just return ???? + * for the year value ... + */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + time_t t = time (NULL); + struct tm *tp = localtime (&t); + tp->tm_year = 10000 - 1900; + char buf[1000]; + errno = 0; + buf[26] = '\xff'; + char *s = asctime_r (tp, buf); + if (s != NULL || errno != EOVERFLOW) + { + puts ("asctime_r did not fail correctly"); + result = 1; + } + if (buf[26] != '\xff') + { + puts ("asctime_r overwrote 27th byte in buffer"); + result = 1; + } + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/time/clocktest.c b/test/time/clocktest.c new file mode 100644 index 0000000..a5b2c09 --- /dev/null +++ b/test/time/clocktest.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include + +volatile int gotit = 0; + +static void +alarm_handler (int signum) +{ + gotit = 1; +} + + +int +main (int argc, char ** argv) +{ + clock_t start, stop; + + if (signal(SIGALRM, alarm_handler) == SIG_ERR) + { + perror ("signal"); + exit (1); + } + alarm(1); + start = clock (); + while (!gotit); + stop = clock (); + + printf ("%ld clock ticks per second (start=%ld,stop=%ld)\n", + stop - start, start, stop); + printf ("CLOCKS_PER_SEC=%ld, sysconf(_SC_CLK_TCK)=%ld\n", + CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK)); + return 0; +} diff --git a/test/time/test_time.c b/test/time/test_time.c new file mode 100644 index 0000000..2ce819a --- /dev/null +++ b/test/time/test_time.c @@ -0,0 +1,116 @@ +/* Copyright (C) 1991, 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +main (int argc, char **argv) +{ + time_t t; + register struct tm *tp; + struct tm tbuf; + int lose = 0; + + --argc; + ++argv; + + do + { + char buf[BUFSIZ]; + if (argc > 0) + { + static char tzenvbuf[BUFSIZ]; + sprintf(tzenvbuf, "TZ=%s", *argv); + if (putenv(tzenvbuf)) + { + puts("putenv failed."); + lose = 1; + } + else + puts (tzenvbuf); + } + tzset(); + tbuf.tm_year = 72; + tbuf.tm_mon = 0; + tbuf.tm_mday = 31; + tbuf.tm_hour = 6; + tbuf.tm_min = 14; + tbuf.tm_sec = 50; + tbuf.tm_isdst = -1; + doit:; + t = mktime(&tbuf); + if (t == (time_t) -1) + { + puts("mktime() failed?"); + lose = 1; + } + tp = localtime(&t); + if (tp == NULL) + { + puts("localtime() failed."); + lose = 1; + } + else if (strftime(buf, sizeof(buf), "%a %b %d %X %Z %Y", tp) == 0) + { + puts("strftime() failed."); + lose = 1; + } + else + puts(buf); + if (tbuf.tm_year == 101) + { + tbuf.tm_year = 97; + tbuf.tm_mon = 0; + goto doit; + } + ++argv; + } while (--argc > 0); + + { +#define SIZE 256 + char buffer[SIZE]; + time_t curtime; + struct tm *loctime; + + curtime = time (NULL); + + loctime = localtime (&curtime); + + fputs (asctime (loctime), stdout); + + strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime); + fputs (buffer, stdout); + strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime); + fputs (buffer, stdout); + + loctime->tm_year = 72; + loctime->tm_mon = 8; + loctime->tm_mday = 12; + loctime->tm_hour = 20; + loctime->tm_min = 49; + loctime->tm_sec = 05; + curtime = mktime (loctime); + strftime (buffer, SIZE, "%D %T was %w the %jth.\n", loctime); + fputs (buffer, stdout); + } + + return (lose ? EXIT_FAILURE : EXIT_SUCCESS); +} diff --git a/test/time/time.c b/test/time/time.c new file mode 100644 index 0000000..a4d68d5 --- /dev/null +++ b/test/time/time.c @@ -0,0 +1,76 @@ +#include +#include +#include + +/* We use this instead of memcmp because some broken C libraries + * add additional nonstandard fields to struct tm... */ + +int tm_cmp(struct tm tm1, struct tm tm2) +{ + return tm1.tm_sec != tm2.tm_sec || + tm1.tm_min != tm2.tm_min || + tm1.tm_hour != tm2.tm_hour || + tm1.tm_mday != tm2.tm_mday || + tm1.tm_mon != tm2.tm_mon || + tm1.tm_year != tm2.tm_year || + tm1.tm_wday != tm2.tm_wday || + tm1.tm_yday != tm2.tm_yday || + tm1.tm_isdst!= tm2.tm_isdst; +} + +char *tm_str(struct tm tm) +{ + static int i; + static char b[4][64]; + i = (i+1)%4; + snprintf(b[i], sizeof b[i], + "s=%.2d m=%.2d h=%.2d mday=%.2d mon=%.2d year=%.4d wday=%d yday=%d isdst=%d", + tm.tm_sec, tm.tm_min, tm.tm_hour, + tm.tm_mday, tm.tm_mon, tm.tm_year, + tm.tm_wday, tm.tm_yday, tm.tm_isdst); + return b[i]; +} + +#define TM(ss,mm,hh,md,mo,yr,wd,yd,dst) (struct tm){ \ + .tm_sec = ss, .tm_min = mm, .tm_hour = hh, \ + .tm_mday = md, .tm_mon = mo, .tm_year = yr, \ + .tm_wday = wd, .tm_yday = yd, .tm_isdst = dst } + +#define TM_EPOCH TM(0,0,0,1,0,70,4,0,0) +#define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0) +#define TM_Y2038 TM(8,14,3,19,0,138,2,18,0) + +#define TEST_TM(r,x,m) (!tm_cmp((r),(x)) || \ +(printf(__FILE__ ":%d: %s failed:\n\tresult: %s\n\texpect: %s\n", __LINE__, \ +m, tm_str((r)), tm_str((x))), err++, 0) ) + +#define TEST(r, f, x, m) ( \ +((r) = (f)) == (x) || \ +(printf(__FILE__ ":%d: %s failed (" m ")\n", __LINE__, #f, r, x), err++, 0) ) + +int main(void) +{ + struct tm tm, *tm_p; + time_t t; + int err=0; + + putenv("TZ=GMT"); + tzset(); + + t=0; tm_p = gmtime(&t); + TEST_TM(*tm_p, TM_EPOCH, "gmtime(0)"); + + tm = TM_Y2038_1S; + t = mktime(&tm); + tm = *(gmtime(&t)); + TEST_TM(*tm_p, TM_Y2038_1S, "mktime/gmtime(Y2038-1)"); + + tm = TM_Y2038; + t = mktime(&tm); + tm = *(gmtime(&t)); + TEST_TM(*tm_p, TM_Y2038, "mktime/gmtime(Y2038)"); + + /* FIXME: set a TZ var and check DST boundary conditions */ + + return err; +} diff --git a/test/time/tst-ftime_l.c b/test/time/tst-ftime_l.c new file mode 100644 index 0000000..95017f1 --- /dev/null +++ b/test/time/tst-ftime_l.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include + + +int +main (void) +{ + locale_t l; + locale_t old; + struct tm tm; + char buf[1000]; + wchar_t wbuf[1000]; + int result = 0; + size_t n; + + l = newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL); + if (l == NULL) + { + puts ("newlocale failed"); + exit (1); + } + + memset (&tm, '\0', sizeof (tm)); + + tm.tm_year = 102; + tm.tm_mon = 2; + tm.tm_mday = 1; + + if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0) + { + puts ("initial strftime failed"); + exit (1); + } + if (strcmp (buf, " 1 MARCH 2002") != 0) + { + printf ("initial strftime: expected \"%s\", got \"%s\"\n", + " 1 MARCH 2002", buf); + result = 1; + } + else + printf ("got \"%s\"\n", buf); + + /* Now using the extended locale model. */ + if (strftime_l (buf, sizeof (buf), "%e %^B %Y", &tm, l) == 0) + { + puts ("strftime_l failed"); + result = 1; + } + else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0) + { + printf ("strftime_l: expected \"%s\", got \"%s\"\n", + " 1 M\xc4RZ 2002", buf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%s\"\n", buf); + setlocale (LC_ALL, "C"); + } + + /* And the wide character version. */ + if (wcsftime_l (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%e %^B %Y", &tm, l) + == 0) + { + puts ("wcsftime_l failed"); + result = 1; + } + else if (wcscmp (wbuf, L" 1 M\x00c4RZ 2002") != 0) + { + printf ("wcsftime_l: expected \"%ls\", got \"%ls\"\n", + L" 1 M\x00c4RZ 2002", wbuf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%ls\"\n", wbuf); + setlocale (LC_ALL, "C"); + } + + old = uselocale (l); + + n = strftime (buf, sizeof (buf), "%e %^B %Y", &tm); + + /* Switch back. */ + (void) uselocale (old); + + if (n == 0) + { + puts ("strftime after first uselocale failed"); + result = 1; + } + else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0) + { + printf ("strftime in non-C locale: expected \"%s\", got \"%s\"\n", + " 1 M\xc4RZ 2002", buf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%s\"\n", buf); + setlocale (LC_ALL, "C"); + } + + if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0) + { + puts ("strftime after second uselocale failed"); + result = 1; + } + else if (strcmp (buf, " 1 MARCH 2002") != 0) + { + printf ("initial strftime: expected \"%s\", got \"%s\"\n", + " 1 MARCH 2002", buf); + result = 1; + } + else + printf ("got \"%s\"\n", buf); + + return result; +} + +#else +int main(void) +{ + puts("Test requires WCHAR support; skipping"); + return 0; +} +#endif diff --git a/test/time/tst-mktime.c b/test/time/tst-mktime.c new file mode 100644 index 0000000..416a856 --- /dev/null +++ b/test/time/tst-mktime.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +int +main (void) +{ + struct tm time_str, *tm; + time_t t; + char daybuf[20]; + int result; + + time_str.tm_year = 2001 - 1900; + time_str.tm_mon = 7 - 1; + time_str.tm_mday = 4; + time_str.tm_hour = 0; + time_str.tm_min = 0; + time_str.tm_sec = 1; + time_str.tm_isdst = -1; + + if (mktime (&time_str) == -1) + { + (void) puts ("-unknown-"); + result = 1; + } + else + { + (void) strftime (daybuf, sizeof (daybuf), "%A", &time_str); + (void) puts (daybuf); + result = strcmp (daybuf, "Wednesday") != 0; + } + + setenv ("TZ", "EST+5", 1); +#define EVENING69 1 * 60 * 60 + 2 * 60 + 29 + t = EVENING69; + tm = localtime (&t); + if (tm == NULL) + { + (void) puts ("localtime returned NULL"); + result = 1; + } + else + { + time_str = *tm; + t = mktime (&time_str); + if (t != EVENING69) + { + printf ("mktime returned %ld, expected %d\n", + (long) t, EVENING69); + result = 1; + } + else + (void) puts ("Dec 31 1969 EST test passed"); + + setenv ("TZ", "CET-1", 1); + t = mktime (&time_str); +#define EVENING69_CET (EVENING69 - (5 - -1) * 60 * 60) + if (t != EVENING69_CET) + { + printf ("mktime returned %ld, expected %ld\n", + (long) t, (long) EVENING69_CET); + result = 1; + } + else + (void) puts ("Dec 31 1969 CET test passed"); + } + + return result; +} diff --git a/test/time/tst-mktime2.c b/test/time/tst-mktime2.c new file mode 100644 index 0000000..6279218 --- /dev/null +++ b/test/time/tst-mktime2.c @@ -0,0 +1,141 @@ +/* Test program from Paul Eggert and Tony Leneis. */ +#include +#include +#include + +static time_t time_t_max; +static time_t time_t_min; + +/* Values we'll use to set the TZ environment variable. */ +static const char *tz_strings[] = + { + (const char *) 0, "GMT0", "JST-9", + "EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" + }; +#define N_STRINGS ((int) (sizeof (tz_strings) / sizeof (tz_strings[0]))) + +/* Fail if mktime fails to convert a date in the spring-forward gap. + Based on a problem report from Andreas Jaeger. */ +static void +spring_forward_gap (void) +{ + /* glibc (up to about 1998-10-07) failed this test. */ + struct tm tm; + + /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" + instead of "TZ=America/Vancouver" in order to detect the bug even + on systems that don't support the Olson extension, or don't have the + full zoneinfo tables installed. */ + setenv ("TZ", "PST8PDT,M4.1.0,M10.5.0", 1); + + tm.tm_year = 98; + tm.tm_mon = 3; + tm.tm_mday = 5; + tm.tm_hour = 2; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + if (mktime (&tm) == (time_t)-1) + exit (1); +} + +static void +mktime_test1 (time_t now) +{ + struct tm *lt = localtime (&now); + if (lt && mktime (lt) != now) + exit (2); +} + +static void +mktime_test (time_t now) +{ + mktime_test1 (now); + mktime_test1 ((time_t) (time_t_max - now)); + mktime_test1 ((time_t) (time_t_min + now)); +} + +static void +irix_6_4_bug (void) +{ + /* Based on code from Ariel Faigon. */ + struct tm tm; + tm.tm_year = 96; + tm.tm_mon = 3; + tm.tm_mday = 0; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + mktime (&tm); + if (tm.tm_mon != 2 || tm.tm_mday != 31) + exit (3); +} + +static void +bigtime_test (int j) +{ + struct tm tm; + time_t now; + tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; + tm.tm_isdst = -1; + now = mktime (&tm); + if (now != (time_t) -1) + { + struct tm *lt = localtime (&now); + if (! (lt + && lt->tm_year == tm.tm_year + && lt->tm_mon == tm.tm_mon + && lt->tm_mday == tm.tm_mday + && lt->tm_hour == tm.tm_hour + && lt->tm_min == tm.tm_min + && lt->tm_sec == tm.tm_sec + && lt->tm_yday == tm.tm_yday + && lt->tm_wday == tm.tm_wday + && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) + == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) + exit (4); + } +} + +static int +do_test (void) +{ + time_t t, delta; + int i, j; + + setenv ("TZ", "America/Sao_Paulo", 1); + /* This test makes some buggy mktime implementations loop. + Give up after 60 seconds; a mktime slower than that + isn't worth using anyway. */ + alarm (60); + + for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2) + continue; + time_t_max--; + if ((time_t) -1 < 0) + for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2) + continue; + delta = time_t_max / 997; /* a suitable prime number */ + for (i = 0; i < N_STRINGS; i++) + { + if (tz_strings[i]) + setenv ("TZ", tz_strings[i], 1); + + for (t = 0; t <= time_t_max - delta; t += delta) + mktime_test (t); + mktime_test ((time_t) 1); + mktime_test ((time_t) (60 * 60)); + mktime_test ((time_t) (60 * 60 * 24)); + + for (j = 1; 0 < j; j *= 2) + bigtime_test (j); + bigtime_test (j - 1); + } + irix_6_4_bug (); + spring_forward_gap (); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/time/tst-mktime3.c b/test/time/tst-mktime3.c new file mode 100644 index 0000000..60d0e0b --- /dev/null +++ b/test/time/tst-mktime3.c @@ -0,0 +1,50 @@ +/* Test program for mktime bugs with out-of-range tm_sec values. */ + +#include +#include +#include + +struct tm tests[] = +{ + { .tm_sec = -1, .tm_mday = 1, .tm_year = 104 }, + { .tm_sec = 65, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, + .tm_mon = 11, .tm_year = 101 } +}; +struct tm expected[] = +{ + { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, + .tm_mon = 11, .tm_year = 103, .tm_wday = 3, .tm_yday = 364 }, + { .tm_sec = 5, .tm_mday = 1, .tm_year = 102, .tm_wday = 2 } +}; + +int +main (void) +{ + setenv ("TZ", "UTC", 1); + int i; + for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + { + if (mktime (&tests[i]) < 0) + { + printf ("mktime %d failed\n", i); + return 1; + } +#define CHECK(name) \ + if (tests[i].name != expected[i].name) \ + { \ + printf ("test %d " #name " got %d expected %d\n", \ + i, tests[i].name, expected[i].name); \ + return 1; \ + } + CHECK (tm_sec) + CHECK (tm_min) + CHECK (tm_hour) + CHECK (tm_mday) + CHECK (tm_mon) + CHECK (tm_year) + CHECK (tm_wday) + CHECK (tm_yday) + CHECK (tm_isdst) + } + return 0; +} diff --git a/test/time/tst-posixtz.c b/test/time/tst-posixtz.c new file mode 100644 index 0000000..ccba63e --- /dev/null +++ b/test/time/tst-posixtz.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +struct +{ + time_t when; + const char *tz; + const char *result; +} tests[] = +{ + { 909312849L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1998/10/25 21:54:09 dst=1 zone=AEDST" }, + { 924864849L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1999/04/23 20:54:09 dst=0 zone=AEST" }, + { 919973892L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1999/02/26 07:18:12 dst=1 zone=AEDST" }, + { 909312849L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1998/10/25 05:54:09 dst=0 zone=EST" }, + { 924864849L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1999/04/23 06:54:09 dst=1 zone=EDT" }, + { 919973892L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1999/02/25 15:18:12 dst=0 zone=EST" }, +}; + +int +main (void) +{ + int result = 0; + size_t cnt; + + for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) + { + char buf[100]; + struct tm *tmp; + + printf ("TZ = \"%s\", time = %ld => ", tests[cnt].tz, tests[cnt].when); + fflush (stdout); + + setenv ("TZ", tests[cnt].tz, 1); + + tmp = localtime (&tests[cnt].when); + + snprintf (buf, sizeof (buf), + "%04d/%02d/%02d %02d:%02d:%02d dst=%d zone=%s", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_isdst, + tzname[tmp->tm_isdst ? 1 : 0]); + + fputs (buf, stdout); + + if (strcmp (buf, tests[cnt].result) == 0) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + } + + setenv ("TZ", "Universal", 1); + localtime (&tests[0].when); + printf ("TZ = \"Universal\" daylight %d tzname = { \"%s\", \"%s\" }", + daylight, tzname[0], tzname[1]); + if (! daylight) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + + setenv ("TZ", "AEST-10AEDST-11,M10.5.0,M3.5.0", 1); + tzset (); + printf ("TZ = \"AEST-10AEDST-11,M10.5.0,M3.5.0\" daylight %d" + " tzname = { \"%s\", \"%s\" }", daylight, tzname[0], tzname[1]); + if (daylight + && strcmp (tzname[0], "AEST") == 0 && strcmp (tzname[1], "AEDST") == 0) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + + return result; +} diff --git a/test/time/tst-strftime.c b/test/time/tst-strftime.c new file mode 100644 index 0000000..374fba4 --- /dev/null +++ b/test/time/tst-strftime.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include + + +static struct +{ + const char *fmt; + size_t min; + size_t max; +} tests[] = + { + { "%2000Y", 2000, 4000 }, + { "%02000Y", 2000, 4000 }, + { "%_2000Y", 2000, 4000 }, + { "%-2000Y", 2000, 4000 }, + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +static int +do_test (void) +{ + size_t cnt; + int result = 0; + + time_t tnow = time (NULL); + struct tm *now = localtime (&tnow); + + for (cnt = 0; cnt < ntests; ++cnt) + { + size_t size = 0; + int res; + char *buf = NULL; + + do + { + size += 500; + buf = (char *) realloc (buf, size); + if (buf == NULL) + { + puts ("out of memory"); + exit (1); + } + + res = strftime (buf, size, tests[cnt].fmt, now); + if (res != 0) + break; + } + while (size < tests[cnt].max); + + if (res == 0) + { + printf ("%Zu: %s: res == 0 despite size == %Zu\n", + cnt, tests[cnt].fmt, size); + result = 1; + } + else if (size < tests[cnt].min) + { + printf ("%Zu: %s: size == %Zu was enough\n", + cnt, tests[cnt].fmt, size); + result = 1; + } + else + printf ("%Zu: %s: size == %Zu: OK\n", cnt, tests[cnt].fmt, size); + + free (buf); + } + + struct tm ttm = + { + /* Initialize the fields which are needed in the tests. */ + .tm_mday = 1, + .tm_hour = 2 + }; + const struct + { + const char *fmt; + const char *exp; + size_t n; + } ftests[] = + { + { "%-e", "1", 1 }, + { "%-k", "2", 1 }, + { "%-l", "2", 1 }, + }; +#define nftests (sizeof (ftests) / sizeof (ftests[0])) + for (cnt = 0; cnt < nftests; ++cnt) + { + char buf[100]; + size_t r = strftime (buf, sizeof (buf), ftests[cnt].fmt, &ttm); + if (r != ftests[cnt].n) + { + printf ("strftime(\"%s\") returned %zu not %zu\n", + ftests[cnt].fmt, r, ftests[cnt].n); + result = 1; + } + if (strcmp (buf, ftests[cnt].exp) != 0) + { + printf ("strftime(\"%s\") produced \"%s\" not \"%s\"\n", + ftests[cnt].fmt, buf, ftests[cnt].exp); + result = 1; + } + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/time/tst-strptime.c b/test/time/tst-strptime.c new file mode 100644 index 0000000..6356aa0 --- /dev/null +++ b/test/time/tst-strptime.c @@ -0,0 +1,193 @@ +/* Test for strptime. + Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +static const struct +{ + const char *locale; + const char *input; + const char *format; + int wday; + int yday; + int mon; + int mday; +} day_tests[] = +{ + { "C", "2000-01-01", "%Y-%m-%d", 6, 0, 0, 1 }, + { "C", "03/03/00", "%D", 5, 62, 2, 3 }, + { "C", "9/9/99", "%x", 4, 251, 8, 9 }, + { "C", "19990502123412", "%Y%m%d%H%M%S", 0, 121, 4, 2 }, + { "C", "2001 20 Mon", "%Y %U %a", 1, 140, 4, 21 }, + { "C", "2001 21 Mon", "%Y %W %a", 1, 140, 4, 21 }, + { "ja_JP.EUC-JP", "2000-01-01 08:12:21 AM", "%Y-%m-%d %I:%M:%S %p", + 6, 0, 0, 1 }, + { "en_US.ISO-8859-1", "2000-01-01 08:12:21 PM", "%Y-%m-%d %I:%M:%S %p", + 6, 0, 0, 1 }, + { "ja_JP.EUC-JP", "2001 20 \xb7\xee", "%Y %U %a", 1, 140, 4, 21 }, + { "ja_JP.EUC-JP", "2001 21 \xb7\xee", "%Y %W %a", 1, 140, 4, 21 }, +}; + + +static const struct +{ + const char *input; + const char *format; + const char *output; + int wday; + int yday; +} tm_tests [] = +{ + {"17410105012000", "%H%M%S%d%m%Y", "2000-01-05 17:41:01", 3, 4} +}; + + + +static int +test_tm (void) +{ + struct tm tm; + size_t i; + int result = 0; + char buf[100]; + + for (i = 0; i < sizeof (tm_tests) / sizeof (tm_tests[0]); ++i) + { + memset (&tm, '\0', sizeof (tm)); + + char *ret = strptime (tm_tests[i].input, tm_tests[i].format, &tm); + if (ret == NULL) + { + printf ("strptime returned NULL for `%s'\n", tm_tests[i].input); + result = 1; + continue; + } + else if (*ret != '\0') + { + printf ("not all of `%s' read\n", tm_tests[i].input); + result = 1; + } + strftime (buf, sizeof (buf), "%F %T", &tm); + printf ("strptime (\"%s\", \"%s\", ...)\n" + "\tshould be: %s, wday = %d, yday = %3d\n" + "\t is: %s, wday = %d, yday = %3d\n", + tm_tests[i].input, tm_tests[i].format, + tm_tests[i].output, + tm_tests[i].wday, tm_tests[i].yday, + buf, tm.tm_wday, tm.tm_yday); + + if (strcmp (buf, tm_tests[i].output) != 0) + { + printf ("Time and date are not correct.\n"); + result = 1; + } + if (tm.tm_wday != tm_tests[i].wday) + { + printf ("weekday for `%s' incorrect: %d instead of %d\n", + tm_tests[i].input, tm.tm_wday, tm_tests[i].wday); + result = 1; + } + if (tm.tm_yday != tm_tests[i].yday) + { + printf ("yearday for `%s' incorrect: %d instead of %d\n", + tm_tests[i].input, tm.tm_yday, tm_tests[i].yday); + result = 1; + } + } + + return result; +} + + +int +main (int argc, char *argv[]) +{ + struct tm tm; + size_t i; + int result = 0; + + for (i = 0; i < sizeof (day_tests) / sizeof (day_tests[0]); ++i) + { + memset (&tm, '\0', sizeof (tm)); + + if (setlocale (LC_ALL, day_tests[i].locale) == NULL) + { + printf ("cannot set locale %s: %m\n", day_tests[i].locale); + exit (EXIT_FAILURE); + } + + char *ret = strptime (day_tests[i].input, day_tests[i].format, &tm); + if (ret == NULL) + { + printf ("strptime returned NULL for `%s'\n", day_tests[i].input); + result = 1; + continue; + } + else if (*ret != '\0') + { + printf ("not all of `%s' read\n", day_tests[i].input); + result = 1; + } + + printf ("strptime (\"%s\", \"%s\", ...)\n" + "\tshould be: wday = %d, yday = %3d, mon = %2d, mday = %2d\n" + "\t is: wday = %d, yday = %3d, mon = %2d, mday = %2d\n", + day_tests[i].input, day_tests[i].format, + day_tests[i].wday, day_tests[i].yday, + day_tests[i].mon, day_tests[i].mday, + tm.tm_wday, tm.tm_yday, tm.tm_mon, tm.tm_mday); + + if (tm.tm_wday != day_tests[i].wday) + { + printf ("weekday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_wday, day_tests[i].wday); + result = 1; + } + if (tm.tm_yday != day_tests[i].yday) + { + printf ("yearday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_yday, day_tests[i].yday); + result = 1; + } + if (tm.tm_mon != day_tests[i].mon) + { + printf ("month for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_mon, day_tests[i].mon); + result = 1; + } + if (tm.tm_mday != day_tests[i].mday) + { + printf ("monthday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_mday, day_tests[i].mday); + result = 1; + } + } + + setlocale (LC_ALL, "C"); + + result |= test_tm (); + + return result; +} diff --git a/test/time/tst-strptime2.c b/test/time/tst-strptime2.c new file mode 100644 index 0000000..73552bb --- /dev/null +++ b/test/time/tst-strptime2.c @@ -0,0 +1,59 @@ +#include +#include +#include + + +static const struct +{ + const char *fmt; + long int gmtoff; +} tests[] = + { + { "1113472456 +1000", 36000 }, + { "1113472456 -1000", -36000 }, + { "1113472456 +10", 36000 }, + { "1113472456 -10", -36000 }, + { "1113472456 +1030", 37800 }, + { "1113472456 -1030", -37800 }, + { "1113472456 +0030", 1800 }, + { "1113472456 -0030", -1800 }, + { "1113472456 -1330", LONG_MAX }, + { "1113472456 +1330", LONG_MAX }, + { "1113472456 -1060", LONG_MAX }, + { "1113472456 +1060", LONG_MAX }, + { "1113472456 1030", LONG_MAX }, + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +int +main (void) +{ + int result = 0; + + for (int i = 0; i < ntests; ++i) + { + struct tm tm; + + if (strptime (tests[i].fmt, "%s %z", &tm) == NULL) + { + if (tests[i].gmtoff != LONG_MAX) + { + printf ("round %d: strptime unexpectedly failed\n", i); + result = 1; + } + continue; + } + + if (tm.tm_gmtoff != tests[i].gmtoff) + { + printf ("round %d: tm_gmtoff is %ld\n", i, (long int) tm.tm_gmtoff); + result = 1; + } + } + + if (result == 0) + puts ("all OK"); + + return 0; +} diff --git a/test/time/tst-timezone.c b/test/time/tst-timezone.c new file mode 100644 index 0000000..4c87916 --- /dev/null +++ b/test/time/tst-timezone.c @@ -0,0 +1,170 @@ +/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +int failed = 0; + +struct test_times +{ + const char *name; + int daylight; + int timezone; + const char *tzname[2]; +}; + +static const struct test_times tests[] = +{ + { "Europe/Amsterdam", 1, -3600, { "CET", "CEST" }}, + { "Europe/Berlin", 1, -3600, { "CET", "CEST" }}, + { "Europe/London", 1, 0, { "GMT", "BST" }}, + { "Universal", 0, 0, {"UTC", "UTC" }}, + { "Australia/Melbourne", 1, -36000, { "EST", "EST" }}, + { "America/Sao_Paulo", 1, 10800, {"BRT", "BRST" }}, + { "America/Chicago", 1, 21600, {"CST", "CDT" }}, + { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }}, + { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }}, + { "Asia/Tokyo", 1, -32400, {"JST", "JDT" }}, + { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }}, + { NULL, 0, 0 } +}; + +/* This string will be used for `putenv' calls. */ +char envstring[100]; + +static void +print_tzvars (void) +{ + printf ("tzname[0]: %s\n", tzname[0]); + printf ("tzname[1]: %s\n", tzname[1]); + printf ("daylight: %d\n", daylight); + printf ("timezone: %ld\n", timezone); +} + + +static void +check_tzvars (const char *name, int dayl, int timez, const char *const tznam[]) +{ + int i; + + if (daylight != dayl) + { + printf ("*** Timezone: %s, daylight is: %d but should be: %d\n", + name, daylight, dayl); + ++failed; + } + if (timezone != timez) + { + printf ("*** Timezone: %s, timezone is: %ld but should be: %d\n", + name, timezone, timez); + ++failed; + } + for (i = 0; i <= 1; ++i) + if (strcmp (tzname[i], tznam[i]) != 0) + { + printf ("*** Timezone: %s, tzname[%d] is: %s but should be: %s\n", + name, i, tzname[i], tznam[i]); + ++failed; + } +} + + +int +main (int argc, char ** argv) +{ + time_t t; + const struct test_times *pt; + char buf[BUFSIZ]; + + /* This should be: Fri May 15 01:02:16 1998 (UTC). */ + t = 895194136; + printf ("We use this date: %s\n", asctime (gmtime (&t))); + + for (pt = tests; pt->name != NULL; ++pt) + { + /* Start with a known state */ + printf ("Checking timezone %s\n", pt->name); + sprintf (buf, "TZ=%s", pt->name); + if (putenv (buf)) + { + puts ("putenv failed."); + failed = 1; + } + tzset (); + print_tzvars (); + check_tzvars (pt->name, pt->daylight, pt->timezone, pt->tzname); + + /* calling localtime shouldn't make a difference */ + localtime (&t); + print_tzvars (); + check_tzvars (pt->name, pt->daylight, pt->timezone, pt->tzname); + } + + /* From a post of Scott Harrington to the timezone + mailing list. */ + { + struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1}; + char buf[200]; + strcpy (envstring, "TZ=Europe/London"); + putenv (envstring); + t = mktime (&tmBuf); + snprintf (buf, sizeof (buf), "TZ=%s %ld %d %d %d %d %d %d %d %d %d", + getenv ("TZ"), t, + tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour, + tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year, + tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst); + fputs (buf, stdout); + puts (" should be"); + puts ("TZ=Europe/London 892162800 0 0 0 10 3 98 5 99 1"); + if (strcmp (buf, "TZ=Europe/London 892162800 0 0 0 10 3 98 5 99 1") != 0) + { + failed = 1; + fputs (" FAILED ***", stdout); + } + } + + printf("\n"); + + { + struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1}; + char buf[200]; + strcpy (envstring, "TZ=GMT"); + /* No putenv call needed! */ + t = mktime (&tmBuf); + snprintf (buf, sizeof (buf), "TZ=%s %ld %d %d %d %d %d %d %d %d %d", + getenv ("TZ"), t, + tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour, + tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year, + tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst); + fputs (buf, stdout); + puts (" should be"); + puts ("TZ=GMT 892166400 0 0 0 10 3 98 5 99 0"); + if (strcmp (buf, "TZ=GMT 892166400 0 0 0 10 3 98 5 99 0") != 0) + { + failed = 1; + fputs (" FAILED ***", stdout); + } + } + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/test/time/tst_wcsftime.c b/test/time/tst_wcsftime.c new file mode 100644 index 0000000..6e35f1e --- /dev/null +++ b/test/time/tst_wcsftime.c @@ -0,0 +1,39 @@ +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include + +int +main (int argc, char *argv[]) +{ + wchar_t buf[200]; + time_t t; + struct tm *tp; + int result = 0; + size_t n; + + time (&t); + tp = gmtime (&t); + + n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]), + L"%H:%M:%S %Y-%m-%d\n", tp); + if (n != 21) + result = 1; + + wprintf (L"It is now %ls", buf); + + wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A\n", tp); + + wprintf (L"The weekday is %ls", buf); + + return result; +} + +#else +int main(void) +{ + puts("Test requires WCHAR support; skipping"); + return 0; +} +#endif diff --git a/test/unistd/Makefile b/test/unistd/Makefile new file mode 100644 index 0000000..c5007cd --- /dev/null +++ b/test/unistd/Makefile @@ -0,0 +1,13 @@ +# uClibc unistd tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +include ../Test.mak + +OPTS_getopt := -abcXXX -9 +OPTS_getopt_long := --add XXX --delete YYY --verbose +ifeq ($(UCLIBC_HAS_GNU_GETOPT),y) +OPTS_tstgetopt := -a -b -cfoobar --required foobar --optional=bazbug --none random --col --color --colour +else +# reordering is not supported, behaves as if POSIXLY_CORRECT would be set +OPTS_tstgetopt := -a -b -cfoobar --required foobar --optional=bazbug --none --colou --color --colour random +endif diff --git a/test/unistd/clone.c b/test/unistd/clone.c new file mode 100644 index 0000000..ea7e6ac --- /dev/null +++ b/test/unistd/clone.c @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* + * clone test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include "clone_cruft.h" + +#define GOT1 (1 << 1) +#define GOT2 (1 << 2) +#define GOT3 (1 << 3) +#define ALLGOT (GOT1|GOT2|GOT3) + +static void child_handler(int sig) +{ + printf("I got a SIGCHLD\n"); +} + +static int clone_main(void *arg) +{ + unsigned long input = (unsigned long)arg; + int secs = (input / 10) * 4; + printf("Clone got %lu, sleeping for %i secs\n", input, secs); + sleep(secs); + return input + 20; +} + +int main(void) +{ + int clone1, clone2, clone3; + char clone1_stack[8192], clone2_stack[8192], clone3_stack[8192]; + int status, nostatus, result, wpid; + + signal(SIGCHLD, child_handler); + + if ((clone1 = do_clone(clone_main, clone1_stack, 0, (void*)11)) == -1) { + perror("Clone 1 failed"); + exit(-1); + } + if ((clone2 = do_clone(clone_main, clone2_stack, 0, (void*)22)) == -1) { + perror("Clone 2 failed"); + exit(-2); + } + if ((clone3 = do_clone(clone_main, clone3_stack, 0, (void*)33)) == -1) { + perror("Clone 3 failed"); + exit(-3); + } + + sleep(1); + printf("Parent: waiting for the clones to die.\n"); + nostatus = status = 0; + while (1) { + if ((wpid = waitpid(clone1, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT1; + if (wpid == clone1) { + status |= GOT1; + printf("Clone1 gave back %i\n", WEXITSTATUS(result)); + } + + if ((wpid = waitpid(clone2, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT2; + if (wpid == clone2) { + status |= GOT2; + printf("Clone2 gave back %i\n", WEXITSTATUS(result)); + } + + if ((wpid = waitpid(clone3, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT3; + if (wpid == clone3) { + status |= GOT3; + printf("Clone3 gave back %i\n", WEXITSTATUS(result)); + } + + if (status == ALLGOT || nostatus == ALLGOT) + break; + } + + if (status == ALLGOT) { + printf("Clones exited.\nGoodbye.\n"); + return EXIT_SUCCESS; + } else { + perror("Waiting for clones failed"); + return EXIT_FAILURE; + } +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/test/unistd/clone_cruft.h b/test/unistd/clone_cruft.h new file mode 100644 index 0000000..b6a395d --- /dev/null +++ b/test/unistd/clone_cruft.h @@ -0,0 +1,24 @@ +/* because people like to make things difficult */ + +#undef do_clone + +#define crappy_sizeof(s) (s == NULL ? 0 : sizeof(s)) + +#if defined __ia64__ + +extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, void *__arg, ...); +# define do_clone(fn, stack, flags, arg) \ + __clone2(fn, stack, crappy_sizeof(stack), flags, arg, NULL, NULL, NULL) + +#elif defined __hppa__ + +# define do_clone(fn, stack, flags, arg) \ + clone(fn, stack, flags, arg) + +#else + +# define do_clone(fn, stack, flags, arg) \ + clone(fn, stack+crappy_sizeof(stack), flags, arg) + +#endif diff --git a/test/unistd/errno.c b/test/unistd/errno.c new file mode 100644 index 0000000..5fdb3b3 --- /dev/null +++ b/test/unistd/errno.c @@ -0,0 +1,29 @@ +/* based originally on one the clone tests in the LTP */ + +#include +#include +#include +#include +#include "clone_cruft.h" + +__attribute__ ((__noreturn__)) +static int child_fn(void *arg) +{ + fprintf(stderr, "in child_fn\n"); + exit(1); +} + +int main(void) +{ + int r_clone, ret_errno; + + r_clone = do_clone(child_fn, NULL, (int) NULL, NULL); + ret_errno = errno; + if (ret_errno != EINVAL || r_clone != -1) { + fprintf(stderr, "clone: res=%d (wanted -1) errno=%d (wanted %d)\n", + r_clone, errno, EINVAL); + return 1; + } + + return 0; +} diff --git a/test/unistd/exec-null.c b/test/unistd/exec-null.c new file mode 100644 index 0000000..3df99f3 --- /dev/null +++ b/test/unistd/exec-null.c @@ -0,0 +1,13 @@ +/* make sure we handle argv[0] == NULL */ + +#include + +int main(int argc, char *argv[]) +{ + if (argc == 0) + return 0; + + char *exec_argv[1], *exec_envp[1]; + exec_argv[0] = exec_envp[0] = NULL; + return execve("./exec-null", exec_argv, exec_envp); +} diff --git a/test/unistd/fork.c b/test/unistd/fork.c new file mode 100644 index 0000000..6d132d6 --- /dev/null +++ b/test/unistd/fork.c @@ -0,0 +1,91 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define GOT1 (1 << 1) +#define GOT2 (1 << 2) +#define GOT3 (1 << 3) + +#ifdef __ARCH_USE_MMU__ + +static void child_handler(int sig) +{ + fprintf(stderr, "I got a SIGCHLD\n"); +} + +int main(void) +{ + pid_t pid1, pid2, pid3; + int status, result, wpid; + + signal(SIGCHLD, child_handler); + + if ((pid1 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 2 seconds...\n"); + sleep(4); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + if ((pid2 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 3 seconds...\n"); + sleep(3); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + if ((pid3 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 4 seconds...\n"); + sleep(2); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + + fprintf(stderr, "Parent: waiting for the child to die.\n"); + status = 0; + while (1) { + wpid = waitpid(pid1, &result, WNOHANG); + if (wpid == pid1) + status |= GOT1; + + wpid = waitpid(pid2, &result, WNOHANG); + if (wpid == pid2) + status |= GOT2; + + wpid = waitpid(pid3, &result, WNOHANG); + if (wpid == pid3) + status |= GOT3; + + if (status == (GOT1 | GOT2 | GOT3)) + break; + } + + fprintf(stderr, "Child process exited.\nGoodbye.\n"); + return EXIT_SUCCESS; +} + +#else + +int main(void) +{ + printf("Skipping test on non-mmu host!\n"); + return EXIT_SUCCESS; +} + +#endif + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/test/unistd/getcwd.c b/test/unistd/getcwd.c new file mode 100644 index 0000000..bcecec7 --- /dev/null +++ b/test/unistd/getcwd.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +int main(void) +{ + char *foo; + char junk[12]; + char crap[100]; + foo = getcwd(NULL, 0); + printf("getcwd(NULL, 0)='%s'\n", foo); + if (foo) { free(foo); } + foo = getcwd(NULL, 100); + printf("\ngetcwd(NULL, 100)='%s'\n", foo); + if (foo) { free(foo); } + foo = getcwd(junk, sizeof(junk)); + printf("\nchar junk[12];\n"); + printf("getcwd(junk, sizeof(junk))='%s'\n", foo); + foo = getcwd(crap, sizeof(crap)); + printf("\nchar crap[100];\n"); + printf("getcwd(crap, sizeof(crap))='%s'\n", foo); + return EXIT_SUCCESS; +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/test/unistd/getopt.c b/test/unistd/getopt.c new file mode 100644 index 0000000..401765c --- /dev/null +++ b/test/unistd/getopt.c @@ -0,0 +1,69 @@ +/* Getopt tests */ + +#include +#include +#include +#include + + +int main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + exit (0); +} + diff --git a/test/unistd/getopt_long.c b/test/unistd/getopt_long.c new file mode 100644 index 0000000..4064e22 --- /dev/null +++ b/test/unistd/getopt_long.c @@ -0,0 +1,93 @@ +/* Getopt tests */ + +#include +#include +#include +#include + + +int main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + diff --git a/test/unistd/tst-preadwrite.c b/test/unistd/tst-preadwrite.c new file mode 100644 index 0000000..2810448 --- /dev/null +++ b/test/unistd/tst-preadwrite.c @@ -0,0 +1,105 @@ +/* Tests for pread and pwrite. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Allow testing of the 64-bit versions as well. */ +#ifndef PREAD +# define PREAD pread +# define PWRITE pwrite +#endif + +#define STRINGIFY(s) STRINGIFY2 (s) +#define STRINGIFY2(s) #s + +/* Prototype for our test function. */ +extern void do_prepare (int argc, char *argv[]); +extern int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +#define PREPARE do_prepare + +/* We might need a bit longer timeout. */ +#define TIMEOUT 20 /* sec */ + +/* This defines the `main' function and some more. */ +#include + +/* These are for the temporary file we generate. */ +char *name; +int fd; + +void +do_prepare (int argc, char *argv[]) +{ + char name_len; + +#define FNAME FNAME2(TRUNCATE) +#define FNAME2(s) "/" STRINGIFY(s) "XXXXXX" + + name_len = strlen (test_dir); + name = malloc (name_len + sizeof (FNAME)); + if (name == NULL) + error (EXIT_FAILURE, errno, "cannot allocate file name"); + mempcpy (mempcpy (name, test_dir, name_len), FNAME, sizeof (FNAME)); + add_temp_file (name); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); +} + + +int +do_test (int argc, char *argv[]) +{ + char buf[1000]; + char res[1000]; + int i; + + memset (buf, '\0', sizeof (buf)); + memset (res, '\xff', sizeof (res)); + + if (write (fd, buf, sizeof (buf)) != sizeof (buf)) + error (EXIT_FAILURE, errno, "during write"); + + for (i = 100; i < 200; ++i) + buf[i] = i; + if (PWRITE (fd, buf + 100, 100, 100) != 100) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE)); + + for (i = 450; i < 600; ++i) + buf[i] = i; + if (PWRITE (fd, buf + 450, 150, 450) != 150) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE)); + + if (PREAD (fd, res, sizeof (buf) - 50, 50) != sizeof (buf) - 50) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PREAD)); + + close (fd); + unlink (name); + + return memcmp (buf + 50, res, sizeof (buf) - 50); +} diff --git a/test/unistd/tst-preadwrite64.c b/test/unistd/tst-preadwrite64.c new file mode 100644 index 0000000..57098e8 --- /dev/null +++ b/test/unistd/tst-preadwrite64.c @@ -0,0 +1,24 @@ +/* Tests for pread64 and pwrite64. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define PREAD pread64 +#define PWRITE pwrite64 + +#include "tst-preadwrite.c" diff --git a/test/unistd/tstgetopt.c b/test/unistd/tstgetopt.c new file mode 100644 index 0000000..97ae2ef --- /dev/null +++ b/test/unistd/tstgetopt.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + static const struct option options[] = + { + {"required", required_argument, NULL, 'r'}, + {"optional", optional_argument, NULL, 'o'}, + {"none", no_argument, NULL, 'n'}, + {"color", no_argument, NULL, 'C'}, + {"colour", no_argument, NULL, 'C'}, + {NULL, 0, NULL, 0 } + }; + + int aflag = 0; + int bflag = 0; + char *cvalue = NULL; + int Cflag = 0; + int nflag = 0; + int index; + int c; + int result = 0; + + while ((c = getopt_long (argc, argv, "abc:", options, NULL)) >= 0) + switch (c) + { + case 'a': + aflag = 1; + break; + case 'b': + bflag = 1; + break; + case 'c': + cvalue = optarg; + break; + case 'C': + ++Cflag; + break; + case '?': + fputs ("Unknown option.\n", stderr); + return 1; + default: + fprintf (stderr, "This should never happen!\n"); + return 1; + + case 'r': + printf ("--required %s\n", optarg); + result |= strcmp (optarg, "foobar") != 0; + break; + case 'o': + printf ("--optional %s\n", optarg); + result |= optarg == NULL || strcmp (optarg, "bazbug") != 0; + break; + case 'n': + puts ("--none"); + nflag = 1; + break; + } + + printf ("aflag = %d, bflag = %d, cvalue = %s, Cflags = %d, nflag = %d\n", + aflag, bflag, cvalue, Cflag, nflag); + + result |= (aflag != 1 || bflag != 1 || cvalue == NULL + || strcmp (cvalue, "foobar") != 0 || Cflag != 3 || nflag != 1); + + for (index = optind; index < argc; index++) + printf ("Non-option argument %s\n", argv[index]); + + result |= optind + 1 != argc || strcmp (argv[optind], "random") != 0; + + return result; +} diff --git a/test/unistd/vfork.c b/test/unistd/vfork.c new file mode 100644 index 0000000..2955839 --- /dev/null +++ b/test/unistd/vfork.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * vfork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + pid_t pid; + int status, wpid; + char *argv[] = { + "/bin/ls", + "-laF", + NULL, + }; + + clearenv(); + if ((pid = vfork()) == 0) { + printf("Hi. I'm the child process...\n"); + execvp(argv[0], argv); + _exit(0); + } + + printf("Hello. I'm the parent process.\n"); + while (1) { + wpid = wait(&status); + if (wpid > 0 && wpid != pid) { + continue; + } + if (wpid == pid) + break; + } + + printf("Child process exited.\nGoodbye.\n"); + return EXIT_SUCCESS; +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..bdaea9f --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: utils +include Makefile.in +include $(top_srcdir)Makerules diff --git a/utils/Makefile.in b/utils/Makefile.in new file mode 100644 index 0000000..ebaa3e4 --- /dev/null +++ b/utils/Makefile.in @@ -0,0 +1,103 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-utils := -DNOT_IN_libc $(SSP_ALL_CFLAGS) -B$(top_builddir)lib -Wl,-rpath-link,$(top_builddir)lib + +CFLAGS-utils-common := -I$(top_srcdir)ldso/include -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=$(UCLIBC_LDSO) +CFLAGS-utils-shared := $(PIEFLAG) $(LDPIEFLAG) + +CFLAGS-ldconfig := $(CFLAGS-utils-common) + +ifeq ($(UCLIBC_STATIC_LDCONFIG),y) +CFLAGS-ldconfig += -static +else +CFLAGS-ldconfig += $(CFLAGS-utils-shared) +endif + +CFLAGS-ldd := $(CFLAGS-utils-common) $(CFLAGS-utils-shared) + +# needs CFLAGS-utils explicitely, because the source file is not located in utils +CFLAGS-iconv := $(CFLAGS-utils) $(CFLAGS-utils-shared) -DL_iconv_main + +CFLAGS-readelf := $(CFLAGS-utils-shared) + +CFLAGS-locale := $(CFLAGS-utils) + +BUILD_CFLAGS-utils := -include $(top_srcdir)include/elf.h + +BUILD_CFLAGS-utils-common := $(CFLAGS-utils-common) + +ifeq ($(LDSO_CACHE_SUPPORT),y) +BUILD_CFLAGS-utils-common += -D__LDSO_CACHE_SUPPORT__=1 +endif + +BUILD_CFLAGS-ldconfig.host := $(BUILD_CFLAGS-utils-common) + +BUILD_CFLAGS-ldd.host := $(BUILD_CFLAGS-utils-common) + +BUILD_LDFLAGS-utils := -Wl,-s + +utils_DIR := $(top_srcdir)utils +utils_OUT := $(top_builddir)utils + +DEPS-ldconfig := $(utils_DIR)/chroot_realpath.c +DEPS-ldconfig.host := $(DEPS-ldconfig) + +utils_OBJ := readelf +ifeq ($(HAVE_SHARED),y) +utils_OBJ += ldconfig ldd +endif + +utils_ICONV_OBJ = +utils_LOCALE_OBJ = +ifeq ($(UCLIBC_HAS_LOCALE),y) +utils_ICONV_OBJ := $(utils_OUT)/iconv +utils_LOCALE_OBJ := $(utils_OUT)/locale +endif + +utils_OBJ := $(patsubst %,$(utils_OUT)/%,$(utils_OBJ)) + +hostutils_OBJ := $(patsubst %,%.host,$(utils_OBJ)) + +utils: $(utils_OBJ) $(utils_ICONV_OBJ) $(utils_LOCALE_OBJ) + +# NOTE: We build the utils AFTER we have a uClibc-targeted toolchain. + +$(utils_OBJ): $(utils_OUT)/% : $(utils_DIR)/%.c | $(libc) + $(compile.u) + +$(utils_OUT)/iconv: $(top_srcdir)libc/misc/wchar/wchar.c | $(libc) + $(compile.u) + +$(utils_OUT)/locale: $(top_srcdir)extra/locale/programs/locale.c | $(libc) + $(compile.u) + +hostutils: $(hostutils_OBJ) + +$(hostutils_OBJ): $(utils_OUT)/%.host : $(utils_DIR)/%.c + $(hcompile.u) + +install-y += utils_install + +utils_install: utils + #$(Q)$(INSTALL) -D -m 755 $(utils_OUT)/readelf $(PREFIX)$(RUNTIME_PREFIX)usr/bin/readelf +ifeq ($(HAVE_SHARED),y) + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldd $(PREFIX)$(RUNTIME_PREFIX)usr/bin/ldd + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldconfig $(PREFIX)$(RUNTIME_PREFIX)sbin/ldconfig +endif +ifeq ($(UCLIBC_HAS_LOCALE),y) + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/iconv $(PREFIX)$(RUNTIME_PREFIX)usr/bin/iconv + $(Q)$(INSTALL) -m 755 $(utils_OUT)/locale $(PREFIX)$(RUNTIME_PREFIX)usr/bin/locale +endif + +objclean-y += utils_clean + +utils_clean: + $(do_rm) $(addprefix $(utils_OUT)/, ldconfig ldd readelf iconv locale *.host) + # This is a hack.. + $(Q)$(RM) $(utils_OUT)/.*.dep + diff --git a/utils/bswap.h b/utils/bswap.h new file mode 100644 index 0000000..666b80a --- /dev/null +++ b/utils/bswap.h @@ -0,0 +1,61 @@ +/* + * Lame bswap replacements as we can't assume the host is sane and provides + * working versions of these. + */ + +#ifndef _BSWAP_H +#define _BSWAP_H 1 + +#if !defined(__BYTE_ORDER) && defined(BYTE_ORDER) +# define __BYTE_ORDER BYTE_ORDER +# if !defined(__BIG_ENDIAN) && defined(BIG_ENDIAN) +# define __BIG_ENDIAN BIG_ENDIAN +# endif +# if !defined(__LITTLE_ENDIAN) && defined(LITTLE_ENDIAN) +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# endif +#endif + +#ifndef __BYTE_ORDER +# ifdef __linux__ +# include +# else +# define __LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +# define __BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +# define __PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp) */ + +# if defined(sun386) || defined(i386) || defined(__LITTLE_ENDIAN__) +# define __BYTE_ORDER __LITTLE_ENDIAN +# endif + +# if defined(sparc) || defined(__BIG_ENDIAN__) +# define __BYTE_ORDER __BIG_ENDIAN +# endif + +# endif /* __linux__ */ +#endif /* __BYTE_ORDER */ + + +#ifndef __BYTE_ORDER +# error "Undefined __BYTE_ORDER" +#endif + +#ifdef __linux__ +# include +#else + +static __inline__ uint16_t bswap_16(uint16_t x) +{ + return ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)); +} +static __inline__ uint32_t bswap_32(uint32_t x) +{ + return ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)); +} +#endif + +#endif diff --git a/utils/chroot_realpath.c b/utils/chroot_realpath.c new file mode 100644 index 0000000..ff1d85d --- /dev/null +++ b/utils/chroot_realpath.c @@ -0,0 +1,165 @@ +/* + * chroot_realpath.c -- resolve pathname as if inside chroot + * Based on realpath.c Copyright (C) 1993 Rick Sladkey + * + * This program 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; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include /* for MAXPATHLEN */ +#include +#include /* for S_IFLNK */ + +#ifndef PATH_MAX +#define PATH_MAX _POSIX_PATH_MAX +#endif + +#define MAX_READLINKS 32 + +char *chroot_realpath(const char *chroot, const char *path, + char resolved_path[]) +{ + char copy_path[PATH_MAX]; + char link_path[PATH_MAX]; + char got_path[PATH_MAX]; + char *got_path_root = got_path; + char *new_path = got_path; + char *max_path; + int readlinks = 0; + int n; + int chroot_len; + + /* Trivial case. */ + if (chroot == NULL || *chroot == '\0' || + (*chroot == '/' && chroot[1] == '\0')) { + strcpy(resolved_path, path); + return resolved_path; + } + + chroot_len = strlen(chroot); + + if (chroot_len + strlen(path) >= PATH_MAX - 3) { + errno = ENAMETOOLONG; + return NULL; + } + + /* Make a copy of the source path since we may need to modify it. */ + strcpy(copy_path, path); + path = copy_path; + max_path = copy_path + PATH_MAX - chroot_len - 3; + + /* Start with the chroot path. */ + strcpy(new_path, chroot); + new_path += chroot_len; + while (*new_path == '/' && new_path > got_path) + new_path--; + got_path_root = new_path; + *new_path++ = '/'; + + /* Expand each slash-separated pathname component. */ + while (*path != '\0') { + /* Ignore stray "/". */ + if (*path == '/') { + path++; + continue; + } + if (*path == '.') { + /* Ignore ".". */ + if (path[1] == '\0' || path[1] == '/') { + path++; + continue; + } + if (path[1] == '.') { + if (path[2] == '\0' || path[2] == '/') { + path += 2; + /* Ignore ".." at root. */ + if (new_path == got_path_root + 1) + continue; + /* Handle ".." by backing up. */ + while ((--new_path)[-1] != '/') ; + continue; + } + } + } + /* Safely copy the next pathname component. */ + while (*path != '\0' && *path != '/') { + if (path > max_path) { + errno = ENAMETOOLONG; + return NULL; + } + *new_path++ = *path++; + } + if (*path == '\0') + /* Don't follow symlink for last pathname component. */ + break; +#ifdef S_IFLNK + /* Protect against infinite loops. */ + if (readlinks++ > MAX_READLINKS) { + errno = ELOOP; + return NULL; + } + /* See if latest pathname component is a symlink. */ + *new_path = '\0'; + n = readlink(got_path, link_path, PATH_MAX - 1); + if (n < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) { + /* Make sure it's null terminated. */ + *new_path = '\0'; + strcpy(resolved_path, got_path); + return NULL; + } + } else { + /* Note: readlink doesn't add the null byte. */ + link_path[n] = '\0'; + if (*link_path == '/') + /* Start over for an absolute symlink. */ + new_path = got_path_root; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/') ; + /* Safe sex check. */ + if (strlen(path) + n >= PATH_MAX - 2) { + errno = ENAMETOOLONG; + return NULL; + } + /* Insert symlink contents into path. */ + strcat(link_path, path); + strcpy(copy_path, link_path); + path = copy_path; + } +#endif /* S_IFLNK */ + *new_path++ = '/'; + } + /* Delete trailing slash but don't whomp a lone slash. */ + if (new_path != got_path + 1 && new_path[-1] == '/') + new_path--; + /* Make sure it's null terminated. */ + *new_path = '\0'; + strcpy(resolved_path, got_path); + return resolved_path; +} diff --git a/utils/ldconfig.c b/utils/ldconfig.c new file mode 100644 index 0000000..0abd061 --- /dev/null +++ b/utils/ldconfig.c @@ -0,0 +1,1010 @@ +/* + * ldconfig - update shared library symlinks + * + * usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ... + * ldconfig -l [-Dv] lib ... + * ldconfig -p + * -D: debug mode, don't update links + * -v: verbose mode, print things as we go + * -q: quiet mode, don't print warnings + * -n: don't process standard directories + * -N: don't update the library cache + * -X: don't update the library links + * -l: library mode, manually link libraries + * -p: print the current library cache + * -f conf: use conf instead of /etc/ld.so.conf + * -C cache: use cache instead of /etc/ld.so.cache + * -r root: first, do a chroot to the indicated directory + * dir ...: directories to process + * lib ...: libraries to link + * + * Copyright 1994-2000 David Engel and Mitch D'Souza + * + * This program may be used for any purpose as long as this + * copyright notice is kept. + * + * 2005/09/16: Dan Howell (modified for cross-development) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bswap.h" +#include "dl-defs.h" + +#define BUFFER_SIZE 4096 + +struct exec { + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#if !defined (N_MAGIC) +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#endif +#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff) +/* Code indicating object file or impure executable. */ +#define OMAGIC 0407 +/* Code indicating pure executable. */ +#define NMAGIC 0410 +/* Code indicating demand-paged executable. */ +#define ZMAGIC 0413 +/* This indicates a demand-paged executable with the header in the text. + The first page is unmapped to help trap NULL pointer references */ +#define QMAGIC 0314 +/* Code indicating core file. */ +#define CMAGIC 0421 + +char *___strtok = NULL; + +/* For SunOS */ +#ifndef PATH_MAX +#include +#define PATH_MAX _POSIX_PATH_MAX +#endif + +/* For SunOS */ +#ifndef N_MAGIC +#define N_MAGIC(exec) ((exec).a_magic & 0xffff) +#endif + +#define EXIT_OK 0 +#define EXIT_FATAL 128 + +char *prog = NULL; +int debug = 0; /* debug mode */ +int verbose = 0; /* verbose mode */ +int libmode = 0; /* library mode */ +int nolinks = 0; /* don't update links */ +int nocache = 0; /* don't build cache */ +void cache_print(void); +void cache_write(void); +void cache_dolib(const char *dir, const char *so, int libtype); +#ifdef __LDSO_CACHE_SUPPORT__ +char *conffile = LDSO_CONF; /* default conf file */ +char *cachefile = LDSO_CACHE; /* default cache file */ +#endif +char *chroot_dir = NULL; +int byteswap = 0; + +struct needed_tab { + char *soname; + int type; +}; + +struct needed_tab needed_tab[] = { + {"libc.so.0", LIB_ELF_LIBC0}, + {"libm.so.0", LIB_ELF_LIBC0}, + {"libdl.so.0", LIB_ELF_LIBC0}, + {"libc.so.5", LIB_ELF_LIBC5}, + {"libm.so.5", LIB_ELF_LIBC5}, + {"libdl.so.1", LIB_ELF_LIBC5}, + {"libc.so.6", LIB_ELF_LIBC6}, + {"libm.so.6", LIB_ELF_LIBC6}, + {"libdl.so.2", LIB_ELF_LIBC6}, + {NULL, LIB_ELF} +}; + +extern char *chroot_realpath(const char *chroot, const char *path, + char resolved_path[]); + +/* These two are used internally -- you shouldn't need to use them */ +static void verror_msg(const char *s, va_list p) +{ + fflush(stdout); + fprintf(stderr, "%s: ", prog); + vfprintf(stderr, s, p); +} + +static void warnx(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + fprintf(stderr, "\n"); +} + +static void err(int errnum, const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + fprintf(stderr, "\n"); + exit(errnum); +} + +static void vperror_msg(const char *s, va_list p) +{ + int err = errno; + + if (s == 0) + s = ""; + verror_msg(s, p); + if (*s) + s = ": "; + fprintf(stderr, "%s%s\n", s, strerror(err)); +} + +static void warn(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vperror_msg(s, p); + va_end(p); +} + +static void *xmalloc(size_t size) +{ + void *ptr; + if ((ptr = malloc(size)) == NULL) + err(EXIT_FATAL, "out of memory"); + return ptr; +} + +static char *xstrdup(const char *str) +{ + char *ptr; + if ((ptr = strdup(str)) == NULL) + err(EXIT_FATAL, "out of memory"); + return ptr; +} + +#undef __ELF_NATIVE_CLASS +#undef readsonameXX +#define readsonameXX readsoname32 +#define __ELF_NATIVE_CLASS 32 +#include "readsoname2.c" + +#undef __ELF_NATIVE_CLASS +#undef readsonameXX +#define readsonameXX readsoname64 +#define __ELF_NATIVE_CLASS 64 +#include "readsoname2.c" +char *readsoname(char *name, FILE *infile, int expected_type, + int *type, int elfclass) +{ + char *res; + + if (elfclass == ELFCLASS32) + res = readsoname32(name, infile, expected_type, type); + else { + res = readsoname64(name, infile, expected_type, type); +#if 0 + /* relies on multilib support which we dont have ... */ + *type |= LIB_ELF64; +#endif + } + + return res; +} + +/* If shared library, return a malloced copy of the soname and set the + * type, else return NULL. + * + * expected_type should be either LIB_ANY or one of the following:- + * LIB_DLL + * LIB_ELF + * LIB_ELF_LIBC5 + * LIB_ELF_LIBC6 + * + * If the lib is ELF and we can not deduce the type the type will + * be set based on expected_type. + * + * If the expected, actual/deduced types missmatch we display a warning + * and use the actual/deduced type. + */ +char *is_shlib(const char *dir, const char *name, int *type, + int *islink, int expected_type) +{ + char *good = NULL; + char *cp, *cp2; + FILE *file; + struct exec exec; + ElfW(Ehdr) *elf_hdr; + struct stat statbuf; + char buff[BUFFER_SIZE]; + char real[BUFFER_SIZE]; + static int byteswapflag = -1; /* start with byte-order unknown */ + + /* see if name is of the form *.so* */ + if (name[strlen(name) - 1] != '~' && (cp = strstr(name, ".so"))) { + /* find the start of the Vminor part, if any */ + if (cp[3] == '.' && (cp2 = strchr(cp + 4, '.'))) + cp = cp2; + else + cp = cp + strlen(cp); + + /* construct the full path name */ + sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? "/" : "", name); + + /* get real path in case of chroot */ + if (!chroot_realpath(chroot_dir, buff, real)) + warn("can't resolve %s in chroot %s", buff, chroot_dir); + + /* first, make sure it's a regular file */ + if (lstat(real, &statbuf)) + warn("skipping %s", buff); + else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) + warnx("%s is not a regular file or symlink, skipping", buff); + else { + /* is it a regular file or a symlink */ + *islink = S_ISLNK(statbuf.st_mode); + + /* then try opening it */ + if (!(file = fopen(real, "rb"))) + warn("skipping %s", buff); + else { + /* now make sure it's a shared library */ + if (fread(&exec, sizeof exec, 1, file) < 1) + warnx("can't read header from %s, skipping", buff); + else if (N_MAGIC(exec) != ZMAGIC + && N_MAGIC(exec) != QMAGIC + && N_MAGIC_SWAP(exec) != ZMAGIC + && N_MAGIC_SWAP(exec) != QMAGIC) { + elf_hdr = (ElfW(Ehdr) *) & exec; + if (elf_hdr->e_ident[0] != 0x7f || + strncmp(elf_hdr->e_ident+1, "ELF", 3) != 0) + { + /* silently ignore linker scripts */ + if (strncmp((char *)&exec, "/* GNU ld", 9) != 0) + warnx("%s is not a shared library, skipping", buff); + } else { + /* always call readsoname to update type */ + if (expected_type == LIB_DLL) { + warnx("%s is not an a.out library, it's ELF!", buff); + expected_type = LIB_ANY; + } + *type = LIB_ELF; + good = readsoname(buff, file, expected_type, type, + elf_hdr->e_ident[EI_CLASS]); + if (byteswapflag == -1) + /* byte-order detected */ + byteswapflag = byteswap; + if (good == NULL || *islink) { + if (good != NULL) + free(good); + good = xstrdup(name); + } else { + /* if the soname does not match the filename, + issue a warning, but only in debug mode. */ + int len = strlen(good); + if (debug && (strncmp(good, name, len) != 0 + || (name[len] != '\0' && name[len] != '.'))) + warnx("%s has inconsistent soname (%s)", buff, good); + } + } + } else { + /* Determine byte-order */ + byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1; + if (byteswapflag == -1) + /* byte-order detected */ + byteswapflag = byteswap; + + if (*islink) + good = xstrdup(name); + else { + good = xmalloc(cp - name + 1); + strncpy(good, name, cp - name); + good[cp - name] = '\0'; + } + if (expected_type != LIB_ANY && expected_type != LIB_DLL) { + warnx("%s is not an ELF library, its an a.out DLL!", buff); + expected_type = LIB_ANY; + } + + *type = LIB_DLL; + } + fclose(file); + + if (byteswapflag >= 0 && byteswap != byteswapflag) { + byteswapflag = -2; + warnx("mixed byte-order detected, using host byte-order..."); + } + if (byteswapflag == -2) + byteswap = 0; + } + } + } + + return good; +} + +/* update the symlink to new library */ +void link_shlib(const char *dir, const char *file, const char *so) +{ + int change = 1; + char libname[BUFFER_SIZE]; + char linkname[BUFFER_SIZE]; + char reallibname[BUFFER_SIZE]; + char reallinkname[BUFFER_SIZE]; + struct stat libstat; + struct stat linkstat; + + /* construct the full path names */ + sprintf(libname, "%s/%s", dir, file); + sprintf(linkname, "%s/%s", dir, so); + if (!chroot_realpath(chroot_dir, libname, reallibname)) + warn("can't resolve %s in chroot %s", libname, chroot_dir); + if (!chroot_realpath(chroot_dir, linkname, reallinkname)) + warn("can't resolve %s in chroot %s", linkname, chroot_dir); + + /* see if a link already exists */ + if (!stat(reallinkname, &linkstat)) { + /* now see if it's the one we want */ + if (stat(reallibname, &libstat)) + warn("can't stat %s", libname); + else if (libstat.st_dev == linkstat.st_dev && + libstat.st_ino == linkstat.st_ino) + change = 0; + } + + /* then update the link, if required */ + if (change > 0 && !nolinks) { + if (!lstat(reallinkname, &linkstat)) { + if (!S_ISLNK(linkstat.st_mode)) { + warnx("%s is not a symlink", linkname); + change = -1; + } else if (remove(reallinkname)) { + warn("can't unlink %s", linkname); + change = -1; + } + } + if (change > 0) { + if (symlink(file, reallinkname)) { + warn("can't link %s to %s", linkname, file); + change = -1; + } + } + } + + /* some people like to know what we're doing */ + if (verbose > 0) + printf("\t%s => %s%s\n", so, file, + change < 0 ? " (SKIPPED)" : + (change > 0 ? " (changed)" : "")); + + return; +} + +/* figure out which library is greater */ +int libcmp(char *p1, char *p2) +{ + while (*p1) { + if (isdigit(*p1) && isdigit(*p2)) { + /* must compare this numerically */ + int v1, v2; + v1 = strtoul(p1, &p1, 10); + v2 = strtoul(p2, &p2, 10); + if (v1 != v2) + return v1 - v2; + } else if (isdigit(*p1) && !isdigit(*p2)) + return 1; + else if (!isdigit(*p1) && isdigit(*p2)) + return -1; + else if (*p1 != *p2) + return *p1 - *p2; + else + p1++, p2++; + } + + return *p1 - *p2; +} + +struct lib { + char *so; /* soname of a library */ + char *name; /* name of a library */ + int libtype; /* type of a library */ + int islink; /* is it a symlink */ + struct lib *next; /* next library in list */ +}; + +/* update all shared library links in a directory */ +void scan_dir(const char *rawname) +{ + DIR *dir; + const char *name; + struct dirent *ent; + char *so, *path, *path_n; + struct lib *lp, *libs = NULL; + int i, libtype, islink, expected_type = LIB_ANY; + char realname[BUFFER_SIZE]; + + /* We need a writable copy of this string */ + path = strdup(rawname); + if (!path) { + err(EXIT_FATAL, "Out of memory!\n"); + } + /* Eliminate all double //s */ + path_n = path; + while ((path_n = strstr(path_n, "//"))) { + i = strlen(path_n); + memmove(path_n, path_n + 1, i - 1); + *(path_n + i - 1) = '\0'; + } + name = path; + +#if 0 + char *t; + /* Check for an embedded expected type */ + t = strrchr(name, '='); + if (t) { + *t++ = '\0'; /* Skip = char */ + if (strcasecmp(t, "libc4") == 0) { + expected_type = LIB_DLL; + } else { + if (strcasecmp(t, "libc5") == 0) { + expected_type = LIB_ELF_LIBC5; + } else { + if (strcasecmp(t, "libc6") == 0) { + expected_type = LIB_ELF_LIBC6; + } else { + if (strcasecmp(t, "libc0") == 0) { + expected_type = LIB_ELF_LIBC0; + } else { + warnx("Unknown type field '%s' for dir '%s' - ignored", t, name); + expected_type = LIB_ANY; + } + } + } + } + } +#endif + + /* let 'em know what's going on */ + if (verbose > 0) + printf("%s:\n", name); + + /* get real path in case of chroot */ + if (!chroot_realpath(chroot_dir, name, realname)) + warn("can't resolve %s in chroot %s", name, chroot_dir); + + /* if we can't open it, we can't do anything */ + if ((dir = opendir(realname)) == NULL) { + warn("skipping %s", name); + free(path); + return; + } + + /* yes, we have to look at every single file */ + while ((ent = readdir(dir)) != NULL) { + /* if it's not a shared library, don't bother */ + if ((so = is_shlib(name, ent->d_name, &libtype, &islink, expected_type)) == NULL) + continue; + + /* have we already seen one with the same so name? */ + for (lp = libs; lp; lp = lp->next) { + if (strcmp(so, lp->so) == 0) { + /* we have, which one do we want to use? */ + if ((!islink && lp->islink) || + (islink == lp->islink && + libcmp(ent->d_name, lp->name) > 0)) { + /* let's use the new one */ + free(lp->name); + lp->name = xstrdup(ent->d_name); + lp->libtype = libtype; + lp->islink = islink; + } + break; + } + } + + /* congratulations, you're the first one we've seen */ + if (!lp) { + lp = xmalloc(sizeof *lp); + lp->so = xstrdup(so); + lp->name = xstrdup(ent->d_name); + lp->libtype = libtype; + lp->islink = islink; + lp->next = libs; + libs = lp; + } + + free(so); + } + + /* don't need this any more */ + closedir(dir); + + /* now we have all the latest libs, update the links */ + for (lp = libs; lp; lp = lp->next) { + if (!lp->islink) + link_shlib(name, lp->name, lp->so); + if (!nocache) + cache_dolib(name, lp->so, lp->libtype); + } + + /* always try to clean up after ourselves */ + while (libs) { + lp = libs->next; + free(libs->so); + free(libs->name); + free(libs); + libs = lp; + } + + free(path); + return; +} + +#ifndef __LDSO_CACHE_SUPPORT__ +void cache_print(void) +{ + printf("Library cache disabled\n"); +} +void cache_dolib(const char *dir, const char *so, int libtype) +{ + return; +} +void cache_write(void) +{ + return; +} +#else +/* return the list of system-specific directories */ +char *get_extpath(void) +{ + char *res = NULL, *cp; + FILE *file; + struct stat stat; + char realconffile[BUFFER_SIZE]; + + if (!chroot_realpath(chroot_dir, conffile, realconffile)) + return NULL; + + if ((file = fopen(realconffile, "r")) != NULL) { + fstat(fileno(file), &stat); + res = xmalloc(stat.st_size + 1); + fread(res, 1, stat.st_size, file); + fclose(file); + res[stat.st_size] = '\0'; + + /* convert comments fo spaces */ + for (cp = res; *cp; /*nada */ ) { + if (*cp == '#') { + do + *cp++ = ' '; + while (*cp && *cp != '\n'); + } else { + cp++; + } + } + } + + return res; +} + +typedef struct liblist { + int flags; + int sooffset; + int liboffset; + char *soname; + char *libname; + struct liblist *next; +} liblist_t; + +static header_t magic = { LDSO_CACHE_MAGIC, LDSO_CACHE_VER, 0 }; +static liblist_t *lib_head = NULL; + +static int liblistcomp(liblist_t *x, liblist_t *y) +{ + int res; + + if ((res = libcmp(x->soname, y->soname)) == 0) { + res = libcmp(strrchr(x->libname, '/') + 1, + strrchr(y->libname, '/') + 1); + } + + return res; +} + +void cache_dolib(const char *dir, const char *so, int libtype) +{ + char fullpath[PATH_MAX]; + liblist_t *new_lib, *cur_lib; + + magic.nlibs++; + sprintf(fullpath, "%s/%s", dir, so); + new_lib = xmalloc(sizeof(liblist_t)); + new_lib->flags = libtype; + new_lib->soname = xstrdup(so); + new_lib->libname = xstrdup(fullpath); + + if (lib_head == NULL || liblistcomp(new_lib, lib_head) > 0) { + new_lib->next = lib_head; + lib_head = new_lib; + } else { + for (cur_lib = lib_head; cur_lib->next != NULL && + liblistcomp(new_lib, cur_lib->next) <= 0; + cur_lib = cur_lib->next) + /* nothing */ ; + new_lib->next = cur_lib->next; + cur_lib->next = new_lib; + } +} + +void cache_write(void) +{ + int cachefd; + int stroffset = 0; + char realcachefile[BUFFER_SIZE]; + char tempfile[BUFFER_SIZE]; + header_t swap_magic; + header_t *magic_ptr; + libentry_t swap_lib; + libentry_t *lib_ptr; + liblist_t *cur_lib; + + if (!magic.nlibs) + return; + + if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) + err(EXIT_FATAL, "can't resolve %s in chroot %s (%s)", + cachefile, chroot_dir, strerror(errno)); + + sprintf(tempfile, "%s~", realcachefile); + + if (unlink(tempfile) && errno != ENOENT) + err(EXIT_FATAL, "can't unlink %s~ (%s)", cachefile, + strerror(errno)); + + if ((cachefd = creat(tempfile, 0644)) < 0) + err(EXIT_FATAL, "can't create %s~ (%s)", cachefile, + strerror(errno)); + + if (byteswap) { + swap_magic = magic; + swap_magic.nlibs = bswap_32(swap_magic.nlibs); + magic_ptr = &swap_magic; + } else { + magic_ptr = &magic; + } + if (write(cachefd, magic_ptr, sizeof(header_t)) != sizeof(header_t)) + err(EXIT_FATAL, "can't write %s~ (%s)", cachefile, + strerror(errno)); + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) { + cur_lib->sooffset = stroffset; + stroffset += strlen(cur_lib->soname) + 1; + cur_lib->liboffset = stroffset; + stroffset += strlen(cur_lib->libname) + 1; + if (byteswap) { + swap_lib.flags = bswap_32(cur_lib->flags); + swap_lib.sooffset = bswap_32(cur_lib->sooffset); + swap_lib.liboffset = bswap_32(cur_lib->liboffset); + lib_ptr = &swap_lib; + } else { + lib_ptr = (libentry_t *) cur_lib; + } + if (write(cachefd, lib_ptr, sizeof(libentry_t)) != + sizeof(libentry_t)) + err(EXIT_FATAL, "can't write %s~ (%s)", cachefile, + strerror(errno)); + } + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) { + if ((size_t)write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1) + != strlen(cur_lib->soname) + 1) + err(EXIT_FATAL, "can't write %s~ (%s)", cachefile, + strerror(errno)); + if ((size_t)write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1) + != strlen(cur_lib->libname) + 1) + err(EXIT_FATAL, "can't write %s~ (%s)", cachefile, + strerror(errno)); + } + + if (close(cachefd)) + err(EXIT_FATAL, "can't close %s~ (%s)", cachefile, + strerror(errno)); + + if (chmod(tempfile, 0644)) + err(EXIT_FATAL, "can't chmod %s~ (%s)", cachefile, + strerror(errno)); + + if (rename(tempfile, realcachefile)) + err(EXIT_FATAL, "can't rename %s~ (%s)", cachefile, + strerror(errno)); +} + +void cache_print(void) +{ + caddr_t c; + struct stat st; + int fd = 0; + char *strs; + header_t *header; + libentry_t *libent; + char realcachefile[BUFFER_SIZE]; + + if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) + err(EXIT_FATAL, "can't resolve %s in chroot %s (%s)", + cachefile, chroot_dir, strerror(errno)); + + if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY)) < 0) + err(EXIT_FATAL, "can't read %s (%s)", cachefile, strerror(errno)); + + c = mmap(0, st.st_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0); + if (c == MAP_FAILED) + err(EXIT_FATAL, "can't map %s (%s)", cachefile, strerror(errno)); + close(fd); + + if (memcmp(((header_t *) c)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) + err(EXIT_FATAL, "%s cache corrupt", cachefile); + + if (memcmp(((header_t *) c)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)) + err(EXIT_FATAL, "wrong cache version - expected %s", + LDSO_CACHE_VER); + + header = (header_t *) c; + libent = (libentry_t *) (c + sizeof(header_t)); + strs = (char *)&libent[header->nlibs]; + + printf("%d libs found in cache `%s' (version %s)\n", + header->nlibs, cachefile, LDSO_CACHE_VER); + + for (fd = 0; fd < header->nlibs; fd++) { + printf("\t%s ", strs + libent[fd].sooffset); + switch (libent[fd].flags & ~LIB_ELF64) { + case LIB_DLL: + printf("(libc4)"); + break; + case LIB_ELF: + printf("(ELF%s)", libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + case LIB_ELF_LIBC0: + printf("(libc0%s)", libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + case LIB_ELF_LIBC5: + case LIB_ELF_LIBC6: + printf("(libc%d%s)", + (libent[fd].flags & ~LIB_ELF64) + 3, + libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + default: + printf("(unknown)"); + break; + } + printf(" => %s\n", strs + libent[fd].liboffset); + } + + munmap(c, st.st_size); +} +#endif + +void usage(void) +{ + fprintf(stderr, +#ifdef __LDSO_CACHE_SUPPORT__ + "ldconfig - updates symlinks and cache for shared libraries\n\n" + "Usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ...\n" + " ldconfig -l [-Dv] lib ...\n" + " ldconfig -p\n\nOptions:\n" +#else + "ldconfig - updates symlinks for shared libraries\n\n" + "Usage: ldconfig [-DvqnX] [-r root] dir ...\n" + " ldconfig -l [-Dv] lib ...\n\nOptions:\n" +#endif + "\t-D:\t\tdebug mode, don't update links\n" + "\t-v:\t\tverbose mode, print things as we go\n" + "\t-q:\t\tquiet mode, don't print warnings\n" + "\t-n:\t\tdon't process standard directories\n" + "\t-N:\t\tdon't update the library cache\n" + "\t-X:\t\tdon't update the library links\n" + "\t-l:\t\tlibrary mode, manually link libraries\n" + "\t-p:\t\tprint the current library cache\n" +#ifdef __LDSO_CACHE_SUPPORT__ + "\t-f conf :\tuse conf instead of %s\n" + "\t-C cache:\tuse cache instead of %s\n" +#endif + "\t-r root :\tfirst, do a chroot to the indicated directory\n" + "\tdir ... :\tdirectories to process\n" +#ifdef __LDSO_CACHE_SUPPORT__ + "\tlib ... :\tlibraries to link\n\n", LDSO_CONF, LDSO_CACHE +#else + "\tlib ... :\tlibraries to link\n\n" +#endif + ); + exit(EXIT_FATAL); +} + +#define DIR_SEP ":, \t\n" +int main(int argc, char **argv) +{ + int i, c; + int nodefault = 0; + char *cp, *dir, *so; + int libtype, islink; + int printcache = 0; +#ifdef __LDSO_CACHE_SUPPORT__ + char *extpath; +#endif + + prog = argv[0]; + opterr = 0; + + while ((c = getopt(argc, argv, "DvqnNXlpf:C:r:")) != EOF) + switch (c) { + case 'D': + debug = 1; /* debug mode */ + nocache = 1; + nolinks = 1; + verbose = 1; + break; + case 'v': + verbose = 1; /* verbose mode */ + break; + case 'q': + if (verbose <= 0) + verbose = -1; /* quiet mode */ + break; + case 'n': + nodefault = 1; /* no default dirs */ + nocache = 1; + break; + case 'N': + nocache = 1; /* don't build cache */ + break; + case 'X': + nolinks = 1; /* don't update links */ + break; + case 'l': + libmode = 1; /* library mode */ + break; + case 'p': + printcache = 1; /* print cache */ + break; + case 'f': +#ifdef __LDSO_CACHE_SUPPORT__ + conffile = optarg; /* alternate conf file */ +#endif + break; + case 'C': +#ifdef __LDSO_CACHE_SUPPORT__ + cachefile = optarg; /* alternate cache file */ +#endif + break; + case 'r': + chroot_dir = optarg; + break; + default: + usage(); + break; + + /* THE REST OF THESE ARE UNDOCUMENTED AND MAY BE REMOVED + IN FUTURE VERSIONS. */ + } + + if (chroot_dir && *chroot_dir) { + if (chroot(chroot_dir) < 0) { + if (chdir(chroot_dir) < 0) + err(EXIT_FATAL, "couldn't chroot to %s (%s)", chroot_dir, strerror(errno)); + chroot_dir = "."; + } else { + if (chdir("/") < 0) + err(EXIT_FATAL, "couldn't chdir to / (%s)", strerror(errno)); + chroot_dir = NULL; + } + } + + /* allow me to introduce myself, hi, my name is ... */ + if (verbose > 0) + printf("%s: uClibc version\n", argv[0]); + + if (printcache) { + /* print the cache -- don't you trust me? */ + cache_print(); + exit(EXIT_OK); + } else if (libmode) { + /* so you want to do things manually, eh? */ + + /* ok, if you're so smart, which libraries do we link? */ + for (i = optind; i < argc; i++) { + /* split into directory and file parts */ + if (!(cp = strrchr(argv[i], '/'))) { + dir = "."; /* no dir, only a filename */ + cp = argv[i]; + } else { + if (cp == argv[i]) + dir = "/"; /* file in root directory */ + else + dir = argv[i]; + *cp++ = '\0'; /* neither of the above */ + } + + /* we'd better do a little bit of checking */ + if ((so = is_shlib(dir, cp, &libtype, &islink, LIB_ANY)) == NULL) + err(EXIT_FATAL, "%s%s%s is not a shared library", + dir, (*dir && strcmp(dir, "/")) ? "/" : "", cp); + + /* so far, so good, maybe he knows what he's doing */ + link_shlib(dir, cp, so); + } + } else { + /* the lazy bum want's us to do all the work for him */ + + /* don't cache dirs on the command line */ + int nocache_save = nocache; + nocache = 1; + + /* OK, which directories should we do? */ + for (i = optind; i < argc; i++) + scan_dir(argv[i]); + + /* restore the desired caching state */ + nocache = nocache_save; + + /* look ma, no defaults */ + if (!nodefault) { + scan_dir(UCLIBC_RUNTIME_PREFIX "lib"); + scan_dir(UCLIBC_RUNTIME_PREFIX "usr/lib"); +#ifndef __LDSO_CACHE_SUPPORT__ + scan_dir(UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"); +#else + /* I guess the defaults aren't good enough */ + if ((extpath = get_extpath())) { + for (cp = strtok(extpath, DIR_SEP); cp; cp = strtok(NULL, DIR_SEP)) { + /* strip trailing slashes */ + int len = strlen(cp); + if (len) + while (cp[--len] == '/' && len) + cp[len] = 0; + /* we do the redundancy check only if cache usage is enabled */ + if (strcmp(UCLIBC_RUNTIME_PREFIX "lib", cp) == 0 + || strcmp(UCLIBC_RUNTIME_PREFIX "usr/lib", cp) == 0) { + if (verbose >= 0) + warnx("You should remove `%s' from `%s'", cp, LDSO_CONF); + continue; + } + scan_dir(cp); + } + free(extpath); + } +#endif + } + + if (!nocache) + cache_write(); + } + + exit(EXIT_OK); +} diff --git a/utils/ldd.c b/utils/ldd.c new file mode 100644 index 0000000..17bab20 --- /dev/null +++ b/utils/ldd.c @@ -0,0 +1,836 @@ +/* vi: set sw=4 ts=4: */ +/* + * A small little ldd implementation for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Several functions in this file (specifically, elf_find_section_type(), + * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from + * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser + * , which is copyright 2000 BitWagon Software LLC + * (GPL2). + * + * Licensed under GPLv2 or later + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bswap.h" +#include "link.h" +#include "dl-defs.h" +/* makefile will include elf.h for us */ + +#ifdef DMALLOC +#include +#endif + +#if defined(__alpha__) +#define MATCH_MACHINE(x) (x == EM_ALPHA) +#define ELFCLASSM ELFCLASS64 +#endif + +#if defined(__arm__) || defined(__thumb__) +#define MATCH_MACHINE(x) (x == EM_ARM) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__avr32__) +#define MATCH_MACHINE(x) (x == EM_AVR32) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__s390__) +#define MATCH_MACHINE(x) (x == EM_S390) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__hppa__) +#define MATCH_MACHINE(x) (x == EM_PARISC) +#if defined(__LP64__) +#define ELFCLASSM ELFCLASS64 +#else +#define ELFCLASSM ELFCLASS32 +#endif +#endif + +#if defined(__i386__) +#ifndef EM_486 +#define MATCH_MACHINE(x) (x == EM_386) +#else +#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) +#endif +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__ia64__) +#define MATCH_MACHINE(x) (x == EM_IA_64) +#define ELFCLASSM ELFCLASS64 +#endif + +#if defined(__mc68000__) +#define MATCH_MACHINE(x) (x == EM_68K) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__mips__) +#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__powerpc64__) +#define MATCH_MACHINE(x) (x == EM_PPC64) +#define ELFCLASSM ELFCLASS64 +#elif defined(__powerpc__) +#define MATCH_MACHINE(x) (x == EM_PPC) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__sh__) +#define MATCH_MACHINE(x) (x == EM_SH) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__v850e__) +#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__sparc__) +#define MATCH_MACHINE(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__cris__) +#define MATCH_MACHINE(x) (x == EM_CRIS) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__x86_64__) +#define MATCH_MACHINE(x) (x == EM_X86_64) +#define ELFCLASSM ELFCLASS64 +#endif + +#ifndef MATCH_MACHINE +# ifdef __linux__ +# include +# endif +# ifdef ELF_ARCH +# define MATCH_MACHINE(x) (x == ELF_ARCH) +# endif +# ifdef ELF_CLASS +# define ELFCLASSM ELF_CLASS +# endif +#endif +#ifndef MATCH_MACHINE +# warning "You really should add a MATCH_MACHINE() macro for your architecture" +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define ELFDATAM ELFDATA2LSB +#elif __BYTE_ORDER == __BIG_ENDIAN +#define ELFDATAM ELFDATA2MSB +#endif + +#ifndef UCLIBC_RUNTIME_PREFIX +# define UCLIBC_RUNTIME_PREFIX "/" +#endif + +struct library { + char *name; + int resolved; + char *path; + struct library *next; +}; +static struct library *lib_list = NULL; +static char not_found[] = "not found"; +static char *interp_name = NULL; +static char *interp_dir = NULL; +static int byteswap; +static int interpreter_already_found = 0; + +static __inline__ uint32_t byteswap32_to_host(uint32_t value) +{ + if (byteswap == 1) { + return (bswap_32(value)); + } else { + return (value); + } +} +static __inline__ uint64_t byteswap64_to_host(uint64_t value) +{ + if (byteswap == 1) { + return (bswap_64(value)); + } else { + return (value); + } +} + +#if ELFCLASSM == ELFCLASS32 +# define byteswap_to_host(x) byteswap32_to_host(x) +#else +# define byteswap_to_host(x) byteswap64_to_host(x) +#endif + +static ElfW(Shdr) *elf_find_section_type(uint32_t key, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Shdr) *shdr; + shdr = (ElfW(Shdr) *) (ehdr->e_shoff + (char *)ehdr); + for (j = ehdr->e_shnum; --j >= 0; ++shdr) { + if (key == byteswap32_to_host(shdr->sh_type)) { + return shdr; + } + } + return NULL; +} + +static ElfW(Phdr) *elf_find_phdr_type(uint32_t type, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Phdr) *phdr = (ElfW(Phdr) *) (ehdr->e_phoff + (char *)ehdr); + for (j = ehdr->e_phnum; --j >= 0; ++phdr) { + if (type == byteswap32_to_host(phdr->p_type)) { + return phdr; + } + } + return NULL; +} + +/* Returns value if return_val==1, ptr otherwise */ +static void *elf_find_dynamic(int64_t const key, ElfW(Dyn) *dynp, + ElfW(Ehdr) *ehdr, int return_val) +{ + ElfW(Phdr) *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); + unsigned tx_reloc = byteswap_to_host(pt_text->p_vaddr) - byteswap_to_host(pt_text->p_offset); + for (; DT_NULL != byteswap_to_host(dynp->d_tag); ++dynp) { + if (key == byteswap_to_host(dynp->d_tag)) { + if (return_val == 1) + return (void *)byteswap_to_host(dynp->d_un.d_val); + else + return (void *)(byteswap_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr); + } + } + return NULL; +} + +static char *elf_find_rpath(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic) +{ + ElfW(Dyn) *dyns; + + for (dyns = dynamic; byteswap_to_host(dyns->d_tag) != DT_NULL; ++dyns) { + if (DT_RPATH == byteswap_to_host(dyns->d_tag)) { + char *strtab; + strtab = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); + return ((char *)strtab + byteswap_to_host(dyns->d_un.d_val)); + } + } + return NULL; +} + +int check_elf_header(ElfW(Ehdr) *const ehdr) +{ + if (!ehdr || strncmp((char *)ehdr, ELFMAG, SELFMAG) != 0 || + ehdr->e_ident[EI_CLASS] != ELFCLASSM || + ehdr->e_ident[EI_VERSION] != EV_CURRENT) + { + return 1; + } + + /* Check if the target endianness matches the host's endianness */ + byteswap = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2MSB) { + /* Ick -- we will have to byte-swap everything */ + byteswap = 1; + } +#elif __BYTE_ORDER == __BIG_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2LSB) { + /* Ick -- we will have to byte-swap everything */ + byteswap = 1; + } +#else +#error Unknown host byte order! +#endif + + /* Be vary lazy, and only byteswap the stuff we use */ + if (byteswap == 1) { + ehdr->e_type = bswap_16(ehdr->e_type); + ehdr->e_phoff = byteswap_to_host(ehdr->e_phoff); + ehdr->e_shoff = byteswap_to_host(ehdr->e_shoff); + ehdr->e_phnum = bswap_16(ehdr->e_phnum); + ehdr->e_shnum = bswap_16(ehdr->e_shnum); + } + + return 0; +} + +#ifdef __LDSO_CACHE_SUPPORT__ +static caddr_t cache_addr = NULL; +static size_t cache_size = 0; + +int map_cache(void) +{ + int fd; + struct stat st; + header_t *header; + libentry_t *libent; + int i, strtabsize; + + if (cache_addr == (caddr_t) - 1) + return -1; + else if (cache_addr != NULL) + return 0; + + if (stat(LDSO_CACHE, &st) || (fd = open(LDSO_CACHE, O_RDONLY, 0)) < 0) { + fprintf(stderr, "ldd: can't open cache '%s'\n", LDSO_CACHE); + cache_addr = (caddr_t) - 1; /* so we won't try again */ + return -1; + } + + cache_size = st.st_size; + cache_addr = mmap(0, cache_size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + if (cache_addr == MAP_FAILED) { + fprintf(stderr, "ldd: can't map cache '%s'\n", LDSO_CACHE); + return -1; + } + + header = (header_t *) cache_addr; + + if (cache_size < sizeof(header_t) + || memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN) + || memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN) + || cache_size < (sizeof(header_t) + header->nlibs * sizeof(libentry_t)) + || cache_addr[cache_size - 1] != '\0') + { + fprintf(stderr, "ldd: cache '%s' is corrupt\n", LDSO_CACHE); + goto fail; + } + + strtabsize = cache_size - sizeof(header_t) - header->nlibs * sizeof(libentry_t); + libent = (libentry_t *) & header[1]; + + for (i = 0; i < header->nlibs; i++) { + if (libent[i].sooffset >= strtabsize || libent[i].liboffset >= strtabsize) { + fprintf(stderr, "ldd: cache '%s' is corrupt\n", LDSO_CACHE); + goto fail; + } + } + + return 0; + +fail: + munmap(cache_addr, cache_size); + cache_addr = (caddr_t) - 1; + return -1; +} + +int unmap_cache(void) +{ + if (cache_addr == NULL || cache_addr == (caddr_t) - 1) + return -1; + +#if 1 + munmap(cache_addr, cache_size); + cache_addr = NULL; +#endif + + return 0; +} +#else +static __inline__ void map_cache(void) +{ +} +static __inline__ void unmap_cache(void) +{ +} +#endif + +/* This function's behavior must exactly match that + * in uClibc/ldso/ldso/dl-elf.c */ +static void search_for_named_library(char *name, char *result, + const char *path_list) +{ + int i, count = 1; + char *path, *path_n; + struct stat filestat; + + /* We need a writable copy of this string */ + path = strdup(path_list); + if (!path) { + fprintf(stderr, "Out of memory!\n"); + exit(EXIT_FAILURE); + } + /* Eliminate all double //s */ + path_n = path; + while ((path_n = strstr(path_n, "//"))) { + i = strlen(path_n); + memmove(path_n, path_n + 1, i - 1); + *(path_n + i - 1) = '\0'; + } + + /* Replace colons with zeros in path_list and count them */ + for (i = strlen(path); i > 0; i--) { + if (path[i] == ':') { + path[i] = 0; + count++; + } + } + path_n = path; + for (i = 0; i < count; i++) { + strcpy(result, path_n); + strcat(result, "/"); + strcat(result, name); + if (stat(result, &filestat) == 0 && filestat.st_mode & S_IRUSR) { + free(path); + return; + } + path_n += (strlen(path_n) + 1); + } + free(path); + *result = '\0'; +} + +void locate_library_file(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, int is_suid, + struct library *lib) +{ + char *buf; + char *path; + struct stat filestat; + + /* If this is a fully resolved name, our job is easy */ + if (stat(lib->name, &filestat) == 0) { + lib->path = strdup(lib->name); + return; + } + + /* We need some elbow room here. Make some room... */ + buf = malloc(1024); + if (!buf) { + fprintf(stderr, "Out of memory!\n"); + exit(EXIT_FAILURE); + } + + /* This function must match the behavior of _dl_load_shared_library + * in readelflib1.c or things won't work out as expected... */ + + /* The ABI specifies that RPATH is searched first, so do that now. */ + path = elf_find_rpath(ehdr, dynamic); + if (path) { + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + return; + } + } + + /* Next check LD_{ELF_}LIBRARY_PATH if specified and allowed. + * Since this app doesn't actually run an executable I will skip + * the suid check, and just use LD_{ELF_}LIBRARY_PATH if set */ + if (is_suid == 1) + path = NULL; + else + path = getenv("LD_LIBRARY_PATH"); + if (path) { + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + return; + } + } +#ifdef __LDSO_CACHE_SUPPORT__ + if (cache_addr != NULL && cache_addr != (caddr_t) - 1) { + int i; + header_t *header = (header_t *) cache_addr; + libentry_t *libent = (libentry_t *) & header[1]; + char *strs = (char *)&libent[header->nlibs]; + + for (i = 0; i < header->nlibs; i++) { + if ((libent[i].flags == LIB_ELF || + libent[i].flags == LIB_ELF_LIBC0 || + libent[i].flags == LIB_ELF_LIBC5) && + strcmp(lib->name, strs + libent[i].sooffset) == 0) + { + lib->path = strdup(strs + libent[i].liboffset); + return; + } + } + } +#endif + + /* Next look for libraries wherever the shared library + * loader was installed -- this is usually where we + * should find things... */ + if (interp_dir) { + search_for_named_library(lib->name, buf, interp_dir); + if (*buf != '\0') { + lib->path = buf; + return; + } + } + + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/ldso/dl-elf.c */ + path = UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" +#ifndef __LDSO_CACHE_SUPPORT__ + ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" +#endif + ; + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + } else { + free(buf); + lib->path = not_found; + } +} + +static int add_library(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, int is_setuid, char *s) +{ + char *tmp, *tmp1, *tmp2; + struct library *cur, *newlib = lib_list; + + if (!s || !strlen(s)) + return 1; + + tmp = s; + while (*tmp) { + if (*tmp == '/') + s = tmp + 1; + tmp++; + } + + /* We add ldso elsewhere */ + if (interpreter_already_found && (tmp = strrchr(interp_name, '/')) != NULL) { + int len = strlen(interp_dir); + if (strcmp(s, interp_name + 1 + len) == 0) + return 1; + } + + for (cur = lib_list; cur; cur = cur->next) { + /* Check if this library is already in the list */ + tmp1 = tmp2 = cur->name; + while (*tmp1) { + if (*tmp1 == '/') + tmp2 = tmp1 + 1; + tmp1++; + } + if (strcmp(tmp2, s) == 0) { + /*printf("find_elf_interpreter is skipping '%s' (already in list)\n", cur->name); */ + return 0; + } + } + + /* Ok, this lib needs to be added to the list */ + newlib = malloc(sizeof(struct library)); + if (!newlib) + return 1; + newlib->name = malloc(strlen(s) + 1); + strcpy(newlib->name, s); + newlib->resolved = 0; + newlib->path = NULL; + newlib->next = NULL; + + /* Now try and locate where this library might be living... */ + locate_library_file(ehdr, dynamic, is_setuid, newlib); + + /*printf("add_library is adding '%s' to '%s'\n", newlib->name, newlib->path); */ + if (!lib_list) { + lib_list = newlib; + } else { + for (cur = lib_list; cur->next; cur = cur->next) ; /* nothing */ + cur->next = newlib; + } + return 0; +} + +static void find_needed_libraries(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, int is_setuid) +{ + ElfW(Dyn) *dyns; + + for (dyns = dynamic; byteswap_to_host(dyns->d_tag) != DT_NULL; ++dyns) { + if (DT_NEEDED == byteswap_to_host(dyns->d_tag)) { + char *strtab; + strtab = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); + add_library(ehdr, dynamic, is_setuid, (char *)strtab + byteswap_to_host(dyns->d_un.d_val)); + } + } +} + +static struct library *find_elf_interpreter(ElfW(Ehdr) *ehdr) +{ + ElfW(Phdr) *phdr; + + if (interpreter_already_found == 1) + return NULL; + phdr = elf_find_phdr_type(PT_INTERP, ehdr); + if (phdr) { + struct library *cur, *newlib = NULL; + char *s = (char *)ehdr + byteswap_to_host(phdr->p_offset); + + char *tmp, *tmp1; + interp_name = strdup(s); + interp_dir = strdup(s); + tmp = strrchr(interp_dir, '/'); + if (*tmp) + *tmp = '\0'; + else { + free(interp_dir); + interp_dir = interp_name; + } + tmp1 = tmp = s; + while (*tmp) { + if (*tmp == '/') + tmp1 = tmp + 1; + tmp++; + } + for (cur = lib_list; cur; cur = cur->next) { + /* Check if this library is already in the list */ + if (strcmp(cur->name, tmp1) == 0) { + /*printf("find_elf_interpreter is replacing '%s' (already in list)\n", cur->name); */ + newlib = cur; + free(newlib->name); + if (newlib->path != not_found) { + free(newlib->path); + } + newlib->name = NULL; + newlib->path = NULL; + return NULL; + } + } + if (newlib == NULL) + newlib = malloc(sizeof(struct library)); + if (!newlib) + return NULL; + newlib->name = malloc(strlen(s) + 1); + strcpy(newlib->name, s); + newlib->path = strdup(newlib->name); + newlib->resolved = 1; + newlib->next = NULL; + +#if 0 + /*printf("find_elf_interpreter is adding '%s' to '%s'\n", newlib->name, newlib->path); */ + if (!lib_list) { + lib_list = newlib; + } else { + for (cur = lib_list; cur->next; cur = cur->next) ; /* nothing */ + cur->next = newlib; + } +#endif + interpreter_already_found = 1; + return newlib; + } + return NULL; +} + +/* map the .so, and locate interesting pieces */ +/* +#warning "There may be two warnings here about vfork() clobbering, ignore them" +*/ +int find_dependancies(char *filename) +{ + int is_suid = 0; + FILE *thefile; + struct library *interp; + struct stat statbuf; + ElfW(Ehdr) *ehdr = NULL; + ElfW(Shdr) *dynsec = NULL; + ElfW(Dyn) *dynamic = NULL; + + if (filename == not_found) + return 0; + + if (!filename) { + fprintf(stderr, "No filename specified.\n"); + return -1; + } + if (!(thefile = fopen(filename, "r"))) { + perror(filename); + return -1; + } + if (fstat(fileno(thefile), &statbuf) < 0) { + perror(filename); + fclose(thefile); + return -1; + } + + if ((size_t) statbuf.st_size < sizeof(ElfW(Ehdr))) + goto foo; + + if (!S_ISREG(statbuf.st_mode)) + goto foo; + + /* mmap the file to make reading stuff from it effortless */ + ehdr = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0); + if (ehdr == MAP_FAILED) { + fclose(thefile); + fprintf(stderr, "Out of memory!\n"); + return -1; + } + +foo: + fclose(thefile); + + /* Check if this looks like a legit ELF file */ + if (check_elf_header(ehdr)) { + fprintf(stderr, "%s: not an ELF file.\n", filename); + return -1; + } + /* Check if this is the right kind of ELF file */ + if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) { + fprintf(stderr, "%s: not a dynamic executable\n", filename); + return -1; + } + if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) { + if (statbuf.st_mode & S_ISUID) + is_suid = 1; + if ((statbuf.st_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) + is_suid = 1; + /* FIXME */ + if (is_suid) + fprintf(stderr, "%s: is setuid\n", filename); + } + + interpreter_already_found = 0; + interp = find_elf_interpreter(ehdr); + +#ifdef __LDSO_LDD_SUPPORT__ + if (interp + && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) + && ehdr->e_ident[EI_CLASS] == ELFCLASSM + && ehdr->e_ident[EI_DATA] == ELFDATAM + && ehdr->e_ident[EI_VERSION] == EV_CURRENT + && MATCH_MACHINE(ehdr->e_machine)) + { + struct stat statbuf; + if (stat(interp->path, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + pid_t pid; + int status; + static const char *const environment[] = { + "PATH=/usr/bin:/bin:/usr/sbin:/sbin", + "SHELL=/bin/sh", + "LD_TRACE_LOADED_OBJECTS=1", + NULL + }; + + if ((pid = vfork()) == 0) { + /* Cool, it looks like we should be able to actually + * run this puppy. Do so now... */ + execle(filename, filename, NULL, environment); + _exit(0xdead); + } + + /* Wait till it returns */ + waitpid(pid, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 1; + } + + /* If the exec failed, we fall through to trying to find + * all the needed libraries ourselves by rummaging about + * in the ELF headers... */ + } + } +#endif + + dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); + if (dynsec) { + dynamic = (ElfW(Dyn) *) (byteswap_to_host(dynsec->sh_offset) + (char *)ehdr); + find_needed_libraries(ehdr, dynamic, is_suid); + } + + return 0; +} + +int main(int argc, char **argv) +{ + int multi = 0; + int got_em_all = 1; + char *filename = NULL; + struct library *cur; + + if (argc < 2) { + fprintf(stderr, "ldd: missing file arguments\n" + "Try `ldd --help' for more information.\n"); + exit(EXIT_FAILURE); + } + if (argc > 2) + multi++; + + while (--argc > 0) { + ++argv; + + if (strcmp(*argv, "--") == 0) { + /* Ignore "--" */ + continue; + } + + if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) { + fprintf(stderr, "Usage: ldd [OPTION]... FILE...\n" + "\t--help\t\tprint this help and exit\n"); + exit(EXIT_SUCCESS); + } + + filename = *argv; + if (!filename) { + fprintf(stderr, "No filename specified.\n"); + exit(EXIT_FAILURE); + } + + if (multi) { + printf("%s:\n", *argv); + } + + map_cache(); + + if (find_dependancies(filename) != 0) + continue; + + while (got_em_all) { + got_em_all = 0; + /* Keep walking the list till everybody is resolved */ + for (cur = lib_list; cur; cur = cur->next) { + if (cur->resolved == 0 && cur->path) { + got_em_all = 1; + printf("checking sub-depends for '%s'\n", cur->path); + find_dependancies(cur->path); + cur->resolved = 1; + } + } + } + + unmap_cache(); + + /* Print the list */ + got_em_all = 0; + for (cur = lib_list; cur; cur = cur->next) { + got_em_all = 1; + printf("\t%s => %s (0x00000000)\n", cur->name, cur->path); + } + if (interp_name && interpreter_already_found == 1) + printf("\t%s => %s (0x00000000)\n", interp_name, interp_name); + else + printf("\tnot a dynamic executable\n"); + + for (cur = lib_list; cur; cur = cur->next) { + free(cur->name); + cur->name = NULL; + if (cur->path && cur->path != not_found) { + free(cur->path); + cur->path = NULL; + } + } + lib_list = NULL; + } + + return 0; +} diff --git a/utils/readelf.c b/utils/readelf.c new file mode 100644 index 0000000..2af4b5c --- /dev/null +++ b/utils/readelf.c @@ -0,0 +1,363 @@ +/* vi: set sw=4 ts=4: */ +/* + * A small little readelf implementation for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Several functions in this file (specifically, elf_find_section_type(), + * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from + * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser + * , which is copyright 2000 BitWagon Software LLC + * (GPL2). + * + * Licensed under GPLv2 or later + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bswap.h" +#include "link.h" +/* makefile will include elf.h for us */ + +static int byteswap; +static __inline__ uint32_t byteswap32_to_host(uint32_t value) +{ + if (byteswap==1) { + return(bswap_32(value)); + } else { + return(value); + } +} +static __inline__ uint64_t byteswap64_to_host(uint64_t value) +{ + if (byteswap==1) { + return(bswap_64(value)); + } else { + return(value); + } +} +#if __WORDSIZE == 64 +# define byteswap_to_host(x) byteswap64_to_host(x) +#else +# define byteswap_to_host(x) byteswap32_to_host(x) +#endif + +static ElfW(Shdr) * elf_find_section_type( uint32_t key, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Shdr) *shdr = (ElfW(Shdr) *)(ehdr->e_shoff + (char *)ehdr); + for (j = ehdr->e_shnum; --j>=0; ++shdr) { + if (key==byteswap32_to_host(shdr->sh_type)) { + return shdr; + } + } + return NULL; +} + +static ElfW(Phdr) * elf_find_phdr_type( uint32_t type, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Phdr) *phdr = (ElfW(Phdr) *)(ehdr->e_phoff + (char *)ehdr); + for (j = ehdr->e_phnum; --j>=0; ++phdr) { + if (type==byteswap32_to_host(phdr->p_type)) { + return phdr; + } + } + return NULL; +} + +/* Returns value if return_val==1, ptr otherwise */ +static void * elf_find_dynamic( int64_t const key, ElfW(Dyn) *dynp, + ElfW(Ehdr) *ehdr, int return_val) +{ + ElfW(Phdr) *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); + ElfW(Addr) tx_reloc = byteswap_to_host(pt_text->p_vaddr) - byteswap_to_host(pt_text->p_offset); + for (; DT_NULL!=byteswap_to_host(dynp->d_tag); ++dynp) { + if (key == byteswap_to_host(dynp->d_tag)) { + if (return_val == 1) + return (void *)byteswap_to_host(dynp->d_un.d_val); + else + return (void *)(byteswap_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr ); + } + } + return NULL; +} + +static int check_elf_header(ElfW(Ehdr) *const ehdr) +{ + if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 || + (ehdr->e_ident[EI_CLASS] != ELFCLASS32 && + ehdr->e_ident[EI_CLASS] != ELFCLASS64) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT) + { + return 1; + } + + /* Check if the target endianness matches the host's endianness */ + byteswap = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2MSB) { + /* Ick -- we will have to byte-swap everything */ + byteswap = 1; + } +#elif __BYTE_ORDER == __BIG_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2LSB) { + byteswap = 1; + } +#else +#error Unknown host byte order! +#endif + /* Be vary lazy, and only byteswap the stuff we use */ + if (byteswap==1) { + ehdr->e_type=bswap_16(ehdr->e_type); + ehdr->e_machine=bswap_16(ehdr->e_machine); + ehdr->e_phoff=byteswap_to_host(ehdr->e_phoff); + ehdr->e_shoff=byteswap_to_host(ehdr->e_shoff); + ehdr->e_phnum=bswap_16(ehdr->e_phnum); + ehdr->e_shnum=bswap_16(ehdr->e_shnum); + } + return 0; +} + + +static void describe_elf_hdr(ElfW(Ehdr)* ehdr) +{ + char *tmp, *tmp1; + + switch (ehdr->e_type) { + case ET_NONE: tmp = "None"; tmp1 = "NONE"; break; + case ET_REL: tmp = "Relocatable File"; tmp1 = "REL"; break; + case ET_EXEC: tmp = "Executable file"; tmp1 = "EXEC"; break; + case ET_DYN: tmp = "Shared object file"; tmp1 = "DYN"; break; + case ET_CORE: tmp = "Core file"; tmp1 = "CORE"; break; + default: + tmp = tmp1 = "Unknown"; + } + printf( "Type:\t\t%s (%s)\n", tmp1, tmp); + + switch (ehdr->e_machine) { + case EM_NONE: tmp="No machine"; break; + case EM_M32: tmp="AT&T WE 32100"; break; + case EM_SPARC: tmp="SUN SPARC"; break; + case EM_386: tmp="Intel 80386"; break; + case EM_68K: tmp="Motorola m68k family"; break; + case EM_88K: tmp="Motorola m88k family"; break; + case EM_486: tmp="Intel 80486"; break; + case EM_860: tmp="Intel 80860"; break; + case EM_MIPS: tmp="MIPS R3000 big-endian"; break; + case EM_S370: tmp="IBM System/370"; break; + case EM_MIPS_RS3_LE: tmp="MIPS R3000 little-endian"; break; + case EM_OLD_SPARCV9: tmp="Sparc v9 (old)"; break; + case EM_PARISC: tmp="HPPA"; break; + /*case EM_PPC_OLD: tmp="Power PC (old)"; break; conflicts with EM_VPP500 */ + case EM_SPARC32PLUS: tmp="Sun's v8plus"; break; + case EM_960: tmp="Intel 80960"; break; + case EM_PPC: tmp="PowerPC"; break; + case EM_PPC64: tmp="PowerPC 64-bit"; break; + case EM_V800: tmp="NEC V800 series"; break; + case EM_FR20: tmp="Fujitsu FR20"; break; + case EM_RH32: tmp="TRW RH-32"; break; + case EM_MCORE: tmp="MCORE"; break; + case EM_ARM: tmp="ARM"; break; + case EM_FAKE_ALPHA: tmp="Digital Alpha"; break; + case EM_SH: tmp="Renesas SH"; break; + case EM_SPARCV9: tmp="SPARC v9 64-bit"; break; + case EM_TRICORE: tmp="Siemens Tricore"; break; + case EM_ARC: tmp="Argonaut RISC Core"; break; + case EM_H8_300: tmp="Renesas H8/300"; break; + case EM_H8_300H: tmp="Renesas H8/300H"; break; + case EM_H8S: tmp="Renesas H8S"; break; + case EM_H8_500: tmp="Renesas H8/500"; break; + case EM_IA_64: tmp="Intel Merced"; break; + case EM_MIPS_X: tmp="Stanford MIPS-X"; break; + case EM_COLDFIRE: tmp="Motorola Coldfire"; break; + case EM_68HC12: tmp="Motorola M68HC12"; break; + case EM_ALPHA: tmp="Alpha"; break; + case EM_CYGNUS_D10V: + case EM_D10V: tmp="Mitsubishi D10V"; break; + case EM_CYGNUS_D30V: + case EM_D30V: tmp="Mitsubishi D30V"; break; + case EM_CYGNUS_M32R: + case EM_M32R: tmp="Renesas M32R (formerly Mitsubishi M32r)"; break; + case EM_CYGNUS_V850: + case EM_V850: tmp="NEC v850"; break; + case EM_CYGNUS_MN10300: + case EM_MN10300: tmp="Matsushita MN10300"; break; + case EM_CYGNUS_MN10200: + case EM_MN10200: tmp="Matsushita MN10200"; break; + case EM_CYGNUS_FR30: + case EM_FR30: tmp="Fujitsu FR30"; break; + case EM_CYGNUS_FRV: + case EM_PJ_OLD: + case EM_PJ: tmp="picoJava"; break; + case EM_MMA: tmp="Fujitsu MMA Multimedia Accelerator"; break; + case EM_PCP: tmp="Siemens PCP"; break; + case EM_NCPU: tmp="Sony nCPU embeeded RISC"; break; + case EM_NDR1: tmp="Denso NDR1 microprocessor"; break; + case EM_STARCORE: tmp="Motorola Start*Core processor"; break; + case EM_ME16: tmp="Toyota ME16 processor"; break; + case EM_ST100: tmp="STMicroelectronic ST100 processor"; break; + case EM_TINYJ: tmp="Advanced Logic Corp. Tinyj emb.fam"; break; + case EM_FX66: tmp="Siemens FX66 microcontroller"; break; + case EM_ST9PLUS: tmp="STMicroelectronics ST9+ 8/16 mc"; break; + case EM_ST7: tmp="STmicroelectronics ST7 8 bit mc"; break; + case EM_68HC16: tmp="Motorola MC68HC16 microcontroller"; break; + case EM_68HC11: tmp="Motorola MC68HC11 microcontroller"; break; + case EM_68HC08: tmp="Motorola MC68HC08 microcontroller"; break; + case EM_68HC05: tmp="Motorola MC68HC05 microcontroller"; break; + case EM_SVX: tmp="Silicon Graphics SVx"; break; + case EM_ST19: tmp="STMicroelectronics ST19 8 bit mc"; break; + case EM_VAX: tmp="Digital VAX"; break; + case EM_AVR_OLD: + case EM_AVR: tmp="Atmel AVR 8-bit microcontroller"; break; + case EM_CRIS: tmp="Axis Communications 32-bit embedded processor"; break; + case EM_JAVELIN: tmp="Infineon Technologies 32-bit embedded processor"; break; + case EM_FIREPATH: tmp="Element 14 64-bit DSP Processor"; break; + case EM_ZSP: tmp="LSI Logic 16-bit DSP Processor"; break; + case EM_MMIX: tmp="Donald Knuth's educational 64-bit processor"; break; + case EM_HUANY: tmp="Harvard University machine-independent object files"; break; + case EM_PRISM: tmp="SiTera Prism"; break; + case EM_X86_64: tmp="AMD x86-64 architecture"; break; + case EM_S390_OLD: + case EM_S390: tmp="IBM S390"; break; + case EM_XSTORMY16: tmp="Sanyo Xstormy16 CPU core"; break; + case EM_OPENRISC: + case EM_OR32: tmp="OpenRISC"; break; + case EM_CRX: tmp="National Semiconductor CRX microprocessor"; break; + case EM_DLX: tmp="OpenDLX"; break; + case EM_IP2K_OLD: + case EM_IP2K: tmp="Ubicom IP2xxx 8-bit microcontrollers"; break; + case EM_IQ2000: tmp="Vitesse IQ2000"; break; + case EM_XTENSA_OLD: + case EM_XTENSA: tmp="Tensilica Xtensa Processor"; break; + case EM_M32C: tmp="Renesas M32c"; break; + case EM_MT: tmp="Morpho Techologies MT processor"; break; + case EM_BLACKFIN: tmp="Analog Devices Blackfin"; break; + case EM_NIOS32: tmp="Altera Nios 32"; break; + case EM_ALTERA_NIOS2: tmp="Altera Nios II"; break; + case EM_VPP500: tmp="Fujitsu VPP500"; break; + case EM_PDSP: tmp="Sony DSP Processor"; break; + default: tmp="unknown"; + } + printf( "Machine:\t%s\n", tmp); + + switch (ehdr->e_ident[EI_CLASS]) { + case ELFCLASSNONE: tmp = "Invalid class"; break; + case ELFCLASS32: tmp = "ELF32"; break; + case ELFCLASS64: tmp = "ELF64"; break; + default: tmp = "Unknown"; + } + printf( "Class:\t\t%s\n", tmp); + + switch (ehdr->e_ident[EI_DATA]) { + case ELFDATANONE: tmp = "Invalid data encoding"; break; + case ELFDATA2LSB: tmp = "2's complement, little endian"; break; + case ELFDATA2MSB: tmp = "2's complement, big endian"; break; + default: tmp = "Unknown"; + } + printf( "Data:\t\t%s\n", tmp); + + printf( "Version:\t%d %s\n", ehdr->e_ident[EI_VERSION], + (ehdr->e_ident[EI_VERSION]==EV_CURRENT)? + "(current)" : "(unknown: %lx)"); + + switch (ehdr->e_ident[EI_OSABI]) { + case ELFOSABI_SYSV: tmp ="UNIX - System V"; break; + case ELFOSABI_HPUX: tmp ="UNIX - HP-UX"; break; + case ELFOSABI_NETBSD: tmp ="UNIX - NetBSD"; break; + case ELFOSABI_LINUX: tmp ="UNIX - Linux"; break; + case ELFOSABI_HURD: tmp ="GNU/Hurd"; break; + case ELFOSABI_SOLARIS: tmp ="UNIX - Solaris"; break; + case ELFOSABI_AIX: tmp ="UNIX - AIX"; break; + case ELFOSABI_IRIX: tmp ="UNIX - IRIX"; break; + case ELFOSABI_FREEBSD: tmp ="UNIX - FreeBSD"; break; + case ELFOSABI_TRU64: tmp ="UNIX - TRU64"; break; + case ELFOSABI_MODESTO: tmp ="Novell - Modesto"; break; + case ELFOSABI_OPENBSD: tmp ="UNIX - OpenBSD"; break; + case ELFOSABI_STANDALONE: tmp ="Standalone App"; break; + case ELFOSABI_ARM: tmp ="ARM"; break; + default: tmp = "Unknown"; + } + printf( "OS/ABI:\t\t%s\n", tmp); + + printf( "ABI Version:\t%d\n", ehdr->e_ident[EI_ABIVERSION]); +} + +static void list_needed_libraries(ElfW(Dyn)* dynamic, char *strtab) +{ + ElfW(Dyn) *dyns; + + printf("Dependancies:\n"); + for (dyns=dynamic; byteswap_to_host(dyns->d_tag)!=DT_NULL; ++dyns) { + if (dyns->d_tag == DT_NEEDED) { + printf("\t%s\n", (char*)strtab + byteswap_to_host(dyns->d_un.d_val)); + } + } +} + +static void describe_elf_interpreter(ElfW(Ehdr)* ehdr) +{ + ElfW(Phdr) *phdr; + phdr = elf_find_phdr_type(PT_INTERP, ehdr); + if (phdr) { + printf("Interpreter:\t%s\n", (char*)ehdr + byteswap_to_host(phdr->p_offset)); + } +} + +int main( int argc, char** argv) +{ + /* map the .so, and locate interesting pieces */ + char *dynstr; + char *thefilename = argv[1]; + FILE *thefile; + struct stat statbuf; + ElfW(Ehdr) *ehdr = 0; + ElfW(Shdr) *dynsec; + ElfW(Dyn) *dynamic; + + if (argc < 2 || !thefilename) { + fprintf(stderr, "No filename specified.\n"); + exit(EXIT_FAILURE); + } + if (!(thefile = fopen(thefilename, "r"))) { + perror(thefilename); + exit(EXIT_FAILURE); + } + if (fstat(fileno(thefile), &statbuf) < 0) { + perror(thefilename); + exit(EXIT_FAILURE); + } + + if ((size_t)statbuf.st_size < sizeof(ElfW(Ehdr))) + goto foo; + + /* mmap the file to make reading stuff from it effortless */ + ehdr = (ElfW(Ehdr) *)mmap(0, statbuf.st_size, + PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0); + +foo: + /* Check if this looks legit */ + if (check_elf_header(ehdr)) { + fprintf(stderr, "This does not appear to be an ELF file.\n"); + exit(EXIT_FAILURE); + } + describe_elf_hdr(ehdr); + describe_elf_interpreter(ehdr); + + dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); + if (dynsec) { + dynamic = (ElfW(Dyn)*)(byteswap_to_host(dynsec->sh_offset) + (char *)ehdr); + dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); + list_needed_libraries(dynamic, dynstr); + } + + return 0; +} diff --git a/utils/readsoname2.c b/utils/readsoname2.c new file mode 100644 index 0000000..6a9f007 --- /dev/null +++ b/utils/readsoname2.c @@ -0,0 +1,143 @@ +char *readsonameXX(char *name, FILE *infile, int expected_type, int *type) +{ + ElfW(Ehdr) *epnt; + ElfW(Phdr) *ppnt; + unsigned int i, j; + char *header; + ElfW(Addr) dynamic_addr = 0; + ElfW(Addr) dynamic_size = 0; + unsigned long page_size = getpagesize(); + ElfW(Addr) strtab_val = 0; + ElfW(Addr) needed_val; + ElfW(Addr) loadaddr = -1; + ElfW(Dyn) *dpnt; + struct stat st; + char *needed; + char *soname = NULL; + int multi_libcs = 0; + + if (expected_type == LIB_DLL) { + warn("%s does not match type specified for directory!", name); + expected_type = LIB_ANY; + } + + *type = LIB_ELF; + + if (fstat(fileno(infile), &st)) + return NULL; + header = + mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + fileno(infile), 0); + if (header == (caddr_t) - 1) + return NULL; + + epnt = (ElfW(Ehdr) *) header; + if ((char *)(epnt + 1) > (char *)(header + st.st_size)) + goto skip; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0; +#elif __BYTE_ORDER == __BIG_ENDIAN + byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0; +#else +#error Unknown host byte order! +#endif + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap == 1) { + epnt->e_phoff = bswap_32(epnt->e_phoff); + epnt->e_phnum = bswap_16(epnt->e_phnum); + } + + ppnt = (ElfW(Phdr) *) & header[epnt->e_phoff]; + if ((char *)ppnt < (char *)header || + (char *)(ppnt + epnt->e_phnum) > (char *)(header + st.st_size)) + goto skip; + + for (i = 0; i < epnt->e_phnum; i++) { + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap == 1) { + ppnt->p_type = bswap_32(ppnt->p_type); + ppnt->p_vaddr = bswap_32(ppnt->p_vaddr); + ppnt->p_offset = bswap_32(ppnt->p_offset); + ppnt->p_filesz = bswap_32(ppnt->p_filesz); + } + + if (loadaddr == (ElfW(Addr)) - 1 && ppnt->p_type == PT_LOAD) + loadaddr = (ppnt->p_vaddr & ~(page_size - 1)) - + (ppnt->p_offset & ~(page_size - 1)); + if (ppnt->p_type == 2) { + dynamic_addr = ppnt->p_offset; + dynamic_size = ppnt->p_filesz; + }; + ppnt++; + }; + + dpnt = (ElfW(Dyn) *) & header[dynamic_addr]; + dynamic_size = dynamic_size / sizeof(ElfW(Dyn)); + if ((char *)dpnt < (char *)header || + (char *)(dpnt + dynamic_size) > (char *)(header + st.st_size)) + goto skip; + + if (byteswap == 1) { + dpnt->d_tag = bswap_32(dpnt->d_tag); + dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val); + } + + while (dpnt->d_tag != DT_NULL) { + if (dpnt->d_tag == DT_STRTAB) + strtab_val = dpnt->d_un.d_val; + dpnt++; + if (byteswap == 1) { + dpnt->d_tag = bswap_32(dpnt->d_tag); + dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val); + } + }; + + if (!strtab_val) + goto skip; + + dpnt = (ElfW(Dyn) *) & header[dynamic_addr]; + while (dpnt->d_tag != DT_NULL) { + if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) { + needed_val = dpnt->d_un.d_val; + if (needed_val + strtab_val >= loadaddr || + needed_val + strtab_val < st.st_size - loadaddr) { + needed = + (char *)(header - loadaddr + strtab_val + + needed_val); + + if (dpnt->d_tag == DT_SONAME) + soname = xstrdup(needed); + + for (j = 0; needed_tab[j].soname != NULL; j++) { + if (strcmp(needed, needed_tab[j].soname) + == 0) { + if (*type != LIB_ELF + && *type != + needed_tab[j].type) + multi_libcs = 1; + *type = needed_tab[j].type; + } + } + } + } + dpnt++; + }; + + if (multi_libcs) + warn("%s appears to be for multiple libc's", name); + + /* If we could not deduce the libc type, and we know what to expect, set the type */ + if (*type == LIB_ELF && expected_type != LIB_ANY) + *type = expected_type; + + if (expected_type != LIB_ANY && expected_type != LIB_ELF && + expected_type != *type) { + warn("%s does not match type specified for directory!", name); + } + + skip: + munmap(header, st.st_size); + + return soname; +} -- 2.39.5

+ +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/extra/locale/collation/da_DK b/extra/locale/collation/da_DK new file mode 100644 index 0000000..83ea9da --- /dev/null +++ b/extra/locale/collation/da_DK @@ -0,0 +1,2075 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +% and are treated as in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/de_AT b/extra/locale/collation/de_AT new file mode 100644 index 0000000..5314a57 --- /dev/null +++ b/extra/locale/collation/de_AT @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/extra/locale/collation/de_BE b/extra/locale/collation/de_BE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/de_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/de_CH b/extra/locale/collation/de_CH new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/de_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/de_DE b/extra/locale/collation/de_DE new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/de_DE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/de_LU b/extra/locale/collation/de_LU new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/de_LU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/el_GR b/extra/locale/collation/el_GR new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/el_GR @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_AU b/extra/locale/collation/en_AU new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_AU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_BW b/extra/locale/collation/en_BW new file mode 100644 index 0000000..a7e9285 --- /dev/null +++ b/extra/locale/collation/en_BW @@ -0,0 +1 @@ +copy "en_ZA" diff --git a/extra/locale/collation/en_CA b/extra/locale/collation/en_CA new file mode 100644 index 0000000..ab4b690 --- /dev/null +++ b/extra/locale/collation/en_CA @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/en_DK b/extra/locale/collation/en_DK new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_DK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_GB b/extra/locale/collation/en_GB new file mode 100644 index 0000000..5314a57 --- /dev/null +++ b/extra/locale/collation/en_GB @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/extra/locale/collation/en_HK b/extra/locale/collation/en_HK new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_HK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_IE b/extra/locale/collation/en_IE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_IE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_IN b/extra/locale/collation/en_IN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/en_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/en_NZ b/extra/locale/collation/en_NZ new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_NZ @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_PH b/extra/locale/collation/en_PH new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/en_PH @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/en_SG b/extra/locale/collation/en_SG new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/en_SG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/en_US b/extra/locale/collation/en_US new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/en_US @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/en_ZA b/extra/locale/collation/en_ZA new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/en_ZA @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/en_ZW b/extra/locale/collation/en_ZW new file mode 100644 index 0000000..a7e9285 --- /dev/null +++ b/extra/locale/collation/en_ZW @@ -0,0 +1 @@ +copy "en_ZA" diff --git a/extra/locale/collation/eo_EO b/extra/locale/collation/eo_EO new file mode 100644 index 0000000..c8057f5 --- /dev/null +++ b/extra/locale/collation/eo_EO @@ -0,0 +1,49 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE % Ĉ +reorder-after + ;;;IGNORE % ĉ +reorder-after + ;;;IGNORE % Ĝ +reorder-after + ;;;IGNORE % ĝ +reorder-after + ;;;IGNORE % Ĥ +reorder-after + ;;;IGNORE % Ä¥ +reorder-after + ;;;IGNORE % Ä´ +reorder-after + ;;;IGNORE % ĵ +reorder-after + ;;;IGNORE % Ŝ +reorder-after + ;;;IGNORE % ŝ +reorder-after + ;;;IGNORE % Ŭ +reorder-after + ;;;IGNORE % Å­ + +reorder-end + diff --git a/extra/locale/collation/es_AR b/extra/locale/collation/es_AR new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_AR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_BO b/extra/locale/collation/es_BO new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_BO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_CL b/extra/locale/collation/es_CL new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_CL @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_CO b/extra/locale/collation/es_CO new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_CO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_CR b/extra/locale/collation/es_CR new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_CR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_DO b/extra/locale/collation/es_DO new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_DO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_EC b/extra/locale/collation/es_EC new file mode 100644 index 0000000..a0ea9ad --- /dev/null +++ b/extra/locale/collation/es_EC @@ -0,0 +1 @@ +copy "es_US" diff --git a/extra/locale/collation/es_ES b/extra/locale/collation/es_ES new file mode 100644 index 0000000..2c0a033 --- /dev/null +++ b/extra/locale/collation/es_ES @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/es_GT b/extra/locale/collation/es_GT new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_GT @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_HN b/extra/locale/collation/es_HN new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_HN @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_MX b/extra/locale/collation/es_MX new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_MX @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_NI b/extra/locale/collation/es_NI new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_NI @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_PA b/extra/locale/collation/es_PA new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_PA @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_PE b/extra/locale/collation/es_PE new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_PE @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_PR b/extra/locale/collation/es_PR new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_PR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_PY b/extra/locale/collation/es_PY new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_PY @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_SV b/extra/locale/collation/es_SV new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_SV @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_US b/extra/locale/collation/es_US new file mode 100644 index 0000000..56a4f36 --- /dev/null +++ b/extra/locale/collation/es_US @@ -0,0 +1,2077 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/es_UY b/extra/locale/collation/es_UY new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_UY @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/es_VE b/extra/locale/collation/es_VE new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/es_VE @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/et_EE b/extra/locale/collation/et_EE new file mode 100644 index 0000000..88c7aae --- /dev/null +++ b/extra/locale/collation/et_EE @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/eu_ES b/extra/locale/collation/eu_ES new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/eu_ES @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/fa_IR b/extra/locale/collation/fa_IR new file mode 100644 index 0000000..a171591 --- /dev/null +++ b/extra/locale/collation/fa_IR @@ -0,0 +1,185 @@ +copy "iso14651_t1" + +% The Persian alphabet order is: ALEF WITH MADDA ABOVE, ALEF, HAMZA (all +% kinds), BEH, PEH, TEH, JEEM, TCHEH, HAH, KHAH, DAL, THAL, REH, ZAIN, JEH, +% SEEN, SHEEN, SAD, DAD, TAH, ZAH, AIN, GHAIN, FEH, QAF, KAF, GAF, LAM, +% MEEM, NOON, WAW, HEH, YEH. +% The various kind of HAMZA are sorted as ALEF WITH HAMZA ABOVE, ALEF WITH +% HAMZA BELOW, WAW WITH HAMZA ABOVE, YEH WITH HAMZA ABOVE. + +collating-symbol % accent hamza over yeh +collating-symbol % dotless +collating-symbol % with dots over +collating-symbol % with wasla over + +collating-symbol +collating-symbol + +% Alternate representations displayed the same +collating-symbol +collating-symbol + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +reorder-after + + + + + + + + + + +reorder-after + + + +reorder-after + + + + +reorder-after + + + +% Persian uses fatha, kasra, damma, fathatan, kasratan, dammatan order. + +reorder-after + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + +reorder-after + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + +% Persian digits are sorted before Arabic ones: they are the basic forms. +reorder-after + <0>;;;IGNORE + <0>;;;IGNORE + <1>;;;IGNORE + <1>;;;IGNORE + <2>;;;IGNORE + <2>;;;IGNORE + <3>;;;IGNORE + <3>;;;IGNORE + <4>;;;IGNORE + <4>;;;IGNORE + <5>;;;IGNORE + <5>;;;IGNORE + <6>;;;IGNORE + <6>;;;IGNORE + <7>;;;IGNORE + <7>;;;IGNORE + <8>;;;IGNORE + <8>;;;IGNORE + <9>;;;IGNORE + <9>;;;IGNORE + +% And then the letters: + ;;;IGNORE % Alef With Madda Above + ;;;IGNORE + ;;;IGNORE % Alef + ;;;IGNORE % Alef Wasla + ;;;IGNORE % Hamza + ;;;IGNORE % Alef With Hamza Above + ;;;IGNORE + ;;;IGNORE % Alef With Hamza Below + ;;;IGNORE + ;;;IGNORE % Waw With Hamza Above + ;;;IGNORE + ;;;IGNORE % Yeh With Hamza Above + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE % Keheh + ;;;IGNORE % Kaf +reorder-after + ;;;IGNORE % Heh + ;;;IGNORE % Teh Marbuta + ;;;IGNORE % Heh With Yeh Above + ;;;IGNORE % Farsi Yeh + ;;;IGNORE % Alef Maksura + ;;;IGNORE % Yeh + +% Finally the letters in Presentation Form: +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + "";"";"";IGNORE % Rial Sign +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-end + diff --git a/extra/locale/collation/fi_FI b/extra/locale/collation/fi_FI new file mode 100644 index 0000000..f510998 --- /dev/null +++ b/extra/locale/collation/fi_FI @@ -0,0 +1,2062 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + +% before letters + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/fo_FO b/extra/locale/collation/fo_FO new file mode 100644 index 0000000..b7628e7 --- /dev/null +++ b/extra/locale/collation/fo_FO @@ -0,0 +1 @@ +copy "da_DK" diff --git a/extra/locale/collation/fr_BE b/extra/locale/collation/fr_BE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/fr_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/fr_CA b/extra/locale/collation/fr_CA new file mode 100644 index 0000000..c911095 --- /dev/null +++ b/extra/locale/collation/fr_CA @@ -0,0 +1 @@ +copy "en_CA" diff --git a/extra/locale/collation/fr_CH b/extra/locale/collation/fr_CH new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/fr_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/fr_FR b/extra/locale/collation/fr_FR new file mode 100644 index 0000000..5314a57 --- /dev/null +++ b/extra/locale/collation/fr_FR @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/extra/locale/collation/fr_LU b/extra/locale/collation/fr_LU new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/fr_LU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/ga_IE b/extra/locale/collation/ga_IE new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/ga_IE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/gd_GB b/extra/locale/collation/gd_GB new file mode 100644 index 0000000..d66184e --- /dev/null +++ b/extra/locale/collation/gd_GB @@ -0,0 +1 @@ +copy "en_DK" diff --git a/extra/locale/collation/gl_ES b/extra/locale/collation/gl_ES new file mode 100644 index 0000000..09fd11b --- /dev/null +++ b/extra/locale/collation/gl_ES @@ -0,0 +1 @@ +copy "es_ES" diff --git a/extra/locale/collation/gv_GB b/extra/locale/collation/gv_GB new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/gv_GB @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/he_IL b/extra/locale/collation/he_IL new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/he_IL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/hi_IN b/extra/locale/collation/hi_IN new file mode 100644 index 0000000..35ae3c6 --- /dev/null +++ b/extra/locale/collation/hi_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/extra/locale/collation/hr_HR b/extra/locale/collation/hr_HR new file mode 100644 index 0000000..0929ea7 --- /dev/null +++ b/extra/locale/collation/hr_HR @@ -0,0 +1,2085 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/extra/locale/collation/hu_HU b/extra/locale/collation/hu_HU new file mode 100644 index 0000000..e87bb76 --- /dev/null +++ b/extra/locale/collation/hu_HU @@ -0,0 +1,357 @@ +copy "iso14651_t1" + +%% a b c cs d dz dzs e f g gy h i j k l ly m n ny o o: p q +%% r s sz t ty u u: v w x y z zs +%% +%% a' e' i' o' u' are sorted as if they were unaccented +%% o" and u" are sorted as if they were o: and u: + +collating-symbol +collating-symbol + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + + + + + + +reorder-after + + + + + + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-end + diff --git a/extra/locale/collation/hy_AM b/extra/locale/collation/hy_AM new file mode 100644 index 0000000..1132128 --- /dev/null +++ b/extra/locale/collation/hy_AM @@ -0,0 +1,91 @@ + +% Armenian sorting is not yet on iso14651_t1 + +copy "iso14651_t1" + +script + +order_start ;forward;forward;forward;forward,position + + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % +order-end + +reorder-sections-after + +reorder-sections-end + diff --git a/extra/locale/collation/id_ID b/extra/locale/collation/id_ID new file mode 100644 index 0000000..3738ee3 --- /dev/null +++ b/extra/locale/collation/id_ID @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/extra/locale/collation/is_IS b/extra/locale/collation/is_IS new file mode 100644 index 0000000..b19add0 --- /dev/null +++ b/extra/locale/collation/is_IS @@ -0,0 +1,2104 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "reorder-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;forward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +% modifier letters + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + +order_end + diff --git a/extra/locale/collation/iso14651_t1 b/extra/locale/collation/iso14651_t1 new file mode 100644 index 0000000..b44d34a --- /dev/null +++ b/extra/locale/collation/iso14651_t1 @@ -0,0 +1,1495 @@ + +# Déclaration des systèmes d'écriture / Declaration of scripts +script +script +script +script +script +script +script +script + +# Déclaration des symboles internes / Declaration of internal symbols +# +# SYMB N° Expl. +# +collating-symbol +# +# / +# +# +collating-symbol # 2 normal --> voir/see +collating-symbol # 3 isol. +collating-symbol # 4 final +collating-symbol # 5 initial +collating-symbol # 6 medial/mdian +# +collating-symbol # 7 minuscule/minuscule (bas de casse/lower case) +collating-symbol # 8 inférieur min./subscript min. (indice/index) +collating-symbol # 9 supér. min./superscript min. (exposant/exponent) +collating-symbol # 10 capitale/capital (haut de casse/upper case) +collating-symbol # 8 minuscule grecque/Greek lower case +collating-symbol # 11 inférieur en capitale/subscript capital +collating-symbol # 12 supérieur en capitale/superscript capital +# +# / +# +collating-symbol # 13 accent madda +collating-symbol # 14 accent hamza +collating-symbol # 14-1 accent hamza/waw +collating-symbol # 14-2 accent hamza under / hamza souscrit +collating-symbol # 14-3 accent under yeh / accent souscrit du ya' +collating-symbol # 14-4 accent hamza/yeh barree +# +collating-symbol # 15 de base/basic (non accentué/non-accented) +# +collating-symbol # 16 particulier/peculiar +collating-symbol # 17 ligature/ligature +collating-symbol # 18 accent aigu/acute accent +collating-symbol # 20 accent grave/grave accent +collating-symbol # 21 brève/breve +collating-symbol # 22 accent circonflexe/circumflex accent +collating-symbol # 23 caron/caron +collating-symbol # 24 rond supérieur/ring above +collating-symbol # 25 tréma/diaeresis (ou/or umlaut) +collating-symbol # 26 double ac. aigu/double acute ac. +collating-symbol # 27 tilde/tilde +collating-symbol # 28 point/dot +collating-symbol # 29 barre oblique/oblique +collating-symbol # 30 cédille/cedilla +collating-symbol # 31 ogonek/ogonek +collating-symbol # 32 macron/macron +# +# GREC +# +collating-symbol # accent aigu/tonos/acute accent +collating-symbol # trma/dialytica/diaeresis +collating-symbol # dialytika tonos +# +collating-symbol <0> +collating-symbol <1> +collating-symbol <2> +collating-symbol <3> +collating-symbol <4> +collating-symbol <5> +collating-symbol <6> +collating-symbol <7> +collating-symbol <8> +collating-symbol <9> +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol